diff options
7 files changed, 139 insertions, 49 deletions
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp index ac8f413c2677..0c863fd6eca8 100644 --- a/core/jni/android/graphics/FontFamily.cpp +++ b/core/jni/android/graphics/FontFamily.cpp @@ -39,27 +39,60 @@ namespace android { -static jlong FontFamily_create(JNIEnv* env, jobject clazz, jstring lang, jint variant) { - if (lang == NULL) { - return (jlong)new minikin::FontFamily(variant); +struct NativeFamilyBuilder { + uint32_t langId; + int variant; + std::vector<minikin::Font> fonts; +}; + +static jlong FontFamily_initBuilder(JNIEnv* env, jobject clazz, jstring lang, jint variant) { + NativeFamilyBuilder* builder = new NativeFamilyBuilder(); + if (lang != nullptr) { + ScopedUtfChars str(env, lang); + builder->langId = minikin::FontStyle::registerLanguageList(str.c_str()); + } else { + builder->langId = minikin::FontStyle::registerLanguageList(""); + } + builder->variant = variant; + return reinterpret_cast<jlong>(builder); +} + +static jlong FontFamily_create(jlong builderPtr) { + if (builderPtr == 0) { + return 0; } - ScopedUtfChars str(env, lang); - uint32_t langId = minikin::FontStyle::registerLanguageList(str.c_str()); - return (jlong)new minikin::FontFamily(langId, variant); + NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr); + minikin::FontFamily* family = new minikin::FontFamily( + builder->langId, builder->variant, std::move(builder->fonts)); + delete builder; + return reinterpret_cast<jlong>(family); +} + +static void FontFamily_abort(jlong builderPtr) { + NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr); + minikin::Font::clearElementsWithLock(&builder->fonts); + delete builder; } -static void FontFamily_unref(JNIEnv* env, jobject clazz, jlong familyPtr) { +static void FontFamily_unref(jlong familyPtr) { minikin::FontFamily* fontFamily = reinterpret_cast<minikin::FontFamily*>(familyPtr); fontFamily->Unref(); } -static jboolean addSkTypeface(minikin::FontFamily* family, sk_sp<SkTypeface> face, - const void* fontData, size_t fontSize, int ttcIndex) { +static void addSkTypeface(jlong builderPtr, sk_sp<SkTypeface> face, const void* fontData, + size_t fontSize, int ttcIndex) { minikin::MinikinFont* minikinFont = new MinikinFontSkia(std::move(face), fontData, fontSize, ttcIndex); - bool result = family->addFont(minikinFont); + NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr); + int weight; + bool italic; + if (!minikin::FontFamily::analyzeStyle(minikinFont, &weight, &italic)) { + ALOGE("analyzeStyle failed. Using default style"); + weight = 400; + italic = false; + } + builder->fonts.push_back(minikin::Font(minikinFont, minikin::FontStyle(weight / 100, italic))); minikinFont->Unref(); - return result; } static void release_global_ref(const void* /*data*/, void* context) { @@ -85,7 +118,7 @@ static void release_global_ref(const void* /*data*/, void* context) { } } -static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong familyPtr, jobject bytebuf, +static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong builderPtr, jobject bytebuf, jint ttcIndex) { NPE_CHECK_RETURN_ZERO(env, bytebuf); const void* fontPtr = env->GetDirectBufferAddress(bytebuf); @@ -112,8 +145,8 @@ static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong familyPtr, ALOGE("addFont failed to create font"); return false; } - minikin::FontFamily* fontFamily = reinterpret_cast<minikin::FontFamily*>(familyPtr); - return addSkTypeface(fontFamily, std::move(face), fontPtr, (size_t)fontSize, ttcIndex); + addSkTypeface(builderPtr, std::move(face), fontPtr, (size_t)fontSize, ttcIndex); + return true; } static struct { @@ -126,7 +159,7 @@ static struct { jfieldID mStyleValue; } gAxisClassInfo; -static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong familyPtr, +static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong builderPtr, jobject font, jint ttcIndex, jobject listOfAxis, jint weight, jboolean isItalic) { NPE_CHECK_RETURN_ZERO(env, font); @@ -178,10 +211,11 @@ static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong ALOGE("addFont failed to create font, invalid request"); return false; } - minikin::FontFamily* fontFamily = reinterpret_cast<minikin::FontFamily*>(familyPtr); minikin::MinikinFont* minikinFont = - new MinikinFontSkia(std::move(face), fontPtr, (size_t)fontSize, ttcIndex); - fontFamily->addFont(minikinFont, minikin::FontStyle(weight / 100, isItalic)); + new MinikinFontSkia(std::move(face), fontPtr, fontSize, ttcIndex); + NativeFamilyBuilder* builder = reinterpret_cast<NativeFamilyBuilder*>(builderPtr); + builder->fonts.push_back(minikin::Font(minikinFont, + minikin::FontStyle(weight / 100, isItalic))); minikinFont->Unref(); return true; } @@ -190,7 +224,7 @@ static void releaseAsset(const void* ptr, void* context) { delete static_cast<Asset*>(context); } -static jboolean FontFamily_addFontFromAssetManager(JNIEnv* env, jobject, jlong familyPtr, +static jboolean FontFamily_addFontFromAssetManager(JNIEnv* env, jobject, jlong builderPtr, jobject jassetMgr, jstring jpath, jint cookie, jboolean isAsset) { NPE_CHECK_RETURN_ZERO(env, jassetMgr); NPE_CHECK_RETURN_ZERO(env, jpath); @@ -233,14 +267,17 @@ static jboolean FontFamily_addFontFromAssetManager(JNIEnv* env, jobject, jlong f ALOGE("addFontFromAsset failed to create font %s", str.c_str()); return false; } - minikin::FontFamily* fontFamily = reinterpret_cast<minikin::FontFamily*>(familyPtr); - return addSkTypeface(fontFamily, std::move(face), buf, bufSize, /* ttcIndex */ 0); + + addSkTypeface(builderPtr, std::move(face), buf, bufSize, 0 /* ttc index */); + return true; } /////////////////////////////////////////////////////////////////////////////// static const JNINativeMethod gFontFamilyMethods[] = { - { "nCreateFamily", "(Ljava/lang/String;I)J", (void*)FontFamily_create }, + { "nInitBuilder", "(Ljava/lang/String;I)J", (void*)FontFamily_initBuilder }, + { "nCreateFamily", "(J)J", (void*)FontFamily_create }, + { "nAbort", "(J)V", (void*)FontFamily_abort }, { "nUnrefFamily", "(J)V", (void*)FontFamily_unref }, { "nAddFont", "(JLjava/nio/ByteBuffer;I)Z", (void*)FontFamily_addFont }, { "nAddFontWeightStyle", "(JLjava/nio/ByteBuffer;ILjava/util/List;IZ)Z", diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java index 8673e0bb6a9c..2c93c325f5fc 100644 --- a/graphics/java/android/graphics/FontFamily.java +++ b/graphics/java/android/graphics/FontFamily.java @@ -19,6 +19,7 @@ package android.graphics; import android.content.res.AssetManager; import android.text.FontConfig; import android.util.Log; +import dalvik.annotation.optimization.CriticalNative; import java.io.FileInputStream; import java.io.IOException; @@ -40,11 +41,11 @@ public class FontFamily { */ public long mNativePtr; + // Points native font family builder. Must be zero after freezing this family. + private long mBuilderPtr; + public FontFamily() { - mNativePtr = nCreateFamily(null, 0); - if (mNativePtr == 0) { - throw new IllegalStateException("error creating native FontFamily"); - } + mBuilderPtr = nInitBuilder(null, 0); } public FontFamily(String lang, String variant) { @@ -54,27 +55,48 @@ public class FontFamily { } else if ("elegant".equals(variant)) { varEnum = 2; } - mNativePtr = nCreateFamily(lang, varEnum); - if (mNativePtr == 0) { - throw new IllegalStateException("error creating native FontFamily"); + mBuilderPtr = nInitBuilder(lang, varEnum); + } + + public void freeze() { + if (mBuilderPtr == 0) { + throw new IllegalStateException("This FontFamily is already frozen"); + } + mNativePtr = nCreateFamily(mBuilderPtr); + mBuilderPtr = 0; + } + + public void abortCreation() { + if (mBuilderPtr == 0) { + throw new IllegalStateException("This FontFamily is already frozen or abandoned"); } + nAbort(mBuilderPtr); + mBuilderPtr = 0; } @Override protected void finalize() throws Throwable { try { - nUnrefFamily(mNativePtr); + if (mNativePtr != 0) { + nUnrefFamily(mNativePtr); + } + if (mBuilderPtr != 0) { + nAbort(mBuilderPtr); + } } finally { super.finalize(); } } public boolean addFont(String path, int ttcIndex) { + if (mBuilderPtr == 0) { + throw new IllegalStateException("Unable to call addFont after freezing."); + } try (FileInputStream file = new FileInputStream(path)) { FileChannel fileChannel = file.getChannel(); long fontSize = fileChannel.size(); ByteBuffer fontBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize); - return nAddFont(mNativePtr, fontBuffer, ttcIndex); + return nAddFont(mBuilderPtr, fontBuffer, ttcIndex); } catch (IOException e) { Log.e(TAG, "Error mapping font file " + path); return false; @@ -83,20 +105,34 @@ public class FontFamily { public boolean addFontWeightStyle(ByteBuffer font, int ttcIndex, List<FontConfig.Axis> axes, int weight, boolean style) { - return nAddFontWeightStyle(mNativePtr, font, ttcIndex, axes, weight, style); + if (mBuilderPtr == 0) { + throw new IllegalStateException("Unable to call addFontWeightStyle after freezing."); + } + return nAddFontWeightStyle(mBuilderPtr, font, ttcIndex, axes, weight, style); } public boolean addFontFromAssetManager(AssetManager mgr, String path, int cookie, boolean isAsset) { - return nAddFontFromAssetManager(mNativePtr, mgr, path, cookie, isAsset); + if (mBuilderPtr == 0) { + throw new IllegalStateException("Unable to call addFontFromAsset after freezing."); + } + return nAddFontFromAssetManager(mBuilderPtr, mgr, path, cookie, isAsset); } - private static native long nCreateFamily(String lang, int variant); + private static native long nInitBuilder(String lang, int variant); + + @CriticalNative + private static native long nCreateFamily(long mBuilderPtr); + + @CriticalNative + private static native void nAbort(long mBuilderPtr); + + @CriticalNative private static native void nUnrefFamily(long nativePtr); - private static native boolean nAddFont(long nativeFamily, ByteBuffer font, int ttcIndex); - private static native boolean nAddFontWeightStyle(long nativeFamily, ByteBuffer font, + private static native boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex); + private static native boolean nAddFontWeightStyle(long builderPtr, ByteBuffer font, int ttcIndex, List<FontConfig.Axis> listOfAxis, int weight, boolean isItalic); - private static native boolean nAddFontFromAssetManager(long nativeFamily, AssetManager mgr, + private static native boolean nAddFontFromAssetManager(long builderPtr, AssetManager mgr, String path, int cookie, boolean isAsset); } diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index 4e863e37f363..7a7c7afb21f1 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -373,10 +373,13 @@ public class Typeface { FontFamily fontFamily = new FontFamily(); if (fontFamily.addFontFromAssetManager(mgr, path, 0, true /* isAsset */)) { + fontFamily.freeze(); FontFamily[] families = { fontFamily }; typeface = createFromFamiliesWithDefault(families); sDynamicTypefaceCache.put(key, typeface); return typeface; + } else { + fontFamily.abortCreation(); } } } @@ -422,8 +425,11 @@ public class Typeface { if (sFallbackFonts != null) { FontFamily fontFamily = new FontFamily(); if (fontFamily.addFont(path, 0 /* ttcIndex */)) { + fontFamily.freeze(); FontFamily[] families = { fontFamily }; return createFromFamiliesWithDefault(families); + } else { + fontFamily.abortCreation(); } } throw new RuntimeException("Font not found " + path); @@ -492,6 +498,7 @@ public class Typeface { Log.e(TAG, "Error creating font " + font.getFontName() + "#" + font.getTtcIndex()); } } + fontFamily.freeze(); return fontFamily; } diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp index ca43156e88a1..9041b44db849 100644 --- a/libs/hwui/hwui/Typeface.cpp +++ b/libs/hwui/hwui/Typeface.cpp @@ -130,9 +130,9 @@ void Typeface::setRobotoTypefaceForTest() { sk_sp<SkTypeface> typeface = SkTypeface::MakeFromStream(fontData.release()); LOG_ALWAYS_FATAL_IF(typeface == nullptr, "Failed to make typeface from %s", kRobotoFont); - minikin::FontFamily* family = new minikin::FontFamily(); minikin::MinikinFont* font = new MinikinFontSkia(std::move(typeface), data, st.st_size, 0); - family->addFont(font); + minikin::FontFamily* family = new minikin::FontFamily( + std::vector<minikin::Font>({ minikin::Font(font, minikin::FontStyle()) })); font->Unref(); std::vector<minikin::FontFamily*> typefaces = { family }; diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java index d0c959972b13..147ed99ee047 100644 --- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java @@ -249,14 +249,17 @@ public class FontFamily_Delegate { // ---- delegate methods ---- @LayoutlibDelegate /*package*/ static boolean addFont(FontFamily thisFontFamily, String path, int ttcIndex) { - final FontFamily_Delegate delegate = getDelegate(thisFontFamily.mNativePtr); + if (thisFontFamily.mBuilderPtr == 0) { + throw new IllegalStateException("Unable to call addFont after freezing."); + } + final FontFamily_Delegate delegate = getDelegate(thisFontFamily.mBuilderPtr); return delegate != null && delegate.addFont(path, ttcIndex); } // ---- native methods ---- @LayoutlibDelegate - /*package*/ static long nCreateFamily(String lang, int variant) { + /*package*/ static long nInitBuilder(String lang, int variant) { // TODO: support lang. This is required for japanese locale. FontFamily_Delegate delegate = new FontFamily_Delegate(); // variant can be 0, 1 or 2. @@ -271,6 +274,11 @@ public class FontFamily_Delegate { } @LayoutlibDelegate + /*package*/ static long nCreateFamily(long builderPtr) { + return builderPtr; + } + + @LayoutlibDelegate /*package*/ static void nUnrefFamily(long nativePtr) { // Removing the java reference for the object doesn't mean that it's freed for garbage // collection. Typeface_Delegate may still hold a reference for it. @@ -278,22 +286,22 @@ public class FontFamily_Delegate { } @LayoutlibDelegate - /*package*/ static boolean nAddFont(long nativeFamily, ByteBuffer font, int ttcIndex) { + /*package*/ static boolean nAddFont(long builderPtr, ByteBuffer font, int ttcIndex) { assert false : "The only client of this method has been overriden."; return false; } @LayoutlibDelegate - /*package*/ static boolean nAddFontWeightStyle(long nativeFamily, ByteBuffer font, + /*package*/ static boolean nAddFontWeightStyle(long builderPtr, ByteBuffer font, int ttcIndex, List<FontConfig.Axis> listOfAxis, int weight, boolean isItalic) { assert false : "The only client of this method has been overriden."; return false; } - static boolean addFont(long nativeFamily, final String path, final int weight, + static boolean addFont(long builderPtr, final String path, final int weight, final boolean isItalic) { - final FontFamily_Delegate delegate = getDelegate(nativeFamily); + final FontFamily_Delegate delegate = getDelegate(builderPtr); if (delegate != null) { if (sFontLocation == null) { delegate.mPostInitRunnables.add(() -> delegate.addFont(path, weight, isItalic)); @@ -305,8 +313,8 @@ public class FontFamily_Delegate { } @LayoutlibDelegate - /*package*/ static boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr, String path) { - FontFamily_Delegate ffd = sManager.getDelegate(nativeFamily); + /*package*/ static boolean nAddFontFromAsset(long builderPtr, AssetManager mgr, String path) { + FontFamily_Delegate ffd = sManager.getDelegate(builderPtr); if (ffd == null) { return false; } diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java index 6e337d50a31f..f6c463f1b578 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java @@ -213,9 +213,10 @@ public final class Typeface_Delegate { Map<String, ByteBuffer> bufferForPath) { FontFamily fontFamily = new FontFamily(family.getLanguage(), family.getVariant()); for (FontConfig.Font font : family.getFonts()) { - FontFamily_Delegate.addFont(fontFamily.mNativePtr, font.getFontName(), + FontFamily_Delegate.addFont(fontFamily.mBuilderPtr, font.getFontName(), font.getWeight(), font.isItalic()); } + fontFamily.freeze(); return fontFamily; } diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java index 7ba86fdc5c30..741eb27558ed 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java @@ -339,7 +339,8 @@ public final class CreateInfo implements ICreateInfo { */ private final static String[] PROMOTED_FIELDS = new String[] { "android.graphics.drawable.VectorDrawable#mVectorState", - "android.view.Choreographer#mLastFrameTimeNanos" + "android.view.Choreographer#mLastFrameTimeNanos", + "android.graphics.FontFamily#mBuilderPtr" }; /** |