mirror of
https://github.com/status-im/react-native.git
synced 2025-01-13 19:15:05 +00:00
Fabric/Text: attributedstring module, the first part
Summary: `fabric/attributedstring` is a simple, cross-platfrom, react-specific implementation of attributed string (aka spanned string). This diff is the first part of this which contains text primitives (types) and conversions. Reviewed By: fkgozali Differential Revision: D7748704 fbshipit-source-id: d76e31807e5ac7ab1a16fd6ee6445c59de5b89a2
This commit is contained in:
parent
6611fefef7
commit
e2287976f3
@ -149,6 +149,15 @@ Pod::Spec.new do |s|
|
||||
end
|
||||
|
||||
s.subspec "fabric" do |ss|
|
||||
ss.subspec "attributedstring" do |sss|
|
||||
sss.dependency "Folly", folly_version
|
||||
sss.compiler_flags = folly_compiler_flags
|
||||
sss.source_files = "ReactCommon/fabric/attributedstring/**/*.{cpp,h}"
|
||||
sss.exclude_files = "**/tests/*"
|
||||
sss.header_dir = "fabric/attributedstring"
|
||||
sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/Folly\"" }
|
||||
end
|
||||
|
||||
ss.subspec "core" do |sss|
|
||||
sss.dependency "Folly", folly_version
|
||||
sss.compiler_flags = folly_compiler_flags
|
||||
@ -194,7 +203,6 @@ Pod::Spec.new do |s|
|
||||
sss.header_dir = "fabric/view"
|
||||
sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_ROOT)/Folly\"" }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
s.subspec "ART" do |ss|
|
||||
|
78
ReactCommon/fabric/attributedstring/BUCK
Normal file
78
ReactCommon/fabric/attributedstring/BUCK
Normal file
@ -0,0 +1,78 @@
|
||||
load("//configurations/buck/apple:flag_defs.bzl", "get_debug_preprocessor_flags")
|
||||
load("//ReactNative:DEFS.bzl", "IS_OSS_BUILD", "react_native_xplat_target", "rn_xplat_cxx_library", "get_apple_inspector_flags", "APPLE")
|
||||
|
||||
APPLE_COMPILER_FLAGS = []
|
||||
|
||||
if not IS_OSS_BUILD:
|
||||
load("@xplat//configurations/buck/apple:flag_defs.bzl", "get_static_library_ios_flags", "flags")
|
||||
APPLE_COMPILER_FLAGS = flags.get_flag_value(get_static_library_ios_flags(), 'compiler_flags')
|
||||
|
||||
rn_xplat_cxx_library(
|
||||
name = "attributedstring",
|
||||
srcs = glob(
|
||||
["**/*.cpp"],
|
||||
excludes = glob(["tests/**/*.cpp"]),
|
||||
),
|
||||
headers = glob(
|
||||
["**/*.h"],
|
||||
excludes = glob(["tests/**/*.h"]),
|
||||
),
|
||||
header_namespace = "",
|
||||
exported_headers = subdir_glob(
|
||||
[
|
||||
("", "*.h"),
|
||||
],
|
||||
prefix = "fabric/attributedstring",
|
||||
),
|
||||
compiler_flags = [
|
||||
"-fexceptions",
|
||||
"-frtti",
|
||||
"-std=c++14",
|
||||
"-Wall",
|
||||
],
|
||||
fbobjc_compiler_flags = APPLE_COMPILER_FLAGS,
|
||||
fbobjc_preprocessor_flags = get_debug_preprocessor_flags() + get_apple_inspector_flags(),
|
||||
fbobjc_tests = [
|
||||
":tests",
|
||||
],
|
||||
force_static = True,
|
||||
macosx_tests_override = [],
|
||||
preprocessor_flags = [
|
||||
"-DLOG_TAG=\"ReactNative\"",
|
||||
"-DWITH_FBSYSTRACE=1",
|
||||
],
|
||||
tests = [],
|
||||
visibility = ["PUBLIC"],
|
||||
deps = [
|
||||
"xplat//fbsystrace:fbsystrace",
|
||||
"xplat//folly:headers_only",
|
||||
"xplat//folly:memory",
|
||||
"xplat//folly:molly",
|
||||
"xplat//third-party/glog:glog",
|
||||
react_native_xplat_target("fabric/debug:debug"),
|
||||
react_native_xplat_target("fabric/core:core"),
|
||||
react_native_xplat_target("fabric/graphics:graphics"),
|
||||
],
|
||||
)
|
||||
|
||||
if not IS_OSS_BUILD:
|
||||
load("@xplat//build_defs:fb_xplat_cxx_test.bzl", "fb_xplat_cxx_test")
|
||||
|
||||
fb_xplat_cxx_test(
|
||||
name = "tests",
|
||||
srcs = glob(["tests/**/*.cpp"]),
|
||||
headers = glob(["tests/**/*.h"]),
|
||||
contacts = ["oncall+react_native@xmail.facebook.com"],
|
||||
compiler_flags = [
|
||||
"-fexceptions",
|
||||
"-frtti",
|
||||
"-std=c++14",
|
||||
"-Wall",
|
||||
],
|
||||
platforms = APPLE,
|
||||
deps = [
|
||||
"xplat//folly:molly",
|
||||
"xplat//third-party/gmock:gtest",
|
||||
":attributedstring",
|
||||
],
|
||||
)
|
37
ReactCommon/fabric/attributedstring/ParagraphAttributes.cpp
Normal file
37
ReactCommon/fabric/attributedstring/ParagraphAttributes.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include "ParagraphAttributes.h"
|
||||
|
||||
#include <fabric/attributedstring/textValuesConversions.h>
|
||||
#include <fabric/debug/DebugStringConvertibleItem.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
#pragma mark - DebugStringConvertible
|
||||
|
||||
SharedDebugStringConvertibleList ParagraphAttributes::getDebugProps() const {
|
||||
ParagraphAttributes defaultParagraphAttributes = {};
|
||||
SharedDebugStringConvertibleList list = {};
|
||||
|
||||
#define PARAGRAPH_ATTRIBUTE(stringName, propertyName, accessor, convertor) \
|
||||
if (propertyName != defaultParagraphAttributes.propertyName) { \
|
||||
list.push_back(std::make_shared<DebugStringConvertibleItem>(#stringName, convertor(propertyName accessor))); \
|
||||
}
|
||||
|
||||
PARAGRAPH_ATTRIBUTE(maximumNumberOfLines, maximumNumberOfLines, , std::to_string)
|
||||
PARAGRAPH_ATTRIBUTE(ellipsizeMode, ellipsizeMode, , stringFromEllipsizeMode)
|
||||
PARAGRAPH_ATTRIBUTE(adjustsFontSizeToFit, adjustsFontSizeToFit, , std::to_string)
|
||||
PARAGRAPH_ATTRIBUTE(minimumFontSize, minimumFontSize, , std::to_string)
|
||||
PARAGRAPH_ATTRIBUTE(maximumFontSize, maximumFontSize, , std::to_string)
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
65
ReactCommon/fabric/attributedstring/ParagraphAttributes.h
Normal file
65
ReactCommon/fabric/attributedstring/ParagraphAttributes.h
Normal file
@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <fabric/attributedstring/TextPrimitives.h>
|
||||
#include <fabric/debug/DebugStringConvertible.h>
|
||||
#include <fabric/graphics/Geometry.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
class ParagraphAttributes;
|
||||
|
||||
using SharedParagraphAttributes = std::shared_ptr<const ParagraphAttributes>;
|
||||
|
||||
/*
|
||||
* Represents all visual attributes of a paragraph of text.
|
||||
* Two data structures, ParagraphAttributes and AttributedText, should be
|
||||
* enough to define visual representation of a piece of text on the screen.
|
||||
*/
|
||||
class ParagraphAttributes:
|
||||
public DebugStringConvertible {
|
||||
|
||||
public:
|
||||
|
||||
#pragma mark - Fields
|
||||
|
||||
/*
|
||||
* Maximum number of lines which paragraph can take.
|
||||
* Zero value represents "no limit".
|
||||
*/
|
||||
int maximumNumberOfLines {0};
|
||||
|
||||
/*
|
||||
* In case if a text cannot fit given boudaures, defines a place where
|
||||
* an ellipsize should be placed.
|
||||
*/
|
||||
EllipsizeMode ellipsizeMode {EllipsizeMode::Clip};
|
||||
|
||||
/*
|
||||
* Enables font size adjustment to fit constrained boundaries.
|
||||
*/
|
||||
bool adjustsFontSizeToFit {false};
|
||||
|
||||
/*
|
||||
* In case of font size adjustment enabled, defines minimum and maximum
|
||||
* font sizes.
|
||||
*/
|
||||
Float minimumFontSize {std::numeric_limits<Float>::quiet_NaN()};
|
||||
Float maximumFontSize {std::numeric_limits<Float>::quiet_NaN()};
|
||||
|
||||
#pragma mark - DebugStringConvertible
|
||||
|
||||
SharedDebugStringConvertibleList getDebugProps() const override;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
94
ReactCommon/fabric/attributedstring/TextPrimitives.h
Normal file
94
ReactCommon/fabric/attributedstring/TextPrimitives.h
Normal file
@ -0,0 +1,94 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
enum class FontStyle {
|
||||
Normal,
|
||||
Italic,
|
||||
Oblique
|
||||
};
|
||||
|
||||
enum class FontWeight: int {
|
||||
Weight100 = 100,
|
||||
UltraLight = 100,
|
||||
Weight200 = 200,
|
||||
Thin = 200,
|
||||
Weight300 = 300,
|
||||
Light = 300,
|
||||
Weight400 = 400,
|
||||
Regular = 400,
|
||||
Weight500 = 500,
|
||||
Medium = 500,
|
||||
Weight600 = 600,
|
||||
Semibold = 600,
|
||||
Demibold = 600,
|
||||
Weight700 = 700,
|
||||
Bold = 700,
|
||||
Weight800 = 800,
|
||||
Heavy = 800,
|
||||
Weight900 = 900,
|
||||
Black = 900
|
||||
};
|
||||
|
||||
enum class FontVariant: int {
|
||||
Default = 0,
|
||||
SmallCaps = 1 << 1,
|
||||
OldstyleNums = 1 << 2,
|
||||
LiningNums = 1 << 3,
|
||||
TabularNums = 1 << 4,
|
||||
ProportionalNums = 1 << 5
|
||||
};
|
||||
|
||||
enum class EllipsizeMode {
|
||||
Clip, // Do not add ellipsize, simply clip.
|
||||
Head, // Truncate at head of line: "...wxyz".
|
||||
Tail, // Truncate at tail of line: "abcd...".
|
||||
Middle // Truncate middle of line: "ab...yz".
|
||||
};
|
||||
|
||||
enum class TextAlignment {
|
||||
Natural, // Indicates the default alignment for script.
|
||||
Left, // Visually left aligned.
|
||||
Center, // Visually centered.
|
||||
Right, // Visually right aligned.
|
||||
Justified // Fully-justified. The last line in a paragraph is natural-aligned.
|
||||
};
|
||||
|
||||
enum class WritingDirection {
|
||||
Natural, // Determines direction using the Unicode Bidi Algorithm rules P2 and P3.
|
||||
LeftToRight, // Left to right writing direction.
|
||||
RightToLeft // Right to left writing direction.
|
||||
};
|
||||
|
||||
enum class TextDecorationLineType {
|
||||
None,
|
||||
Underline,
|
||||
Strikethrough,
|
||||
UnderlineStrikethrough
|
||||
};
|
||||
|
||||
enum class TextDecorationLineStyle {
|
||||
Single,
|
||||
Thick,
|
||||
Double
|
||||
};
|
||||
|
||||
enum class TextDecorationLinePattern {
|
||||
Solid,
|
||||
Dot,
|
||||
Dash,
|
||||
DashDot,
|
||||
DashDotDot,
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
||||
|
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <fabric/attributedstring/TextPrimitives.h>
|
||||
|
||||
using namespace facebook::react;
|
||||
|
||||
TEST(AttributedStringTest, testSomething) {
|
||||
// TODO
|
||||
}
|
120
ReactCommon/fabric/attributedstring/textValuesConversions.h
Normal file
120
ReactCommon/fabric/attributedstring/textValuesConversions.h
Normal file
@ -0,0 +1,120 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fabric/attributedstring/TextPrimitives.h>
|
||||
#include <fabric/graphics/Geometry.h>
|
||||
#include <folly/dynamic.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
inline std::string stringFromEllipsizeMode(const EllipsizeMode &ellipsisMode) {
|
||||
switch (ellipsisMode) {
|
||||
case EllipsizeMode::Clip: return "clip";
|
||||
case EllipsizeMode::Head: return "head";
|
||||
case EllipsizeMode::Tail: return "tail";
|
||||
case EllipsizeMode::Middle: return "middle";
|
||||
}
|
||||
}
|
||||
|
||||
inline EllipsizeMode ellipsizeModeFromDynamic(const folly::dynamic &value) {
|
||||
auto string = value.getString();
|
||||
if (string == "clip") { return EllipsizeMode::Clip; }
|
||||
if (string == "head") { return EllipsizeMode::Head; }
|
||||
if (string == "tail") { return EllipsizeMode::Tail; }
|
||||
if (string == "middle") { return EllipsizeMode::Middle; }
|
||||
abort();
|
||||
}
|
||||
|
||||
inline FontWeight fontWeightFromDynamic(const folly::dynamic &value) {
|
||||
auto string = value.asString();
|
||||
if (string == "normal") { return FontWeight::Regular; }
|
||||
if (string == "regular") { return FontWeight::Regular; }
|
||||
if (string == "bold") { return FontWeight::Bold; }
|
||||
if (string == "100") { return FontWeight::Weight100; }
|
||||
if (string == "200") { return FontWeight::Weight200; }
|
||||
if (string == "300") { return FontWeight::Weight300; }
|
||||
if (string == "400") { return FontWeight::Weight400; }
|
||||
if (string == "500") { return FontWeight::Weight500; }
|
||||
if (string == "600") { return FontWeight::Weight600; }
|
||||
if (string == "700") { return FontWeight::Weight700; }
|
||||
if (string == "800") { return FontWeight::Weight800; }
|
||||
if (string == "900") { return FontWeight::Weight900; }
|
||||
abort();
|
||||
}
|
||||
|
||||
inline FontStyle fontStyleFromDynamic(const folly::dynamic &value) {
|
||||
auto string = value.asString();
|
||||
if (string == "normal") { return FontStyle::Normal; }
|
||||
if (string == "italic") { return FontStyle::Italic; }
|
||||
if (string == "oblique") { return FontStyle::Oblique; }
|
||||
abort();
|
||||
}
|
||||
|
||||
inline FontVariant fontVariantFromDynamic(const folly::dynamic &value) {
|
||||
assert(value.isArray());
|
||||
FontVariant fontVariant = FontVariant::Default;
|
||||
for (auto &&item : value) {
|
||||
auto string = item.asString();
|
||||
if (string == "small-caps") { fontVariant = (FontVariant)((int)fontVariant | (int)FontVariant::SmallCaps); continue; }
|
||||
if (string == "oldstyle-nums") { fontVariant = (FontVariant)((int)fontVariant | (int)FontVariant::OldstyleNums); continue; }
|
||||
if (string == "lining-nums") { fontVariant = (FontVariant)((int)fontVariant | (int)FontVariant::LiningNums); continue; }
|
||||
if (string == "tabular-nums") { fontVariant = (FontVariant)((int)fontVariant | (int)FontVariant::TabularNums); continue; }
|
||||
if (string == "proportional-nums") { fontVariant = (FontVariant)((int)fontVariant | (int)FontVariant::ProportionalNums); continue; }
|
||||
}
|
||||
return fontVariant;
|
||||
}
|
||||
|
||||
inline TextAlignment textAlignmentFromDynamic(const folly::dynamic &value) {
|
||||
auto string = value.asString();
|
||||
if (string == "natural") { return TextAlignment::Natural; }
|
||||
if (string == "left") { return TextAlignment::Left; }
|
||||
if (string == "center") { return TextAlignment::Center; }
|
||||
if (string == "right") { return TextAlignment::Right; }
|
||||
if (string == "justified") { return TextAlignment::Justified; }
|
||||
abort();
|
||||
}
|
||||
|
||||
inline WritingDirection writingDirectionFromDynamic(const folly::dynamic &value) {
|
||||
auto string = value.asString();
|
||||
if (string == "natural") { return WritingDirection::Natural; }
|
||||
if (string == "ltr") { return WritingDirection::LeftToRight; }
|
||||
if (string == "rtl") { return WritingDirection::RightToLeft; }
|
||||
abort();
|
||||
}
|
||||
|
||||
inline TextDecorationLineType textDecorationLineTypeFromDynamic(const folly::dynamic &value) {
|
||||
auto string = value.asString();
|
||||
if (string == "none") { return TextDecorationLineType::None; }
|
||||
if (string == "underline") { return TextDecorationLineType::Underline; }
|
||||
if (string == "strikethrough") { return TextDecorationLineType::Strikethrough; }
|
||||
if (string == "underline-strikethrough") { return TextDecorationLineType::UnderlineStrikethrough; }
|
||||
abort();
|
||||
}
|
||||
|
||||
inline TextDecorationLineStyle textDecorationLineStyleFromDynamic(const folly::dynamic &value) {
|
||||
auto string = value.asString();
|
||||
if (string == "single") { return TextDecorationLineStyle::Single; }
|
||||
if (string == "thick") { return TextDecorationLineStyle::Thick; }
|
||||
if (string == "double") { return TextDecorationLineStyle::Double; }
|
||||
abort();
|
||||
}
|
||||
|
||||
inline TextDecorationLinePattern textDecorationLinePatternFromDynamic(const folly::dynamic &value) {
|
||||
auto string = value.asString();
|
||||
if (string == "solid") { return TextDecorationLinePattern::Solid; }
|
||||
if (string == "dot") { return TextDecorationLinePattern::Dot; }
|
||||
if (string == "dash") { return TextDecorationLinePattern::Dash; }
|
||||
if (string == "dash-dot") { return TextDecorationLinePattern::DashDot; }
|
||||
if (string == "dash-dot-dot") { return TextDecorationLinePattern::DashDotDot; }
|
||||
abort();
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
Loading…
x
Reference in New Issue
Block a user