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

Commit b7a09f01 authored by Seigo Nonaka's avatar Seigo Nonaka
Browse files

Don't shift drawing offset by default.

Shifting drawing offset misalign multiple TextViews vertically.

Bug: 325165220
Test: Manually done
Test: atest CtsTextTestCases
Test: atest CtsWidgetTestCases
Test: atest CtsGraphicsTestCases
Test: atest FrameworksCoreTests:android.text
Change-Id: Ib3e82d64fa1417db52362983319a073bab9c4382
parent af889dbe
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -1496,6 +1496,7 @@ package android {
    field @Deprecated public static final int sharedUserLabel = 16843361; // 0x1010261
    field public static final int sharedUserMaxSdkVersion = 16844365; // 0x101064d
    field public static final int shell = 16844180; // 0x1010594
    field @FlaggedApi("com.android.text.flags.use_bounds_for_width") public static final int shiftDrawingOffsetForStartOverhang;
    field public static final int shortcutDisabledMessage = 16844075; // 0x101052b
    field public static final int shortcutId = 16844072; // 0x1010528
    field public static final int shortcutLongLabel = 16844074; // 0x101052a
@@ -47543,6 +47544,7 @@ package android.text {
    method @FlaggedApi("com.android.text.flags.no_break_no_hyphenation_span") @NonNull public android.text.DynamicLayout.Builder setLineBreakConfig(@NonNull android.graphics.text.LineBreakConfig);
    method @NonNull public android.text.DynamicLayout.Builder setLineSpacing(float, @FloatRange(from=0.0) float);
    method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") @NonNull public android.text.DynamicLayout.Builder setMinimumFontMetrics(@Nullable android.graphics.Paint.FontMetrics);
    method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @NonNull public android.text.DynamicLayout.Builder setShiftDrawingOffsetForStartOverhang(boolean);
    method @NonNull public android.text.DynamicLayout.Builder setTextDirection(@NonNull android.text.TextDirectionHeuristic);
    method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @NonNull public android.text.DynamicLayout.Builder setUseBoundsForWidth(boolean);
    method @NonNull public android.text.DynamicLayout.Builder setUseLineSpacingFromFallbacks(boolean);
@@ -47746,6 +47748,7 @@ package android.text {
    method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @Nullable public final int[] getRightIndents();
    method public float getSecondaryHorizontal(int);
    method public void getSelectionPath(int, int, android.graphics.Path);
    method @FlaggedApi("com.android.text.flags.use_bounds_for_width") public boolean getShiftDrawingOffsetForStartOverhang();
    method public final float getSpacingAdd();
    method public final float getSpacingMultiplier();
    method @NonNull public final CharSequence getText();
@@ -47802,6 +47805,7 @@ package android.text {
    method @NonNull public android.text.Layout.Builder setMaxLines(@IntRange(from=1) int);
    method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") @NonNull public android.text.Layout.Builder setMinimumFontMetrics(@Nullable android.graphics.Paint.FontMetrics);
    method @NonNull public android.text.Layout.Builder setRightIndents(@Nullable int[]);
    method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @NonNull public android.text.Layout.Builder setShiftDrawingOffsetForStartOverhang(boolean);
    method @NonNull public android.text.Layout.Builder setTextDirectionHeuristic(@NonNull android.text.TextDirectionHeuristic);
    method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @NonNull public android.text.Layout.Builder setUseBoundsForWidth(boolean);
  }
@@ -48073,6 +48077,7 @@ package android.text {
    method @NonNull public android.text.StaticLayout.Builder setLineSpacing(float, @FloatRange(from=0.0) float);
    method @NonNull public android.text.StaticLayout.Builder setMaxLines(@IntRange(from=0) int);
    method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") @NonNull public android.text.StaticLayout.Builder setMinimumFontMetrics(@Nullable android.graphics.Paint.FontMetrics);
    method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @NonNull public android.text.StaticLayout.Builder setShiftDrawingOffsetForStartOverhang(boolean);
    method public android.text.StaticLayout.Builder setText(CharSequence);
    method @NonNull public android.text.StaticLayout.Builder setTextDirection(@NonNull android.text.TextDirectionHeuristic);
    method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @NonNull public android.text.StaticLayout.Builder setUseBoundsForWidth(boolean);
@@ -60889,6 +60894,7 @@ package android.widget {
    method public float getShadowDx();
    method public float getShadowDy();
    method public float getShadowRadius();
    method @FlaggedApi("com.android.text.flags.use_bounds_for_width") public boolean getShiftDrawingOffsetForStartOverhang();
    method public final boolean getShowSoftInputOnFocus();
    method public CharSequence getText();
    method @NonNull public android.view.textclassifier.TextClassifier getTextClassifier();
@@ -61025,6 +61031,7 @@ package android.widget {
    method public void setSearchResultHighlights(@Nullable int...);
    method public void setSelectAllOnFocus(boolean);
    method public void setShadowLayer(float, float, float, int);
    method @FlaggedApi("com.android.text.flags.use_bounds_for_width") public void setShiftDrawingOffsetForStartOverhang(boolean);
    method public final void setShowSoftInputOnFocus(boolean);
    method public void setSingleLine();
    method public void setSingleLine(boolean);
+10 −5
Original line number Diff line number Diff line
@@ -273,7 +273,7 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
                outerwidth /* ellipsizedWidth */, null /* ellipsize */, 1 /* maxLines */,
                BREAK_STRATEGY_SIMPLE, HYPHENATION_FREQUENCY_NONE, null /* leftIndents */,
                null /* rightIndents */, JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, false,
                null);
                false /* shiftDrawingOffsetForStartOverhang */, null);

        mEllipsizedWidth = outerwidth;
        mEllipsizedStart = 0;
@@ -346,7 +346,8 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
                ellipsizedWidth, ellipsize, 1 /* maxLines */,
                BREAK_STRATEGY_SIMPLE, HYPHENATION_FREQUENCY_NONE, null /* leftIndents */,
                null /* rightIndents */, JUSTIFICATION_MODE_NONE,
                LineBreakConfig.NONE, metrics, false /* useBoundsForWidth */, null);
                LineBreakConfig.NONE, metrics, false /* useBoundsForWidth */,
                false /* shiftDrawingOffsetForStartOverhang */, null);
    }

    /** @hide */
@@ -363,12 +364,14 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
            TextUtils.TruncateAt ellipsize,
            Metrics metrics,
            boolean useBoundsForWidth,
            boolean shiftDrawingOffsetForStartOverhang,
            @Nullable Paint.FontMetrics minimumFontMetrics) {
        this(text, paint, width, align, TextDirectionHeuristics.LTR,
                spacingMult, spacingAdd, includePad, fallbackLineSpacing, ellipsizedWidth,
                ellipsize, 1 /* maxLines */, Layout.BREAK_STRATEGY_SIMPLE,
                Layout.HYPHENATION_FREQUENCY_NONE, null, null, Layout.JUSTIFICATION_MODE_NONE,
                LineBreakConfig.NONE, metrics, useBoundsForWidth, minimumFontMetrics);
                LineBreakConfig.NONE, metrics, useBoundsForWidth,
                shiftDrawingOffsetForStartOverhang, minimumFontMetrics);
    }

    /* package */ BoringLayout(
@@ -392,12 +395,14 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
            LineBreakConfig lineBreakConfig,
            Metrics metrics,
            boolean useBoundsForWidth,
            boolean shiftDrawingOffsetForStartOverhang,
            @Nullable Paint.FontMetrics minimumFontMetrics) {

        super(text, paint, width, align, textDir, spacingMult, spacingAdd, includePad,
                fallbackLineSpacing, ellipsizedWidth, ellipsize, maxLines, breakStrategy,
                hyphenationFrequency, leftIndents, rightIndents, justificationMode,
                lineBreakConfig, useBoundsForWidth, minimumFontMetrics);
                lineBreakConfig, useBoundsForWidth, shiftDrawingOffsetForStartOverhang,
                minimumFontMetrics);


        boolean trust;
