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:
Valentin Shergin 2018-05-07 17:43:07 -07:00 коммит произвёл Facebook Github Bot
Родитель 6611fefef7
Коммит e2287976f3
7 изменённых файлов: 421 добавлений и 1 удалений

Просмотреть файл

@ -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|

Просмотреть файл

@ -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",
],
)

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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
}

Просмотреть файл

@ -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