Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c147dbbc authored by Raph Levien's avatar Raph Levien Committed by Android (Google) Code Review
Browse files

Merge "Avoid copying of font table data, provide raw font bytes" into nyc-dev

parents 0e868a19 296bf8c5
Loading
Loading
Loading
Loading
+49 −29
Original line number Diff line number Diff line
@@ -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);
@@ -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);
@@ -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;
@@ -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;
@@ -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.
@@ -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);
}

///////////////////////////////////////////////////////////////////////////////
@@ -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",
+17 −2
Original line number Diff line number Diff line
@@ -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;

/**
@@ -27,6 +31,9 @@ import java.util.List;
 * @hide
 */
public class FontFamily {

    private static String TAG = "FontFamily";

    /**
     * @hide
     */
@@ -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,
@@ -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);
+28 −11
Original line number Diff line number Diff line
@@ -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() {
@@ -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();
}
+15 −4
Original line number Diff line number Diff line
@@ -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();

@@ -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);

@@ -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
+4 −1
Original line number Diff line number Diff line
@@ -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 {