/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.text;

import static com.android.graphics.hwui.flags.Flags.highContrastTextLuminance;
import static com.android.text.flags.Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE;
import static com.android.text.flags.Flags.FLAG_USE_BOUNDS_FOR_WIDTH;
import static com.android.text.flags.Flags.FLAG_LETTER_SPACING_JUSTIFICATION;

import android.annotation.FlaggedApi;
import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.BlendMode;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.text.LineBreakConfig;
import android.graphics.text.LineBreaker;
import android.os.Build;
import android.text.method.TextKeyListener;
import android.text.style.AlignmentSpan;
import android.text.style.LeadingMarginSpan;
import android.text.style.LeadingMarginSpan.LeadingMarginSpan2;
import android.text.style.LineBackgroundSpan;
import android.text.style.ParagraphStyle;
import android.text.style.ReplacementSpan;
import android.text.style.TabStopSpan;
import android.widget.TextView;

import com.android.graphics.hwui.flags.Flags;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.ColorUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.text.BreakIterator;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

/**
 * A base class that manages text layout in visual elements on
 * the screen.
 * <p>For text that will be edited, use a {@link DynamicLayout},
 * which will be updated as the text changes.
 * For text that will not change, use a {@link StaticLayout}.
 */
public abstract class Layout {

    // These should match the constants in framework/base/libs/hwui/hwui/DrawTextFunctor.h
    private static final float HIGH_CONTRAST_TEXT_BORDER_WIDTH_MIN_PX = 4f;
    private static final float HIGH_CONTRAST_TEXT_BORDER_WIDTH_FACTOR = 0.2f;

    /** @hide */
    @IntDef(prefix = { "BREAK_STRATEGY_" }, value = {
            LineBreaker.BREAK_STRATEGY_SIMPLE,
            LineBreaker.BREAK_STRATEGY_HIGH_QUALITY,
            LineBreaker.BREAK_STRATEGY_BALANCED
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface BreakStrategy {}

    /**
     * Value for break strategy indicating simple line breaking. Automatic hyphens are not added
     * (though soft hyphens are respected), and modifying text generally doesn't affect the layout
     * before it (which yields a more consistent user experience when editing), but layout may not
     * be the highest quality.
     */
    public static final int BREAK_STRATEGY_SIMPLE = LineBreaker.BREAK_STRATEGY_SIMPLE;

    /**
     * Value for break strategy indicating high quality line breaking, including automatic
     * hyphenation and doing whole-paragraph optimization of line breaks.
     */
    public static final int BREAK_STRATEGY_HIGH_QUALITY = LineBreaker.BREAK_STRATEGY_HIGH_QUALITY;

    /**
     * Value for break strategy indicating balanced line breaking. The breaks are chosen to
     * make all lines as close to the same length as possible, including automatic hyphenation.
     */
    public static final int BREAK_STRATEGY_BALANCED = LineBreaker.BREAK_STRATEGY_BALANCED;

    /** @hide */
    @IntDef(prefix = { "HYPHENATION_FREQUENCY_" }, value = {
            HYPHENATION_FREQUENCY_NORMAL,
            HYPHENATION_FREQUENCY_NORMAL_FAST,
            HYPHENATION_FREQUENCY_FULL,
            HYPHENATION_FREQUENCY_FULL_FAST,
            HYPHENATION_FREQUENCY_NONE
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface HyphenationFrequency {}

    /**
     * Value for hyphenation frequency indicating no automatic hyphenation. Useful
     * for backward compatibility, and for cases where the automatic hyphenation algorithm results
     * in incorrect hyphenation. Mid-word breaks may still happen when a word is wider than the
     * layout and there is otherwise no valid break. Soft hyphens are ignored and will not be used
     * as suggestions for potential line breaks.
     */
    public static final int HYPHENATION_FREQUENCY_NONE = 0;

    /**
     * Value for hyphenation frequency indicating a light amount of automatic hyphenation, which
     * is a conservative default. Useful for informal cases, such as short sentences or chat
     * messages.
     */
    public static final int HYPHENATION_FREQUENCY_NORMAL = 1;

    /**
     * Value for hyphenation frequency indicating the full amount of automatic hyphenation, typical
     * in typography. Useful for running text and where it's important to put the maximum amount of
     * text in a screen with limited space.
     */
    public static final int HYPHENATION_FREQUENCY_FULL = 2;

    /**
     * Value for hyphenation frequency indicating a light amount of automatic hyphenation with
     * using faster algorithm.
     *
     * This option is useful for informal cases, such as short sentences or chat messages. To make
     * text rendering faster with hyphenation, this algorithm ignores some hyphen character related
     * typographic features, e.g. kerning.
     */
    public static final int HYPHENATION_FREQUENCY_NORMAL_FAST = 3;
    /**
     * Value for hyphenation frequency indicating the full amount of automatic hyphenation with
     * using faster algorithm.
     *
     * This option is useful for running text and where it's important to put the maximum amount of
     * text in a screen with limited space. To make text rendering faster with hyphenation, this
     * algorithm ignores some hyphen character related typographic features, e.g. kerning.
     */
    public static final int HYPHENATION_FREQUENCY_FULL_FAST = 4;

    private static final ParagraphStyle[] NO_PARA_SPANS =
        ArrayUtils.emptyArray(ParagraphStyle.class);

    /** @hide */
    @IntDef(prefix = { "JUSTIFICATION_MODE_" }, value = {
            LineBreaker.JUSTIFICATION_MODE_NONE,
            LineBreaker.JUSTIFICATION_MODE_INTER_WORD,
            LineBreaker.JUSTIFICATION_MODE_INTER_CHARACTER,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface JustificationMode {}

    /**
     * Value for justification mode indicating no justification.
     */
    public static final int JUSTIFICATION_MODE_NONE = LineBreaker.JUSTIFICATION_MODE_NONE;

    /**
     * Value for justification mode indicating the text is justified by stretching word spacing.
     */
    public static final int JUSTIFICATION_MODE_INTER_WORD =
            LineBreaker.JUSTIFICATION_MODE_INTER_WORD;

    /**
     * Value for justification mode indicating the text is justified by stretching letter spacing.
     */
    @FlaggedApi(FLAG_LETTER_SPACING_JUSTIFICATION)
    public static final int JUSTIFICATION_MODE_INTER_CHARACTER =
            LineBreaker.JUSTIFICATION_MODE_INTER_CHARACTER;

    /*
     * Line spacing multiplier for default line spacing.
     */
    public static final float DEFAULT_LINESPACING_MULTIPLIER = 1.0f;

    /*
     * Line spacing addition for default line spacing.
     */
    public static final float DEFAULT_LINESPACING_ADDITION = 0.0f;

    /**
     * Strategy which considers a text segment to be inside a rectangle area if the segment bounds
     * intersect the rectangle.
     */
    @NonNull
    public static final TextInclusionStrategy INCLUSION_STRATEGY_ANY_OVERLAP =
            RectF::intersects;

    /**
     * Strategy which considers a text segment to be inside a rectangle area if the center of the
     * segment bounds is inside the rectangle.
     */
    @NonNull
    public static final TextInclusionStrategy INCLUSION_STRATEGY_CONTAINS_CENTER =
            (segmentBounds, area) ->
                    area.contains(segmentBounds.centerX(), segmentBounds.centerY());

    /**
     * Strategy which considers a text segment to be inside a rectangle area if the segment bounds
     * are completely contained within the rectangle.
     */
    @NonNull
    public static final TextInclusionStrategy INCLUSION_STRATEGY_CONTAINS_ALL =
            (segmentBounds, area) -> area.contains(segmentBounds);

    /**
     * Return how wide a layout must be in order to display the specified text with one line per
     * paragraph.
     *
     * <p>As of O, Uses
     * {@link TextDirectionHeuristics#FIRSTSTRONG_LTR} as the default text direction heuristics. In
     * the earlier versions uses {@link TextDirectionHeuristics#LTR} as the default.</p>
     */
    public static float getDesiredWidth(CharSequence source,
                                        TextPaint paint) {
        return getDesiredWidth(source, 0, source.length(), paint);
    }

    /**
     * Return how wide a layout must be in order to display the specified text slice with one
     * line per paragraph.
     *
     * <p>As of O, Uses
     * {@link TextDirectionHeuristics#FIRSTSTRONG_LTR} as the default text direction heuristics. In
     * the earlier versions uses {@link TextDirectionHeuristics#LTR} as the default.</p>
     */
    public static float getDesiredWidth(CharSequence source, int start, int end, TextPaint paint) {
        return getDesiredWidth(source, start, end, paint, TextDirectionHeuristics.FIRSTSTRONG_LTR);
    }

    /**
     * Return how wide a layout must be in order to display the
     * specified text slice with one line per paragraph.
     *
     * @hide
     */
    public static float getDesiredWidth(CharSequence source, int start, int end, TextPaint paint,
            TextDirectionHeuristic textDir) {
        return getDesiredWidthWithLimit(source, start, end, paint, textDir, Float.MAX_VALUE, false);
    }
    /**
     * Return how wide a layout must be in order to display the
     * specified text slice with one line per paragraph.
     *
     * If the measured width exceeds given limit, returns limit value instead.
     * @hide
     */
    public static float getDesiredWidthWithLimit(CharSequence source, int start, int end,
            TextPaint paint, TextDirectionHeuristic textDir, float upperLimit,
            boolean useBoundsForWidth) {
        float need = 0;

        int next;
        for (int i = start; i <= end; i = next) {
            next = TextUtils.indexOf(source, '\n', i, end);

            if (next < 0)
                next = end;

            // note, omits trailing paragraph char
            float w = measurePara(paint, source, i, next, textDir, useBoundsForWidth);
            if (w > upperLimit) {
                return upperLimit;
            }

            if (w > need)
                need = w;

            next++;
        }

        return need;
    }

    /**
     * Subclasses of Layout use this constructor to set the display text,
     * width, and other standard properties.
     * @param text the text to render
     * @param paint the default paint for the layout.  Styles can override
     * various attributes of the paint.
     * @param width the wrapping width for the text.
     * @param align whether to left, right, or center the text.  Styles can
     * override the alignment.
     * @param spacingMult factor by which to scale the font size to get the
     * default line spacing
     * @param spacingAdd amount to add to the default line spacing
     */
    protected Layout(CharSequence text, TextPaint paint,
                     int width, Alignment align,
                     float spacingMult, float spacingAdd) {
        this(text, paint, width, align, TextDirectionHeuristics.FIRSTSTRONG_LTR,
                spacingMult, spacingAdd, false, false, 0, null, Integer.MAX_VALUE,
                BREAK_STRATEGY_SIMPLE, HYPHENATION_FREQUENCY_NONE, null, null,
                JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, false, false, null);
    }

    /**
     * Subclasses of Layout use this constructor to set the display text,
     * width, and other standard properties.
     * @param text the text to render
     * @param paint the default paint for the layout.  Styles can override
     * various attributes of the paint.
     * @param width the wrapping width for the text.
     * @param align whether to left, right, or center the text.  Styles can
     * override the alignment.
     * @param textDir a text direction heuristic.
     * @param spacingMult factor by which to scale the font size to get the
     * default line spacing
     * @param spacingAdd amount to add to the default line spacing
     * @param includePad true for enabling including font padding
     * @param fallbackLineSpacing true for enabling fallback line spacing
     * @param ellipsizedWidth width as used for ellipsizing purpose
     * @param ellipsize an ellipsize option
     * @param maxLines a maximum number of lines.
     * @param breakStrategy a break strategy.
     * @param hyphenationFrequency a hyphenation frequency
     * @param leftIndents a visually left margins
     * @param rightIndents a visually right margins
     * @param justificationMode a justification mode
     * @param lineBreakConfig a line break config
     *
     * @hide
     */
    protected Layout(
            CharSequence text,
            TextPaint paint,
            int width,
            Alignment align,
            TextDirectionHeuristic textDir,
            float spacingMult,
            float spacingAdd,
            boolean includePad,
            boolean fallbackLineSpacing,
            int ellipsizedWidth,
            TextUtils.TruncateAt ellipsize,
            int maxLines,
            int breakStrategy,
            int hyphenationFrequency,
            int[] leftIndents,
            int[] rightIndents,
            int justificationMode,
            LineBreakConfig lineBreakConfig,
            boolean useBoundsForWidth,
            boolean shiftDrawingOffsetForStartOverhang,
            Paint.FontMetrics minimumFontMetrics
    ) {

        if (width < 0)
            throw new IllegalArgumentException("Layout: " + width + " < 0");

        // Ensure paint doesn't have baselineShift set.
        // While normally we don't modify the paint the user passed in,
        // we were already doing this in Styled.drawUniformRun with both
        // baselineShift and bgColor.  We probably should reevaluate bgColor.
        if (paint != null) {
            paint.bgColor = 0;
            paint.baselineShift = 0;
        }

        mText = text;
        mPaint = paint;
        mWidth = width;
        mAlignment = align;
        mSpacingMult = spacingMult;
        mSpacingAdd = spacingAdd;
        mSpannedText = text instanceof Spanned;
        mTextDir = textDir;
        mIncludePad = includePad;
        mFallbackLineSpacing = fallbackLineSpacing;
        mEllipsizedWidth = ellipsize == null ? width : ellipsizedWidth;
        mEllipsize = ellipsize;
        mMaxLines = maxLines;
        mBreakStrategy = breakStrategy;
        mHyphenationFrequency = hyphenationFrequency;
        mLeftIndents = leftIndents;
        mRightIndents = rightIndents;
        mJustificationMode = justificationMode;
        mLineBreakConfig = lineBreakConfig;
        mUseBoundsForWidth = useBoundsForWidth;
        mShiftDrawingOffsetForStartOverhang = shiftDrawingOffsetForStartOverhang;
        mMinimumFontMetrics = minimumFontMetrics;
    }

    /**
     * Replace constructor properties of this Layout with new ones.  Be careful.
     */
    /* package */ void replaceWith(CharSequence text, TextPaint paint,
                              int width, Alignment align,
                              float spacingmult, float spacingadd) {
        if (width < 0) {
            throw new IllegalArgumentException("Layout: " + width + " < 0");
        }

        mText = text;
        mPaint = paint;
        mWidth = width;
        mAlignment = align;
        mSpacingMult = spacingmult;
        mSpacingAdd = spacingadd;
        mSpannedText = text instanceof Spanned;
    }

    /**
     * Draw this Layout on the specified Canvas.
     *
     * This API draws background first, then draws text on top of it.
     *
     * @see #draw(Canvas, List, List, Path, Paint, int)
     */
    public void draw(Canvas c) {
        draw(c, (Path) null, (Paint) null, 0);
    }

    /**
     * Draw this Layout on the specified canvas, with the highlight path drawn
     * between the background and the text.
     *
     * @param canvas the canvas
     * @param selectionHighlight the path of the selection highlight or cursor; can be null
     * @param selectionHighlightPaint the paint for the selection highlight
     * @param cursorOffsetVertical the amount to temporarily translate the
     *        canvas while rendering the highlight
     *
     * @see #draw(Canvas, List, List, Path, Paint, int)
     */
    public void draw(
            Canvas canvas, Path selectionHighlight,
            Paint selectionHighlightPaint, int cursorOffsetVertical) {
        draw(canvas, null, null, selectionHighlight, selectionHighlightPaint, cursorOffsetVertical);
    }

    /**
     * Draw this layout on the specified canvas.
     *
     * This API draws background first, then draws highlight paths on top of it, then draws
     * selection or cursor, then finally draws text on top of it.
     *
     * @see #drawBackground(Canvas)
     * @see #drawText(Canvas)
     *
     * @param canvas the canvas
     * @param highlightPaths the path of the highlights. The highlightPaths and highlightPaints must
     *                      have the same length and aligned in the same order. For example, the
     *                      paint of the n-th of the highlightPaths should be stored at the n-th of
     *                      highlightPaints.
     * @param highlightPaints the paints for the highlights. The highlightPaths and highlightPaints
     *                        must have the same length and aligned in the same order. For example,
     *                        the paint of the n-th of the highlightPaths should be stored at the
     *                        n-th of highlightPaints.
     * @param selectionPath the selection or cursor path
     * @param selectionPaint the paint for the selection or cursor.
     * @param cursorOffsetVertical the amount to temporarily translate the canvas while rendering
     *                            the highlight
     */
    public void draw(@NonNull Canvas canvas,
            @Nullable List<Path> highlightPaths,
            @Nullable List<Paint> highlightPaints,
            @Nullable Path selectionPath,
            @Nullable Paint selectionPaint,
            int cursorOffsetVertical) {
        float leftShift = 0;
        if (mUseBoundsForWidth && mShiftDrawingOffsetForStartOverhang) {
            RectF drawingRect = computeDrawingBoundingBox();
            if (drawingRect.left < 0) {
                leftShift = -drawingRect.left;
                canvas.translate(leftShift, 0);
            }
        }
        final long lineRange = getLineRangeForDraw(canvas);
        int firstLine = TextUtils.unpackRangeStartFromLong(lineRange);
        int lastLine = TextUtils.unpackRangeEndFromLong(lineRange);
        if (lastLine < 0) return;

        if (shouldDrawHighlightsOnTop(canvas)) {
            drawBackground(canvas, firstLine, lastLine);
        } else {
            drawWithoutText(canvas, highlightPaths, highlightPaints, selectionPath, selectionPaint,
                    cursorOffsetVertical, firstLine, lastLine);
        }

        drawText(canvas, firstLine, lastLine);

        // Since high contrast text draws a thick border on the text, the highlight actually makes
        // it harder to read. In this case we draw over the top of the text with a blend mode that
        // ensures the text stays high-contrast.
        if (shouldDrawHighlightsOnTop(canvas)) {
            drawHighlights(canvas, highlightPaths, highlightPaints, selectionPath, selectionPaint,
                    cursorOffsetVertical, firstLine, lastLine);
        }

        if (leftShift != 0) {
            // Manually translate back to the original position because of b/324498002, using
            // save/restore disappears the toggle switch drawables.
            canvas.translate(-leftShift, 0);
        }
    }

    private static boolean shouldDrawHighlightsOnTop(Canvas canvas) {
        return Flags.highContrastTextSmallTextRect() && canvas.isHighContrastTextEnabled();
    }

    private static Paint setToHighlightPaint(Paint p, BlendMode blendMode, Paint outPaint) {
        if (p == null) return null;
        outPaint.set(p);
        outPaint.setBlendMode(blendMode);
        // Yellow for maximum contrast
        outPaint.setColor(Color.YELLOW);
        return outPaint;
    }

    /**
     * Draw text part of this layout.
     *
     * Different from {@link #draw(Canvas, List, List, Path, Paint, int)} API, this API only draws
     * text part, not drawing highlights, selections, or backgrounds.
     *
     * @see #draw(Canvas, List, List, Path, Paint, int)
     * @see #drawBackground(Canvas)
     *
     * @param canvas the canvas
     */
    public void drawText(@NonNull Canvas canvas) {
        final long lineRange = getLineRangeForDraw(canvas);
        int firstLine = TextUtils.unpackRangeStartFromLong(lineRange);
        int lastLine = TextUtils.unpackRangeEndFromLong(lineRange);
        if (lastLine < 0) return;
        drawText(canvas, firstLine, lastLine);
    }

    /**
     * Draw background of this layout.
     *
     * Different from {@link #draw(Canvas, List, List, Path, Paint, int)} API, this API only draws
     * background, not drawing text, highlights or selections. The background here is drawn by
     * {@link LineBackgroundSpan} attached to the text.
     *
     * @see #draw(Canvas, List, List, Path, Paint, int)
     * @see #drawText(Canvas)
     *
     * @param canvas the canvas
     */
    public void drawBackground(@NonNull Canvas canvas) {
        final long lineRange = getLineRangeForDraw(canvas);
        int firstLine = TextUtils.unpackRangeStartFromLong(lineRange);
        int lastLine = TextUtils.unpackRangeEndFromLong(lineRange);
        if (lastLine < 0) return;
        drawBackground(canvas, firstLine, lastLine);
    }

    /**
     * @hide public for Editor.java
     */
    public void drawWithoutText(
            @NonNull Canvas canvas,
            @Nullable List<Path> highlightPaths,
            @Nullable List<Paint> highlightPaints,
            @Nullable Path selectionPath,
            @Nullable Paint selectionPaint,
            int cursorOffsetVertical,
            int firstLine,
            int lastLine) {
        drawBackground(canvas, firstLine, lastLine);
        drawHighlights(canvas, highlightPaths, highlightPaints, selectionPath, selectionPaint,
                cursorOffsetVertical, firstLine, lastLine);
    }

    /**
     * @hide public for Editor.java
     */
    public void drawHighlights(
            @NonNull Canvas canvas,
            @Nullable List<Path> highlightPaths,
            @Nullable List<Paint> highlightPaints,
            @Nullable Path selectionPath,
            @Nullable Paint selectionPaint,
            int cursorOffsetVertical,
            int firstLine,
            int lastLine) {
        if (highlightPaths == null && highlightPaints == null) {
            return;
        }
        if (cursorOffsetVertical != 0) canvas.translate(0, cursorOffsetVertical);
        try {
            BlendMode blendMode = determineHighContrastHighlightBlendMode(canvas);
            if (highlightPaths != null) {
                if (highlightPaints == null) {
                    throw new IllegalArgumentException(
                            "if highlight is specified, highlightPaint must be specified.");
                }
                if (highlightPaints.size() != highlightPaths.size()) {
                    throw new IllegalArgumentException(
                            "The highlight path size is different from the size of highlight"
                                    + " paints");
                }
                for (int i = 0; i < highlightPaths.size(); ++i) {
                    final Path highlight = highlightPaths.get(i);
                    Paint highlightPaint = highlightPaints.get(i);
                    if (shouldDrawHighlightsOnTop(canvas)) {
                        highlightPaint = setToHighlightPaint(highlightPaint, blendMode,
                                mWorkPlainPaint);
                    }

                    if (highlight != null) {
                        canvas.drawPath(highlight, highlightPaint);
                    }
                }
            }

            if (selectionPath != null) {
                if (shouldDrawHighlightsOnTop(canvas)) {
                    selectionPaint = setToHighlightPaint(selectionPaint, blendMode,
                            mWorkPlainPaint);
                }
                canvas.drawPath(selectionPath, selectionPaint);
            }
        } finally {
            if (cursorOffsetVertical != 0) canvas.translate(0, -cursorOffsetVertical);
        }
    }

    @Nullable
    private BlendMode determineHighContrastHighlightBlendMode(Canvas canvas) {
        if (!shouldDrawHighlightsOnTop(canvas)) {
            return null;
        }

        return isHighContrastTextDark() ? BlendMode.MULTIPLY : BlendMode.DIFFERENCE;
    }

    private boolean isHighContrastTextDark() {
        // High-contrast text mode
        // Determine if the text is black-on-white or white-on-black, so we know what blendmode will
        // give the highest contrast and most realistic text color.
        // This equation should match the one in libs/hwui/hwui/DrawTextFunctor.h
        if (highContrastTextLuminance()) {
            var lab = new double[3];
            ColorUtils.colorToLAB(mPaint.getColor(), lab);
            return lab[0] < 0.5;
        } else {
            var color = mPaint.getColor();
            int channelSum = Color.red(color) + Color.green(color) + Color.blue(color);
            return channelSum < (128 * 3);
        }
    }

    private boolean isJustificationRequired(int lineNum) {
        if (mJustificationMode == JUSTIFICATION_MODE_NONE) return false;
        final int lineEnd = getLineEnd(lineNum);
        return lineEnd < mText.length() && mText.charAt(lineEnd - 1) != '\n';
    }

    private float getJustifyWidth(int lineNum) {
        Alignment paraAlign = mAlignment;

        int left = 0;
        int right = mWidth;

        final int dir = getParagraphDirection(lineNum);

        ParagraphStyle[] spans = NO_PARA_SPANS;
        if (mSpannedText) {
            Spanned sp = (Spanned) mText;
            final int start = getLineStart(lineNum);

            final boolean isFirstParaLine = (start == 0 || mText.charAt(start - 1) == '\n');

            if (isFirstParaLine) {
                final int spanEnd = sp.nextSpanTransition(start, mText.length(),
                        ParagraphStyle.class);
                spans = getParagraphSpans(sp, start, spanEnd, ParagraphStyle.class);

                for (int n = spans.length - 1; n >= 0; n--) {
                    if (spans[n] instanceof AlignmentSpan) {
                        paraAlign = ((AlignmentSpan) spans[n]).getAlignment();
                        break;
                    }
                }
            }

            final int length = spans.length;
            boolean useFirstLineMargin = isFirstParaLine;
            for (int n = 0; n < length; n++) {
                if (spans[n] instanceof LeadingMarginSpan2) {
                    int count = ((LeadingMarginSpan2) spans[n]).getLeadingMarginLineCount();
                    int startLine = getLineForOffset(sp.getSpanStart(spans[n]));
                    if (lineNum < startLine + count) {
                        useFirstLineMargin = true;
                        break;
                    }
                }
            }
            for (int n = 0; n < length; n++) {
                if (spans[n] instanceof LeadingMarginSpan) {
                    LeadingMarginSpan margin = (LeadingMarginSpan) spans[n];
                    if (dir == DIR_RIGHT_TO_LEFT) {
                        right -= margin.getLeadingMargin(useFirstLineMargin);
                    } else {
                        left += margin.getLeadingMargin(useFirstLineMargin);
                    }
                }
            }
        }

        final Alignment align;
        if (paraAlign == Alignment.ALIGN_LEFT) {
            align = (dir == DIR_LEFT_TO_RIGHT) ?  Alignment.ALIGN_NORMAL : Alignment.ALIGN_OPPOSITE;
        } else if (paraAlign == Alignment.ALIGN_RIGHT) {
            align = (dir == DIR_LEFT_TO_RIGHT) ?  Alignment.ALIGN_OPPOSITE : Alignment.ALIGN_NORMAL;
        } else {
            align = paraAlign;
        }

        final int indentWidth;
        if (align == Alignment.ALIGN_NORMAL) {
            if (dir == DIR_LEFT_TO_RIGHT) {
                indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
            } else {
                indentWidth = -getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
            }
        } else if (align == Alignment.ALIGN_OPPOSITE) {
            if (dir == DIR_LEFT_TO_RIGHT) {
                indentWidth = -getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
            } else {
                indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
            }
        } else { // Alignment.ALIGN_CENTER
            indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_CENTER);
        }

        return right - left - indentWidth;
    }

    /**
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public void drawText(Canvas canvas, int firstLine, int lastLine) {
        int previousLineBottom = getLineTop(firstLine);
        int previousLineEnd = getLineStart(firstLine);
        ParagraphStyle[] spans = NO_PARA_SPANS;
        int spanEnd = 0;
        final TextPaint paint = mWorkPaint;
        paint.set(mPaint);
        CharSequence buf = mText;

        Alignment paraAlign = mAlignment;
        TabStops tabStops = null;
        boolean tabStopsIsInitialized = false;

        TextLine tl = TextLine.obtain();

        // Draw the lines, one at a time.
        // The baseline is the top of the following line minus the current line's descent.
        for (int lineNum = firstLine; lineNum <= lastLine; lineNum++) {
            int start = previousLineEnd;
            previousLineEnd = getLineStart(lineNum + 1);
            final boolean justify = isJustificationRequired(lineNum);
            int end = getLineVisibleEnd(lineNum, start, previousLineEnd,
                    true /* trailingSpaceAtLastLineIsVisible */);
            paint.setStartHyphenEdit(getStartHyphenEdit(lineNum));
            paint.setEndHyphenEdit(getEndHyphenEdit(lineNum));

            int ltop = previousLineBottom;
            int lbottom = getLineTop(lineNum + 1);
            previousLineBottom = lbottom;
            int lbaseline = lbottom - getLineDescent(lineNum);

            int dir = getParagraphDirection(lineNum);
            int left = 0;
            int right = mWidth;

            if (mSpannedText) {
                Spanned sp = (Spanned) buf;
                int textLength = buf.length();
                boolean isFirstParaLine = (start == 0 || buf.charAt(start - 1) == '\n');

                // New batch of paragraph styles, collect into spans array.
                // Compute the alignment, last alignment style wins.
                // Reset tabStops, we'll rebuild if we encounter a line with
                // tabs.
                // We expect paragraph spans to be relatively infrequent, use
                // spanEnd so that we can check less frequently.  Since
                // paragraph styles ought to apply to entire paragraphs, we can
                // just collect the ones present at the start of the paragraph.
                // If spanEnd is before the end of the paragraph, that's not
                // our problem.
                if (start >= spanEnd && (lineNum == firstLine || isFirstParaLine)) {
                    spanEnd = sp.nextSpanTransition(start, textLength,
                                                    ParagraphStyle.class);
                    spans = getParagraphSpans(sp, start, spanEnd, ParagraphStyle.class);

                    paraAlign = mAlignment;
                    for (int n = spans.length - 1; n >= 0; n--) {
                        if (spans[n] instanceof AlignmentSpan) {
                            paraAlign = ((AlignmentSpan) spans[n]).getAlignment();
                            break;
                        }
                    }

                    tabStopsIsInitialized = false;
                }

                // Draw all leading margin spans.  Adjust left or right according
                // to the paragraph direction of the line.
                final int length = spans.length;
                boolean useFirstLineMargin = isFirstParaLine;
                for (int n = 0; n < length; n++) {
                    if (spans[n] instanceof LeadingMarginSpan2) {
                        int count = ((LeadingMarginSpan2) spans[n]).getLeadingMarginLineCount();
                        int startLine = getLineForOffset(sp.getSpanStart(spans[n]));
                        // if there is more than one LeadingMarginSpan2, use
                        // the count that is greatest
                        if (lineNum < startLine + count) {
                            useFirstLineMargin = true;
                            break;
                        }
                    }
                }
                for (int n = 0; n < length; n++) {
                    if (spans[n] instanceof LeadingMarginSpan) {
                        LeadingMarginSpan margin = (LeadingMarginSpan) spans[n];
                        if (dir == DIR_RIGHT_TO_LEFT) {
                            margin.drawLeadingMargin(canvas, paint, right, dir, ltop,
                                                     lbaseline, lbottom, buf,
                                                     start, end, isFirstParaLine, this);
                            right -= margin.getLeadingMargin(useFirstLineMargin);
                        } else {
                            margin.drawLeadingMargin(canvas, paint, left, dir, ltop,
                                                     lbaseline, lbottom, buf,
                                                     start, end, isFirstParaLine, this);
                            left += margin.getLeadingMargin(useFirstLineMargin);
                        }
                    }
                }
            }

            boolean hasTab = getLineContainsTab(lineNum);
            // Can't tell if we have tabs for sure, currently
            if (hasTab && !tabStopsIsInitialized) {
                if (tabStops == null) {
                    tabStops = new TabStops(TAB_INCREMENT, spans);
                } else {
                    tabStops.reset(TAB_INCREMENT, spans);
                }
                tabStopsIsInitialized = true;
            }

            // Determine whether the line aligns to normal, opposite, or center.
            Alignment align = paraAlign;
            if (align == Alignment.ALIGN_LEFT) {
                align = (dir == DIR_LEFT_TO_RIGHT) ?
                    Alignment.ALIGN_NORMAL : Alignment.ALIGN_OPPOSITE;
            } else if (align == Alignment.ALIGN_RIGHT) {
                align = (dir == DIR_LEFT_TO_RIGHT) ?
                    Alignment.ALIGN_OPPOSITE : Alignment.ALIGN_NORMAL;
            }

            int x;
            final int indentWidth;
            if (align == Alignment.ALIGN_NORMAL) {
                if (dir == DIR_LEFT_TO_RIGHT) {
                    indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
                    x = left + indentWidth;
                } else {
                    indentWidth = -getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
                    x = right - indentWidth;
                }
            } else {
                int max = (int)getLineExtent(lineNum, tabStops, false);
                if (align == Alignment.ALIGN_OPPOSITE) {
                    if (dir == DIR_LEFT_TO_RIGHT) {
                        indentWidth = -getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT);
                        x = right - max - indentWidth;
                    } else {
                        indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_LEFT);
                        x = left - max + indentWidth;
                    }
                } else { // Alignment.ALIGN_CENTER
                    indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_CENTER);
                    max = max & ~1;
                    x = ((right + left - max) >> 1) + indentWidth;
                }
            }

            Directions directions = getLineDirections(lineNum);
            if (directions == DIRS_ALL_LEFT_TO_RIGHT && !mSpannedText && !hasTab && !justify) {
                // XXX: assumes there's nothing additional to be done
                canvas.drawText(buf, start, end, x, lbaseline, paint);
            } else {
                tl.set(paint, buf, start, end, dir, directions, hasTab, tabStops,
                        getEllipsisStart(lineNum),
                        getEllipsisStart(lineNum) + getEllipsisCount(lineNum),
                        isFallbackLineSpacingEnabled());
                if (justify) {
                    tl.justify(mJustificationMode, right - left - indentWidth);
                }
                tl.draw(canvas, x, ltop, lbaseline, lbottom);
            }
        }

