Loading core/api/current.txt +8 −0 Original line number Diff line number Diff line Loading @@ -16259,6 +16259,8 @@ package android.graphics { public static class Paint.FontMetricsInt { ctor public Paint.FontMetricsInt(); method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") public void set(@NonNull android.graphics.Paint.FontMetricsInt); method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") public void set(@NonNull android.graphics.Paint.FontMetrics); field public int ascent; field public int bottom; field public int descent; Loading Loading @@ -46719,6 +46721,7 @@ package android.text { method @NonNull public android.text.DynamicLayout.Builder setJustificationMode(int); 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 @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); Loading Loading @@ -46907,6 +46910,7 @@ package android.text { method public int getLineVisibleEnd(int); method public float getLineWidth(int); method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @IntRange(from=1) public final int getMaxLines(); method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") @Nullable public android.graphics.Paint.FontMetrics getMinimumFontMetrics(); method public int getOffsetForHorizontal(int, float); method public int getOffsetToLeftOf(int); method public int getOffsetToRightOf(int); Loading Loading @@ -46973,6 +46977,7 @@ package android.text { method @NonNull public android.text.Layout.Builder setLineSpacingAmount(float); method @NonNull public android.text.Layout.Builder setLineSpacingMultiplier(@FloatRange(from=0) float); 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 @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); Loading Loading @@ -47244,6 +47249,7 @@ package android.text { method @NonNull public android.text.StaticLayout.Builder setLineBreakConfig(@NonNull android.graphics.text.LineBreakConfig); 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 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); Loading Loading @@ -59922,6 +59928,7 @@ package android.widget { method public int getMinHeight(); method public int getMinLines(); method public int getMinWidth(); method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") @Nullable public android.graphics.Paint.FontMetrics getMinimumFontMetrics(); method public final android.text.method.MovementMethod getMovementMethod(); method public int getOffsetForPosition(float, float); method public android.text.TextPaint getPaint(); Loading Loading @@ -60058,6 +60065,7 @@ package android.widget { method public void setMinHeight(int); method public void setMinLines(int); method public void setMinWidth(int); method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") public void setMinimumFontMetrics(@Nullable android.graphics.Paint.FontMetrics); method public final void setMovementMethod(android.text.method.MovementMethod); method public void setOnEditorActionListener(android.widget.TextView.OnEditorActionListener); method public void setPaintFlags(int); core/java/android/text/BoringLayout.java +35 −8 Original line number Diff line number Diff line Loading @@ -190,7 +190,8 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback @Nullable TextUtils.TruncateAt ellipsize, @IntRange(from = 0) int ellipsizedWidth, boolean useFallbackLineSpacing) { return replaceOrMake(source, paint, outerWidth, align, 1.0f, 0.0f, metrics, includePad, ellipsize, ellipsizedWidth, useFallbackLineSpacing, false /* useBoundsForWidth */); ellipsize, ellipsizedWidth, useFallbackLineSpacing, false /* useBoundsForWidth */, null /* minimumFontMetrics */); } /** @hide */ Loading @@ -199,7 +200,8 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback @NonNull Alignment align, float spacingMultiplier, float spacingAmount, @NonNull BoringLayout.Metrics metrics, boolean includePad, @Nullable TextUtils.TruncateAt ellipsize, @IntRange(from = 0) int ellipsizedWidth, boolean useFallbackLineSpacing, boolean useBoundsForWidth) { boolean useFallbackLineSpacing, boolean useBoundsForWidth, @Nullable Paint.FontMetrics minimumFontMetrics) { boolean trust; if (ellipsize == null || ellipsize == TextUtils.TruncateAt.MARQUEE) { Loading Loading @@ -270,7 +272,8 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback spacingAdd, includePad, false /* fallbackLineSpacing */, outerwidth /* ellipsizedWidth */, null /* ellipsize */, 1 /* maxLines */, BREAK_STRATEGY_SIMPLE, HYPHENATION_FREQUENCY_NONE, null /* leftIndents */, null /* rightIndents */, JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, false); null /* rightIndents */, JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, false, null); mEllipsizedWidth = outerwidth; mEllipsizedStart = 0; Loading Loading @@ -343,7 +346,7 @@ 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 */); LineBreakConfig.NONE, metrics, false /* useBoundsForWidth */, null); } /** @hide */ Loading @@ -359,12 +362,13 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback int ellipsizedWidth, TextUtils.TruncateAt ellipsize, Metrics metrics, boolean useBoundsForWidth) { boolean useBoundsForWidth, @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); LineBreakConfig.NONE, metrics, useBoundsForWidth, minimumFontMetrics); } /* package */ BoringLayout( Loading @@ -387,12 +391,13 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback int justificationMode, LineBreakConfig lineBreakConfig, Metrics metrics, boolean useBoundsForWidth) { boolean useBoundsForWidth, @Nullable Paint.FontMetrics minimumFontMetrics) { super(text, paint, width, align, textDir, spacingMult, spacingAdd, includePad, fallbackLineSpacing, ellipsizedWidth, ellipsize, maxLines, breakStrategy, hyphenationFrequency, leftIndents, rightIndents, justificationMode, lineBreakConfig, useBoundsForWidth); lineBreakConfig, useBoundsForWidth, minimumFontMetrics); boolean trust; Loading Loading @@ -548,6 +553,15 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback public static @Nullable Metrics isBoring(@NonNull CharSequence text, @NonNull TextPaint paint, @NonNull TextDirectionHeuristic textDir, boolean useFallbackLineSpacing, @Nullable Metrics metrics) { return isBoring(text, paint, textDir, useFallbackLineSpacing, null, metrics); } /** * @hide */ public static @Nullable Metrics isBoring(@NonNull CharSequence text, @NonNull TextPaint paint, @NonNull TextDirectionHeuristic textDir, boolean useFallbackLineSpacing, @Nullable Paint.FontMetrics minimumFontMetrics, @Nullable Metrics metrics) { final int textLength = text.length(); if (hasAnyInterestingChars(text, textLength)) { return null; // There are some interesting characters. Not boring. Loading @@ -570,6 +584,19 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback fm.reset(); } if (ClientFlags.fixLineHeightForLocale()) { if (minimumFontMetrics == null) { paint.getFontMetricsIntForLocale(fm); } else { fm.set(minimumFontMetrics); // Because the font metrics is provided by public APIs, adjust the top/bottom with // ascent/descent: top must be smaller than ascent, bottom must be larger than // descent. fm.top = Math.min(fm.top, fm.ascent); fm.bottom = Math.max(fm.bottom, fm.descent); } } TextLine line = TextLine.obtain(); line.set(paint, text, 0, textLength, Layout.DIR_LEFT_TO_RIGHT, Layout.DIRS_ALL_LEFT_TO_RIGHT, false, null, Loading core/java/android/text/ClientFlags.java +7 −0 Original line number Diff line number Diff line Loading @@ -47,4 +47,11 @@ public class ClientFlags { public static boolean useBoundsForWidth() { return TextFlags.isFeatureEnabled(Flags.FLAG_USE_BOUNDS_FOR_WIDTH); } /** * @see Flags#fixLineHeightForLocale() */ public static boolean fixLineHeightForLocale() { return TextFlags.isFeatureEnabled(Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE); } } core/java/android/text/DynamicLayout.java +44 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.text; import static com.android.text.flags.Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE; import static com.android.text.flags.Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN; import static com.android.text.flags.Flags.FLAG_USE_BOUNDS_FOR_WIDTH; Loading Loading @@ -314,6 +315,43 @@ public class DynamicLayout extends Layout { 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 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 Layout.Builder#setMinimumFontMetrics(Paint.FontMetrics) * @see StaticLayout.Builder#setMinimumFontMetrics(Paint.FontMetrics) */ @NonNull @FlaggedApi(FLAG_FIX_LINE_HEIGHT_FOR_LOCALE) public Builder setMinimumFontMetrics(@Nullable Paint.FontMetrics minimumFontMetrics) { mMinimumFontMetrics = minimumFontMetrics; return this; } /** * Build the {@link DynamicLayout} after options have been set. * Loading Loading @@ -347,6 +385,7 @@ public class DynamicLayout extends Layout { private int mEllipsizedWidth; private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE; private boolean mUseBoundsForWidth; private @Nullable Paint.FontMetrics mMinimumFontMetrics; private final Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt(); Loading Loading @@ -422,7 +461,7 @@ public class DynamicLayout extends Layout { false /* fallbackLineSpacing */, ellipsizedWidth, ellipsize, Integer.MAX_VALUE /* maxLines */, breakStrategy, hyphenationFrequency, null /* leftIndents */, null /* rightIndents */, justificationMode, lineBreakConfig, false /* useBoundsForWidth */); lineBreakConfig, false /* useBoundsForWidth */, null /* minimumFontMetrics */); final Builder b = Builder.obtain(base, paint, width) .setAlignment(align) Loading @@ -448,7 +487,7 @@ 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.mLineBreakConfig, b.mUseBoundsForWidth, b.mMinimumFontMetrics); mDisplay = b.mDisplay; mIncludePad = b.mIncludePad; Loading Loading @@ -476,6 +515,7 @@ public class DynamicLayout extends Layout { mBase = b.mBase; mFallbackLineSpacing = b.mFallbackLineSpacing; mUseBoundsForWidth = b.mUseBoundsForWidth; mMinimumFontMetrics = b.mMinimumFontMetrics; if (b.mEllipsize != null) { mInts = new PackedIntVector(COLUMNS_ELLIPSIZE); mEllipsizedWidth = b.mEllipsizedWidth; Loading Loading @@ -672,6 +712,7 @@ public class DynamicLayout extends Layout { .setAddLastLineLineSpacing(!islast) .setIncludePad(false) .setUseBoundsForWidth(mUseBoundsForWidth) .setMinimumFontMetrics(mMinimumFontMetrics) .setCalculateBounds(true); reflowed = b.buildPartialStaticLayoutForDynamicLayout(true /* trackpadding */, reflowed); Loading Loading @@ -1324,6 +1365,7 @@ public class DynamicLayout extends Layout { private Rect mTempRect = new Rect(); private boolean mUseBoundsForWidth; @Nullable Paint.FontMetrics mMinimumFontMetrics; @UnsupportedAppUsage private static StaticLayout sStaticLayout = null; Loading core/java/android/text/Layout.java +64 −4 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.text; 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 android.annotation.FlaggedApi; Loading Loading @@ -287,7 +288,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); JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, false, null); } /** Loading Loading @@ -336,7 +337,8 @@ public abstract class Layout { int[] rightIndents, int justificationMode, LineBreakConfig lineBreakConfig, boolean useBoundsForWidth boolean useBoundsForWidth, Paint.FontMetrics minimumFontMetrics ) { if (width < 0) Loading Loading @@ -371,6 +373,7 @@ public abstract class Layout { mJustificationMode = justificationMode; mLineBreakConfig = lineBreakConfig; mUseBoundsForWidth = useBoundsForWidth; mMinimumFontMetrics = minimumFontMetrics; } /** Loading Loading @@ -3332,6 +3335,7 @@ public abstract class Layout { private int mJustificationMode; private LineBreakConfig mLineBreakConfig; private boolean mUseBoundsForWidth; private @Nullable Paint.FontMetrics mMinimumFontMetrics; /** @hide */ @IntDef(prefix = { "DIR_" }, value = { Loading Loading @@ -3787,12 +3791,48 @@ public abstract class Layout { 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, null); mFallbackLineSpacing, mMinimumFontMetrics, null); if (metrics == null) { return null; } Loading Loading @@ -3833,7 +3873,8 @@ public abstract class Layout { mText, mPaint, mWidth, mAlignment, mTextDir, mSpacingMult, mSpacingAdd, mIncludePad, mFallbackLineSpacing, mEllipsizedWidth, mEllipsize, mMaxLines, mBreakStrategy, mHyphenationFrequency, mLeftIndents, mRightIndents, mJustificationMode, mLineBreakConfig, metrics, mUseBoundsForWidth); mJustificationMode, mLineBreakConfig, metrics, mUseBoundsForWidth, mMinimumFontMetrics); } } Loading @@ -3858,6 +3899,7 @@ public abstract class Layout { private int mJustificationMode = JUSTIFICATION_MODE_NONE; private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE; private boolean mUseBoundsForWidth; private Paint.FontMetrics mMinimumFontMetrics; } /////////////////////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -4164,4 +4206,22 @@ public abstract class Layout { public boolean getUseBoundsForWidth() { return mUseBoundsForWidth; } /** * 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; } } Loading
core/api/current.txt +8 −0 Original line number Diff line number Diff line Loading @@ -16259,6 +16259,8 @@ package android.graphics { public static class Paint.FontMetricsInt { ctor public Paint.FontMetricsInt(); method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") public void set(@NonNull android.graphics.Paint.FontMetricsInt); method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") public void set(@NonNull android.graphics.Paint.FontMetrics); field public int ascent; field public int bottom; field public int descent; Loading Loading @@ -46719,6 +46721,7 @@ package android.text { method @NonNull public android.text.DynamicLayout.Builder setJustificationMode(int); 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 @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); Loading Loading @@ -46907,6 +46910,7 @@ package android.text { method public int getLineVisibleEnd(int); method public float getLineWidth(int); method @FlaggedApi("com.android.text.flags.use_bounds_for_width") @IntRange(from=1) public final int getMaxLines(); method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") @Nullable public android.graphics.Paint.FontMetrics getMinimumFontMetrics(); method public int getOffsetForHorizontal(int, float); method public int getOffsetToLeftOf(int); method public int getOffsetToRightOf(int); Loading Loading @@ -46973,6 +46977,7 @@ package android.text { method @NonNull public android.text.Layout.Builder setLineSpacingAmount(float); method @NonNull public android.text.Layout.Builder setLineSpacingMultiplier(@FloatRange(from=0) float); 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 @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); Loading Loading @@ -47244,6 +47249,7 @@ package android.text { method @NonNull public android.text.StaticLayout.Builder setLineBreakConfig(@NonNull android.graphics.text.LineBreakConfig); 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 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); Loading Loading @@ -59922,6 +59928,7 @@ package android.widget { method public int getMinHeight(); method public int getMinLines(); method public int getMinWidth(); method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") @Nullable public android.graphics.Paint.FontMetrics getMinimumFontMetrics(); method public final android.text.method.MovementMethod getMovementMethod(); method public int getOffsetForPosition(float, float); method public android.text.TextPaint getPaint(); Loading Loading @@ -60058,6 +60065,7 @@ package android.widget { method public void setMinHeight(int); method public void setMinLines(int); method public void setMinWidth(int); method @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") public void setMinimumFontMetrics(@Nullable android.graphics.Paint.FontMetrics); method public final void setMovementMethod(android.text.method.MovementMethod); method public void setOnEditorActionListener(android.widget.TextView.OnEditorActionListener); method public void setPaintFlags(int);
core/java/android/text/BoringLayout.java +35 −8 Original line number Diff line number Diff line Loading @@ -190,7 +190,8 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback @Nullable TextUtils.TruncateAt ellipsize, @IntRange(from = 0) int ellipsizedWidth, boolean useFallbackLineSpacing) { return replaceOrMake(source, paint, outerWidth, align, 1.0f, 0.0f, metrics, includePad, ellipsize, ellipsizedWidth, useFallbackLineSpacing, false /* useBoundsForWidth */); ellipsize, ellipsizedWidth, useFallbackLineSpacing, false /* useBoundsForWidth */, null /* minimumFontMetrics */); } /** @hide */ Loading @@ -199,7 +200,8 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback @NonNull Alignment align, float spacingMultiplier, float spacingAmount, @NonNull BoringLayout.Metrics metrics, boolean includePad, @Nullable TextUtils.TruncateAt ellipsize, @IntRange(from = 0) int ellipsizedWidth, boolean useFallbackLineSpacing, boolean useBoundsForWidth) { boolean useFallbackLineSpacing, boolean useBoundsForWidth, @Nullable Paint.FontMetrics minimumFontMetrics) { boolean trust; if (ellipsize == null || ellipsize == TextUtils.TruncateAt.MARQUEE) { Loading Loading @@ -270,7 +272,8 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback spacingAdd, includePad, false /* fallbackLineSpacing */, outerwidth /* ellipsizedWidth */, null /* ellipsize */, 1 /* maxLines */, BREAK_STRATEGY_SIMPLE, HYPHENATION_FREQUENCY_NONE, null /* leftIndents */, null /* rightIndents */, JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, false); null /* rightIndents */, JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, false, null); mEllipsizedWidth = outerwidth; mEllipsizedStart = 0; Loading Loading @@ -343,7 +346,7 @@ 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 */); LineBreakConfig.NONE, metrics, false /* useBoundsForWidth */, null); } /** @hide */ Loading @@ -359,12 +362,13 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback int ellipsizedWidth, TextUtils.TruncateAt ellipsize, Metrics metrics, boolean useBoundsForWidth) { boolean useBoundsForWidth, @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); LineBreakConfig.NONE, metrics, useBoundsForWidth, minimumFontMetrics); } /* package */ BoringLayout( Loading @@ -387,12 +391,13 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback int justificationMode, LineBreakConfig lineBreakConfig, Metrics metrics, boolean useBoundsForWidth) { boolean useBoundsForWidth, @Nullable Paint.FontMetrics minimumFontMetrics) { super(text, paint, width, align, textDir, spacingMult, spacingAdd, includePad, fallbackLineSpacing, ellipsizedWidth, ellipsize, maxLines, breakStrategy, hyphenationFrequency, leftIndents, rightIndents, justificationMode, lineBreakConfig, useBoundsForWidth); lineBreakConfig, useBoundsForWidth, minimumFontMetrics); boolean trust; Loading Loading @@ -548,6 +553,15 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback public static @Nullable Metrics isBoring(@NonNull CharSequence text, @NonNull TextPaint paint, @NonNull TextDirectionHeuristic textDir, boolean useFallbackLineSpacing, @Nullable Metrics metrics) { return isBoring(text, paint, textDir, useFallbackLineSpacing, null, metrics); } /** * @hide */ public static @Nullable Metrics isBoring(@NonNull CharSequence text, @NonNull TextPaint paint, @NonNull TextDirectionHeuristic textDir, boolean useFallbackLineSpacing, @Nullable Paint.FontMetrics minimumFontMetrics, @Nullable Metrics metrics) { final int textLength = text.length(); if (hasAnyInterestingChars(text, textLength)) { return null; // There are some interesting characters. Not boring. Loading @@ -570,6 +584,19 @@ public class BoringLayout extends Layout implements TextUtils.EllipsizeCallback fm.reset(); } if (ClientFlags.fixLineHeightForLocale()) { if (minimumFontMetrics == null) { paint.getFontMetricsIntForLocale(fm); } else { fm.set(minimumFontMetrics); // Because the font metrics is provided by public APIs, adjust the top/bottom with // ascent/descent: top must be smaller than ascent, bottom must be larger than // descent. fm.top = Math.min(fm.top, fm.ascent); fm.bottom = Math.max(fm.bottom, fm.descent); } } TextLine line = TextLine.obtain(); line.set(paint, text, 0, textLength, Layout.DIR_LEFT_TO_RIGHT, Layout.DIRS_ALL_LEFT_TO_RIGHT, false, null, Loading
core/java/android/text/ClientFlags.java +7 −0 Original line number Diff line number Diff line Loading @@ -47,4 +47,11 @@ public class ClientFlags { public static boolean useBoundsForWidth() { return TextFlags.isFeatureEnabled(Flags.FLAG_USE_BOUNDS_FOR_WIDTH); } /** * @see Flags#fixLineHeightForLocale() */ public static boolean fixLineHeightForLocale() { return TextFlags.isFeatureEnabled(Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE); } }
core/java/android/text/DynamicLayout.java +44 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.text; import static com.android.text.flags.Flags.FLAG_FIX_LINE_HEIGHT_FOR_LOCALE; import static com.android.text.flags.Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN; import static com.android.text.flags.Flags.FLAG_USE_BOUNDS_FOR_WIDTH; Loading Loading @@ -314,6 +315,43 @@ public class DynamicLayout extends Layout { 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 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 Layout.Builder#setMinimumFontMetrics(Paint.FontMetrics) * @see StaticLayout.Builder#setMinimumFontMetrics(Paint.FontMetrics) */ @NonNull @FlaggedApi(FLAG_FIX_LINE_HEIGHT_FOR_LOCALE) public Builder setMinimumFontMetrics(@Nullable Paint.FontMetrics minimumFontMetrics) { mMinimumFontMetrics = minimumFontMetrics; return this; } /** * Build the {@link DynamicLayout} after options have been set. * Loading Loading @@ -347,6 +385,7 @@ public class DynamicLayout extends Layout { private int mEllipsizedWidth; private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE; private boolean mUseBoundsForWidth; private @Nullable Paint.FontMetrics mMinimumFontMetrics; private final Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt(); Loading Loading @@ -422,7 +461,7 @@ public class DynamicLayout extends Layout { false /* fallbackLineSpacing */, ellipsizedWidth, ellipsize, Integer.MAX_VALUE /* maxLines */, breakStrategy, hyphenationFrequency, null /* leftIndents */, null /* rightIndents */, justificationMode, lineBreakConfig, false /* useBoundsForWidth */); lineBreakConfig, false /* useBoundsForWidth */, null /* minimumFontMetrics */); final Builder b = Builder.obtain(base, paint, width) .setAlignment(align) Loading @@ -448,7 +487,7 @@ 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.mLineBreakConfig, b.mUseBoundsForWidth, b.mMinimumFontMetrics); mDisplay = b.mDisplay; mIncludePad = b.mIncludePad; Loading Loading @@ -476,6 +515,7 @@ public class DynamicLayout extends Layout { mBase = b.mBase; mFallbackLineSpacing = b.mFallbackLineSpacing; mUseBoundsForWidth = b.mUseBoundsForWidth; mMinimumFontMetrics = b.mMinimumFontMetrics; if (b.mEllipsize != null) { mInts = new PackedIntVector(COLUMNS_ELLIPSIZE); mEllipsizedWidth = b.mEllipsizedWidth; Loading Loading @@ -672,6 +712,7 @@ public class DynamicLayout extends Layout { .setAddLastLineLineSpacing(!islast) .setIncludePad(false) .setUseBoundsForWidth(mUseBoundsForWidth) .setMinimumFontMetrics(mMinimumFontMetrics) .setCalculateBounds(true); reflowed = b.buildPartialStaticLayoutForDynamicLayout(true /* trackpadding */, reflowed); Loading Loading @@ -1324,6 +1365,7 @@ public class DynamicLayout extends Layout { private Rect mTempRect = new Rect(); private boolean mUseBoundsForWidth; @Nullable Paint.FontMetrics mMinimumFontMetrics; @UnsupportedAppUsage private static StaticLayout sStaticLayout = null; Loading
core/java/android/text/Layout.java +64 −4 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package android.text; 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 android.annotation.FlaggedApi; Loading Loading @@ -287,7 +288,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); JUSTIFICATION_MODE_NONE, LineBreakConfig.NONE, false, null); } /** Loading Loading @@ -336,7 +337,8 @@ public abstract class Layout { int[] rightIndents, int justificationMode, LineBreakConfig lineBreakConfig, boolean useBoundsForWidth boolean useBoundsForWidth, Paint.FontMetrics minimumFontMetrics ) { if (width < 0) Loading Loading @@ -371,6 +373,7 @@ public abstract class Layout { mJustificationMode = justificationMode; mLineBreakConfig = lineBreakConfig; mUseBoundsForWidth = useBoundsForWidth; mMinimumFontMetrics = minimumFontMetrics; } /** Loading Loading @@ -3332,6 +3335,7 @@ public abstract class Layout { private int mJustificationMode; private LineBreakConfig mLineBreakConfig; private boolean mUseBoundsForWidth; private @Nullable Paint.FontMetrics mMinimumFontMetrics; /** @hide */ @IntDef(prefix = { "DIR_" }, value = { Loading Loading @@ -3787,12 +3791,48 @@ public abstract class Layout { 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, null); mFallbackLineSpacing, mMinimumFontMetrics, null); if (metrics == null) { return null; } Loading Loading @@ -3833,7 +3873,8 @@ public abstract class Layout { mText, mPaint, mWidth, mAlignment, mTextDir, mSpacingMult, mSpacingAdd, mIncludePad, mFallbackLineSpacing, mEllipsizedWidth, mEllipsize, mMaxLines, mBreakStrategy, mHyphenationFrequency, mLeftIndents, mRightIndents, mJustificationMode, mLineBreakConfig, metrics, mUseBoundsForWidth); mJustificationMode, mLineBreakConfig, metrics, mUseBoundsForWidth, mMinimumFontMetrics); } } Loading @@ -3858,6 +3899,7 @@ public abstract class Layout { private int mJustificationMode = JUSTIFICATION_MODE_NONE; private LineBreakConfig mLineBreakConfig = LineBreakConfig.NONE; private boolean mUseBoundsForWidth; private Paint.FontMetrics mMinimumFontMetrics; } /////////////////////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -4164,4 +4206,22 @@ public abstract class Layout { public boolean getUseBoundsForWidth() { return mUseBoundsForWidth; } /** * 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; } }