Use hyphenationFrequency for text measurement

Summary:
Implements the calculation of measurement and position of Text attachments in Android

Changelog: [Internal]

Reviewed By: JoshuaGross

Differential Revision: D30586616

fbshipit-source-id: e9ecc002f03477e3465d746855e1dff2e5f0b321
This commit is contained in:
Genki Kondo
2021-08-27 09:04:01 -07:00
committed by Facebook GitHub Bot
parent 4c258a6419
commit f3e8ea9c29
4 changed files with 74 additions and 12 deletions
@@ -68,9 +68,10 @@ public class TextAttributeProps {
private static final int DEFAULT_TEXT_SHADOW_COLOR = 0x55000000;
private static final int DEFAULT_JUSTIFICATION_MODE =
(Build.VERSION.SDK_INT < Build.VERSION_CODES.O) ? 0 : Layout.JUSTIFICATION_MODE_NONE;
private static final int DEFAULT_BREAK_STRATEGY =
(Build.VERSION.SDK_INT < Build.VERSION_CODES.M) ? 0 : Layout.BREAK_STRATEGY_HIGH_QUALITY;
private static final int DEFAULT_HYPHENATION_FREQUENCY =
(Build.VERSION.SDK_INT < Build.VERSION_CODES.M) ? 0 : Layout.HYPHENATION_FREQUENCY_NONE;
protected float mLineHeight = Float.NaN;
protected boolean mIsColorSet = false;
@@ -568,4 +569,22 @@ public class TextAttributeProps {
}
return androidTextBreakStrategy;
}
public static int getHyphenationFrequency(@Nullable String hyphenationFrequency) {
int androidHyphenationFrequency = DEFAULT_HYPHENATION_FREQUENCY;
if (hyphenationFrequency != null) {
switch (hyphenationFrequency) {
case "none":
androidHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE;
break;
case "normal":
androidHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NORMAL;
break;
default:
androidHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_FULL;
break;
}
}
return androidHyphenationFrequency;
}
}
@@ -64,6 +64,7 @@ public class TextLayoutManager {
private static final boolean DEFAULT_INCLUDE_FONT_PADDING = true;
private static final String INCLUDE_FONT_PADDING_KEY = "includeFontPadding";
private static final String TEXT_BREAK_STRATEGY_KEY = "textBreakStrategy";
private static final String HYPHENATION_FREQUENCY_KEY = "android_hyphenationFrequency";
private static final String MAXIMUM_NUMBER_OF_LINES_KEY = "maximumNumberOfLines";
private static final LruCache<ReadableNativeMap, Spannable> sSpannableCache =
new LruCache<>(spannableCacheSize);
@@ -250,7 +251,8 @@ public class TextLayoutManager {
float width,
YogaMeasureMode widthYogaMeasureMode,
boolean includeFontPadding,
int textBreakStrategy) {
int textBreakStrategy,
int hyphenationFrequency) {
Layout layout;
int spanLength = text.length();
boolean unconstrainedWidth = widthYogaMeasureMode == YogaMeasureMode.UNDEFINED || width < 0;
@@ -281,10 +283,9 @@ public class TextLayoutManager {
.setLineSpacing(0.f, 1.f)
.setIncludePad(includeFontPadding)
.setBreakStrategy(textBreakStrategy)
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
.setHyphenationFrequency(hyphenationFrequency)
.build();
}
} else if (boring != null && (unconstrainedWidth || boring.width <= width)) {
int boringLayoutWidth = boring.width;
if (boring.width < 0) {
@@ -325,7 +326,7 @@ public class TextLayoutManager {
.setLineSpacing(0.f, 1.f)
.setIncludePad(includeFontPadding)
.setBreakStrategy(textBreakStrategy)
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
.setHyphenationFrequency(hyphenationFrequency);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
builder.setUseLineSpacingFromFallbacks(true);
@@ -378,6 +379,9 @@ public class TextLayoutManager {
paragraphAttributes.hasKey(INCLUDE_FONT_PADDING_KEY)
? paragraphAttributes.getBoolean(INCLUDE_FONT_PADDING_KEY)
: DEFAULT_INCLUDE_FONT_PADDING;
int hyphenationFrequency =
TextAttributeProps.getHyphenationFrequency(
paragraphAttributes.getString(HYPHENATION_FREQUENCY_KEY));
if (text == null) {
throw new IllegalStateException("Spannable element has not been prepared in onBeforeLayout");
@@ -387,7 +391,13 @@ public class TextLayoutManager {
Layout layout =
createLayout(
text, boring, width, widthYogaMeasureMode, includeFontPadding, textBreakStrategy);
text,
boring,
width,
widthYogaMeasureMode,
includeFontPadding,
textBreakStrategy,
hyphenationFrequency);
int maximumNumberOfLines =
paragraphAttributes.hasKey(MAXIMUM_NUMBER_OF_LINES_KEY)
@@ -539,10 +549,19 @@ public class TextLayoutManager {
paragraphAttributes.hasKey(INCLUDE_FONT_PADDING_KEY)
? paragraphAttributes.getBoolean(INCLUDE_FONT_PADDING_KEY)
: DEFAULT_INCLUDE_FONT_PADDING;
int hyphenationFrequency =
TextAttributeProps.getTextBreakStrategy(
paragraphAttributes.getString(HYPHENATION_FREQUENCY_KEY));
Layout layout =
createLayout(
text, boring, width, YogaMeasureMode.EXACTLY, includeFontPadding, textBreakStrategy);
text,
boring,
width,
YogaMeasureMode.EXACTLY,
includeFontPadding,
textBreakStrategy,
hyphenationFrequency);
return FontMetricsUtil.getFontMetrics(text, layout, sTextPaintInstance, context);
}
@@ -61,6 +61,7 @@ public class TextLayoutManagerMapBuffer {
public static final short PA_KEY_TEXT_BREAK_STRATEGY = 2;
public static final short PA_KEY_ADJUST_FONT_SIZE_TO_FIT = 3;
public static final short PA_KEY_INCLUDE_FONT_PADDING = 4;
public static final short PA_KEY_HYPHENATION_FREQUENCY = 5;
private static final boolean ENABLE_MEASURE_LOGGING = ReactBuildConfig.DEBUG && false;
@@ -264,7 +265,8 @@ public class TextLayoutManagerMapBuffer {
float width,
YogaMeasureMode widthYogaMeasureMode,
boolean includeFontPadding,
int textBreakStrategy) {
int textBreakStrategy,
int hyphenationFrequency) {
Layout layout;
int spanLength = text.length();
boolean unconstrainedWidth = widthYogaMeasureMode == YogaMeasureMode.UNDEFINED || width < 0;
@@ -295,7 +297,7 @@ public class TextLayoutManagerMapBuffer {
.setLineSpacing(0.f, 1.f)
.setIncludePad(includeFontPadding)
.setBreakStrategy(textBreakStrategy)
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL)
.setHyphenationFrequency(hyphenationFrequency)
.build();
}
@@ -338,7 +340,7 @@ public class TextLayoutManagerMapBuffer {
.setLineSpacing(0.f, 1.f)
.setIncludePad(includeFontPadding)
.setBreakStrategy(textBreakStrategy)
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL);
.setHyphenationFrequency(hyphenationFrequency);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
builder.setUseLineSpacingFromFallbacks(true);
@@ -391,6 +393,9 @@ public class TextLayoutManagerMapBuffer {
paragraphAttributes.hasKey(PA_KEY_INCLUDE_FONT_PADDING)
? paragraphAttributes.getBoolean(PA_KEY_INCLUDE_FONT_PADDING)
: DEFAULT_INCLUDE_FONT_PADDING;
int hyphenationFrequency =
TextAttributeProps.getTextBreakStrategy(
paragraphAttributes.getString(PA_KEY_HYPHENATION_FREQUENCY));
if (text == null) {
throw new IllegalStateException("Spannable element has not been prepared in onBeforeLayout");
@@ -404,7 +409,13 @@ public class TextLayoutManagerMapBuffer {
Layout layout =
createLayout(
text, boring, width, widthYogaMeasureMode, includeFontPadding, textBreakStrategy);
text,
boring,
width,
widthYogaMeasureMode,
includeFontPadding,
textBreakStrategy,
hyphenationFrequency);
int maximumNumberOfLines =
paragraphAttributes.hasKey(PA_KEY_MAX_NUMBER_OF_LINES)
@@ -561,10 +572,19 @@ public class TextLayoutManagerMapBuffer {
paragraphAttributes.hasKey(PA_KEY_INCLUDE_FONT_PADDING)
? paragraphAttributes.getBoolean(PA_KEY_INCLUDE_FONT_PADDING)
: DEFAULT_INCLUDE_FONT_PADDING;
int hyphenationFrequency =
TextAttributeProps.getTextBreakStrategy(
paragraphAttributes.getString(PA_KEY_HYPHENATION_FREQUENCY));
Layout layout =
createLayout(
text, boring, width, YogaMeasureMode.EXACTLY, includeFontPadding, textBreakStrategy);
text,
boring,
width,
YogaMeasureMode.EXACTLY,
includeFontPadding,
textBreakStrategy,
hyphenationFrequency);
return FontMetricsUtil.getFontMetrics(text, layout, sTextPaintInstance, context);
}