Typeface.java revision f9e3d311275c37fe5f2562993687a1627780a6d0
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.graphics; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.AssetManager; 209a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport android.graphics.FontListParser.Family; 211a73f732f91e97c9c66b808c245ddda36a10e987Raph Levienimport android.util.Log; 2236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhatimport android.util.LongSparseArray; 239a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport android.util.SparseArray; 249a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 259a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport org.xmlpull.v1.XmlPullParserException; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guyimport java.io.File; 289a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.io.FileInputStream; 299a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.io.FileNotFoundException; 309a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.io.IOException; 319a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.util.ArrayList; 329a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.util.HashMap; 339a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.util.List; 349a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.util.Map; 35a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The Typeface class specifies the typeface and intrinsic style of a font. 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is used in the paint, along with optionally Paint settings like 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * textSize, textSkewX, textScaleX to specify 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * how text appears when drawn (and measured). 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Typeface { 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 449a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien private static String TAG = "Typeface"; 459a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The default NORMAL typeface object */ 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final Typeface DEFAULT; 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The default BOLD typeface object. Note: this may be not actually be 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * bold, depending on what fonts are installed. Call getStyle() to know 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for sure. 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final Typeface DEFAULT_BOLD; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The NORMAL style of the default sans serif typeface. */ 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final Typeface SANS_SERIF; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The NORMAL style of the default serif typeface. */ 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final Typeface SERIF; 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The NORMAL style of the default monospace typeface. */ 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final Typeface MONOSPACE; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6146926698996d3857a650ed535024a88dbeaff1e1Romain Guy static Typeface[] sDefaults; 6236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat private static final LongSparseArray<SparseArray<Typeface>> sTypefaceCache = 6336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat new LongSparseArray<SparseArray<Typeface>>(3); 6446926698996d3857a650ed535024a88dbeaff1e1Romain Guy 659a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien static Typeface sDefaultTypeface; 669a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien static Map<String, Typeface> sSystemFontMap; 67363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien static FontFamily[] sFallbackFonts; 689a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 69baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta static final String SYSTEM_FONTS_CONFIG = "system_fonts.xml"; 70baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta static final String FALLBACK_FONTS_CONFIG = "fallback_fonts.xml"; 71baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta 72a033630e805c407080221e20b236b6054f324670Raph Levien /** 73a033630e805c407080221e20b236b6054f324670Raph Levien * @hide 74a033630e805c407080221e20b236b6054f324670Raph Levien */ 7536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat public long native_instance; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Style 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int NORMAL = 0; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int BOLD = 1; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int ITALIC = 2; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int BOLD_ITALIC = 3; 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8346926698996d3857a650ed535024a88dbeaff1e1Romain Guy private int mStyle = 0; 8446926698996d3857a650ed535024a88dbeaff1e1Romain Guy 859a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien private static void setDefault(Typeface t) { 869a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien sDefaultTypeface = t; 879a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien nativeSetDefault(t.native_instance); 889a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 899a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Returns the typeface's intrinsic style attributes */ 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getStyle() { 9246926698996d3857a650ed535024a88dbeaff1e1Romain Guy return mStyle; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Returns true if getStyle() has the BOLD bit set. */ 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final boolean isBold() { 9746926698996d3857a650ed535024a88dbeaff1e1Romain Guy return (mStyle & BOLD) != 0; 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Returns true if getStyle() has the ITALIC bit set. */ 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final boolean isItalic() { 10246926698996d3857a650ed535024a88dbeaff1e1Romain Guy return (mStyle & ITALIC) != 0; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a typeface object given a family name, and option style information. 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If null is passed for the name, then the "default" font will be chosen. 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The resulting typeface object can be queried (getStyle()) to discover what 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * its "real" style characteristics are. 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param familyName May be null. The name of the font family. 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param style The style (normal, bold, italic) of the typeface. 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The best matching typeface. 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static Typeface create(String familyName, int style) { 1179a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien if (sSystemFontMap != null) { 1189a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien return create(sSystemFontMap.get(familyName), style); 1199a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new Typeface(nativeCreate(familyName, style)); 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a typeface object that best matches the specified existing 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * typeface and the specified Style. Use this call if you want to pick a new 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * style from the same family of an existing typeface object. If family is 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * null, this selects from the default font's family. 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param family May be null. The name of the existing type face. 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param style The style (normal, bold, italic) of the typeface. 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The best matching typeface. 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static Typeface create(Typeface family, int style) { 13536bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat long ni = 0; 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (family != null) { 13746926698996d3857a650ed535024a88dbeaff1e1Romain Guy // Return early if we're asked for the same face/style 13846926698996d3857a650ed535024a88dbeaff1e1Romain Guy if (family.mStyle == style) { 13946926698996d3857a650ed535024a88dbeaff1e1Romain Guy return family; 14046926698996d3857a650ed535024a88dbeaff1e1Romain Guy } 14146926698996d3857a650ed535024a88dbeaff1e1Romain Guy 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ni = family.native_instance; 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14446926698996d3857a650ed535024a88dbeaff1e1Romain Guy 14546926698996d3857a650ed535024a88dbeaff1e1Romain Guy Typeface typeface; 14646926698996d3857a650ed535024a88dbeaff1e1Romain Guy SparseArray<Typeface> styles = sTypefaceCache.get(ni); 14746926698996d3857a650ed535024a88dbeaff1e1Romain Guy 14846926698996d3857a650ed535024a88dbeaff1e1Romain Guy if (styles != null) { 14946926698996d3857a650ed535024a88dbeaff1e1Romain Guy typeface = styles.get(style); 15046926698996d3857a650ed535024a88dbeaff1e1Romain Guy if (typeface != null) { 15146926698996d3857a650ed535024a88dbeaff1e1Romain Guy return typeface; 15246926698996d3857a650ed535024a88dbeaff1e1Romain Guy } 15346926698996d3857a650ed535024a88dbeaff1e1Romain Guy } 15446926698996d3857a650ed535024a88dbeaff1e1Romain Guy 15546926698996d3857a650ed535024a88dbeaff1e1Romain Guy typeface = new Typeface(nativeCreateFromTypeface(ni, style)); 15646926698996d3857a650ed535024a88dbeaff1e1Romain Guy if (styles == null) { 15746926698996d3857a650ed535024a88dbeaff1e1Romain Guy styles = new SparseArray<Typeface>(4); 15846926698996d3857a650ed535024a88dbeaff1e1Romain Guy sTypefaceCache.put(ni, styles); 15946926698996d3857a650ed535024a88dbeaff1e1Romain Guy } 16046926698996d3857a650ed535024a88dbeaff1e1Romain Guy styles.put(style, typeface); 16146926698996d3857a650ed535024a88dbeaff1e1Romain Guy 16246926698996d3857a650ed535024a88dbeaff1e1Romain Guy return typeface; 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns one of the default typeface objects, based on the specified style 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the default typeface that corresponds to the style 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static Typeface defaultFromStyle(int style) { 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sDefaults[style]; 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1739a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new typeface from the specified font data. 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param mgr The application's asset manager 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param path The file name of the font data in the assets directory 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The new typeface. 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static Typeface createFromAsset(AssetManager mgr, String path) { 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new Typeface(nativeCreateFromAsset(mgr, path)); 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 183a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy 184a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy /** 185a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy * Create a new typeface from the specified font file. 186a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy * 1879a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien * @param path The path to the font data. 188a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy * @return The new typeface. 189a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy */ 190a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy public static Typeface createFromFile(File path) { 191a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy return new Typeface(nativeCreateFromFile(path.getAbsolutePath())); 192a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy } 193a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy 194a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy /** 195a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy * Create a new typeface from the specified font file. 196a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy * 1979a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien * @param path The full path to the font data. 198a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy * @return The new typeface. 199a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy */ 200a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy public static Typeface createFromFile(String path) { 201a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy return new Typeface(nativeCreateFromFile(path)); 202a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy } 203a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy 2041a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien /** 2051a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * Create a new typeface from an array of font families. 2061a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * 2071a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * @param families array of font families 2081a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * @hide 2091a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien */ 2101a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien public static Typeface createFromFamilies(FontFamily[] families) { 2111a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien long[] ptrArray = new long[families.length]; 2121a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien for (int i = 0; i < families.length; i++) { 2131a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien ptrArray[i] = families[i].mNativePtr; 2141a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien } 2151a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien return new Typeface(nativeCreateFromArray(ptrArray)); 2161a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien } 2171a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien 218363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien /** 219363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien * Create a new typeface from an array of font families, including 220363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien * also the font families in the fallback list. 221363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien * 222363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien * @param families array of font families 223363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien * @hide 224363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien */ 225363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien public static Typeface createFromFamiliesWithDefault(FontFamily[] families) { 226363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien long[] ptrArray = new long[families.length + sFallbackFonts.length]; 227363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien for (int i = 0; i < families.length; i++) { 228363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien ptrArray[i] = families[i].mNativePtr; 229363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien } 230363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien for (int i = 0; i < sFallbackFonts.length; i++) { 231363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien ptrArray[i + families.length] = sFallbackFonts[i].mNativePtr; 232363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien } 233363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien return new Typeface(nativeCreateFromArray(ptrArray)); 234363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien } 235363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // don't allow clients to call this directly 23736bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat private Typeface(long ni) { 23846926698996d3857a650ed535024a88dbeaff1e1Romain Guy if (ni == 0) { 23931a69fdbe1edd8d686043e8ca7d278289f65808eMike Reed throw new RuntimeException("native typeface cannot be made"); 24031a69fdbe1edd8d686043e8ca7d278289f65808eMike Reed } 24146926698996d3857a650ed535024a88dbeaff1e1Romain Guy 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_instance = ni; 24346926698996d3857a650ed535024a88dbeaff1e1Romain Guy mStyle = nativeGetStyle(ni); 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2459a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 2469a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien private static FontFamily makeFamilyFromParsed(FontListParser.Family family) { 2479a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien // TODO: expand to handle attributes like lang and variant 248f9e3d311275c37fe5f2562993687a1627780a6d0Raph Levien FontFamily fontFamily = new FontFamily(family.lang, family.variant); 2499a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien for (String fontFile : family.fontFiles) { 2509a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien fontFamily.addFont(new File(fontFile)); 2519a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 2529a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien return fontFamily; 2539a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 2549a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 255baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta /* 256baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta * (non-Javadoc) 257baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta * 258baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta * This should only be called once, from the static class initializer block. 259baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta */ 260baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta private static void init() { 2619a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien // Load font config and initialize Minikin state 262baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta File systemFontConfigLocation = getSystemFontConfigLocation(); 263baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta File systemConfigFilename = new File(systemFontConfigLocation, SYSTEM_FONTS_CONFIG); 264baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta File configFilename = new File(systemFontConfigLocation, FALLBACK_FONTS_CONFIG); 2659a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien try { 2669a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien // TODO: throws an exception non-Minikin builds, to fail early; 2679a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien // remove when Minikin-only 2689a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien new FontFamily(); 2699a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 2709a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien FileInputStream systemIn = new FileInputStream(systemConfigFilename); 2719a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien List<FontListParser.Family> systemFontConfig = FontListParser.parse(systemIn); 272363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien 273363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien FileInputStream fallbackIn = new FileInputStream(configFilename); 274363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien List<FontFamily> familyList = new ArrayList<FontFamily>(); 275363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien // Note that the default typeface is always present in the fallback list; 276363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien // this is an enhancement from pre-Minikin behavior. 277363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien familyList.add(makeFamilyFromParsed(systemFontConfig.get(0))); 278363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien for (Family f : FontListParser.parse(fallbackIn)) { 279363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien familyList.add(makeFamilyFromParsed(f)); 280363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien } 281363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien sFallbackFonts = familyList.toArray(new FontFamily[familyList.size()]); 282363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien setDefault(Typeface.createFromFamilies(sFallbackFonts)); 283363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien 2849a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien Map<String, Typeface> systemFonts = new HashMap<String, Typeface>(); 285363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien for (int i = 0; i < systemFontConfig.size(); i++) { 286363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien Typeface typeface; 287363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien Family f = systemFontConfig.get(i); 288363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien if (i == 0) { 289363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien // The first entry is the default typeface; no sense in duplicating 290363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien // the corresponding FontFamily. 291363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien typeface = sDefaultTypeface; 292363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien } else { 293363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien FontFamily fontFamily = makeFamilyFromParsed(f); 294363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien FontFamily[] families = { fontFamily }; 295363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien typeface = Typeface.createFromFamiliesWithDefault(families); 296363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien } 2979a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien for (String name : f.names) { 2989a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien systemFonts.put(name, typeface); 2999a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 3009a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 3019a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien sSystemFontMap = systemFonts; 3029a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 3039a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } catch (RuntimeException e) { 3049a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien Log.w(TAG, "Didn't create default family (most likely, non-Minikin build)"); 3059a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien // TODO: normal in non-Minikin case, remove or make error when Minikin-only 3069a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } catch (FileNotFoundException e) { 3079a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien Log.e(TAG, "Error opening " + configFilename); 3089a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } catch (IOException e) { 3099a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien Log.e(TAG, "Error reading " + configFilename); 3109a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } catch (XmlPullParserException e) { 3119a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien Log.e(TAG, "XML parse exception for " + configFilename); 3129a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 313baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta } 3149a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 315baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta static { 316baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta init(); 3179a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien // Set up defaults and typefaces exposed in public API 31846926698996d3857a650ed535024a88dbeaff1e1Romain Guy DEFAULT = create((String) null, 0); 31946926698996d3857a650ed535024a88dbeaff1e1Romain Guy DEFAULT_BOLD = create((String) null, Typeface.BOLD); 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SANS_SERIF = create("sans-serif", 0); 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SERIF = create("serif", 0); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MONOSPACE = create("monospace", 0); 3239a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sDefaults = new Typeface[] { 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DEFAULT, 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DEFAULT_BOLD, 32746926698996d3857a650ed535024a88dbeaff1e1Romain Guy create((String) null, Typeface.ITALIC), 32846926698996d3857a650ed535024a88dbeaff1e1Romain Guy create((String) null, Typeface.BOLD_ITALIC), 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 330baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta 331baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta } 332baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta 333baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta private static File getSystemFontConfigLocation() { 334baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta return new File("/system/etc/"); 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3379a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien @Override 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() throws Throwable { 33946926698996d3857a650ed535024a88dbeaff1e1Romain Guy try { 34046926698996d3857a650ed535024a88dbeaff1e1Romain Guy nativeUnref(native_instance); 34146926698996d3857a650ed535024a88dbeaff1e1Romain Guy } finally { 34246926698996d3857a650ed535024a88dbeaff1e1Romain Guy super.finalize(); 34346926698996d3857a650ed535024a88dbeaff1e1Romain Guy } 34446926698996d3857a650ed535024a88dbeaff1e1Romain Guy } 34546926698996d3857a650ed535024a88dbeaff1e1Romain Guy 34646926698996d3857a650ed535024a88dbeaff1e1Romain Guy @Override 34746926698996d3857a650ed535024a88dbeaff1e1Romain Guy public boolean equals(Object o) { 34846926698996d3857a650ed535024a88dbeaff1e1Romain Guy if (this == o) return true; 34946926698996d3857a650ed535024a88dbeaff1e1Romain Guy if (o == null || getClass() != o.getClass()) return false; 35046926698996d3857a650ed535024a88dbeaff1e1Romain Guy 35146926698996d3857a650ed535024a88dbeaff1e1Romain Guy Typeface typeface = (Typeface) o; 35246926698996d3857a650ed535024a88dbeaff1e1Romain Guy 35346926698996d3857a650ed535024a88dbeaff1e1Romain Guy return mStyle == typeface.mStyle && native_instance == typeface.native_instance; 35446926698996d3857a650ed535024a88dbeaff1e1Romain Guy } 35546926698996d3857a650ed535024a88dbeaff1e1Romain Guy 35646926698996d3857a650ed535024a88dbeaff1e1Romain Guy @Override 35746926698996d3857a650ed535024a88dbeaff1e1Romain Guy public int hashCode() { 35836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat /* 35936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat * Modified method for hashCode with long native_instance derived from 36036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat * http://developer.android.com/reference/java/lang/Object.html 36136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat */ 36236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat int result = 17; 36336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat result = 31 * result + (int) (native_instance ^ (native_instance >>> 32)); 36446926698996d3857a650ed535024a88dbeaff1e1Romain Guy result = 31 * result + mStyle; 36546926698996d3857a650ed535024a88dbeaff1e1Romain Guy return result; 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 36836bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat private static native long nativeCreate(String familyName, int style); 36936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat private static native long nativeCreateFromTypeface(long native_instance, int style); 37036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat private static native void nativeUnref(long native_instance); 37136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat private static native int nativeGetStyle(long native_instance); 37236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat private static native long nativeCreateFromAsset(AssetManager mgr, String path); 37336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat private static native long nativeCreateFromFile(String path); 3741a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien private static native long nativeCreateFromArray(long[] familyArray); 3759a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien private static native void nativeSetDefault(long native_instance); 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 377