        TextLine.recycle(tl);
    }

    /**
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public void drawBackground(
            @NonNull Canvas canvas,
            int firstLine, int lastLine) {

        drawHighContrastBackground(canvas, firstLine, lastLine);

        // First, draw LineBackgroundSpans.
        // LineBackgroundSpans know nothing about the alignment, margins, or
        // direction of the layout or line.  XXX: Should they?
        // They are evaluated at each line.
        if (mSpannedText) {
            if (mLineBackgroundSpans == null) {
                mLineBackgroundSpans = new SpanSet<LineBackgroundSpan>(LineBackgroundSpan.class);
            }

            Spanned buffer = (Spanned) mText;
            int textLength = buffer.length();
            mLineBackgroundSpans.init(buffer, 0, textLength);

            if (mLineBackgroundSpans.numberOfSpans > 0) {
                int previousLineBottom = getLineTop(firstLine);
                int previousLineEnd = getLineStart(firstLine);
                ParagraphStyle[] spans = NO_PARA_SPANS;
                int spansLength = 0;
                TextPaint paint = mPaint;
                int spanEnd = 0;
                final int width = mWidth;
                for (int i = firstLine; i <= lastLine; i++) {
                    int start = previousLineEnd;
                    int end = getLineStart(i + 1);
                    previousLineEnd = end;

                    int ltop = previousLineBottom;
                    int lbottom = getLineTop(i + 1);
                    previousLineBottom = lbottom;
                    int lbaseline = lbottom - getLineDescent(i);

                    if (end >= spanEnd) {
                        // These should be infrequent, so we'll use this so that
                        // we don't have to check as often.
                        spanEnd = mLineBackgroundSpans.getNextTransition(start, textLength);
                        // All LineBackgroundSpans on a line contribute to its background.
                        spansLength = 0;
                        // Duplication of the logic of getParagraphSpans
                        if (start != end || start == 0) {
                            // Equivalent to a getSpans(start, end), but filling the 'spans' local
                            // array instead to reduce memory allocation
                            for (int j = 0; j < mLineBackgroundSpans.numberOfSpans; j++) {
                                // equal test is valid since both intervals are not empty by
                                // construction
                                if (mLineBackgroundSpans.spanStarts[j] >= end ||
                                        mLineBackgroundSpans.spanEnds[j] <= start) continue;
                                spans = GrowingArrayUtils.append(
                                        spans, spansLength, mLineBackgroundSpans.spans[j]);
                                spansLength++;
                            }
                        }
                    }

                    for (int n = 0; n < spansLength; n++) {
                        LineBackgroundSpan lineBackgroundSpan = (LineBackgroundSpan) spans[n];
                        lineBackgroundSpan.drawBackground(canvas, paint, 0, width,
                                ltop, lbaseline, lbottom,
                                buffer, start, end, i);
                    }
                }
            }
            mLineBackgroundSpans.recycle();
        }
    }

    /**
     * Draws a solid rectangle behind the text, the same color as the high contrast stroke border,
     * to make it even easier to read.
     *
     * <p>We draw it here instead of in DrawTextFunctor so that multiple spans don't draw
     * backgrounds over each other's text.
     */
    private void drawHighContrastBackground(@NonNull Canvas canvas, int firstLine, int lastLine) {
        if (!shouldDrawHighlightsOnTop(canvas)) {
            return;
        }

        var padding = Math.max(HIGH_CONTRAST_TEXT_BORDER_WIDTH_MIN_PX,
                mPaint.getTextSize() * HIGH_CONTRAST_TEXT_BORDER_WIDTH_FACTOR);

        var bgPaint = mWorkPlainPaint;
        bgPaint.reset();
        bgPaint.setColor(isHighContrastTextDark() ? Color.WHITE : Color.BLACK);
        bgPaint.setStyle(Paint.Style.FILL);

        int start = getLineStart(firstLine);
        int end = getLineEnd(lastLine);
        // Draw a separate background rectangle for each line of text, that only surrounds the
        // characters on that line.
        forEachCharacterBounds(
                start,
                end,
                firstLine,
                lastLine,
                new CharacterBoundsListener() {
                    int mLastLineNum = -1;
                    final RectF mLineBackground = new RectF();

                    @Override
                    public void onCharacterBounds(int index, int lineNum, float left, float top,
                            float right, float bottom) {
                        if (lineNum != mLastLineNum) {
                            drawRect();
                            mLineBackground.set(left, top, right, bottom);
                            mLastLineNum = lineNum;
                        } else {
                            mLineBackground.union(left, top, right, bottom);
                        }
                    }

                    @Override
                    public void onEnd() {
                        drawRect();
                    }

                    private void drawRect() {
                        if (!mLineBackground.isEmpty()) {
                            mLineBackground.inset(-padding, -padding);
                            canvas.drawRect(mLineBackground, bgPaint);
                        }
                    }
                }
        );
    }

    /**
     * @param canvas
     * @return The range of lines that need to be drawn, possibly empty.
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public long getLineRangeForDraw(Canvas canvas) {
        int dtop, dbottom;

        synchronized (sTempRect) {
            if (!canvas.getClipBounds(sTempRect)) {
                // Negative range end used as a special flag
                return TextUtils.packRangeInLong(0, -1);
            }

            dtop = sTempRect.top;
            dbottom = sTempRect.bottom;
        }

        final int top = Math.max(dtop, 0);
        final int bottom = Math.min(getLineTop(getLineCount()), dbottom);

        if (top >= bottom) return TextUtils.packRangeInLong(0, -1);
        return TextUtils.packRangeInLong(getLineForVertical(top), getLineForVertical(bottom));
    }

    /**
     * Return the start position of the line, given the left and right bounds of the margins.
     *
     * @param line the line index
     * @param left the left bounds (0, or leading margin if ltr para)
     * @param right the right bounds (width, minus leading margin if rtl para)
     * @return the start position of the line (to right of line if rtl para)
     */
    private int getLineStartPos(int line, int left, int right) {
        // Adjust the point at which to start rendering depending on the
        // alignment of the paragraph.
        Alignment align = getParagraphAlignment(line);
        int dir = getParagraphDirection(line);

        if (align == Alignment.ALIGN_LEFT) {
            align = (dir == DIR_LEFT_TO_RIGHT) ? Alignment.ALIGN_NORMAL : Alignment.ALIGN_OPPOSITE;
        } else if (align == Alignment.ALIGN_RIGHT) {
            align = (dir == DIR_LEFT_TO_RIGHT) ? Alignment.ALIGN_OPPOSITE : Alignment.ALIGN_NORMAL;
        }

        int x;
        if (align == Alignment.ALIGN_NORMAL) {
            if (dir == DIR_LEFT_TO_RIGHT) {
                x = left + getIndentAdjust(line, Alignment.ALIGN_LEFT);
            } else {
                x = right + getIndentAdjust(line, Alignment.ALIGN_RIGHT);
            }
        } else {
            TabStops tabStops = null;
            if (mSpannedText && getLineContainsTab(line)) {
                Spanned spanned = (Spanned) mText;
                int start = getLineStart(line);
                int spanEnd = spanned.nextSpanTransition(start, spanned.length(),
                        TabStopSpan.class);
                TabStopSpan[] tabSpans = getParagraphSpans(spanned, start, spanEnd,
                        TabStopSpan.class);
                if (tabSpans.length > 0) {
                    tabStops = new TabStops(TAB_INCREMENT, tabSpans);
                }
            }
            int max = (int)getLineExtent(line, tabStops, false);
            if (align == Alignment.ALIGN_OPPOSITE) {
                if (dir == DIR_LEFT_TO_RIGHT) {
                    x = right - max + getIndentAdjust(line, Alignment.ALIGN_RIGHT);
                } else {
                    // max is negative here
                    x = left - max + getIndentAdjust(line, Alignment.ALIGN_LEFT);
                }
            } else { // Alignment.ALIGN_CENTER
                max = max & ~1;
                x = (left + right - max) >> 1 + getIndentAdjust(line, Alignment.ALIGN_CENTER);
            }
        }
        return x;
    }

    /**
     * Increase the width of this layout to the specified width.
     * Be careful to use this only when you know it is appropriate&mdash;
     * it does not cause the text to reflow to use the full new width.
     */
    public final void increaseWidthTo(int wid) {
        if (wid < mWidth) {
            throw new RuntimeException("attempted to reduce Layout width");
        }

        mWidth = wid;
    }

    /**
     * Return the total height of this layout.
     */
    public int getHeight() {
        return getLineTop(getLineCount());
    }

    /**
     * Return the total height of this layout.
     *
     * @param cap if true and max lines is set, returns the height of the layout at the max lines.
     *
     * @hide
     */
    public int getHeight(boolean cap) {
        return getHeight();
    }

    /**
     * Return the number of lines of text in this layout.
     */
    public abstract int getLineCount();

    /**
     * Get an actual bounding box that draws text content.
     *
     * Note that the {@link RectF#top} and {@link RectF#bottom} may be different from the
     * {@link Layout#getLineTop(int)} of the first line and {@link Layout#getLineBottom(int)} of
     * the last line. The line top and line bottom are calculated based on yMin/yMax or
     * ascent/descent value of font file. On the other hand, the drawing bounding boxes are
     * calculated based on actual glyphs used there.
     *
     * @return bounding rectangle
     */
    @NonNull
    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
    public RectF computeDrawingBoundingBox() {
        float left = 0;
        float right = 0;
        float top = 0;
        float bottom = 0;
        TextLine tl = TextLine.obtain();
        RectF rectF = new RectF();
        for (int line = 0; line < getLineCount(); ++line) {
            final int start = getLineStart(line);
            final int end = getLineVisibleEnd(line);

            final boolean hasTabs = getLineContainsTab(line);
            TabStops tabStops = null;
            if (hasTabs && mText instanceof Spanned) {
                // Just checking this line should be good enough, tabs should be
                // consistent across all lines in a paragraph.
                TabStopSpan[] tabs = getParagraphSpans((Spanned) mText, start, end,
                        TabStopSpan.class);
                if (tabs.length > 0) {
                    tabStops = new TabStops(TAB_INCREMENT, tabs); // XXX should reuse
                }
            }
            final Directions directions = getLineDirections(line);
            // Returned directions can actually be null
            if (directions == null) {
                continue;
            }
            final int dir = getParagraphDirection(line);

            final TextPaint paint = mWorkPaint;
            paint.set(mPaint);
            paint.setStartHyphenEdit(getStartHyphenEdit(line));
            paint.setEndHyphenEdit(getEndHyphenEdit(line));
            tl.set(paint, mText, start, end, dir, directions, hasTabs, tabStops,
                    getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line),
                    isFallbackLineSpacingEnabled());
            if (isJustificationRequired(line)) {
                tl.justify(mJustificationMode, getJustifyWidth(line));
            }
            tl.metrics(null, rectF, false, null);

            float lineLeft = rectF.left;
            float lineRight = rectF.right;
            float lineTop = rectF.top + getLineBaseline(line);
            float lineBottom = rectF.bottom + getLineBaseline(line);
            if (getParagraphDirection(line) == Layout.DIR_RIGHT_TO_LEFT) {
                lineLeft += getWidth();
                lineRight += getWidth();
            }

            if (line == 0) {
                left = lineLeft;
                right = lineRight;
                top = lineTop;
                bottom = lineBottom;
            } else {
                left = Math.min(left, lineLeft);
                right = Math.max(right, lineRight);
                top = Math.min(top, lineTop);
                bottom = Math.max(bottom, lineBottom);
            }
        }
        TextLine.recycle(tl);
        return new RectF(left, top, right, bottom);
    }

    /**
     * Return the baseline for the specified line (0&hellip;getLineCount() - 1)
     * If bounds is not null, return the top, left, right, bottom extents
     * of the specified line in it.
     * @param line which line to examine (0..getLineCount() - 1)
     * @param bounds Optional. If not null, it returns the extent of the line
     * @return the Y-coordinate of the baseline
     */
    public int getLineBounds(int line, Rect bounds) {
        if (bounds != null) {
            bounds.left = 0;     // ???
            bounds.top = getLineTop(line);
            bounds.right = mWidth;   // ???
            bounds.bottom = getLineTop(line + 1);
        }
        return getLineBaseline(line);
    }

    /**
     * Return the vertical position of the top of the specified line
     * (0&hellip;getLineCount()).
     * If the specified line is equal to the line count, returns the
     * bottom of the last line.
     */
    public abstract int getLineTop(int line);

    /**
     * Return the descent of the specified line(0&hellip;getLineCount() - 1).
     */
    public abstract int getLineDescent(int line);

    /**
     * Return the text offset of the beginning of the specified line (
     * 0&hellip;getLineCount()). If the specified line is equal to the line
     * count, returns the length of the text.
     */
    public abstract int getLineStart(int line);

    /**
     * Returns the primary directionality of the paragraph containing the
     * specified line, either 1 for left-to-right lines, or -1 for right-to-left
     * lines (see {@link #DIR_LEFT_TO_RIGHT}, {@link #DIR_RIGHT_TO_LEFT}).
     */
    public abstract int getParagraphDirection(int line);

    /**
     * Returns whether the specified line contains one or more
     * characters that need to be handled specially, like tabs.
     */
    public abstract boolean getLineContainsTab(int line);

    /**
     * Returns the directional run information for the specified line.
     * The array alternates counts of characters in left-to-right
     * and right-to-left segments of the line.
     *
     * <p>NOTE: this is inadequate to support bidirectional text, and will change.
     */
    public abstract Directions getLineDirections(int line);

    /**
     * Returns the (negative) number of extra pixels of ascent padding in the
     * top line of the Layout.
     */
    public abstract int getTopPadding();

    /**
     * Returns the number of extra pixels of descent padding in the
     * bottom line of the Layout.
     */
    public abstract int getBottomPadding();

    /**
     * Returns the start hyphen edit for a line.
     *
     * @hide
     */
    public @Paint.StartHyphenEdit int getStartHyphenEdit(int line) {
        return Paint.START_HYPHEN_EDIT_NO_EDIT;
    }

    /**
     * Returns the end hyphen edit for a line.
     *
     * @hide
     */
    public @Paint.EndHyphenEdit int getEndHyphenEdit(int line) {
        return Paint.END_HYPHEN_EDIT_NO_EDIT;
    }

    /**
     * Returns the left indent for a line.
     *
     * @hide
     */
    public int getIndentAdjust(int line, Alignment alignment) {
        return 0;
    }

    /**
     * Returns true if the character at offset and the preceding character
     * are at different run levels (and thus there's a split caret).
     * @param offset the offset
     * @return true if at a level boundary
     * @hide
     */
    @UnsupportedAppUsage
    public boolean isLevelBoundary(int offset) {
        int line = getLineForOffset(offset);
        Directions dirs = getLineDirections(line);
        if (dirs == DIRS_ALL_LEFT_TO_RIGHT || dirs == DIRS_ALL_RIGHT_TO_LEFT) {
            return false;
        }

        int[] runs = dirs.mDirections;
        int lineStart = getLineStart(line);
        int lineEnd = getLineEnd(line);
        if (offset == lineStart || offset == lineEnd) {
            int paraLevel = getParagraphDirection(line) == 1 ? 0 : 1;
            int runIndex = offset == lineStart ? 0 : runs.length - 2;
            return ((runs[runIndex + 1] >>> RUN_LEVEL_SHIFT) & RUN_LEVEL_MASK) != paraLevel;
        }

        offset -= lineStart;
        for (int i = 0; i < runs.length; i += 2) {
            if (offset == runs[i]) {
                return true;
            }
        }
        return false;
    }

    /**
     * Returns true if the character at offset is right to left (RTL).
     * @param offset the offset
     * @return true if the character is RTL, false if it is LTR
     */
    public boolean isRtlCharAt(int offset) {
        int line = getLineForOffset(offset);
        Directions dirs = getLineDirections(line);
        if (dirs == DIRS_ALL_LEFT_TO_RIGHT) {
            return false;
        }
        if (dirs == DIRS_ALL_RIGHT_TO_LEFT) {
            return  true;
        }
        int[] runs = dirs.mDirections;
        int lineStart = getLineStart(line);
        for (int i = 0; i < runs.length; i += 2) {
            int start = lineStart + runs[i];
            int limit = start + (runs[i+1] & RUN_LENGTH_MASK);
            if (offset >= start && offset < limit) {
                int level = (runs[i+1] >>> RUN_LEVEL_SHIFT) & RUN_LEVEL_MASK;
                return ((level & 1) != 0);
            }
        }
        // Should happen only if the offset is "out of bounds"
        return false;
    }

    /**
     * Returns the range of the run that the character at offset belongs to.
     * @param offset the offset
     * @return The range of the run
     * @hide
     */
    public long getRunRange(int offset) {
        int line = getLineForOffset(offset);
        Directions dirs = getLineDirections(line);
        if (dirs == DIRS_ALL_LEFT_TO_RIGHT || dirs == DIRS_ALL_RIGHT_TO_LEFT) {
            return TextUtils.packRangeInLong(0, getLineEnd(line));
        }
        int[] runs = dirs.mDirections;
        int lineStart = getLineStart(line);
        for (int i = 0; i < runs.length; i += 2) {
            int start = lineStart + runs[i];
            int limit = start + (runs[i+1] & RUN_LENGTH_MASK);
            if (offset >= start && offset < limit) {
                return TextUtils.packRangeInLong(start, limit);
            }
        }
        // Should happen only if the offset is "out of bounds"
        return TextUtils.packRangeInLong(0, getLineEnd(line));
    }

    /**
     * Checks if the trailing BiDi level should be used for an offset
     *
     * This method is useful when the offset is at the BiDi level transition point and determine
     * which run need to be used. For example, let's think about following input: (L* denotes
     * Left-to-Right characters, R* denotes Right-to-Left characters.)
     * Input (Logical Order): L1 L2 L3 R1 R2 R3 L4 L5 L6
     * Input (Display Order): L1 L2 L3 R3 R2 R1 L4 L5 L6
     *
     * Then, think about selecting the range (3, 6). The offset=3 and offset=6 are ambiguous here
     * since they are at the BiDi transition point.  In Android, the offset is considered to be
     * associated with the trailing run if the BiDi level of the trailing run is higher than of the
     * previous run.  In this case, the BiDi level of the input text is as follows:
     *
     * Input (Logical Order): L1 L2 L3 R1 R2 R3 L4 L5 L6
     *              BiDi Run: [ Run 0 ][ Run 1 ][ Run 2 ]
     *            BiDi Level:  0  0  0  1  1  1  0  0  0
     *
     * Thus, offset = 3 is part of Run 1 and this method returns true for offset = 3, since the BiDi
     * level of Run 1 is higher than the level of Run 0.  Similarly, the offset = 6 is a part of Run
     * 1 and this method returns false for the offset = 6 since the BiDi level of Run 1 is higher
     * than the level of Run 2.
     *
     * @returns true if offset is at the BiDi level transition point and trailing BiDi level is
     *          higher than previous BiDi level. See above for the detail.
     * @hide
     */
    @VisibleForTesting
    public boolean primaryIsTrailingPrevious(int offset) {
        int line = getLineForOffset(offset);
        int lineStart = getLineStart(line);
        int lineEnd = getLineEnd(line);
        int[] runs = getLineDirections(line).mDirections;

        int levelAt = -1;
        for (int i = 0; i < runs.length; i += 2) {
            int start = lineStart + runs[i];
            int limit = start + (runs[i+1] & RUN_LENGTH_MASK);
            if (limit > lineEnd) {
                limit = lineEnd;
            }
            if (offset >= start && offset < limit) {
                if (offset > start) {
                    // Previous character is at same level, so don't use trailing.
                    return false;
                }
                levelAt = (runs[i+1] >>> RUN_LEVEL_SHIFT) & RUN_LEVEL_MASK;
                break;
            }
        }
        if (levelAt == -1) {
            // Offset was limit of line.
            levelAt = getParagraphDirection(line) == 1 ? 0 : 1;
        }

        // At level boundary, check previous level.
        int levelBefore = -1;
        if (offset == lineStart) {
            levelBefore = getParagraphDirection(line) == 1 ? 0 : 1;
        } else {
            offset -= 1;
            for (int i = 0; i < runs.length; i += 2) {
                int start = lineStart + runs[i];
                int limit = start + (runs[i+1] & RUN_LENGTH_MASK);
                if (limit > lineEnd) {
                    limit = lineEnd;
                }
                if (offset >= start && offset < limit) {
                    levelBefore = (runs[i+1] >>> RUN_LEVEL_SHIFT) & RUN_LEVEL_MASK;
                    break;
                }
            }
        }

        return levelBefore < levelAt;
    }

    /**
     * Computes in linear time the results of calling
     * #primaryIsTrailingPrevious for all offsets on a line.
     * @param line The line giving the offsets we compute the information for
     * @return The array of results, indexed from 0, where 0 corresponds to the line start offset
     * @hide
     */
    @VisibleForTesting
    public boolean[] primaryIsTrailingPreviousAllLineOffsets(int line) {
        int lineStart = getLineStart(line);
        int lineEnd = getLineEnd(line);
        int[] runs = getLineDirections(line).mDirections;

        boolean[] trailing = new boolean[lineEnd - lineStart + 1];

        byte[] level = new byte[lineEnd - lineStart + 1];
        for (int i = 0; i < runs.length; i += 2) {
            int start = lineStart + runs[i];
            int limit = start + (runs[i + 1] & RUN_LENGTH_MASK);
            if (limit > lineEnd) {
                limit = lineEnd;
            }
            if (limit == start) {
                continue;
            }
            level[limit - lineStart - 1] =
                    (byte) ((runs[i + 1] >>> RUN_LEVEL_SHIFT) & RUN_LEVEL_MASK);
        }

        for (int i = 0; i < runs.length; i += 2) {
            int start = lineStart + runs[i];
            byte currentLevel = (byte) ((runs[i + 1] >>> RUN_LEVEL_SHIFT) & RUN_LEVEL_MASK);
            trailing[start - lineStart] = currentLevel > (start == lineStart
                    ? (getParagraphDirection(line) == 1 ? 0 : 1)
                    : level[start - lineStart - 1]);
        }

        return trailing;
    }

    /**
     * Get the primary horizontal position for the specified text offset.
     * This is the location where a new character would be inserted in
     * the paragraph's primary direction.
     */
    public float getPrimaryHorizontal(int offset) {
        return getPrimaryHorizontal(offset, false /* not clamped */);
    }

    /**
     * Get the primary horizontal position for the specified text offset, but
     * optionally clamp it so that it doesn't exceed the width of the layout.
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public float getPrimaryHorizontal(int offset, boolean clamped) {
        boolean trailing = primaryIsTrailingPrevious(offset);
        return getHorizontal(offset, trailing, clamped);
    }

    /**
     * Get the secondary horizontal position for the specified text offset.
     * This is the location where a new character would be inserted in
     * the direction other than the paragraph's primary direction.
     */
    public float getSecondaryHorizontal(int offset) {
        return getSecondaryHorizontal(offset, false /* not clamped */);
    }

    /**
     * Get the secondary horizontal position for the specified text offset, but
     * optionally clamp it so that it doesn't exceed the width of the layout.
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public float getSecondaryHorizontal(int offset, boolean clamped) {
        boolean trailing = primaryIsTrailingPrevious(offset);
        return getHorizontal(offset, !trailing, clamped);
    }

    private float getHorizontal(int offset, boolean primary) {
        return primary ? getPrimaryHorizontal(offset) : getSecondaryHorizontal(offset);
    }

    private float getHorizontal(int offset, boolean trailing, boolean clamped) {
        int line = getLineForOffset(offset);

        return getHorizontal(offset, trailing, line, clamped);
    }

    private float getHorizontal(int offset, boolean trailing, int line, boolean clamped) {
        int start = getLineStart(line);
        int end = getLineEnd(line);
        int dir = getParagraphDirection(line);
        boolean hasTab = getLineContainsTab(line);
        Directions directions = getLineDirections(line);

        TabStops tabStops = null;
        if (hasTab && mText instanceof Spanned) {
            // Just checking this line should be good enough, tabs should be
            // consistent across all lines in a paragraph.
            TabStopSpan[] tabs = getParagraphSpans((Spanned) mText, start, end, TabStopSpan.class);
            if (tabs.length > 0) {
                tabStops = new TabStops(TAB_INCREMENT, tabs); // XXX should reuse
            }
        }

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

        if (clamped && wid > mWidth) {
            wid = mWidth;
        }
        int left = getParagraphLeft(line);
        int right = getParagraphRight(line);

        return getLineStartPos(line, left, right) + wid;
    }

    /**
     * Computes in linear time the results of calling #getHorizontal for all offsets on a line.
     *
     * @param line The line giving the offsets we compute information for
     * @param clamped Whether to clamp the results to the width of the layout
     * @param primary Whether the results should be the primary or the secondary horizontal
     * @return The array of results, indexed from 0, where 0 corresponds to the line start offset
     */
    private float[] getLineHorizontals(int line, boolean clamped, boolean primary) {
        int start = getLineStart(line);
        int end = getLineEnd(line);
        int dir = getParagraphDirection(line);
        boolean hasTab = getLineContainsTab(line);
        Directions directions = getLineDirections(line);

        TabStops tabStops = null;
        if (hasTab && mText instanceof Spanned) {
            // Just checking this line should be good enough, tabs should be
            // consistent across all lines in a paragraph.
            TabStopSpan[] tabs = getParagraphSpans((Spanned) mText, start, end, TabStopSpan.class);
            if (tabs.length > 0) {
                tabStops = new TabStops(TAB_INCREMENT, tabs); // XXX should reuse
            }
        }

        TextLine tl = TextLine.obtain();
        tl.set(mPaint, mText, start, end, dir, directions, hasTab, tabStops,
                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line),
                isFallbackLineSpacingEnabled());
        boolean[] trailings = primaryIsTrailingPreviousAllLineOffsets(line);
        if (!primary) {
            for (int offset = 0; offset < trailings.length; ++offset) {
                trailings[offset] = !trailings[offset];
            }
        }
        float[] wid = tl.measureAllOffsets(trailings, null);
        TextLine.recycle(tl);

        if (clamped) {
            for (int offset = 0; offset < wid.length; ++offset) {
                if (wid[offset] > mWidth) {
                    wid[offset] = mWidth;
                }
            }
        }
        int left = getParagraphLeft(line);
        int right = getParagraphRight(line);

        int lineStartPos = getLineStartPos(line, left, right);
        float[] horizontal = new float[end - start + 1];
        for (int offset = 0; offset < horizontal.length; ++offset) {
            horizontal[offset] = lineStartPos + wid[offset];
        }
        return horizontal;
    }

    private void fillHorizontalBoundsForLine(int line, float[] horizontalBounds) {
        final int lineStart = getLineStart(line);
        final int lineEnd = getLineEnd(line);
        final int lineLength = lineEnd - lineStart;

        final int dir = getParagraphDirection(line);
        final Directions directions = getLineDirections(line);

        final boolean hasTab = getLineContainsTab(line);
        TabStops tabStops = null;
        if (hasTab && mText instanceof Spanned) {
            // Just checking this line should be good enough, tabs should be
            // consistent across all lines in a paragraph.
            TabStopSpan[] tabs =
                    getParagraphSpans((Spanned) mText, lineStart, lineEnd, TabStopSpan.class);
            if (tabs.length > 0) {
                tabStops = new TabStops(TAB_INCREMENT, tabs); // XXX should reuse
            }
        }

        final TextLine tl = TextLine.obtain();
        tl.set(mPaint, mText, lineStart, lineEnd, dir, directions, hasTab, tabStops,
                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line),
                isFallbackLineSpacingEnabled());
        if (horizontalBounds == null || horizontalBounds.length < 2 * lineLength) {
            horizontalBounds = new float[2 * lineLength];
        }

        tl.measureAllBounds(horizontalBounds, null);
        TextLine.recycle(tl);
    }

    /**
     * Return the characters' bounds in the given range. The {@code bounds} array will be filled
     * starting from {@code boundsStart} (inclusive). The coordinates are in local text layout.
     *
     * @param start the start index to compute the character bounds, inclusive.
     * @param end the end index to compute the character bounds, exclusive.
     * @param bounds the array to fill in the character bounds. The array is divided into segments
     *               of four where each index in that segment represents left, top, right and
     *               bottom of the character.
     * @param boundsStart the inclusive start index in the array to start filling in the values
     *                    from.
     *
     * @throws IndexOutOfBoundsException if the range defined by {@code start} and {@code end}
     * exceeds the range of the text, or {@code bounds} doesn't have enough space to store the
     * result.
     * @throws IllegalArgumentException if {@code bounds} is null.
     */
    public void fillCharacterBounds(@IntRange(from = 0) int start, @IntRange(from = 0) int end,
            @NonNull float[] bounds, @IntRange(from = 0) int boundsStart) {
        if (start < 0 || end < start || end > mText.length()) {
            throw new IndexOutOfBoundsException("given range: " + start + ", " + end + " is "
                    + "out of the text range: 0, " + mText.length());
        }

        if (bounds == null) {
            throw new IllegalArgumentException("bounds can't be null.");
        }

        final int neededLength = 4 * (end - start);
        if (neededLength > bounds.length - boundsStart) {
            throw new IndexOutOfBoundsException("bounds doesn't have enough space to store the "
                    + "result, needed: " + neededLength + " had: "
                    + (bounds.length - boundsStart));
        }

        if (start == end) {
            return;
        }

        final int startLine = getLineForOffset(start);
        final int endLine = getLineForOffset(end - 1);

        forEachCharacterBounds(start, end, startLine, endLine,
                (index, lineNum, left, lineTop, right, lineBottom) -> {
                    final int boundsIndex = boundsStart + 4 * (index - start);
                    bounds[boundsIndex] = left;
                    bounds[boundsIndex + 1] = lineTop;
                    bounds[boundsIndex + 2] = right;
                    bounds[boundsIndex + 3] = lineBottom;
                });
    }

    /**
     * Return the characters' bounds in the given range. The coordinates are in local text layout.
     *
     * @param start the start index to compute the character bounds, inclusive.
     * @param end the end index to compute the character bounds, exclusive.
     * @param startLine index of the line that contains {@code start}
     * @param endLine index of the line that contains {@code end}
     * @param listener called for each character with its bounds
     *
     */
    private void forEachCharacterBounds(
            @IntRange(from = 0) int start,
            @IntRange(from = 0) int end,
            @IntRange(from = 0) int startLine,
            @IntRange(from = 0) int endLine,
            CharacterBoundsListener listener
    ) {
        float[] horizontalBounds = null;
        for (int line = startLine; line <= endLine; ++line) {
            final int lineStart = getLineStart(line);
            final int lineEnd = getLineEnd(line);
            final int lineLength = lineEnd - lineStart;
            if (horizontalBounds == null || horizontalBounds.length < 2 * lineLength) {
                horizontalBounds = new float[2 * lineLength];
            }
            fillHorizontalBoundsForLine(line, horizontalBounds);

            final int lineLeft = getParagraphLeft(line);
            final int lineRight = getParagraphRight(line);
            final int lineStartPos = getLineStartPos(line, lineLeft, lineRight);

            final int lineTop = getLineTop(line);
            final int lineBottom = getLineBottom(line);

            final int startIndex = Math.max(start, lineStart);
            final int endIndex = Math.min(end, lineEnd);
            for (int index = startIndex; index < endIndex; ++index) {
                final int offset = index - lineStart;
                final float left = horizontalBounds[offset * 2] + lineStartPos;
                final float right = horizontalBounds[offset * 2 + 1] + lineStartPos;

                listener.onCharacterBounds(index, line, left, lineTop, right, lineBottom);
            }
        }
        listener.onEnd();
    }

    /**
     * Get the leftmost position that should be exposed for horizontal
     * scrolling on the specified line.
     */
    public float getLineLeft(int line) {
        final int dir = getParagraphDirection(line);
        Alignment align = getParagraphAlignment(line);
        // Before Q, StaticLayout.Builder.setAlignment didn't check whether the input alignment
        // is null. And when it is null, the old behavior is the same as ALIGN_CENTER.
        // To keep consistency, we convert a null alignment to ALIGN_CENTER.
        if (align == null) {
            align = Alignment.ALIGN_CENTER;
        }

        // First convert combinations of alignment and direction settings to
        // three basic cases: ALIGN_LEFT, ALIGN_RIGHT and ALIGN_CENTER.
        // For unexpected cases, it will fallback to ALIGN_LEFT.
        final Alignment resultAlign;
        switch(align) {
            case ALIGN_NORMAL:
                resultAlign =
                        dir == DIR_RIGHT_TO_LEFT ? Alignment.ALIGN_RIGHT : Alignment.ALIGN_LEFT;
                break;
            case ALIGN_OPPOSITE:
                resultAlign =
                        dir == DIR_RIGHT_TO_LEFT ? Alignment.ALIGN_LEFT : Alignment.ALIGN_RIGHT;
                break;
            case ALIGN_CENTER:
                resultAlign = Alignment.ALIGN_CENTER;
                break;
            case ALIGN_RIGHT:
                resultAlign = Alignment.ALIGN_RIGHT;
                break;
            default: /* align == Alignment.ALIGN_LEFT */
                resultAlign = Alignment.ALIGN_LEFT;
        }

        // Here we must use getLineMax() to do the computation, because it maybe overridden by
        // derived class. And also note that line max equals the width of the text in that line
        // plus the leading margin.
        switch (resultAlign) {
            case ALIGN_CENTER:
                final int left = getParagraphLeft(line);
                final float max = getLineMax(line);
                // This computation only works when mWidth equals leadingMargin plus
                // the width of text in this line. If this condition doesn't meet anymore,
                // please change here too.
                return (float) Math.floor(left + (mWidth - max) / 2);
            case ALIGN_RIGHT:
                return mWidth - getLineMax(line);
            default: /* resultAlign == Alignment.ALIGN_LEFT */
                return 0;
        }
    }

    /**
     * Get the rightmost position that should be exposed for horizontal
     * scrolling on the specified line.
     */
    public float getLineRight(int line) {
        final int dir = getParagraphDirection(line);
        Alignment align = getParagraphAlignment(line);
        // Before Q, StaticLayout.Builder.setAlignment didn't check whether the input alignment
        // is null. And when it is null, the old behavior is the same as ALIGN_CENTER.
        // To keep consistency, we convert a null alignment to ALIGN_CENTER.
        if (align == null) {
            align = Alignment.ALIGN_CENTER;
        }

        final Alignment resultAlign;
        switch(align) {
            case ALIGN_NORMAL:
                resultAlign =
                        dir == DIR_RIGHT_TO_LEFT ? Alignment.ALIGN_RIGHT : Alignment.ALIGN_LEFT;
                break;
            case ALIGN_OPPOSITE:
                resultAlign =
                        dir == DIR_RIGHT_TO_LEFT ? Alignment.ALIGN_LEFT : Alignment.ALIGN_RIGHT;
                break;
            case ALIGN_CENTER:
                resultAlign = Alignment.ALIGN_CENTER;
                break;
            case ALIGN_RIGHT:
                resultAlign = Alignment.ALIGN_RIGHT;
                break;
            default: /* align == Alignment.ALIGN_LEFT */
                resultAlign = Alignment.ALIGN_LEFT;
        }

        switch (resultAlign) {
            case ALIGN_CENTER:
                final int right = getParagraphRight(line);
                final float max = getLineMax(line);
                // This computation only works when mWidth equals leadingMargin plus width of the
                // text in this line. If this condition doesn't meet anymore, please change here.
                return (float) Math.ceil(right - (mWidth - max) / 2);
            case ALIGN_RIGHT:
                return mWidth;
            default: /* resultAlign == Alignment.ALIGN_LEFT */
                return getLineMax(line);
        }
    }

    /**
     * Gets the unsigned horizontal extent of the specified line, including
     * leading margin indent, but excluding trailing whitespace.
     */
    public float getLineMax(int line) {
        float margin = getParagraphLeadingMargin(line);
        float signedExtent = getLineExtent(line, false);
        return margin + (signedExtent >= 0 ? signedExtent : -signedExtent);
    }

    /**
     * Gets the unsigned horizontal extent of the specified line, including
     * leading margin indent and trailing whitespace.
     */
    public float getLineWidth(int line) {
        float margin = getParagraphLeadingMargin(line);
        float signedExtent = getLineExtent(line, true);
        return margin + (signedExtent >= 0 ? signedExtent : -signedExtent);
    }

    /**
     * Like {@link #getLineExtent(int,TabStops,boolean)} but determines the
     * tab stops instead of using the ones passed in.
     * @param line the index of the line
     * @param full whether to include trailing whitespace
     * @return the extent of the line
     */
    private float getLineExtent(int line, boolean full) {
        final int start = getLineStart(line);
        final int end = full ? getLineEnd(line) : getLineVisibleEnd(line);

        final boolean hasTabs = getLineContainsTab(line);
        TabStops tabStops = null;
        if (hasTabs && mText instanceof Spanned) {
            // Just checking this line should be good enough, tabs should be
            // consistent across all lines in a paragraph.
            TabStopSpan[] tabs = getParagraphSpans((Spanned) mText, start, end, TabStopSpan.class);
            if (tabs.length > 0) {
                tabStops = new TabStops(TAB_INCREMENT, tabs); // XXX should reuse
            }
        }
        final Directions directions = getLineDirections(line);
        // Returned directions can actually be null
        if (directions == null) {
            return 0f;
        }
        final int dir = getParagraphDirection(line);

        final TextLine tl = TextLine.obtain();
        final TextPaint paint = mWorkPaint;
        paint.set(mPaint);
        paint.setStartHyphenEdit(getStartHyphenEdit(line));
        paint.setEndHyphenEdit(getEndHyphenEdit(line));
        tl.set(paint, mText, start, end, dir, directions, hasTabs, tabStops,
                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line),
                isFallbackLineSpacingEnabled());
        if (isJustificationRequired(line)) {
            tl.justify(mJustificationMode, getJustifyWidth(line));
        }
        final float width = tl.metrics(null, null, mUseBoundsForWidth, null);
        TextLine.recycle(tl);
        return width;
    }

    /**
     * Returns the number of letter spacing unit in the line.
     *
     * <p>
     * This API returns a number of letters that is a target of letter spacing. The letter spacing
     * won't be added to the middle of the characters that are needed to be treated as a single,
     * e.g., ligatured or conjunct form. Note that this value is different from the number of]
     * grapheme clusters that is calculated by {@link BreakIterator#getCharacterInstance(Locale)}.
     * For example, if the "fi" is ligatured, the ligatured form is treated as single uni and letter
     * spacing is not added, but it has two separate grapheme cluster.
     *
     * <p>
     * This value is used for calculating the letter spacing amount for the justification because
     * the letter spacing is applied between clusters. For example, if extra {@code W} pixels needed
     * to be filled by letter spacing, the amount of letter spacing to be applied is
     * {@code W}/(letter spacing unit count - 1) px.
     *
     * @param line the index of the line
     * @param includeTrailingWhitespace whether to include trailing whitespace
     * @return the number of cluster count in the line.
     */
    @IntRange(from = 0)
    @FlaggedApi(FLAG_LETTER_SPACING_JUSTIFICATION)
    public int getLineLetterSpacingUnitCount(@IntRange(from = 0) int line,
            boolean includeTrailingWhitespace) {
        final int start = getLineStart(line);
        final int end = includeTrailingWhitespace ? getLineEnd(line)
                : getLineVisibleEnd(line, getLineStart(line), getLineStart(line + 1),
                        false  // trailingSpaceAtLastLineIsVisible: Treating trailing whitespaces at
                               // the last line as a invisible chars for single line justification.
                );

        final Directions directions = getLineDirections(line);
        // Returned directions can actually be null
        if (directions == null) {
            return 0;
        }
        final int dir = getParagraphDirection(line);

        final TextLine tl = TextLine.obtain();
        final TextPaint paint = mWorkPaint;
        paint.set(mPaint);
        paint.setStartHyphenEdit(getStartHyphenEdit(line));
        paint.setEndHyphenEdit(getEndHyphenEdit(line));
        tl.set(paint, mText, start, end, dir, directions,
                false, null, // tab width is not used for cluster counting.
                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line),
                isFallbackLineSpacingEnabled());
        if (mLineInfo == null) {
            mLineInfo = new TextLine.LineInfo();
        }
        mLineInfo.setClusterCount(0);
        tl.metrics(null, null, mUseBoundsForWidth, mLineInfo);
        TextLine.recycle(tl);
        return mLineInfo.getClusterCount();
    }

    /**
     * Returns the signed horizontal extent of the specified line, excluding
     * leading margin.  If full is false, excludes trailing whitespace.
     * @param line the index of the line
     * @param tabStops the tab stops, can be null if we know they're not used.
     * @param full whether to include trailing whitespace
     * @return the extent of the text on this line
     */
    private float getLineExtent(int line, TabStops tabStops, boolean full) {
        final int start = getLineStart(line);
        final int end = full ? getLineEnd(line) : getLineVisibleEnd(line);
        final boolean hasTabs = getLineContainsTab(line);
        final Directions directions = getLineDirections(line);
        final int dir = getParagraphDirection(line);

        final TextLine tl = TextLine.obtain();
        final TextPaint paint = mWorkPaint;
        paint.set(mPaint);
        paint.setStartHyphenEdit(getStartHyphenEdit(line));
        paint.setEndHyphenEdit(getEndHyphenEdit(line));
        tl.set(paint, mText, start, end, dir, directions, hasTabs, tabStops,
                getEllipsisStart(line), getEllipsisStart(line) + getEllipsisCount(line),
                isFallbackLineSpacingEnabled());
        if (isJustificationRequired(line)) {
            tl.justify(mJustificationMode, getJustifyWidth(line));
        }
        final float width = tl.metrics(null, null, mUseBoundsForWidth, null);
        TextLine.recycle(tl);
        return width;
    }

    /**
     * Get the line number corresponding to the specified vertical position.
     * If you ask for a position above 0, you get 0; if you ask for a position
     * below the bottom of the text, you get the last line.
     */
    // FIXME: It may be faster to do a linear search for layouts without many lines.
    public int getLineForVertical(int vertical) {
        int high = getLineCount(), low = -1, guess;

        while (high - low > 1) {
            guess = (high + low) / 2;

            if (getLineTop(guess) > vertical)
                high = guess;
            else
                low = guess;
        }

        if (low < 0)
            return 0;
        else
            return low;
    }

    /**
     * Get the line number on which the specified text offset appears.
     * If you ask for a position before 0, you get 0; if you ask for a position
     * beyond the end of the text, you get the last line.
     */
    public int getLineForOffset(int offset) {
        int high = getLineCount(), low = -1, guess;

        while (high - low > 1) {
            guess = (high + low) / 2;

            if (getLineStart(guess) > offset)
                high = guess;
            else
                low = guess;
        }

        if (low < 0) {
            return 0;
        } else {
            return low;
        }
    }

    /**
     * Get the character offset on the specified line whose position is
     * closest to the specified horizontal position.
     */
    public int getOffsetForHorizontal(int line, float horiz) {
        return getOffsetForHorizontal(line, horiz, true);
    }

    /**
     * Get the character offset on the specified line whose position is
     * closest to the specified horizontal position.
     *
     * @param line the line used to find the closest offset
     * @param horiz the horizontal position used to find the closest offset
     * @param primary whether to use the primary position or secondary position to find the offset
     *
     * @hide
     */
    public int getOffsetForHorizontal(int line, float horiz, boolean primary) {
        // TODO: use Paint.getOffsetForAdvance to avoid binary search
        final int lineEndOffset = getLineEnd(line);
        final int lineStartOffset = getLineStart(line);

        Directions dirs = getLineDirections(line);

        TextLine tl = TextLine.obtain();
        // 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),
                isFallbackLineSpacingEnabled());
        final HorizontalMeasurementProvider horizontal =
                new HorizontalMeasurementProvider(line, primary);

        final int max;
        if (line == getLineCount() - 1) {
            max = lineEndOffset;
        } else {
            max = tl.getOffsetToLeftRightOf(lineEndOffset - lineStartOffset,
                    !isRtlCharAt(lineEndOffset - 1)) + lineStartOffset;
        }
        int best = lineStartOffset;
        float bestdist = Math.abs(horizontal.get(lineStartOffset) - horiz);

        for (int i = 0; i < dirs.mDirections.length; i += 2) {
            int here = lineStartOffset + dirs.mDirections[i];
            int there = here + (dirs.mDirections[i+1] & RUN_LENGTH_MASK);
            boolean isRtl = (dirs.mDirections[i+1] & RUN_RTL_FLAG) != 0;
            int swap = isRtl ? -1 : 1;

            if (there > max)
                there = max;
            int high = there - 1 + 1, low = here + 1 - 1, guess;

            while (high - low > 1) {
                guess = (high + low) / 2;
                int adguess = getOffsetAtStartOf(guess);

                if (horizontal.get(adguess) * swap >= horiz * swap) {
                    high = guess;
                } else {
                    low = guess;
                }
            }

            if (low < here + 1)
                low = here + 1;

            if (low < there) {
                int aft = tl.getOffsetToLeftRightOf(low - lineStartOffset, isRtl) + lineStartOffset;
                low = tl.getOffsetToLeftRightOf(aft - lineStartOffset, !isRtl) + lineStartOffset;
                if (low >= here && low < there) {
                    float dist = Math.abs(horizontal.get(low) - horiz);
                    if (aft < there) {
                        float other = Math.abs(horizontal.get(aft) - horiz);

                        if (other < dist) {
                            dist = other;
                            low = aft;
                        }
                    }

                    if (dist < bestdist) {
                        bestdist = dist;
                        best = low;
                    }
                }
            }

            float dist = Math.abs(horizontal.get(here) - horiz);

            if (dist < bestdist) {
                bestdist = dist;
                best = here;
            }
        }

        float dist = Math.abs(horizontal.get(max) - horiz);

        if (dist <= bestdist) {
            best = max;
        }

        TextLine.recycle(tl);
        return best;
    }

    /**
     * Responds to #getHorizontal queries, by selecting the better strategy between:
     * - calling #getHorizontal explicitly for each query
     * - precomputing all #getHorizontal measurements, and responding to any query in constant time
     * The first strategy is used for LTR-only text, while the second is used for all other cases.
     * The class is currently only used in #getOffsetForHorizontal, so reuse with care in other
     * contexts.
     */
    private class HorizontalMeasurementProvider {
        private final int mLine;
        private final boolean mPrimary;

        private float[] mHorizontals;
        private int mLineStartOffset;

        HorizontalMeasurementProvider(final int line, final boolean primary) {
            mLine = line;
            mPrimary = primary;
            init();
        }

        private void init() {
            final Directions dirs = getLineDirections(mLine);
            if (dirs == DIRS_ALL_LEFT_TO_RIGHT) {
                return;
            }

            mHorizontals = getLineHorizontals(mLine, false, mPrimary);
            mLineStartOffset = getLineStart(mLine);
        }

        float get(final int offset) {
            final int index = offset - mLineStartOffset;
            if (mHorizontals == null || index < 0 || index >= mHorizontals.length) {
                return getHorizontal(offset, mPrimary);
            } else {
                return mHorizontals[index];
            }
        }
    }

    /**
     * Finds the range of text which is inside the specified rectangle area. The start of the range
     * is the start of the first text segment inside the area, and the end of the range is the end
     * of the last text segment inside the area.
     *
     * <p>A text segment is considered to be inside the area according to the provided {@link
     * TextInclusionStrategy}. If a text segment spans multiple lines or multiple directional runs
     * (e.g. a hyphenated word), the text segment is divided into pieces at the line and run breaks,
     * then the text segment is considered to be inside the area if any of its pieces are inside the
     * area.
     *
     * <p>The returned range may also include text segments which are not inside the specified area,
     * if those text segments are in between text segments which are inside the area. For example,
     * the returned range may be "segment1 segment2 segment3" if "segment1" and "segment3" are
     * inside the area and "segment2" is not.
     *
     * @param area area for which the text range will be found
     * @param segmentFinder SegmentFinder for determining the ranges of text to be considered as a
     *     text segment
     * @param inclusionStrategy strategy for determining whether a text segment is inside the
     *     specified area
     * @return int array of size 2 containing the start (inclusive) and end (exclusive) character
     *     offsets of the text range, or null if there are no text segments inside the area
     */
    @Nullable
    public int[] getRangeForRect(@NonNull RectF area, @NonNull SegmentFinder segmentFinder,
            @NonNull TextInclusionStrategy inclusionStrategy) {
        // Find the first line whose bottom (without line spacing) is below the top of the area.
        int startLine = getLineForVertical((int) area.top);
        if (area.top > getLineBottom(startLine, /* includeLineSpacing= */ false)) {
            startLine++;
            if (startLine >= getLineCount()) {
                // The entire area is below the last line, so it does not contain any text.
                return null;
            }
        }

        // Find the last line whose top is above the bottom of the area.
        int endLine = getLineForVertical((int) area.bottom);
        if (endLine == 0 && area.bottom < getLineTop(0)) {
            // The entire area is above the first line, so it does not contain any text.
            return null;
        }
        if (endLine < startLine) {
            // The entire area is between two lines, so it does not contain any text.
            return null;
        }

        int start = getStartOrEndOffsetForAreaWithinLine(
                startLine, area, segmentFinder, inclusionStrategy, /* getStart= */ true);
        // If the area does not contain any text on this line, keep trying subsequent lines until
        // the end line is reached.
        while (start == -1 && startLine < endLine) {
            startLine++;
            start = getStartOrEndOffsetForAreaWithinLine(
                    startLine, area, segmentFinder, inclusionStrategy, /* getStart= */ true);
        }
        if (start == -1) {
            // All lines were checked, the area does not contain any text.
            return null;
        }

        int end = getStartOrEndOffsetForAreaWithinLine(
                endLine, area, segmentFinder, inclusionStrategy, /* getStart= */ false);
        // If the area does not contain any text on this line, keep trying previous lines until
        // the start line is reached.
        while (end == -1 && startLine < endLine) {
            endLine--;
            end = getStartOrEndOffsetForAreaWithinLine(
                    endLine, area, segmentFinder, inclusionStrategy, /* getStart= */ false);
        }
        if (end == -1) {
            // All lines were checked, the area does not contain any text.
            return null;
        }

        // If a text segment spans multiple lines or multiple directional runs (e.g. a hyphenated
        // word), then getStartOrEndOffsetForAreaWithinLine() can return an offset in the middle of
        // a text segment. Adjust the range to include the rest of any partial text segments. If
        // start is already the start boundary of a text segment, then this is a no-op.
        start = segmentFinder.previousStartBoundary(start + 1);
        end = segmentFinder.nextEndBoundary(end - 1);

        return new int[] {start, end};
    }

    /**
     * Finds the start character offset of the first text segment within a line inside the specified
     * rectangle area, or the end character offset of the last text segment inside the area.
     *
     * @param line index of the line to search
     * @param area area inside which text segments will be found
     * @param segmentFinder SegmentFinder for determining the ranges of text to be considered as a
     *     text segment
     * @param inclusionStrategy strategy for determining whether a text segment is inside the
     *     specified area
     * @param getStart true to find the start of the first text segment inside the area, false to
     *     find the end of the last text segment
     * @return the start character offset of the first text segment inside the area, or the end
     *     character offset of the last text segment inside the area.
     */
    private int getStartOrEndOffsetForAreaWithinLine(
            @IntRange(from = 0) int line,
            @NonNull RectF area,
            @NonNull SegmentFinder segmentFinder,
            @NonNull TextInclusionStrategy inclusionStrategy,
            boolean getStart) {
        int lineTop = getLineTop(line);
        int lineBottom = getLineBottom(line, /* includeLineSpacing= */ false);

        int lineStartOffset = getLineStart(line);
        int lineEndOffset = getLineEnd(line);
        if (lineStartOffset == lineEndOffset) {
            return -1;
        }

        float[] horizontalBounds = new float[2 * (lineEndOffset - lineStartOffset)];
        fillHorizontalBoundsForLine(line, horizontalBounds);

        int lineStartPos = getLineStartPos(line, getParagraphLeft(line), getParagraphRight(line));

        // Loop through the runs forwards or backwards depending on getStart value.
        Layout.Directions directions = getLineDirections(line);
        int runIndex = getStart ? 0 : directions.getRunCount() - 1;
        while ((getStart && runIndex < directions.getRunCount()) || (!getStart && runIndex >= 0)) {
            // runStartOffset and runEndOffset are offset indices within the line.
            int runStartOffset = directions.getRunStart(runIndex);
            int runEndOffset = Math.min(
                    runStartOffset + directions.getRunLength(runIndex),
                    lineEndOffset - lineStartOffset);
            boolean isRtl = directions.isRunRtl(runIndex);
            float runLeft = lineStartPos
                    + (isRtl
                            ? horizontalBounds[2 * (runEndOffset - 1)]
                            : horizontalBounds[2 * runStartOffset]);
            float runRight = lineStartPos
                    + (isRtl
                            ? horizontalBounds[2 * runStartOffset + 1]
                            : horizontalBounds[2 * (runEndOffset - 1) + 1]);

            int result =
                    getStart
                            ? getStartOffsetForAreaWithinRun(
                                    area, lineTop, lineBottom,
                                    lineStartOffset, lineStartPos, horizontalBounds,
                                    runStartOffset, runEndOffset, runLeft, runRight, isRtl,
                                    segmentFinder, inclusionStrategy)
                            : getEndOffsetForAreaWithinRun(
                                    area, lineTop, lineBottom,
                                    lineStartOffset, lineStartPos, horizontalBounds,
                                    runStartOffset, runEndOffset, runLeft, runRight, isRtl,
                                    segmentFinder, inclusionStrategy);
            if (result >= 0) {
                return result;
            }

            runIndex += getStart ? 1 : -1;
        }
        return -1;
    }

    /**
     * Finds the start character offset of the first text segment within a directional run inside
     * the specified rectangle area.
     *
     * @param area area inside which text segments will be found
     * @param lineTop top of the line containing this run
     * @param lineBottom bottom (not including line spacing) of the line containing this run
     * @param lineStartOffset start character offset of the line containing this run
     * @param lineStartPos start position of the line containing this run
     * @param horizontalBounds array containing the signed horizontal bounds of the characters in
     *     the line. The left and right bounds of the character at offset i are stored at index (2 *
     *     i) and index (2 * i + 1). Bounds are relative to {@code lineStartPos}.
     * @param runStartOffset start offset of the run relative to {@code lineStartOffset}
     * @param runEndOffset end offset of the run relative to {@code lineStartOffset}
     * @param runLeft left bound of the run
     * @param runRight right bound of the run
     * @param isRtl whether the run is right-to-left
     * @param segmentFinder SegmentFinder for determining the ranges of text to be considered as a
     *     text segment
     * @param inclusionStrategy strategy for determining whether a text segment is inside the
     *     specified area
     * @return the start character offset of the first text segment inside the area
     */
    private static int getStartOffsetForAreaWithinRun(
            @NonNull RectF area,
            int lineTop, int lineBottom,
            @IntRange(from = 0) int lineStartOffset,
            @IntRange(from = 0) int lineStartPos,
            @NonNull float[] horizontalBounds,
            @IntRange(from = 0) int runStartOffset, @IntRange(from = 0) int runEndOffset,
            float runLeft, float runRight,
            boolean isRtl,
            @NonNull SegmentFinder segmentFinder,
            @NonNull TextInclusionStrategy inclusionStrategy) {
        if (runRight < area.left || runLeft > area.right) {
            // The run does not overlap the area.
            return -1;
        }

        // Find the first character in the run whose bounds overlap with the area.
        // firstCharOffset is an offset index within the line.
        int firstCharOffset;
        if ((!isRtl && area.left <= runLeft) || (isRtl && area.right >= runRight)) {
            firstCharOffset = runStartOffset;
        } else {
            int low = runStartOffset;
            int high = runEndOffset;
            int guess;
            while (high - low > 1) {
                guess = (high + low) / 2;
                // Left edge of the character at guess
                float pos = lineStartPos + horizontalBounds[2 * guess];
                if ((!isRtl && pos > area.left) || (isRtl && pos < area.right)) {
                    high = guess;
                } else {
                    low = guess;
                }
            }
            // The area edge is between the left edge of the character at low and the left edge of
            // the character at high. For LTR text, this is within the character at low. For RTL
            // text, this is within the character at high.
            firstCharOffset = isRtl ? high : low;
        }

        // Find the first text segment containing this character (or, if no text segment contains
        // this character, the first text segment after this character). All previous text segments
        // in this run are to the left (for LTR) of the area.
        int segmentEndOffset =
                segmentFinder.nextEndBoundary(lineStartOffset + firstCharOffset);
        if (segmentEndOffset == SegmentFinder.DONE) {
            // There are no text segments containing or after firstCharOffset, so no text segments
            // in this run overlap the area.
            return -1;
        }
        int segmentStartOffset = segmentFinder.previousStartBoundary(segmentEndOffset);
        if (segmentStartOffset >= lineStartOffset + runEndOffset) {
            // The text segment is after the end of this run, so no text segments in this run
            // overlap the area.
            return -1;
        }
        // If the segment extends outside of this run, only consider the piece of the segment within
        // this run.
        segmentStartOffset = Math.max(segmentStartOffset, lineStartOffset + runStartOffset);
        segmentEndOffset = Math.min(segmentEndOffset, lineStartOffset + runEndOffset);

        RectF segmentBounds = new RectF(0, lineTop, 0, lineBottom);
        while (true) {
            // Start (left for LTR, right for RTL) edge of the character at segmentStartOffset.
            float segmentStart = lineStartPos + horizontalBounds[
                    2 * (segmentStartOffset - lineStartOffset) + (isRtl ? 1 : 0)];
            if ((!isRtl && segmentStart > area.right) || (isRtl && segmentStart < area.left)) {
                // The entire area is to the left (for LTR) of the text segment. So the area does
                // not contain any text segments within this run.
                return -1;
            }
            // End (right for LTR, left for RTL) edge of the character at (segmentStartOffset - 1).
            float segmentEnd = lineStartPos + horizontalBounds[
                    2 * (segmentEndOffset - lineStartOffset - 1) + (isRtl ? 0 : 1)];
            segmentBounds.left = isRtl ? segmentEnd : segmentStart;
            segmentBounds.right = isRtl ? segmentStart : segmentEnd;
            if (inclusionStrategy.isSegmentInside(segmentBounds, area)) {
                return segmentStartOffset;
            }
            // Try the next text segment.
            segmentStartOffset = segmentFinder.nextStartBoundary(segmentStartOffset);
            if (segmentStartOffset == SegmentFinder.DONE
                    || segmentStartOffset >= lineStartOffset + runEndOffset) {
                // No more text segments within this run.
                return -1;
            }
            segmentEndOffset = segmentFinder.nextEndBoundary(segmentStartOffset);
            // If the segment extends past the end of this run, only consider the piece of the
            // segment within this run.
            segmentEndOffset = Math.min(segmentEndOffset, lineStartOffset + runEndOffset);
        }
    }

    /**
     * Finds the end character offset of the last text segment within a directional run inside the
     * specified rectangle area.
     *
     * @param area area inside which text segments will be found
     * @param lineTop top of the line containing this run
     * @param lineBottom bottom (not including line spacing) of the line containing this run
     * @param lineStartOffset start character offset of the line containing this run
     * @param lineStartPos start position of the line containing this run
     * @param horizontalBounds array containing the signed horizontal bounds of the characters in
     *     the line. The left and right bounds of the character at offset i are stored at index (2 *
     *     i) and index (2 * i + 1). Bounds are relative to {@code lineStartPos}.
     * @param runStartOffset start offset of the run relative to {@code lineStartOffset}
     * @param runEndOffset end offset of the run relative to {@code lineStartOffset}
     * @param runLeft left bound of the run
     * @param runRight right bound of the run
     * @param isRtl whether the run is right-to-left
     * @param segmentFinder SegmentFinder for determining the ranges of text to be considered as a
     *     text segment
     * @param inclusionStrategy strategy for determining whether a text segment is inside the
     *     specified area
     * @return the end character offset of the last text segment inside the area
     */
    private static int getEndOffsetForAreaWithinRun(
            @NonNull RectF area,
            int lineTop, int lineBottom,
            @IntRange(from = 0) int lineStartOffset,
            @IntRange(from = 0) int lineStartPos,
            @NonNull float[] horizontalBounds,
            @IntRange(from = 0) int runStartOffset, @IntRange(from = 0) int runEndOffset,
            float runLeft, float runRight,
            boolean isRtl,
            @NonNull SegmentFinder segmentFinder,
            @NonNull TextInclusionStrategy inclusionStrategy) {
        if (runRight < area.left || runLeft > area.right) {
            // The run does not overlap the area.
            return -1;
        }

        // Find the last character in the run whose bounds overlap with the area.
        // firstCharOffset is an offset index within the line.
        int lastCharOffset;
        if ((!isRtl && area.right >= runRight) || (isRtl && area.left <= runLeft)) {
            lastCharOffset = runEndOffset - 1;
        } else {
            int low = runStartOffset;
            int high = runEndOffset;
            int guess;
            while (high - low > 1) {
                guess = (high + low) / 2;
                // Left edge of the character at guess
                float pos = lineStartPos + horizontalBounds[2 * guess];
                if ((!isRtl && pos > area.right) || (isRtl && pos < area.left)) {
                    high = guess;
                } else {
                    low = guess;
                }
            }
            // The area edge is between the left edge of the character at low and the left edge of
            // the character at high. For LTR text, this is within the character at low. For RTL
            // text, this is within the character at high.
            lastCharOffset = isRtl ? high : low;
        }

        // Find the last text segment containing this character (or, if no text segment contains
        // this character, the first text segment before this character). All following text
        // segments in this run are to the right (for LTR) of the area.
        // + 1 to allow segmentStartOffset = lineStartOffset + lastCharOffset
        int segmentStartOffset =
                segmentFinder.previousStartBoundary(lineStartOffset + lastCharOffset + 1);
        if (segmentStartOffset == SegmentFinder.DONE) {
            // There are no text segments containing or before lastCharOffset, so no text segments
            // in this run overlap the area.
            return -1;
        }
        int segmentEndOffset = segmentFinder.nextEndBoundary(segmentStartOffset);
        if (segmentEndOffset <= lineStartOffset + runStartOffset) {
            // The text segment is before the start of this run, so no text segments in this run
            // overlap the area.
            return -1;
        }
        // If the segment extends outside of this run, only consider the piece of the segment within
        // this run.
        segmentStartOffset = Math.max(segmentStartOffset, lineStartOffset + runStartOffset);
        segmentEndOffset = Math.min(segmentEndOffset, lineStartOffset + runEndOffset);

        RectF segmentBounds = new RectF(0, lineTop, 0, lineBottom);
        while (true) {
            // End (right for LTR, left for RTL) edge of the character at (segmentStartOffset - 1).
            float segmentEnd = lineStartPos + horizontalBounds[
                    2 * (segmentEndOffset - lineStartOffset - 1) + (isRtl ? 0 : 1)];
            if ((!isRtl && segmentEnd < area.left) || (isRtl && segmentEnd > area.right)) {
                // The entire area is to the right (for LTR) of the text segment. So the
                // area does not contain any text segments within this run.
                return -1;
            }
            // Start (left for LTR, right for RTL) edge of the character at segmentStartOffset.
            float segmentStart = lineStartPos + horizontalBounds[
                    2 * (segmentStartOffset - lineStartOffset) + (isRtl ? 1 : 0)];
            segmentBounds.left = isRtl ? segmentEnd : segmentStart;
            segmentBounds.right = isRtl ? segmentStart : segmentEnd;
            if (inclusionStrategy.isSegmentInside(segmentBounds, area)) {
                return segmentEndOffset;
            }
            // Try the previous text segment.
            segmentEndOffset = segmentFinder.previousEndBoundary(segmentEndOffset);
            if (segmentEndOffset == SegmentFinder.DONE
                    || segmentEndOffset <= lineStartOffset + runStartOffset) {
                // No more text segments within this run.
                return -1;
            }
            segmentStartOffset = segmentFinder.previousStartBoundary(segmentEndOffset);
            // If the segment extends past the start of this run, only consider the piece of the
            // segment within this run.
            segmentStartOffset = Math.max(segmentStartOffset, lineStartOffset + runStartOffset);
        }
    }

    /**
     * Return the text offset after the last character on the specified line.
     */
    public final int getLineEnd(int line) {
        return getLineStart(line + 1);
    }

    /**
     * Return the text offset after the last visible character (so whitespace
     * is not counted) on the specified line.
     */
    public int getLineVisibleEnd(int line) {
        return getLineVisibleEnd(line, getLineStart(line), getLineStart(line + 1),
                true /* trailingSpaceAtLastLineIsVisible */);
    }

    private int getLineVisibleEnd(int line, int start, int end,
            boolean trailingSpaceAtLastLineIsVisible) {
        CharSequence text = mText;
        char ch;

        // Historically, trailing spaces at the last line is counted as visible. However, this
        // doesn't work well for justification.
        if (trailingSpaceAtLastLineIsVisible) {
            if (line == getLineCount() - 1) {
                return end;
            }
        }

        for (; end > start; end--) {
            ch = text.charAt(end - 1);

            if (ch == '\n') {
                return end - 1;
            }

            if (!TextLine.isLineEndSpace(ch)) {
                break;
            }

        }

        return end;
    }

    /**
     * Return the vertical position of the bottom of the specified line.
     */
    public final int getLineBottom(int line) {
        return getLineBottom(line, /* includeLineSpacing= */ true);
    }

    /**
     * Return the vertical position of the bottom of the specified line.
     *
     * @param line index of the line
     * @param includeLineSpacing whether to include the line spacing
     */
    public int getLineBottom(int line, boolean includeLineSpacing) {
        if (includeLineSpacing) {
            return getLineTop(line + 1);
        } else {
            return getLineTop(line + 1) - getLineExtra(line);
        }
    }

    /**
     * Return the vertical position of the baseline of the specified line.
     */
    public final int getLineBaseline(int line) {
        // getLineTop(line+1) == getLineBottom(line)
        return getLineTop(line+1) - getLineDescent(line);
    }

    /**
     * Get the ascent of the text on the specified line.
     * The return value is negative to match the Paint.ascent() convention.
     */
    public final int getLineAscent(int line) {
        // getLineTop(line+1) - getLineDescent(line) == getLineBaseLine(line)
        return getLineTop(line) - (getLineTop(line+1) - getLineDescent(line));
    }

    /**
     * Return the extra space added as a result of line spacing attributes
     * {@link #getSpacingAdd()} and {@link #getSpacingMultiplier()}. Default value is {@code zero}.
     *
     * @param line the index of the line, the value should be equal or greater than {@code zero}
     * @hide
     */
    public int getLineExtra(@IntRange(from = 0) int line) {
        return 0;
    }

    public int getOffsetToLeftOf(int offset) {
        return getOffsetToLeftRightOf(offset, true);
    }

    public int getOffsetToRightOf(int offset) {
        return getOffsetToLeftRightOf(offset, false);
    }

    private int getOffsetToLeftRightOf(int caret, boolean toLeft) {
        int line = getLineForOffset(caret);
        int lineStart = getLineStart(line);
        int lineEnd = getLineEnd(line);
        int lineDir = getParagraphDirection(line);

        boolean lineChanged = false;
        boolean advance = toLeft == (lineDir == DIR_RIGHT_TO_LEFT);
        // if walking off line, look at the line we're headed to
        if (advance) {
            if (caret == lineEnd) {
                if (line < getLineCount() - 1) {
                    lineChanged = true;
                    ++line;
                } else {
                    return caret; // at very end, don't move
                }
            }
        } else {
            if (caret == lineStart) {
                if (line > 0) {
                    lineChanged = true;
                    --line;
                } else {
                    return caret; // at very start, don't move
                }
            }
        }

        if (lineChanged) {
            lineStart = getLineStart(line);
            lineEnd = getLineEnd(line);
            int newDir = getParagraphDirection(line);
            if (newDir != lineDir) {
                // unusual case.  we want to walk onto the line, but it runs
                // in a different direction than this one, so we fake movement
                // in the opposite direction.
                toLeft = !toLeft;
                lineDir = newDir;
            }
        }

        Directions directions = getLineDirections(line);

        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),
                isFallbackLineSpacingEnabled());
        caret = lineStart + tl.getOffsetToLeftRightOf(caret - lineStart, toLeft);
        TextLine.recycle(tl);
        return caret;
    }

    private int getOffsetAtStartOf(int offset) {
        // XXX this probably should skip local reorderings and
        // zero-width characters, look at callers
        if (offset == 0)
            return 0;

        CharSequence text = mText;
        char c = text.charAt(offset);

        if (c >= '\uDC00' && c <= '\uDFFF') {
            char c1 = text.charAt(offset - 1);

            if (c1 >= '\uD800' && c1 <= '\uDBFF')
                offset -= 1;
        }

        if (mSpannedText) {
            ReplacementSpan[] spans = ((Spanned) text).getSpans(offset, offset,
                                                       ReplacementSpan.class);

            for (int i = 0; i < spans.length; i++) {
                int start = ((Spanned) text).getSpanStart(spans[i]);
                int end = ((Spanned) text).getSpanEnd(spans[i]);

                if (start < offset && end > offset)
                    offset = start;
            }
        }

        return offset;
    }

    /**
     * Determine whether we should clamp cursor position. Currently it's
     * only robust for left-aligned displays.
     * @hide
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public boolean shouldClampCursor(int line) {
        // Only clamp cursor position in left-aligned displays.
        switch (getParagraphAlignment(line)) {
            case ALIGN_LEFT:
                return true;
            case ALIGN_NORMAL:
                return getParagraphDirection(line) > 0;
            default:
                return false;
        }

    }

    /**
     * Fills in the specified Path with a representation of a cursor
     * at the specified offset.  This will often be a vertical line
     * but can be multiple discontinuous lines in text with multiple
     * directionalities.
     */
    public void getCursorPath(final int point, final Path dest, final CharSequence editingBuffer) {
        dest.reset();

        int line = getLineForOffset(point);
        int top = getLineTop(line);
        int bottom = getLineBottom(line, /* includeLineSpacing= */ false);

        boolean clamped = shouldClampCursor(line);
        float h1 = getPrimaryHorizontal(point, clamped) - 0.5f;

        int caps = TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SHIFT_ON) |
                   TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SELECTING);
        int fn = TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_ALT_ON);
        int dist = 0;

        if (caps != 0 || fn != 0) {
            dist = (bottom - top) >> 2;

            if (fn != 0)
                top += dist;
            if (caps != 0)
                bottom -= dist;
        }

        if (h1 < 0.5f)
            h1 = 0.5f;

        dest.moveTo(h1, top);
        dest.lineTo(h1, bottom);

        if (caps == 2) {
            dest.moveTo(h1, bottom);
            dest.lineTo(h1 - dist, bottom + dist);
            dest.lineTo(h1, bottom);
            dest.lineTo(h1 + dist, bottom + dist);
        } else if (caps == 1) {
            dest.moveTo(h1, bottom);
            dest.lineTo(h1 - dist, bottom + dist);

            dest.moveTo(h1 - dist, bottom + dist - 0.5f);
            dest.lineTo(h1 + dist, bottom + dist - 0.5f);

            dest.moveTo(h1 + dist, bottom + dist);
            dest.lineTo(h1, bottom);
        }

        if (fn == 2) {
            dest.moveTo(h1, top);
            dest.lineTo(h1 - dist, top - dist);
            dest.lineTo(h1, top);
            dest.lineTo(h1 + dist, top - dist);
        } else if (fn == 1) {
            dest.moveTo(h1, top);
            dest.lineTo(h1 - dist, top - dist);

            dest.moveTo(h1 - dist, top - dist + 0.5f);
            dest.lineTo(h1 + dist, top - dist + 0.5f);

            dest.moveTo(h1 + dist, top - dist);
            dest.lineTo(h1, top);
        }
    }

    private void addSelection(int line, int start, int end,
            int top, int bottom, SelectionRectangleConsumer consumer) {
        int linestart = getLineStart(line);
        int lineend = getLineEnd(line);
        Directions dirs = getLineDirections(line);

        if (lineend > linestart && mText.charAt(lineend - 1) == '\n') {
            lineend--;
        }

        for (int i = 0; i < dirs.mDirections.length; i += 2) {
            int here = linestart + dirs.mDirections[i];
            int there = here + (dirs.mDirections[i + 1] & RUN_LENGTH_MASK);

            if (there > lineend) {
                there = lineend;
            }

            if (start <= there && end >= here) {
                int st = Math.max(start, here);
                int en = Math.min(end, there);

                if (st != en) {
                    float h1 = getHorizontal(st, false, line, false /* not clamped */);
                    float h2 = getHorizontal(en, true, line, false /* not clamped */);

                    float left = Math.min(h1, h2);
                    float right = Math.max(h1, h2);

                    final @TextSelectionLayout int layout =
                            ((dirs.mDirections[i + 1] & RUN_RTL_FLAG) != 0)
                                    ? TEXT_SELECTION_LAYOUT_RIGHT_TO_LEFT
                                    : TEXT_SELECTION_LAYOUT_LEFT_TO_RIGHT;

                    consumer.accept(left, top, right, bottom, layout);
                }
            }
        }
    }

    /**
     * Fills in the specified Path with a representation of a highlight
     * between the specified offsets.  This will often be a rectangle
     * or a potentially discontinuous set of rectangles.  If the start
     * and end are the same, the returned path is empty.
     */
    public void getSelectionPath(int start, int end, Path dest) {
        dest.reset();
        getSelection(start, end, (left, top, right, bottom, textSelectionLayout) ->
                dest.addRect(left, top, right, bottom, Path.Direction.CW));
    }

    /**
     * Calculates the rectangles which should be highlighted to indicate a selection between start
     * and end and feeds them into the given {@link SelectionRectangleConsumer}.
     *
     * @param start    the starting index of the selection
     * @param end      the ending index of the selection
     * @param consumer the {@link SelectionRectangleConsumer} which will receive the generated
     *                 rectangles. It will be called every time a rectangle is generated.
     * @hide
     * @see #getSelectionPath(int, int, Path)
     */
    public final void getSelection(int start, int end, final SelectionRectangleConsumer consumer) {
        if (start == end) {
            return;
        }

        if (end < start) {
            int temp = end;
            end = start;
            start = temp;
        }

        final int startline = getLineForOffset(start);
        final int endline = getLineForOffset(end);

        int top = getLineTop(startline);
        int bottom = getLineBottom(endline, /* includeLineSpacing= */ false);

        if (startline == endline) {
            addSelection(startline, start, end, top, bottom, consumer);
        } else {
            final float width = mWidth;

            addSelection(startline, start, getLineEnd(startline),
                    top, getLineBottom(startline), consumer);

            if (getParagraphDirection(startline) == DIR_RIGHT_TO_LEFT) {
                consumer.accept(getLineLeft(startline), top, 0, getLineBottom(startline),
                        TEXT_SELECTION_LAYOUT_RIGHT_TO_LEFT);
            } else {
                consumer.accept(getLineRight(startline), top, width, getLineBottom(startline),
                        TEXT_SELECTION_LAYOUT_LEFT_TO_RIGHT);
            }

            for (int i = startline + 1; i < endline; i++) {
                top = getLineTop(i);
                bottom = getLineBottom(i);
                if (getParagraphDirection(i) == DIR_RIGHT_TO_LEFT) {
                    consumer.accept(0, top, width, bottom, TEXT_SELECTION_LAYOUT_RIGHT_TO_LEFT);
                } else {
                    consumer.accept(0, top, width, bottom, TEXT_SELECTION_LAYOUT_LEFT_TO_RIGHT);
                }
            }

            top = getLineTop(endline);
            bottom = getLineBottom(endline, /* includeLineSpacing= */ false);

            addSelection(endline, getLineStart(endline), end, top, bottom, consumer);

            if (getParagraphDirection(endline) == DIR_RIGHT_TO_LEFT) {
                consumer.accept(width, top, getLineRight(endline), bottom,
                        TEXT_SELECTION_LAYOUT_RIGHT_TO_LEFT);
            } else {
                consumer.accept(0, top, getLineLeft(endline), bottom,
                        TEXT_SELECTION_LAYOUT_LEFT_TO_RIGHT);
            }
        }
    }

    /**
     * Get the alignment of the specified paragraph, taking into account
     * markup attached to it.
     */
    public final Alignment getParagraphAlignment(int line) {
        Alignment align = mAlignment;

        if (mSpannedText) {
            Spanned sp = (Spanned) mText;
            AlignmentSpan[] spans = getParagraphSpans(sp, getLineStart(line),
                                                getLineEnd(line),
                                                AlignmentSpan.class);

            int spanLength = spans.length;
            if (spanLength > 0) {
                align = spans[spanLength-1].getAlignment();
            }
        }

        return align;
    }

    /**
     * Get the left edge of the specified paragraph, inset by left margins.
     */
    public final int getParagraphLeft(int line) {
        int left = 0;
        int dir = getParagraphDirection(line);
        if (dir == DIR_RIGHT_TO_LEFT || !mSpannedText) {
            return left; // leading margin has no impact, or no styles
        }
        return getParagraphLeadingMargin(line);
    }

    /**
     * Get the right edge of the specified paragraph, inset by right margins.
     */
    public final int getParagraphRight(int line) {
        int right = mWidth;
        int dir = getParagraphDirection(line);
        if (dir == DIR_LEFT_TO_RIGHT || !mSpannedText) {
            return right; // leading margin has no impact, or no styles
        }
        return right - getParagraphLeadingMargin(line);
    }

    /**
     * Returns the effective leading margin (unsigned) for this line,
     * taking into account LeadingMarginSpan and LeadingMarginSpan2.
     * @param line the line index
     * @return the leading margin of this line
     */
    private int getParagraphLeadingMargin(int line) {
        if (!mSpannedText) {
            return 0;
        }
        Spanned spanned = (Spanned) mText;

        int lineStart = getLineStart(line);
        int lineEnd = getLineEnd(line);
        int spanEnd = spanned.nextSpanTransition(lineStart, lineEnd,
                LeadingMarginSpan.class);
        LeadingMarginSpan[] spans = getParagraphSpans(spanned, lineStart, spanEnd,
                                                LeadingMarginSpan.class);
        if (spans.length == 0) {
            return 0; // no leading margin span;
        }

        int margin = 0;

        boolean useFirstLineMargin = lineStart == 0 || spanned.charAt(lineStart - 1) == '\n';
        for (int i = 0; i < spans.length; i++) {
            if (spans[i] instanceof LeadingMarginSpan2) {
                int spStart = spanned.getSpanStart(spans[i]);
                int spanLine = getLineForOffset(spStart);
                int count = ((LeadingMarginSpan2) spans[i]).getLeadingMarginLineCount();
                // if there is more than one LeadingMarginSpan2, use the count that is greatest
                useFirstLineMargin |= line < spanLine + count;
            }
        }
        for (int i = 0; i < spans.length; i++) {
            LeadingMarginSpan span = spans[i];
            margin += span.getLeadingMargin(useFirstLineMargin);
        }

        return margin;
    }

    private static float measurePara(TextPaint paint, CharSequence text, int start, int end,
            TextDirectionHeuristic textDir, boolean useBoundsForWidth) {
        MeasuredParagraph mt = null;
        TextLine tl = TextLine.obtain();
        try {
            mt = MeasuredParagraph.buildForBidi(text, start, end, textDir, mt);
            final char[] chars = mt.getChars();
            final int len = chars.length;
            final Directions directions = mt.getDirections(0, len);
            final int dir = mt.getParagraphDir();
            boolean hasTabs = false;
            TabStops tabStops = null;
            // leading margins should be taken into account when measuring a paragraph
            int margin = 0;
            if (text instanceof Spanned) {
                Spanned spanned = (Spanned) text;
                LeadingMarginSpan[] spans = getParagraphSpans(spanned, start, end,
                        LeadingMarginSpan.class);
                for (LeadingMarginSpan lms : spans) {
                    margin += lms.getLeadingMargin(true);
                }
            }
            for (int i = 0; i < len; ++i) {
                if (chars[i] == '\t') {
                    hasTabs = true;
                    if (text instanceof Spanned) {
                        Spanned spanned = (Spanned) text;
                        int spanEnd = spanned.nextSpanTransition(start, end,
                                TabStopSpan.class);
                        TabStopSpan[] spans = getParagraphSpans(spanned, start, spanEnd,
                                TabStopSpan.class);
                        if (spans.length > 0) {
                            tabStops = new TabStops(TAB_INCREMENT, spans);
                        }
                    }
                    break;
                }
            }
            tl.set(paint, text, start, end, dir, directions, hasTabs, tabStops,
                    0 /* ellipsisStart */, 0 /* ellipsisEnd */,
                    false /* use fallback line spacing. unused */);
            return margin + Math.abs(tl.metrics(null, null, useBoundsForWidth, null));
        } finally {
            TextLine.recycle(tl);
            if (mt != null) {
                mt.recycle();
            }
        }
    }

    /**
     * @hide
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public static class TabStops {
        private float[] mStops;
        private int mNumStops;
        private float mIncrement;

        public TabStops(float increment, Object[] spans) {
            reset(increment, spans);
        }

        void reset(float increment, Object[] spans) {
            this.mIncrement = increment;

            int ns = 0;
            if (spans != null) {
                float[] stops = this.mStops;
                for (Object o : spans) {
                    if (o instanceof TabStopSpan) {
                        if (stops == null) {
                            stops = new float[10];
                        } else if (ns == stops.length) {
                            float[] nstops = new float[ns * 2];
                            for (int i = 0; i < ns; ++i) {
                                nstops[i] = stops[i];
                            }
                            stops = nstops;
                        }
                        stops[ns++] = ((TabStopSpan) o).getTabStop();
                    }
                }
                if (ns > 1) {
                    Arrays.sort(stops, 0, ns);
                }
                if (stops != this.mStops) {
                    this.mStops = stops;
                }
            }
            this.mNumStops = ns;
        }

        float nextTab(float h) {
            int ns = this.mNumStops;
            if (ns > 0) {
                float[] stops = this.mStops;
                for (int i = 0; i < ns; ++i) {
                    float stop = stops[i];
                    if (stop > h) {
                        return stop;
                    }
                }
            }
            return nextDefaultStop(h, mIncrement);
        }

        /**
         * Returns the position of next tab stop.
         */
        public static float nextDefaultStop(float h, float inc) {
            return ((int) ((h + inc) / inc)) * inc;
        }
    }

    /**
     * Returns the position of the next tab stop after h on the line.
     *
     * @param text the text
     * @param start start of the line
     * @param end limit of the line
     * @param h the current horizontal offset
     * @param tabs the tabs, can be null.  If it is null, any tabs in effect
     * on the line will be used.  If there are no tabs, a default offset
     * will be used to compute the tab stop.
     * @return the offset of the next tab stop.
     */
    /* package */ static float nextTab(CharSequence text, int start, int end,
                                       float h, Object[] tabs) {
        float nh = Float.MAX_VALUE;
        boolean alltabs = false;

        if (text instanceof Spanned) {
            if (tabs == null) {
                tabs = getParagraphSpans((Spanned) text, start, end, TabStopSpan.class);
                alltabs = true;
            }

            for (int i = 0; i < tabs.length; i++) {
                if (!alltabs) {
                    if (!(tabs[i] instanceof TabStopSpan))
                        continue;
                }

                int where = ((TabStopSpan) tabs[i]).getTabStop();

                if (where < nh && where > h)
                    nh = where;
            }

            if (nh != Float.MAX_VALUE)
                return nh;
        }

        return ((int) ((h + TAB_INCREMENT) / TAB_INCREMENT)) * TAB_INCREMENT;
    }

    protected final boolean isSpanned() {
        return mSpannedText;
    }

    /**
     * Returns the same as <code>text.getSpans()</code>, except where
     * <code>start</code> and <code>end</code> are the same and are not
     * at the very beginning of the text, in which case an empty array
     * is returned instead.
     * <p>
     * This is needed because of the special case that <code>getSpans()</code>
     * on an empty range returns the spans adjacent to that range, which is
     * primarily for the sake of <code>TextWatchers</code> so they will get
     * notifications when text goes from empty to non-empty.  But it also
     * has the unfortunate side effect that if the text ends with an empty
     * paragraph, that paragraph accidentally picks up the styles of the
     * preceding paragraph (even though those styles will not be picked up
     * by new text that is inserted into the empty paragraph).
     * <p>
     * The reason it just checks whether <code>start</code> and <code>end</code>
     * is the same is that the only time a line can contain 0 characters
     * is if it is the final paragraph of the Layout; otherwise any line will
     * contain at least one printing or newline character.  The reason for the
     * additional check if <code>start</code> is greater than 0 is that
     * if the empty paragraph is the entire content of the buffer, paragraph
     * styles that are already applied to the buffer will apply to text that
     * is inserted into it.
     */
    /* package */static <T> T[] getParagraphSpans(Spanned text, int start, int end, Class<T> type) {
        if (start == end && start > 0) {
            return ArrayUtils.emptyArray(type);
        }

        if(text instanceof SpannableStringBuilder) {
            return ((SpannableStringBuilder) text).getSpans(start, end, type, false);
        } else {
            return text.getSpans(start, end, type);
        }
    }

    private void ellipsize(int start, int end, int line,
                           char[] dest, int destoff, TextUtils.TruncateAt method) {
        final int ellipsisCount = getEllipsisCount(line);
        if (ellipsisCount == 0) {
            return;
        }
        final int ellipsisStart = getEllipsisStart(line);
        final int lineStart = getLineStart(line);

        final String ellipsisString = TextUtils.getEllipsisString(method);
        final int ellipsisStringLen = ellipsisString.length();
        // Use the ellipsis string only if there are that at least as many characters to replace.
        final boolean useEllipsisString = ellipsisCount >= ellipsisStringLen;
        final int min = Math.max(0, start - ellipsisStart - lineStart);
        final int max = Math.min(ellipsisCount, end - ellipsisStart - lineStart);

        for (int i = min; i < max; i++) {
            final char c;
            if (useEllipsisString && i < ellipsisStringLen) {
                c = ellipsisString.charAt(i);
            } else {
                c = TextUtils.ELLIPSIS_FILLER;
            }

            final int a = i + ellipsisStart + lineStart;
            dest[destoff + a - start] = c;
        }
    }

    /**
     * Stores information about bidirectional (left-to-right or right-to-left)
     * text within the layout of a line.
     */
    public static class Directions {
        /**
         * Directions represents directional runs within a line of text. Runs are pairs of ints
         * listed in visual order, starting from the leading margin.  The first int of each pair is
         * the offset from the first character of the line to the start of the run.  The second int
         * represents both the length and level of the run. The length is in the lower bits,
         * accessed by masking with RUN_LENGTH_MASK.  The level is in the higher bits, accessed by
         * shifting by RUN_LEVEL_SHIFT and masking by RUN_LEVEL_MASK. To simply test for an RTL
         * direction, test the bit using RUN_RTL_FLAG, if set then the direction is rtl.
         * @hide
         */
        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
        public int[] mDirections;

        /**
         * @hide
         */
        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
        public Directions(int[] dirs) {
            mDirections = dirs;
        }

        /**
         * Returns number of BiDi runs.
         *
         * @hide
         */
        public @IntRange(from = 0) int getRunCount() {
            return mDirections.length / 2;
        }

        /**
         * Returns the start offset of the BiDi run.
         *
         * @param runIndex the index of the BiDi run
         * @return the start offset of the BiDi run.
         * @hide
         */
        public @IntRange(from = 0) int getRunStart(@IntRange(from = 0) int runIndex) {
            return mDirections[runIndex * 2];
        }

        /**
         * Returns the length of the BiDi run.
         *
         * Note that this method may return too large number due to reducing the number of object
         * allocations. The too large number means the remaining part is assigned to this run. The
         * caller must clamp the returned value.
         *
         * @param runIndex the index of the BiDi run
         * @return the length of the BiDi run.
         * @hide
         */
        public @IntRange(from = 0) int getRunLength(@IntRange(from = 0) int runIndex) {
            return mDirections[runIndex * 2 + 1] & RUN_LENGTH_MASK;
        }

        /**
         * Returns the BiDi level of this run.
         *
         * @param runIndex the index of the BiDi run
         * @return the BiDi level of this run.
         * @hide
         */
        @IntRange(from = 0)
        public int getRunLevel(int runIndex) {
            return (mDirections[runIndex * 2 + 1] >>> RUN_LEVEL_SHIFT) & RUN_LEVEL_MASK;
        }

        /**
         * Returns true if the BiDi run is RTL.
         *
         * @param runIndex the index of the BiDi run
         * @return true if the BiDi run is RTL.
         * @hide
         */
        public boolean isRunRtl(int runIndex) {
            return (mDirections[runIndex * 2 + 1] & RUN_RTL_FLAG) != 0;
        }
    }

    /**
     * Return the offset of the first character to be ellipsized away,
     * relative to the start of the line.  (So 0 if the beginning of the
     * line is ellipsized, not getLineStart().)
     */
    public abstract int getEllipsisStart(int line);

    /**
     * Returns the number of characters to be ellipsized away, or 0 if
     * no ellipsis is to take place.
     */
    public abstract int getEllipsisCount(int line);

    /* package */ static class Ellipsizer implements CharSequence, GetChars {
        /* package */ CharSequence mText;
        /* package */ Layout mLayout;
        /* package */ int mWidth;
        /* package */ TextUtils.TruncateAt mMethod;

        public Ellipsizer(CharSequence s) {
            mText = s;
        }

        public char charAt(int off) {
            char[] buf = TextUtils.obtain(1);
            getChars(off, off + 1, buf, 0);
            char ret = buf[0];

            TextUtils.recycle(buf);
            return ret;
        }

        public void getChars(int start, int end, char[] dest, int destoff) {
            int line1 = mLayout.getLineForOffset(start);
            int line2 = mLayout.getLineForOffset(end);

            TextUtils.getChars(mText, start, end, dest, destoff);

            for (int i = line1; i <= line2; i++) {
                mLayout.ellipsize(start, end, i, dest, destoff, mMethod);
            }
        }

        public int length() {
            return mText.length();
        }

        public CharSequence subSequence(int start, int end) {
            char[] s = new char[end - start];
            getChars(start, end, s, 0);
            return new String(s);
        }

        @Override
        public String toString() {
            char[] s = new char[length()];
            getChars(0, length(), s, 0);
            return new String(s);
        }

    }

    /* package */ static class SpannedEllipsizer extends Ellipsizer implements Spanned {
        private Spanned mSpanned;

        public SpannedEllipsizer(CharSequence display) {
            super(display);
            mSpanned = (Spanned) display;
        }

        public <T> T[] getSpans(int start, int end, Class<T> type) {
            return mSpanned.getSpans(start, end, type);
        }

        public int getSpanStart(Object tag) {
            return mSpanned.getSpanStart(tag);
        }

        public int getSpanEnd(Object tag) {
            return mSpanned.getSpanEnd(tag);
        }

        public int getSpanFlags(Object tag) {
            return mSpanned.getSpanFlags(tag);
        }

        @SuppressWarnings("rawtypes")
        public int nextSpanTransition(int start, int limit, Class type) {
            return mSpanned.nextSpanTransition(start, limit, type);
        }

        @Override
        public CharSequence subSequence(int start, int end) {
            char[] s = new char[end - start];
            getChars(start, end, s, 0);

            SpannableString ss = new SpannableString(new String(s));
            TextUtils.copySpansFrom(mSpanned, start, end, Object.class, ss, 0);
            return ss;
        }
    }

    private CharSequence mText;
    @UnsupportedAppUsage
    private TextPaint mPaint;
    private final TextPaint mWorkPaint = new TextPaint();
    private final Paint mWorkPlainPaint = new Paint();
    private int mWidth;
    private Alignment mAlignment = Alignment.ALIGN_NORMAL;
    private float mSpacingMult;
    private float mSpacingAdd;
    private static final Rect sTempRect = new Rect();
    private boolean mSpannedText;
    private TextDirectionHeuristic mTextDir;
    private SpanSet<LineBackgroundSpan> mLineBackgroundSpans;
    private boolean mIncludePad;
    private boolean mFallbackLineSpacing;
    private int mEllipsizedWidth;
    private TextUtils.TruncateAt mEllipsize;
    private int mMaxLines;
    private int mBreakStrategy;
    private int mHyphenationFrequency;
    private int[] mLeftIndents;
    private int[] mRightIndents;
    private int mJustificationMode;
    private LineBreakConfig mLineBreakConfig;
    private boolean mUseBoundsForWidth;
    private boolean mShiftDrawingOffsetForStartOverhang;
    private @Nullable Paint.FontMetrics mMinimumFontMetrics;

    private TextLine.LineInfo mLineInfo = null;

    /** @hide */
    @IntDef(prefix = { "DIR_" }, value = {
            DIR_LEFT_TO_RIGHT,
            DIR_RIGHT_TO_LEFT
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Direction {}

    public static final int DIR_LEFT_TO_RIGHT = 1;
    public static final int DIR_RIGHT_TO_LEFT = -1;

    /* package */ static final int DIR_REQUEST_LTR = 1;
    /* package */ static final int DIR_REQUEST_RTL = -1;
    @UnsupportedAppUsage
    /* package */ static final int DIR_REQUEST_DEFAULT_LTR = 2;
    /* package */ static final int DIR_REQUEST_DEFAULT_RTL = -2;

    /* package */ static final int RUN_LENGTH_MASK = 0x03ffffff;
    /* package */ static final int RUN_LEVEL_SHIFT = 26;
    /* package */ static final int RUN_LEVEL_MASK = 0x3f;
    /* package */ static final int RUN_RTL_FLAG = 1 << RUN_LEVEL_SHIFT;

    public enum Alignment {
        ALIGN_NORMAL,
        ALIGN_OPPOSITE,
        ALIGN_CENTER,
        /** @hide */
        @UnsupportedAppUsage
        ALIGN_LEFT,
        /** @hide */
        @UnsupportedAppUsage
        ALIGN_RIGHT,
    }

    private static final float TAB_INCREMENT = 20;

    /** @hide */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    @UnsupportedAppUsage
    public static final Directions DIRS_ALL_LEFT_TO_RIGHT =
        new Directions(new int[] { 0, RUN_LENGTH_MASK });

    /** @hide */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    @UnsupportedAppUsage
    public static final Directions DIRS_ALL_RIGHT_TO_LEFT =
        new Directions(new int[] { 0, RUN_LENGTH_MASK | RUN_RTL_FLAG });

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "TEXT_SELECTION_LAYOUT_" }, value = {
            TEXT_SELECTION_LAYOUT_RIGHT_TO_LEFT,
            TEXT_SELECTION_LAYOUT_LEFT_TO_RIGHT
    })
    public @interface TextSelectionLayout {}

    /** @hide */
    public static final int TEXT_SELECTION_LAYOUT_RIGHT_TO_LEFT = 0;
    /** @hide */
    public static final int TEXT_SELECTION_LAYOUT_LEFT_TO_RIGHT = 1;

    /** @hide */
    @FunctionalInterface
    public interface SelectionRectangleConsumer {
        /**
         * Performs this operation on the given rectangle.
         *
         * @param left   the left edge of the rectangle
         * @param top    the top edge of the rectangle
         * @param right  the right edge of the rectangle
         * @param bottom the bottom edge of the rectangle
         * @param textSelectionLayout the layout (RTL or LTR) of the text covered by this
         *                            selection rectangle
         */
        void accept(float left, float top, float right, float bottom,
                @TextSelectionLayout int textSelectionLayout);
    }

    /**
     * Strategy for determining whether a text segment is inside a rectangle area.
     *
     * @see #getRangeForRect(RectF, SegmentFinder, TextInclusionStrategy)
     */
    @FunctionalInterface
    public interface TextInclusionStrategy {
        /**
         * Returns true if this {@link TextInclusionStrategy} considers the segment with bounds
         * {@code segmentBounds} to be inside {@code area}.
         *
         * <p>The segment is a range of text which does not cross line boundaries or directional run
         * boundaries. The horizontal bounds of the segment are the start bound of the first
         * character to the end bound of the last character. The vertical bounds match the line
         * bounds ({@code getLineTop(line)} and {@code getLineBottom(line, false)}).
         */
        boolean isSegmentInside(@NonNull RectF segmentBounds, @NonNull RectF area);
    }

    /**
     * A builder class for Layout object.
     *
     * Different from {@link StaticLayout.Builder}, this builder generates the optimal layout based
     * on input. If the given text and parameters can be rendered with {@link BoringLayout}, this
     * builder generates {@link BoringLayout} instance. Otherwise, {@link StaticLayout} instance is
     * generated.
     *
     * @see StaticLayout.Builder
     */
    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
    public static final class Builder {
        /**
         * Construct a builder class.
         *
         * @param text a text to be displayed.
         * @param start an inclusive start index of the text to be displayed.
         * @param end an exclusive end index of the text to be displayed.
         * @param paint a paint object to be used for drawing text.
         * @param width a width constraint in pixels.
         */
        public Builder(
                @NonNull CharSequence text,
                @IntRange(from = 0) int start,
                @IntRange(from = 0) int end,
                @NonNull TextPaint paint,
                @IntRange(from = 0) int width) {
            mText = text;
            mStart = start;
            mEnd = end;
            mPaint = paint;
            mWidth = width;
            mEllipsizedWidth = width;
        }

        /**
         * Set the text alignment.
         *
         * The default value is {@link Layout.Alignment#ALIGN_NORMAL}.
         *
         * @param alignment an alignment.
         * @return this builder instance.
         * @see Layout.Alignment
         * @see Layout#getAlignment()
         * @see StaticLayout.Builder#setAlignment(Alignment)
         */
        @NonNull
        public Builder setAlignment(@NonNull Alignment alignment) {
            mAlignment = alignment;
            return this;
        }

        /**
         * Set the text direction heuristics.
         *
         * The text direction heuristics is used to resolve text direction on the text.
         *
         * The default value is {@link TextDirectionHeuristics#FIRSTSTRONG_LTR}
         *
         * @param textDirection a text direction heuristic.
         * @return this builder instance.
         * @see TextDirectionHeuristics
         * @see Layout#getTextDirectionHeuristic()
         * @see StaticLayout.Builder#setTextDirection(TextDirectionHeuristic)
         */
        @NonNull
        public Builder setTextDirectionHeuristic(@NonNull TextDirectionHeuristic textDirection) {
            mTextDir = textDirection;
            return this;
        }

        /**
         * Set the line spacing amount.
         *
         * The specified amount of pixels will be added to each line.
         *
         * The default value is {@code 0}. The negative value is allowed for squeezing lines.
         *
         * @param amount an amount of pixels to be added to line height.
         * @return this builder instance.
         * @see Layout#getLineSpacingAmount()
         * @see Layout#getSpacingAdd()
         * @see StaticLayout.Builder#setLineSpacing(float, float)
         */
        @NonNull
        public Builder setLineSpacingAmount(float amount) {
            mSpacingAdd = amount;
            return this;
        }

        /**
         * Set the line spacing multiplier.
         *
         * The specified value will be multiplied to each line.
         *
         * The default value is {@code 1}.
         *
         * @param multiplier a multiplier to be applied to the line height
         * @return this builder instance.
         * @see Layout#getLineSpacingMultiplier()
         * @see Layout#getSpacingMultiplier()
         * @see StaticLayout.Builder#setLineSpacing(float, float)
         */
        @NonNull
        public Builder setLineSpacingMultiplier(@FloatRange(from = 0) float multiplier) {
            mSpacingMult = multiplier;
            return this;
        }

        /**
         * Set whether including extra padding into the first and the last line height.
         *
         * By setting true, the first line of the text and the last line of the text will have extra
         * vertical space for avoiding clipping.
         *
         * The default value is {@code true}.
         *
         * @param includeFontPadding true for including extra space into first and last line.
         * @return this builder instance.
         * @see Layout#isFontPaddingIncluded()
         * @see StaticLayout.Builder#setIncludePad(boolean)
         */
        @NonNull
        public Builder setFontPaddingIncluded(boolean includeFontPadding) {
            mIncludePad = includeFontPadding;
            return this;
        }

        /**
         * Set whether to respect the ascent and descent of the fallback fonts.
         *
         * Set whether to respect the ascent and descent of the fallback fonts that are used in
         * displaying the text (which is needed to avoid text from consecutive lines running into
         * each other). If set, fallback fonts that end up getting used can increase the ascent
         * and descent of the lines that they are used on.
         *
         * The default value is {@code false}
         *
         * @param fallbackLineSpacing whether to expand line height based on fallback fonts.
         * @return this builder instance.
         * @see Layout#isFallbackLineSpacingEnabled()
         * @see StaticLayout.Builder#setUseLineSpacingFromFallbacks(boolean)
         */
        @NonNull
        public Builder setFallbackLineSpacingEnabled(boolean fallbackLineSpacing) {
            mFallbackLineSpacing = fallbackLineSpacing;
            return this;
        }

        /**
         * Set the width as used for ellipsizing purpose in pixels.
         *
         * The passed value is ignored and forced to set to the value of width constraint passed in
         * constructor if no ellipsize option is set.
         *
         * The default value is the width constraint.
         *
         * @param ellipsizeWidth a ellipsizing width in pixels.
         * @return this builder instance.
         * @see Layout#getEllipsizedWidth()
         * @see StaticLayout.Builder#setEllipsizedWidth(int)
         */
        @NonNull
        public Builder setEllipsizedWidth(@IntRange(from = 0) int ellipsizeWidth) {
            mEllipsizedWidth = ellipsizeWidth;
            return this;
        }

        /**
         * Set the ellipsizing type.
         *
         * By setting null, the ellipsize is disabled.
         *
         * The default value is {@code null}.
         *
         * @param ellipsize type of the ellipsize. null for disabling ellipsize.
         * @return this builder instance.
         * @see Layout#getEllipsize()
         * @see StaticLayout.Builder#getEllipsize()
         * @see android.text.TextUtils.TruncateAt
         */
        @NonNull
        public Builder setEllipsize(@Nullable TextUtils.TruncateAt ellipsize) {
            mEllipsize = ellipsize;
            return this;
        }

        /**
         * Set the maximum number of lines.
         *
         * The default value is unlimited.
         *
         * @param maxLines maximum number of lines in the layout.
         * @return this builder instance.
         * @see Layout#getMaxLines()
         * @see StaticLayout.Builder#setMaxLines(int)
         */
        @NonNull
        public Builder setMaxLines(@IntRange(from = 1) int maxLines) {
            mMaxLines = maxLines;
            return this;
        }

        /**
         * Set the line break strategy.
         *
         * The default value is {@link Layout#BREAK_STRATEGY_SIMPLE}.
         *
         * @param breakStrategy a break strategy for line breaking.
         * @return this builder instance.
         * @see Layout#getBreakStrategy()
         * @see StaticLayout.Builder#setBreakStrategy(int)
         * @see Layout#BREAK_STRATEGY_SIMPLE
         * @see Layout#BREAK_STRATEGY_HIGH_QUALITY
         * @see Layout#BREAK_STRATEGY_BALANCED
         */
        @NonNull
        public Builder setBreakStrategy(@BreakStrategy int breakStrategy) {
            mBreakStrategy = breakStrategy;
            return this;
        }

        /**
         * Set the hyphenation frequency.
         *
         * The default value is {@link Layout#HYPHENATION_FREQUENCY_NONE}.
         *
         * @param hyphenationFrequency a hyphenation frequency.
         * @return this builder instance.
         * @see Layout#getHyphenationFrequency()
         * @see StaticLayout.Builder#setHyphenationFrequency(int)
         * @see Layout#HYPHENATION_FREQUENCY_NONE
         * @see Layout#HYPHENATION_FREQUENCY_NORMAL
         * @see Layout#HYPHENATION_FREQUENCY_FULL
         * @see Layout#HYPHENATION_FREQUENCY_NORMAL_FAST
         * @see Layout#HYPHENATION_FREQUENCY_FULL_FAST
         */
        @NonNull
        public Builder setHyphenationFrequency(@HyphenationFrequency int hyphenationFrequency) {
            mHyphenationFrequency = hyphenationFrequency;
            return this;
        }

        /**
         * Set visually left indents in pixels per lines.
         *
         * For the lines past the last element in the array, the last element repeats. Passing null
         * for disabling indents.
         *
         * Note that even with the RTL layout, this method reserve spacing at the visually left of
         * the line.
         *
         * The default value is {@code null}.
         *
         * @param leftIndents array of indents values for the left margins in pixels.
         * @return this builder instance.
         * @see Layout#getLeftIndents()
         * @see Layout#getRightIndents()
         * @see Layout.Builder#setRightIndents(int[])
         * @see StaticLayout.Builder#setIndents(int[], int[])
         */
        @NonNull
        public Builder setLeftIndents(@Nullable int[] leftIndents) {
            mLeftIndents = leftIndents;
            return this;
        }

        /**
         * Set visually right indents in pixels per lines.
         *
         * For the lines past the last element in the array, the last element repeats. Passing null
         * for disabling indents.
         *
         * Note that even with the RTL layout, this method reserve spacing at the visually right of
         * the line.
         *
         * The default value is {@code null}.
         *
         * @param rightIndents array of indents values for the right margins in pixels.
         * @return this builder instance.
         * @see Layout#getLeftIndents()
         * @see Layout#getRightIndents()
         * @see Layout.Builder#setLeftIndents(int[])
         * @see StaticLayout.Builder#setIndents(int[], int[])
         */
        @NonNull
        public Builder setRightIndents(@Nullable int[] rightIndents) {
            mRightIndents = rightIndents;
            return this;
        }

        /**
         * Set justification mode.
         *
         * When justification mode is {@link Layout#JUSTIFICATION_MODE_INTER_WORD}, the word spacing
         * on the given Paint passed to the constructor will be ignored. This behavior also affects
         * spans which change the word spacing.
         *
         * The default value is {@link Layout#JUSTIFICATION_MODE_NONE}.
         *
         * @param justificationMode justification mode.
         * @return this builder instance.
         * @see Layout#getJustificationMode()
         * @see StaticLayout.Builder#setJustificationMode(int)
         * @see Layout#JUSTIFICATION_MODE_NONE
         * @see Layout#JUSTIFICATION_MODE_INTER_WORD
         */
        @NonNull
        public Builder setJustificationMode(@JustificationMode int justificationMode) {
            mJustificationMode = justificationMode;
            return this;
        }

        /**
         * Set the line break configuration.
         *
         * The default value is a LinebreakConfig instance that has
         * {@link LineBreakConfig#LINE_BREAK_STYLE_NONE} and
         * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_NONE}.
         *
         * @param lineBreakConfig the line break configuration
         * @return this builder instance.
         * @see Layout#getLineBreakConfig()
         * @see StaticLayout.Builder#setLineBreakConfig(LineBreakConfig)
         */
        @NonNull
        public Builder setLineBreakConfig(@NonNull LineBreakConfig lineBreakConfig) {
            mLineBreakConfig = lineBreakConfig;
            return this;
        }

        /**
         * Set true for using width of bounding box as a source of automatic line breaking and
         * drawing.
         *
         * If this value is false, the Layout determines the drawing offset and automatic line
         * breaking based on total advances. By setting true, use all joined glyph's bounding boxes
         * as a source of text width.
         *
         * If the font has glyphs that have negative bearing X or its xMax is greater than advance,
         * the glyph clipping can happen because the drawing area may be bigger. By setting this to
         * true, the Layout will reserve more spaces for drawing.
         *
         * @param useBoundsForWidth True for using bounding box, false for advances.
         * @return this builder instance
         * @see Layout#getUseBoundsForWidth()
         * @see StaticLayout.Builder#setUseBoundsForWidth(boolean)
         */
        // The corresponding getter is getUseBoundsForWidth
        @NonNull
        @SuppressLint("MissingGetterMatchingBuilder")
        @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
        public Builder setUseBoundsForWidth(boolean useBoundsForWidth) {
            mUseBoundsForWidth = useBoundsForWidth;
            return this;
        }

        /**
         * Set true for shifting the drawing x offset for showing overhang at the start position.
         *
         * This flag is ignored if the {@link #getUseBoundsForWidth()} is false.
         *
         * If this value is false, the Layout draws text from the zero even if there is a glyph
         * stroke in a region where the x coordinate is negative.
         *
         * If this value is true, the Layout draws text with shifting the x coordinate of the
         * drawing bounding box.
         *
         * This value is false by default.
         *
         * @param shiftDrawingOffsetForStartOverhang true for shifting the drawing offset for
         *                                          showing the stroke that is in the region where
         *                                          the x coordinate is negative.
         * @see #setUseBoundsForWidth(boolean)
         * @see #getUseBoundsForWidth()
         */
        @NonNull
        // The corresponding getter is getShiftDrawingOffsetForStartOverhang()
        @SuppressLint("MissingGetterMatchingBuilder")
        @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
        public Builder setShiftDrawingOffsetForStartOverhang(
                boolean shiftDrawingOffsetForStartOverhang) {
            mShiftDrawingOffsetForStartOverhang = shiftDrawingOffsetForStartOverhang;
            return this;
        }

        /**
         * Set the minimum font metrics used for line spacing.
         *
         * <p>
         * {@code null} is the default value. If {@code null} is set or left it as default, the font
         * metrics obtained by {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)} is used.
         *
         * <p>
         * The minimum meaning here is the minimum value of line spacing: maximum value of
         * {@link Paint#ascent()}, minimum value of {@link Paint#descent()}.
         *
         * <p>
         * By setting this value, each line will have minimum line spacing regardless of the text
         * rendered. For example, usually Japanese script has larger vertical metrics than Latin
         * script. By setting the metrics obtained by
         * {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)} for Japanese or leave it
         * {@code null} if the Paint's locale is Japanese, the line spacing for Japanese is reserved
         * if the text is an English text. If the vertical metrics of the text is larger than
         * Japanese, for example Burmese, the bigger font metrics is used.
         *
         * @param minimumFontMetrics A minimum font metrics. Passing {@code null} for using the
         *                          value obtained by
         *                          {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)}
         * @see android.widget.TextView#setMinimumFontMetrics(Paint.FontMetrics)
         * @see android.widget.TextView#getMinimumFontMetrics()
         * @see Layout#getMinimumFontMetrics()
         * @see StaticLayout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
         * @see DynamicLayout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
         */
        @NonNull
        @FlaggedApi(FLAG_FIX_LINE_HEIGHT_FOR_LOCALE)
        public Builder setMinimumFontMetrics(@Nullable Paint.FontMetrics minimumFontMetrics) {
            mMinimumFontMetrics = minimumFontMetrics;
            return this;
        }

        private BoringLayout.Metrics isBoring() {
            if (mStart != 0 || mEnd != mText.length()) {  // BoringLayout only support entire text.
                return null;
            }
            BoringLayout.Metrics metrics = BoringLayout.isBoring(mText, mPaint, mTextDir,
                    mFallbackLineSpacing, mMinimumFontMetrics, null);
            if (metrics == null) {
                return null;
            }
            if (metrics.width <= mWidth) {
                return metrics;
            }
            if (mEllipsize != null) {
                return metrics;
            }
            return null;
        }

        /**
         * Build a Layout object.
         */
        @NonNull
        public Layout build() {
            BoringLayout.Metrics metrics = isBoring();
            if (metrics == null) {  // we cannot use BoringLayout, create StaticLayout.
                return StaticLayout.Builder.obtain(mText, mStart, mEnd, mPaint, mWidth)
                        .setAlignment(mAlignment)
                        .setLineSpacing(mSpacingAdd, mSpacingMult)
                        .setTextDirection(mTextDir)
                        .setIncludePad(mIncludePad)
                        .setUseLineSpacingFromFallbacks(mFallbackLineSpacing)
                        .setEllipsizedWidth(mEllipsizedWidth)
                        .setEllipsize(mEllipsize)
                        .setMaxLines(mMaxLines)
                        .setBreakStrategy(mBreakStrategy)
                        .setHyphenationFrequency(mHyphenationFrequency)
                        .setIndents(mLeftIndents, mRightIndents)
                        .setJustificationMode(mJustificationMode)
                        .setLineBreakConfig(mLineBreakConfig)
                        .setUseBoundsForWidth(mUseBoundsForWidth)
                        .setShiftDrawingOffsetForStartOverhang(mShiftDrawingOffsetForStartOverhang)
                        .build();
            } else {
                return new BoringLayout(
                        mText, mPaint, mWidth, mAlignment, mTextDir, mSpacingMult, mSpacingAdd,
                        mIncludePad, mFallbackLineSpacing, mEllipsizedWidth, mEllipsize, mMaxLines,
                        mBreakStrategy, mHyphenationFrequency, mLeftIndents, mRightIndents,
                        mJustificationMode, mLineBreakConfig, metrics, mUseBoundsForWidth,
                        mShiftDrawingOffsetForStartOverhang, mMinimumFontMetrics);
            }
        }

        private final CharSequence mText;
        private final int mStart;
        private final int mEnd;
        private final TextPaint mPaint;
        private final int mWidth;
        private Alignment mAlignment = Alignment.ALIGN_NORMAL;
        private float mSpacingMult = 1.0f;
        private float mSpacingAdd = 0.0f;
        private TextDirectionHeuristic mTextDir = TextDirectionHeuristics.FIRSTSTRONG_LTR;
        private boolean mIncludePad = true;
        private boolean mFallbackLineSpacing = false;
        private int mEllipsizedWidth;
        private TextUtils.TruncateAt mEllipsize = null;
        private int mMaxLines = Integer.MAX_VALUE;
        private int mBreakStrategy = BREAK_STRATEGY_SIMPLE;
        private int mHyphenationFrequency = HYPHENATION_FREQUENCY_NONE;
        private int[] mLeftIndents = null;
        private int[] mRightIndents = null;
        private int mJustificationMode = JUSTIFICATION_MODE_NONE;
        private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;
        private boolean mUseBoundsForWidth;
        private boolean mShiftDrawingOffsetForStartOverhang;
        private Paint.FontMetrics mMinimumFontMetrics;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////
    // Getters of parameters that is used for building Layout instance
    ///////////////////////////////////////////////////////////////////////////////////////////////

    // TODO(316208691): Revive following removed API docs.
    // @see Layout.Builder
    /**
     * Return the text used for creating this layout.
     *
     * @return the text used for creating this layout.
     */
    @NonNull
    public final CharSequence getText() {
        return mText;
    }

    // TODO(316208691): Revive following removed API docs.
    // @see Layout.Builder
    /**
     * Return the paint used for creating this layout.
     *
     * Do not modify the returned paint object. This paint object will still be used for
     * drawing/measuring text.
     *
     * @return the paint used for creating this layout.
     */
    @NonNull
    public final TextPaint getPaint() {
        return mPaint;
    }

    // TODO(316208691): Revive following removed API docs.
    // @see Layout.Builder
    /**
     * Return the width used for creating this layout in pixels.
     *
     * @return the width used for creating this layout in pixels.
     */
    @IntRange(from = 0)
    public final int getWidth() {
        return mWidth;
    }

    // TODO(316208691): Revive following removed API docs.
    // @see Layout.Builder#setAlignment(Alignment)
    /**
     * Returns the alignment used for creating this layout in pixels.
     *
     * @return the alignment used for creating this layout.
     * @see StaticLayout.Builder#setAlignment(Alignment)
     */
    @NonNull
    public final Alignment getAlignment() {
        return mAlignment;
    }

    /**
     * Returns the text direction heuristic used for creating this layout.
     *
     * @return the text direction heuristic used for creating this layout
     * @see Layout.Builder#setTextDirectionHeuristic(TextDirectionHeuristic)
     * @see StaticLayout.Builder#setTextDirection(TextDirectionHeuristic)
     */
    @NonNull
    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
    public final TextDirectionHeuristic getTextDirectionHeuristic() {
        return mTextDir;
    }

    // TODO(316208691): Revive following removed API docs.
    // This is an alias of {@link #getLineSpacingMultiplier}.
    // @see Layout.Builder#setLineSpacingMultiplier(float)
    // @see Layout#getLineSpacingMultiplier()
    /**
     * Returns the multiplier applied to the line height.
     *
     * @return the line height multiplier.
     * @see StaticLayout.Builder#setLineSpacing(float, float)
     */
    public final float getSpacingMultiplier() {
        return getLineSpacingMultiplier();
    }

    /**
     * Returns the multiplier applied to the line height.
     *
     * @return the line height multiplier.
     * @see Layout.Builder#setLineSpacingMultiplier(float)
     * @see StaticLayout.Builder#setLineSpacing(float, float)
     * @see Layout#getSpacingMultiplier()
     */
    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
    public final float getLineSpacingMultiplier() {
        return mSpacingMult;
    }

    // TODO(316208691): Revive following removed API docs.
    // This is an alias of {@link #getLineSpacingAmount()}.
    // @see Layout.Builder#setLineSpacingAmount(float)
    // @see Layout#getLineSpacingAmount()
    /**
     * Returns the amount added to the line height.
     *
     * @return the line height additional amount.
     * @see StaticLayout.Builder#setLineSpacing(float, float)
     */
    public final float getSpacingAdd() {
        return getLineSpacingAmount();
    }

    /**
     * Returns the amount added to the line height.
     *
     * @return the line height additional amount.
     * @see Layout.Builder#setLineSpacingAmount(float)
     * @see StaticLayout.Builder#setLineSpacing(float, float)
     * @see Layout#getSpacingAdd()
     */
    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
    public final float getLineSpacingAmount() {
        return mSpacingAdd;
    }

    /**
     * Returns true if this layout is created with increased line height.
     *
     * @return true if the layout is created with increased line height.
     * @see Layout.Builder#setFontPaddingIncluded(boolean)
     * @see StaticLayout.Builder#setIncludePad(boolean)
     */
    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
    public final boolean isFontPaddingIncluded() {
        return mIncludePad;
    }

    // TODO(316208691): Revive following removed API docs.
    // @see Layout.Builder#setFallbackLineSpacingEnabled(boolean)
    /**
     * Return true if the fallback line space is enabled in this Layout.
     *
     * @return true if the fallback line space is enabled. Otherwise, returns false.
     * @see StaticLayout.Builder#setUseLineSpacingFromFallbacks(boolean)
     */
    // not being final because of already published API.
    public boolean isFallbackLineSpacingEnabled() {
        return mFallbackLineSpacing;
    }

    // TODO(316208691): Revive following removed API docs.
    // @see Layout.Builder#setEllipsizedWidth(int)
    // @see Layout.Builder#setEllipsize(TextUtils.TruncateAt)
    // @see Layout#getEllipsize()
    /**
     * Return the width to which this layout is ellipsized.
     *
     * If no ellipsize is applied, the same amount of {@link #getWidth} is returned.
     *
     * @return the amount of ellipsized width in pixels.
     * @see StaticLayout.Builder#setEllipsizedWidth(int)
     * @see StaticLayout.Builder#setEllipsize(TextUtils.TruncateAt)
     */
    @IntRange(from = 0)
    public int getEllipsizedWidth() {  // not being final because of already published API.
        return mEllipsizedWidth;
    }

    /**
     * Return the ellipsize option used for creating this layout.
     *
     * May return null if no ellipsize option was selected.
     *
     * @return The ellipsize option used for creating this layout, or null if no ellipsize option
     * was selected.
     * @see Layout.Builder#setEllipsize(TextUtils.TruncateAt)
     * @see StaticLayout.Builder#setEllipsize(TextUtils.TruncateAt)
     * @see Layout.Builder#setEllipsizedWidth(int)
     * @see StaticLayout.Builder#setEllipsizedWidth(int)
     * @see Layout#getEllipsizedWidth()
     */
    @Nullable
    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
    public final TextUtils.TruncateAt getEllipsize() {
        return mEllipsize;
    }

    /**
     * Return the maximum lines allowed used for creating this layout.
     *
     * Note that this is not an actual line count of this layout. Use {@link #getLineCount()} for
     * getting the actual line count of this layout.
     *
     * @return the maximum lines allowed used for creating this layout.
     * @see Layout.Builder#setMaxLines(int)
     * @see StaticLayout.Builder#setMaxLines(int)
     */
    @IntRange(from = 1)
    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
    public final int getMaxLines() {
        return mMaxLines;
    }

    /**
     * Return the break strategy used for creating this layout.
     *
     * @return the break strategy used for creating this layout.
     * @see Layout.Builder#setBreakStrategy(int)
     * @see StaticLayout.Builder#setBreakStrategy(int)
     */
    @BreakStrategy
    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
    public final int getBreakStrategy() {
        return mBreakStrategy;
    }

    /**
     * Return the hyphenation frequency used for creating this layout.
     *
     * @return the hyphenation frequency used for creating this layout.
     * @see Layout.Builder#setHyphenationFrequency(int)
     * @see StaticLayout.Builder#setHyphenationFrequency(int)
     */
    @HyphenationFrequency
    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
    public final int getHyphenationFrequency() {
        return mHyphenationFrequency;
    }

    /**
     * Return a copy of the left indents used for this layout.
     *
     * May return null if no left indentation is applied.
     *
     * @return the array of left indents in pixels.
     * @see Layout.Builder#setLeftIndents(int[])
     * @see Layout.Builder#setRightIndents(int[])
     * @see StaticLayout.Builder#setIndents(int[], int[])
     */
    @Nullable
    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
    public final int[] getLeftIndents() {
        if (mLeftIndents == null) {
            return null;
        }
        int[] newArray = new int[mLeftIndents.length];
        System.arraycopy(mLeftIndents, 0, newArray, 0, newArray.length);
        return newArray;
    }

    /**
     * Return a copy of the right indents used for this layout.
     *
     * May return null if no right indentation is applied.
     *
     * @return the array of right indents in pixels.
     * @see Layout.Builder#setLeftIndents(int[])
     * @see Layout.Builder#setRightIndents(int[])
     * @see StaticLayout.Builder#setIndents(int[], int[])
     */
    @Nullable
    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
    public final int[] getRightIndents() {
        if (mRightIndents == null) {
            return null;
        }
        int[] newArray = new int[mRightIndents.length];
        System.arraycopy(mRightIndents, 0, newArray, 0, newArray.length);
        return newArray;
    }

    /**
     * Return the justification mode used for creating this layout.
     *
     * @return the justification mode used for creating this layout.
     * @see Layout.Builder#setJustificationMode(int)
     * @see StaticLayout.Builder#setJustificationMode(int)
     */
    @JustificationMode
    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
    public final int getJustificationMode() {
        return mJustificationMode;
    }

    /**
     * Gets the {@link LineBreakConfig} used for creating this layout.
     *
     * Do not modify the returned object.
     *
     * @return The line break config used for creating this layout.
     */
    // not being final because of subclass has already published API.
    @NonNull
    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
    public LineBreakConfig getLineBreakConfig() {
        return mLineBreakConfig;
    }

    /**
     * Returns true if using bounding box as a width, false for using advance as a width.
     *
     * @return True if using bounding box for width, false if using advance for width.
     * @see android.widget.TextView#setUseBoundsForWidth(boolean)
     * @see android.widget.TextView#getUseBoundsForWidth()
     * @see StaticLayout.Builder#setUseBoundsForWidth(boolean)
     * @see DynamicLayout.Builder#setUseBoundsForWidth(boolean)
     */
    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
    public boolean getUseBoundsForWidth() {
        return mUseBoundsForWidth;
    }

    /**
     * Returns true if shifting drawing offset for start overhang.
     *
     * @return True if shifting drawing offset for start overhang.
     * @see android.widget.TextView#setShiftDrawingOffsetForStartOverhang(boolean)
     * @see TextView#getShiftDrawingOffsetForStartOverhang()
     * @see StaticLayout.Builder#setShiftDrawingOffsetForStartOverhang(boolean)
     * @see DynamicLayout.Builder#setShiftDrawingOffsetForStartOverhang(boolean)
     */
    @FlaggedApi(FLAG_USE_BOUNDS_FOR_WIDTH)
    public boolean getShiftDrawingOffsetForStartOverhang() {
        return mShiftDrawingOffsetForStartOverhang;
    }

    /**
     * Get the minimum font metrics used for line spacing.
     *
     * @see android.widget.TextView#setMinimumFontMetrics(Paint.FontMetrics)
     * @see android.widget.TextView#getMinimumFontMetrics()
     * @see Layout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
     * @see StaticLayout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
     * @see DynamicLayout.Builder#setMinimumFontMetrics(Paint.FontMetrics)
     *
     * @return a minimum font metrics. {@code null} for using the value obtained by
     *         {@link Paint#getFontMetricsForLocale(Paint.FontMetrics)}
     */
    @Nullable
    @FlaggedApi(FLAG_FIX_LINE_HEIGHT_FOR_LOCALE)
    public Paint.FontMetrics getMinimumFontMetrics() {
        return mMinimumFontMetrics;
    }

    /**
     * Callback for {@link #forEachCharacterBounds(int, int, int, int, CharacterBoundsListener)}
     */
    private interface CharacterBoundsListener {
        void onCharacterBounds(int index, int lineNum, float left, float top, float right,
                float bottom);

        /** Called after the last character has been sent to {@link #onCharacterBounds}. */
        default void onEnd() {}
    }
}
