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

Commit 259ee0e2 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add LineBreakSpan and merge method"

parents 85e95f50 e4ea1c10
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -17533,17 +17533,21 @@ package android.graphics.text {
  public final class LineBreakConfig {
  public final class LineBreakConfig {
    method public int getLineBreakStyle();
    method public int getLineBreakStyle();
    method public int getLineBreakWordStyle();
    method public int getLineBreakWordStyle();
    method @NonNull public android.graphics.text.LineBreakConfig merge(@NonNull android.graphics.text.LineBreakConfig);
    field public static final int LINE_BREAK_STYLE_LOOSE = 1; // 0x1
    field public static final int LINE_BREAK_STYLE_LOOSE = 1; // 0x1
    field public static final int LINE_BREAK_STYLE_NONE = 0; // 0x0
    field public static final int LINE_BREAK_STYLE_NONE = 0; // 0x0
    field public static final int LINE_BREAK_STYLE_NORMAL = 2; // 0x2
    field public static final int LINE_BREAK_STYLE_NORMAL = 2; // 0x2
    field public static final int LINE_BREAK_STYLE_STRICT = 3; // 0x3
    field public static final int LINE_BREAK_STYLE_STRICT = 3; // 0x3
    field public static final int LINE_BREAK_STYLE_UNSPECIFIED = -1; // 0xffffffff
    field public static final int LINE_BREAK_WORD_STYLE_NONE = 0; // 0x0
    field public static final int LINE_BREAK_WORD_STYLE_NONE = 0; // 0x0
    field public static final int LINE_BREAK_WORD_STYLE_PHRASE = 1; // 0x1
    field public static final int LINE_BREAK_WORD_STYLE_PHRASE = 1; // 0x1
    field public static final int LINE_BREAK_WORD_STYLE_UNSPECIFIED = -1; // 0xffffffff
  }
  }
  public static final class LineBreakConfig.Builder {
  public static final class LineBreakConfig.Builder {
    ctor public LineBreakConfig.Builder();
    ctor public LineBreakConfig.Builder();
    method @NonNull public android.graphics.text.LineBreakConfig build();
    method @NonNull public android.graphics.text.LineBreakConfig build();
    method @NonNull public android.graphics.text.LineBreakConfig.Builder merge(@NonNull android.graphics.text.LineBreakConfig);
    method @NonNull public android.graphics.text.LineBreakConfig.Builder setLineBreakStyle(int);
    method @NonNull public android.graphics.text.LineBreakConfig.Builder setLineBreakStyle(int);
    method @NonNull public android.graphics.text.LineBreakConfig.Builder setLineBreakWordStyle(int);
    method @NonNull public android.graphics.text.LineBreakConfig.Builder setLineBreakWordStyle(int);
  }
  }
@@ -48402,6 +48406,11 @@ package android.text.style {
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    method public void writeToParcel(@NonNull android.os.Parcel, int);
  }
  }
  public class LineBreakConfigSpan {
    ctor public LineBreakConfigSpan(@NonNull android.graphics.text.LineBreakConfig);
    method @NonNull public android.graphics.text.LineBreakConfig getLineBreakConfig();
  }
  public interface LineHeightSpan extends android.text.style.ParagraphStyle android.text.style.WrapTogetherSpan {
  public interface LineHeightSpan extends android.text.style.ParagraphStyle android.text.style.WrapTogetherSpan {
    method public void chooseHeight(CharSequence, int, int, int, int, android.graphics.Paint.FontMetricsInt);
    method public void chooseHeight(CharSequence, int, int, int, int, android.graphics.Paint.FontMetricsInt);
  }
  }
