Loading core/java/android/text/Layout.java +1 −1 Original line number Diff line number Diff line Loading @@ -1910,7 +1910,7 @@ public abstract class Layout { MeasuredText mt = MeasuredText.obtain(); TextLine tl = TextLine.obtain(); try { mt.setPara(text, start, end, textDir, null); mt.setPara(text, start, end, textDir); Directions directions; int dir; if (mt.mEasy) { Loading core/java/android/text/MeasuredText.java +24 −19 Original line number Diff line number Diff line Loading @@ -39,7 +39,6 @@ class MeasuredText { private int mPos; private TextPaint mWorkPaint; private StaticLayout.Builder mBuilder; private MeasuredText() { mWorkPaint = new TextPaint(); Loading Loading @@ -82,7 +81,6 @@ class MeasuredText { void finish() { mText = null; mBuilder = null; if (mLen > 1000) { mWidths = null; mChars = null; Loading @@ -93,9 +91,7 @@ class MeasuredText { /** * Analyzes text for bidirectional runs. Allocates working buffers. */ void setPara(CharSequence text, int start, int end, TextDirectionHeuristic textDir, StaticLayout.Builder builder) { mBuilder = builder; void setPara(CharSequence text, int start, int end, TextDirectionHeuristic textDir) { mText = text; mTextStart = start; Loading Loading @@ -159,12 +155,12 @@ class MeasuredText { /** * Apply the style. * * If StaticLyaout.Builder is not provided in setPara() method, this method measures the styled * text width. * If StaticLayout.Builder is provided in setPara() method, this method just passes the style * information to native code by calling StaticLayout.Builder.addstyleRun() and returns 0. * If nativeStaticLayoutPtr is 0, this method measures the styled text width. * If nativeStaticLayoutPtr is not 0, this method just passes the style information to native * code by calling StaticLayout.addstyleRun() and returns 0. */ float addStyleRun(TextPaint paint, int len, Paint.FontMetricsInt fm) { float addStyleRun(TextPaint paint, int len, Paint.FontMetricsInt fm, long nativeStaticLayoutPtr) { if (fm != null) { paint.getFontMetricsInt(fm); } Loading @@ -174,10 +170,10 @@ class MeasuredText { if (mEasy) { final boolean isRtl = mDir != Layout.DIR_LEFT_TO_RIGHT; if (mBuilder == null) { if (nativeStaticLayoutPtr == 0) { return paint.getTextRunAdvances(mChars, p, len, p, len, isRtl, mWidths, p); } else { mBuilder.addStyleRun(paint, p, p + len, isRtl); StaticLayout.addStyleRun(nativeStaticLayoutPtr, paint, p, p + len, isRtl); return 0.0f; // Builder.addStyleRun doesn't return the width. } } Loading @@ -187,12 +183,12 @@ class MeasuredText { for (int q = p, i = p + 1, e = p + len;; ++i) { if (i == e || mLevels[i] != level) { final boolean isRtl = (level & 0x1) != 0; if (mBuilder == null) { if (nativeStaticLayoutPtr == 0) { totalAdvance += paint.getTextRunAdvances(mChars, q, i - q, q, i - q, isRtl, mWidths, q); } else { // Builder.addStyleRun doesn't return the width. mBuilder.addStyleRun(paint, q, i, isRtl); StaticLayout.addStyleRun(nativeStaticLayoutPtr, paint, q, i, isRtl); } if (i == e) { break; Loading @@ -201,11 +197,15 @@ class MeasuredText { level = mLevels[i]; } } return totalAdvance; // If mBuilder is null, the result is zero. return totalAdvance; // If nativeStaticLayoutPtr is 0, the result is zero. } float addStyleRun(TextPaint paint, int len, Paint.FontMetricsInt fm) { return addStyleRun(paint, len, fm, 0 /* native ptr */); } float addStyleRun(TextPaint paint, MetricAffectingSpan[] spans, int len, Paint.FontMetricsInt fm) { Paint.FontMetricsInt fm, long nativeStaticLayoutPtr) { TextPaint workPaint = mWorkPaint; workPaint.set(paint); Loading @@ -224,18 +224,18 @@ class MeasuredText { float wid; if (replacement == null) { wid = addStyleRun(workPaint, len, fm); wid = addStyleRun(workPaint, len, fm, nativeStaticLayoutPtr); } else { // Use original text. Shouldn't matter. wid = replacement.getSize(workPaint, mText, mTextStart + mPos, mTextStart + mPos + len, fm); if (mBuilder == null) { if (nativeStaticLayoutPtr == 0) { float[] w = mWidths; w[mPos] = wid; for (int i = mPos + 1, e = mPos + len; i < e; i++) w[i] = 0; } else { mBuilder.addReplacementRun(paint, mPos, mPos + len, wid); StaticLayout.addReplacementRun(nativeStaticLayoutPtr, paint, mPos, mPos + len, wid); } mPos += len; } Loading @@ -253,6 +253,11 @@ class MeasuredText { return wid; } float addStyleRun(TextPaint paint, MetricAffectingSpan[] spans, int len, Paint.FontMetricsInt fm) { return addStyleRun(paint, spans, len, fm, 0 /* native ptr */); } int breakText(int limit, boolean forwards, float width) { float[] w = mWidths; if (forwards) { Loading core/java/android/text/StaticLayout.java +321 −292 Original line number Diff line number Diff line Loading @@ -32,6 +32,9 @@ import android.util.Pools.SynchronizedPool; import com.android.internal.util.ArrayUtils; import com.android.internal.util.GrowingArrayUtils; import dalvik.annotation.optimization.CriticalNative; import dalvik.annotation.optimization.FastNative; import java.util.Arrays; /** Loading @@ -57,9 +60,7 @@ public class StaticLayout extends Layout { * default values. */ public final static class Builder { private Builder() { mNativePtr = nNewBuilder(); } private Builder() {} /** * Obtain a builder for constructing StaticLayout objects. Loading Loading @@ -116,13 +117,11 @@ public class StaticLayout extends Layout { b.mRightIndents = null; b.mLeftPaddings = null; b.mRightPaddings = null; nFinishBuilder(b.mNativePtr); sPool.release(b); } // release any expensive state /* package */ void finish() { nFinishBuilder(mNativePtr); mText = null; mPaint = null; mLeftIndents = null; Loading Loading @@ -404,32 +403,6 @@ public class StaticLayout extends Layout { return this; } /** * Measurement and break iteration is done in native code. The protocol for using * the native code is as follows. * * For each paragraph, do a nSetupParagraph, which sets paragraph text, line width, tab * stops, break strategy, and hyphenation frequency (and possibly other parameters in the * future). * * Then, for each run within the paragraph: * - one of the following, depending on the type of run: * + addStyleRun (a text run, to be measured in native code) * + addReplacementRun (a replacement run, width is given) * * Run nComputeLineBreaks() to obtain line breaks for the paragraph. * * After all paragraphs, call finish() to release expensive buffers. */ /* package */ void addStyleRun(TextPaint paint, int start, int end, boolean isRtl) { nAddStyleRun(mNativePtr, paint.getNativeInstance(), start, end, isRtl); } /* package */ void addReplacementRun(TextPaint paint, int start, int end, float width) { nAddReplacementRun(mNativePtr, paint.getNativeInstance(), start, end, width); } /** * Build the {@link StaticLayout} after options have been set. * Loading @@ -446,17 +419,6 @@ public class StaticLayout extends Layout { return result; } @Override protected void finalize() throws Throwable { try { nFreeBuilder(mNativePtr); } finally { super.finalize(); } } /* package */ long mNativePtr; private CharSequence mText; private int mStart; private int mEnd; Loading Loading @@ -694,13 +656,21 @@ public class StaticLayout extends Layout { indents = null; } final long nativePtr = nInit( b.mBreakStrategy, b.mHyphenationFrequency, // TODO: Support more justification mode, e.g. letter spacing, stretching. b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE, indents, mLeftPaddings, mRightPaddings); try { int paraEnd; for (int paraStart = bufStart; paraStart <= bufEnd; paraStart = paraEnd) { paraEnd = TextUtils.indexOf(source, CHAR_NEW_LINE, paraStart, bufEnd); if (paraEnd < 0) if (paraEnd < 0) { paraEnd = bufEnd; else } else { paraEnd++; } int firstWidthLineCount = 1; int firstWidth = outerWidth; Loading Loading @@ -730,8 +700,7 @@ public class StaticLayout extends Layout { if (chooseHt.length == 0) { chooseHt = null; // So that out() would not assume it has any contents } else { if (chooseHtv == null || chooseHtv.length < chooseHt.length) { if (chooseHtv == null || chooseHtv.length < chooseHt.length) { chooseHtv = ArrayUtils.newUnpaddedIntArray(chooseHt.length); } Loading @@ -752,7 +721,7 @@ public class StaticLayout extends Layout { } } measured.setPara(source, paraStart, paraEnd, textDir, b); measured.setPara(source, paraStart, paraEnd, textDir); char[] chs = measured.mChars; float[] widths = measured.mWidths; byte[] chdirs = measured.mLevels; Loading @@ -774,15 +743,6 @@ public class StaticLayout extends Layout { } } nSetupParagraph(b.mNativePtr, chs, paraEnd - paraStart, firstWidth, firstWidthLineCount, restWidth, variableTabStops, TAB_INCREMENT, b.mBreakStrategy, b.mHyphenationFrequency, // TODO: Support more justification mode, e.g. letter spacing, stretching. b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE, // TODO: indents and paddings don't need to get passed to native code for every // paragraph. Pass them to native code just once. indents, mLeftPaddings, mRightPaddings, mLineCount); // measurement has to be done before performing line breaking // but we don't want to recompute fontmetrics or span ranges the // second time, so we cache those and then use those stored values Loading @@ -804,19 +764,20 @@ public class StaticLayout extends Layout { if (spanned == null) { spanEnd = paraEnd; int spanLen = spanEnd - spanStart; measured.addStyleRun(paint, spanLen, fm); measured.addStyleRun(paint, spanLen, fm, nativePtr); } else { spanEnd = spanned.nextSpanTransition(spanStart, paraEnd, MetricAffectingSpan.class); int spanLen = spanEnd - spanStart; MetricAffectingSpan[] spans = spanned.getSpans(spanStart, spanEnd, MetricAffectingSpan.class); spans = TextUtils.removeEmptySpans(spans, spanned, MetricAffectingSpan.class); measured.addStyleRun(paint, spans, spanLen, fm); spans = TextUtils.removeEmptySpans(spans, spanned, MetricAffectingSpan.class); measured.addStyleRun(paint, spans, spanLen, fm, nativePtr); } // the order of storage here (top, bottom, ascent, descent) has to match the code below // where these values are retrieved // the order of storage here (top, bottom, ascent, descent) has to match the // code below where these values are retrieved fmCache[fmCacheCount * 4 + 0] = fm.top; fmCache[fmCacheCount * 4 + 1] = fm.bottom; fmCache[fmCacheCount * 4 + 2] = fm.ascent; Loading @@ -827,9 +788,28 @@ public class StaticLayout extends Layout { spanEndCacheCount++; } int breakCount = nComputeLineBreaks(b.mNativePtr, lineBreaks, lineBreaks.breaks, lineBreaks.widths, lineBreaks.ascents, lineBreaks.descents, lineBreaks.flags, lineBreaks.breaks.length, widths); int breakCount = nComputeLineBreaks( nativePtr, // Inputs chs, paraEnd - paraStart, firstWidth, firstWidthLineCount, restWidth, variableTabStops, TAB_INCREMENT, mLineCount, // Outputs lineBreaks, lineBreaks.breaks.length, lineBreaks.breaks, lineBreaks.widths, lineBreaks.ascents, lineBreaks.descents, lineBreaks.flags, widths); final int[] breaks = lineBreaks.breaks; final float[] lineWidths = lineBreaks.widths; Loading Loading @@ -865,7 +845,8 @@ public class StaticLayout extends Layout { breakCount = remainingLineCount; } // here is the offset of the starting character of the line we are currently measuring // here is the offset of the starting character of the line we are currently // measuring int here = paraStart; int fmTop = 0, fmBottom = 0, fmAscent = 0, fmDescent = 0; Loading Loading @@ -914,10 +895,11 @@ public class StaticLayout extends Layout { : fmDescent; v = out(source, here, endPos, ascent, descent, fmTop, fmBottom, v, spacingmult, spacingadd, chooseHt, chooseHtv, fm, flags[breakIndex], needMultiply, chdirs, dir, easy, bufEnd, includepad, trackpad, addLastLineSpacing, chs, widths, paraStart, ellipsize, ellipsizedWidth, lineWidths[breakIndex], paint, moreChars); v, spacingmult, spacingadd, chooseHt, chooseHtv, fm, flags[breakIndex], needMultiply, chdirs, dir, easy, bufEnd, includepad, trackpad, addLastLineSpacing, chs, widths, paraStart, ellipsize, ellipsizedWidth, lineWidths[breakIndex], paint, moreChars); if (endPos < spanEnd) { // preserve metrics for current span Loading @@ -938,13 +920,14 @@ public class StaticLayout extends Layout { } } if (paraEnd == bufEnd) if (paraEnd == bufEnd) { break; } } if ((bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE) && mLineCount < mMaximumVisibleLineCount) { measured.setPara(source, bufEnd, bufEnd, textDir, b); if ((bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE) && mLineCount < mMaximumVisibleLineCount) { measured.setPara(source, bufEnd, bufEnd, textDir); paint.getFontMetricsInt(fm); Loading @@ -959,6 +942,9 @@ public class StaticLayout extends Layout { null, bufStart, ellipsize, ellipsizedWidth, 0, paint, false); } } finally { nFinish(nativePtr); } } // The parameters that are not changed in the method are marked as final to make the code Loading Loading @@ -1487,26 +1473,51 @@ public class StaticLayout extends Layout { mMaxLineHeight : super.getHeight(); } private static native long nNewBuilder(); private static native void nFreeBuilder(long nativePtr); private static native void nFinishBuilder(long nativePtr); /** * Measurement and break iteration is done in native code. The protocol for using * the native code is as follows. * * First, call nInit to setup native line breaker object. Then, for each paragraph, do the * following: * * - Call one of the following methods for each run within the paragraph depending on the type * of run: * + addStyleRun (a text run, to be measured in native code) * + addReplacementRun (a replacement run, width is given) * * - Run nComputeLineBreaks() to obtain line breaks for the paragraph. * * After all paragraphs, call finish() to release expensive buffers. */ /* package */ static void addStyleRun(long nativePtr, TextPaint paint, int start, int end, boolean isRtl) { nAddStyleRun(nativePtr, paint.getNativeInstance(), start, end, isRtl); } /* package */ static void addReplacementRun(long nativePtr, TextPaint paint, int start, int end, float width) { nAddReplacementRun(nativePtr, paint.getNativeInstance(), start, end, width); } @FastNative private static native long nInit( @BreakStrategy int breakStrategy, @HyphenationFrequency int hyphenationFrequency, boolean isJustified, @Nullable int[] indents, @Nullable int[] leftPaddings, @Nullable int[] rightPaddings); // Set up paragraph text and settings; done as one big method to minimize jni crossings private static native void nSetupParagraph( /* non zero */ long nativePtr, @NonNull char[] text, @IntRange(from = 0) int length, @FloatRange(from = 0.0f) float firstWidth, @IntRange(from = 0) int firstWidthLineCount, @FloatRange(from = 0.0f) float restWidth, @Nullable int[] variableTabStops, int defaultTabStop, @BreakStrategy int breakStrategy, @HyphenationFrequency int hyphenationFrequency, boolean isJustified, @Nullable int[] indents, @Nullable int[] leftPaddings, @Nullable int[] rightPaddings, @IntRange(from = 0) int indentsOffset); @CriticalNative private static native void nFinish(long nativePtr); // TODO: Make this method CriticalNative once native code defers doing layouts. @CriticalNative private static native void nAddStyleRun( /* non-zero */ long nativePtr, /* non-zero */ long nativePaint, @IntRange(from = 0) int start, @IntRange(from = 0) int end, boolean isRtl); // TODO: Make this method CriticalNative once native code defers doing layouts. @CriticalNative private static native void nAddReplacementRun( /* non-zero */ long nativePtr, /* non-zero */ long nativePaint, @IntRange(from = 0) int start, @IntRange(from = 0) int end, Loading @@ -1519,10 +1530,28 @@ public class StaticLayout extends Layout { // arrays do not have to be resized // The individual character widths will be returned in charWidths. The length of charWidths must // be at least the length of the text. private static native int nComputeLineBreaks(long nativePtr, LineBreaks recycle, int[] recycleBreaks, float[] recycleWidths, float[] recycleAscents, float[] recycleDescents, int[] recycleFlags, int recycleLength, float[] charWidths); private static native int nComputeLineBreaks( /* non zero */ long nativePtr, // Inputs @NonNull char[] text, @IntRange(from = 0) int length, @FloatRange(from = 0.0f) float firstWidth, @IntRange(from = 0) int firstWidthLineCount, @FloatRange(from = 0.0f) float restWidth, @Nullable int[] variableTabStops, int defaultTabStop, @IntRange(from = 0) int indentsOffset, // Outputs @NonNull LineBreaks recycle, @IntRange(from = 0) int recycleLength, @NonNull int[] recycleBreaks, @NonNull float[] recycleWidths, @NonNull float[] recycleAscents, @NonNull float[] recycleDescents, @NonNull int[] recycleFlags, @NonNull float[] charWidths); private int mLineCount; private int mTopPadding, mBottomPadding; Loading core/java/android/text/TextUtils.java +2 −2 Original line number Diff line number Diff line Loading @@ -1519,7 +1519,7 @@ public class TextUtils { } // XXX this is probably ok, but need to look at it more tempMt.setPara(format, 0, format.length(), textDir, null); tempMt.setPara(format, 0, format.length(), textDir); float moreWid = tempMt.addStyleRun(p, tempMt.mLen, null); if (w + moreWid <= avail) { Loading @@ -1541,7 +1541,7 @@ public class TextUtils { private static float setPara(MeasuredText mt, TextPaint paint, CharSequence text, int start, int end, TextDirectionHeuristic textDir) { mt.setPara(text, start, end, textDir, null); mt.setPara(text, start, end, textDir); float width; Spanned sp = text instanceof Spanned ? (Spanned) text : null; Loading core/jni/android_text_StaticLayout.cpp +225 −69 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/text/Layout.java +1 −1 Original line number Diff line number Diff line Loading @@ -1910,7 +1910,7 @@ public abstract class Layout { MeasuredText mt = MeasuredText.obtain(); TextLine tl = TextLine.obtain(); try { mt.setPara(text, start, end, textDir, null); mt.setPara(text, start, end, textDir); Directions directions; int dir; if (mt.mEasy) { Loading
core/java/android/text/MeasuredText.java +24 −19 Original line number Diff line number Diff line Loading @@ -39,7 +39,6 @@ class MeasuredText { private int mPos; private TextPaint mWorkPaint; private StaticLayout.Builder mBuilder; private MeasuredText() { mWorkPaint = new TextPaint(); Loading Loading @@ -82,7 +81,6 @@ class MeasuredText { void finish() { mText = null; mBuilder = null; if (mLen > 1000) { mWidths = null; mChars = null; Loading @@ -93,9 +91,7 @@ class MeasuredText { /** * Analyzes text for bidirectional runs. Allocates working buffers. */ void setPara(CharSequence text, int start, int end, TextDirectionHeuristic textDir, StaticLayout.Builder builder) { mBuilder = builder; void setPara(CharSequence text, int start, int end, TextDirectionHeuristic textDir) { mText = text; mTextStart = start; Loading Loading @@ -159,12 +155,12 @@ class MeasuredText { /** * Apply the style. * * If StaticLyaout.Builder is not provided in setPara() method, this method measures the styled * text width. * If StaticLayout.Builder is provided in setPara() method, this method just passes the style * information to native code by calling StaticLayout.Builder.addstyleRun() and returns 0. * If nativeStaticLayoutPtr is 0, this method measures the styled text width. * If nativeStaticLayoutPtr is not 0, this method just passes the style information to native * code by calling StaticLayout.addstyleRun() and returns 0. */ float addStyleRun(TextPaint paint, int len, Paint.FontMetricsInt fm) { float addStyleRun(TextPaint paint, int len, Paint.FontMetricsInt fm, long nativeStaticLayoutPtr) { if (fm != null) { paint.getFontMetricsInt(fm); } Loading @@ -174,10 +170,10 @@ class MeasuredText { if (mEasy) { final boolean isRtl = mDir != Layout.DIR_LEFT_TO_RIGHT; if (mBuilder == null) { if (nativeStaticLayoutPtr == 0) { return paint.getTextRunAdvances(mChars, p, len, p, len, isRtl, mWidths, p); } else { mBuilder.addStyleRun(paint, p, p + len, isRtl); StaticLayout.addStyleRun(nativeStaticLayoutPtr, paint, p, p + len, isRtl); return 0.0f; // Builder.addStyleRun doesn't return the width. } } Loading @@ -187,12 +183,12 @@ class MeasuredText { for (int q = p, i = p + 1, e = p + len;; ++i) { if (i == e || mLevels[i] != level) { final boolean isRtl = (level & 0x1) != 0; if (mBuilder == null) { if (nativeStaticLayoutPtr == 0) { totalAdvance += paint.getTextRunAdvances(mChars, q, i - q, q, i - q, isRtl, mWidths, q); } else { // Builder.addStyleRun doesn't return the width. mBuilder.addStyleRun(paint, q, i, isRtl); StaticLayout.addStyleRun(nativeStaticLayoutPtr, paint, q, i, isRtl); } if (i == e) { break; Loading @@ -201,11 +197,15 @@ class MeasuredText { level = mLevels[i]; } } return totalAdvance; // If mBuilder is null, the result is zero. return totalAdvance; // If nativeStaticLayoutPtr is 0, the result is zero. } float addStyleRun(TextPaint paint, int len, Paint.FontMetricsInt fm) { return addStyleRun(paint, len, fm, 0 /* native ptr */); } float addStyleRun(TextPaint paint, MetricAffectingSpan[] spans, int len, Paint.FontMetricsInt fm) { Paint.FontMetricsInt fm, long nativeStaticLayoutPtr) { TextPaint workPaint = mWorkPaint; workPaint.set(paint); Loading @@ -224,18 +224,18 @@ class MeasuredText { float wid; if (replacement == null) { wid = addStyleRun(workPaint, len, fm); wid = addStyleRun(workPaint, len, fm, nativeStaticLayoutPtr); } else { // Use original text. Shouldn't matter. wid = replacement.getSize(workPaint, mText, mTextStart + mPos, mTextStart + mPos + len, fm); if (mBuilder == null) { if (nativeStaticLayoutPtr == 0) { float[] w = mWidths; w[mPos] = wid; for (int i = mPos + 1, e = mPos + len; i < e; i++) w[i] = 0; } else { mBuilder.addReplacementRun(paint, mPos, mPos + len, wid); StaticLayout.addReplacementRun(nativeStaticLayoutPtr, paint, mPos, mPos + len, wid); } mPos += len; } Loading @@ -253,6 +253,11 @@ class MeasuredText { return wid; } float addStyleRun(TextPaint paint, MetricAffectingSpan[] spans, int len, Paint.FontMetricsInt fm) { return addStyleRun(paint, spans, len, fm, 0 /* native ptr */); } int breakText(int limit, boolean forwards, float width) { float[] w = mWidths; if (forwards) { Loading
core/java/android/text/StaticLayout.java +321 −292 Original line number Diff line number Diff line Loading @@ -32,6 +32,9 @@ import android.util.Pools.SynchronizedPool; import com.android.internal.util.ArrayUtils; import com.android.internal.util.GrowingArrayUtils; import dalvik.annotation.optimization.CriticalNative; import dalvik.annotation.optimization.FastNative; import java.util.Arrays; /** Loading @@ -57,9 +60,7 @@ public class StaticLayout extends Layout { * default values. */ public final static class Builder { private Builder() { mNativePtr = nNewBuilder(); } private Builder() {} /** * Obtain a builder for constructing StaticLayout objects. Loading Loading @@ -116,13 +117,11 @@ public class StaticLayout extends Layout { b.mRightIndents = null; b.mLeftPaddings = null; b.mRightPaddings = null; nFinishBuilder(b.mNativePtr); sPool.release(b); } // release any expensive state /* package */ void finish() { nFinishBuilder(mNativePtr); mText = null; mPaint = null; mLeftIndents = null; Loading Loading @@ -404,32 +403,6 @@ public class StaticLayout extends Layout { return this; } /** * Measurement and break iteration is done in native code. The protocol for using * the native code is as follows. * * For each paragraph, do a nSetupParagraph, which sets paragraph text, line width, tab * stops, break strategy, and hyphenation frequency (and possibly other parameters in the * future). * * Then, for each run within the paragraph: * - one of the following, depending on the type of run: * + addStyleRun (a text run, to be measured in native code) * + addReplacementRun (a replacement run, width is given) * * Run nComputeLineBreaks() to obtain line breaks for the paragraph. * * After all paragraphs, call finish() to release expensive buffers. */ /* package */ void addStyleRun(TextPaint paint, int start, int end, boolean isRtl) { nAddStyleRun(mNativePtr, paint.getNativeInstance(), start, end, isRtl); } /* package */ void addReplacementRun(TextPaint paint, int start, int end, float width) { nAddReplacementRun(mNativePtr, paint.getNativeInstance(), start, end, width); } /** * Build the {@link StaticLayout} after options have been set. * Loading @@ -446,17 +419,6 @@ public class StaticLayout extends Layout { return result; } @Override protected void finalize() throws Throwable { try { nFreeBuilder(mNativePtr); } finally { super.finalize(); } } /* package */ long mNativePtr; private CharSequence mText; private int mStart; private int mEnd; Loading Loading @@ -694,13 +656,21 @@ public class StaticLayout extends Layout { indents = null; } final long nativePtr = nInit( b.mBreakStrategy, b.mHyphenationFrequency, // TODO: Support more justification mode, e.g. letter spacing, stretching. b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE, indents, mLeftPaddings, mRightPaddings); try { int paraEnd; for (int paraStart = bufStart; paraStart <= bufEnd; paraStart = paraEnd) { paraEnd = TextUtils.indexOf(source, CHAR_NEW_LINE, paraStart, bufEnd); if (paraEnd < 0) if (paraEnd < 0) { paraEnd = bufEnd; else } else { paraEnd++; } int firstWidthLineCount = 1; int firstWidth = outerWidth; Loading Loading @@ -730,8 +700,7 @@ public class StaticLayout extends Layout { if (chooseHt.length == 0) { chooseHt = null; // So that out() would not assume it has any contents } else { if (chooseHtv == null || chooseHtv.length < chooseHt.length) { if (chooseHtv == null || chooseHtv.length < chooseHt.length) { chooseHtv = ArrayUtils.newUnpaddedIntArray(chooseHt.length); } Loading @@ -752,7 +721,7 @@ public class StaticLayout extends Layout { } } measured.setPara(source, paraStart, paraEnd, textDir, b); measured.setPara(source, paraStart, paraEnd, textDir); char[] chs = measured.mChars; float[] widths = measured.mWidths; byte[] chdirs = measured.mLevels; Loading @@ -774,15 +743,6 @@ public class StaticLayout extends Layout { } } nSetupParagraph(b.mNativePtr, chs, paraEnd - paraStart, firstWidth, firstWidthLineCount, restWidth, variableTabStops, TAB_INCREMENT, b.mBreakStrategy, b.mHyphenationFrequency, // TODO: Support more justification mode, e.g. letter spacing, stretching. b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE, // TODO: indents and paddings don't need to get passed to native code for every // paragraph. Pass them to native code just once. indents, mLeftPaddings, mRightPaddings, mLineCount); // measurement has to be done before performing line breaking // but we don't want to recompute fontmetrics or span ranges the // second time, so we cache those and then use those stored values Loading @@ -804,19 +764,20 @@ public class StaticLayout extends Layout { if (spanned == null) { spanEnd = paraEnd; int spanLen = spanEnd - spanStart; measured.addStyleRun(paint, spanLen, fm); measured.addStyleRun(paint, spanLen, fm, nativePtr); } else { spanEnd = spanned.nextSpanTransition(spanStart, paraEnd, MetricAffectingSpan.class); int spanLen = spanEnd - spanStart; MetricAffectingSpan[] spans = spanned.getSpans(spanStart, spanEnd, MetricAffectingSpan.class); spans = TextUtils.removeEmptySpans(spans, spanned, MetricAffectingSpan.class); measured.addStyleRun(paint, spans, spanLen, fm); spans = TextUtils.removeEmptySpans(spans, spanned, MetricAffectingSpan.class); measured.addStyleRun(paint, spans, spanLen, fm, nativePtr); } // the order of storage here (top, bottom, ascent, descent) has to match the code below // where these values are retrieved // the order of storage here (top, bottom, ascent, descent) has to match the // code below where these values are retrieved fmCache[fmCacheCount * 4 + 0] = fm.top; fmCache[fmCacheCount * 4 + 1] = fm.bottom; fmCache[fmCacheCount * 4 + 2] = fm.ascent; Loading @@ -827,9 +788,28 @@ public class StaticLayout extends Layout { spanEndCacheCount++; } int breakCount = nComputeLineBreaks(b.mNativePtr, lineBreaks, lineBreaks.breaks, lineBreaks.widths, lineBreaks.ascents, lineBreaks.descents, lineBreaks.flags, lineBreaks.breaks.length, widths); int breakCount = nComputeLineBreaks( nativePtr, // Inputs chs, paraEnd - paraStart, firstWidth, firstWidthLineCount, restWidth, variableTabStops, TAB_INCREMENT, mLineCount, // Outputs lineBreaks, lineBreaks.breaks.length, lineBreaks.breaks, lineBreaks.widths, lineBreaks.ascents, lineBreaks.descents, lineBreaks.flags, widths); final int[] breaks = lineBreaks.breaks; final float[] lineWidths = lineBreaks.widths; Loading Loading @@ -865,7 +845,8 @@ public class StaticLayout extends Layout { breakCount = remainingLineCount; } // here is the offset of the starting character of the line we are currently measuring // here is the offset of the starting character of the line we are currently // measuring int here = paraStart; int fmTop = 0, fmBottom = 0, fmAscent = 0, fmDescent = 0; Loading Loading @@ -914,10 +895,11 @@ public class StaticLayout extends Layout { : fmDescent; v = out(source, here, endPos, ascent, descent, fmTop, fmBottom, v, spacingmult, spacingadd, chooseHt, chooseHtv, fm, flags[breakIndex], needMultiply, chdirs, dir, easy, bufEnd, includepad, trackpad, addLastLineSpacing, chs, widths, paraStart, ellipsize, ellipsizedWidth, lineWidths[breakIndex], paint, moreChars); v, spacingmult, spacingadd, chooseHt, chooseHtv, fm, flags[breakIndex], needMultiply, chdirs, dir, easy, bufEnd, includepad, trackpad, addLastLineSpacing, chs, widths, paraStart, ellipsize, ellipsizedWidth, lineWidths[breakIndex], paint, moreChars); if (endPos < spanEnd) { // preserve metrics for current span Loading @@ -938,13 +920,14 @@ public class StaticLayout extends Layout { } } if (paraEnd == bufEnd) if (paraEnd == bufEnd) { break; } } if ((bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE) && mLineCount < mMaximumVisibleLineCount) { measured.setPara(source, bufEnd, bufEnd, textDir, b); if ((bufEnd == bufStart || source.charAt(bufEnd - 1) == CHAR_NEW_LINE) && mLineCount < mMaximumVisibleLineCount) { measured.setPara(source, bufEnd, bufEnd, textDir); paint.getFontMetricsInt(fm); Loading @@ -959,6 +942,9 @@ public class StaticLayout extends Layout { null, bufStart, ellipsize, ellipsizedWidth, 0, paint, false); } } finally { nFinish(nativePtr); } } // The parameters that are not changed in the method are marked as final to make the code Loading Loading @@ -1487,26 +1473,51 @@ public class StaticLayout extends Layout { mMaxLineHeight : super.getHeight(); } private static native long nNewBuilder(); private static native void nFreeBuilder(long nativePtr); private static native void nFinishBuilder(long nativePtr); /** * Measurement and break iteration is done in native code. The protocol for using * the native code is as follows. * * First, call nInit to setup native line breaker object. Then, for each paragraph, do the * following: * * - Call one of the following methods for each run within the paragraph depending on the type * of run: * + addStyleRun (a text run, to be measured in native code) * + addReplacementRun (a replacement run, width is given) * * - Run nComputeLineBreaks() to obtain line breaks for the paragraph. * * After all paragraphs, call finish() to release expensive buffers. */ /* package */ static void addStyleRun(long nativePtr, TextPaint paint, int start, int end, boolean isRtl) { nAddStyleRun(nativePtr, paint.getNativeInstance(), start, end, isRtl); } /* package */ static void addReplacementRun(long nativePtr, TextPaint paint, int start, int end, float width) { nAddReplacementRun(nativePtr, paint.getNativeInstance(), start, end, width); } @FastNative private static native long nInit( @BreakStrategy int breakStrategy, @HyphenationFrequency int hyphenationFrequency, boolean isJustified, @Nullable int[] indents, @Nullable int[] leftPaddings, @Nullable int[] rightPaddings); // Set up paragraph text and settings; done as one big method to minimize jni crossings private static native void nSetupParagraph( /* non zero */ long nativePtr, @NonNull char[] text, @IntRange(from = 0) int length, @FloatRange(from = 0.0f) float firstWidth, @IntRange(from = 0) int firstWidthLineCount, @FloatRange(from = 0.0f) float restWidth, @Nullable int[] variableTabStops, int defaultTabStop, @BreakStrategy int breakStrategy, @HyphenationFrequency int hyphenationFrequency, boolean isJustified, @Nullable int[] indents, @Nullable int[] leftPaddings, @Nullable int[] rightPaddings, @IntRange(from = 0) int indentsOffset); @CriticalNative private static native void nFinish(long nativePtr); // TODO: Make this method CriticalNative once native code defers doing layouts. @CriticalNative private static native void nAddStyleRun( /* non-zero */ long nativePtr, /* non-zero */ long nativePaint, @IntRange(from = 0) int start, @IntRange(from = 0) int end, boolean isRtl); // TODO: Make this method CriticalNative once native code defers doing layouts. @CriticalNative private static native void nAddReplacementRun( /* non-zero */ long nativePtr, /* non-zero */ long nativePaint, @IntRange(from = 0) int start, @IntRange(from = 0) int end, Loading @@ -1519,10 +1530,28 @@ public class StaticLayout extends Layout { // arrays do not have to be resized // The individual character widths will be returned in charWidths. The length of charWidths must // be at least the length of the text. private static native int nComputeLineBreaks(long nativePtr, LineBreaks recycle, int[] recycleBreaks, float[] recycleWidths, float[] recycleAscents, float[] recycleDescents, int[] recycleFlags, int recycleLength, float[] charWidths); private static native int nComputeLineBreaks( /* non zero */ long nativePtr, // Inputs @NonNull char[] text, @IntRange(from = 0) int length, @FloatRange(from = 0.0f) float firstWidth, @IntRange(from = 0) int firstWidthLineCount, @FloatRange(from = 0.0f) float restWidth, @Nullable int[] variableTabStops, int defaultTabStop, @IntRange(from = 0) int indentsOffset, // Outputs @NonNull LineBreaks recycle, @IntRange(from = 0) int recycleLength, @NonNull int[] recycleBreaks, @NonNull float[] recycleWidths, @NonNull float[] recycleAscents, @NonNull float[] recycleDescents, @NonNull int[] recycleFlags, @NonNull float[] charWidths); private int mLineCount; private int mTopPadding, mBottomPadding; Loading
core/java/android/text/TextUtils.java +2 −2 Original line number Diff line number Diff line Loading @@ -1519,7 +1519,7 @@ public class TextUtils { } // XXX this is probably ok, but need to look at it more tempMt.setPara(format, 0, format.length(), textDir, null); tempMt.setPara(format, 0, format.length(), textDir); float moreWid = tempMt.addStyleRun(p, tempMt.mLen, null); if (w + moreWid <= avail) { Loading @@ -1541,7 +1541,7 @@ public class TextUtils { private static float setPara(MeasuredText mt, TextPaint paint, CharSequence text, int start, int end, TextDirectionHeuristic textDir) { mt.setPara(text, start, end, textDir, null); mt.setPara(text, start, end, textDir); float width; Spanned sp = text instanceof Spanned ? (Spanned) text : null; Loading
core/jni/android_text_StaticLayout.cpp +225 −69 File changed.Preview size limit exceeded, changes collapsed. Show changes