19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.graphics;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.AssetManager;
201a73f732f91e97c9c66b808c245ddda36a10e987Raph Levienimport android.util.Log;
2136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhatimport android.util.LongSparseArray;
225849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinirimport android.util.LruCache;
239a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport android.util.SparseArray;
249a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
259a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport org.xmlpull.v1.XmlPullParserException;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guyimport java.io.File;
289a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.io.FileInputStream;
299a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.io.FileNotFoundException;
309a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.io.IOException;
31fb95699364e555148b437cfa1e5c69384f843845Ben Wagnerimport java.nio.ByteBuffer;
32fb95699364e555148b437cfa1e5c69384f843845Ben Wagnerimport java.nio.channels.FileChannel;
339a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.util.ArrayList;
349a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.util.HashMap;
359a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.util.List;
369a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.util.Map;
37a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The Typeface class specifies the typeface and intrinsic style of a font.
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is used in the paint, along with optionally Paint settings like
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * textSize, textSkewX, textScaleX to specify
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * how text appears when drawn (and measured).
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Typeface {
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
469a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien    private static String TAG = "Typeface";
479a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The default NORMAL typeface object */
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final Typeface DEFAULT;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The default BOLD typeface object. Note: this may be not actually be
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * bold, depending on what fonts are installed. Call getStyle() to know
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for sure.
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final Typeface DEFAULT_BOLD;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The NORMAL style of the default sans serif typeface. */
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final Typeface SANS_SERIF;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The NORMAL style of the default serif typeface. */
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final Typeface SERIF;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The NORMAL style of the default monospace typeface. */
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final Typeface MONOSPACE;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6346926698996d3857a650ed535024a88dbeaff1e1Romain Guy    static Typeface[] sDefaults;
6436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static final LongSparseArray<SparseArray<Typeface>> sTypefaceCache =
6536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat            new LongSparseArray<SparseArray<Typeface>>(3);
6646926698996d3857a650ed535024a88dbeaff1e1Romain Guy
675849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir    /**
685849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir     * Cache for Typeface objects dynamically loaded from assets. Currently max size is 16.
695849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir     */
705849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir    private static final LruCache<String, Typeface> sDynamicTypefaceCache = new LruCache<>(16);
715849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir
729a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien    static Typeface sDefaultTypeface;
739a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien    static Map<String, Typeface> sSystemFontMap;
74363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien    static FontFamily[] sFallbackFonts;
759a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
76117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    static final String FONTS_CONFIG = "fonts.xml";
77baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta
78a033630e805c407080221e20b236b6054f324670Raph Levien    /**
79a033630e805c407080221e20b236b6054f324670Raph Levien     * @hide
80a033630e805c407080221e20b236b6054f324670Raph Levien     */
8136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    public long native_instance;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Style
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int NORMAL = 0;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int BOLD = 1;
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int ITALIC = 2;
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int BOLD_ITALIC = 3;
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8946926698996d3857a650ed535024a88dbeaff1e1Romain Guy    private int mStyle = 0;
9046926698996d3857a650ed535024a88dbeaff1e1Romain Guy
919a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien    private static void setDefault(Typeface t) {
929a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        sDefaultTypeface = t;
939a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        nativeSetDefault(t.native_instance);
949a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien    }
959a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Returns the typeface's intrinsic style attributes */
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getStyle() {
9846926698996d3857a650ed535024a88dbeaff1e1Romain Guy        return mStyle;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Returns true if getStyle() has the BOLD bit set. */
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final boolean isBold() {
10346926698996d3857a650ed535024a88dbeaff1e1Romain Guy        return (mStyle & BOLD) != 0;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Returns true if getStyle() has the ITALIC bit set. */
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final boolean isItalic() {
10846926698996d3857a650ed535024a88dbeaff1e1Romain Guy        return (mStyle & ITALIC) != 0;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a typeface object given a family name, and option style information.
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If null is passed for the name, then the "default" font will be chosen.
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The resulting typeface object can be queried (getStyle()) to discover what
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * its "real" style characteristics are.
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param familyName May be null. The name of the font family.
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param style  The style (normal, bold, italic) of the typeface.
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *               e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The best matching typeface.
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Typeface create(String familyName, int style) {
1239a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        if (sSystemFontMap != null) {
1249a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien            return create(sSystemFontMap.get(familyName), style);
1259a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        }
1263660789f06c5fbcb81e6c7c79612048bff8f0f66Raph Levien        return null;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a typeface object that best matches the specified existing
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * typeface and the specified Style. Use this call if you want to pick a new
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * style from the same family of an existing typeface object. If family is
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * null, this selects from the default font's family.
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param family May be null. The name of the existing type face.
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param style  The style (normal, bold, italic) of the typeface.
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *               e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The best matching typeface.
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Typeface create(Typeface family, int style) {
141ff86bcd08827d1050a8cfd99b521c21848b3f364Raph Levien        if (style < 0 || style > 3) {
142ff86bcd08827d1050a8cfd99b521c21848b3f364Raph Levien            style = 0;
143ff86bcd08827d1050a8cfd99b521c21848b3f364Raph Levien        }
14436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        long ni = 0;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (family != null) {
14646926698996d3857a650ed535024a88dbeaff1e1Romain Guy            // Return early if we're asked for the same face/style
14746926698996d3857a650ed535024a88dbeaff1e1Romain Guy            if (family.mStyle == style) {
14846926698996d3857a650ed535024a88dbeaff1e1Romain Guy                return family;
14946926698996d3857a650ed535024a88dbeaff1e1Romain Guy            }
15046926698996d3857a650ed535024a88dbeaff1e1Romain Guy
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ni = family.native_instance;
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15346926698996d3857a650ed535024a88dbeaff1e1Romain Guy
15446926698996d3857a650ed535024a88dbeaff1e1Romain Guy        Typeface typeface;
15546926698996d3857a650ed535024a88dbeaff1e1Romain Guy        SparseArray<Typeface> styles = sTypefaceCache.get(ni);
15646926698996d3857a650ed535024a88dbeaff1e1Romain Guy
15746926698996d3857a650ed535024a88dbeaff1e1Romain Guy        if (styles != null) {
15846926698996d3857a650ed535024a88dbeaff1e1Romain Guy            typeface = styles.get(style);
15946926698996d3857a650ed535024a88dbeaff1e1Romain Guy            if (typeface != null) {
16046926698996d3857a650ed535024a88dbeaff1e1Romain Guy                return typeface;
16146926698996d3857a650ed535024a88dbeaff1e1Romain Guy            }
16246926698996d3857a650ed535024a88dbeaff1e1Romain Guy        }
16346926698996d3857a650ed535024a88dbeaff1e1Romain Guy
16446926698996d3857a650ed535024a88dbeaff1e1Romain Guy        typeface = new Typeface(nativeCreateFromTypeface(ni, style));
16546926698996d3857a650ed535024a88dbeaff1e1Romain Guy        if (styles == null) {
16646926698996d3857a650ed535024a88dbeaff1e1Romain Guy            styles = new SparseArray<Typeface>(4);
16746926698996d3857a650ed535024a88dbeaff1e1Romain Guy            sTypefaceCache.put(ni, styles);
16846926698996d3857a650ed535024a88dbeaff1e1Romain Guy        }
16946926698996d3857a650ed535024a88dbeaff1e1Romain Guy        styles.put(style, typeface);
17046926698996d3857a650ed535024a88dbeaff1e1Romain Guy
17146926698996d3857a650ed535024a88dbeaff1e1Romain Guy        return typeface;
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns one of the default typeface objects, based on the specified style
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the default typeface that corresponds to the style
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Typeface defaultFromStyle(int style) {
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sDefaults[style];
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1829a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a new typeface from the specified font data.
1855849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir     *
1865849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir     * @param mgr  The application's asset manager
1875849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir     * @param path The file name of the font data in the assets directory
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The new typeface.
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Typeface createFromAsset(AssetManager mgr, String path) {
191d573794d83a049fe59e289944f0cd77406dd776aRaph Levien        if (sFallbackFonts != null) {
1925849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir            synchronized (sDynamicTypefaceCache) {
1935849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir                final String key = createAssetUid(mgr, path);
1945849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir                Typeface typeface = sDynamicTypefaceCache.get(key);
1955849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir                if (typeface != null) return typeface;
1965849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir
1975849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir                FontFamily fontFamily = new FontFamily();
1985849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir                if (fontFamily.addFontFromAsset(mgr, path)) {
1995849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir                    FontFamily[] families = { fontFamily };
2005849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir                    typeface = createFromFamiliesWithDefault(families);
2015849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir                    sDynamicTypefaceCache.put(key, typeface);
2025849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir                    return typeface;
2035849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir                }
204d573794d83a049fe59e289944f0cd77406dd776aRaph Levien            }
205d573794d83a049fe59e289944f0cd77406dd776aRaph Levien        }
206bf8d5620f7f3be72ec217f4bcc14a417d4e1dee6Behdad Esfahbod        throw new RuntimeException("Font asset not found " + path);
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
208a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy
209a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy    /**
2105849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir     * Creates a unique id for a given AssetManager and asset path.
2115849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir     *
2125849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir     * @param mgr  AssetManager instance
2135849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir     * @param path The path for the asset.
2145849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir     * @return Unique id for a given AssetManager and asset path.
2155849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir     */
2165849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir    private static String createAssetUid(final AssetManager mgr, String path) {
2175849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir        final SparseArray<String> pkgs = mgr.getAssignedPackageIdentifiers();
2185849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir        final StringBuilder builder = new StringBuilder();
2195849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir        final int size = pkgs.size();
2205849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir        for (int i = 0; i < size; i++) {
2215849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir            builder.append(pkgs.valueAt(i));
2225849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir            builder.append("-");
2235849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir        }
2245849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir        builder.append(path);
2255849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir        return builder.toString();
2265849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir    }
2275849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir
2285849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir    /**
229a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy     * Create a new typeface from the specified font file.
230a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy     *
2319a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien     * @param path The path to the font data.
232a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy     * @return The new typeface.
233a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy     */
234a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy    public static Typeface createFromFile(File path) {
235d573794d83a049fe59e289944f0cd77406dd776aRaph Levien        return createFromFile(path.getAbsolutePath());
236a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy    }
237a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy
238a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy    /**
239a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy     * Create a new typeface from the specified font file.
240a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy     *
2419a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien     * @param path The full path to the font data.
242a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy     * @return The new typeface.
243a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy     */
244a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy    public static Typeface createFromFile(String path) {
245d573794d83a049fe59e289944f0cd77406dd776aRaph Levien        if (sFallbackFonts != null) {
246d573794d83a049fe59e289944f0cd77406dd776aRaph Levien            FontFamily fontFamily = new FontFamily();
2473fa667e22401bf3ba96957fe31167bf05d164c55Seigo Nonaka            if (fontFamily.addFont(path, 0 /* ttcIndex */)) {
248d573794d83a049fe59e289944f0cd77406dd776aRaph Levien                FontFamily[] families = { fontFamily };
249d573794d83a049fe59e289944f0cd77406dd776aRaph Levien                return createFromFamiliesWithDefault(families);
250d573794d83a049fe59e289944f0cd77406dd776aRaph Levien            }
251d573794d83a049fe59e289944f0cd77406dd776aRaph Levien        }
252bf8d5620f7f3be72ec217f4bcc14a417d4e1dee6Behdad Esfahbod        throw new RuntimeException("Font not found " + path);
253a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy    }
254a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy
2551a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    /**
2561a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien     * Create a new typeface from an array of font families.
2571a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien     *
2581a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien     * @param families array of font families
2591a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien     * @hide
2601a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien     */
2611a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    public static Typeface createFromFamilies(FontFamily[] families) {
2621a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien        long[] ptrArray = new long[families.length];
2631a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien        for (int i = 0; i < families.length; i++) {
2641a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien            ptrArray[i] = families[i].mNativePtr;
2651a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien        }
2661a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien        return new Typeface(nativeCreateFromArray(ptrArray));
2671a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    }
2681a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
269363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien    /**
270363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien     * Create a new typeface from an array of font families, including
271363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien     * also the font families in the fallback list.
272363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien     *
273363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien     * @param families array of font families
274363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien     * @hide
275363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien     */
276363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien    public static Typeface createFromFamiliesWithDefault(FontFamily[] families) {
277363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien        long[] ptrArray = new long[families.length + sFallbackFonts.length];
278363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien        for (int i = 0; i < families.length; i++) {
279363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien            ptrArray[i] = families[i].mNativePtr;
280363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien        }
281363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien        for (int i = 0; i < sFallbackFonts.length; i++) {
282363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien            ptrArray[i + families.length] = sFallbackFonts[i].mNativePtr;
283363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien        }
284363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien        return new Typeface(nativeCreateFromArray(ptrArray));
285363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien    }
286363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // don't allow clients to call this directly
28836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private Typeface(long ni) {
28946926698996d3857a650ed535024a88dbeaff1e1Romain Guy        if (ni == 0) {
29031a69fdbe1edd8d686043e8ca7d278289f65808eMike Reed            throw new RuntimeException("native typeface cannot be made");
29131a69fdbe1edd8d686043e8ca7d278289f65808eMike Reed        }
29246926698996d3857a650ed535024a88dbeaff1e1Romain Guy
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        native_instance = ni;
29446926698996d3857a650ed535024a88dbeaff1e1Romain Guy        mStyle = nativeGetStyle(ni);
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2969a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
297fb95699364e555148b437cfa1e5c69384f843845Ben Wagner    private static FontFamily makeFamilyFromParsed(FontListParser.Family family,
298fb95699364e555148b437cfa1e5c69384f843845Ben Wagner            Map<String, ByteBuffer> bufferForPath) {
299f9e3d311275c37fe5f2562993687a1627780a6d0Raph Levien        FontFamily fontFamily = new FontFamily(family.lang, family.variant);
300117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien        for (FontListParser.Font font : family.fonts) {
301fb95699364e555148b437cfa1e5c69384f843845Ben Wagner            ByteBuffer fontBuffer = bufferForPath.get(font.fontName);
302fb95699364e555148b437cfa1e5c69384f843845Ben Wagner            if (fontBuffer == null) {
303fb95699364e555148b437cfa1e5c69384f843845Ben Wagner                try (FileInputStream file = new FileInputStream(font.fontName)) {
304fb95699364e555148b437cfa1e5c69384f843845Ben Wagner                    FileChannel fileChannel = file.getChannel();
305fb95699364e555148b437cfa1e5c69384f843845Ben Wagner                    long fontSize = fileChannel.size();
306fb95699364e555148b437cfa1e5c69384f843845Ben Wagner                    fontBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize);
307fb95699364e555148b437cfa1e5c69384f843845Ben Wagner                    bufferForPath.put(font.fontName, fontBuffer);
308fb95699364e555148b437cfa1e5c69384f843845Ben Wagner                } catch (IOException e) {
309fb95699364e555148b437cfa1e5c69384f843845Ben Wagner                    Log.e(TAG, "Error mapping font file " + font.fontName);
310fb95699364e555148b437cfa1e5c69384f843845Ben Wagner                    continue;
311fb95699364e555148b437cfa1e5c69384f843845Ben Wagner                }
312fb95699364e555148b437cfa1e5c69384f843845Ben Wagner            }
313fb95699364e555148b437cfa1e5c69384f843845Ben Wagner            if (!fontFamily.addFontWeightStyle(fontBuffer, font.ttcIndex, font.axes,
314fb95699364e555148b437cfa1e5c69384f843845Ben Wagner                    font.weight, font.isItalic)) {
315fb95699364e555148b437cfa1e5c69384f843845Ben Wagner                Log.e(TAG, "Error creating font " + font.fontName + "#" + font.ttcIndex);
316fb95699364e555148b437cfa1e5c69384f843845Ben Wagner            }
3179a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        }
3189a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        return fontFamily;
3199a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien    }
3209a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
321baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta    /*
322baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta     * (non-Javadoc)
323baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta     *
324baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta     * This should only be called once, from the static class initializer block.
325baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta     */
326baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta    private static void init() {
3279a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        // Load font config and initialize Minikin state
328baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta        File systemFontConfigLocation = getSystemFontConfigLocation();
329117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien        File configFilename = new File(systemFontConfigLocation, FONTS_CONFIG);
3309a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        try {
331117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien            FileInputStream fontsIn = new FileInputStream(configFilename);
332117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien            FontListParser.Config fontConfig = FontListParser.parse(fontsIn);
3339a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
334fb95699364e555148b437cfa1e5c69384f843845Ben Wagner            Map<String, ByteBuffer> bufferForPath = new HashMap<String, ByteBuffer>();
335fb95699364e555148b437cfa1e5c69384f843845Ben Wagner
336363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien            List<FontFamily> familyList = new ArrayList<FontFamily>();
337363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien            // Note that the default typeface is always present in the fallback list;
338363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien            // this is an enhancement from pre-Minikin behavior.
339117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien            for (int i = 0; i < fontConfig.families.size(); i++) {
340a87b07d7fafd59ae26073a80cd742b17ea427ecdBen Wagner                FontListParser.Family f = fontConfig.families.get(i);
341117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                if (i == 0 || f.name == null) {
342fb95699364e555148b437cfa1e5c69384f843845Ben Wagner                    familyList.add(makeFamilyFromParsed(f, bufferForPath));
343117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                }
344363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien            }
345363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien            sFallbackFonts = familyList.toArray(new FontFamily[familyList.size()]);
346363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien            setDefault(Typeface.createFromFamilies(sFallbackFonts));
347363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien
3489a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien            Map<String, Typeface> systemFonts = new HashMap<String, Typeface>();
349117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien            for (int i = 0; i < fontConfig.families.size(); i++) {
350363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien                Typeface typeface;
351a87b07d7fafd59ae26073a80cd742b17ea427ecdBen Wagner                FontListParser.Family f = fontConfig.families.get(i);
352117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                if (f.name != null) {
353117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                    if (i == 0) {
354117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                        // The first entry is the default typeface; no sense in
355117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                        // duplicating the corresponding FontFamily.
356117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                        typeface = sDefaultTypeface;
357117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                    } else {
358fb95699364e555148b437cfa1e5c69384f843845Ben Wagner                        FontFamily fontFamily = makeFamilyFromParsed(f, bufferForPath);
359117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                        FontFamily[] families = { fontFamily };
360117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                        typeface = Typeface.createFromFamiliesWithDefault(families);
361117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                    }
362117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                    systemFonts.put(f.name, typeface);
363363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien                }
364117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien            }
365117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien            for (FontListParser.Alias alias : fontConfig.aliases) {
366117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                Typeface base = systemFonts.get(alias.toName);
367117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                Typeface newFace = base;
368117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                int weight = alias.weight;
369117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                if (weight != 400) {
370117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                    newFace = new Typeface(nativeCreateWeightAlias(base.native_instance, weight));
3719a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien                }
372117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                systemFonts.put(alias.name, newFace);
3739a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien            }
3749a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien            sSystemFontMap = systemFonts;
3759a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
3769a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        } catch (RuntimeException e) {
377117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien            Log.w(TAG, "Didn't create default family (most likely, non-Minikin build)", e);
3789a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien            // TODO: normal in non-Minikin case, remove or make error when Minikin-only
3799a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        } catch (FileNotFoundException e) {
380a87b07d7fafd59ae26073a80cd742b17ea427ecdBen Wagner            Log.e(TAG, "Error opening " + configFilename, e);
3819a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        } catch (IOException e) {
382a87b07d7fafd59ae26073a80cd742b17ea427ecdBen Wagner            Log.e(TAG, "Error reading " + configFilename, e);
3839a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        } catch (XmlPullParserException e) {
384a87b07d7fafd59ae26073a80cd742b17ea427ecdBen Wagner            Log.e(TAG, "XML parse exception for " + configFilename, e);
3859a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        }
386baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta    }
3879a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
388baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta    static {
389baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta        init();
3909a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        // Set up defaults and typefaces exposed in public API
39146926698996d3857a650ed535024a88dbeaff1e1Romain Guy        DEFAULT         = create((String) null, 0);
39246926698996d3857a650ed535024a88dbeaff1e1Romain Guy        DEFAULT_BOLD    = create((String) null, Typeface.BOLD);
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SANS_SERIF      = create("sans-serif", 0);
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SERIF           = create("serif", 0);
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MONOSPACE       = create("monospace", 0);
3969a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sDefaults = new Typeface[] {
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            DEFAULT,
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            DEFAULT_BOLD,
40046926698996d3857a650ed535024a88dbeaff1e1Romain Guy            create((String) null, Typeface.ITALIC),
40146926698996d3857a650ed535024a88dbeaff1e1Romain Guy            create((String) null, Typeface.BOLD_ITALIC),
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        };
403baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta
404baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta    }
405baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta
406baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta    private static File getSystemFontConfigLocation() {
407baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta        return new File("/system/etc/");
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4109a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien    @Override
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void finalize() throws Throwable {
41246926698996d3857a650ed535024a88dbeaff1e1Romain Guy        try {
41346926698996d3857a650ed535024a88dbeaff1e1Romain Guy            nativeUnref(native_instance);
414ffa84e008c712ceffa09d6b89a49882c88b3cca5Hans Boehm            native_instance = 0;  // Other finalizers can still call us.
41546926698996d3857a650ed535024a88dbeaff1e1Romain Guy        } finally {
41646926698996d3857a650ed535024a88dbeaff1e1Romain Guy            super.finalize();
41746926698996d3857a650ed535024a88dbeaff1e1Romain Guy        }
41846926698996d3857a650ed535024a88dbeaff1e1Romain Guy    }
41946926698996d3857a650ed535024a88dbeaff1e1Romain Guy
42046926698996d3857a650ed535024a88dbeaff1e1Romain Guy    @Override
42146926698996d3857a650ed535024a88dbeaff1e1Romain Guy    public boolean equals(Object o) {
42246926698996d3857a650ed535024a88dbeaff1e1Romain Guy        if (this == o) return true;
42346926698996d3857a650ed535024a88dbeaff1e1Romain Guy        if (o == null || getClass() != o.getClass()) return false;
42446926698996d3857a650ed535024a88dbeaff1e1Romain Guy
42546926698996d3857a650ed535024a88dbeaff1e1Romain Guy        Typeface typeface = (Typeface) o;
42646926698996d3857a650ed535024a88dbeaff1e1Romain Guy
42746926698996d3857a650ed535024a88dbeaff1e1Romain Guy        return mStyle == typeface.mStyle && native_instance == typeface.native_instance;
42846926698996d3857a650ed535024a88dbeaff1e1Romain Guy    }
42946926698996d3857a650ed535024a88dbeaff1e1Romain Guy
43046926698996d3857a650ed535024a88dbeaff1e1Romain Guy    @Override
43146926698996d3857a650ed535024a88dbeaff1e1Romain Guy    public int hashCode() {
43236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        /*
43336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat         * Modified method for hashCode with long native_instance derived from
43436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat         * http://developer.android.com/reference/java/lang/Object.html
43536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat         */
43636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        int result = 17;
43736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        result = 31 * result + (int) (native_instance ^ (native_instance >>> 32));
43846926698996d3857a650ed535024a88dbeaff1e1Romain Guy        result = 31 * result + mStyle;
43946926698996d3857a650ed535024a88dbeaff1e1Romain Guy        return result;
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
44236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native long nativeCreateFromTypeface(long native_instance, int style);
443117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    private static native long nativeCreateWeightAlias(long native_instance, int weight);
44436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native void nativeUnref(long native_instance);
44536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native int  nativeGetStyle(long native_instance);
4461a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    private static native long nativeCreateFromArray(long[] familyArray);
4479a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien    private static native void nativeSetDefault(long native_instance);
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
449