OSDN Git Service

Support fallbacks for custom typefaces (Minikin)
authorRaph Levien <raph@google.com>
Mon, 2 Jun 2014 05:52:12 +0000 (22:52 -0700)
committerRaph Levien <raph@google.com>
Mon, 2 Jun 2014 17:56:23 +0000 (10:56 -0700)
This patch adds the fallback font list to custom typefaces created from
files and assets, as well as those created by name. This is a fix for
the deskclock half of bug 15139067 "Centered text isn't working".

Change-Id: I0cc60951953dfb73817a98ddfee5713f0387ee90

core/jni/android/graphics/FontFamily.cpp
core/jni/android/graphics/MinikinSkia.h
graphics/java/android/graphics/FontFamily.java
graphics/java/android/graphics/Typeface.java

index 3bab8a2..dd6b36f 100644 (file)
@@ -23,6 +23,9 @@
 #include "GraphicsJNI.h"
 #include <ScopedPrimitiveArray.h>
 #include <ScopedUtfChars.h>
+#include <android_runtime/android_util_AssetManager.h>
+#include <androidfw/AssetManager.h>
+#include "Utils.h"
 
 #ifdef USE_MINIKIN
 #include <minikin/FontFamily.h>
@@ -51,19 +54,60 @@ static void FontFamily_unref(JNIEnv* env, jobject clazz, jlong familyPtr) {
 #endif
 }
 
+#ifdef USE_MINIKIN
+static jboolean addSkTypeface(FontFamily* family, SkTypeface* face) {
+    MinikinFont* minikinFont = new MinikinFontSkia(face);
+    bool result = family->addFont(minikinFont);
+    minikinFont->Unref();
+    return result;
+}
+#endif
+
 static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong familyPtr, jstring path) {
 #ifdef USE_MINIKIN
     NPE_CHECK_RETURN_ZERO(env, path);
     ScopedUtfChars str(env, path);
-    ALOGD("addFont %s", str.c_str());
     SkTypeface* face = SkTypeface::CreateFromFile(str.c_str());
     if (face == NULL) {
         ALOGE("addFont failed to create font %s", str.c_str());
         return false;
     }
-    MinikinFont* minikinFont = new MinikinFontSkia(face);
     FontFamily* fontFamily = (FontFamily*)familyPtr;
-    return fontFamily->addFont(minikinFont);
+    return addSkTypeface(fontFamily, face);
+#else
+    return false;
+#endif
+}
+
+static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPtr,
+        jobject jassetMgr, jstring jpath) {
+#ifdef USE_MINIKIN
+    NPE_CHECK_RETURN_ZERO(env, jassetMgr);
+    NPE_CHECK_RETURN_ZERO(env, jpath);
+
+    AssetManager* mgr = assetManagerForJavaObject(env, jassetMgr);
+    if (NULL == mgr) {
+        return false;
+    }
+
+    ScopedUtfChars str(env, jpath);
+    Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
+    if (NULL == asset) {
+        return false;
+    }
+
+    SkStream* stream = new AssetStreamAdaptor(asset,
+                                              AssetStreamAdaptor::kYes_OwnAsset,
+                                              AssetStreamAdaptor::kYes_HasMemoryBase);
+    SkTypeface* face = SkTypeface::CreateFromStream(stream);
+    // Note: SkTypeface::CreateFromStream holds its own reference to the stream
+    stream->unref();
+    if (face == NULL) {
+        ALOGE("addFontFromAsset failed to create font %s", str.c_str());
+        return false;
+    }
+    FontFamily* fontFamily = (FontFamily*)familyPtr;
+    return addSkTypeface(fontFamily, face);
 #else
     return false;
 #endif
@@ -75,6 +119,8 @@ static JNINativeMethod gFontFamilyMethods[] = {
     { "nCreateFamily",            "(Ljava/lang/String;I)J", (void*)FontFamily_create },
     { "nUnrefFamily",             "(J)V", (void*)FontFamily_unref },
     { "nAddFont",                 "(JLjava/lang/String;)Z", (void*)FontFamily_addFont },
+    { "nAddFontFromAsset",        "(JLandroid/content/res/AssetManager;Ljava/lang/String;)Z",
+                                           (void*)FontFamily_addFontFromAsset },
 };
 
 int register_android_graphics_FontFamily(JNIEnv* env)
index 7a8954d..1cc2c51 100644 (file)
@@ -18,6 +18,7 @@ namespace android {
 
 class MinikinFontSkia : public MinikinFont {
 public:
+    // Note: this takes ownership of the reference (will unref on dtor)
     explicit MinikinFontSkia(SkTypeface *typeface);
 
     ~MinikinFontSkia();
index 6802b9a..11d3165 100644 (file)
@@ -16,6 +16,8 @@
 
 package android.graphics;
 
+import android.content.res.AssetManager;
+
 import java.io.File;
 
 /**
@@ -58,11 +60,17 @@ public class FontFamily {
         }
     }
 
-    public boolean addFont(File path) {
-        return nAddFont(mNativePtr, path.getAbsolutePath());
+    public boolean addFont(String path) {
+        return nAddFont(mNativePtr, path);
+    }
+
+    public boolean addFontFromAsset(AssetManager mgr, String path) {
+        return nAddFontFromAsset(mNativePtr, mgr, path);
     }
 
-    static native long nCreateFamily(String lang, int variant);
-    static native void nUnrefFamily(long nativePtr);
-    static native boolean nAddFont(long nativeFamily, String path);
+    private static native long nCreateFamily(String lang, int variant);
+    private static native void nUnrefFamily(long nativePtr);
+    private static native boolean nAddFont(long nativeFamily, String path);
+    private static native boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr,
+            String path);
 }
index 2b07c3f..cb48de2 100644 (file)
@@ -178,6 +178,15 @@ public class Typeface {
      * @return The new typeface.
      */
     public static Typeface createFromAsset(AssetManager mgr, String path) {
+        if (sFallbackFonts != null) {
+            FontFamily fontFamily = new FontFamily();
+            if (fontFamily.addFontFromAsset(mgr, path)) {
+                FontFamily[] families = { fontFamily };
+                return createFromFamiliesWithDefault(families);
+            } else {
+                return null;
+            }
+        }
         return new Typeface(nativeCreateFromAsset(mgr, path));
     }
 
@@ -188,7 +197,7 @@ public class Typeface {
      * @return The new typeface.
      */
     public static Typeface createFromFile(File path) {
-        return new Typeface(nativeCreateFromFile(path.getAbsolutePath()));
+        return createFromFile(path.getAbsolutePath());
     }
 
     /**
@@ -198,6 +207,15 @@ public class Typeface {
      * @return The new typeface.
      */
     public static Typeface createFromFile(String path) {
+        if (sFallbackFonts != null) {
+            FontFamily fontFamily = new FontFamily();
+            if (fontFamily.addFont(path)) {
+                FontFamily[] families = { fontFamily };
+                return createFromFamiliesWithDefault(families);
+            } else {
+                return null;
+            }
+        }
         return new Typeface(nativeCreateFromFile(path));
     }
 
@@ -247,7 +265,7 @@ public class Typeface {
         // TODO: expand to handle attributes like lang and variant
         FontFamily fontFamily = new FontFamily(family.lang, family.variant);
         for (String fontFile : family.fontFiles) {
-            fontFamily.addFont(new File(fontFile));
+            fontFamily.addFont(fontFile);
         }
         return fontFamily;
     }