Loading core/java/android/text/MeasuredText.java +3 −3 Original line number Diff line number Diff line Loading @@ -180,7 +180,7 @@ class MeasuredText { if (widths != null) { width = paint.getTextRunAdvances(mChars, p, len, p, len, isRtl, widths, p); if (mBuilder != null) { mBuilder.addMeasuredRun(p, p + len, widths); mBuilder.addMeasuredRun(paint, p, p + len, widths); } } else { width = mBuilder.addStyleRun(paint, p, p + len, isRtl); Loading @@ -197,7 +197,7 @@ class MeasuredText { totalAdvance += paint.getTextRunAdvances(mChars, q, i - q, q, i - q, isRtl, widths, q); if (mBuilder != null) { mBuilder.addMeasuredRun(q, i, widths); mBuilder.addMeasuredRun(paint, q, i, widths); } } else { totalAdvance += mBuilder.addStyleRun(paint, q, i, isRtl); Loading Loading @@ -243,7 +243,7 @@ class MeasuredText { for (int i = mPos + 1, e = mPos + len; i < e; i++) w[i] = 0; } else { mBuilder.addReplacementRun(mPos, mPos + len, wid); mBuilder.addReplacementRun(paint, mPos, mPos + len, wid); } mPos += len; } Loading core/java/android/text/StaticLayout.java +27 −14 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.text.style.LineHeightSpan; import android.text.style.MetricAffectingSpan; import android.text.style.TabStopSpan; import android.util.Log; import android.util.Pair; import android.util.Pools.SynchronizedPool; import com.android.internal.util.ArrayUtils; Loading Loading @@ -439,29 +440,34 @@ public class StaticLayout extends Layout { * After all paragraphs, call finish() to release expensive buffers. */ /* package */ float addStyleRun(TextPaint paint, int start, int end, boolean isRtl) { private Pair<String, long[]> getLocaleAndHyphenatorIfChanged(TextPaint paint) { final LocaleList locales = paint.getTextLocales(); final String languageTags; long[] hyphenators; if (!locales.equals(mLocales)) { languageTags = locales.toLanguageTags(); hyphenators = getHyphenators(locales); mLocales = locales; return new Pair(locales.toLanguageTags(), getHyphenators(locales)); } else { // passing null means keep current locale. // TODO: move locale change detection to native. languageTags = null; hyphenators = null; return new Pair(null, null); } } /* package */ float addStyleRun(TextPaint paint, int start, int end, boolean isRtl) { Pair<String, long[]> locHyph = getLocaleAndHyphenatorIfChanged(paint); return nAddStyleRun(mNativePtr, paint.getNativeInstance(), start, end, isRtl, languageTags, hyphenators); locHyph.first, locHyph.second); } /* package */ void addMeasuredRun(int start, int end, float[] widths) { nAddMeasuredRun(mNativePtr, start, end, widths); /* package */ void addMeasuredRun(TextPaint paint, int start, int end, float[] widths) { Pair<String, long[]> locHyph = getLocaleAndHyphenatorIfChanged(paint); nAddMeasuredRun(mNativePtr, start, end, widths, locHyph.first, locHyph.second); } /* package */ void addReplacementRun(int start, int end, float width) { nAddReplacementRun(mNativePtr, start, end, width); /* package */ void addReplacementRun(TextPaint paint, int start, int end, float width) { Pair<String, long[]> locHyph = getLocaleAndHyphenatorIfChanged(paint); nAddReplacementRun(mNativePtr, start, end, width, locHyph.first, locHyph.second); } /** Loading Loading @@ -810,6 +816,9 @@ public class StaticLayout extends Layout { } } // TODO: Move locale tracking code to native. b.mLocales = null; // Reset the locale tracking. nSetupParagraph(b.mNativePtr, chs, paraEnd - paraStart, firstWidth, firstWidthLineCount, restWidth, variableTabStops, TAB_INCREMENT, b.mBreakStrategy, b.mHyphenationFrequency, Loading Loading @@ -1539,14 +1548,18 @@ public class StaticLayout extends Layout { @IntRange(from = 0) int indentsOffset); private static native float nAddStyleRun( /* non zero */ long nativePtr, /* non zero */ long nativePaint, /* non-zero */ long nativePtr, /* non-zero */ long nativePaint, @IntRange(from = 0) int start, @IntRange(from = 0) int end, boolean isRtl, @Nullable String languageTags, @Nullable long[] hyphenators); private static native void nAddMeasuredRun(long nativePtr, int start, int end, float[] widths); private static native void nAddMeasuredRun(/* non-zero */ long nativePtr, @IntRange(from = 0) int start, @IntRange(from = 0) int end, @NonNull float[] widths, @Nullable String languageTags, @Nullable long[] hyphenators); private static native void nAddReplacementRun(long nativePtr, int start, int end, float width); private static native void nAddReplacementRun(/* non-zero */ long nativePtr, @IntRange(from = 0) int start, @IntRange(from = 0) int end, @FloatRange(from = 0.0f) float width, @Nullable String languageTags, @Nullable long[] hyphenators); private static native void nGetWidths(long nativePtr, float[] widths); Loading core/jni/android_text_StaticLayout.cpp +51 −23 Original line number Diff line number Diff line Loading @@ -193,6 +193,46 @@ static void nFinishBuilder(JNIEnv*, jclass, jlong nativePtr) { b->finish(); } class ScopedNullableUtfString { public: ScopedNullableUtfString(JNIEnv* env, jstring s) : mEnv(env), mStr(s) { if (s == nullptr) { mUtf8Chars = nullptr; } else { mUtf8Chars = mEnv->GetStringUTFChars(s, nullptr); } } ~ScopedNullableUtfString() { if (mUtf8Chars != nullptr) { mEnv->ReleaseStringUTFChars(mStr, mUtf8Chars); } } const char* get() const { return mUtf8Chars; } private: JNIEnv* mEnv; jstring mStr; const char* mUtf8Chars; }; static std::vector<minikin::Hyphenator*> makeHyphenators(JNIEnv* env, jlongArray hyphenators) { std::vector<minikin::Hyphenator*> out; if (hyphenators == nullptr) { return out; } ScopedLongArrayRO longArray(env, hyphenators); size_t size = longArray.size(); out.reserve(size); for (size_t i = 0; i < size; i++) { out.push_back(reinterpret_cast<minikin::Hyphenator*>(longArray[i])); } return out; } // Basically similar to Paint.getTextRunAdvances but with C++ interface static jfloat nAddStyleRun(JNIEnv* env, jclass, jlong nativePtr, jlong nativePaint, jint start, jint end, jboolean isRtl, jstring langTags, jlongArray hyphenators) { Loading @@ -204,40 +244,28 @@ static jfloat nAddStyleRun(JNIEnv* env, jclass, jlong nativePtr, jlong nativePai minikin::FontStyle style = MinikinUtils::prepareMinikinPaint(&minikinPaint, paint, typeface); std::vector<minikin::Hyphenator*> hyphVec; const char* langTagStr; if (langTags == nullptr) { langTagStr = nullptr; // nullptr languageTag means keeping current locale } else { ScopedLongArrayRO hyphArr(env, hyphenators); const size_t numLocales = hyphArr.size(); hyphVec.reserve(numLocales); for (size_t i = 0; i < numLocales; i++) { hyphVec.push_back(reinterpret_cast<minikin::Hyphenator*>(hyphArr[i])); } langTagStr = env->GetStringUTFChars(langTags, nullptr); } ScopedNullableUtfString langTagsString(env, langTags); float result = b->addStyleRun(&minikinPaint, resolvedTypeface->fFontCollection, style, start, end, isRtl, langTagStr, hyphVec); if (langTagStr != nullptr) { env->ReleaseStringUTFChars(langTags, langTagStr); } end, isRtl, langTagsString.get(), makeHyphenators(env, hyphenators)); return result; } // Accept width measurements for the run, passed in from Java static void nAddMeasuredRun(JNIEnv* env, jclass, jlong nativePtr, jint start, jint end, jfloatArray widths) { jint start, jint end, jfloatArray widths, jstring langTags, jlongArray hyphenators) { minikin::LineBreaker* b = reinterpret_cast<minikin::LineBreaker*>(nativePtr); env->GetFloatArrayRegion(widths, start, end - start, b->charWidths() + start); ScopedNullableUtfString langTagsString(env, langTags); b->addStyleRun(nullptr, nullptr, minikin::FontStyle{}, start, end, false, nullptr /* keep current locale */, std::vector<minikin::Hyphenator*>()); langTagsString.get(), makeHyphenators(env, hyphenators)); } static void nAddReplacementRun(JNIEnv* env, jclass, jlong nativePtr, jint start, jint end, jfloat width) { jint start, jint end, jfloat width, jstring langTags, jlongArray hyphenators) { minikin::LineBreaker* b = reinterpret_cast<minikin::LineBreaker*>(nativePtr); b->addReplacement(start, end, width); ScopedNullableUtfString langTagsString(env, langTags); b->addReplacement(start, end, width, langTagsString.get(), makeHyphenators(env, hyphenators)); } static void nGetWidths(JNIEnv* env, jclass, jlong nativePtr, jfloatArray widths) { Loading @@ -252,8 +280,8 @@ static const JNINativeMethod gMethods[] = { {"nFinishBuilder", "(J)V", (void*) nFinishBuilder}, {"nSetupParagraph", "(J[CIFIF[IIIIZ[I[I[II)V", (void*) nSetupParagraph}, {"nAddStyleRun", "(JJIIZLjava/lang/String;[J)F", (void*) nAddStyleRun}, {"nAddMeasuredRun", "(JII[F)V", (void*) nAddMeasuredRun}, {"nAddReplacementRun", "(JIIF)V", (void*) nAddReplacementRun}, {"nAddMeasuredRun", "(JII[FLjava/lang/String;[J)V", (void*) nAddMeasuredRun}, {"nAddReplacementRun", "(JIIFLjava/lang/String;[J)V", (void*) nAddReplacementRun}, {"nGetWidths", "(J[F)V", (void*) nGetWidths}, {"nComputeLineBreaks", "(JLandroid/text/StaticLayout$LineBreaks;[I[F[F[F[II)I", (void*) nComputeLineBreaks} Loading Loading
core/java/android/text/MeasuredText.java +3 −3 Original line number Diff line number Diff line Loading @@ -180,7 +180,7 @@ class MeasuredText { if (widths != null) { width = paint.getTextRunAdvances(mChars, p, len, p, len, isRtl, widths, p); if (mBuilder != null) { mBuilder.addMeasuredRun(p, p + len, widths); mBuilder.addMeasuredRun(paint, p, p + len, widths); } } else { width = mBuilder.addStyleRun(paint, p, p + len, isRtl); Loading @@ -197,7 +197,7 @@ class MeasuredText { totalAdvance += paint.getTextRunAdvances(mChars, q, i - q, q, i - q, isRtl, widths, q); if (mBuilder != null) { mBuilder.addMeasuredRun(q, i, widths); mBuilder.addMeasuredRun(paint, q, i, widths); } } else { totalAdvance += mBuilder.addStyleRun(paint, q, i, isRtl); Loading Loading @@ -243,7 +243,7 @@ class MeasuredText { for (int i = mPos + 1, e = mPos + len; i < e; i++) w[i] = 0; } else { mBuilder.addReplacementRun(mPos, mPos + len, wid); mBuilder.addReplacementRun(paint, mPos, mPos + len, wid); } mPos += len; } Loading
core/java/android/text/StaticLayout.java +27 −14 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import android.text.style.LineHeightSpan; import android.text.style.MetricAffectingSpan; import android.text.style.TabStopSpan; import android.util.Log; import android.util.Pair; import android.util.Pools.SynchronizedPool; import com.android.internal.util.ArrayUtils; Loading Loading @@ -439,29 +440,34 @@ public class StaticLayout extends Layout { * After all paragraphs, call finish() to release expensive buffers. */ /* package */ float addStyleRun(TextPaint paint, int start, int end, boolean isRtl) { private Pair<String, long[]> getLocaleAndHyphenatorIfChanged(TextPaint paint) { final LocaleList locales = paint.getTextLocales(); final String languageTags; long[] hyphenators; if (!locales.equals(mLocales)) { languageTags = locales.toLanguageTags(); hyphenators = getHyphenators(locales); mLocales = locales; return new Pair(locales.toLanguageTags(), getHyphenators(locales)); } else { // passing null means keep current locale. // TODO: move locale change detection to native. languageTags = null; hyphenators = null; return new Pair(null, null); } } /* package */ float addStyleRun(TextPaint paint, int start, int end, boolean isRtl) { Pair<String, long[]> locHyph = getLocaleAndHyphenatorIfChanged(paint); return nAddStyleRun(mNativePtr, paint.getNativeInstance(), start, end, isRtl, languageTags, hyphenators); locHyph.first, locHyph.second); } /* package */ void addMeasuredRun(int start, int end, float[] widths) { nAddMeasuredRun(mNativePtr, start, end, widths); /* package */ void addMeasuredRun(TextPaint paint, int start, int end, float[] widths) { Pair<String, long[]> locHyph = getLocaleAndHyphenatorIfChanged(paint); nAddMeasuredRun(mNativePtr, start, end, widths, locHyph.first, locHyph.second); } /* package */ void addReplacementRun(int start, int end, float width) { nAddReplacementRun(mNativePtr, start, end, width); /* package */ void addReplacementRun(TextPaint paint, int start, int end, float width) { Pair<String, long[]> locHyph = getLocaleAndHyphenatorIfChanged(paint); nAddReplacementRun(mNativePtr, start, end, width, locHyph.first, locHyph.second); } /** Loading Loading @@ -810,6 +816,9 @@ public class StaticLayout extends Layout { } } // TODO: Move locale tracking code to native. b.mLocales = null; // Reset the locale tracking. nSetupParagraph(b.mNativePtr, chs, paraEnd - paraStart, firstWidth, firstWidthLineCount, restWidth, variableTabStops, TAB_INCREMENT, b.mBreakStrategy, b.mHyphenationFrequency, Loading Loading @@ -1539,14 +1548,18 @@ public class StaticLayout extends Layout { @IntRange(from = 0) int indentsOffset); private static native float nAddStyleRun( /* non zero */ long nativePtr, /* non zero */ long nativePaint, /* non-zero */ long nativePtr, /* non-zero */ long nativePaint, @IntRange(from = 0) int start, @IntRange(from = 0) int end, boolean isRtl, @Nullable String languageTags, @Nullable long[] hyphenators); private static native void nAddMeasuredRun(long nativePtr, int start, int end, float[] widths); private static native void nAddMeasuredRun(/* non-zero */ long nativePtr, @IntRange(from = 0) int start, @IntRange(from = 0) int end, @NonNull float[] widths, @Nullable String languageTags, @Nullable long[] hyphenators); private static native void nAddReplacementRun(long nativePtr, int start, int end, float width); private static native void nAddReplacementRun(/* non-zero */ long nativePtr, @IntRange(from = 0) int start, @IntRange(from = 0) int end, @FloatRange(from = 0.0f) float width, @Nullable String languageTags, @Nullable long[] hyphenators); private static native void nGetWidths(long nativePtr, float[] widths); Loading
core/jni/android_text_StaticLayout.cpp +51 −23 Original line number Diff line number Diff line Loading @@ -193,6 +193,46 @@ static void nFinishBuilder(JNIEnv*, jclass, jlong nativePtr) { b->finish(); } class ScopedNullableUtfString { public: ScopedNullableUtfString(JNIEnv* env, jstring s) : mEnv(env), mStr(s) { if (s == nullptr) { mUtf8Chars = nullptr; } else { mUtf8Chars = mEnv->GetStringUTFChars(s, nullptr); } } ~ScopedNullableUtfString() { if (mUtf8Chars != nullptr) { mEnv->ReleaseStringUTFChars(mStr, mUtf8Chars); } } const char* get() const { return mUtf8Chars; } private: JNIEnv* mEnv; jstring mStr; const char* mUtf8Chars; }; static std::vector<minikin::Hyphenator*> makeHyphenators(JNIEnv* env, jlongArray hyphenators) { std::vector<minikin::Hyphenator*> out; if (hyphenators == nullptr) { return out; } ScopedLongArrayRO longArray(env, hyphenators); size_t size = longArray.size(); out.reserve(size); for (size_t i = 0; i < size; i++) { out.push_back(reinterpret_cast<minikin::Hyphenator*>(longArray[i])); } return out; } // Basically similar to Paint.getTextRunAdvances but with C++ interface static jfloat nAddStyleRun(JNIEnv* env, jclass, jlong nativePtr, jlong nativePaint, jint start, jint end, jboolean isRtl, jstring langTags, jlongArray hyphenators) { Loading @@ -204,40 +244,28 @@ static jfloat nAddStyleRun(JNIEnv* env, jclass, jlong nativePtr, jlong nativePai minikin::FontStyle style = MinikinUtils::prepareMinikinPaint(&minikinPaint, paint, typeface); std::vector<minikin::Hyphenator*> hyphVec; const char* langTagStr; if (langTags == nullptr) { langTagStr = nullptr; // nullptr languageTag means keeping current locale } else { ScopedLongArrayRO hyphArr(env, hyphenators); const size_t numLocales = hyphArr.size(); hyphVec.reserve(numLocales); for (size_t i = 0; i < numLocales; i++) { hyphVec.push_back(reinterpret_cast<minikin::Hyphenator*>(hyphArr[i])); } langTagStr = env->GetStringUTFChars(langTags, nullptr); } ScopedNullableUtfString langTagsString(env, langTags); float result = b->addStyleRun(&minikinPaint, resolvedTypeface->fFontCollection, style, start, end, isRtl, langTagStr, hyphVec); if (langTagStr != nullptr) { env->ReleaseStringUTFChars(langTags, langTagStr); } end, isRtl, langTagsString.get(), makeHyphenators(env, hyphenators)); return result; } // Accept width measurements for the run, passed in from Java static void nAddMeasuredRun(JNIEnv* env, jclass, jlong nativePtr, jint start, jint end, jfloatArray widths) { jint start, jint end, jfloatArray widths, jstring langTags, jlongArray hyphenators) { minikin::LineBreaker* b = reinterpret_cast<minikin::LineBreaker*>(nativePtr); env->GetFloatArrayRegion(widths, start, end - start, b->charWidths() + start); ScopedNullableUtfString langTagsString(env, langTags); b->addStyleRun(nullptr, nullptr, minikin::FontStyle{}, start, end, false, nullptr /* keep current locale */, std::vector<minikin::Hyphenator*>()); langTagsString.get(), makeHyphenators(env, hyphenators)); } static void nAddReplacementRun(JNIEnv* env, jclass, jlong nativePtr, jint start, jint end, jfloat width) { jint start, jint end, jfloat width, jstring langTags, jlongArray hyphenators) { minikin::LineBreaker* b = reinterpret_cast<minikin::LineBreaker*>(nativePtr); b->addReplacement(start, end, width); ScopedNullableUtfString langTagsString(env, langTags); b->addReplacement(start, end, width, langTagsString.get(), makeHyphenators(env, hyphenators)); } static void nGetWidths(JNIEnv* env, jclass, jlong nativePtr, jfloatArray widths) { Loading @@ -252,8 +280,8 @@ static const JNINativeMethod gMethods[] = { {"nFinishBuilder", "(J)V", (void*) nFinishBuilder}, {"nSetupParagraph", "(J[CIFIF[IIIIZ[I[I[II)V", (void*) nSetupParagraph}, {"nAddStyleRun", "(JJIIZLjava/lang/String;[J)F", (void*) nAddStyleRun}, {"nAddMeasuredRun", "(JII[F)V", (void*) nAddMeasuredRun}, {"nAddReplacementRun", "(JIIF)V", (void*) nAddReplacementRun}, {"nAddMeasuredRun", "(JII[FLjava/lang/String;[J)V", (void*) nAddMeasuredRun}, {"nAddReplacementRun", "(JIIFLjava/lang/String;[J)V", (void*) nAddReplacementRun}, {"nGetWidths", "(J[F)V", (void*) nGetWidths}, {"nComputeLineBreaks", "(JLandroid/text/StaticLayout$LineBreaks;[I[F[F[F[II)I", (void*) nComputeLineBreaks} Loading