Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 78c774de authored by Seigo Nonaka's avatar Seigo Nonaka
Browse files

Implement fallback line spacing for BoringLayout

The fallback line spacing is a feature of extending the line height
when the fallback font has taller glyph. This was implemented to
StaticLayout in Android P but not yet implemented in BoringLayout.

This CL enables this feature to the BoringLayout as well.

Not to break existing apps, change this behavior only if the
targetSdk version is T or later.

This is a 2nd attempt of Ia6d6f9f44e73ddaf5e8fe9a8aead7a53efbddd44
The root cause of SystemUI crash was wrong API usage. (start, end) was
passed instead of (start, count).

Bug: 210923482
Test: atest FallbackLineSpacingTest BoringLayoutFallbackLineSpacingTest
Test: atest CtsGraphicsTestCases
Test: atest CtsTextTestCases
Test: atest SystemUITests
Change-Id: I9137607b0120934f7ad2a12c0f0b8aaa52915831
parent 0d5215b3
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -15977,6 +15977,8 @@ package android.graphics {
    method public String getFontFeatureSettings();
    method public float getFontMetrics(android.graphics.Paint.FontMetrics);
    method public android.graphics.Paint.FontMetrics getFontMetrics();
    method public void getFontMetricsInt(@NonNull CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int, boolean, @NonNull android.graphics.Paint.FontMetricsInt);
    method public void getFontMetricsInt(@NonNull char[], @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0) int, boolean, @NonNull android.graphics.Paint.FontMetricsInt);
    method public int getFontMetricsInt(android.graphics.Paint.FontMetricsInt);
    method public android.graphics.Paint.FontMetricsInt getFontMetricsInt();
    method public float getFontSpacing();
@@ -44654,6 +44656,7 @@ package android.text {
  public class BoringLayout extends android.text.Layout implements android.text.TextUtils.EllipsizeCallback {
    ctor public BoringLayout(CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, android.text.BoringLayout.Metrics, boolean);
    ctor public BoringLayout(CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, android.text.BoringLayout.Metrics, boolean, android.text.TextUtils.TruncateAt, int);
    ctor public BoringLayout(@NonNull CharSequence, @NonNull android.text.TextPaint, @IntRange(from=0) int, @NonNull android.text.Layout.Alignment, float, float, @NonNull android.text.BoringLayout.Metrics, boolean, @NonNull android.text.TextUtils.TruncateAt, @IntRange(from=0) int, boolean);
    method public void ellipsized(int, int);
    method public int getBottomPadding();
    method public int getEllipsisCount(int);
@@ -44668,9 +44671,12 @@ package android.text {
    method public int getTopPadding();
    method public static android.text.BoringLayout.Metrics isBoring(CharSequence, android.text.TextPaint);
    method public static android.text.BoringLayout.Metrics isBoring(CharSequence, android.text.TextPaint, android.text.BoringLayout.Metrics);
    method @Nullable public static android.text.BoringLayout.Metrics isBoring(@NonNull CharSequence, @NonNull android.text.TextPaint, @NonNull android.text.TextDirectionHeuristic, boolean, @Nullable android.text.BoringLayout.Metrics);
    method public static android.text.BoringLayout make(CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, android.text.BoringLayout.Metrics, boolean);
    method public static android.text.BoringLayout make(CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, android.text.BoringLayout.Metrics, boolean, android.text.TextUtils.TruncateAt, int);
    method @NonNull public static android.text.BoringLayout make(@NonNull CharSequence, @NonNull android.text.TextPaint, @IntRange(from=0) int, @NonNull android.text.Layout.Alignment, @NonNull android.text.BoringLayout.Metrics, boolean, @NonNull android.text.TextUtils.TruncateAt, @IntRange(from=0) int, boolean);
    method public android.text.BoringLayout replaceOrMake(CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, android.text.BoringLayout.Metrics, boolean);
    method @NonNull public android.text.BoringLayout replaceOrMake(@NonNull CharSequence, @NonNull android.text.TextPaint, @IntRange(from=0) int, @NonNull android.text.Layout.Alignment, @NonNull android.text.BoringLayout.Metrics, boolean, @NonNull android.text.TextUtils.TruncateAt, @IntRange(from=0) int, boolean);
    method public android.text.BoringLayout replaceOrMake(CharSequence, android.text.TextPaint, int, android.text.Layout.Alignment, float, float, android.text.BoringLayout.Metrics, boolean, android.text.TextUtils.TruncateAt, int);
  }
@@ -44879,6 +44885,7 @@ package android.text {
    method public abstract int getTopPadding();
    method public final int getWidth();
    method public final void increaseWidthTo(int);
    method public boolean isFallbackLineSpacingEnabled();
    method public boolean isRtlCharAt(int);
    method protected final boolean isSpanned();
    field public static final int BREAK_STRATEGY_BALANCED = 2; // 0x2
+153 −17
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package android.text;

import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Canvas;
import android.graphics.Paint;
@@ -84,6 +87,41 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
                includePad, ellipsize, ellipsizedWidth);
    }

    /**
     * Utility function to construct a BoringLayout instance.
     *
     * The spacing multiplier and additional amount spacing are not used by BoringLayout.
     * {@link Layout#getSpacingMultiplier()} will return 1.0 and {@link Layout#getSpacingAdd()} will
     * return 0.0.
     *
     * @param source the text to render
     * @param paint the default paint for the layout
     * @param outerWidth the wrapping width for the text
     * @param align whether to left, right, or center the text
     * @param metrics {@code #Metrics} instance that contains information about FontMetrics and
     *                line width
     * @param includePad set whether to include extra space beyond font ascent and descent which is
     *                   needed to avoid clipping in some scripts
     * @param ellipsize whether to ellipsize the text if width of the text is longer than the
     *                  requested width
     * @param ellipsizedWidth the width to which this Layout is ellipsizing. If {@code ellipsize} is
     *                        {@code null}, or is {@link TextUtils.TruncateAt#MARQUEE} this value is
     *                        not used, {@code outerWidth} is used instead
     * @param useFallbackLineSpacing True for adjusting the line spacing based on fallback fonts.
     *                              False for keeping the first font's line height. If some glyphs
     *                              requires larger vertical spaces, by passing true to this
     *                              argument, the layout increase the line height to fit all glyphs.
     */
    public static @NonNull BoringLayout make(
            @NonNull CharSequence source, @NonNull TextPaint paint,
            @IntRange(from = 0) int outerWidth,
            @NonNull Alignment align, @NonNull BoringLayout.Metrics metrics,
            boolean includePad, @NonNull TextUtils.TruncateAt ellipsize,
            @IntRange(from = 0) int ellipsizedWidth, boolean useFallbackLineSpacing) {
        return new BoringLayout(source, paint, outerWidth, align, 1f, 0f, metrics, includePad,
                ellipsize, ellipsizedWidth, useFallbackLineSpacing);
    }

    /**
     * Returns a BoringLayout for the specified text, potentially reusing
     * this one if it is already suitable.  The caller must make sure that
@@ -109,7 +147,7 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
        mEllipsizedStart = 0;
        mEllipsizedCount = 0;

        init(source, paint, align, metrics, includePad, true);
        init(source, paint, align, metrics, includePad, true, false /* useFallbackLineSpacing */);
        return this;
    }

