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
This commit is contained in:
@ -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
|
||||
|
@ -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},
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
Reference in New Issue
Block a user