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

Commit 396c7894 authored by James.cf Lin's avatar James.cf Lin Committed by James Lin
Browse files

Update the text wrapping API.

1) Update the LineBreakConfig class to be immutable.
2) Do not return null in the PrecomputedText.Params#getLineBreaiConfig API

Bug: 216638444
Test: atest TextViewTest; atest MeasuredTextTest; atest PrecomputedTextTest; atest TextViewPrecomputedTextTest; atest StaticLayoutLineBreakingVariantsTest
Merged-In: I93bcb6ebc35344e34e9bb8a24df375aa7b3a8d81
Merged-In: I07766137ff6639c7d4acaad07dbcf11a2841cdb0
Change-Id: I07766137ff6639c7d4acaad07dbcf11a2841cdb0
parent dac2c8c6
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -16399,12 +16399,8 @@ package android.graphics.pdf {
package android.graphics.text {
  public final class LineBreakConfig {
    ctor public LineBreakConfig();
    method public int getLineBreakStyle();
    method public int getLineBreakWordStyle();
    method public void set(@NonNull android.graphics.text.LineBreakConfig);
    method public void setLineBreakStyle(int);
    method public void setLineBreakWordStyle(int);
    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_NORMAL = 2; // 0x2
@@ -16413,6 +16409,13 @@ package android.graphics.text {
    field public static final int LINE_BREAK_WORD_STYLE_PHRASE = 1; // 0x1
  }
  public static final class LineBreakConfig.Builder {
    ctor public LineBreakConfig.Builder();
    method @NonNull public android.graphics.text.LineBreakConfig build();
    method @NonNull public android.graphics.text.LineBreakConfig.Builder setLineBreakStyle(int);
    method @NonNull public android.graphics.text.LineBreakConfig.Builder setLineBreakWordStyle(int);
  }
  public class LineBreaker {
    method @NonNull public android.graphics.text.LineBreaker.Result computeLineBreaks(@NonNull android.graphics.text.MeasuredText, @NonNull android.graphics.text.LineBreaker.ParagraphConstraints, @IntRange(from=0) int);
    field public static final int BREAK_STRATEGY_BALANCED = 2; // 0x2
@@ -45061,7 +45064,7 @@ package android.text {
  public static final class PrecomputedText.Params {
    method public int getBreakStrategy();
    method public int getHyphenationFrequency();
    method @Nullable public android.graphics.text.LineBreakConfig getLineBreakConfig();
    method @NonNull public android.graphics.text.LineBreakConfig getLineBreakConfig();
    method @NonNull public android.text.TextDirectionHeuristic getTextDirection();
    method @NonNull public android.text.TextPaint getTextPaint();
  }
@@ -57351,7 +57354,8 @@ package android.widget {
    method public final android.text.Layout getLayout();
    method public float getLetterSpacing();
    method public int getLineBounds(int, android.graphics.Rect);
    method @NonNull public android.graphics.text.LineBreakConfig getLineBreakConfig();
    method public int getLineBreakStyle();
    method public int getLineBreakWordStyle();
    method public int getLineCount();
    method public int getLineHeight();
    method public float getLineSpacingExtra();
@@ -57479,7 +57483,8 @@ package android.widget {
    method public void setKeyListener(android.text.method.KeyListener);
    method public void setLastBaselineToBottomHeight(@IntRange(from=0) @Px int);
    method public void setLetterSpacing(float);
    method public void setLineBreakConfig(@NonNull android.graphics.text.LineBreakConfig);
    method public void setLineBreakStyle(int);
    method public void setLineBreakWordStyle(int);
    method public void setLineHeight(@IntRange(from=0) @Px int);
    method public void setLineSpacing(float, float);
    method public void setLines(int);
+9 −31
Original line number Diff line number Diff line
@@ -99,7 +99,7 @@ public class PrecomputedText implements Spannable {
        private final @Layout.HyphenationFrequency int mHyphenationFrequency;

        // The line break configuration for calculating text wrapping.
        private final @Nullable LineBreakConfig mLineBreakConfig;
        private final @NonNull LineBreakConfig mLineBreakConfig;

        /**
         * A builder for creating {@link Params}.
@@ -119,7 +119,7 @@ public class PrecomputedText implements Spannable {
                    Layout.HYPHENATION_FREQUENCY_NORMAL;

            // The line break configuration for calculating text wrapping.
            private @Nullable LineBreakConfig mLineBreakConfig;
            private @NonNull LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;

            /**
             * Builder constructor.
@@ -212,7 +212,7 @@ public class PrecomputedText implements Spannable {
        // For the external developers, use Builder instead.
        /** @hide */
        public Params(@NonNull TextPaint paint,
                @Nullable LineBreakConfig lineBreakConfig,
                @NonNull LineBreakConfig lineBreakConfig,
                @NonNull TextDirectionHeuristic textDir,
                @Layout.BreakStrategy int strategy,
                @Layout.HyphenationFrequency int frequency) {
@@ -260,11 +260,12 @@ public class PrecomputedText implements Spannable {
        }

        /**
         * Return the line break configuration for this text.
         * Returns the {@link LineBreakConfig} for this text.
         *
         * @return the current line break configuration, null if no line break configuration is set.
         * @return the current line break configuration. The {@link LineBreakConfig} with default
         * values will be returned if no line break configuration is set.
         */
        public @Nullable LineBreakConfig getLineBreakConfig() {
        public @NonNull LineBreakConfig getLineBreakConfig() {
            return mLineBreakConfig;
        }

@@ -297,9 +298,9 @@ public class PrecomputedText implements Spannable {
        /** @hide */
        public @CheckResultUsableResult int checkResultUsable(@NonNull TextPaint paint,
                @NonNull TextDirectionHeuristic textDir, @Layout.BreakStrategy int strategy,
                @Layout.HyphenationFrequency int frequency, @Nullable LineBreakConfig lbConfig) {
                @Layout.HyphenationFrequency int frequency, @NonNull LineBreakConfig lbConfig) {
            if (mBreakStrategy == strategy && mHyphenationFrequency == frequency
                    && isLineBreakEquals(mLineBreakConfig, lbConfig)
                    && mLineBreakConfig.equals(lbConfig)
                    && mPaint.equalsForTextMeasurement(paint)) {
                return mTextDir == textDir ? USABLE : NEED_RECOMPUTE;
            } else {
@@ -307,29 +308,6 @@ public class PrecomputedText implements Spannable {
            }
        }

        /**
         * Check the two LineBreakConfig instances are equal.
         * This method assumes they are equal if one parameter is null and the other parameter has
         * a LineBreakStyle value of LineBreakConfig.LINE_BREAK_STYLE_NONE.
         *
         * @param o1 the first LineBreakConfig instance.
         * @param o2 the second LineBreakConfig instance.
         * @return true if the two LineBreakConfig instances are equal.
         */
        private boolean isLineBreakEquals(LineBreakConfig o1, LineBreakConfig o2) {
            if (Objects.equals(o1, o2)) {
                return true;
            }
            if (o1 == null && (o2 != null
                    && o2.getLineBreakStyle() == LineBreakConfig.LINE_BREAK_STYLE_NONE)) {
                return true;
            } else if (o2 == null && (o1 != null
                    && o1.getLineBreakStyle() == LineBreakConfig.LINE_BREAK_STYLE_NONE)) {
                return true;
            }
            return false;
        }

        /**
         * Check if the same text layout.
         *
+4 −2
Original line number Diff line number Diff line
@@ -112,6 +112,7 @@ public class StaticLayout extends Layout {
            b.mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE;
            b.mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE;
            b.mJustificationMode = Layout.JUSTIFICATION_MODE_NONE;
            b.mLineBreakConfig = LineBreakConfig.NONE;
            return b;
        }

@@ -410,7 +411,8 @@ public class StaticLayout extends Layout {
         *
         * @param lineBreakConfig the line break configuration for text wrapping.
         * @return this builder, useful for chaining.
         * @see android.widget.TextView#setLineBreakConfig
         * @see android.widget.TextView#setLineBreakStyle
         * @see android.widget.TextView#setLineBreakWordStyle
         */
        @NonNull
        public Builder setLineBreakConfig(@NonNull LineBreakConfig lineBreakConfig) {
@@ -454,7 +456,7 @@ public class StaticLayout extends Layout {
        @Nullable private int[] mRightIndents;
        private int mJustificationMode;
        private boolean mAddLastLineLineSpacing;
        private LineBreakConfig mLineBreakConfig;
        private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;

        private final Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();

+76 −54
Original line number Diff line number Diff line
@@ -788,7 +788,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    private Layout mLayout;
    private boolean mLocalesChanged = false;
    private int mTextSizeUnit = -1;
    private LineBreakConfig mLineBreakConfig = new LineBreakConfig();
    private int mLineBreakStyle = DEFAULT_LINE_BREAK_STYLE;
    private int mLineBreakWordStyle = DEFAULT_LINE_BREAK_WORD_STYLE;
    // This is used to reflect the current user preference for changing font weight and making text
    // more bold.
@@ -1457,13 +1458,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                    break;
                case com.android.internal.R.styleable.TextView_lineBreakStyle:
                    mLineBreakConfig.setLineBreakStyle(
                            a.getInt(attr, LineBreakConfig.LINE_BREAK_STYLE_NONE));
                    mLineBreakStyle = a.getInt(attr, LineBreakConfig.LINE_BREAK_STYLE_NONE);
                    break;
                case com.android.internal.R.styleable.TextView_lineBreakWordStyle:
                    mLineBreakConfig.setLineBreakWordStyle(
                            a.getInt(attr, LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE));
                    mLineBreakWordStyle = a.getInt(attr,
                            LineBreakConfig.LINE_BREAK_WORD_STYLE_NONE);
                    break;
                case com.android.internal.R.styleable.TextView_autoSizeTextType:
@@ -4301,13 +4301,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            @LineBreakConfig.LineBreakStyle int lineBreakStyle,
            @LineBreakConfig.LineBreakWordStyle int lineBreakWordStyle) {
        boolean updated = false;
        if (isLineBreakStyleSpecified && mLineBreakConfig.getLineBreakStyle() != lineBreakStyle) {
            mLineBreakConfig.setLineBreakStyle(lineBreakStyle);
        if (isLineBreakStyleSpecified && mLineBreakStyle != lineBreakStyle) {
            mLineBreakStyle = lineBreakStyle;
            updated = true;
        }
        if (isLineBreakWordStyleSpecified
                && mLineBreakConfig.getLineBreakWordStyle() != lineBreakWordStyle) {
            mLineBreakConfig.setLineBreakWordStyle(lineBreakWordStyle);
        if (isLineBreakWordStyleSpecified && mLineBreakWordStyle != lineBreakWordStyle) {
            mLineBreakWordStyle = lineBreakWordStyle;
            updated = true;
        }
        if (updated && mLayout != null) {
@@ -4871,50 +4870,72 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    }
    /**
     * Sets line break configuration indicates which strategy needs to be used when calculating the
     * text wrapping.
     * <P>
     * There are two types of line break rules that can be configured at the same time. One is
     * line break style(lb) and the other is line break word style(lw). The line break style
     * affects rule-based breaking. The line break word style affects dictionary-based breaking
     * and provide phrase-based breaking opportunities. There are several types for the
     * line break style:
     * Set the line break style for text wrapping.
     *
     * The line break style to indicates the line break strategies can be used when
     * calculating the text wrapping. The line break style affects rule-based breaking. It
     * specifies the strictness of line-breaking rules.
     * There are several types for the line break style:
     * {@link LineBreakConfig#LINE_BREAK_STYLE_LOOSE},
     * {@link LineBreakConfig#LINE_BREAK_STYLE_NORMAL} and
     * {@link LineBreakConfig#LINE_BREAK_STYLE_STRICT}.
     * The type for the line break word style is
     * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_PHRASE}.
     * The default values of the line break style and the line break word style are
     * {@link LineBreakConfig#LINE_BREAK_STYLE_NONE} and
     * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_NONE} respectively, indicating that no line
     * breaking rules are specified.
     * See <a href="https://drafts.csswg.org/css-text/#line-break-property">
     * {@link LineBreakConfig#LINE_BREAK_STYLE_STRICT}. The default values of the line break style
     * is {@link LineBreakConfig#LINE_BREAK_STYLE_NONE}, indicating no breaking rule is specified.
     * See <a href="https://www.w3.org/TR/css-text-3/#line-break-property">
     *         the line-break property</a>
     *
     * @param lineBreakConfig the line break config for text wrapping.
     * @param lineBreakStyle the line break style for the text.
     */
    public void setLineBreakConfig(@NonNull LineBreakConfig lineBreakConfig) {
        Objects.requireNonNull(lineBreakConfig);
        if (mLineBreakConfig.equals(lineBreakConfig)) {
            return;
    public void setLineBreakStyle(@LineBreakConfig.LineBreakStyle int lineBreakStyle) {
        if (mLineBreakStyle != lineBreakStyle) {
            mLineBreakStyle = lineBreakStyle;
            if (mLayout != null) {
                nullLayouts();
                requestLayout();
                invalidate();
            }
        mLineBreakConfig.set(lineBreakConfig);
        }
    }
    /**
     * Set the line break word style for text wrapping.
     *
     * The line break word style affects dictionary-based breaking and provide phrase-based
     * breaking opportunities. The type for the line break word style is
     * {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_PHRASE}. The default values of the line break
     * word style is {@link LineBreakConfig#LINE_BREAK_WORD_STYLE_NONE}, indicating no breaking rule
     * is specified.
     * See <a href="https://www.w3.org/TR/css-text-3/#word-break-property">
     *         the word-break property</a>
     *
     * @param lineBreakWordStyle the line break word style for the tet
     */
    public void setLineBreakWordStyle(@LineBreakConfig.LineBreakWordStyle int lineBreakWordStyle) {
        if (mLineBreakWordStyle != lineBreakWordStyle) {
            mLineBreakWordStyle = lineBreakWordStyle;
            if (mLayout != null) {
                nullLayouts();
                requestLayout();
                invalidate();
            }
        }
    }
    /**
     * Get the current line break style for text wrapping.
     *
     * @return the current line break style to be used for text wrapping.
     */
    public @LineBreakConfig.LineBreakStyle int getLineBreakStyle() {
        return mLineBreakStyle;
    }
    /**
     * Get the current line break configuration for text wrapping.
     * Get the current line word break style for text wrapping.
     *
     * @return the current line break configuration to be used for text wrapping.
     * @return the current line break word style to be used for text wrapping.
     */
    public @NonNull LineBreakConfig getLineBreakConfig() {
        LineBreakConfig lbConfig = new LineBreakConfig();
        lbConfig.set(mLineBreakConfig);
        return lbConfig;
    public @LineBreakConfig.LineBreakWordStyle int getLineBreakWordStyle() {
        return mLineBreakWordStyle;
    }
    /**
@@ -4924,7 +4945,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     * @see PrecomputedText
     */
    public @NonNull PrecomputedText.Params getTextMetricsParams() {
        return new PrecomputedText.Params(new TextPaint(mTextPaint), mLineBreakConfig,
        return new PrecomputedText.Params(new TextPaint(mTextPaint),
                LineBreakConfig.getLineBreakConfig(mLineBreakStyle, mLineBreakWordStyle),
                getTextDirectionHeuristic(),
                mBreakStrategy, mHyphenationFrequency);
    }
@@ -4941,13 +4963,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        mTextDir = params.getTextDirection();
        mBreakStrategy = params.getBreakStrategy();
        mHyphenationFrequency = params.getHyphenationFrequency();
        if (params.getLineBreakConfig() != null) {
            mLineBreakConfig.set(params.getLineBreakConfig());
        } else {
            // Set default value if the line break config in the PrecomputedText.Params is null.
            mLineBreakConfig.setLineBreakStyle(DEFAULT_LINE_BREAK_STYLE);
            mLineBreakConfig.setLineBreakWordStyle(DEFAULT_LINE_BREAK_WORD_STYLE);
        }
        LineBreakConfig lineBreakConfig = params.getLineBreakConfig();
        mLineBreakStyle = lineBreakConfig.getLineBreakStyle();
        mLineBreakWordStyle = lineBreakConfig.getLineBreakWordStyle();
        if (mLayout != null) {
            nullLayouts();
            requestLayout();
@@ -6486,7 +6504,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            }
            final @PrecomputedText.Params.CheckResultUsableResult int checkResult =
                    precomputed.getParams().checkResultUsable(getPaint(), mTextDir, mBreakStrategy,
                            mHyphenationFrequency, mLineBreakConfig);
                            mHyphenationFrequency, LineBreakConfig.getLineBreakConfig(
                                    mLineBreakStyle, mLineBreakWordStyle));
            switch (checkResult) {
                case PrecomputedText.Params.UNUSABLE:
                    throw new IllegalArgumentException(
@@ -9383,7 +9402,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                        .setHyphenationFrequency(mHyphenationFrequency)
                        .setJustificationMode(mJustificationMode)
                        .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE)
                        .setLineBreakConfig(mLineBreakConfig);
                        .setLineBreakConfig(LineBreakConfig.getLineBreakConfig(
                                mLineBreakStyle, mLineBreakWordStyle));
                if (shouldEllipsize) {
                    builder.setEllipsize(mEllipsize)
                            .setEllipsizedWidth(ellipsisWidth);
@@ -9498,7 +9518,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                    .setHyphenationFrequency(mHyphenationFrequency)
                    .setJustificationMode(mJustificationMode)
                    .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE)
                    .setLineBreakConfig(mLineBreakConfig);
                    .setLineBreakConfig(LineBreakConfig.getLineBreakConfig(
                            mLineBreakStyle, mLineBreakWordStyle));
            if (shouldEllipsize) {
                builder.setEllipsize(effectiveEllipsize)
                        .setEllipsizedWidth(ellipsisWidth);
@@ -9866,7 +9887,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                .setJustificationMode(getJustificationMode())
                .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE)
                .setTextDirection(getTextDirectionHeuristic())
                .setLineBreakConfig(mLineBreakConfig);
                .setLineBreakConfig(LineBreakConfig.getLineBreakConfig(
                        mLineBreakStyle, mLineBreakWordStyle));
        final StaticLayout layout = layoutBuilder.build();
+2 −2
Original line number Diff line number Diff line
@@ -5479,9 +5479,9 @@
            <enum name="none" value="0" />
            <!-- Use the least restrictive rule for line-breaking. -->
            <enum name="loose" value="1" />
            <!-- Indicate breaking text with the most comment set of line-breaking rules. -->
            <!-- Indicates breaking text with the most comment set of line-breaking rules. -->
            <enum name="normal" value="2" />
            <!-- ndicates breaking text with the most strictest line-breaking rules. -->
            <!-- Indicates breaking text with the most strictest line-breaking rules. -->
            <enum name="strict" value="3" />
        </attr>
        <!-- Specify the phrase-based line break can be used when calculating the text wrapping.-->
Loading