Loading core/jni/android/graphics/FontFamily.cpp +49 −29 Original line number Diff line number Diff line Loading @@ -53,36 +53,14 @@ static void FontFamily_unref(JNIEnv* env, jobject clazz, jlong familyPtr) { fontFamily->Unref(); } static jboolean addSkTypeface(FontFamily* family, SkTypeface* face) { MinikinFont* minikinFont = new MinikinFontSkia(face); static jboolean addSkTypeface(FontFamily* family, SkTypeface* face, const void* fontData, size_t fontSize, int ttcIndex) { MinikinFont* minikinFont = new MinikinFontSkia(face, fontData, fontSize, ttcIndex); bool result = family->addFont(minikinFont); minikinFont->Unref(); return result; } static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong familyPtr, jstring path, jint ttcIndex) { NPE_CHECK_RETURN_ZERO(env, path); ScopedUtfChars str(env, path); SkTypeface* face = SkTypeface::CreateFromFile(str.c_str(), ttcIndex); if (face == NULL) { ALOGE("addFont failed to create font %s", str.c_str()); return false; } FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr); return addSkTypeface(fontFamily, face); } static struct { jmethodID mGet; jmethodID mSize; } gListClassInfo; static struct { jfieldID mTag; jfieldID mStyleValue; } gAxisClassInfo; static void release_global_ref(const void* /*data*/, void* context) { JNIEnv* env = AndroidRuntime::getJNIEnv(); bool needToAttach = (env == NULL); Loading @@ -106,6 +84,47 @@ static void release_global_ref(const void* /*data*/, void* context) { } } static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong familyPtr, jobject bytebuf, jint ttcIndex) { NPE_CHECK_RETURN_ZERO(env, bytebuf); const void* fontPtr = env->GetDirectBufferAddress(bytebuf); if (fontPtr == NULL) { ALOGE("addFont failed to create font, buffer invalid"); return false; } jlong fontSize = env->GetDirectBufferCapacity(bytebuf); if (fontSize < 0) { ALOGE("addFont failed to create font, buffer size invalid"); return false; } jobject fontRef = MakeGlobalRefOrDie(env, bytebuf); SkAutoTUnref<SkData> data(SkData::NewWithProc(fontPtr, fontSize, release_global_ref, reinterpret_cast<void*>(fontRef))); std::unique_ptr<SkStreamAsset> fontData(new SkMemoryStream(data)); SkFontMgr::FontParameters params; params.setCollectionIndex(ttcIndex); SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault()); SkTypeface* face = fm->createFromStream(fontData.release(), params); if (face == NULL) { ALOGE("addFont failed to create font"); return false; } FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr); return addSkTypeface(fontFamily, face, fontPtr, (size_t)fontSize, ttcIndex); } static struct { jmethodID mGet; jmethodID mSize; } gListClassInfo; static struct { jfieldID mTag; jfieldID mStyleValue; } gAxisClassInfo; static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong familyPtr, jobject font, jint ttcIndex, jobject listOfAxis, jint weight, jboolean isItalic) { NPE_CHECK_RETURN_ZERO(env, font); Loading Loading @@ -133,7 +152,7 @@ static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong } } void* fontPtr = env->GetDirectBufferAddress(font); const void* fontPtr = env->GetDirectBufferAddress(font); if (fontPtr == NULL) { ALOGE("addFont failed to create font, buffer invalid"); return false; Loading @@ -159,7 +178,7 @@ static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong return false; } FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr); MinikinFont* minikinFont = new MinikinFontSkia(face); MinikinFont* minikinFont = new MinikinFontSkia(face, fontPtr, (size_t)fontSize, ttcIndex); fontFamily->addFont(minikinFont, FontStyle(weight / 100, isItalic)); minikinFont->Unref(); return true; Loading Loading @@ -191,6 +210,7 @@ static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPt return false; } size_t bufSize = asset->getLength(); SkAutoTUnref<SkData> data(SkData::NewWithProc(buf, asset->getLength(), releaseAsset, asset)); SkMemoryStream* stream = new SkMemoryStream(data); // CreateFromStream takes ownership of stream. Loading @@ -200,7 +220,7 @@ static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPt return false; } FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr); return addSkTypeface(fontFamily, face); return addSkTypeface(fontFamily, face, buf, bufSize, /* ttcIndex */ 0); } /////////////////////////////////////////////////////////////////////////////// Loading @@ -208,7 +228,7 @@ static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPt static const JNINativeMethod gFontFamilyMethods[] = { { "nCreateFamily", "(Ljava/lang/String;I)J", (void*)FontFamily_create }, { "nUnrefFamily", "(J)V", (void*)FontFamily_unref }, { "nAddFont", "(JLjava/lang/String;I)Z", (void*)FontFamily_addFont }, { "nAddFont", "(JLjava/nio/ByteBuffer;I)Z", (void*)FontFamily_addFont }, { "nAddFontWeightStyle", "(JLjava/nio/ByteBuffer;ILjava/util/List;IZ)Z", (void*)FontFamily_addFontWeightStyle }, { "nAddFontFromAsset", "(JLandroid/content/res/AssetManager;Ljava/lang/String;)Z", Loading graphics/java/android/graphics/FontFamily.java +17 −2 Original line number Diff line number Diff line Loading @@ -17,8 +17,12 @@ package android.graphics; import android.content.res.AssetManager; import android.util.Log; import java.io.FileInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.util.List; /** Loading @@ -27,6 +31,9 @@ import java.util.List; * @hide */ public class FontFamily { private static String TAG = "FontFamily"; /** * @hide */ Loading Loading @@ -62,7 +69,15 @@ public class FontFamily { } public boolean addFont(String path, int ttcIndex) { return nAddFont(mNativePtr, path, ttcIndex); 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); } catch (IOException e) { Log.e(TAG, "Error mapping font file " + path); return false; } } public boolean addFontWeightStyle(ByteBuffer font, int ttcIndex, List<FontListParser.Axis> axes, Loading @@ -76,7 +91,7 @@ public class FontFamily { 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, int ttcIndex); private static native boolean nAddFont(long nativeFamily, ByteBuffer font, int ttcIndex); private static native boolean nAddFontWeightStyle(long nativeFamily, ByteBuffer font, int ttcIndex, List<FontListParser.Axis> listOfAxis, int weight, boolean isItalic); Loading libs/hwui/hwui/MinikinSkia.cpp +28 −11 Original line number Diff line number Diff line Loading @@ -22,8 +22,9 @@ namespace android { MinikinFontSkia::MinikinFontSkia(SkTypeface *typeface) : mTypeface(typeface) { MinikinFontSkia::MinikinFontSkia(SkTypeface* typeface, const void* fontData, size_t fontSize, int ttcIndex) : mTypeface(typeface), mFontData(fontData), mFontSize(fontSize), mTtcIndex(ttcIndex) { } MinikinFontSkia::~MinikinFontSkia() { Loading Loading @@ -66,22 +67,38 @@ void MinikinFontSkia::GetBounds(MinikinRect* bounds, uint32_t glyph_id, bounds->mBottom = skBounds.fBottom; } bool MinikinFontSkia::GetTable(uint32_t tag, uint8_t *buf, size_t *size) { if (buf == NULL) { const void* MinikinFontSkia::GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy) { // we don't have a buffer to the font data, copy to own buffer const size_t tableSize = mTypeface->getTableSize(tag); *size = tableSize; return tableSize != 0; } else { const size_t actualSize = mTypeface->getTableData(tag, 0, *size, buf); *size = actualSize; return actualSize != 0; if (tableSize == 0) { return nullptr; } void* buf = malloc(tableSize); if (buf == nullptr) { return nullptr; } mTypeface->getTableData(tag, 0, tableSize, buf); *destroy = free; return buf; } SkTypeface *MinikinFontSkia::GetSkTypeface() const { return mTypeface; } const void* MinikinFontSkia::GetFontData() const { return mFontData; } size_t MinikinFontSkia::GetFontSize() const { return mFontSize; } int MinikinFontSkia::GetFontIndex() const { return mTtcIndex; } int32_t MinikinFontSkia::GetUniqueId() const { return mTypeface->uniqueID(); } Loading libs/hwui/hwui/MinikinSkia.h +15 −4 Original line number Diff line number Diff line Loading @@ -28,7 +28,8 @@ namespace android { class ANDROID_API MinikinFontSkia : public MinikinFont { public: // Note: this takes ownership of the reference (will unref on dtor) explicit MinikinFontSkia(SkTypeface *typeface); explicit MinikinFontSkia(SkTypeface *typeface, const void* fontData, size_t fontSize, int ttcIndex); ~MinikinFontSkia(); Loading @@ -38,13 +39,17 @@ public: void GetBounds(MinikinRect* bounds, uint32_t glyph_id, const MinikinPaint &paint) const; // If buf is NULL, just update size bool GetTable(uint32_t tag, uint8_t *buf, size_t *size); const void* GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy); int32_t GetUniqueId() const; SkTypeface* GetSkTypeface() const; // Access to underlying raw font bytes const void* GetFontData() const; size_t GetFontSize() const; int GetFontIndex() const; static uint32_t packPaintFlags(const SkPaint* paint); static void unpackPaintFlags(SkPaint* paint, uint32_t paintFlags); Loading @@ -52,6 +57,12 @@ public: static void populateSkPaint(SkPaint* paint, const MinikinFont* font, FontFakery fakery); private: SkTypeface* mTypeface; // A raw pointer to the font data - it should be owned by some other object with // lifetime at least as long as this object. const void* mFontData; size_t mFontSize; int mTtcIndex; }; } // namespace android Loading libs/hwui/hwui/Typeface.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -66,7 +66,10 @@ static FontCollection *makeFontCollection() { ALOGD("makeFontCollection adding %s", fn); SkTypeface *skFace = SkTypeface::CreateFromFile(fn); if (skFace != NULL) { MinikinFont *font = new MinikinFontSkia(skFace); // TODO: might be a nice optimization to get access to the underlying font // data, but would require us opening the file ourselves and passing that // to the appropriate Create method of SkTypeface. MinikinFont *font = new MinikinFontSkia(skFace, NULL, 0, 0); family->addFont(font); font->Unref(); } else { Loading Loading
core/jni/android/graphics/FontFamily.cpp +49 −29 Original line number Diff line number Diff line Loading @@ -53,36 +53,14 @@ static void FontFamily_unref(JNIEnv* env, jobject clazz, jlong familyPtr) { fontFamily->Unref(); } static jboolean addSkTypeface(FontFamily* family, SkTypeface* face) { MinikinFont* minikinFont = new MinikinFontSkia(face); static jboolean addSkTypeface(FontFamily* family, SkTypeface* face, const void* fontData, size_t fontSize, int ttcIndex) { MinikinFont* minikinFont = new MinikinFontSkia(face, fontData, fontSize, ttcIndex); bool result = family->addFont(minikinFont); minikinFont->Unref(); return result; } static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong familyPtr, jstring path, jint ttcIndex) { NPE_CHECK_RETURN_ZERO(env, path); ScopedUtfChars str(env, path); SkTypeface* face = SkTypeface::CreateFromFile(str.c_str(), ttcIndex); if (face == NULL) { ALOGE("addFont failed to create font %s", str.c_str()); return false; } FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr); return addSkTypeface(fontFamily, face); } static struct { jmethodID mGet; jmethodID mSize; } gListClassInfo; static struct { jfieldID mTag; jfieldID mStyleValue; } gAxisClassInfo; static void release_global_ref(const void* /*data*/, void* context) { JNIEnv* env = AndroidRuntime::getJNIEnv(); bool needToAttach = (env == NULL); Loading @@ -106,6 +84,47 @@ static void release_global_ref(const void* /*data*/, void* context) { } } static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong familyPtr, jobject bytebuf, jint ttcIndex) { NPE_CHECK_RETURN_ZERO(env, bytebuf); const void* fontPtr = env->GetDirectBufferAddress(bytebuf); if (fontPtr == NULL) { ALOGE("addFont failed to create font, buffer invalid"); return false; } jlong fontSize = env->GetDirectBufferCapacity(bytebuf); if (fontSize < 0) { ALOGE("addFont failed to create font, buffer size invalid"); return false; } jobject fontRef = MakeGlobalRefOrDie(env, bytebuf); SkAutoTUnref<SkData> data(SkData::NewWithProc(fontPtr, fontSize, release_global_ref, reinterpret_cast<void*>(fontRef))); std::unique_ptr<SkStreamAsset> fontData(new SkMemoryStream(data)); SkFontMgr::FontParameters params; params.setCollectionIndex(ttcIndex); SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault()); SkTypeface* face = fm->createFromStream(fontData.release(), params); if (face == NULL) { ALOGE("addFont failed to create font"); return false; } FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr); return addSkTypeface(fontFamily, face, fontPtr, (size_t)fontSize, ttcIndex); } static struct { jmethodID mGet; jmethodID mSize; } gListClassInfo; static struct { jfieldID mTag; jfieldID mStyleValue; } gAxisClassInfo; static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong familyPtr, jobject font, jint ttcIndex, jobject listOfAxis, jint weight, jboolean isItalic) { NPE_CHECK_RETURN_ZERO(env, font); Loading Loading @@ -133,7 +152,7 @@ static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong } } void* fontPtr = env->GetDirectBufferAddress(font); const void* fontPtr = env->GetDirectBufferAddress(font); if (fontPtr == NULL) { ALOGE("addFont failed to create font, buffer invalid"); return false; Loading @@ -159,7 +178,7 @@ static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong return false; } FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr); MinikinFont* minikinFont = new MinikinFontSkia(face); MinikinFont* minikinFont = new MinikinFontSkia(face, fontPtr, (size_t)fontSize, ttcIndex); fontFamily->addFont(minikinFont, FontStyle(weight / 100, isItalic)); minikinFont->Unref(); return true; Loading Loading @@ -191,6 +210,7 @@ static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPt return false; } size_t bufSize = asset->getLength(); SkAutoTUnref<SkData> data(SkData::NewWithProc(buf, asset->getLength(), releaseAsset, asset)); SkMemoryStream* stream = new SkMemoryStream(data); // CreateFromStream takes ownership of stream. Loading @@ -200,7 +220,7 @@ static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPt return false; } FontFamily* fontFamily = reinterpret_cast<FontFamily*>(familyPtr); return addSkTypeface(fontFamily, face); return addSkTypeface(fontFamily, face, buf, bufSize, /* ttcIndex */ 0); } /////////////////////////////////////////////////////////////////////////////// Loading @@ -208,7 +228,7 @@ static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPt static const JNINativeMethod gFontFamilyMethods[] = { { "nCreateFamily", "(Ljava/lang/String;I)J", (void*)FontFamily_create }, { "nUnrefFamily", "(J)V", (void*)FontFamily_unref }, { "nAddFont", "(JLjava/lang/String;I)Z", (void*)FontFamily_addFont }, { "nAddFont", "(JLjava/nio/ByteBuffer;I)Z", (void*)FontFamily_addFont }, { "nAddFontWeightStyle", "(JLjava/nio/ByteBuffer;ILjava/util/List;IZ)Z", (void*)FontFamily_addFontWeightStyle }, { "nAddFontFromAsset", "(JLandroid/content/res/AssetManager;Ljava/lang/String;)Z", Loading
graphics/java/android/graphics/FontFamily.java +17 −2 Original line number Diff line number Diff line Loading @@ -17,8 +17,12 @@ package android.graphics; import android.content.res.AssetManager; import android.util.Log; import java.io.FileInputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.util.List; /** Loading @@ -27,6 +31,9 @@ import java.util.List; * @hide */ public class FontFamily { private static String TAG = "FontFamily"; /** * @hide */ Loading Loading @@ -62,7 +69,15 @@ public class FontFamily { } public boolean addFont(String path, int ttcIndex) { return nAddFont(mNativePtr, path, ttcIndex); 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); } catch (IOException e) { Log.e(TAG, "Error mapping font file " + path); return false; } } public boolean addFontWeightStyle(ByteBuffer font, int ttcIndex, List<FontListParser.Axis> axes, Loading @@ -76,7 +91,7 @@ public class FontFamily { 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, int ttcIndex); private static native boolean nAddFont(long nativeFamily, ByteBuffer font, int ttcIndex); private static native boolean nAddFontWeightStyle(long nativeFamily, ByteBuffer font, int ttcIndex, List<FontListParser.Axis> listOfAxis, int weight, boolean isItalic); Loading
libs/hwui/hwui/MinikinSkia.cpp +28 −11 Original line number Diff line number Diff line Loading @@ -22,8 +22,9 @@ namespace android { MinikinFontSkia::MinikinFontSkia(SkTypeface *typeface) : mTypeface(typeface) { MinikinFontSkia::MinikinFontSkia(SkTypeface* typeface, const void* fontData, size_t fontSize, int ttcIndex) : mTypeface(typeface), mFontData(fontData), mFontSize(fontSize), mTtcIndex(ttcIndex) { } MinikinFontSkia::~MinikinFontSkia() { Loading Loading @@ -66,22 +67,38 @@ void MinikinFontSkia::GetBounds(MinikinRect* bounds, uint32_t glyph_id, bounds->mBottom = skBounds.fBottom; } bool MinikinFontSkia::GetTable(uint32_t tag, uint8_t *buf, size_t *size) { if (buf == NULL) { const void* MinikinFontSkia::GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy) { // we don't have a buffer to the font data, copy to own buffer const size_t tableSize = mTypeface->getTableSize(tag); *size = tableSize; return tableSize != 0; } else { const size_t actualSize = mTypeface->getTableData(tag, 0, *size, buf); *size = actualSize; return actualSize != 0; if (tableSize == 0) { return nullptr; } void* buf = malloc(tableSize); if (buf == nullptr) { return nullptr; } mTypeface->getTableData(tag, 0, tableSize, buf); *destroy = free; return buf; } SkTypeface *MinikinFontSkia::GetSkTypeface() const { return mTypeface; } const void* MinikinFontSkia::GetFontData() const { return mFontData; } size_t MinikinFontSkia::GetFontSize() const { return mFontSize; } int MinikinFontSkia::GetFontIndex() const { return mTtcIndex; } int32_t MinikinFontSkia::GetUniqueId() const { return mTypeface->uniqueID(); } Loading
libs/hwui/hwui/MinikinSkia.h +15 −4 Original line number Diff line number Diff line Loading @@ -28,7 +28,8 @@ namespace android { class ANDROID_API MinikinFontSkia : public MinikinFont { public: // Note: this takes ownership of the reference (will unref on dtor) explicit MinikinFontSkia(SkTypeface *typeface); explicit MinikinFontSkia(SkTypeface *typeface, const void* fontData, size_t fontSize, int ttcIndex); ~MinikinFontSkia(); Loading @@ -38,13 +39,17 @@ public: void GetBounds(MinikinRect* bounds, uint32_t glyph_id, const MinikinPaint &paint) const; // If buf is NULL, just update size bool GetTable(uint32_t tag, uint8_t *buf, size_t *size); const void* GetTable(uint32_t tag, size_t* size, MinikinDestroyFunc* destroy); int32_t GetUniqueId() const; SkTypeface* GetSkTypeface() const; // Access to underlying raw font bytes const void* GetFontData() const; size_t GetFontSize() const; int GetFontIndex() const; static uint32_t packPaintFlags(const SkPaint* paint); static void unpackPaintFlags(SkPaint* paint, uint32_t paintFlags); Loading @@ -52,6 +57,12 @@ public: static void populateSkPaint(SkPaint* paint, const MinikinFont* font, FontFakery fakery); private: SkTypeface* mTypeface; // A raw pointer to the font data - it should be owned by some other object with // lifetime at least as long as this object. const void* mFontData; size_t mFontSize; int mTtcIndex; }; } // namespace android Loading
libs/hwui/hwui/Typeface.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -66,7 +66,10 @@ static FontCollection *makeFontCollection() { ALOGD("makeFontCollection adding %s", fn); SkTypeface *skFace = SkTypeface::CreateFromFile(fn); if (skFace != NULL) { MinikinFont *font = new MinikinFontSkia(skFace); // TODO: might be a nice optimization to get access to the underlying font // data, but would require us opening the file ourselves and passing that // to the appropriate Create method of SkTypeface. MinikinFont *font = new MinikinFontSkia(skFace, NULL, 0, 0); family->addFont(font); font->Unref(); } else { Loading