diff --git a/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp b/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp index fe64a462aa3..cafee311389 100644 --- a/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp +++ b/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.cpp @@ -21,13 +21,15 @@ bool ParagraphAttributes::operator==(const ParagraphAttributes &rhs) const { ellipsizeMode, textBreakStrategy, adjustsFontSizeToFit, - includeFontPadding) == + includeFontPadding, + android_hyphenationFrequency) == std::tie( rhs.maximumNumberOfLines, rhs.ellipsizeMode, rhs.textBreakStrategy, rhs.adjustsFontSizeToFit, - rhs.includeFontPadding) && + rhs.includeFontPadding, + rhs.android_hyphenationFrequency) && floatEquality(minimumFontSize, rhs.minimumFontSize) && floatEquality(maximumFontSize, rhs.maximumFontSize); } @@ -47,7 +49,10 @@ SharedDebugStringConvertibleList ParagraphAttributes::getDebugProps() const { debugStringConvertibleItem("adjustsFontSizeToFit", adjustsFontSizeToFit), debugStringConvertibleItem("minimumFontSize", minimumFontSize), debugStringConvertibleItem("maximumFontSize", maximumFontSize), - debugStringConvertibleItem("includeFontPadding", includeFontPadding)}; + debugStringConvertibleItem("includeFontPadding", includeFontPadding), + debugStringConvertibleItem( + "android_hyphenationFrequency", + android_hyphenationFrequency)}; } #endif diff --git a/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h b/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h index a5666035eff..c4fa4a5944a 100644 --- a/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h +++ b/ReactCommon/react/renderer/attributedstring/ParagraphAttributes.h @@ -42,6 +42,9 @@ class ParagraphAttributes : public DebugStringConvertible { */ EllipsizeMode ellipsizeMode{}; + /* + * (Android only) Break strategy for breaking paragraphs into lines. + */ TextBreakStrategy textBreakStrategy{}; /* @@ -55,6 +58,11 @@ class ParagraphAttributes : public DebugStringConvertible { */ bool includeFontPadding{true}; + /* + * (Android only) Frequency of automatic hyphenation to use when determining word breaks. + */ + HyphenationFrequency android_hyphenationFrequency{}; + /* * In case of font size adjustment enabled, defines minimum and maximum * font sizes. @@ -89,7 +97,8 @@ struct hash { attributes.adjustsFontSizeToFit, attributes.minimumFontSize, attributes.maximumFontSize, - attributes.includeFontPadding); + attributes.includeFontPadding, + attributes.android_hyphenationFrequency); } }; } // namespace std diff --git a/ReactCommon/react/renderer/attributedstring/conversions.h b/ReactCommon/react/renderer/attributedstring/conversions.h index da688767fcd..43c449cdde2 100644 --- a/ReactCommon/react/renderer/attributedstring/conversions.h +++ b/ReactCommon/react/renderer/attributedstring/conversions.h @@ -712,6 +712,48 @@ inline void fromRawValue( result = AccessibilityRole::None; } +inline std::string toString(const HyphenationFrequency &hyphenationFrequency) { + switch (hyphenationFrequency) { + case HyphenationFrequency::None: + return "none"; + case HyphenationFrequency::Normal: + return "normal"; + case HyphenationFrequency::Full: + return "full"; + } + + LOG(ERROR) << "Unsupported HyphenationFrequency value"; + react_native_assert(false); + return "none"; +} + +inline void fromRawValue( + const PropsParserContext &context, + const RawValue &value, + HyphenationFrequency &result) { + react_native_assert(value.hasType()); + if (value.hasType()) { + auto string = (std::string)value; + if (string == "none") { + result = HyphenationFrequency::None; + } else if (string == "normal") { + result = HyphenationFrequency::Normal; + } else if (string == "full") { + result = HyphenationFrequency::Full; + } else { + // sane default + LOG(ERROR) << "Unsupported HyphenationFrequency value: " << string; + react_native_assert(false); + result = HyphenationFrequency::None; + } + return; + } + + LOG(ERROR) << "Unsupported HyphenationFrequency type"; + react_native_assert(false); + result = HyphenationFrequency::None; +} + inline ParagraphAttributes convertRawProp( const PropsParserContext &context, RawProps const &rawProps, @@ -761,6 +803,12 @@ inline ParagraphAttributes convertRawProp( "includeFontPadding", sourceParagraphAttributes.includeFontPadding, defaultParagraphAttributes.includeFontPadding); + paragraphAttributes.android_hyphenationFrequency = convertRawProp( + context, + rawProps, + "android_hyphenationFrequency", + sourceParagraphAttributes.android_hyphenationFrequency, + defaultParagraphAttributes.android_hyphenationFrequency); return paragraphAttributes; } @@ -796,6 +844,9 @@ inline folly::dynamic toDynamic( values("textBreakStrategy", toString(paragraphAttributes.textBreakStrategy)); values("adjustsFontSizeToFit", paragraphAttributes.adjustsFontSizeToFit); values("includeFontPadding", paragraphAttributes.includeFontPadding); + values( + "android_hyphenationFrequency", + toString(paragraphAttributes.android_hyphenationFrequency)); return values; } diff --git a/ReactCommon/react/renderer/attributedstring/primitives.h b/ReactCommon/react/renderer/attributedstring/primitives.h index cb080f35b83..49c14ea0637 100644 --- a/ReactCommon/react/renderer/attributedstring/primitives.h +++ b/ReactCommon/react/renderer/attributedstring/primitives.h @@ -53,7 +53,11 @@ enum class EllipsizeMode { Middle // Truncate middle of line: "ab...yz". }; -enum class TextBreakStrategy { Simple, Balanced, HighQuality }; +enum class TextBreakStrategy { + Simple, // Simple strategy. + Balanced, // Balances line lengths. + HighQuality // High-quality strategy, including hyphenation. +}; enum class TextAlignment { Natural, // Indicates the default alignment for script. @@ -126,6 +130,12 @@ enum class TextTransform { Unset, }; +enum class HyphenationFrequency { + None, // No hyphenation. + Normal, // Less frequent hyphenation. + Full // Standard amount of hyphenation. +}; + } // namespace react } // namespace facebook @@ -213,4 +223,11 @@ struct hash { return hash()(static_cast(v)); } }; + +template <> +struct hash { + size_t operator()(const facebook::react::HyphenationFrequency &v) const { + return hash()(static_cast(v)); + } +}; } // namespace std