Add an overload for createLayout to reduce code duplication (#45083)

Summary:
Adds an overload for `createLayout` method that also handles extracting paragraph attributes and scaling font size if necessary.

## Changelog:

[ANDROID] [CHANGED] - Extracted common parts related to calculating text layout to a helper

Pull Request resolved: https://github.com/facebook/react-native/pull/45083

Test Plan: Tried out on RNTester

Reviewed By: robhogan

Differential Revision: D58818560

Pulled By: cortinico

fbshipit-source-id: a42b5de04c4a70edb88cdd734387d7e4cee94032
This commit is contained in:
Jakub Piasecki
2024-06-20 11:09:15 -07:00
committed by Facebook GitHub Bot
parent 8a6b88eeaf
commit 2eaf0b0848
2 changed files with 75 additions and 104 deletions
@@ -7628,6 +7628,7 @@ public class com/facebook/react/views/text/TextLayoutManager {
public static final field PA_KEY_TEXT_BREAK_STRATEGY S
public fun <init> ()V
public static fun adjustSpannableFontToFit (Landroid/text/Spannable;FLcom/facebook/yoga/YogaMeasureMode;FLcom/facebook/yoga/YogaMeasureMode;DIZIILandroid/text/Layout$Alignment;)V
public static fun createLayout (Landroid/content/Context;Lcom/facebook/react/common/mapbuffer/MapBuffer;Lcom/facebook/react/common/mapbuffer/MapBuffer;FFLcom/facebook/react/views/text/ReactTextViewManagerCallback;)Landroid/text/Layout;
public static fun deleteCachedSpannableForTag (I)V
public static fun getOrCreateSpannableForText (Landroid/content/Context;Lcom/facebook/react/common/mapbuffer/MapBuffer;Lcom/facebook/react/views/text/ReactTextViewManagerCallback;)Landroid/text/Spannable;
public static fun getTextAlignment (Lcom/facebook/react/common/mapbuffer/MapBuffer;Landroid/text/Spannable;)Landroid/text/Layout$Alignment;
@@ -422,6 +422,69 @@ public class TextLayoutManager {
return layout;
}
public static Layout createLayout(
@NonNull Context context,
MapBuffer attributedString,
MapBuffer paragraphAttributes,
float width,
float height,
ReactTextViewManagerCallback reactTextViewManagerCallback) {
Spannable text =
getOrCreateSpannableForText(context, attributedString, reactTextViewManagerCallback);
BoringLayout.Metrics boring = BoringLayout.isBoring(text, sTextPaintInstance);
int textBreakStrategy =
TextAttributeProps.getTextBreakStrategy(
paragraphAttributes.getString(PA_KEY_TEXT_BREAK_STRATEGY));
boolean includeFontPadding =
paragraphAttributes.contains(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));
boolean adjustFontSizeToFit =
paragraphAttributes.contains(PA_KEY_ADJUST_FONT_SIZE_TO_FIT)
? paragraphAttributes.getBoolean(PA_KEY_ADJUST_FONT_SIZE_TO_FIT)
: DEFAULT_ADJUST_FONT_SIZE_TO_FIT;
int maximumNumberOfLines =
paragraphAttributes.contains(PA_KEY_MAX_NUMBER_OF_LINES)
? paragraphAttributes.getInt(PA_KEY_MAX_NUMBER_OF_LINES)
: ReactConstants.UNSET;
Layout.Alignment alignment = getTextAlignment(attributedString, text);
if (adjustFontSizeToFit) {
double minimumFontSize =
paragraphAttributes.contains(PA_KEY_MINIMUM_FONT_SIZE)
? paragraphAttributes.getDouble(PA_KEY_MINIMUM_FONT_SIZE)
: Double.NaN;
adjustSpannableFontToFit(
text,
width,
YogaMeasureMode.EXACTLY,
height,
YogaMeasureMode.UNDEFINED,
minimumFontSize,
maximumNumberOfLines,
includeFontPadding,
textBreakStrategy,
hyphenationFrequency,
alignment);
}
return createLayout(
text,
boring,
width,
YogaMeasureMode.EXACTLY,
includeFontPadding,
textBreakStrategy,
hyphenationFrequency,
alignment);
}
public static void adjustSpannableFontToFit(
Spannable text,
float width,
@@ -505,66 +568,25 @@ public class TextLayoutManager {
@Nullable float[] attachmentsPositions) {
// TODO(5578671): Handle text direction (see View#getTextDirectionHeuristic)
Spannable text =
getOrCreateSpannableForText(context, attributedString, reactTextViewManagerCallback);
Layout layout =
createLayout(
context,
attributedString,
paragraphAttributes,
width,
height,
reactTextViewManagerCallback);
Spannable text = (Spannable) layout.getText();
if (text == null) {
return 0;
}
int textBreakStrategy =
TextAttributeProps.getTextBreakStrategy(
paragraphAttributes.getString(PA_KEY_TEXT_BREAK_STRATEGY));
boolean includeFontPadding =
paragraphAttributes.contains(PA_KEY_INCLUDE_FONT_PADDING)
? paragraphAttributes.getBoolean(PA_KEY_INCLUDE_FONT_PADDING)
: DEFAULT_INCLUDE_FONT_PADDING;
int hyphenationFrequency =
TextAttributeProps.getHyphenationFrequency(
paragraphAttributes.getString(PA_KEY_HYPHENATION_FREQUENCY));
boolean adjustFontSizeToFit =
paragraphAttributes.contains(PA_KEY_ADJUST_FONT_SIZE_TO_FIT)
? paragraphAttributes.getBoolean(PA_KEY_ADJUST_FONT_SIZE_TO_FIT)
: DEFAULT_ADJUST_FONT_SIZE_TO_FIT;
int maximumNumberOfLines =
paragraphAttributes.contains(PA_KEY_MAX_NUMBER_OF_LINES)
? paragraphAttributes.getInt(PA_KEY_MAX_NUMBER_OF_LINES)
: ReactConstants.UNSET;
Layout.Alignment alignment = getTextAlignment(attributedString, text);
if (adjustFontSizeToFit) {
double minimumFontSize =
paragraphAttributes.contains(PA_KEY_MINIMUM_FONT_SIZE)
? paragraphAttributes.getDouble(PA_KEY_MINIMUM_FONT_SIZE)
: Double.NaN;
adjustSpannableFontToFit(
text,
width,
widthYogaMeasureMode,
height,
heightYogaMeasureMode,
minimumFontSize,
maximumNumberOfLines,
includeFontPadding,
textBreakStrategy,
hyphenationFrequency,
alignment);
}
BoringLayout.Metrics boring = BoringLayout.isBoring(text, sTextPaintInstance);
Layout layout =
createLayout(
text,
boring,
width,
widthYogaMeasureMode,
includeFontPadding,
textBreakStrategy,
hyphenationFrequency,
alignment);
int calculatedLineCount =
maximumNumberOfLines == ReactConstants.UNSET || maximumNumberOfLines == 0
? layout.getLineCount()
@@ -718,60 +740,8 @@ public class TextLayoutManager {
float width,
float height) {
Spannable text = getOrCreateSpannableForText(context, attributedString, null);
BoringLayout.Metrics boring = BoringLayout.isBoring(text, sTextPaintInstance);
int textBreakStrategy =
TextAttributeProps.getTextBreakStrategy(
paragraphAttributes.getString(PA_KEY_TEXT_BREAK_STRATEGY));
boolean includeFontPadding =
paragraphAttributes.contains(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));
boolean adjustFontSizeToFit =
paragraphAttributes.contains(PA_KEY_ADJUST_FONT_SIZE_TO_FIT)
? paragraphAttributes.getBoolean(PA_KEY_ADJUST_FONT_SIZE_TO_FIT)
: DEFAULT_ADJUST_FONT_SIZE_TO_FIT;
int maximumNumberOfLines =
paragraphAttributes.contains(PA_KEY_MAX_NUMBER_OF_LINES)
? paragraphAttributes.getInt(PA_KEY_MAX_NUMBER_OF_LINES)
: ReactConstants.UNSET;
Layout.Alignment alignment = getTextAlignment(attributedString, text);
if (adjustFontSizeToFit) {
double minimumFontSize =
paragraphAttributes.contains(PA_KEY_MINIMUM_FONT_SIZE)
? paragraphAttributes.getDouble(PA_KEY_MINIMUM_FONT_SIZE)
: Double.NaN;
adjustSpannableFontToFit(
text,
width,
YogaMeasureMode.EXACTLY,
height,
YogaMeasureMode.UNDEFINED,
minimumFontSize,
maximumNumberOfLines,
includeFontPadding,
textBreakStrategy,
hyphenationFrequency,
alignment);
}
Layout layout =
createLayout(
text,
boring,
width,
YogaMeasureMode.EXACTLY,
includeFontPadding,
textBreakStrategy,
hyphenationFrequency,
alignment);
return FontMetricsUtil.getFontMetrics(text, layout, sTextPaintInstance, context);
createLayout(context, attributedString, paragraphAttributes, width, height, null);
return FontMetricsUtil.getFontMetrics(layout.getText(), layout, sTextPaintInstance, context);
}
}