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
19ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonakaimport static android.content.res.FontResourcesParser.FamilyResourceEntry;
2046dd24a710ee93ef9d75ea74e8a196e213f2e1daSiyamed Sinirimport static android.content.res.FontResourcesParser.FontFamilyFilesResourceEntry;
2146dd24a710ee93ef9d75ea74e8a196e213f2e1daSiyamed Sinirimport static android.content.res.FontResourcesParser.FontFileResourceEntry;
2246dd24a710ee93ef9d75ea74e8a196e213f2e1daSiyamed Sinirimport static android.content.res.FontResourcesParser.ProviderResourceEntry;
23ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka
24e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonakaimport android.annotation.IntDef;
2520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonakaimport android.annotation.IntRange;
2618e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarriimport android.annotation.NonNull;
27ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarriimport android.annotation.Nullable;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.AssetManager;
29ff55115121a7a2753ba2265cb3201a3a14c0874dSeigo Nonakaimport android.graphics.fonts.FontVariationAxis;
3069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonakaimport android.net.Uri;
31080b054bddee55428943b821c99887543d1fd290Seigo Nonakaimport android.provider.FontRequest;
32b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport android.provider.FontsContract;
3304d72abde1efc963ebb2f145f859552e83b92d13Clara Bayarriimport android.text.FontConfig;
340d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonakaimport android.util.ArrayMap;
35fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarriimport android.util.Base64;
361a73f732f91e97c9c66b808c245ddda36a10e987Raph Levienimport android.util.Log;
3736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhatimport android.util.LongSparseArray;
385849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinirimport android.util.LruCache;
399a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport android.util.SparseArray;
409a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
41b0812a30499376e09e2deb5995e998c629f24985Clara Bayarriimport com.android.internal.annotations.GuardedBy;
420d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonakaimport com.android.internal.annotations.VisibleForTesting;
4320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonakaimport com.android.internal.util.Preconditions;
44b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri
45abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonakaimport dalvik.annotation.optimization.CriticalNative;
46abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka
47abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonakaimport libcore.util.NativeAllocationRegistry;
48abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka
499a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport org.xmlpull.v1.XmlPullParserException;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
51a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guyimport java.io.File;
5220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonakaimport java.io.FileDescriptor;
539a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.io.FileInputStream;
549a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.io.FileNotFoundException;
559a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.io.IOException;
56dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinirimport java.io.InputStream;
57e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonakaimport java.lang.annotation.Retention;
58e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonakaimport java.lang.annotation.RetentionPolicy;
59fb95699364e555148b437cfa1e5c69384f843845Ben Wagnerimport java.nio.ByteBuffer;
60fb95699364e555148b437cfa1e5c69384f843845Ben Wagnerimport java.nio.channels.FileChannel;
619a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.util.ArrayList;
6220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonakaimport java.util.Arrays;
6320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonakaimport java.util.Collections;
649a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.util.HashMap;
659a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.util.List;
669a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.util.Map;
67a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The Typeface class specifies the typeface and intrinsic style of a font.
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is used in the paint, along with optionally Paint settings like
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * textSize, textSkewX, textScaleX to specify
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * how text appears when drawn (and measured).
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Typeface {
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
769a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien    private static String TAG = "Typeface";
779a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
78abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka    private static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
79abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka            Typeface.class.getClassLoader(), nativeGetReleaseFunc(), 64);
80abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The default NORMAL typeface object */
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final Typeface DEFAULT;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The default BOLD typeface object. Note: this may be not actually be
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * bold, depending on what fonts are installed. Call getStyle() to know
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * for sure.
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final Typeface DEFAULT_BOLD;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The NORMAL style of the default sans serif typeface. */
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final Typeface SANS_SERIF;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The NORMAL style of the default serif typeface. */
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final Typeface SERIF;
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** The NORMAL style of the default monospace typeface. */
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final Typeface MONOSPACE;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9646926698996d3857a650ed535024a88dbeaff1e1Romain Guy    static Typeface[] sDefaults;
974a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka
984a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka    /**
994a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka     * Cache for Typeface objects for style variant. Currently max size is 3.
1004a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka     */
1014a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka    @GuardedBy("sStyledCacheLock")
1024a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka    private static final LongSparseArray<SparseArray<Typeface>> sStyledTypefaceCache =
103b0812a30499376e09e2deb5995e998c629f24985Clara Bayarri            new LongSparseArray<>(3);
1044a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka    private static final Object sStyledCacheLock = new Object();
1054a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka
1064a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka    /**
1074a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka     * Cache for Typeface objects for weight variant. Currently max size is 3.
1084a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka     */
1094a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka    @GuardedBy("sWeightCacheLock")
1104a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka    private static final LongSparseArray<SparseArray<Typeface>> sWeightTypefaceCache =
1114a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka            new LongSparseArray<>(3);
1124a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka    private static final Object sWeightCacheLock = new Object();
11346926698996d3857a650ed535024a88dbeaff1e1Romain Guy
1145849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir    /**
1155849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir     * Cache for Typeface objects dynamically loaded from assets. Currently max size is 16.
1165849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir     */
1174a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka    @GuardedBy("sDynamicCacheLock")
1185849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir    private static final LruCache<String, Typeface> sDynamicTypefaceCache = new LruCache<>(16);
1194a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka    private static final Object sDynamicCacheLock = new Object();
1205849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir
1219a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien    static Typeface sDefaultTypeface;
1220d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka    static final Map<String, Typeface> sSystemFontMap;
1230d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka    static final Map<String, FontFamily[]> sSystemFallbackMap;
1249a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
125a033630e805c407080221e20b236b6054f324670Raph Levien    /**
126a033630e805c407080221e20b236b6054f324670Raph Levien     * @hide
127a033630e805c407080221e20b236b6054f324670Raph Levien     */
12836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    public long native_instance;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
130e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka    /** @hide */
131e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka    @IntDef(value = {NORMAL, BOLD, ITALIC, BOLD_ITALIC})
132e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka    @Retention(RetentionPolicy.SOURCE)
133e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka    public @interface Style {}
134e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Style
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int NORMAL = 0;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int BOLD = 1;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int ITALIC = 2;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static final int BOLD_ITALIC = 3;
1404a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka    /** @hide */ public static final int STYLE_MASK = 0x03;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
142e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka    private @Style int mStyle = 0;
143e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka
144e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka    /**
145e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka     * A maximum value for the weight value.
146e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka     * @hide
147e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka     */
148e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka    public static final int MAX_WEIGHT = 1000;
149e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka
150e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka    private @IntRange(from = 0, to = MAX_WEIGHT) int mWeight = 0;
15146926698996d3857a650ed535024a88dbeaff1e1Romain Guy
1525421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka    // Value for weight and italic. Indicates the value is resolved by font metadata.
1535421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka    // Must be the same as the C++ constant in core/jni/android/graphics/FontFamily.cpp
1545421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka    /** @hide */
1555421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka    public static final int RESOLVE_BY_FONT_TABLE = -1;
1560d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka    private static final String DEFAULT_FAMILY = "sans-serif";
1575421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka
1585421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka    // Style value for building typeface.
1595421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka    private static final int STYLE_NORMAL = 0;
1605421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka    private static final int STYLE_ITALIC = 1;
1615421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka
1620763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka    private int[] mSupportedAxes;
1630763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka    private static final int[] EMPTY_AXES = {};
1640763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka
1659a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien    private static void setDefault(Typeface t) {
1669a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        sDefaultTypeface = t;
1679a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        nativeSetDefault(t.native_instance);
1689a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien    }
1699a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
170f3523ec5242f90f9608d7f860144f58ef5707b10Seigo Nonaka    /** Returns the typeface's weight value */
171f3523ec5242f90f9608d7f860144f58ef5707b10Seigo Nonaka    public @IntRange(from = 0, to = 1000) int getWeight() {
1724a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka        return mWeight;
1734a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka    }
1744a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Returns the typeface's intrinsic style attributes */
176e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka    public @Style int getStyle() {
17746926698996d3857a650ed535024a88dbeaff1e1Romain Guy        return mStyle;
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Returns true if getStyle() has the BOLD bit set. */
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final boolean isBold() {
18246926698996d3857a650ed535024a88dbeaff1e1Romain Guy        return (mStyle & BOLD) != 0;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /** Returns true if getStyle() has the ITALIC bit set. */
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public final boolean isItalic() {
18746926698996d3857a650ed535024a88dbeaff1e1Romain Guy        return (mStyle & ITALIC) != 0;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
19118e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri     * @hide
192ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri     * Used by Resources to load a font resource of type font file.
19318e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri     */
194ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri    @Nullable
19518e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri    public static Typeface createFromResources(AssetManager mgr, String path, int cookie) {
1964a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka        synchronized (sDynamicCacheLock) {
1970d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            final String key = Builder.createAssetUid(
1980d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    mgr, path, 0 /* ttcIndex */, null /* axes */,
1990d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    RESOLVE_BY_FONT_TABLE /* weight */, RESOLVE_BY_FONT_TABLE /* italic */,
2000d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    DEFAULT_FAMILY);
2010d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            Typeface typeface = sDynamicTypefaceCache.get(key);
2020d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            if (typeface != null) return typeface;
2030d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka
2040d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            FontFamily fontFamily = new FontFamily();
2050d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            // TODO: introduce ttc index and variation settings to resource type font.
2060d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            if (fontFamily.addFontFromAssetManager(mgr, path, cookie, false /* isAsset */,
2070d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    0 /* ttcIndex */, RESOLVE_BY_FONT_TABLE /* weight */,
2080d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    RESOLVE_BY_FONT_TABLE /* italic */, null /* axes */)) {
2090d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                if (!fontFamily.freeze()) {
2100d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    return null;
21118e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri                }
2120d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                FontFamily[] families = {fontFamily};
2130d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                typeface = createFromFamiliesWithDefault(families, DEFAULT_FAMILY,
2140d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                        RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
2150d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                sDynamicTypefaceCache.put(key, typeface);
2160d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                return typeface;
21718e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri            }
21818e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri        }
219ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri        return null;
220ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri    }
221ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri
222ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri    /**
223ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri     * @hide
224ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri     * Used by Resources to load a font resource of type xml.
225ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri     */
226ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri    @Nullable
227ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka    public static Typeface createFromResources(
228ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka            FamilyResourceEntry entry, AssetManager mgr, String path) {
2290d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        if (entry instanceof ProviderResourceEntry) {
2300d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            final ProviderResourceEntry providerEntry = (ProviderResourceEntry) entry;
2310d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            // Downloadable font
2320d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            List<List<String>> givenCerts = providerEntry.getCerts();
2330d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            List<List<byte[]>> certs = new ArrayList<>();
2340d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            if (givenCerts != null) {
2350d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                for (int i = 0; i < givenCerts.size(); i++) {
2360d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    List<String> certSet = givenCerts.get(i);
2370d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    List<byte[]> byteArraySet = new ArrayList<>();
2380d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    for (int j = 0; j < certSet.size(); j++) {
2390d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                        byteArraySet.add(Base64.decode(certSet.get(j), Base64.DEFAULT));
240fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri                    }
2410d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    certs.add(byteArraySet);
242fb483cc90c27a9c0fcafa28343a8fd644f8384a4Clara Bayarri                }
2434b5a4d221f377686a730182a3bffb8c6f190e313Clara Bayarri            }
2440d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            // Downloaded font and it wasn't cached, request it again and return a
2450d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            // default font instead (nothing we can do now).
2460d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            FontRequest request = new FontRequest(providerEntry.getAuthority(),
2470d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    providerEntry.getPackage(), providerEntry.getQuery(), certs);
2480d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            Typeface typeface = FontsContract.getFontSync(request);
2490d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            return typeface == null ? DEFAULT : typeface;
2500d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        }
251ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri
2520d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        Typeface typeface = findFromCache(mgr, path);
2530d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        if (typeface != null) return typeface;
2545a09c64345ba35783b5d24ed7c4ca0ea8afbcc0aSeigo Nonaka
2550d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        // family is FontFamilyFilesResourceEntry
2560d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        final FontFamilyFilesResourceEntry filesEntry = (FontFamilyFilesResourceEntry) entry;
257ac873c9f25d2a687c9195226b9d680f51c91fa30Seigo Nonaka
2580d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        FontFamily fontFamily = new FontFamily();
2590d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        for (final FontFileResourceEntry fontFile : filesEntry.getEntries()) {
2600d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            if (!fontFamily.addFontFromAssetManager(mgr, fontFile.getFileName(),
261e34ad1871b9f7da309af0b4e11b93b1be834f38bMihai Popa                    0 /* resourceCookie */, false /* isAsset */, fontFile.getTtcIndex(),
262690e62bb6849aa7ad2d9e012138e8a5054059ed8Mihai Popa                    fontFile.getWeight(), fontFile.getItalic(),
263690e62bb6849aa7ad2d9e012138e8a5054059ed8Mihai Popa                    FontVariationAxis.fromFontVariationSettings(fontFile.getVariationSettings()))) {
2645e0aed49a874b32b135bbd8da620357764b69ad4Seigo Nonaka                return null;
2655e0aed49a874b32b135bbd8da620357764b69ad4Seigo Nonaka            }
266ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri        }
2670d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        if (!fontFamily.freeze()) {
2680d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            return null;
2690d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        }
2700d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        FontFamily[] familyChain = { fontFamily };
2710d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        typeface = createFromFamiliesWithDefault(familyChain, DEFAULT_FAMILY,
2720d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE);
2734a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka        synchronized (sDynamicCacheLock) {
2740d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */,
2750d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    null /* axes */, RESOLVE_BY_FONT_TABLE /* weight */,
2760d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    RESOLVE_BY_FONT_TABLE /* italic */, DEFAULT_FAMILY);
2770d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            sDynamicTypefaceCache.put(key, typeface);
2780d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        }
2790d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        return typeface;
280ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri    }
281ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri
282ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri    /**
283b12397e57e79c5dd9e8b2cb3839f5cd30b5d515fClara Bayarri     * Used by resources for cached loading if the font is available.
284ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri     * @hide
285ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri     */
286b12397e57e79c5dd9e8b2cb3839f5cd30b5d515fClara Bayarri    public static Typeface findFromCache(AssetManager mgr, String path) {
2874a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka        synchronized (sDynamicCacheLock) {
288d154829cb15d61f1469f939d608e691256e2a765Seigo Nonaka            final String key = Builder.createAssetUid(mgr, path, 0 /* ttcIndex */, null /* axes */,
2890d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    RESOLVE_BY_FONT_TABLE /* weight */, RESOLVE_BY_FONT_TABLE /* italic */,
2900d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    DEFAULT_FAMILY);
291ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri            Typeface typeface = sDynamicTypefaceCache.get(key);
292ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri            if (typeface != null) {
293ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri                return typeface;
294ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri            }
295ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri        }
296ed00bfdfae5d5cbc9e13f4e8affdece48f4c5b7fClara Bayarri        return null;
29718e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri    }
29818e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri
29918e9f9f3778318918c44d944489cb50daaf45d1cClara Bayarri    /**
30020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     * A builder class for creating new Typeface instance.
30120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     *
3025421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka     * <p>
30320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     * Examples,
30420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     * 1) Create Typeface from ttf file.
30520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     * <pre>
30620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     * <code>
3075421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka     * Typeface.Builder buidler = new Typeface.Builder("your_font_file.ttf");
30820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     * Typeface typeface = builder.build();
30920e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     * </code>
31020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     * </pre>
31120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     *
31220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     * 2) Create Typeface from ttc file in assets directory.
31320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     * <pre>
31420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     * <code>
3155421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka     * Typeface.Builder buidler = new Typeface.Builder(getAssets(), "your_font_file.ttc");
3165421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka     * builder.setTtcIndex(2);  // Set index of font collection.
31720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     * Typeface typeface = builder.build();
31820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     * </code>
31920e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     * </pre>
32020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     *
3215421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka     * 3) Create Typeface with variation settings.
32220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     * <pre>
3235421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka     * <code>
3245421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka     * Typeface.Builder buidler = new Typeface.Builder("your_font_file.ttf");
3255421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka     * builder.setFontVariationSettings("'wght' 700, 'slnt' 20, 'ital' 1");
3265421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka     * builder.setWeight(700);  // Tell the system that this is a bold font.
3275421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka     * builder.setItalic(true);  // Tell the system that this is an italic style font.
3285421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka     * Typeface typeface = builder.build();
3295421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka     * </code>
3305421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka     * </pre>
3315421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka     * </p>
33220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka     */
33320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka    public static final class Builder {
33469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka        /** @hide */
33569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka        public static final int NORMAL_WEIGHT = 400;
33669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka        /** @hide */
33769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka        public static final int BOLD_WEIGHT = 700;
33820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka
33920e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        private int mTtcIndex;
340ff55115121a7a2753ba2265cb3201a3a14c0874dSeigo Nonaka        private FontVariationAxis[] mAxes;
34120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka
34220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        private AssetManager mAssetManager;
34320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        private String mPath;
34420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        private FileDescriptor mFd;
34520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka
34669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka        private FontsContract.FontInfo[] mFonts;
34769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka        private Map<Uri, ByteBuffer> mFontBuffers;
3485b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka
34969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka        private String mFallbackFamilyName;
35069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka
3515421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka        private int mWeight = RESOLVE_BY_FONT_TABLE;
3525421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka        private int mItalic = RESOLVE_BY_FONT_TABLE;
35320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka
35420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        /**
3555421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka         * Constructs a builder with a file path.
35620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         *
35720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * @param path The file object refers to the font file.
35820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         */
3595421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka        public Builder(@NonNull File path) {
3605421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka            mPath = path.getAbsolutePath();
36120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        }
36220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka
36320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        /**
3645421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka         * Constructs a builder with a file descriptor.
36520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         *
36683ba4f9a04833409080d97480a665e029ee71365Seigo Nonaka         * Caller is responsible for closing the passed file descriptor after {@link #build} is
36783ba4f9a04833409080d97480a665e029ee71365Seigo Nonaka         * called.
36883ba4f9a04833409080d97480a665e029ee71365Seigo Nonaka         *
36920e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * @param fd The file descriptor. The passed fd must be mmap-able.
37020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         */
3715421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka        public Builder(@NonNull FileDescriptor fd) {
37220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            mFd = fd;
37320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        }
37420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka
37520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        /**
3765421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka         * Constructs a builder with a file path.
37720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         *
37820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * @param path The full path to the font file.
37920e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         */
3805421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka        public Builder(@NonNull String path) {
38120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            mPath = path;
38220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        }
38320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka
38420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        /**
3855421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka         * Constructs a builder from an asset manager and a file path in an asset directory.
38620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         *
38720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * @param assetManager The application's asset manager
38820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * @param path The file name of the font data in the asset directory
38920e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         */
3905421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka        public Builder(@NonNull AssetManager assetManager, @NonNull String path) {
39120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            mAssetManager = Preconditions.checkNotNull(assetManager);
39220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            mPath = Preconditions.checkStringNotEmpty(path);
39320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        }
39420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka
39520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        /**
39669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka         * Constracts a builder from an array of FontsContract.FontInfo.
39769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka         *
39869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka         * Since {@link FontsContract.FontInfo} holds information about TTC indices and
39969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka         * variation settings, there is no need to call {@link #setTtcIndex} or
40069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka         * {@link #setFontVariationSettings}. Similary, {@link FontsContract.FontInfo} holds
40169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka         * weight and italic information, so {@link #setWeight} and {@link #setItalic} are used
40269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka         * for style matching during font selection.
40369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka         *
40446dd24a710ee93ef9d75ea74e8a196e213f2e1daSiyamed Sinir         * @param fonts The array of {@link FontsContract.FontInfo}
40569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka         * @param buffers The mapping from URI to buffers to be used during building.
40669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka         * @hide
40769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka         */
40869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka        public Builder(@NonNull FontsContract.FontInfo[] fonts,
40969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                @NonNull Map<Uri, ByteBuffer> buffers) {
41069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka            mFonts = fonts;
41169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka            mFontBuffers = buffers;
41269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka        }
41369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka
41469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka        /**
41520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * Sets weight of the font.
41620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         *
4175421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka         * Tells the system the weight of the given font. If not provided, the system will resolve
4185421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka         * the weight value by reading font tables.
4195421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka         * @param weight a weight value.
42020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         */
4215421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka        public Builder setWeight(@IntRange(from = 1, to = 1000) int weight) {
42220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            mWeight = weight;
42320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            return this;
42420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        }
42520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka
42620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        /**
42720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * Sets italic information of the font.
42820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         *
4295421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka         * Tells the system the style of the given font. If not provided, the system will resolve
4305421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka         * the style by reading font tables.
4315421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka         * @param italic {@code true} if the font is italic. Otherwise {@code false}.
43220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         */
4335421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka        public Builder setItalic(boolean italic) {
4345421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka            mItalic = italic ? STYLE_ITALIC : STYLE_NORMAL;
43520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            return this;
43620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        }
43720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka
43820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        /**
439e72b5c5163d2928c61850e60f422aaf960ed2675Mihai Popa         * Sets an index of the font collection. See {@link android.R.attr#ttcIndex}.
44020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         *
44120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * Can not be used for Typeface source. build() method will return null for invalid index.
44220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * @param ttcIndex An index of the font collection. If the font source is not font
44320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         *                 collection, do not call this method or specify 0.
44420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         */
44520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        public Builder setTtcIndex(@IntRange(from = 0) int ttcIndex) {
44669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka            if (mFonts != null) {
44769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                throw new IllegalArgumentException(
44869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                        "TTC index can not be specified for FontResult source.");
44969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka            }
45020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            mTtcIndex = ttcIndex;
45120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            return this;
45220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        }
45320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka
45420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        /**
45520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * Sets a font variation settings.
45620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         *
45720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * @param variationSettings See {@link android.widget.TextView#setFontVariationSettings}.
4580f07dd5b14e76695bbae758e948e00b86935232cSeigo Nonaka         * @throws IllegalArgumentException If given string is not a valid font variation settings
4590f07dd5b14e76695bbae758e948e00b86935232cSeigo Nonaka         *                                  format.
46020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         */
4610f07dd5b14e76695bbae758e948e00b86935232cSeigo Nonaka        public Builder setFontVariationSettings(@Nullable String variationSettings) {
46269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka            if (mFonts != null) {
46369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                throw new IllegalArgumentException(
46469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                        "Font variation settings can not be specified for FontResult source.");
46569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka            }
46669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka            if (mAxes != null) {
46769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                throw new IllegalStateException("Font variation settings are already set.");
46869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka            }
469ff55115121a7a2753ba2265cb3201a3a14c0874dSeigo Nonaka            mAxes = FontVariationAxis.fromFontVariationSettings(variationSettings);
47020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            return this;
47120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        }
47220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka
47320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        /**
47420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * Sets a font variation settings.
47520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         *
47620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * @param axes An array of font variation axis tag-value pairs.
47720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         */
478ff55115121a7a2753ba2265cb3201a3a14c0874dSeigo Nonaka        public Builder setFontVariationSettings(@Nullable FontVariationAxis[] axes) {
47969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka            if (mFonts != null) {
48069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                throw new IllegalArgumentException(
48169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                        "Font variation settings can not be specified for FontResult source.");
48269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka            }
48369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka            if (mAxes != null) {
48469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                throw new IllegalStateException("Font variation settings are already set.");
48569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka            }
48620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            mAxes = axes;
48720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            return this;
48820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        }
48920e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka
49020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        /**
4915b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         * Sets a fallback family name.
4925b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         *
4935b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         * By specifying a fallback family name, a fallback Typeface will be returned if the
4945b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         * {@link #build} method fails to create a Typeface from the provided font. The fallback
4955b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         * family will be resolved with the provided weight and italic information specified by
4965b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         * {@link #setWeight} and {@link #setItalic}.
4975b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         *
4985b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         * If {@link #setWeight} is not called, the fallback family keeps the default weight.
4995b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         * Similary, if {@link #setItalic} is not called, the fallback family keeps the default
5005b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         * italic information. For example, calling {@code builder.setFallback("sans-serif-light")}
5015b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         * is equivalent to calling {@code builder.setFallback("sans-serif").setWeight(300)} in
5025b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         * terms of fallback. The default weight and italic information are overridden by calling
5035b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         * {@link #setWeight} and {@link #setItalic}. For example, if a Typeface is constructed
5045b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         * using {@code builder.setFallback("sans-serif-light").setWeight(700)}, the fallback text
5055b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         * will render as sans serif bold.
5065b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         *
5075b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         * @param familyName A family name to be used for fallback if the provided font can not be
5085b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         *                   used. By passing {@code null}, build() returns {@code null}.
5095b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         *                   If {@link #setFallback} is not called on the builder, {@code null}
5105b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         *                   is assumed.
5115b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka         */
5125b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka        public Builder setFallback(@Nullable String familyName) {
5135b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka            mFallbackFamilyName = familyName;
5145b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka            return this;
5155b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka        }
5165b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka
5175b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka        /**
51820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * Creates a unique id for a given AssetManager and asset path.
51920e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         *
52020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * @param mgr  AssetManager instance
52120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * @param path The path for the asset.
52220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * @param ttcIndex The TTC index for the font.
52320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * @param axes The font variation settings.
52420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * @return Unique id for a given AssetManager and asset path.
52520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         */
52620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        private static String createAssetUid(final AssetManager mgr, String path, int ttcIndex,
5270d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                @Nullable FontVariationAxis[] axes, int weight, int italic, String fallback) {
52820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            final SparseArray<String> pkgs = mgr.getAssignedPackageIdentifiers();
52920e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            final StringBuilder builder = new StringBuilder();
53020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            final int size = pkgs.size();
53120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            for (int i = 0; i < size; i++) {
53220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                builder.append(pkgs.valueAt(i));
53320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                builder.append("-");
53420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            }
53520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            builder.append(path);
53620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            builder.append("-");
53720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            builder.append(Integer.toString(ttcIndex));
53820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            builder.append("-");
539d154829cb15d61f1469f939d608e691256e2a765Seigo Nonaka            builder.append(Integer.toString(weight));
540d154829cb15d61f1469f939d608e691256e2a765Seigo Nonaka            builder.append("-");
541d154829cb15d61f1469f939d608e691256e2a765Seigo Nonaka            builder.append(Integer.toString(italic));
5420d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            // Family name may contain hyphen. Use double hyphen for avoiding key conflicts before
5430d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            // and after appending falblack name.
5440d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            builder.append("--");
5450d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            builder.append(fallback);
5460d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            builder.append("--");
54720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            if (axes != null) {
548ff55115121a7a2753ba2265cb3201a3a14c0874dSeigo Nonaka                for (FontVariationAxis axis : axes) {
549ff55115121a7a2753ba2265cb3201a3a14c0874dSeigo Nonaka                    builder.append(axis.getTag());
55020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    builder.append("-");
55120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    builder.append(Float.toString(axis.getStyleValue()));
55220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                }
55320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            }
55420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            return builder.toString();
55520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        }
55620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka
5575b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka        private Typeface resolveFallbackTypeface() {
5585b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka            if (mFallbackFamilyName == null) {
5595b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka                return null;
5605b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka            }
5615b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka
5625b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka            Typeface base =  sSystemFontMap.get(mFallbackFamilyName);
5635b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka            if (base == null) {
5645b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka                base = sDefaultTypeface;
5655b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka            }
5665b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka
5675b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka            if (mWeight == RESOLVE_BY_FONT_TABLE && mItalic == RESOLVE_BY_FONT_TABLE) {
5685b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka                return base;
5695b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka            }
5705b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka
571373b15bda93c8b400c5e1271bc93cbef26af503fSeigo Nonaka            final int weight = (mWeight == RESOLVE_BY_FONT_TABLE) ? base.mWeight : mWeight;
5725b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka            final boolean italic =
5735b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka                    (mItalic == RESOLVE_BY_FONT_TABLE) ? (base.mStyle & ITALIC) != 0 : mItalic == 1;
574762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka            return createWeightStyle(base, weight, italic);
5755b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka        }
5765b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka
57720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        /**
57820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * Generates new Typeface from specified configuration.
57920e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         *
58020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         * @return Newly created Typeface. May return null if some parameters are invalid.
58120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka         */
58220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        public Typeface build() {
583d154829cb15d61f1469f939d608e691256e2a765Seigo Nonaka            if (mFd != null) {  // Builder is created with file descriptor.
58420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                try (FileInputStream fis = new FileInputStream(mFd)) {
58520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    FileChannel channel = fis.getChannel();
58620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    long size = channel.size();
58720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    ByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, size);
58820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka
58920e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    final FontFamily fontFamily = new FontFamily();
59020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    if (!fontFamily.addFontFromBuffer(buffer, mTtcIndex, mAxes, mWeight, mItalic)) {
59120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                        fontFamily.abortCreation();
5925b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka                        return resolveFallbackTypeface();
5935b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka                    }
5945b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka                    if (!fontFamily.freeze()) {
5955b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka                        return resolveFallbackTypeface();
59620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    }
59720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    FontFamily[] families = { fontFamily };
5980d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    return createFromFamiliesWithDefault(families, mFallbackFamilyName, mWeight,
5990d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                            mItalic);
60020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                } catch (IOException e) {
6015b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka                    return resolveFallbackTypeface();
60220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                }
603d154829cb15d61f1469f939d608e691256e2a765Seigo Nonaka            } else if (mAssetManager != null) {  // Builder is created with asset manager.
604d154829cb15d61f1469f939d608e691256e2a765Seigo Nonaka                final String key = createAssetUid(
6050d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                        mAssetManager, mPath, mTtcIndex, mAxes, mWeight, mItalic,
6060d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                        mFallbackFamilyName);
6074a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka                synchronized (sDynamicCacheLock) {
60820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    Typeface typeface = sDynamicTypefaceCache.get(key);
60920e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    if (typeface != null) return typeface;
61020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    final FontFamily fontFamily = new FontFamily();
61120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    if (!fontFamily.addFontFromAssetManager(mAssetManager, mPath, mTtcIndex,
61220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                            true /* isAsset */, mTtcIndex, mWeight, mItalic, mAxes)) {
61320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                        fontFamily.abortCreation();
6145b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka                        return resolveFallbackTypeface();
6155b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka                    }
6165b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka                    if (!fontFamily.freeze()) {
6175b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka                        return resolveFallbackTypeface();
61820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    }
61920e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    FontFamily[] families = { fontFamily };
6200d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    typeface = createFromFamiliesWithDefault(families, mFallbackFamilyName,
6210d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                            mWeight, mItalic);
62220e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    sDynamicTypefaceCache.put(key, typeface);
62320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    return typeface;
62420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                }
625d154829cb15d61f1469f939d608e691256e2a765Seigo Nonaka            } else if (mPath != null) {  // Builder is created with file path.
62620e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                final FontFamily fontFamily = new FontFamily();
62720e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                if (!fontFamily.addFont(mPath, mTtcIndex, mAxes, mWeight, mItalic)) {
62820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                    fontFamily.abortCreation();
6295b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka                    return resolveFallbackTypeface();
6305b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka                }
6315b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka                if (!fontFamily.freeze()) {
6325b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka                    return resolveFallbackTypeface();
63320e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                }
63420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka                FontFamily[] families = { fontFamily };
6350d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                return createFromFamiliesWithDefault(families, mFallbackFamilyName, mWeight,
6360d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                        mItalic);
63769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka            } else if (mFonts != null) {
63869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                final FontFamily fontFamily = new FontFamily();
63969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                boolean atLeastOneFont = false;
64069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                for (FontsContract.FontInfo font : mFonts) {
64169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                    final ByteBuffer fontBuffer = mFontBuffers.get(font.getUri());
64269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                    if (fontBuffer == null) {
64369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                        continue;  // skip
64469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                    }
64569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                    final boolean success = fontFamily.addFontFromBuffer(fontBuffer,
64669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                            font.getTtcIndex(), font.getAxes(), font.getWeight(),
64769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                            font.isItalic() ? STYLE_ITALIC : STYLE_NORMAL);
64869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                    if (!success) {
64969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                        fontFamily.abortCreation();
65069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                        return null;
65169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                    }
65269754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                    atLeastOneFont = true;
65369754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                }
65469754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                if (!atLeastOneFont) {
65569754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                    // No fonts are avaialble. No need to create new Typeface and returns fallback
65669754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                    // Typeface instead.
65769754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                    fontFamily.abortCreation();
65869754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                    return null;
65969754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                }
66069754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                fontFamily.freeze();
66169754bf66dae9d047d5a0ff2c71820aa35b9cc70Seigo Nonaka                FontFamily[] families = { fontFamily };
6620d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                return createFromFamiliesWithDefault(families, mFallbackFamilyName, mWeight,
6630d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                        mItalic);
66420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka            }
6655421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka
6665421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka            // Must not reach here.
6675421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka            throw new IllegalArgumentException("No source was set.");
66820e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        }
66920e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka    }
67020e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka
67120e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka    /**
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a typeface object given a family name, and option style information.
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If null is passed for the name, then the "default" font will be chosen.
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The resulting typeface object can be queried (getStyle()) to discover what
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * its "real" style characteristics are.
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param familyName May be null. The name of the font family.
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param style  The style (normal, bold, italic) of the typeface.
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *               e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The best matching typeface.
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
682e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka    public static Typeface create(String familyName, @Style int style) {
6830d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        return create(sSystemFontMap.get(familyName), style);
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a typeface object that best matches the specified existing
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * typeface and the specified Style. Use this call if you want to pick a new
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * style from the same family of an existing typeface object. If family is
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * null, this selects from the default font's family.
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6924a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka     * <p>
6934a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka     * This method is not thread safe on API 27 or before.
6944a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka     * This method is thread safe on API 28 or after.
6954a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka     * </p>
6964a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka     *
697762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka     * @param family An existing {@link Typeface} object. In case of {@code null}, the default
698762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka     *               typeface is used instead.
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param style  The style (normal, bold, italic) of the typeface.
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *               e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The best matching typeface.
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
703e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka    public static Typeface create(Typeface family, @Style int style) {
7044a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka        if ((style & ~STYLE_MASK) != 0) {
7054a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka            style = NORMAL;
7064a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka        }
7074a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka        if (family == null) {
7084a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka            family = sDefaultTypeface;
709ff86bcd08827d1050a8cfd99b521c21848b3f364Raph Levien        }
71046926698996d3857a650ed535024a88dbeaff1e1Romain Guy
7114a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka        // Return early if we're asked for the same face/style
7124a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka        if (family.mStyle == style) {
7134a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka            return family;
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
71546926698996d3857a650ed535024a88dbeaff1e1Romain Guy
7164a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka        final long ni = family.native_instance;
71746926698996d3857a650ed535024a88dbeaff1e1Romain Guy
7184a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka        Typeface typeface;
7194a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka        synchronized (sStyledCacheLock) {
7204a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka            SparseArray<Typeface> styles = sStyledTypefaceCache.get(ni);
7214a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka
7224a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka            if (styles == null) {
7234a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka                styles = new SparseArray<Typeface>(4);
7244a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka                sStyledTypefaceCache.put(ni, styles);
7254a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka            } else {
7264a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka                typeface = styles.get(style);
7274a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka                if (typeface != null) {
7284a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka                    return typeface;
7294a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka                }
73046926698996d3857a650ed535024a88dbeaff1e1Romain Guy            }
73146926698996d3857a650ed535024a88dbeaff1e1Romain Guy
7324a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka            typeface = new Typeface(nativeCreateFromTypeface(ni, style));
7334a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka            styles.put(style, typeface);
73446926698996d3857a650ed535024a88dbeaff1e1Romain Guy        }
73546926698996d3857a650ed535024a88dbeaff1e1Romain Guy        return typeface;
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
738762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka    /**
739762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka     * Creates a typeface object that best matches the specified existing typeface and the specified
740762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka     * weight and italic style
741f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * <p>Below are numerical values and corresponding common weight names.</p>
742f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * <table>
743f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * <thead>
744f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * <tr><th>Value</th><th>Common weight name</th></tr>
745f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * </thead>
746f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * <tbody>
747f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * <tr><td>100</td><td>Thin</td></tr>
748f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * <tr><td>200</td><td>Extra Light</td></tr>
749f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * <tr><td>300</td><td>Light</td></tr>
750f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * <tr><td>400</td><td>Normal</td></tr>
751f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * <tr><td>500</td><td>Medium</td></tr>
752f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * <tr><td>600</td><td>Semi Bold</td></tr>
753f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * <tr><td>700</td><td>Bold</td></tr>
754f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * <tr><td>800</td><td>Extra Bold</td></tr>
755f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * <tr><td>900</td><td>Black</td></tr>
756f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * </tbody>
757f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * </table>
758762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka     *
7594a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka     * <p>
7604a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka     * This method is thread safe.
7614a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka     * </p>
7624a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka     *
763762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka     * @param family An existing {@link Typeface} object. In case of {@code null}, the default
764762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka     *               typeface is used instead.
765762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka     * @param weight The desired weight to be drawn.
766762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka     * @param italic {@code true} if italic style is desired to be drawn. Otherwise, {@code false}
767762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka     * @return A {@link Typeface} object for drawing specified weight and italic style. Never
768762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka     *         returns {@code null}
769f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     *
770f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * @see #getWeight()
771f2944cd61b84913c6c821594b289e7af9746efffSeigo Nonaka     * @see #isItalic()
772762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka     */
773762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka    public static @NonNull Typeface create(@Nullable Typeface family,
774762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka            @IntRange(from = 1, to = 1000) int weight, boolean italic) {
775762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka        Preconditions.checkArgumentInRange(weight, 0, 1000, "weight");
776762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka        if (family == null) {
777762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka            family = sDefaultTypeface;
778762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka        }
779762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka        return createWeightStyle(family, weight, italic);
780762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka    }
781762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka
782762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka    private static @NonNull Typeface createWeightStyle(@NonNull Typeface base,
783762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka            @IntRange(from = 1, to = 1000) int weight, boolean italic) {
7844a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka        final int key = (weight << 1) | (italic ? 1 : 0);
785762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka
786762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka        Typeface typeface;
7874a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka        synchronized(sWeightCacheLock) {
7884a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka            SparseArray<Typeface> innerCache = sWeightTypefaceCache.get(base.native_instance);
7894a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka            if (innerCache == null) {
7904a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka                innerCache = new SparseArray<>(4);
7914a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka                sWeightTypefaceCache.put(base.native_instance, innerCache);
7924a40e0febf3de60c54c19797aecd3c698b770699Seigo Nonaka            } else {
793762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka                typeface = innerCache.get(key);
794762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka                if (typeface != null) {
795762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka                    return typeface;
796762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka                }
797762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka            }
798762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka
799762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka            typeface = new Typeface(
800762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka                    nativeCreateFromTypefaceWithExactStyle(
801762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka                            base.native_instance, weight, italic));
802762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka            innerCache.put(key, typeface);
803762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka        }
804762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka        return typeface;
805762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka    }
806762dc8bdaec8a3ac32874f6aaa67e2063439445fSeigo Nonaka
8079ff994d98846d24bc488939af6e7dc440149a4bcSeigo Nonaka    /** @hide */
808ffae6c7f71e9da9f887002994d270b9dbf6d0673Seigo Nonaka    public static Typeface createFromTypefaceWithVariation(@Nullable Typeface family,
809ffae6c7f71e9da9f887002994d270b9dbf6d0673Seigo Nonaka            @NonNull List<FontVariationAxis> axes) {
8109ff994d98846d24bc488939af6e7dc440149a4bcSeigo Nonaka        final long ni = family == null ? 0 : family.native_instance;
8119ff994d98846d24bc488939af6e7dc440149a4bcSeigo Nonaka        return new Typeface(nativeCreateFromTypefaceWithVariation(ni, axes));
8129ff994d98846d24bc488939af6e7dc440149a4bcSeigo Nonaka    }
8139ff994d98846d24bc488939af6e7dc440149a4bcSeigo Nonaka
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns one of the default typeface objects, based on the specified style
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the default typeface that corresponds to the style
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
819e245116af39f58288b3003f221fc0f151b0fea05Seigo Nonaka    public static Typeface defaultFromStyle(@Style int style) {
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return sDefaults[style];
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8229a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Create a new typeface from the specified font data.
8255849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir     *
8265849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir     * @param mgr  The application's asset manager
8275849500a193ac1327242e01d7f6912d0a384ffc9Siyamed Sinir     * @param path The file name of the font data in the assets directory
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The new typeface.
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static Typeface createFromAsset(AssetManager mgr, String path) {
831dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir        Preconditions.checkNotNull(path); // for backward compatibility
832dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir        Preconditions.checkNotNull(mgr);
8335b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka
834dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir        Typeface typeface = new Builder(mgr, path).build();
835dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir        if (typeface != null) return typeface;
836dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir        // check if the file exists, and throw an exception for backward compatibility
837dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir        try (InputStream inputStream = mgr.open(path)) {
838dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir        } catch (IOException e) {
839dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir            throw new RuntimeException("Font asset not found " + path);
840d573794d83a049fe59e289944f0cd77406dd776aRaph Levien        }
841dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir
842dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir        return Typeface.DEFAULT;
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
844a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy
845a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy    /**
846b12397e57e79c5dd9e8b2cb3839f5cd30b5d515fClara Bayarri     * Creates a unique id for a given font provider and query.
847b12397e57e79c5dd9e8b2cb3839f5cd30b5d515fClara Bayarri     */
848b12397e57e79c5dd9e8b2cb3839f5cd30b5d515fClara Bayarri    private static String createProviderUid(String authority, String query) {
849b12397e57e79c5dd9e8b2cb3839f5cd30b5d515fClara Bayarri        final StringBuilder builder = new StringBuilder();
850b12397e57e79c5dd9e8b2cb3839f5cd30b5d515fClara Bayarri        builder.append("provider:");
851b12397e57e79c5dd9e8b2cb3839f5cd30b5d515fClara Bayarri        builder.append(authority);
852b12397e57e79c5dd9e8b2cb3839f5cd30b5d515fClara Bayarri        builder.append("-");
853b12397e57e79c5dd9e8b2cb3839f5cd30b5d515fClara Bayarri        builder.append(query);
854b12397e57e79c5dd9e8b2cb3839f5cd30b5d515fClara Bayarri        return builder.toString();
855b12397e57e79c5dd9e8b2cb3839f5cd30b5d515fClara Bayarri    }
856b12397e57e79c5dd9e8b2cb3839f5cd30b5d515fClara Bayarri
857b12397e57e79c5dd9e8b2cb3839f5cd30b5d515fClara Bayarri    /**
858a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy     * Create a new typeface from the specified font file.
859a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy     *
860dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir     * @param file The path to the font data.
861a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy     * @return The new typeface.
862a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy     */
863dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir    public static Typeface createFromFile(@Nullable File file) {
86420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        // For the compatibility reasons, leaving possible NPE here.
86520e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka        // See android.graphics.cts.TypefaceTest#testCreateFromFileByFileReferenceNull
866dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir
867dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir        Typeface typeface = new Builder(file).build();
868dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir        if (typeface != null) return typeface;
869dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir
870dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir        // check if the file exists, and throw an exception for backward compatibility
871dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir        if (!file.exists()) {
872dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir            throw new RuntimeException("Font asset not found " + file.getAbsolutePath());
873dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir        }
874dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir
875dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir        return Typeface.DEFAULT;
876a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy    }
877a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy
878a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy    /**
879a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy     * Create a new typeface from the specified font file.
880a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy     *
8819a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien     * @param path The full path to the font data.
882a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy     * @return The new typeface.
883a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy     */
88420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka    public static Typeface createFromFile(@Nullable String path) {
885dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir        Preconditions.checkNotNull(path); // for backward compatibility
886dbeee4e4aa74a953b10a5262065cb24d604d647aSiyamed Sinir        return createFromFile(new File(path));
887a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy    }
888a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy
8891a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    /**
8901a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien     * Create a new typeface from an array of font families.
8911a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien     *
8921a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien     * @param families array of font families
8931a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien     */
89420e5d91739fb88a02afb4888bf9f938308bc9b7bSeigo Nonaka    private static Typeface createFromFamilies(FontFamily[] families) {
8951a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien        long[] ptrArray = new long[families.length];
8961a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien        for (int i = 0; i < families.length; i++) {
8971a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien            ptrArray[i] = families[i].mNativePtr;
8981a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien        }
899d154829cb15d61f1469f939d608e691256e2a765Seigo Nonaka        return new Typeface(nativeCreateFromArray(
900d154829cb15d61f1469f939d608e691256e2a765Seigo Nonaka                ptrArray, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE));
9011a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien    }
9021a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien
903363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien    /**
90459897ec4ab51e1639f670cc2912a8a7ef34e52a1Seigo Nonaka     * This method is used by supportlib-v27.
90559897ec4ab51e1639f670cc2912a8a7ef34e52a1Seigo Nonaka     * TODO: Remove private API use in supportlib: http://b/72665240
90659897ec4ab51e1639f670cc2912a8a7ef34e52a1Seigo Nonaka     */
90759897ec4ab51e1639f670cc2912a8a7ef34e52a1Seigo Nonaka    private static Typeface createFromFamiliesWithDefault(FontFamily[] families, int weight,
90859897ec4ab51e1639f670cc2912a8a7ef34e52a1Seigo Nonaka                int italic) {
90959897ec4ab51e1639f670cc2912a8a7ef34e52a1Seigo Nonaka        return createFromFamiliesWithDefault(families, DEFAULT_FAMILY, weight, italic);
91059897ec4ab51e1639f670cc2912a8a7ef34e52a1Seigo Nonaka    }
91159897ec4ab51e1639f670cc2912a8a7ef34e52a1Seigo Nonaka
91259897ec4ab51e1639f670cc2912a8a7ef34e52a1Seigo Nonaka    /**
913363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien     * Create a new typeface from an array of font families, including
914363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien     * also the font families in the fallback list.
9150d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka     * @param fallbackName the family name. If given families don't support characters, the
9160d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka     *               characters will be rendered with this family.
91746dd24a710ee93ef9d75ea74e8a196e213f2e1daSiyamed Sinir     * @param weight the weight for this family. In that case, the table information in the first
91846dd24a710ee93ef9d75ea74e8a196e213f2e1daSiyamed Sinir     *               family's font is used. If the first family has multiple fonts, the closest to
91946dd24a710ee93ef9d75ea74e8a196e213f2e1daSiyamed Sinir     *               the regular weight and upright font is used.
92046dd24a710ee93ef9d75ea74e8a196e213f2e1daSiyamed Sinir     * @param italic the italic information for this family. In that case, the table information in
92146dd24a710ee93ef9d75ea74e8a196e213f2e1daSiyamed Sinir     *               the first family's font is used. If the first family has multiple fonts, the
92246dd24a710ee93ef9d75ea74e8a196e213f2e1daSiyamed Sinir     *               closest to the regular weight and upright font is used.
923363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien     * @param families array of font families
924363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien     */
925d154829cb15d61f1469f939d608e691256e2a765Seigo Nonaka    private static Typeface createFromFamiliesWithDefault(FontFamily[] families,
9260d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                String fallbackName, int weight, int italic) {
9270d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        FontFamily[] fallback = sSystemFallbackMap.get(fallbackName);
9280d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        if (fallback == null) {
9290d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            fallback = sSystemFallbackMap.get(DEFAULT_FAMILY);
9300d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        }
9310d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        long[] ptrArray = new long[families.length + fallback.length];
932363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien        for (int i = 0; i < families.length; i++) {
933363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien            ptrArray[i] = families[i].mNativePtr;
934363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien        }
9350d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        for (int i = 0; i < fallback.length; i++) {
9360d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            ptrArray[i + families.length] = fallback[i].mNativePtr;
937363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien        }
938d154829cb15d61f1469f939d608e691256e2a765Seigo Nonaka        return new Typeface(nativeCreateFromArray(ptrArray, weight, italic));
939363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien    }
940363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // don't allow clients to call this directly
94236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private Typeface(long ni) {
94346926698996d3857a650ed535024a88dbeaff1e1Romain Guy        if (ni == 0) {
94431a69fdbe1edd8d686043e8ca7d278289f65808eMike Reed            throw new RuntimeException("native typeface cannot be made");
94531a69fdbe1edd8d686043e8ca7d278289f65808eMike Reed        }
94646926698996d3857a650ed535024a88dbeaff1e1Romain Guy
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        native_instance = ni;
948abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka        sRegistry.registerNativeAllocation(this, native_instance);
94946926698996d3857a650ed535024a88dbeaff1e1Romain Guy        mStyle = nativeGetStyle(ni);
950373b15bda93c8b400c5e1271bc93cbef26af503fSeigo Nonaka        mWeight = nativeGetWeight(ni);
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9529a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
9530d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka    private static @Nullable ByteBuffer mmap(String fullPath) {
9540d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        try (FileInputStream file = new FileInputStream(fullPath)) {
9550d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            final FileChannel fileChannel = file.getChannel();
9560d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            final long fontSize = fileChannel.size();
9570d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            return fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize);
9580d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        } catch (IOException e) {
9590d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            Log.e(TAG, "Error mapping font file " + fullPath);
9600d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            return null;
9610d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        }
9620d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka    }
9630d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka
9640d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka    private static @Nullable FontFamily createFontFamily(
96599975a3e25e11f5c5958d8a901d37902087c75fdRoozbeh Pournader            String familyName, List<FontConfig.Font> fonts, String[] languageTags, int variant,
9660d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            Map<String, ByteBuffer> cache, String fontDir) {
96799975a3e25e11f5c5958d8a901d37902087c75fdRoozbeh Pournader        final FontFamily family = new FontFamily(languageTags, variant);
9680d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        for (int i = 0; i < fonts.size(); i++) {
9690d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            final FontConfig.Font font = fonts.get(i);
9700d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            final String fullPath = fontDir + font.getFontName();
9710d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            ByteBuffer buffer = cache.get(fullPath);
9720d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            if (buffer == null) {
9730d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                if (cache.containsKey(fullPath)) {
9740d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    continue;  // Already failed to mmap. Skip it.
9750d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                }
9760d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                buffer = mmap(fullPath);
9770d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                cache.put(fullPath, buffer);
9780d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                if (buffer == null) {
979fb95699364e555148b437cfa1e5c69384f843845Ben Wagner                    continue;
980fb95699364e555148b437cfa1e5c69384f843845Ben Wagner                }
981fb95699364e555148b437cfa1e5c69384f843845Ben Wagner            }
9820d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            if (!family.addFontFromBuffer(buffer, font.getTtcIndex(), font.getAxes(),
9835421e810233ecadf0ebc7d7760dc9ac07a141e6cSeigo Nonaka                    font.getWeight(), font.isItalic() ? STYLE_ITALIC : STYLE_NORMAL)) {
9840d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                Log.e(TAG, "Error creating font " + fullPath + "#" + font.getTtcIndex());
985fb95699364e555148b437cfa1e5c69384f843845Ben Wagner            }
9869a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        }
9870d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        if (!family.freeze()) {
98899975a3e25e11f5c5958d8a901d37902087c75fdRoozbeh Pournader            Log.e(TAG, "Unable to load Family: " + familyName + " : "
98999975a3e25e11f5c5958d8a901d37902087c75fdRoozbeh Pournader                    + Arrays.toString(languageTags));
990bf629ed08077e59877158a30cc04711319bce977Seigo Nonaka            return null;
9915b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka        }
9920d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        return family;
9939a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien    }
9949a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
9950d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka    private static void pushFamilyToFallback(FontConfig.Family xmlFamily,
9960d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            ArrayMap<String, ArrayList<FontFamily>> fallbackMap,
9970d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            Map<String, ByteBuffer> cache,
9980d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            String fontDir) {
9990d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka
100099975a3e25e11f5c5958d8a901d37902087c75fdRoozbeh Pournader        final String[] languageTags = xmlFamily.getLanguages();
10010d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        final int variant = xmlFamily.getVariant();
10020d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka
10030d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        final ArrayList<FontConfig.Font> defaultFonts = new ArrayList<>();
10040d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        final ArrayMap<String, ArrayList<FontConfig.Font>> specificFallbackFonts = new ArrayMap<>();
10050d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka
10060d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        // Collect default fallback and specific fallback fonts.
10070d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        for (final FontConfig.Font font : xmlFamily.getFonts()) {
10080d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            final String fallbackName = font.getFallbackFor();
10090d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            if (fallbackName == null) {
10100d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                defaultFonts.add(font);
10110d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            } else {
10120d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                ArrayList<FontConfig.Font> fallback = specificFallbackFonts.get(fallbackName);
10130d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                if (fallback == null) {
10140d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    fallback = new ArrayList<>();
10150d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    specificFallbackFonts.put(fallbackName, fallback);
10160d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                }
10170d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                fallback.add(font);
10180d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            }
10190d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        }
10200d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka
10210d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        final FontFamily defaultFamily = defaultFonts.isEmpty() ? null : createFontFamily(
102299975a3e25e11f5c5958d8a901d37902087c75fdRoozbeh Pournader                xmlFamily.getName(), defaultFonts, languageTags, variant, cache, fontDir);
10230d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka
10240d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        // Insert family into fallback map.
10250d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        for (int i = 0; i < fallbackMap.size(); i++) {
10260d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            final ArrayList<FontConfig.Font> fallback =
10270d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    specificFallbackFonts.get(fallbackMap.keyAt(i));
10280d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            if (fallback == null) {
10290d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                if (defaultFamily != null) {
10300d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    fallbackMap.valueAt(i).add(defaultFamily);
10310d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                }
10320d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            } else {
10330d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                final FontFamily family = createFontFamily(
103499975a3e25e11f5c5958d8a901d37902087c75fdRoozbeh Pournader                        xmlFamily.getName(), fallback, languageTags, variant, cache, fontDir);
10350d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                if (family != null) {
10360d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    fallbackMap.valueAt(i).add(family);
1037545faa4c4c1a74360ed27f81cdc6dce1c7a067e4Seigo Nonaka                } else if (defaultFamily != null) {
1038545faa4c4c1a74360ed27f81cdc6dce1c7a067e4Seigo Nonaka                    fallbackMap.valueAt(i).add(defaultFamily);
1039545faa4c4c1a74360ed27f81cdc6dce1c7a067e4Seigo Nonaka                } else {
1040545faa4c4c1a74360ed27f81cdc6dce1c7a067e4Seigo Nonaka                    // There is no valid for for default fallback. Ignore.
10410d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                }
10420d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            }
10430d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        }
10440d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka    }
10450d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka
10460d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka    /**
10470d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka     * Build the system fallback from xml file.
1048baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta     *
10490d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka     * @param xmlPath A full path string to the fonts.xml file.
10500d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka     * @param fontDir A full path string to the system font directory. This must end with
10510d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka     *                slash('/').
10520d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka     * @param fontMap An output system font map. Caller must pass empty map.
10530d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka     * @param fallbackMap An output system fallback map. Caller must pass empty map.
10540d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka     * @hide
1055baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta     */
10560d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka    @VisibleForTesting
10570d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka    public static void buildSystemFallback(String xmlPath, String fontDir,
10580d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            ArrayMap<String, Typeface> fontMap, ArrayMap<String, FontFamily[]> fallbackMap) {
10599a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        try {
10600d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            final FileInputStream fontsIn = new FileInputStream(xmlPath);
10610d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            final FontConfig fontConfig = FontListParser.parse(fontsIn);
10620d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka
10630d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            final HashMap<String, ByteBuffer> bufferCache = new HashMap<String, ByteBuffer>();
10640d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            final FontConfig.Family[] xmlFamilies = fontConfig.getFamilies();
10650d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka
10660d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            final ArrayMap<String, ArrayList<FontFamily>> fallbackListMap = new ArrayMap<>();
10670d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            // First traverse families which have a 'name' attribute to create fallback map.
10680d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            for (final FontConfig.Family xmlFamily : xmlFamilies) {
10690d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                final String familyName = xmlFamily.getName();
10700d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                if (familyName == null) {
10710d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    continue;
10720d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                }
10730d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                final FontFamily family = createFontFamily(
10740d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                        xmlFamily.getName(), Arrays.asList(xmlFamily.getFonts()),
107599975a3e25e11f5c5958d8a901d37902087c75fdRoozbeh Pournader                        xmlFamily.getLanguages(), xmlFamily.getVariant(), bufferCache, fontDir);
10760d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                if (family == null) {
10770d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    continue;
1078117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                }
10790d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                final ArrayList<FontFamily> fallback = new ArrayList<>();
10800d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                fallback.add(family);
10810d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                fallbackListMap.put(familyName, fallback);
1082363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien            }
10830d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka
10840d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            // Then, add fallback fonts to the each fallback map.
10850d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            for (int i = 0; i < xmlFamilies.length; i++) {
10860d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                final FontConfig.Family xmlFamily = xmlFamilies[i];
10870d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                // The first family (usually the sans-serif family) is always placed immediately
10880d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                // after the primary family in the fallback.
10890d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                if (i == 0 || xmlFamily.getName() == null) {
10900d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    pushFamilyToFallback(xmlFamily, fallbackListMap, bufferCache, fontDir);
10910d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                }
10920d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            }
10930d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka
10940d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            // Build the font map and fallback map.
10950d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            for (int i = 0; i < fallbackListMap.size(); i++) {
10960d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                final String fallbackName = fallbackListMap.keyAt(i);
10970d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                final List<FontFamily> familyList = fallbackListMap.valueAt(i);
10980d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                final FontFamily[] families = familyList.toArray(new FontFamily[familyList.size()]);
10990d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka
11000d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                fallbackMap.put(fallbackName, families);
11010d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                final long[] ptrArray = new long[families.length];
11020d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                for (int j = 0; j < families.length; j++) {
11030d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                    ptrArray[j] = families[j].mNativePtr;
1104363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien                }
11050d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                fontMap.put(fallbackName, new Typeface(nativeCreateFromArray(
11060d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                        ptrArray, RESOLVE_BY_FONT_TABLE, RESOLVE_BY_FONT_TABLE)));
1107117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien            }
11080d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka
11090d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            // Insert alias to font maps.
11100d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            for (final FontConfig.Alias alias : fontConfig.getAliases()) {
11110d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                Typeface base = fontMap.get(alias.getToName());
1112117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                Typeface newFace = base;
111304d72abde1efc963ebb2f145f859552e83b92d13Clara Bayarri                int weight = alias.getWeight();
1114117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                if (weight != 400) {
1115117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien                    newFace = new Typeface(nativeCreateWeightAlias(base.native_instance, weight));
11169a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien                }
11170d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                fontMap.put(alias.getName(), newFace);
11189a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien            }
11199a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        } catch (RuntimeException e) {
1120117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien            Log.w(TAG, "Didn't create default family (most likely, non-Minikin build)", e);
11219a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien            // TODO: normal in non-Minikin case, remove or make error when Minikin-only
11229a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        } catch (FileNotFoundException e) {
11230d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            Log.e(TAG, "Error opening " + xmlPath, e);
11249a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        } catch (IOException e) {
11250d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            Log.e(TAG, "Error reading " + xmlPath, e);
11269a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        } catch (XmlPullParserException e) {
11270d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka            Log.e(TAG, "XML parse exception for " + xmlPath, e);
11289a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        }
1129baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta    }
11309a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
1131baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta    static {
11320d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        final ArrayMap<String, Typeface> systemFontMap = new ArrayMap<>();
11330d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        final ArrayMap<String, FontFamily[]> systemFallbackMap = new ArrayMap<>();
11340d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/", systemFontMap,
11350d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka                systemFallbackMap);
11360d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        sSystemFontMap = Collections.unmodifiableMap(systemFontMap);
11370d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        sSystemFallbackMap = Collections.unmodifiableMap(systemFallbackMap);
11380d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka
11390d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka        setDefault(sSystemFontMap.get(DEFAULT_FAMILY));
11400d253e46aa0b4cb2ea56e220812aeab92de64ae1Seigo Nonaka
11419a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien        // Set up defaults and typefaces exposed in public API
114246926698996d3857a650ed535024a88dbeaff1e1Romain Guy        DEFAULT         = create((String) null, 0);
114346926698996d3857a650ed535024a88dbeaff1e1Romain Guy        DEFAULT_BOLD    = create((String) null, Typeface.BOLD);
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SANS_SERIF      = create("sans-serif", 0);
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SERIF           = create("serif", 0);
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        MONOSPACE       = create("monospace", 0);
11479a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        sDefaults = new Typeface[] {
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            DEFAULT,
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            DEFAULT_BOLD,
115146926698996d3857a650ed535024a88dbeaff1e1Romain Guy            create((String) null, Typeface.ITALIC),
115246926698996d3857a650ed535024a88dbeaff1e1Romain Guy            create((String) null, Typeface.BOLD_ITALIC),
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        };
1154baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta
1155baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta    }
1156baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta
11579a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien    @Override
115846926698996d3857a650ed535024a88dbeaff1e1Romain Guy    public boolean equals(Object o) {
115946926698996d3857a650ed535024a88dbeaff1e1Romain Guy        if (this == o) return true;
116046926698996d3857a650ed535024a88dbeaff1e1Romain Guy        if (o == null || getClass() != o.getClass()) return false;
116146926698996d3857a650ed535024a88dbeaff1e1Romain Guy
116246926698996d3857a650ed535024a88dbeaff1e1Romain Guy        Typeface typeface = (Typeface) o;
116346926698996d3857a650ed535024a88dbeaff1e1Romain Guy
116446926698996d3857a650ed535024a88dbeaff1e1Romain Guy        return mStyle == typeface.mStyle && native_instance == typeface.native_instance;
116546926698996d3857a650ed535024a88dbeaff1e1Romain Guy    }
116646926698996d3857a650ed535024a88dbeaff1e1Romain Guy
116746926698996d3857a650ed535024a88dbeaff1e1Romain Guy    @Override
116846926698996d3857a650ed535024a88dbeaff1e1Romain Guy    public int hashCode() {
116936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        /*
117036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat         * Modified method for hashCode with long native_instance derived from
117136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat         * http://developer.android.com/reference/java/lang/Object.html
117236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat         */
117336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        int result = 17;
117436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat        result = 31 * result + (int) (native_instance ^ (native_instance >>> 32));
117546926698996d3857a650ed535024a88dbeaff1e1Romain Guy        result = 31 * result + mStyle;
117646926698996d3857a650ed535024a88dbeaff1e1Romain Guy        return result;
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11790763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka    /** @hide */
11800763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka    public boolean isSupportedAxes(int axis) {
11810763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka        if (mSupportedAxes == null) {
11820763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka            synchronized (this) {
11830763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka                if (mSupportedAxes == null) {
11840763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka                    mSupportedAxes = nativeGetSupportedAxes(native_instance);
11850763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka                    if (mSupportedAxes == null) {
11860763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka                        mSupportedAxes = EMPTY_AXES;
11870763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka                    }
11880763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka                }
11890763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka            }
11900763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka        }
1191ffae6c7f71e9da9f887002994d270b9dbf6d0673Seigo Nonaka        return Arrays.binarySearch(mSupportedAxes, axis) >= 0;
11920763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka    }
11930763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka
119436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat    private static native long nativeCreateFromTypeface(long native_instance, int style);
11955b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka    private static native long nativeCreateFromTypefaceWithExactStyle(
11965b6347a6af668ba47b3fab14cefbe03cc440c3a4Seigo Nonaka            long native_instance, int weight, boolean italic);
1197ff55115121a7a2753ba2265cb3201a3a14c0874dSeigo Nonaka    // TODO: clean up: change List<FontVariationAxis> to FontVariationAxis[]
11989ff994d98846d24bc488939af6e7dc440149a4bcSeigo Nonaka    private static native long nativeCreateFromTypefaceWithVariation(
1199ff55115121a7a2753ba2265cb3201a3a14c0874dSeigo Nonaka            long native_instance, List<FontVariationAxis> axes);
1200117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien    private static native long nativeCreateWeightAlias(long native_instance, int weight);
1201d154829cb15d61f1469f939d608e691256e2a765Seigo Nonaka    private static native long nativeCreateFromArray(long[] familyArray, int weight, int italic);
12020763650a13dd1968f45e8e64950a32c6b508ce28Seigo Nonaka    private static native int[] nativeGetSupportedAxes(long native_instance);
1203abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka
1204abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka    @CriticalNative
1205abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka    private static native void nativeSetDefault(long nativePtr);
1206abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka
1207abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka    @CriticalNative
1208abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka    private static native int  nativeGetStyle(long nativePtr);
1209abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka
1210abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka    @CriticalNative
1211abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka    private static native int  nativeGetWeight(long nativePtr);
1212abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka
1213abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka    @CriticalNative
1214abe50314163dcc8faf05cf21d649899146bbdbdcSeigo Nonaka    private static native long nativeGetReleaseFunc();
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1216