diff --git a/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp b/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp index 5a7de8fbf9a..9aaea5aec5a 100644 --- a/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp +++ b/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp @@ -50,6 +50,9 @@ void TextAttributes::apply(TextAttributes textAttributes) { letterSpacing = !std::isnan(textAttributes.letterSpacing) ? textAttributes.letterSpacing : letterSpacing; + textTransform = textAttributes.textTransform.hasValue() + ? textAttributes.textTransform + : textTransform; // Paragraph Styles lineHeight = !std::isnan(textAttributes.lineHeight) @@ -120,7 +123,8 @@ bool TextAttributes::operator==(const TextAttributes &rhs) const { textShadowColor, isHighlighted, layoutDirection, - accessibilityRole) == + accessibilityRole, + textTransform) == std::tie( rhs.foregroundColor, rhs.backgroundColor, @@ -139,7 +143,8 @@ bool TextAttributes::operator==(const TextAttributes &rhs) const { rhs.textShadowColor, rhs.isHighlighted, rhs.layoutDirection, - rhs.accessibilityRole) && + rhs.accessibilityRole, + rhs.textTransform) && floatEquality(opacity, rhs.opacity) && floatEquality(fontSize, rhs.fontSize) && floatEquality(fontSizeMultiplier, rhs.fontSizeMultiplier) && diff --git a/ReactCommon/react/renderer/attributedstring/TextAttributes.h b/ReactCommon/react/renderer/attributedstring/TextAttributes.h index f15f11416f3..87bbffc30e2 100644 --- a/ReactCommon/react/renderer/attributedstring/TextAttributes.h +++ b/ReactCommon/react/renderer/attributedstring/TextAttributes.h @@ -51,6 +51,7 @@ class TextAttributes : public DebugStringConvertible { better::optional fontVariant{}; better::optional allowFontScaling{}; Float letterSpacing{std::numeric_limits::quiet_NaN()}; + better::optional textTransform{}; // Paragraph Styles Float lineHeight{std::numeric_limits::quiet_NaN()}; @@ -117,6 +118,7 @@ struct hash { textAttributes.fontVariant, textAttributes.allowFontScaling, textAttributes.letterSpacing, + textAttributes.textTransform, textAttributes.lineHeight, textAttributes.alignment, textAttributes.baseWritingDirection, diff --git a/ReactCommon/react/renderer/attributedstring/conversions.h b/ReactCommon/react/renderer/attributedstring/conversions.h index 34fe3dbab47..98a3885c9c2 100644 --- a/ReactCommon/react/renderer/attributedstring/conversions.h +++ b/ReactCommon/react/renderer/attributedstring/conversions.h @@ -260,6 +260,55 @@ inline std::string toString(const FontVariant &fontVariant) { return result; } +inline void fromRawValue(const RawValue &value, TextTransform &result) { + react_native_assert(value.hasType()); + if (value.hasType()) { + auto string = (std::string)value; + if (string == "none") { + result = TextTransform::None; + } else if (string == "uppercase") { + result = TextTransform::Uppercase; + } else if (string == "lowercase") { + result = TextTransform::Lowercase; + } else if (string == "capitalize") { + result = TextTransform::Capitalize; + } else if (string == "unset") { + result = TextTransform::Unset; + } else { + LOG(ERROR) << "Unsupported TextTransform value: " << string; + react_native_assert(false); + // sane default for prod + result = TextTransform::None; + } + return; + } + + LOG(ERROR) << "Unsupported TextTransform type"; + react_native_assert(false); + // sane default for prod + result = TextTransform::None; +} + +inline std::string toString(const TextTransform &textTransform) { + switch (textTransform) { + case TextTransform::None: + return "none"; + case TextTransform::Uppercase: + return "uppercase"; + case TextTransform::Lowercase: + return "lowercase"; + case TextTransform::Capitalize: + return "capitalize"; + case TextTransform::Unset: + return "unset"; + } + + LOG(ERROR) << "Unsupported TextTransform value"; + react_native_assert(false); + // sane default for prod + return "none"; +} + inline void fromRawValue(const RawValue &value, TextAlignment &result) { react_native_assert(value.hasType()); if (value.hasType()) { @@ -765,6 +814,9 @@ inline folly::dynamic toDynamic(const TextAttributes &textAttributes) { if (!std::isnan(textAttributes.letterSpacing)) { _textAttributes("letterSpacing", textAttributes.letterSpacing); } + if (textAttributes.textTransform.hasValue()) { + _textAttributes("textTransform", toString(*textAttributes.textTransform)); + } if (!std::isnan(textAttributes.lineHeight)) { _textAttributes("lineHeight", textAttributes.lineHeight); } diff --git a/ReactCommon/react/renderer/attributedstring/primitives.h b/ReactCommon/react/renderer/attributedstring/primitives.h index 13946ec180f..deeb40b11a7 100644 --- a/ReactCommon/react/renderer/attributedstring/primitives.h +++ b/ReactCommon/react/renderer/attributedstring/primitives.h @@ -117,6 +117,14 @@ enum class AccessibilityRole { Toolbar, }; +enum class TextTransform { + None, + Uppercase, + Lowercase, + Capitalize, + Unset, +}; + } // namespace react } // namespace facebook @@ -197,4 +205,11 @@ struct hash { return hash()(static_cast(v)); } }; + +template <> +struct hash { + size_t operator()(const facebook::react::TextTransform &v) const { + return hash()(static_cast(v)); + } +}; } // namespace std diff --git a/ReactCommon/react/renderer/components/text/BaseTextProps.cpp b/ReactCommon/react/renderer/components/text/BaseTextProps.cpp index cae5c975a3d..fb4fe1d57d3 100644 --- a/ReactCommon/react/renderer/components/text/BaseTextProps.cpp +++ b/ReactCommon/react/renderer/components/text/BaseTextProps.cpp @@ -79,6 +79,11 @@ static TextAttributes convertRawProp( "letterSpacing", sourceTextAttributes.letterSpacing, defaultTextAttributes.letterSpacing); + textAttributes.textTransform = convertRawProp( + rawProps, + "textTransform", + sourceTextAttributes.textTransform, + defaultTextAttributes.textTransform); // Paragraph textAttributes.lineHeight = convertRawProp(