Pull out construction of Layout from TextLayoutManager.measureText into separate function

Summary:
Changelog: [Internal]

Construction of Layout will be needed in `TextLayoutManager.measureLines`, pulling it out into separate function prevents code duplication.

Reviewed By: shergin

Differential Revision: D23782905

fbshipit-source-id: 8ab817559ca154716a190ca1012e809c5fa2fd6e
This commit is contained in:
Samuel Susla
2020-09-22 01:53:24 -07:00
committed by Facebook GitHub Bot
parent 23717e48af
commit acb967e1bb
@@ -257,51 +257,19 @@ public class TextLayoutManager {
return sb;
}
public static long measureText(
Context context,
ReadableMap attributedString,
ReadableMap paragraphAttributes,
private static Layout createLayout(
Spannable text,
BoringLayout.Metrics boring,
float width,
YogaMeasureMode widthYogaMeasureMode,
float height,
YogaMeasureMode heightYogaMeasureMode,
ReactTextViewManagerCallback reactTextViewManagerCallback,
@Nullable float[] attachmentsPositions) {
// TODO(5578671): Handle text direction (see View#getTextDirectionHeuristic)
TextPaint textPaint = sTextPaintInstance;
Spannable text;
if (attributedString.hasKey("cacheId")) {
int cacheId = attributedString.getInt("cacheId");
if (sTagToSpannableCache.containsKey(cacheId)) {
text = sTagToSpannableCache.get(cacheId);
} else {
return 0;
}
} else {
text = getOrCreateSpannableForText(context, attributedString, reactTextViewManagerCallback);
}
int textBreakStrategy =
TextAttributeProps.getTextBreakStrategy(
paragraphAttributes.getString(TEXT_BREAK_STRATEGY_KEY));
boolean includeFontPadding =
paragraphAttributes.hasKey(INCLUDE_FONT_PADDING_KEY)
? paragraphAttributes.getBoolean(INCLUDE_FONT_PADDING_KEY)
: DEFAULT_INCLUDE_FONT_PADDING;
if (text == null) {
throw new IllegalStateException("Spannable element has not been prepared in onBeforeLayout");
}
BoringLayout.Metrics boring = BoringLayout.isBoring(text, textPaint);
float desiredWidth = boring == null ? Layout.getDesiredWidth(text, textPaint) : Float.NaN;
// technically, width should never be negative, but there is currently a bug in
boolean unconstrainedWidth = widthYogaMeasureMode == YogaMeasureMode.UNDEFINED || width < 0;
boolean includeFontPadding,
int textBreakStrategy) {
Layout layout;
int spanLength = text.length();
boolean unconstrainedWidth = widthYogaMeasureMode == YogaMeasureMode.UNDEFINED || width < 0;
TextPaint textPaint = sTextPaintInstance;
float desiredWidth = boring == null ? Layout.getDesiredWidth(text, textPaint) : Float.NaN;
if (boring == null
&& (unconstrainedWidth
|| (!YogaConstants.isUndefined(desiredWidth) && desiredWidth <= width))) {
@@ -367,6 +335,55 @@ public class TextLayoutManager {
.build();
}
}
return layout;
}
public static long measureText(
Context context,
ReadableMap attributedString,
ReadableMap paragraphAttributes,
float width,
YogaMeasureMode widthYogaMeasureMode,
float height,
YogaMeasureMode heightYogaMeasureMode,
ReactTextViewManagerCallback reactTextViewManagerCallback,
@Nullable float[] attachmentsPositions) {
// TODO(5578671): Handle text direction (see View#getTextDirectionHeuristic)
TextPaint textPaint = sTextPaintInstance;
Spannable text;
if (attributedString.hasKey("cacheId")) {
int cacheId = attributedString.getInt("cacheId");
if (sTagToSpannableCache.containsKey(cacheId)) {
text = sTagToSpannableCache.get(cacheId);
} else {
return 0;
}
} else {
text = getOrCreateSpannableForText(context, attributedString, reactTextViewManagerCallback);
}
int textBreakStrategy =
TextAttributeProps.getTextBreakStrategy(
paragraphAttributes.getString(TEXT_BREAK_STRATEGY_KEY));
boolean includeFontPadding =
paragraphAttributes.hasKey(INCLUDE_FONT_PADDING_KEY)
? paragraphAttributes.getBoolean(INCLUDE_FONT_PADDING_KEY)
: DEFAULT_INCLUDE_FONT_PADDING;
if (text == null) {
throw new IllegalStateException("Spannable element has not been prepared in onBeforeLayout");
}
BoringLayout.Metrics boring = BoringLayout.isBoring(text, textPaint);
float desiredWidth = boring == null ? Layout.getDesiredWidth(text, textPaint) : Float.NaN;
// technically, width should never be negative, but there is currently a bug in
boolean unconstrainedWidth = widthYogaMeasureMode == YogaMeasureMode.UNDEFINED || width < 0;
Layout layout =
createLayout(
text, boring, width, widthYogaMeasureMode, includeFontPadding, textBreakStrategy);
int maximumNumberOfLines =
paragraphAttributes.hasKey(MAXIMUM_NUMBER_OF_LINES_KEY)
@@ -408,9 +425,9 @@ public class TextLayoutManager {
// follows a similar logic than used in pre-fabric (see ReactTextView.onLayout method).
int attachmentIndex = 0;
int lastAttachmentFoundInSpan;
for (int i = 0; i < spanLength; i = lastAttachmentFoundInSpan) {
for (int i = 0; i < text.length(); i = lastAttachmentFoundInSpan) {
lastAttachmentFoundInSpan =
text.nextSpanTransition(i, spanLength, TextInlineViewPlaceholderSpan.class);
text.nextSpanTransition(i, text.length(), TextInlineViewPlaceholderSpan.class);
TextInlineViewPlaceholderSpan[] placeholders =
text.getSpans(i, lastAttachmentFoundInSpan, TextInlineViewPlaceholderSpan.class);
for (TextInlineViewPlaceholderSpan placeholder : placeholders) {
@@ -432,7 +449,7 @@ public class TextLayoutManager {
// There's a bug on Samsung devices where calling getPrimaryHorizontal on
// the last offset in the layout will result in an endless loop. Work around
// this bug by avoiding getPrimaryHorizontal in that case.
if (start == spanLength - 1) {
if (start == text.length() - 1) {
placeholderLeftPosition =
isRtlParagraph
// Equivalent to `layout.getLineLeft(line)` but `getLineLeft` returns incorrect