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

Commit 46926698 authored by Romain Guy's avatar Romain Guy
Browse files

Don't allocate new typefaces when not needed.

The Typeface.create(Typeface, int) API can be used to create a new
typeface derived from an existing typeface. The implementation would
however create a new Typeface instance on every call, creating
unnecessary garbage in text-heavy applications. This changelist
adds a small cache of derived typefaces to avoid allocations whenever
possible.

Change-Id: Ib7290b3183e372aae12cf66033690e15cd4d0691
parent 3fe4eb9c
Loading
Loading
Loading
Loading
+64 −14
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.graphics;

import android.content.res.AssetManager;
import android.util.SparseArray;

import java.io.File;

@@ -43,9 +44,11 @@ public class Typeface {
    /** The NORMAL style of the default monospace typeface. */
    public static final Typeface MONOSPACE;

    /* package */ static Typeface[] sDefaults;
    static Typeface[] sDefaults;
    private static final SparseArray<SparseArray<Typeface>> sTypefaceCache =
            new SparseArray<SparseArray<Typeface>>(3);

    /* package */ int native_instance;
    int native_instance;

    // Style
    public static final int NORMAL = 0;
@@ -53,19 +56,21 @@ public class Typeface {
    public static final int ITALIC = 2;
    public static final int BOLD_ITALIC = 3;

    private int mStyle = 0;

    /** Returns the typeface's intrinsic style attributes */
    public int getStyle() {
        return nativeGetStyle(native_instance);
        return mStyle;
    }

    /** Returns true if getStyle() has the BOLD bit set. */
    public final boolean isBold() {
        return (getStyle() & BOLD) != 0;
        return (mStyle & BOLD) != 0;
    }

    /** Returns true if getStyle() has the ITALIC bit set. */
    public final boolean isItalic() {
        return (getStyle() & ITALIC) != 0;
        return (mStyle & ITALIC) != 0;
    }

    /**
@@ -97,9 +102,32 @@ public class Typeface {
    public static Typeface create(Typeface family, int style) {
        int ni = 0;        
        if (family != null) {
            // Return early if we're asked for the same face/style
            if (family.mStyle == style) {
                return family;
            }

            ni = family.native_instance;
        }
        return new Typeface(nativeCreateFromTypeface(ni, style));

        Typeface typeface;
        SparseArray<Typeface> styles = sTypefaceCache.get(ni);

        if (styles != null) {
            typeface = styles.get(style);
            if (typeface != null) {
                return typeface;
            }
        }

        typeface = new Typeface(nativeCreateFromTypeface(ni, style));
        if (styles == null) {
            styles = new SparseArray<Typeface>(4);
            sTypefaceCache.put(ni, styles);
        }
        styles.put(style, typeface);

        return typeface;
    }

    /**
@@ -143,10 +171,12 @@ public class Typeface {

    // don't allow clients to call this directly
    private Typeface(int ni) {
        if (0 == ni) {
        if (ni == 0) {
            throw new RuntimeException("native typeface cannot be made");
        }

        native_instance = ni;
        mStyle = nativeGetStyle(ni);
    }
    
    static {
@@ -165,8 +195,28 @@ public class Typeface {
    }

    protected void finalize() throws Throwable {
        super.finalize();
        try {
            nativeUnref(native_instance);
        } finally {
            super.finalize();
        }
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Typeface typeface = (Typeface) o;

        return mStyle == typeface.mStyle && native_instance == typeface.native_instance;
    }

    @Override
    public int hashCode() {
        int result = native_instance;
        result = 31 * result + mStyle;
        return result;
    }

    private static native int  nativeCreate(String familyName, int style);