Loading apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java +11 −0 Original line number Original line Diff line number Diff line Loading @@ -88,4 +88,15 @@ public class StaticLayoutPerfTest { .build(); .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(); } } } } core/java/android/text/StaticLayout.java +2 −4 Original line number Original line Diff line number Diff line Loading @@ -780,9 +780,7 @@ public class StaticLayout extends Layout { firstWidth, firstWidthLineCount, restWidth, firstWidth, firstWidthLineCount, restWidth, variableTabStops, TAB_INCREMENT, b.mBreakStrategy, b.mHyphenationFrequency, variableTabStops, TAB_INCREMENT, b.mBreakStrategy, b.mHyphenationFrequency, // TODO: Support more justification mode, e.g. letter spacing, stretching. // TODO: Support more justification mode, e.g. letter spacing, stretching. b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE, b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE, indents, mLineCount); (indents != null && indents.length > mLineCount) ? indents : null, mLineCount); // measurement has to be done before performing line breaking // measurement has to be done before performing line breaking // but we don't want to recompute fontmetrics or span ranges the // but we don't want to recompute fontmetrics or span ranges the Loading Loading @@ -1506,7 +1504,7 @@ public class StaticLayout extends Layout { @FloatRange(from = 0.0f) float restWidth, @Nullable int[] variableTabStops, @FloatRange(from = 0.0f) float restWidth, @Nullable int[] variableTabStops, int defaultTabStop, @BreakStrategy int breakStrategy, int defaultTabStop, @BreakStrategy int breakStrategy, @HyphenationFrequency int hyphenationFrequency, boolean isJustified, @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, private static native float nAddStyleRun(long nativePtr, long nativePaint, int start, int end, boolean isRtl); boolean isRtl); Loading core/jni/android_text_StaticLayout.cpp +35 −9 Original line number Original line Diff line number Diff line Loading @@ -52,17 +52,46 @@ struct JLineBreaksID { static jclass gLineBreaks_class; static jclass gLineBreaks_class; static JLineBreaksID gLineBreaks_fieldID; static JLineBreaksID gLineBreaks_fieldID; class JNILineBreakerLineWidth : public minikin::LineBreaker::LineWidthDelegate { public: JNILineBreakerLineWidth(float firstWidth, int32_t firstLineCount, float restWidth, std::vector<float>&& 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<float> mIndents; const int32_t mIndentsOffset; }; // set text and set a number of parameters for creating a layout (width, tabstops, strategy, // set text and set a number of parameters for creating a layout (width, tabstops, strategy, // hyphenFrequency) // hyphenFrequency) static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray text, jint length, static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray text, jint length, jfloat firstWidth, jint firstWidthLineLimit, jfloat restWidth, jfloat firstWidth, jint firstWidthLineLimit, jfloat restWidth, jintArray variableTabStops, jint defaultTabStop, jint strategy, jint hyphenFrequency, 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<minikin::LineBreaker*>(nativePtr); minikin::LineBreaker* b = reinterpret_cast<minikin::LineBreaker*>(nativePtr); b->resize(length); b->resize(length); env->GetCharArrayRegion(text, 0, length, b->buffer()); env->GetCharArrayRegion(text, 0, length, b->buffer()); b->setText(); b->setText(); b->setLineWidths(firstWidth, firstWidthLineLimit, restWidth); if (variableTabStops == nullptr) { if (variableTabStops == nullptr) { b->setTabStops(nullptr, 0, defaultTabStop); b->setTabStops(nullptr, 0, defaultTabStop); } else { } else { Loading @@ -73,17 +102,14 @@ static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray tex b->setHyphenationFrequency(static_cast<minikin::HyphenationFrequency>(hyphenFrequency)); b->setHyphenationFrequency(static_cast<minikin::HyphenationFrequency>(hyphenFrequency)); b->setJustified(isJustified); b->setJustified(isJustified); std::vector<float> indentVec; // TODO: copy indents only once when LineBreaker is started to be used. // TODO: copy indents only once when LineBreaker is started to be used. if (indents != nullptr) { if (indents != nullptr) { // If indents is not null, it is guaranteed that lineOffset is less than the size of array. ScopedIntArrayRO indentArr(env, indents); ScopedIntArrayRO indentArr(env, indents); std::vector<float> indentVec( indentVec.assign(indentArr.get(), indentArr.get() + indentArr.size()); indentArr.get() + insetsOffset, indentArr.get() + indentArr.size()); b->setIndents(indentVec); } else { b->setIndents(std::vector<float>()); } } b->setLineWidthDelegate(std::make_unique<JNILineBreakerLineWidth>( firstWidth, firstWidthLineLimit, restWidth, std::move(indentVec), indentsOffset)); } } static void recycleCopy(JNIEnv* env, jobject recycle, jintArray recycleBreaks, static void recycleCopy(JNIEnv* env, jobject recycle, jintArray recycleBreaks, Loading Loading
apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java +11 −0 Original line number Original line Diff line number Diff line Loading @@ -88,4 +88,15 @@ public class StaticLayoutPerfTest { .build(); .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(); } } } }
core/java/android/text/StaticLayout.java +2 −4 Original line number Original line Diff line number Diff line Loading @@ -780,9 +780,7 @@ public class StaticLayout extends Layout { firstWidth, firstWidthLineCount, restWidth, firstWidth, firstWidthLineCount, restWidth, variableTabStops, TAB_INCREMENT, b.mBreakStrategy, b.mHyphenationFrequency, variableTabStops, TAB_INCREMENT, b.mBreakStrategy, b.mHyphenationFrequency, // TODO: Support more justification mode, e.g. letter spacing, stretching. // TODO: Support more justification mode, e.g. letter spacing, stretching. b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE, b.mJustificationMode != Layout.JUSTIFICATION_MODE_NONE, indents, mLineCount); (indents != null && indents.length > mLineCount) ? indents : null, mLineCount); // measurement has to be done before performing line breaking // measurement has to be done before performing line breaking // but we don't want to recompute fontmetrics or span ranges the // but we don't want to recompute fontmetrics or span ranges the Loading Loading @@ -1506,7 +1504,7 @@ public class StaticLayout extends Layout { @FloatRange(from = 0.0f) float restWidth, @Nullable int[] variableTabStops, @FloatRange(from = 0.0f) float restWidth, @Nullable int[] variableTabStops, int defaultTabStop, @BreakStrategy int breakStrategy, int defaultTabStop, @BreakStrategy int breakStrategy, @HyphenationFrequency int hyphenationFrequency, boolean isJustified, @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, private static native float nAddStyleRun(long nativePtr, long nativePaint, int start, int end, boolean isRtl); boolean isRtl); Loading
core/jni/android_text_StaticLayout.cpp +35 −9 Original line number Original line Diff line number Diff line Loading @@ -52,17 +52,46 @@ struct JLineBreaksID { static jclass gLineBreaks_class; static jclass gLineBreaks_class; static JLineBreaksID gLineBreaks_fieldID; static JLineBreaksID gLineBreaks_fieldID; class JNILineBreakerLineWidth : public minikin::LineBreaker::LineWidthDelegate { public: JNILineBreakerLineWidth(float firstWidth, int32_t firstLineCount, float restWidth, std::vector<float>&& 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<float> mIndents; const int32_t mIndentsOffset; }; // set text and set a number of parameters for creating a layout (width, tabstops, strategy, // set text and set a number of parameters for creating a layout (width, tabstops, strategy, // hyphenFrequency) // hyphenFrequency) static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray text, jint length, static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray text, jint length, jfloat firstWidth, jint firstWidthLineLimit, jfloat restWidth, jfloat firstWidth, jint firstWidthLineLimit, jfloat restWidth, jintArray variableTabStops, jint defaultTabStop, jint strategy, jint hyphenFrequency, 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<minikin::LineBreaker*>(nativePtr); minikin::LineBreaker* b = reinterpret_cast<minikin::LineBreaker*>(nativePtr); b->resize(length); b->resize(length); env->GetCharArrayRegion(text, 0, length, b->buffer()); env->GetCharArrayRegion(text, 0, length, b->buffer()); b->setText(); b->setText(); b->setLineWidths(firstWidth, firstWidthLineLimit, restWidth); if (variableTabStops == nullptr) { if (variableTabStops == nullptr) { b->setTabStops(nullptr, 0, defaultTabStop); b->setTabStops(nullptr, 0, defaultTabStop); } else { } else { Loading @@ -73,17 +102,14 @@ static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray tex b->setHyphenationFrequency(static_cast<minikin::HyphenationFrequency>(hyphenFrequency)); b->setHyphenationFrequency(static_cast<minikin::HyphenationFrequency>(hyphenFrequency)); b->setJustified(isJustified); b->setJustified(isJustified); std::vector<float> indentVec; // TODO: copy indents only once when LineBreaker is started to be used. // TODO: copy indents only once when LineBreaker is started to be used. if (indents != nullptr) { if (indents != nullptr) { // If indents is not null, it is guaranteed that lineOffset is less than the size of array. ScopedIntArrayRO indentArr(env, indents); ScopedIntArrayRO indentArr(env, indents); std::vector<float> indentVec( indentVec.assign(indentArr.get(), indentArr.get() + indentArr.size()); indentArr.get() + insetsOffset, indentArr.get() + indentArr.size()); b->setIndents(indentVec); } else { b->setIndents(std::vector<float>()); } } b->setLineWidthDelegate(std::make_unique<JNILineBreakerLineWidth>( firstWidth, firstWidthLineLimit, restWidth, std::move(indentVec), indentsOffset)); } } static void recycleCopy(JNIEnv* env, jobject recycle, jintArray recycleBreaks, static void recycleCopy(JNIEnv* env, jobject recycle, jintArray recycleBreaks, Loading