@@ -712,7 +717,7 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback
                     int cursorOffset) {
        if (mDirect != null && highlight == null) {
            float leftShift = 0;
            if (getUseBoundsForWidth()) {
            if (getUseBoundsForWidth() && getShiftDrawingOffsetForStartOverhang()) {
                RectF drawingRect = computeDrawingBoundingBox();
                if (drawingRect.left < 0) {
                    leftShift = -drawingRect.left;
+38 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.annotation.FloatRange;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Paint;
import android.graphics.Rect;
@@ -316,6 +317,35 @@ public class DynamicLayout extends Layout {
            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.
         *
@@ -386,6 +416,7 @@ public class DynamicLayout extends Layout {
        private int mEllipsizedWidth;
        private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;
        private boolean mUseBoundsForWidth;
        private boolean mShiftDrawingOffsetForStartOverhang;
        private @Nullable Paint.FontMetrics mMinimumFontMetrics;

        private final Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt();
@@ -462,7 +493,8 @@ public class DynamicLayout extends Layout {
                false /* fallbackLineSpacing */, ellipsizedWidth, ellipsize,
                Integer.MAX_VALUE /* maxLines */, breakStrategy, hyphenationFrequency,
                null /* leftIndents */, null /* rightIndents */, justificationMode,
                lineBreakConfig, false /* useBoundsForWidth */, null /* minimumFontMetrics */);
                lineBreakConfig, false /* useBoundsForWidth */, false,
                null /* minimumFontMetrics */);

        final Builder b = Builder.obtain(base, paint, width)
                .setAlignment(align)
@@ -488,7 +520,8 @@ public class DynamicLayout extends Layout {
                b.mIncludePad, b.mFallbackLineSpacing, b.mEllipsizedWidth, b.mEllipsize,
                Integer.MAX_VALUE /* maxLines */, b.mBreakStrategy, b.mHyphenationFrequency,
                null /* leftIndents */, null /* rightIndents */, b.mJustificationMode,
                b.mLineBreakConfig, b.mUseBoundsForWidth, b.mMinimumFontMetrics);
                b.mLineBreakConfig, b.mUseBoundsForWidth, b.mShiftDrawingOffsetForStartOverhang,
                b.mMinimumFontMetrics);

        mDisplay = b.mDisplay;
        mIncludePad = b.mIncludePad;
@@ -516,6 +549,7 @@ public class DynamicLayout extends Layout {
        mBase = b.mBase;
        mFallbackLineSpacing = b.mFallbackLineSpacing;
        mUseBoundsForWidth = b.mUseBoundsForWidth;
        mShiftDrawingOffsetForStartOverhang = b.mShiftDrawingOffsetForStartOverhang;
        mMinimumFontMetrics = b.mMinimumFontMetrics;
        if (b.mEllipsize != null) {
            mInts = new PackedIntVector(COLUMNS_ELLIPSIZE);
@@ -713,6 +747,7 @@ public class DynamicLayout extends Layout {
                .setAddLastLineLineSpacing(!islast)
                .setIncludePad(false)
                .setUseBoundsForWidth(mUseBoundsForWidth)
                .setShiftDrawingOffsetForStartOverhang(mShiftDrawingOffsetForStartOverhang)
                .setMinimumFontMetrics(mMinimumFontMetrics)
                .setCalculateBounds(true);

@@ -1392,6 +1427,7 @@ public class DynamicLayout extends Layout {
    private Rect mTempRect = new Rect();

    private boolean mUseBoundsForWidth;
    private boolean mShiftDrawingOffsetForStartOverhang;
    @Nullable Paint.FontMetrics mMinimumFontMetrics;

    @UnsupportedAppUsage
+52 −3
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ 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.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
@@ -299,7 +300,7 @@ public abstract class Layout {
        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, null);
                JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, false, false, null);
    }

    /**
@@ -349,6 +350,7 @@ public abstract class Layout {
            int justificationMode,
            LineBreakConfig lineBreakConfig,
            boolean useBoundsForWidth,
            boolean shiftDrawingOffsetForStartOverhang,
            Paint.FontMetrics minimumFontMetrics
    ) {

@@ -384,6 +386,7 @@ public abstract class Layout {
        mJustificationMode = justificationMode;
        mLineBreakConfig = lineBreakConfig;
        mUseBoundsForWidth = useBoundsForWidth;
        mShiftDrawingOffsetForStartOverhang = shiftDrawingOffsetForStartOverhang;
        mMinimumFontMetrics = minimumFontMetrics;
    }

@@ -465,7 +468,7 @@ public abstract class Layout {
            @Nullable Paint selectionPaint,
            int cursorOffsetVertical) {
        float leftShift = 0;
        if (mUseBoundsForWidth) {
        if (mUseBoundsForWidth && mShiftDrawingOffsetForStartOverhang) {
            RectF drawingRect = computeDrawingBoundingBox();
            if (drawingRect.left < 0) {
                leftShift = -drawingRect.left;
@@ -3414,6 +3417,7 @@ public abstract class Layout {
    private int mJustificationMode;
    private LineBreakConfig mLineBreakConfig;
    private boolean mUseBoundsForWidth;
    private boolean mShiftDrawingOffsetForStartOverhang;
    private @Nullable Paint.FontMetrics mMinimumFontMetrics;

    private TextLine.LineInfo mLineInfo = null;
@@ -3872,6 +3876,35 @@ public abstract class Layout {
            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.
         *
@@ -3948,6 +3981,7 @@ public abstract class Layout {
                        .setJustificationMode(mJustificationMode)
                        .setLineBreakConfig(mLineBreakConfig)
                        .setUseBoundsForWidth(mUseBoundsForWidth)
                        .setShiftDrawingOffsetForStartOverhang(mShiftDrawingOffsetForStartOverhang)
                        .build();
            } else {
                return new BoringLayout(
@@ -3955,7 +3989,7 @@ public abstract class Layout {
                        mIncludePad, mFallbackLineSpacing, mEllipsizedWidth, mEllipsize, mMaxLines,
                        mBreakStrategy, mHyphenationFrequency, mLeftIndents, mRightIndents,
                        mJustificationMode, mLineBreakConfig, metrics, mUseBoundsForWidth,
                        mMinimumFontMetrics);
                        mShiftDrawingOffsetForStartOverhang, mMinimumFontMetrics);
            }
        }

@@ -3980,6 +4014,7 @@ public abstract class Layout {
        private int mJustificationMode = JUSTIFICATION_MODE_NONE;
        private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;
        private boolean mUseBoundsForWidth;
        private boolean mShiftDrawingOffsetForStartOverhang;
        private Paint.FontMetrics mMinimumFontMetrics;
    }

@@ -4293,6 +4328,20 @@ public abstract class Layout {
        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.
     *
+33 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.annotation.FloatRange;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Paint;
import android.graphics.RectF;
@@ -453,6 +454,35 @@ public class StaticLayout extends Layout {
            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;
        }

        /**
         * Internal API that tells underlying line breaker that calculating bounding boxes even if
         * the line break is performed with advances. This is useful for DynamicLayout internal
@@ -566,6 +596,7 @@ public class StaticLayout extends Layout {
        private boolean mAddLastLineLineSpacing;
        private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE;
        private boolean mUseBoundsForWidth;
        private boolean mShiftDrawingOffsetForStartOverhang;
        private boolean mCalculateBounds;
        @Nullable private Paint.FontMetrics mMinimumFontMetrics;

@@ -599,6 +630,7 @@ public class StaticLayout extends Layout {
                JUSTIFICATION_MODE_NONE,
                null,  // lineBreakConfig,
                false,  // useBoundsForWidth
                false,  // shiftDrawingOffsetForStartOverhang
                null  // minimumFontMetrics
        );

@@ -677,7 +709,7 @@ public class StaticLayout extends Layout {
                b.mIncludePad, b.mFallbackLineSpacing, b.mEllipsizedWidth, b.mEllipsize,
                b.mMaxLines, b.mBreakStrategy, b.mHyphenationFrequency, b.mLeftIndents,
                b.mRightIndents, b.mJustificationMode, b.mLineBreakConfig, b.mUseBoundsForWidth,
                b.mMinimumFontMetrics);
                b.mShiftDrawingOffsetForStartOverhang, b.mMinimumFontMetrics);

        mColumns = columnSize;
        if (b.mEllipsize != null) {
Loading