diff options
| -rw-r--r-- | core/java/android/text/MeasuredText.java | 6 | ||||
| -rw-r--r-- | core/java/android/text/StaticLayout.java | 41 | ||||
| -rw-r--r-- | core/jni/android_text_StaticLayout.cpp | 74 |
3 files changed, 81 insertions, 40 deletions
diff --git a/core/java/android/text/MeasuredText.java b/core/java/android/text/MeasuredText.java index ce3e2822fa22..9f54d8e2ab7b 100644 --- a/core/java/android/text/MeasuredText.java +++ b/core/java/android/text/MeasuredText.java @@ -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); @@ -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); @@ -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; } diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index b6911fe8cb29..e71ad5b21fcf 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -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; @@ -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); } /** @@ -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, @@ -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); diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp index 4d7f33fb907e..e20761993a60 100644 --- a/core/jni/android_text_StaticLayout.cpp +++ b/core/jni/android_text_StaticLayout.cpp @@ -172,6 +172,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) { @@ -183,40 +223,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) { @@ -231,8 +259,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} |