diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java index 74d136654c62f..57a61ec8218f5 100644 --- a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java +++ b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java @@ -88,4 +88,15 @@ public class StaticLayoutPerfTest { .build(); } } + + @Test + public void testCreateRandom_breakBalanced() { + final BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + while (state.keepRunning()) { + final CharSequence text = generateRandomParagraph(9); + StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH) + .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED) + .build(); + } + } } diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index 888bb00b6b582..c124c7fd6a0cc 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -780,9 +780,7 @@ public class StaticLayout extends Layout { 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, - (indents != null && indents.length > mLineCount) ? indents : null, - mLineCount); + b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE, indents, mLineCount); // measurement has to be done before performing line breaking // but we don't want to recompute fontmetrics or span ranges the @@ -1506,7 +1504,7 @@ public class StaticLayout extends Layout { @FloatRange(from = 0.0f) float restWidth, @Nullable int[] variableTabStops, int defaultTabStop, @BreakStrategy int breakStrategy, @HyphenationFrequency int hyphenationFrequency, boolean isJustified, - @Nullable int[] indents, @IntRange(from = 0) int intentsOffset); + @Nullable int[] indents, @IntRange(from = 0) int indentsOffset); private static native float nAddStyleRun(long nativePtr, long nativePaint, int start, int end, boolean isRtl); diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp index 15ab8f7d661ba..7442fa2d62dcc 100644 --- a/core/jni/android_text_StaticLayout.cpp +++ b/core/jni/android_text_StaticLayout.cpp @@ -52,17 +52,46 @@ struct JLineBreaksID { static jclass gLineBreaks_class; static JLineBreaksID gLineBreaks_fieldID; +class JNILineBreakerLineWidth : public minikin::LineBreaker::LineWidthDelegate { + public: + JNILineBreakerLineWidth(float firstWidth, int32_t firstLineCount, float restWidth, + std::vector&& indents, int32_t indentsOffset) + : mFirstWidth(firstWidth), mFirstLineCount(firstLineCount), mRestWidth(restWidth), + mIndents(std::move(indents)), mIndentsOffset(indentsOffset) {} + + float getLineWidth(size_t lineNo) override { + const float width = ((ssize_t)lineNo < (ssize_t)mFirstLineCount) + ? mFirstWidth : mRestWidth; + if (mIndents.empty()) { + return width; + } + + const size_t indentIndex = lineNo + mIndentsOffset; + if (indentIndex < mIndents.size()) { + return width - mIndents[indentIndex]; + } else { + return width - mIndents.back(); + } + } + + private: + const float mFirstWidth; + const int32_t mFirstLineCount; + const float mRestWidth; + const std::vector mIndents; + const int32_t mIndentsOffset; +}; + // set text and set a number of parameters for creating a layout (width, tabstops, strategy, // hyphenFrequency) static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray text, jint length, jfloat firstWidth, jint firstWidthLineLimit, jfloat restWidth, jintArray variableTabStops, jint defaultTabStop, jint strategy, jint hyphenFrequency, - jboolean isJustified, jintArray indents, jint insetsOffset) { + jboolean isJustified, jintArray indents, jint indentsOffset) { minikin::LineBreaker* b = reinterpret_cast(nativePtr); b->resize(length); env->GetCharArrayRegion(text, 0, length, b->buffer()); b->setText(); - b->setLineWidths(firstWidth, firstWidthLineLimit, restWidth); if (variableTabStops == nullptr) { b->setTabStops(nullptr, 0, defaultTabStop); } else { @@ -73,17 +102,14 @@ static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray tex b->setHyphenationFrequency(static_cast(hyphenFrequency)); b->setJustified(isJustified); + std::vector indentVec; // TODO: copy indents only once when LineBreaker is started to be used. if (indents != nullptr) { - // If indents is not null, it is guaranteed that lineOffset is less than the size of array. ScopedIntArrayRO indentArr(env, indents); - std::vector indentVec( - indentArr.get() + insetsOffset, indentArr.get() + indentArr.size()); - b->setIndents(indentVec); - } else { - b->setIndents(std::vector()); + indentVec.assign(indentArr.get(), indentArr.get() + indentArr.size()); } - + b->setLineWidthDelegate(std::make_unique( + firstWidth, firstWidthLineLimit, restWidth, std::move(indentVec), indentsOffset)); } static void recycleCopy(JNIEnv* env, jobject recycle, jintArray recycleBreaks,