@@ -118,12 +156,14 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
     * this one if it is already suitable.  The caller must make sure that
     * no one is still using this Layout.
     *
     * The spacing multiplier and additional amount spacing are not used by BoringLayout.
     * {@link Layout#getSpacingMultiplier()} will return 1.0 and {@link Layout#getSpacingAdd()} will
     * return 0.0.
     *
     * @param source the text to render
     * @param paint the default paint for the layout
     * @param outerWidth the wrapping width for the text
     * @param align whether to left, right, or center the text
     * @param spacingMult this value is no longer used by BoringLayout
     * @param spacingAdd this value is no longer used by BoringLayout
     * @param metrics {@code #Metrics} instance that contains information about FontMetrics and
     *                line width
     * @param includePad set whether to include extra space beyond font ascent and descent which is
@@ -132,15 +172,21 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
     *                  requested width
     * @param ellipsizedWidth the width to which this Layout is ellipsizing. If {@code ellipsize} is
     *                        {@code null}, or is {@link TextUtils.TruncateAt#MARQUEE} this value is
     *                        not used, {@code outerwidth} is used instead
     *                        not used, {@code outerWidth} is used instead
     * @param useFallbackLineSpacing True for adjusting the line spacing based on fallback fonts.
     *                              False for keeping the first font's line height. If some glyphs
     *                              requires larger vertical spaces, by passing true to this
     *                              argument, the layout increase the line height to fit all glyphs.
     */
    public BoringLayout replaceOrMake(CharSequence source, TextPaint paint, int outerWidth,
            Alignment align, float spacingMult, float spacingAdd, BoringLayout.Metrics metrics,
            boolean includePad, TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
    public @NonNull BoringLayout replaceOrMake(@NonNull CharSequence source,
            @NonNull TextPaint paint, @IntRange(from = 0) int outerWidth,
            @NonNull Alignment align, @NonNull BoringLayout.Metrics metrics, boolean includePad,
            @NonNull TextUtils.TruncateAt ellipsize, @IntRange(from = 0) int ellipsizedWidth,
            boolean useFallbackLineSpacing) {
        boolean trust;

        if (ellipsize == null || ellipsize == TextUtils.TruncateAt.MARQUEE) {
            replaceWith(source, paint, outerWidth, align, spacingMult, spacingAdd);
            replaceWith(source, paint, outerWidth, align, 1f, 0f);

            mEllipsizedWidth = outerWidth;
            mEllipsizedStart = 0;
@@ -148,16 +194,45 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
            trust = true;
        } else {
            replaceWith(TextUtils.ellipsize(source, paint, ellipsizedWidth, ellipsize, true, this),
                    paint, outerWidth, align, spacingMult, spacingAdd);
                    paint, outerWidth, align, 1f, 0f);

            mEllipsizedWidth = ellipsizedWidth;
            trust = false;
        }

        init(getText(), paint, align, metrics, includePad, trust);
        init(getText(), paint, align, metrics, includePad, trust,
                useFallbackLineSpacing);
        return this;
    }

    /**
     * Returns a BoringLayout for the specified text, potentially reusing
     * this one if it is already suitable.  The caller must make sure that
     * no one is still using this Layout.
     *
     * @param source the text to render
     * @param paint the default paint for the layout
     * @param outerWidth the wrapping width for the text
     * @param align whether to left, right, or center the text
     * @param spacingMult this value is no longer used by BoringLayout
     * @param spacingAdd this value is no longer used by BoringLayout
     * @param metrics {@code #Metrics} instance that contains information about FontMetrics and
     *                line width
     * @param includePad set whether to include extra space beyond font ascent and descent which is
     *                   needed to avoid clipping in some scripts
     * @param ellipsize whether to ellipsize the text if width of the text is longer than the
     *                  requested width
     * @param ellipsizedWidth the width to which this Layout is ellipsizing. If {@code ellipsize} is
     *                        {@code null}, or is {@link TextUtils.TruncateAt#MARQUEE} this value is
     *                        not used, {@code outerWidth} is used instead
     */
    public BoringLayout replaceOrMake(CharSequence source, TextPaint paint, int outerWidth,
            Alignment align, float spacingMult, float spacingAdd, BoringLayout.Metrics metrics,
            boolean includePad, TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
        return replaceOrMake(source, paint, outerWidth, align, metrics,
                includePad, ellipsize, ellipsizedWidth, false /* useFallbackLineSpacing */);
    }

    /**
     * @param source the text to render
     * @param paint the default paint for the layout
@@ -178,7 +253,7 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
        mEllipsizedStart = 0;
        mEllipsizedCount = 0;

        init(source, paint, align, metrics, includePad, true);
        init(source, paint, align, metrics, includePad, true, false /* useFallbackLineSpacing */);
    }

    /**
@@ -194,14 +269,46 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
     * @param includePad set whether to include extra space beyond font ascent and descent which is
     *                   needed to avoid clipping in some scripts
     * @param ellipsize whether to ellipsize the text if width of the text is longer than the
     *                  requested {@code outerwidth}
     *                  requested {@code outerWidth}
     * @param ellipsizedWidth the width to which this Layout is ellipsizing. If {@code ellipsize} is
     *                        {@code null}, or is {@link TextUtils.TruncateAt#MARQUEE} this value is
     *                        not used, {@code outerwidth} is used instead
     *                        not used, {@code outerWidth} is used instead
     */
    public BoringLayout(CharSequence source, TextPaint paint, int outerWidth, Alignment align,
            float spacingMult, float spacingAdd, BoringLayout.Metrics metrics, boolean includePad,
            TextUtils.TruncateAt ellipsize, int ellipsizedWidth) {
        this(source, paint, outerWidth, align, spacingMult, spacingAdd, metrics, includePad,
                ellipsize, ellipsizedWidth, false /* fallbackLineSpacing */);
    }

    /**
     *
     * @param source the text to render
     * @param paint the default paint for the layout
     * @param outerWidth the wrapping width for the text
     * @param align whether to left, right, or center the text
     * @param spacingMult this value is no longer used by BoringLayout
     * @param spacingAdd this value is no longer used by BoringLayout
     * @param metrics {@code #Metrics} instance that contains information about FontMetrics and
     *                line width
     * @param includePad set whether to include extra space beyond font ascent and descent which is
     *                   needed to avoid clipping in some scripts
     * @param ellipsize whether to ellipsize the text if width of the text is longer than the
     *                  requested {@code outerWidth}
     * @param ellipsizedWidth the width to which this Layout is ellipsizing. If {@code ellipsize} is
     *                        {@code null}, or is {@link TextUtils.TruncateAt#MARQUEE} this value is
     *                        not used, {@code outerWidth} is used instead
     * @param useFallbackLineSpacing True for adjusting the line spacing based on fallback fonts.
     *                              False for keeping the first font's line height. If some glyphs
     *                              requires larger vertical spaces, by passing true to this
     *                              argument, the layout increase the line height to fit all glyphs.
     */
    public BoringLayout(
            @NonNull CharSequence source, @NonNull TextPaint paint,
            @IntRange(from = 0) int outerWidth, @NonNull Alignment align, float spacingMult,
            float spacingAdd, @NonNull BoringLayout.Metrics metrics, boolean includePad,
            @NonNull TextUtils.TruncateAt ellipsize, @IntRange(from = 0) int ellipsizedWidth,
            boolean useFallbackLineSpacing) {
        /*
         * It is silly to have to call super() and then replaceWith(),
         * but we can't use "this" for the callback until the call to
@@ -224,11 +331,12 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
            trust = false;
        }

        init(getText(), paint, align, metrics, includePad, trust);
        init(getText(), paint, align, metrics, includePad, trust, useFallbackLineSpacing);
    }

    /* package */ void init(CharSequence source, TextPaint paint, Alignment align,
            BoringLayout.Metrics metrics, boolean includePad, boolean trustWidth) {
            BoringLayout.Metrics metrics, boolean includePad, boolean trustWidth,
            boolean useFallbackLineSpacing) {
        int spacing;

        if (source instanceof String && align == Layout.Alignment.ALIGN_NORMAL) {
@@ -260,7 +368,7 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
            TextLine line = TextLine.obtain();
            line.set(paint, source, 0, source.length(), Layout.DIR_LEFT_TO_RIGHT,
                    Layout.DIRS_ALL_LEFT_TO_RIGHT, false, null,
                    mEllipsizedStart, mEllipsizedStart + mEllipsizedCount);
                    mEllipsizedStart, mEllipsizedStart + mEllipsizedCount, useFallbackLineSpacing);
            mMax = (int) Math.ceil(line.metrics(null));
            TextLine.recycle(line);
        }
@@ -336,6 +444,27 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
    @UnsupportedAppUsage
    public static Metrics isBoring(CharSequence text, TextPaint paint,
            TextDirectionHeuristic textDir, Metrics metrics) {
        return isBoring(text, paint, textDir, false /* useFallbackLineSpacing */, metrics);
    }

    /**
     * Returns null if not boring; the width, ascent, and descent in the
     * provided Metrics object (or a new one if the provided one was null)
     * if boring.
     *
     * @param text a text to be calculated text layout.
     * @param paint a paint object used for styling.
     * @param textDir a text direction.
     * @param useFallbackLineSpacing True for adjusting the line spacing based on fallback fonts.
     *                              False for keeping the first font's line height. If some glyphs
     *                              requires larger vertical spaces, by passing true to this
     *                              argument, the layout increase the line height to fit all glyphs.
     * @param metrics the out metrics.
     * @return metrics on success. null if text cannot be rendered by BoringLayout.
     */
    public static @Nullable Metrics isBoring(@NonNull CharSequence text, @NonNull TextPaint paint,
            @NonNull TextDirectionHeuristic textDir, boolean useFallbackLineSpacing,
            @Nullable Metrics metrics) {
        final int textLength = text.length();
        if (hasAnyInterestingChars(text, textLength)) {
           return null;  // There are some interesting characters. Not boring.
@@ -362,7 +491,8 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
        line.set(paint, text, 0, textLength, Layout.DIR_LEFT_TO_RIGHT,
                Layout.DIRS_ALL_LEFT_TO_RIGHT, false, null,
                0 /* ellipsisStart, 0 since text has not been ellipsized at this point */,
                0 /* ellipsisEnd, 0 since text has not been ellipsized at this point */);
                0 /* ellipsisEnd, 0 since text has not been ellipsized at this point */,
                useFallbackLineSpacing);
        fm.width = (int) Math.ceil(line.metrics(fm));
        TextLine.recycle(line);

@@ -450,6 +580,11 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
        return mEllipsizedWidth;
    }

    @Override
    public boolean isFallbackLineSpacingEnabled() {
        return mUseFallbackLineSpacing;
    }

    // Override draw so it will be faster.
    @Override
    public void draw(Canvas c, Path highlight, Paint highlightpaint,
@@ -471,6 +606,7 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback

    private String mDirect;
    private Paint mPaint;
    private boolean mUseFallbackLineSpacing;

    /* package */ int mBottom, mDesc;   // for Direct
    private int mTopPadding, mBottomPadding;
+25 −8
Original line number Diff line number Diff line
@@ -591,7 +591,8 @@ public abstract class Layout {
            } else {
                tl.set(paint, buf, start, end, dir, directions, hasTab, tabStops,
                        getEllipsisStart(lineNum),
                        getEllipsisStart(lineNum) + getEllipsisCount(lineNum));
                        getEllipsisStart(lineNum) + getEllipsisCount(lineNum),
                        isFallbackLineSpacingEnabled());
                if (justify) {
                    tl.justify(right - left - indentWidth);
                }
@@ -959,6 +960,15 @@ public abstract class Layout {
        return 0;
    }

    /**
     * Return true if the fallback line space is enabled in this Layout.
     *
     * @return true if the fallback line space is enabled. Otherwise returns false.
     */
    public boolean isFallbackLineSpacingEnabled() {
        return false;
    }

    /**
     * Returns true if the character at offset and the preceding character
     * are at different run levels (and thus there's a split caret).
@@ -1231,7 +1241,8 @@ public abstract class Layout {

        TextLine tl = TextLine.obtain();
        tl.set(mPaint, mText, start, end, dir, directions, hasTab, tabStops,
                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line));
                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line),
                isFallbackLineSpacingEnabled());
        float wid = tl.measure(offset - start, trailing, null);
        TextLine.recycle(tl);

@@ -1271,7 +1282,8 @@ public abstract class Layout {

        TextLine tl = TextLine.obtain();
        tl.set(mPaint, mText, start, end, dir, directions, hasTab, tabStops,
                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line));
                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line),
                isFallbackLineSpacingEnabled());
        boolean[] trailings = primaryIsTrailingPreviousAllLineOffsets(line);
        if (!primary) {
            for (int offset = 0; offset < trailings.length; ++offset) {
@@ -1456,7 +1468,8 @@ public abstract class Layout {
        paint.setStartHyphenEdit(getStartHyphenEdit(line));
        paint.setEndHyphenEdit(getEndHyphenEdit(line));
        tl.set(paint, mText, start, end, dir, directions, hasTabs, tabStops,
                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line));
                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line),
                isFallbackLineSpacingEnabled());
        if (isJustificationRequired(line)) {
            tl.justify(getJustifyWidth(line));
        }
@@ -1486,7 +1499,8 @@ public abstract class Layout {
        paint.setStartHyphenEdit(getStartHyphenEdit(line));
        paint.setEndHyphenEdit(getEndHyphenEdit(line));
        tl.set(paint, mText, start, end, dir, directions, hasTabs, tabStops,
                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line));
                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line),
                isFallbackLineSpacingEnabled());
        if (isJustificationRequired(line)) {
            tl.justify(getJustifyWidth(line));
        }
@@ -1572,7 +1586,8 @@ public abstract class Layout {
        // XXX: we don't care about tabs as we just use TextLine#getOffsetToLeftRightOf here.
        tl.set(mPaint, mText, lineStartOffset, lineEndOffset, getParagraphDirection(line), dirs,
                false, null,
                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line));
                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line),
                isFallbackLineSpacingEnabled());
        final HorizontalMeasurementProvider horizontal =
                new HorizontalMeasurementProvider(line, primary);

@@ -1828,7 +1843,8 @@ public abstract class Layout {
        TextLine tl = TextLine.obtain();
        // XXX: we don't care about tabs
        tl.set(mPaint, mText, lineStart, lineEnd, lineDir, directions, false, null,
                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line));
                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line),
                isFallbackLineSpacingEnabled());
        caret = lineStart + tl.getOffsetToLeftRightOf(caret - lineStart, toLeft);
        TextLine.recycle(tl);
        return caret;
@@ -2202,7 +2218,8 @@ public abstract class Layout {
                }
            }
            tl.set(paint, text, start, end, dir, directions, hasTabs, tabStops,
                    0 /* ellipsisStart */, 0 /* ellipsisEnd */);
                    0 /* ellipsisStart */, 0 /* ellipsisEnd */,
                    false /* use fallback line spacing. unused */);
            return margin + Math.abs(tl.metrics(null));
        } finally {
            TextLine.recycle(tl);
+10 −4

File changed.

Preview size limit exceeded, changes collapsed.

+35 −1

File changed.

Preview size limit exceeded, changes collapsed.

Loading