diff --git a/ReactCommon/fabric/attributedstring/conversions.h b/ReactCommon/fabric/attributedstring/conversions.h index c19a70d7ffc..d798a0a40ad 100644 --- a/ReactCommon/fabric/attributedstring/conversions.h +++ b/ReactCommon/fabric/attributedstring/conversions.h @@ -7,8 +7,12 @@ #pragma once +#include #include +#include #include +#include +#include #include #include @@ -199,5 +203,78 @@ inline folly::dynamic toDynamic(const ParagraphAttributes ¶graphAttributes) return values; } +inline folly::dynamic toDynamic(const TextAttributes &textAttributes) { + auto _textAttributes = folly::dynamic::object(); + _textAttributes("foregroundColor", toDynamic(textAttributes.foregroundColor)); + if (textAttributes.backgroundColor) { + _textAttributes("backgroundColor", toDynamic(textAttributes.backgroundColor)); + } + if (!isnan(textAttributes.opacity)) { + _textAttributes("opacity", textAttributes.opacity); + } + if (!textAttributes.fontFamily.empty()) { + _textAttributes("fontFamily", textAttributes.fontFamily); + } + if (!isnan(textAttributes.fontSize)) { + _textAttributes("fontSize", textAttributes.fontSize); + } + if (!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", toString(*textAttributes.fontVariant)); + } + if (textAttributes.allowFontScaling.has_value()) { + _textAttributes("allowFontScaling", *textAttributes.allowFontScaling); + } + if (!isnan(textAttributes.letterSpacing)) { + _textAttributes("letterSpacing", textAttributes.letterSpacing); + } + if (!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("textDecorationLineType", 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 (!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; +} + } // namespace react } // namespace facebook diff --git a/ReactCommon/fabric/attributedstring/tests/TextAttributesTest.cpp b/ReactCommon/fabric/attributedstring/tests/TextAttributesTest.cpp new file mode 100644 index 00000000000..ed8084126fb --- /dev/null +++ b/ReactCommon/fabric/attributedstring/tests/TextAttributesTest.cpp @@ -0,0 +1,36 @@ +/** + * 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. + */ + +#include + +#include +#include +#include +#include +#include +#include + +namespace facebook { +namespace react { + +TEST(TextAttributesTest, testToDynamic) { + auto text = TextAttributes(); + text.foregroundColor = {colorFromComponents({200/255.0, 153/255.0, 100/255.0, 1.0})}; + text.opacity = 0.5; + text.fontStyle = FontStyle::Italic; + text.fontWeight = FontWeight::Thin; + text.fontVariant = FontVariant::TabularNums; + + auto result = toDynamic(text); + assert(result["foregroundColor"] == toDynamic(text.foregroundColor)); + assert(result["opacity"] == text.opacity); + assert(result["fontStyle"] == toString(*text.fontStyle)); + assert(result["fontWeight"] == toString(*text.fontWeight)); +} + +} +} diff --git a/ReactCommon/fabric/graphics/conversions.h b/ReactCommon/fabric/graphics/conversions.h index 5300b0a53c7..ce537280a9c 100644 --- a/ReactCommon/fabric/graphics/conversions.h +++ b/ReactCommon/fabric/graphics/conversions.h @@ -43,6 +43,16 @@ inline void fromDynamic(const folly::dynamic &value, SharedColor &result) { result = colorFromComponents({red, green, blue, alpha}); } +inline folly::dynamic toDynamic(const SharedColor &color) { + ColorComponents components = colorComponentsFromColor(color); + auto ratio = 256.f; + return + (((int)(components.alpha * ratio) & 0xff) << 24 | + ((int)(components.red * ratio) & 0xff) << 16 | + ((int)(components.green * ratio) & 0xff) << 8 | + ((int)(components.blue * ratio) & 0xff)); +} + inline std::string toString(const SharedColor &value) { ColorComponents components = colorComponentsFromColor(value); auto ratio = 256.f;