GT2/Ejectable/node_modules/react-native/ReactCommon/fabric/attributedstring/conversions.h

632 lines
18 KiB
C
Raw Normal View History

2021-08-16 00:14:59 +00:00
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* 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 <folly/Conv.h>
#include <folly/dynamic.h>
#include <react/attributedstring/AttributedString.h>
#include <react/attributedstring/ParagraphAttributes.h>
#include <react/attributedstring/TextAttributes.h>
#include <react/attributedstring/conversions.h>
#include <react/attributedstring/primitives.h>
#include <react/core/LayoutableShadowNode.h>
#include <react/core/ShadowNode.h>
#include <react/core/conversions.h>
#include <react/core/propsConversions.h>
#include <react/graphics/Geometry.h>
#include <react/graphics/conversions.h>
#include <cmath>
#include <glog/logging.h>
namespace facebook {
namespace react {
inline std::string toString(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 void fromRawValue(const RawValue &value, EllipsizeMode &result) {
auto string = (std::string)value;
if (string == "clip") {
result = EllipsizeMode::Clip;
return;
}
if (string == "head") {
result = EllipsizeMode::Head;
return;
}
if (string == "tail") {
result = EllipsizeMode::Tail;
return;
}
if (string == "middle") {
result = EllipsizeMode::Middle;
return;
}
abort();
}
inline std::string toString(const TextBreakStrategy &textBreakStrategy) {
switch (textBreakStrategy) {
case TextBreakStrategy::Simple:
return "simple";
case TextBreakStrategy::HighQuality:
return "highQuality";
case TextBreakStrategy::Balanced:
return "balanced";
}
}
inline void fromRawValue(const RawValue &value, TextBreakStrategy &result) {
auto string = (std::string)value;
if (string == "simple") {
result = TextBreakStrategy::Simple;
return;
}
if (string == "highQuality") {
result = TextBreakStrategy::HighQuality;
return;
}
if (string == "balanced") {
result = TextBreakStrategy::Balanced;
return;
}
abort();
}
inline void fromRawValue(const RawValue &value, FontWeight &result) {
auto string = (std::string)value;
if (string == "normal") {
result = FontWeight::Regular;
return;
}
if (string == "regular") {
result = FontWeight::Regular;
return;
}
if (string == "bold") {
result = FontWeight::Bold;
return;
}
if (string == "100") {
result = FontWeight::Weight100;
return;
}
if (string == "200") {
result = FontWeight::Weight200;
return;
}
if (string == "300") {
result = FontWeight::Weight300;
return;
}
if (string == "400") {
result = FontWeight::Weight400;
return;
}
if (string == "500") {
result = FontWeight::Weight500;
return;
}
if (string == "600") {
result = FontWeight::Weight600;
return;
}
if (string == "700") {
result = FontWeight::Weight700;
return;
}
if (string == "800") {
result = FontWeight::Weight800;
return;
}
if (string == "900") {
result = FontWeight::Weight900;
return;
}
abort();
}
inline std::string toString(const FontWeight &fontWeight) {
return folly::to<std::string>((int)fontWeight);
}
inline void fromRawValue(const RawValue &value, FontStyle &result) {
auto string = (std::string)value;
if (string == "normal") {
result = FontStyle::Normal;
return;
}
if (string == "italic") {
result = FontStyle::Italic;
return;
}
if (string == "oblique") {
result = FontStyle::Oblique;
return;
}
abort();
}
inline std::string toString(const FontStyle &fontStyle) {
switch (fontStyle) {
case FontStyle::Normal:
return "normal";
case FontStyle::Italic:
return "italic";
case FontStyle::Oblique:
return "oblique";
}
}
inline void fromRawValue(const RawValue &value, FontVariant &result) {
assert(value.hasType<std::vector<std::string>>());
result = FontVariant::Default;
auto items = std::vector<std::string>{value};
for (const auto &item : items) {
if (item == "small-caps") {
result = (FontVariant)((int)result | (int)FontVariant::SmallCaps);
continue;
}
if (item == "oldstyle-nums") {
result = (FontVariant)((int)result | (int)FontVariant::OldstyleNums);
continue;
}
if (item == "lining-nums") {
result = (FontVariant)((int)result | (int)FontVariant::LiningNums);
continue;
}
if (item == "tabular-nums") {
result = (FontVariant)((int)result | (int)FontVariant::TabularNums);
continue;
}
if (item == "proportional-nums") {
result = (FontVariant)((int)result | (int)FontVariant::ProportionalNums);
continue;
}
}
}
inline std::string toString(const FontVariant &fontVariant) {
auto result = std::string{};
auto separator = std::string{", "};
if ((int)fontVariant & (int)FontVariant::SmallCaps) {
result += "small-caps" + separator;
}
if ((int)fontVariant & (int)FontVariant::OldstyleNums) {
result += "oldstyle-nums" + separator;
}
if ((int)fontVariant & (int)FontVariant::LiningNums) {
result += "lining-nums" + separator;
}
if ((int)fontVariant & (int)FontVariant::TabularNums) {
result += "tabular-nums" + separator;
}
if ((int)fontVariant & (int)FontVariant::ProportionalNums) {
result += "proportional-nums" + separator;
}
if (!result.empty()) {
result.erase(result.length() - separator.length());
}
return result;
}
inline void fromRawValue(const RawValue &value, TextAlignment &result) {
auto string = (std::string)value;
if (string == "auto") {
result = TextAlignment::Natural;
return;
}
if (string == "left") {
result = TextAlignment::Left;
return;
}
if (string == "center") {
result = TextAlignment::Center;
return;
}
if (string == "right") {
result = TextAlignment::Right;
return;
}
if (string == "justify") {
result = TextAlignment::Justified;
return;
}
abort();
}
inline std::string toString(const TextAlignment &textAlignment) {
switch (textAlignment) {
case TextAlignment::Natural:
return "natural";
case TextAlignment::Left:
return "left";
case TextAlignment::Center:
return "center";
case TextAlignment::Right:
return "right";
case TextAlignment::Justified:
return "justified";
}
}
inline void fromRawValue(const RawValue &value, WritingDirection &result) {
auto string = (std::string)value;
if (string == "natural") {
result = WritingDirection::Natural;
return;
}
if (string == "ltr") {
result = WritingDirection::LeftToRight;
return;
}
if (string == "rtl") {
result = WritingDirection::RightToLeft;
return;
}
abort();
}
inline std::string toString(const WritingDirection &writingDirection) {
switch (writingDirection) {
case WritingDirection::Natural:
return "natural";
case WritingDirection::LeftToRight:
return "ltr";
case WritingDirection::RightToLeft:
return "rtl";
}
}
inline void fromRawValue(
const RawValue &value,
TextDecorationLineType &result) {
auto string = (std::string)value;
if (string == "none") {
result = TextDecorationLineType::None;
return;
}
if (string == "underline") {
result = TextDecorationLineType::Underline;
return;
}
// TODO: remove "line-through" after deprecation
if (string == "strikethrough" || string == "line-through") {
result = TextDecorationLineType::Strikethrough;
return;
}
// TODO: remove "underline line-through" after "line-through" deprecation
if (string == "underline-strikethrough" ||
string == "underline line-through") {
result = TextDecorationLineType::UnderlineStrikethrough;
return;
}
abort();
}
inline std::string toString(
const TextDecorationLineType &textDecorationLineType) {
switch (textDecorationLineType) {
case TextDecorationLineType::None:
return "none";
case TextDecorationLineType::Underline:
return "underline";
case TextDecorationLineType::Strikethrough:
return "strikethrough";
case TextDecorationLineType::UnderlineStrikethrough:
return "underline-strikethrough";
}
}
inline void fromRawValue(
const RawValue &value,
TextDecorationLineStyle &result) {
auto string = (std::string)value;
if (string == "single") {
result = TextDecorationLineStyle::Single;
return;
}
if (string == "thick") {
result = TextDecorationLineStyle::Thick;
return;
}
if (string == "double") {
result = TextDecorationLineStyle::Double;
return;
}
abort();
}
inline std::string toString(
const TextDecorationLineStyle &textDecorationLineStyle) {
switch (textDecorationLineStyle) {
case TextDecorationLineStyle::Single:
return "single";
case TextDecorationLineStyle::Thick:
return "thick";
case TextDecorationLineStyle::Double:
return "double";
}
}
inline void fromRawValue(
const RawValue &value,
TextDecorationLinePattern &result) {
auto string = (std::string)value;
if (string == "solid") {
result = TextDecorationLinePattern::Solid;
return;
}
if (string == "dot") {
result = TextDecorationLinePattern::Dot;
return;
}
if (string == "dash") {
result = TextDecorationLinePattern::Dash;
return;
}
if (string == "dash-dot") {
result = TextDecorationLinePattern::DashDot;
return;
}
if (string == "dash-dot-dot") {
result = TextDecorationLinePattern::DashDotDot;
return;
}
abort();
}
inline std::string toString(
const TextDecorationLinePattern &textDecorationLinePattern) {
switch (textDecorationLinePattern) {
case TextDecorationLinePattern::Solid:
return "solid";
case TextDecorationLinePattern::Dot:
return "dot";
case TextDecorationLinePattern::Dash:
return "dash";
case TextDecorationLinePattern::DashDot:
return "dash-dot";
case TextDecorationLinePattern::DashDotDot:
return "dash-dot-dot";
}
}
inline ParagraphAttributes convertRawProp(
RawProps const &rawProps,
ParagraphAttributes const &sourceParagraphAttributes,
ParagraphAttributes const &defaultParagraphAttributes) {
auto paragraphAttributes = ParagraphAttributes{};
paragraphAttributes.maximumNumberOfLines = convertRawProp(
rawProps,
"numberOfLines",
sourceParagraphAttributes.maximumNumberOfLines,
defaultParagraphAttributes.maximumNumberOfLines);
paragraphAttributes.ellipsizeMode = convertRawProp(
rawProps,
"ellipsizeMode",
sourceParagraphAttributes.ellipsizeMode,
defaultParagraphAttributes.ellipsizeMode);
paragraphAttributes.textBreakStrategy = convertRawProp(
rawProps,
"textBreakStrategy",
sourceParagraphAttributes.textBreakStrategy,
defaultParagraphAttributes.textBreakStrategy);
paragraphAttributes.adjustsFontSizeToFit = convertRawProp(
rawProps,
"adjustsFontSizeToFit",
sourceParagraphAttributes.adjustsFontSizeToFit,
defaultParagraphAttributes.adjustsFontSizeToFit);
paragraphAttributes.minimumFontSize = convertRawProp(
rawProps,
"minimumFontSize",
sourceParagraphAttributes.minimumFontSize,
defaultParagraphAttributes.minimumFontSize);
paragraphAttributes.maximumFontSize = convertRawProp(
rawProps,
"maximumFontSize",
sourceParagraphAttributes.maximumFontSize,
defaultParagraphAttributes.maximumFontSize);
return paragraphAttributes;
}
inline void fromRawValue(
RawValue const &value,
AttributedString::Range &result) {
auto map = (better::map<std::string, int>)value;
auto start = map.find("start");
if (start != map.end()) {
result.location = start->second;
}
auto end = map.find("end");
if (end != map.end()) {
result.length = start->second - result.location;
}
}
inline std::string toString(AttributedString::Range const &range) {
return "{location: " + folly::to<std::string>(range.location) +
", length: " + folly::to<std::string>(range.length) + "}";
}
#ifdef ANDROID
inline folly::dynamic toDynamic(
const ParagraphAttributes &paragraphAttributes) {
auto values = folly::dynamic::object();
values("maximumNumberOfLines", paragraphAttributes.maximumNumberOfLines);
values("ellipsizeMode", toString(paragraphAttributes.ellipsizeMode));
values("textBreakStrategy", toString(paragraphAttributes.textBreakStrategy));
values("adjustsFontSizeToFit", paragraphAttributes.adjustsFontSizeToFit);
return values;
}
inline folly::dynamic toDynamic(const FontVariant &fontVariant) {
auto result = folly::dynamic::array();
if ((int)fontVariant & (int)FontVariant::SmallCaps) {
result.push_back("small-caps");
}
if ((int)fontVariant & (int)FontVariant::OldstyleNums) {
result.push_back("oldstyle-nums");
}
if ((int)fontVariant & (int)FontVariant::LiningNums) {
result.push_back("lining-nums");
}
if ((int)fontVariant & (int)FontVariant::TabularNums) {
result.push_back("tabular-nums");
}
if ((int)fontVariant & (int)FontVariant::ProportionalNums) {
result.push_back("proportional-nums");
}
return result;
}
inline folly::dynamic toDynamic(const TextAttributes &textAttributes) {
auto _textAttributes = folly::dynamic::object();
if (textAttributes.foregroundColor) {
_textAttributes(
"foregroundColor", toDynamic(textAttributes.foregroundColor));
}
if (textAttributes.backgroundColor) {
_textAttributes(
"backgroundColor", toDynamic(textAttributes.backgroundColor));
}
if (!std::isnan(textAttributes.opacity)) {
_textAttributes("opacity", textAttributes.opacity);
}
if (!textAttributes.fontFamily.empty()) {
_textAttributes("fontFamily", textAttributes.fontFamily);
}
if (!std::isnan(textAttributes.fontSize)) {
_textAttributes("fontSize", textAttributes.fontSize);
}
if (!std::isnan(textAttributes.fontSizeMultiplier)) {
_textAttributes("fontSizeMultiplier", textAttributes.fontSizeMultiplier);
}
if (textAttributes.fontWeight.has_value()) {
_textAttributes("fontWeight", toString(*textAttributes.fontWeight));
}
if (textAttributes.fontStyle.has_value()) {
_textAttributes("fontStyle", toString(*textAttributes.fontStyle));
}
if (textAttributes.fontVariant.has_value()) {
_textAttributes("fontVariant", toDynamic(*textAttributes.fontVariant));
}
if (textAttributes.allowFontScaling.has_value()) {
_textAttributes("allowFontScaling", *textAttributes.allowFontScaling);
}
if (!std::isnan(textAttributes.letterSpacing)) {
_textAttributes("letterSpacing", textAttributes.letterSpacing);
}
if (!std::isnan(textAttributes.lineHeight)) {
_textAttributes("lineHeight", textAttributes.lineHeight);
}
if (textAttributes.alignment.has_value()) {
_textAttributes("alignment", toString(*textAttributes.alignment));
}
if (textAttributes.baseWritingDirection.has_value()) {
_textAttributes(
"baseWritingDirection", toString(*textAttributes.baseWritingDirection));
}
// Decoration
if (textAttributes.textDecorationColor) {
_textAttributes(
"textDecorationColor", toDynamic(textAttributes.textDecorationColor));
}
if (textAttributes.textDecorationLineType.has_value()) {
_textAttributes(
"textDecorationLine", toString(*textAttributes.textDecorationLineType));
}
if (textAttributes.textDecorationLineStyle.has_value()) {
_textAttributes(
"textDecorationLineStyle",
toString(*textAttributes.textDecorationLineStyle));
}
if (textAttributes.textDecorationLinePattern.has_value()) {
_textAttributes(
"textDecorationLinePattern",
toString(*textAttributes.textDecorationLinePattern));
}
// Shadow
// textShadowOffset = textAttributes.textShadowOffset.has_value() ?
// textAttributes.textShadowOffset.value() : textShadowOffset;
if (!std::isnan(textAttributes.textShadowRadius)) {
_textAttributes("textShadowRadius", textAttributes.textShadowRadius);
}
if (textAttributes.textShadowColor) {
_textAttributes(
"textShadowColor", toDynamic(textAttributes.textShadowColor));
}
// Special
if (textAttributes.isHighlighted.has_value()) {
_textAttributes("isHighlighted", *textAttributes.isHighlighted);
}
if (textAttributes.layoutDirection.has_value()) {
_textAttributes(
"layoutDirection", toString(*textAttributes.layoutDirection));
}
return _textAttributes;
}
inline folly::dynamic toDynamic(const AttributedString &attributedString) {
auto value = folly::dynamic::object();
auto fragments = folly::dynamic::array();
for (auto fragment : attributedString.getFragments()) {
folly::dynamic dynamicFragment = folly::dynamic::object();
dynamicFragment["string"] = fragment.string;
if (fragment.parentShadowView.componentHandle) {
dynamicFragment["reactTag"] = fragment.parentShadowView.tag;
}
if (fragment.isAttachment()) {
dynamicFragment["isAttachment"] = true;
dynamicFragment["width"] =
(int)fragment.parentShadowView.layoutMetrics.frame.size.width;
dynamicFragment["height"] =
(int)fragment.parentShadowView.layoutMetrics.frame.size.height;
}
dynamicFragment["textAttributes"] = toDynamic(fragment.textAttributes);
fragments.push_back(dynamicFragment);
}
value("fragments", fragments);
value(
"hash", std::hash<facebook::react::AttributedString>{}(attributedString));
value("string", attributedString.getString());
return value;
}
inline folly::dynamic toDynamic(AttributedString::Range const &range) {
folly::dynamic dynamicValue = folly::dynamic::object();
dynamicValue["location"] = range.location;
dynamicValue["length"] = range.length;
return dynamicValue;
}
#endif
} // namespace react
} // namespace facebook