diff options
| author | Roozbeh Pournader <roozbeh@google.com> | 2017-08-10 11:32:24 -0700 |
|---|---|---|
| committer | Roozbeh Pournader <roozbeh@google.com> | 2017-08-17 12:10:31 -0700 |
| commit | 737dfead64dd24a431beff85b685594dc0efb49a (patch) | |
| tree | 544614313b240caf09ed181859b57a6027f5b1fe /core/java/android/text/StaticLayout.java | |
| parent | 980d88d9a70451c8caec882e4488e38c90427c1f (diff) | |
Support extra linespacing based on fallback fonts
* Increase the ascent and descent of individual lines in StaticLayout
as needed, if any fallback fonts that end up getting used call for
it. For backward compatibility, this is hidden behind a builder
flag.
* Document in Paint.java that the returned parameters are only for
the default font, and a layout may need more space based on
fallbacks used.
Also update for changes in minikin API:
* MinikinFont now requires a method for getting vertical extents
(ascent, descent, and line gap).
* minikin API now allows asking for vertical extents of laid out
text.
* minikin API's LineBreaker now returns ascents and descents for each
line.
Finally, added performances test for creating a StaticLayout.
Follwing are the numbers on a marlin with a stable clock before and
after this CL.
For fixed text almost always hitting the cache:
Before: mean=260684 median=260188 min=258532 standardDeviation=1897
After: mean=262432 median=261509 min=260429 standardDeviation=2185
For random text almost never hitting the cache:
Before: mean=5971827 median=5991126 min=5886871 standardDeviation=83724
After: mean=6337093 median=6317010 min=6311222 standardDeviation=40213
Bug: 28963299
Bug: 29063863
Bug: 32057121
Bug: 37756858
Test: bit FrameworksCoreTests:android.text.
Test: bit CtsTextTestCases:*
Change-Id: I482a98ff8f472e8bab4f0ba9d1d7b368858038ff
Diffstat (limited to 'core/java/android/text/StaticLayout.java')
| -rw-r--r-- | core/java/android/text/StaticLayout.java | 51 |
1 files changed, 41 insertions, 10 deletions
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index 6a7db4ed4e27..dd82e1e0b5d2 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -90,6 +90,7 @@ public class StaticLayout extends Layout { b.mSpacingMult = 1.0f; b.mSpacingAdd = 0.0f; b.mIncludePad = true; + b.mFallbackLineSpacing = false; b.mEllipsizedWidth = width; b.mEllipsize = null; b.mMaxLines = Integer.MAX_VALUE; @@ -228,6 +229,24 @@ public class StaticLayout extends Layout { } /** + * Set whether to respect the ascent and descent of the fallback fonts that are used in + * displaying the text (which is needed to avoid text from consecutive lines running into + * each other). If set, fallback fonts that end up getting used can increase the ascent + * and descent of the lines that they are used on. + * + * <p>For backward compatibility reasons, the default is {@code false}, but setting this to + * true is strongly recommended. It is required to be true if text could be in languages + * like Burmese or Tibetan where text is typically much taller or deeper than Latin text. + * + * @param useLineSpacingFromFallbacks whether to expand linespacing based on fallback fonts + * @return this builder, useful for chaining + */ + public Builder setUseLineSpacingFromFallbacks(boolean useLineSpacingFromFallbacks) { + mFallbackLineSpacing = useLineSpacingFromFallbacks; + return this; + } + + /** * Set the width as used for ellipsizing purposes, if it differs from the * normal layout width. The default is the {@code width} * passed to {@link #obtain}. @@ -432,6 +451,7 @@ public class StaticLayout extends Layout { float mSpacingMult; float mSpacingAdd; boolean mIncludePad; + boolean mFallbackLineSpacing; int mEllipsizedWidth; TextUtils.TruncateAt mEllipsize; int mMaxLines; @@ -606,6 +626,7 @@ public class StaticLayout extends Layout { TextPaint paint = b.mPaint; int outerWidth = b.mWidth; TextDirectionHeuristic textDir = b.mTextDir; + final boolean fallbackLineSpacing = b.mFallbackLineSpacing; float spacingmult = b.mSpacingMult; float spacingadd = b.mSpacingAdd; float ellipsizedWidth = b.mEllipsizedWidth; @@ -784,11 +805,14 @@ public class StaticLayout extends Layout { nGetWidths(b.mNativePtr, widths); int breakCount = nComputeLineBreaks(b.mNativePtr, lineBreaks, lineBreaks.breaks, - lineBreaks.widths, lineBreaks.flags, lineBreaks.breaks.length); + lineBreaks.widths, lineBreaks.ascents, lineBreaks.descents, lineBreaks.flags, + lineBreaks.breaks.length); - int[] breaks = lineBreaks.breaks; - float[] lineWidths = lineBreaks.widths; - int[] flags = lineBreaks.flags; + final int[] breaks = lineBreaks.breaks; + final float[] lineWidths = lineBreaks.widths; + final float[] ascents = lineBreaks.ascents; + final float[] descents = lineBreaks.descents; + final int[] flags = lineBreaks.flags; final int remainingLineCount = mMaximumVisibleLineCount - mLineCount; final boolean ellipsisMayBeApplied = ellipsize != null @@ -799,7 +823,7 @@ public class StaticLayout extends Layout { && ellipsisMayBeApplied) { // Calculate width and flag. float width = 0; - int flag = 0; + int flag = 0; // XXX May need to also have starting hyphen edit for (int i = remainingLineCount - 1; i < breakCount; i++) { if (i == breakCount - 1) { width += lineWidths[i]; @@ -808,7 +832,7 @@ public class StaticLayout extends Layout { width += widths[j]; } } - flag |= flags[i] & TAB_MASK; // XXX May need to also have starting hyphen edit + flag |= flags[i] & TAB_MASK; } // Treat the last line and overflowed lines as a single line. breaks[remainingLineCount - 1] = breaks[breakCount - 1]; @@ -859,8 +883,14 @@ public class StaticLayout extends Layout { boolean moreChars = (endPos < bufEnd); + final int ascent = fallbackLineSpacing + ? Math.min(fmAscent, (int) Math.round(ascents[breakIndex])) + : fmAscent; + final int descent = fallbackLineSpacing + ? Math.max(fmDescent, (int) Math.round(descents[breakIndex])) + : fmDescent; v = out(source, here, endPos, - fmAscent, fmDescent, fmTop, fmBottom, + ascent, descent, fmTop, fmBottom, v, spacingmult, spacingadd, chooseHt, chooseHtv, fm, flags[breakIndex], needMultiply, chdirs, dir, easy, bufEnd, includepad, trackpad, addLastLineSpacing, chs, widths, paraStart, ellipsize, @@ -891,8 +921,6 @@ public class StaticLayout extends Layout { if ((bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE) && mLineCount < mMaximumVisibleLineCount) { - // Log.e("text", "output last " + bufEnd); - measured.setPara(source, bufEnd, bufEnd, textDir, b); paint.getFontMetricsInt(fm); @@ -1470,7 +1498,8 @@ public class StaticLayout extends Layout { // to reduce the number of JNI calls in the common case where the // arrays do not have to be resized private static native int nComputeLineBreaks(long nativePtr, LineBreaks recycle, - int[] recycleBreaks, float[] recycleWidths, int[] recycleFlags, int recycleLength); + int[] recycleBreaks, float[] recycleWidths, float[] recycleAscents, + float[] recycleDescents, int[] recycleFlags, int recycleLength); private int mLineCount; private int mTopPadding, mBottomPadding; @@ -1529,6 +1558,8 @@ public class StaticLayout extends Layout { private static final int INITIAL_SIZE = 16; public int[] breaks = new int[INITIAL_SIZE]; public float[] widths = new float[INITIAL_SIZE]; + public float[] ascents = new float[INITIAL_SIZE]; + public float[] descents = new float[INITIAL_SIZE]; public int[] flags = new int[INITIAL_SIZE]; // hasTab // breaks, widths, and flags should all have the same length } |