+9 −0
Original line number Original line Diff line number Diff line
@@ -3335,6 +3335,15 @@ package android.text {
    field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig.NamedFamilyList> CREATOR;
    field @NonNull public static final android.os.Parcelable.Creator<android.text.FontConfig.NamedFamilyList> CREATOR;
  }
  }


  public class MeasuredParagraph {
    method @NonNull public static android.text.MeasuredParagraph buildForStaticLayoutTest(@NonNull android.text.TextPaint, @Nullable android.graphics.text.LineBreakConfig, @NonNull CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @NonNull android.text.TextDirectionHeuristic, int, boolean, @Nullable android.text.MeasuredParagraph.StyleRunCallback);
  }

  public static interface MeasuredParagraph.StyleRunCallback {
    method public void onAppendReplacementRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, @FloatRange(from=0) @Px float);
    method public void onAppendStyleRun(@NonNull android.graphics.Paint, @Nullable android.graphics.text.LineBreakConfig, @IntRange(from=0) int, boolean);
  }

  public static final class Selection.MemoryTextWatcher implements android.text.TextWatcher {
  public static final class Selection.MemoryTextWatcher implements android.text.TextWatcher {
    ctor public Selection.MemoryTextWatcher();
    ctor public Selection.MemoryTextWatcher();
    method public void afterTextChanged(android.text.Editable);
    method public void afterTextChanged(android.text.Editable);
+149 −17
Original line number Original line Diff line number Diff line
@@ -20,6 +20,9 @@ import android.annotation.FloatRange;
import android.annotation.IntRange;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.Px;
import android.annotation.SuppressLint;
import android.annotation.TestApi;
import android.graphics.Paint;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Rect;
import android.graphics.text.LineBreakConfig;
import android.graphics.text.LineBreakConfig;
@@ -28,6 +31,7 @@ import android.text.AutoGrowArray.ByteArray;
import android.text.AutoGrowArray.FloatArray;
import android.text.AutoGrowArray.FloatArray;
import android.text.AutoGrowArray.IntArray;
import android.text.AutoGrowArray.IntArray;
import android.text.Layout.Directions;
import android.text.Layout.Directions;
import android.text.style.LineBreakConfigSpan;
import android.text.style.MetricAffectingSpan;
import android.text.style.MetricAffectingSpan;
import android.text.style.ReplacementSpan;
import android.text.style.ReplacementSpan;
import android.util.Pools.SynchronizedPool;
import android.util.Pools.SynchronizedPool;
@@ -57,6 +61,7 @@ import java.util.Arrays;
 * MeasuredParagraph is NOT a thread safe object.
 * MeasuredParagraph is NOT a thread safe object.
 * @hide
 * @hide
 */
 */
@TestApi
public class MeasuredParagraph {
public class MeasuredParagraph {
    private static final char OBJECT_REPLACEMENT_CHARACTER = '\uFFFC';
    private static final char OBJECT_REPLACEMENT_CHARACTER = '\uFFFC';


@@ -73,6 +78,7 @@ public class MeasuredParagraph {
     * Recycle the MeasuredParagraph.
     * Recycle the MeasuredParagraph.
     *
     *
     * Do not call any methods after you call this method.
     * Do not call any methods after you call this method.
     * @hide
     */
     */
    public void recycle() {
    public void recycle() {
        release();
        release();
@@ -126,11 +132,14 @@ public class MeasuredParagraph {
    private @Nullable MeasuredText mMeasuredText;
    private @Nullable MeasuredText mMeasuredText;


    // Following three objects are for avoiding object allocation.
    // Following three objects are for avoiding object allocation.
    private @NonNull TextPaint mCachedPaint = new TextPaint();
    private final @NonNull TextPaint mCachedPaint = new TextPaint();
    private @Nullable Paint.FontMetricsInt mCachedFm;
    private @Nullable Paint.FontMetricsInt mCachedFm;
    private final @NonNull LineBreakConfig.Builder mLineBreakConfigBuilder =
            new LineBreakConfig.Builder();


    /**
    /**
     * Releases internal buffers.
     * Releases internal buffers.
     * @hide
     */
     */
    public void release() {
    public void release() {
        reset();
        reset();
@@ -158,6 +167,7 @@ public class MeasuredParagraph {
     * Returns the length of the paragraph.
     * Returns the length of the paragraph.
     *
     *
     * This is always available.
     * This is always available.
     * @hide
     */
     */
    public int getTextLength() {
    public int getTextLength() {
        return mTextLength;
        return mTextLength;
@@ -167,6 +177,7 @@ public class MeasuredParagraph {
     * Returns the characters to be measured.
     * Returns the characters to be measured.
     *
     *
     * This is always available.
     * This is always available.
     * @hide
     */
     */
    public @NonNull char[] getChars() {
    public @NonNull char[] getChars() {
        return mCopiedBuffer;
        return mCopiedBuffer;
@@ -176,6 +187,7 @@ public class MeasuredParagraph {
     * Returns the paragraph direction.
     * Returns the paragraph direction.
     *
     *
     * This is always available.
     * This is always available.
     * @hide
     */
     */
    public @Layout.Direction int getParagraphDir() {
    public @Layout.Direction int getParagraphDir() {
        return mParaDir;
        return mParaDir;
@@ -185,6 +197,7 @@ public class MeasuredParagraph {
     * Returns the directions.
     * Returns the directions.
     *
     *
     * This is always available.
     * This is always available.
     * @hide
     */
     */
    public Directions getDirections(@IntRange(from = 0) int start,  // inclusive
    public Directions getDirections(@IntRange(from = 0) int start,  // inclusive
                                    @IntRange(from = 0) int end) {  // exclusive
                                    @IntRange(from = 0) int end) {  // exclusive
@@ -202,6 +215,7 @@ public class MeasuredParagraph {
     *
     *
     * This is available only if the MeasuredParagraph is computed with buildForMeasurement.
     * This is available only if the MeasuredParagraph is computed with buildForMeasurement.
     * Returns 0 in other cases.
     * Returns 0 in other cases.
     * @hide
     */
     */
    public @FloatRange(from = 0.0f) float getWholeWidth() {
    public @FloatRange(from = 0.0f) float getWholeWidth() {
        return mWholeWidth;
        return mWholeWidth;
@@ -212,6 +226,7 @@ public class MeasuredParagraph {
     *
     *
     * This is available only if the MeasuredParagraph is computed with buildForMeasurement.
     * This is available only if the MeasuredParagraph is computed with buildForMeasurement.
     * Returns empty array in other cases.
     * Returns empty array in other cases.
     * @hide
     */
     */
    public @NonNull FloatArray getWidths() {
    public @NonNull FloatArray getWidths() {
        return mWidths;
        return mWidths;
@@ -224,6 +239,7 @@ public class MeasuredParagraph {
     *
     *
     * This is available only if the MeasuredParagraph is computed with buildForStaticLayout.
     * This is available only if the MeasuredParagraph is computed with buildForStaticLayout.
     * Returns empty array in other cases.
     * Returns empty array in other cases.
     * @hide
     */
     */
    public @NonNull IntArray getSpanEndCache() {
    public @NonNull IntArray getSpanEndCache() {
        return mSpanEndCache;
        return mSpanEndCache;
@@ -236,6 +252,7 @@ public class MeasuredParagraph {
     *
     *
     * This is available only if the MeasuredParagraph is computed with buildForStaticLayout.
     * This is available only if the MeasuredParagraph is computed with buildForStaticLayout.
     * Returns empty array in other cases.
     * Returns empty array in other cases.
     * @hide
     */
     */
    public @NonNull IntArray getFontMetrics() {
    public @NonNull IntArray getFontMetrics() {
        return mFontMetrics;
        return mFontMetrics;
@@ -246,6 +263,7 @@ public class MeasuredParagraph {
     *
     *
     * This is available only if the MeasuredParagraph is computed with buildForStaticLayout.
     * This is available only if the MeasuredParagraph is computed with buildForStaticLayout.
     * Returns null in other cases.
     * Returns null in other cases.
     * @hide
     */
     */
    public MeasuredText getMeasuredText() {
    public MeasuredText getMeasuredText() {
        return mMeasuredText;
        return mMeasuredText;
@@ -259,6 +277,7 @@ public class MeasuredParagraph {
     *
     *
     * @param start the inclusive start offset of the target region in the text
     * @param start the inclusive start offset of the target region in the text
     * @param end the exclusive end offset of the target region in the text
     * @param end the exclusive end offset of the target region in the text
     * @hide
     */
     */
    public float getWidth(int start, int end) {
    public float getWidth(int start, int end) {
        if (mMeasuredText == null) {
        if (mMeasuredText == null) {
@@ -280,6 +299,7 @@ public class MeasuredParagraph {
     * at (0, 0).
     * at (0, 0).
     *
     *
     * This is available only if the MeasuredParagraph is computed with buildForStaticLayout.
     * This is available only if the MeasuredParagraph is computed with buildForStaticLayout.
     * @hide
     */
     */
    public void getBounds(@IntRange(from = 0) int start, @IntRange(from = 0) int end,
    public void getBounds(@IntRange(from = 0) int start, @IntRange(from = 0) int end,
            @NonNull Rect bounds) {
            @NonNull Rect bounds) {
@@ -290,6 +310,7 @@ public class MeasuredParagraph {
     * Retrieves the font metrics for the given range.
     * Retrieves the font metrics for the given range.
     *
     *
     * This is available only if the MeasuredParagraph is computed with buildForStaticLayout.
     * This is available only if the MeasuredParagraph is computed with buildForStaticLayout.
     * @hide
     */
     */
    public void getFontMetricsInt(@IntRange(from = 0) int start, @IntRange(from = 0) int end,
    public void getFontMetricsInt(@IntRange(from = 0) int start, @IntRange(from = 0) int end,
            @NonNull Paint.FontMetricsInt fmi) {
            @NonNull Paint.FontMetricsInt fmi) {
@@ -300,6 +321,7 @@ public class MeasuredParagraph {
     * Returns a width of the character at the offset.
     * Returns a width of the character at the offset.
     *
     *
     * This is available only if the MeasuredParagraph is computed with buildForStaticLayout.
     * This is available only if the MeasuredParagraph is computed with buildForStaticLayout.
     * @hide
     */
     */
    public float getCharWidthAt(@IntRange(from = 0) int offset) {
    public float getCharWidthAt(@IntRange(from = 0) int offset) {
        return mMeasuredText.getCharWidthAt(offset);
        return mMeasuredText.getCharWidthAt(offset);
@@ -318,6 +340,7 @@ public class MeasuredParagraph {
     * @param recycle pass existing MeasuredParagraph if you want to recycle it.
     * @param recycle pass existing MeasuredParagraph if you want to recycle it.
     *
     *
     * @return measured text
     * @return measured text
     * @hide
     */
     */
    public static @NonNull MeasuredParagraph buildForBidi(@NonNull CharSequence text,
    public static @NonNull MeasuredParagraph buildForBidi(@NonNull CharSequence text,
                                                     @IntRange(from = 0) int start,
                                                     @IntRange(from = 0) int start,
@@ -343,6 +366,7 @@ public class MeasuredParagraph {
     * @param recycle pass existing MeasuredParagraph if you want to recycle it.
     * @param recycle pass existing MeasuredParagraph if you want to recycle it.
     *
     *
     * @return measured text
     * @return measured text
     * @hide
     */
     */
    public static @NonNull MeasuredParagraph buildForMeasurement(@NonNull TextPaint paint,
    public static @NonNull MeasuredParagraph buildForMeasurement(@NonNull TextPaint paint,
                                                            @NonNull CharSequence text,
                                                            @NonNull CharSequence text,
@@ -361,24 +385,52 @@ public class MeasuredParagraph {
        if (mt.mSpanned == null) {
        if (mt.mSpanned == null) {
            // No style change by MetricsAffectingSpan. Just measure all text.
            // No style change by MetricsAffectingSpan. Just measure all text.
            mt.applyMetricsAffectingSpan(
            mt.applyMetricsAffectingSpan(
                    paint, null /* lineBreakConfig */, null /* spans */, start, end,
                    paint, null /* lineBreakConfig */, null /* spans */, null /* lbcSpans */,
                    null /* native builder ptr */);
                    start, end, null /* native builder ptr */, null);
        } else {
        } else {
            // There may be a MetricsAffectingSpan. Split into span transitions and apply styles.
            // There may be a MetricsAffectingSpan. Split into span transitions and apply styles.
            int spanEnd;
            int spanEnd;
            for (int spanStart = start; spanStart < end; spanStart = spanEnd) {
            for (int spanStart = start; spanStart < end; spanStart = spanEnd) {
                spanEnd = mt.mSpanned.nextSpanTransition(spanStart, end, MetricAffectingSpan.class);
                int maSpanEnd = mt.mSpanned.nextSpanTransition(spanStart, end,
                        MetricAffectingSpan.class);
                int lbcSpanEnd = mt.mSpanned.nextSpanTransition(spanStart, end,
                        LineBreakConfigSpan.class);
                spanEnd = Math.min(maSpanEnd, lbcSpanEnd);
                MetricAffectingSpan[] spans = mt.mSpanned.getSpans(spanStart, spanEnd,
                MetricAffectingSpan[] spans = mt.mSpanned.getSpans(spanStart, spanEnd,
                        MetricAffectingSpan.class);
                        MetricAffectingSpan.class);
                LineBreakConfigSpan[] lbcSpans = mt.mSpanned.getSpans(spanStart, spanEnd,
                        LineBreakConfigSpan.class);
                spans = TextUtils.removeEmptySpans(spans, mt.mSpanned, MetricAffectingSpan.class);
                spans = TextUtils.removeEmptySpans(spans, mt.mSpanned, MetricAffectingSpan.class);
                lbcSpans = TextUtils.removeEmptySpans(lbcSpans, mt.mSpanned,
                        LineBreakConfigSpan.class);
                mt.applyMetricsAffectingSpan(
                mt.applyMetricsAffectingSpan(
                        paint, null /* line break config */, spans, spanStart, spanEnd,
                        paint, null /* line break config */, spans, lbcSpans, spanStart, spanEnd,
                        null /* native builder ptr */);
                        null /* native builder ptr */, null);
            }
            }
        }
        }
        return mt;
        return mt;
    }
    }


    /**
     * A test interface for observing the style run calculation.
     * @hide
     */
    @TestApi
    public interface StyleRunCallback {
        /**
         * Called when a single style run is identified.
         */
        void onAppendStyleRun(@NonNull Paint paint,
                @Nullable LineBreakConfig lineBreakConfig, @IntRange(from = 0) int length,
                boolean isRtl);

        /**
         * Called when a single replacement run is identified.
         */
        void onAppendReplacementRun(@NonNull Paint paint,
                @IntRange(from = 0) int length, @Px @FloatRange(from = 0) float width);
    }

    /**
    /**
     * Generates new MeasuredParagraph for StaticLayout.
     * Generates new MeasuredParagraph for StaticLayout.
     *
     *
@@ -397,6 +449,7 @@ public class MeasuredParagraph {
     * @param recycle pass existing MeasuredParagraph if you want to recycle it.
     * @param recycle pass existing MeasuredParagraph if you want to recycle it.
     *
     *
     * @return measured text
     * @return measured text
     * @hide
     */
     */
    public static @NonNull MeasuredParagraph buildForStaticLayout(
    public static @NonNull MeasuredParagraph buildForStaticLayout(
            @NonNull TextPaint paint,
            @NonNull TextPaint paint,
@@ -409,6 +462,57 @@ public class MeasuredParagraph {
            boolean computeLayout,
            boolean computeLayout,
            @Nullable MeasuredParagraph hint,
            @Nullable MeasuredParagraph hint,
            @Nullable MeasuredParagraph recycle) {
            @Nullable MeasuredParagraph recycle) {
        return buildForStaticLayoutInternal(paint, lineBreakConfig, text, start, end, textDir,
                hyphenationMode, computeLayout, hint, recycle, null);
    }

    /**
     * Generates new MeasuredParagraph for StaticLayout.
     *
     * If recycle is null, this returns new instance. If recycle is not null, this fills computed
     * result to recycle and returns recycle.
     *
     * @param paint the paint to be used for rendering the text.
     * @param lineBreakConfig the line break configuration for text wrapping.
     * @param text the character sequence to be measured
     * @param start the inclusive start offset of the target region in the text
     * @param end the exclusive end offset of the target region in the text
     * @param textDir the text direction
     * @param hyphenationMode a hyphenation mode
     * @param computeLayout true if need to compute full layout, otherwise false.
     *
     * @return measured text
     * @hide
     */
    @SuppressLint("ExecutorRegistration")
    @TestApi
    @NonNull
    public static MeasuredParagraph buildForStaticLayoutTest(
            @NonNull TextPaint paint,
            @Nullable LineBreakConfig lineBreakConfig,
            @NonNull CharSequence text,
            @IntRange(from = 0) int start,
            @IntRange(from = 0) int end,
            @NonNull TextDirectionHeuristic textDir,
            int hyphenationMode,
            boolean computeLayout,
            @Nullable StyleRunCallback testCallback) {
        return buildForStaticLayoutInternal(paint, lineBreakConfig, text, start, end, textDir,
                hyphenationMode, computeLayout, null, null, testCallback);
    }

    private static @NonNull MeasuredParagraph buildForStaticLayoutInternal(
            @NonNull TextPaint paint,
            @Nullable LineBreakConfig lineBreakConfig,
            @NonNull CharSequence text,
            @IntRange(from = 0) int start,
            @IntRange(from = 0) int end,
            @NonNull TextDirectionHeuristic textDir,
            int hyphenationMode,
            boolean computeLayout,
            @Nullable MeasuredParagraph hint,
            @Nullable MeasuredParagraph recycle,
            @Nullable StyleRunCallback testCallback) {
        final MeasuredParagraph mt = recycle == null ? obtain() : recycle;
        final MeasuredParagraph mt = recycle == null ? obtain() : recycle;
        mt.resetAndAnalyzeBidi(text, start, end, textDir);
        mt.resetAndAnalyzeBidi(text, start, end, textDir);
        final MeasuredText.Builder builder;
        final MeasuredText.Builder builder;
@@ -426,23 +530,29 @@ public class MeasuredParagraph {
        } else {
        } else {
            if (mt.mSpanned == null) {
            if (mt.mSpanned == null) {
                // No style change by MetricsAffectingSpan. Just measure all text.
                // No style change by MetricsAffectingSpan. Just measure all text.
                mt.applyMetricsAffectingSpan(paint, lineBreakConfig, null /* spans */, start, end,
                mt.applyMetricsAffectingSpan(paint, lineBreakConfig, null /* spans */, null,
                        builder);
                        start, end, builder, testCallback);
                mt.mSpanEndCache.append(end);
                mt.mSpanEndCache.append(end);
            } else {
            } else {
                // There may be a MetricsAffectingSpan. Split into span transitions and apply
                // There may be a MetricsAffectingSpan. Split into span transitions and apply
                // styles.
                // styles.
                int spanEnd;
                int spanEnd;
                for (int spanStart = start; spanStart < end; spanStart = spanEnd) {
                for (int spanStart = start; spanStart < end; spanStart = spanEnd) {
                    spanEnd = mt.mSpanned.nextSpanTransition(spanStart, end,
                    int maSpanEnd = mt.mSpanned.nextSpanTransition(spanStart, end,
                                                             MetricAffectingSpan.class);
                                                             MetricAffectingSpan.class);
                    int lbcSpanEnd = mt.mSpanned.nextSpanTransition(spanStart, end,
                            LineBreakConfigSpan.class);
                    spanEnd = Math.min(maSpanEnd, lbcSpanEnd);
                    MetricAffectingSpan[] spans = mt.mSpanned.getSpans(spanStart, spanEnd,
                    MetricAffectingSpan[] spans = mt.mSpanned.getSpans(spanStart, spanEnd,
                            MetricAffectingSpan.class);
                            MetricAffectingSpan.class);
                    LineBreakConfigSpan[] lbcSpans = mt.mSpanned.getSpans(spanStart, spanEnd,
                            LineBreakConfigSpan.class);
                    spans = TextUtils.removeEmptySpans(spans, mt.mSpanned,
                    spans = TextUtils.removeEmptySpans(spans, mt.mSpanned,
                                                       MetricAffectingSpan.class);
                                                       MetricAffectingSpan.class);
                    // TODO: Update line break config with spans.
                    lbcSpans = TextUtils.removeEmptySpans(lbcSpans, mt.mSpanned,
                    mt.applyMetricsAffectingSpan(paint, lineBreakConfig, spans, spanStart, spanEnd,
                                                       LineBreakConfigSpan.class);
                            builder);
                    mt.applyMetricsAffectingSpan(paint, lineBreakConfig, spans, lbcSpans, spanStart,
                            spanEnd, builder, testCallback);
                    mt.mSpanEndCache.append(spanEnd);
                    mt.mSpanEndCache.append(spanEnd);
                }
                }
            }
            }
@@ -519,7 +629,8 @@ public class MeasuredParagraph {
                                     @IntRange(from = 0) int start,  // inclusive, in copied buffer
                                     @IntRange(from = 0) int start,  // inclusive, in copied buffer
                                     @IntRange(from = 0) int end,  // exclusive, in copied buffer
                                     @IntRange(from = 0) int end,  // exclusive, in copied buffer
                                     @NonNull TextPaint paint,
                                     @NonNull TextPaint paint,
                                     @Nullable MeasuredText.Builder builder) {
                                     @Nullable MeasuredText.Builder builder,
                                     @Nullable StyleRunCallback testCallback) {
        // Use original text. Shouldn't matter.
        // Use original text. Shouldn't matter.
        // TODO: passing uninitizlied FontMetrics to developers. Do we need to keep this for
        // TODO: passing uninitizlied FontMetrics to developers. Do we need to keep this for
        //       backward compatibility? or Should we initialize them for getFontMetricsInt?
        //       backward compatibility? or Should we initialize them for getFontMetricsInt?
@@ -535,13 +646,17 @@ public class MeasuredParagraph {
        } else {
        } else {
            builder.appendReplacementRun(paint, end - start, width);
            builder.appendReplacementRun(paint, end - start, width);
        }
        }
        if (testCallback != null) {
            testCallback.onAppendReplacementRun(paint, end - start, width);
        }
    }
    }


    private void applyStyleRun(@IntRange(from = 0) int start,  // inclusive, in copied buffer
    private void applyStyleRun(@IntRange(from = 0) int start,  // inclusive, in copied buffer
                               @IntRange(from = 0) int end,  // exclusive, in copied buffer
                               @IntRange(from = 0) int end,  // exclusive, in copied buffer
                               @NonNull TextPaint paint,
                               @NonNull TextPaint paint,
                               @Nullable LineBreakConfig config,
                               @Nullable LineBreakConfig config,
                               @Nullable MeasuredText.Builder builder) {
                               @Nullable MeasuredText.Builder builder,
                               @Nullable StyleRunCallback testCallback) {


        if (mLtrWithoutBidi) {
        if (mLtrWithoutBidi) {
            // If the whole text is LTR direction, just apply whole region.
            // If the whole text is LTR direction, just apply whole region.
@@ -552,6 +667,9 @@ public class MeasuredParagraph {
            } else {
            } else {
                builder.appendStyleRun(paint, config, end - start, false /* isRtl */);
                builder.appendStyleRun(paint, config, end - start, false /* isRtl */);
            }
            }
            if (testCallback != null) {
                testCallback.onAppendStyleRun(paint, config, end - start, false);
            }
        } else {
        } else {
            // If there is multiple bidi levels, split into individual bidi level and apply style.
            // If there is multiple bidi levels, split into individual bidi level and apply style.
            byte level = mLevels.get(start);
            byte level = mLevels.get(start);
@@ -568,6 +686,9 @@ public class MeasuredParagraph {
                    } else {
                    } else {
                        builder.appendStyleRun(paint, config, levelEnd - levelStart, isRtl);
                        builder.appendStyleRun(paint, config, levelEnd - levelStart, isRtl);
                    }
                    }
                    if (testCallback != null) {
                        testCallback.onAppendStyleRun(paint, config, levelEnd - levelStart, isRtl);
                    }
                    if (levelEnd == end) {
                    if (levelEnd == end) {
                        break;
                        break;
                    }
                    }
@@ -582,9 +703,11 @@ public class MeasuredParagraph {
            @NonNull TextPaint paint,
            @NonNull TextPaint paint,
            @Nullable LineBreakConfig lineBreakConfig,
            @Nullable LineBreakConfig lineBreakConfig,
            @Nullable MetricAffectingSpan[] spans,
            @Nullable MetricAffectingSpan[] spans,
            @Nullable LineBreakConfigSpan[] lbcSpans,
            @IntRange(from = 0) int start,  // inclusive, in original text buffer
            @IntRange(from = 0) int start,  // inclusive, in original text buffer
            @IntRange(from = 0) int end,  // exclusive, in original text buffer
            @IntRange(from = 0) int end,  // exclusive, in original text buffer
            @Nullable MeasuredText.Builder builder) {
            @Nullable MeasuredText.Builder builder,
            @Nullable StyleRunCallback testCallback) {
        mCachedPaint.set(paint);
        mCachedPaint.set(paint);
        // XXX paint should not have a baseline shift, but...
        // XXX paint should not have a baseline shift, but...
        mCachedPaint.baselineShift = 0;
        mCachedPaint.baselineShift = 0;
@@ -609,6 +732,14 @@ public class MeasuredParagraph {
            }
            }
        }
        }


        if (lbcSpans != null) {
            mLineBreakConfigBuilder.reset(lineBreakConfig);
            for (LineBreakConfigSpan lbcSpan : lbcSpans) {
                mLineBreakConfigBuilder.merge(lbcSpan.getLineBreakConfig());
            }
            lineBreakConfig = mLineBreakConfigBuilder.build();
        }

        final int startInCopiedBuffer = start - mTextStart;
        final int startInCopiedBuffer = start - mTextStart;
        final int endInCopiedBuffer = end - mTextStart;
        final int endInCopiedBuffer = end - mTextStart;


@@ -618,10 +749,10 @@ public class MeasuredParagraph {


        if (replacement != null) {
        if (replacement != null) {
            applyReplacementRun(replacement, startInCopiedBuffer, endInCopiedBuffer, mCachedPaint,
            applyReplacementRun(replacement, startInCopiedBuffer, endInCopiedBuffer, mCachedPaint,
                    builder);
                    builder, testCallback);
        } else {
        } else {
            applyStyleRun(startInCopiedBuffer, endInCopiedBuffer, mCachedPaint,
            applyStyleRun(startInCopiedBuffer, endInCopiedBuffer, mCachedPaint,
                    lineBreakConfig, builder);
                    lineBreakConfig, builder, testCallback);
        }
        }


        if (needFontMetrics) {
        if (needFontMetrics) {
@@ -690,6 +821,7 @@ public class MeasuredParagraph {


    /**
    /**
     * This only works if the MeasuredParagraph is computed with buildForStaticLayout.
     * This only works if the MeasuredParagraph is computed with buildForStaticLayout.
     * @hide
     */
     */
    public @IntRange(from = 0) int getMemoryUsage() {
    public @IntRange(from = 0) int getMemoryUsage() {
        return mMeasuredText.getMemoryUsage();
        return mMeasuredText.getMemoryUsage();
+6 −10
Original line number Original line Diff line number Diff line
@@ -329,22 +329,17 @@ public class PrecomputedText implements Spannable {
        @Override
        @Override
        public int hashCode() {
        public int hashCode() {
            // TODO: implement MinikinPaint::hashCode and use it to keep consistency with equals.
            // TODO: implement MinikinPaint::hashCode and use it to keep consistency with equals.
            int lineBreakStyle = (mLineBreakConfig != null)
                    ? mLineBreakConfig.getLineBreakStyle() : LineBreakConfig.LINE_BREAK_STYLE_NONE;
            return Objects.hash(mPaint.getTextSize(), mPaint.getTextScaleX(), mPaint.getTextSkewX(),
            return Objects.hash(mPaint.getTextSize(), mPaint.getTextScaleX(), mPaint.getTextSkewX(),
                    mPaint.getLetterSpacing(), mPaint.getWordSpacing(), mPaint.getFlags(),
                    mPaint.getLetterSpacing(), mPaint.getWordSpacing(), mPaint.getFlags(),
                    mPaint.getTextLocales(), mPaint.getTypeface(),
                    mPaint.getTextLocales(), mPaint.getTypeface(),
                    mPaint.getFontVariationSettings(), mPaint.isElegantTextHeight(), mTextDir,
                    mPaint.getFontVariationSettings(), mPaint.isElegantTextHeight(), mTextDir,
                    mBreakStrategy, mHyphenationFrequency, lineBreakStyle);
                    mBreakStrategy, mHyphenationFrequency,
                    LineBreakConfig.getResolvedLineBreakStyle(mLineBreakConfig),
                    LineBreakConfig.getResolvedLineBreakWordStyle(mLineBreakConfig));
        }
        }


        @Override
        @Override
        public String toString() {
        public String toString() {
            int lineBreakStyle = (mLineBreakConfig != null)
                    ? mLineBreakConfig.getLineBreakStyle() : LineBreakConfig.LINE_BREAK_STYLE_NONE;
            int lineBreakWordStyle = (mLineBreakConfig != null)
                    ? mLineBreakConfig.getLineBreakWordStyle()
                            : LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE;
            return "{"
            return "{"
                + "textSize=" + mPaint.getTextSize()
                + "textSize=" + mPaint.getTextSize()
                + ", textScaleX=" + mPaint.getTextScaleX()
                + ", textScaleX=" + mPaint.getTextScaleX()
@@ -357,8 +352,9 @@ public class PrecomputedText implements Spannable {
                + ", textDir=" + mTextDir
                + ", textDir=" + mTextDir
                + ", breakStrategy=" + mBreakStrategy
                + ", breakStrategy=" + mBreakStrategy
                + ", hyphenationFrequency=" + mHyphenationFrequency
                + ", hyphenationFrequency=" + mHyphenationFrequency
                + ", lineBreakStyle=" + lineBreakStyle
                + ", lineBreakStyle=" + LineBreakConfig.getResolvedLineBreakStyle(mLineBreakConfig)
                + ", lineBreakWordStyle=" + lineBreakWordStyle
                + ", lineBreakWordStyle="
                    + LineBreakConfig.getResolvedLineBreakWordStyle(mLineBreakConfig)
                + "}";
                + "}";
        }
        }
    };
    };
+1 −1
Original line number Original line Diff line number Diff line
@@ -448,7 +448,7 @@ public class StaticLayout extends Layout {


        private void reviseLineBreakConfig() {
        private void reviseLineBreakConfig() {
            boolean autoPhraseBreaking = mLineBreakConfig.getAutoPhraseBreaking();
            boolean autoPhraseBreaking = mLineBreakConfig.getAutoPhraseBreaking();
            int wordStyle = mLineBreakConfig.getLineBreakWordStyle();
            int wordStyle = LineBreakConfig.getResolvedLineBreakWordStyle(mLineBreakConfig);
            if (autoPhraseBreaking) {
            if (autoPhraseBreaking) {
                if (wordStyle != LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE) {
                if (wordStyle != LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE) {
                    if (shouldEnablePhraseBreaking()) {
                    if (shouldEnablePhraseBreaking()) {
Loading