summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Seigo Nonaka <nona@google.com> 2015-12-02 10:53:18 +0900
committer Seigo Nonaka <nona@google.com> 2015-12-07 16:50:20 -0800
commitcfc607cf57d453f977c9c4bf09b41ac481c4bbec (patch)
tree8c77b689bdeef7721a7248955c306dfe1907c90e
parent39a275b3980b5ea75e060da540229b95a47333f7 (diff)
Introduce cache mechanism for LocaleList.
Setting the LocaleList to the native Paint object is not a lightweight operation since it needs to propagate a string object to the native code which then needs to parse it for making minikin language list. To avoid performance regressions, cache the minikin language ID in android.graphics.Paint and send the LocaleList with cached ID instead of a string the next time native code is called. BUG: 25122318 Change-Id: Ib5ce8bcff8a1c0a2b1a1c3d1868ea8be5a0e642f
-rw-r--r--core/jni/android/graphics/MinikinUtils.cpp5
-rw-r--r--core/jni/android/graphics/Paint.cpp28
-rw-r--r--core/jni/android/graphics/Paint.h10
-rw-r--r--core/jni/android/graphics/PaintImpl.cpp11
-rw-r--r--graphics/java/android/graphics/Paint.java36
5 files changed, 59 insertions, 31 deletions
diff --git a/core/jni/android/graphics/MinikinUtils.cpp b/core/jni/android/graphics/MinikinUtils.cpp
index 9b774b3cfc53..0597d3f37a71 100644
--- a/core/jni/android/graphics/MinikinUtils.cpp
+++ b/core/jni/android/graphics/MinikinUtils.cpp
@@ -33,11 +33,10 @@ FontStyle MinikinUtils::prepareMinikinPaint(MinikinPaint* minikinPaint, FontColl
FontStyle resolved = resolvedFace->fStyle;
/* Prepare minikin FontStyle */
- const std::string& langs = paint->getTextLocales();
- FontLanguages minikinLangs(langs.c_str(), langs.size());
FontVariant minikinVariant = (paint->getFontVariant() == VARIANT_ELEGANT) ? VARIANT_ELEGANT
: VARIANT_COMPACT;
- FontStyle minikinStyle(minikinLangs, minikinVariant, resolved.getWeight(), resolved.getItalic());
+ const uint32_t langListId = paint->getMinikinLangListId();
+ FontStyle minikinStyle(langListId, minikinVariant, resolved.getWeight(), resolved.getItalic());
/* Prepare minikin Paint */
// Note: it would be nice to handle fractional size values (it would improve smooth zoom
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 9c11dd153871..654d148e2029 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -71,13 +71,6 @@ static void defaultSettingsForAndroid(Paint* paint) {
paint->setTextEncoding(Paint::kGlyphID_TextEncoding);
}
-struct LocalesCacheEntry {
- std::string javaLocales;
- std::string languageTags;
-};
-
-static thread_local LocalesCacheEntry sSingleEntryLocalesCache;
-
namespace PaintGlue {
enum MoveOpt {
AFTER, AT_OR_AFTER, BEFORE, AT_OR_BEFORE, AT
@@ -402,15 +395,20 @@ namespace PaintGlue {
}
}
- static void setTextLocales(JNIEnv* env, jobject clazz, jlong objHandle, jstring locales) {
+ static jint setTextLocales(JNIEnv* env, jobject clazz, jlong objHandle, jstring locales) {
Paint* obj = reinterpret_cast<Paint*>(objHandle);
ScopedUtfChars localesChars(env, locales);
- if (sSingleEntryLocalesCache.javaLocales != localesChars.c_str()) {
- sSingleEntryLocalesCache.javaLocales = localesChars.c_str();
- toLanguageTags(&sSingleEntryLocalesCache.languageTags, localesChars.c_str());
- }
+ std::string buf;
+ toLanguageTags(&buf, localesChars.c_str());
+ jint minikinLangListId = FontStyle::registerLanguageList(buf);
+ obj->setMinikinLangListId(minikinLangListId);
+ return minikinLangListId;
+ }
- obj->setTextLocales(sSingleEntryLocalesCache.languageTags);
+ static void setTextLocalesByMinikinLangListId(JNIEnv* env, jobject clazz, jlong objHandle,
+ jint minikinLangListId) {
+ Paint* obj = reinterpret_cast<Paint*>(objHandle);
+ obj->setMinikinLangListId(minikinLangListId);
}
static jboolean isElegantTextHeight(JNIEnv* env, jobject, jlong paintHandle) {
@@ -991,7 +989,9 @@ static const JNINativeMethod methods[] = {
{"nSetRasterizer","!(JJ)J", (void*) PaintGlue::setRasterizer},
{"nGetTextAlign","!(J)I", (void*) PaintGlue::getTextAlign},
{"nSetTextAlign","!(JI)V", (void*) PaintGlue::setTextAlign},
- {"nSetTextLocales","!(JLjava/lang/String;)V", (void*) PaintGlue::setTextLocales},
+ {"nSetTextLocales","!(JLjava/lang/String;)I", (void*) PaintGlue::setTextLocales},
+ {"nSetTextLocalesByMinikinLangListId","!(JI)V",
+ (void*) PaintGlue::setTextLocalesByMinikinLangListId},
{"nIsElegantTextHeight","!(J)Z", (void*) PaintGlue::isElegantTextHeight},
{"nSetElegantTextHeight","!(JZ)V", (void*) PaintGlue::setElegantTextHeight},
{"nGetTextSize","!(J)F", (void*) PaintGlue::getTextSize},
diff --git a/core/jni/android/graphics/Paint.h b/core/jni/android/graphics/Paint.h
index 7a34bc291ee4..cb6e622ccced 100644
--- a/core/jni/android/graphics/Paint.h
+++ b/core/jni/android/graphics/Paint.h
@@ -53,12 +53,12 @@ public:
return mFontFeatureSettings;
}
- void setTextLocales(const std::string &textLocales) {
- mTextLocales = textLocales;
+ void setMinikinLangListId(uint32_t minikinLangListId) {
+ mMinikinLangListId = minikinLangListId;
}
- const std::string& getTextLocales() const {
- return mTextLocales;
+ uint32_t getMinikinLangListId() const {
+ return mMinikinLangListId;
}
void setFontVariant(FontVariant variant) {
@@ -80,7 +80,7 @@ public:
private:
float mLetterSpacing = 0;
std::string mFontFeatureSettings;
- std::string mTextLocales;
+ uint32_t mMinikinLangListId;
FontVariant mFontVariant;
uint32_t mHyphenEdit = 0;
};
diff --git a/core/jni/android/graphics/PaintImpl.cpp b/core/jni/android/graphics/PaintImpl.cpp
index d5a0972d35e3..bd513ae60823 100644
--- a/core/jni/android/graphics/PaintImpl.cpp
+++ b/core/jni/android/graphics/PaintImpl.cpp
@@ -22,13 +22,14 @@
namespace android {
-Paint::Paint() : SkPaint(),
- mLetterSpacing(0), mFontFeatureSettings(), mTextLocales(), mFontVariant(VARIANT_DEFAULT) {
+Paint::Paint() :
+ SkPaint(), mLetterSpacing(0), mFontFeatureSettings(), mMinikinLangListId(0),
+ mFontVariant(VARIANT_DEFAULT) {
}
Paint::Paint(const Paint& paint) : SkPaint(paint),
mLetterSpacing(paint.mLetterSpacing), mFontFeatureSettings(paint.mFontFeatureSettings),
- mTextLocales(paint.mTextLocales), mFontVariant(paint.mFontVariant),
+ mMinikinLangListId(paint.mMinikinLangListId), mFontVariant(paint.mFontVariant),
mHyphenEdit(paint.mHyphenEdit) {
}
@@ -39,7 +40,7 @@ Paint& Paint::operator=(const Paint& other) {
SkPaint::operator=(other);
mLetterSpacing = other.mLetterSpacing;
mFontFeatureSettings = other.mFontFeatureSettings;
- mTextLocales = other.mTextLocales;
+ mMinikinLangListId = other.mMinikinLangListId;
mFontVariant = other.mFontVariant;
mHyphenEdit = other.mHyphenEdit;
return *this;
@@ -49,7 +50,7 @@ bool operator==(const Paint& a, const Paint& b) {
return static_cast<const SkPaint&>(a) == static_cast<const SkPaint&>(b)
&& a.mLetterSpacing == b.mLetterSpacing
&& a.mFontFeatureSettings == b.mFontFeatureSettings
- && a.mTextLocales == b.mTextLocales
+ && a.mMinikinLangListId == b.mMinikinLangListId
&& a.mFontVariant == b.mFontVariant
&& a.mHyphenEdit == b.mHyphenEdit;
}
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 35182f9d05a6..90522f71a845 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -25,6 +25,9 @@ import android.text.SpannedString;
import android.text.TextUtils;
import android.util.LocaleList;
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.HashMap;
import java.util.Locale;
/**
@@ -56,6 +59,16 @@ public class Paint {
private LocaleList mLocales;
private String mFontFeatureSettings;
+ private static final Object sCacheLock = new Object();
+
+ /**
+ * Cache for the Minikin language list ID.
+ *
+ * A map from a string representation of the LocaleList to Minikin's language list ID.
+ */
+ @GuardedBy("sCacheLock")
+ private static final HashMap<String, Integer> sMinikinLangListIdCache = new HashMap<>();
+
/**
* @hide
*/
@@ -1335,7 +1348,7 @@ public class Paint {
return;
}
mLocales = new LocaleList(locale);
- nSetTextLocales(mNativePaint, locale.toString());
+ syncTextLocalesWithMinikin();
}
/**
@@ -1372,7 +1385,21 @@ public class Paint {
}
if (locales.equals(mLocales)) return;
mLocales = locales;
- nSetTextLocales(mNativePaint, locales.toLanguageTags());
+ syncTextLocalesWithMinikin();
+ }
+
+ private void syncTextLocalesWithMinikin() {
+ final String languageTags = mLocales.toLanguageTags();
+ final Integer minikinLangListId;
+ synchronized (sCacheLock) {
+ minikinLangListId = sMinikinLangListIdCache.get(languageTags);
+ if (minikinLangListId == null) {
+ final int newID = nSetTextLocales(mNativePaint, languageTags);
+ sMinikinLangListIdCache.put(languageTags, newID);
+ return;
+ }
+ }
+ nSetTextLocalesByMinikinLangListId(mNativePaint, minikinLangListId.intValue());
}
/**
@@ -2714,8 +2741,9 @@ public class Paint {
private static native void nSetTextAlign(long paintPtr,
int align);
- private static native void nSetTextLocales(long paintPtr,
- String locales);
+ private static native int nSetTextLocales(long paintPtr, String locales);
+ private static native void nSetTextLocalesByMinikinLangListId(long paintPtr,
+ int mMinikinLangListId);
private static native float nGetTextAdvances(long paintPtr, long typefacePtr,
char[] text, int index, int count, int contextIndex, int contextCount,