summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/text/MeasuredText.java6
-rw-r--r--core/java/android/text/StaticLayout.java41
-rw-r--r--core/jni/android_text_StaticLayout.cpp74
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}