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