Typeface.java revision a87b07d7fafd59ae26073a80cd742b17ea427ecd
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.graphics; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.AssetManager; 201a73f732f91e97c9c66b808c245ddda36a10e987Raph Levienimport android.util.Log; 2136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhatimport android.util.LongSparseArray; 229a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport android.util.SparseArray; 239a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 249a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport org.xmlpull.v1.XmlPullParserException; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guyimport java.io.File; 279a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.io.FileInputStream; 289a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.io.FileNotFoundException; 299a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.io.IOException; 309a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.util.ArrayList; 319a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.util.HashMap; 329a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.util.List; 339a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levienimport java.util.Map; 34a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The Typeface class specifies the typeface and intrinsic style of a font. 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is used in the paint, along with optionally Paint settings like 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * textSize, textSkewX, textScaleX to specify 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * how text appears when drawn (and measured). 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Typeface { 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 439a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien private static String TAG = "Typeface"; 449a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The default NORMAL typeface object */ 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final Typeface DEFAULT; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The default BOLD typeface object. Note: this may be not actually be 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * bold, depending on what fonts are installed. Call getStyle() to know 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for sure. 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final Typeface DEFAULT_BOLD; 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The NORMAL style of the default sans serif typeface. */ 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final Typeface SANS_SERIF; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The NORMAL style of the default serif typeface. */ 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final Typeface SERIF; 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The NORMAL style of the default monospace typeface. */ 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final Typeface MONOSPACE; 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6046926698996d3857a650ed535024a88dbeaff1e1Romain Guy static Typeface[] sDefaults; 6136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat private static final LongSparseArray<SparseArray<Typeface>> sTypefaceCache = 6236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat new LongSparseArray<SparseArray<Typeface>>(3); 6346926698996d3857a650ed535024a88dbeaff1e1Romain Guy 649a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien static Typeface sDefaultTypeface; 659a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien static Map<String, Typeface> sSystemFontMap; 66363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien static FontFamily[] sFallbackFonts; 679a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 68117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien static final String FONTS_CONFIG = "fonts.xml"; 69baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta 70a033630e805c407080221e20b236b6054f324670Raph Levien /** 71a033630e805c407080221e20b236b6054f324670Raph Levien * @hide 72a033630e805c407080221e20b236b6054f324670Raph Levien */ 7336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat public long native_instance; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Style 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int NORMAL = 0; 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int BOLD = 1; 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int ITALIC = 2; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int BOLD_ITALIC = 3; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8146926698996d3857a650ed535024a88dbeaff1e1Romain Guy private int mStyle = 0; 8246926698996d3857a650ed535024a88dbeaff1e1Romain Guy 839a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien private static void setDefault(Typeface t) { 849a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien sDefaultTypeface = t; 859a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien nativeSetDefault(t.native_instance); 869a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 879a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Returns the typeface's intrinsic style attributes */ 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getStyle() { 9046926698996d3857a650ed535024a88dbeaff1e1Romain Guy return mStyle; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Returns true if getStyle() has the BOLD bit set. */ 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final boolean isBold() { 9546926698996d3857a650ed535024a88dbeaff1e1Romain Guy return (mStyle & BOLD) != 0; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Returns true if getStyle() has the ITALIC bit set. */ 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public final boolean isItalic() { 10046926698996d3857a650ed535024a88dbeaff1e1Romain Guy return (mStyle & ITALIC) != 0; 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a typeface object given a family name, and option style information. 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If null is passed for the name, then the "default" font will be chosen. 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The resulting typeface object can be queried (getStyle()) to discover what 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * its "real" style characteristics are. 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param familyName May be null. The name of the font family. 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param style The style (normal, bold, italic) of the typeface. 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The best matching typeface. 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static Typeface create(String familyName, int style) { 1159a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien if (sSystemFontMap != null) { 1169a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien return create(sSystemFontMap.get(familyName), style); 1179a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 1183660789f06c5fbcb81e6c7c79612048bff8f0f66Raph Levien return null; 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a typeface object that best matches the specified existing 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * typeface and the specified Style. Use this call if you want to pick a new 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * style from the same family of an existing typeface object. If family is 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * null, this selects from the default font's family. 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param family May be null. The name of the existing type face. 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param style The style (normal, bold, italic) of the typeface. 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * e.g. NORMAL, BOLD, ITALIC, BOLD_ITALIC 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The best matching typeface. 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static Typeface create(Typeface family, int style) { 133ff86bcd08827d1050a8cfd99b521c21848b3f364Raph Levien if (style < 0 || style > 3) { 134ff86bcd08827d1050a8cfd99b521c21848b3f364Raph Levien style = 0; 135ff86bcd08827d1050a8cfd99b521c21848b3f364Raph Levien } 13636bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat long ni = 0; 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (family != null) { 13846926698996d3857a650ed535024a88dbeaff1e1Romain Guy // Return early if we're asked for the same face/style 13946926698996d3857a650ed535024a88dbeaff1e1Romain Guy if (family.mStyle == style) { 14046926698996d3857a650ed535024a88dbeaff1e1Romain Guy return family; 14146926698996d3857a650ed535024a88dbeaff1e1Romain Guy } 14246926698996d3857a650ed535024a88dbeaff1e1Romain Guy 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ni = family.native_instance; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 14546926698996d3857a650ed535024a88dbeaff1e1Romain Guy 14646926698996d3857a650ed535024a88dbeaff1e1Romain Guy Typeface typeface; 14746926698996d3857a650ed535024a88dbeaff1e1Romain Guy SparseArray<Typeface> styles = sTypefaceCache.get(ni); 14846926698996d3857a650ed535024a88dbeaff1e1Romain Guy 14946926698996d3857a650ed535024a88dbeaff1e1Romain Guy if (styles != null) { 15046926698996d3857a650ed535024a88dbeaff1e1Romain Guy typeface = styles.get(style); 15146926698996d3857a650ed535024a88dbeaff1e1Romain Guy if (typeface != null) { 15246926698996d3857a650ed535024a88dbeaff1e1Romain Guy return typeface; 15346926698996d3857a650ed535024a88dbeaff1e1Romain Guy } 15446926698996d3857a650ed535024a88dbeaff1e1Romain Guy } 15546926698996d3857a650ed535024a88dbeaff1e1Romain Guy 15646926698996d3857a650ed535024a88dbeaff1e1Romain Guy typeface = new Typeface(nativeCreateFromTypeface(ni, style)); 15746926698996d3857a650ed535024a88dbeaff1e1Romain Guy if (styles == null) { 15846926698996d3857a650ed535024a88dbeaff1e1Romain Guy styles = new SparseArray<Typeface>(4); 15946926698996d3857a650ed535024a88dbeaff1e1Romain Guy sTypefaceCache.put(ni, styles); 16046926698996d3857a650ed535024a88dbeaff1e1Romain Guy } 16146926698996d3857a650ed535024a88dbeaff1e1Romain Guy styles.put(style, typeface); 16246926698996d3857a650ed535024a88dbeaff1e1Romain Guy 16346926698996d3857a650ed535024a88dbeaff1e1Romain Guy return typeface; 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns one of the default typeface objects, based on the specified style 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return the default typeface that corresponds to the style 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static Typeface defaultFromStyle(int style) { 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return sDefaults[style]; 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1749a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Create a new typeface from the specified font data. 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param mgr The application's asset manager 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param path The file name of the font data in the assets directory 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The new typeface. 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static Typeface createFromAsset(AssetManager mgr, String path) { 182d573794d83a049fe59e289944f0cd77406dd776aRaph Levien if (sFallbackFonts != null) { 183d573794d83a049fe59e289944f0cd77406dd776aRaph Levien FontFamily fontFamily = new FontFamily(); 184d573794d83a049fe59e289944f0cd77406dd776aRaph Levien if (fontFamily.addFontFromAsset(mgr, path)) { 185d573794d83a049fe59e289944f0cd77406dd776aRaph Levien FontFamily[] families = { fontFamily }; 186d573794d83a049fe59e289944f0cd77406dd776aRaph Levien return createFromFamiliesWithDefault(families); 187d573794d83a049fe59e289944f0cd77406dd776aRaph Levien } 188d573794d83a049fe59e289944f0cd77406dd776aRaph Levien } 189bf8d5620f7f3be72ec217f4bcc14a417d4e1dee6Behdad Esfahbod throw new RuntimeException("Font asset not found " + path); 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 191a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy 192a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy /** 193a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy * Create a new typeface from the specified font file. 194a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy * 1959a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien * @param path The path to the font data. 196a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy * @return The new typeface. 197a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy */ 198a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy public static Typeface createFromFile(File path) { 199d573794d83a049fe59e289944f0cd77406dd776aRaph Levien return createFromFile(path.getAbsolutePath()); 200a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy } 201a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy 202a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy /** 203a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy * Create a new typeface from the specified font file. 204a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy * 2059a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien * @param path The full path to the font data. 206a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy * @return The new typeface. 207a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy */ 208a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy public static Typeface createFromFile(String path) { 209d573794d83a049fe59e289944f0cd77406dd776aRaph Levien if (sFallbackFonts != null) { 210d573794d83a049fe59e289944f0cd77406dd776aRaph Levien FontFamily fontFamily = new FontFamily(); 2113fa667e22401bf3ba96957fe31167bf05d164c55Seigo Nonaka if (fontFamily.addFont(path, 0 /* ttcIndex */)) { 212d573794d83a049fe59e289944f0cd77406dd776aRaph Levien FontFamily[] families = { fontFamily }; 213d573794d83a049fe59e289944f0cd77406dd776aRaph Levien return createFromFamiliesWithDefault(families); 214d573794d83a049fe59e289944f0cd77406dd776aRaph Levien } 215d573794d83a049fe59e289944f0cd77406dd776aRaph Levien } 216bf8d5620f7f3be72ec217f4bcc14a417d4e1dee6Behdad Esfahbod throw new RuntimeException("Font not found " + path); 217a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy } 218a87a132ebf1c2dd733cf52feff6e44525257c961Romain Guy 2191a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien /** 2201a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * Create a new typeface from an array of font families. 2211a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * 2221a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * @param families array of font families 2231a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien * @hide 2241a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien */ 2251a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien public static Typeface createFromFamilies(FontFamily[] families) { 2261a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien long[] ptrArray = new long[families.length]; 2271a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien for (int i = 0; i < families.length; i++) { 2281a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien ptrArray[i] = families[i].mNativePtr; 2291a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien } 2301a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien return new Typeface(nativeCreateFromArray(ptrArray)); 2311a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien } 2321a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien 233363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien /** 234363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien * Create a new typeface from an array of font families, including 235363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien * also the font families in the fallback list. 236363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien * 237363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien * @param families array of font families 238363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien * @hide 239363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien */ 240363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien public static Typeface createFromFamiliesWithDefault(FontFamily[] families) { 241363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien long[] ptrArray = new long[families.length + sFallbackFonts.length]; 242363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien for (int i = 0; i < families.length; i++) { 243363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien ptrArray[i] = families[i].mNativePtr; 244363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien } 245363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien for (int i = 0; i < sFallbackFonts.length; i++) { 246363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien ptrArray[i + families.length] = sFallbackFonts[i].mNativePtr; 247363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien } 248363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien return new Typeface(nativeCreateFromArray(ptrArray)); 249363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien } 250363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // don't allow clients to call this directly 25236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat private Typeface(long ni) { 25346926698996d3857a650ed535024a88dbeaff1e1Romain Guy if (ni == 0) { 25431a69fdbe1edd8d686043e8ca7d278289f65808eMike Reed throw new RuntimeException("native typeface cannot be made"); 25531a69fdbe1edd8d686043e8ca7d278289f65808eMike Reed } 25646926698996d3857a650ed535024a88dbeaff1e1Romain Guy 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project native_instance = ni; 25846926698996d3857a650ed535024a88dbeaff1e1Romain Guy mStyle = nativeGetStyle(ni); 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2609a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 2619a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien private static FontFamily makeFamilyFromParsed(FontListParser.Family family) { 262f9e3d311275c37fe5f2562993687a1627780a6d0Raph Levien FontFamily fontFamily = new FontFamily(family.lang, family.variant); 263117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien for (FontListParser.Font font : family.fonts) { 264a87b07d7fafd59ae26073a80cd742b17ea427ecdBen Wagner fontFamily.addFontWeightStyle(font.fontName, font.ttcIndex, font.axes, 265a87b07d7fafd59ae26073a80cd742b17ea427ecdBen Wagner font.weight, font.isItalic); 2669a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 2679a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien return fontFamily; 2689a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 2699a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 270baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta /* 271baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta * (non-Javadoc) 272baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta * 273baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta * This should only be called once, from the static class initializer block. 274baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta */ 275baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta private static void init() { 2769a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien // Load font config and initialize Minikin state 277baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta File systemFontConfigLocation = getSystemFontConfigLocation(); 278117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien File configFilename = new File(systemFontConfigLocation, FONTS_CONFIG); 2799a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien try { 280117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien FileInputStream fontsIn = new FileInputStream(configFilename); 281117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien FontListParser.Config fontConfig = FontListParser.parse(fontsIn); 2829a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 283363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien List<FontFamily> familyList = new ArrayList<FontFamily>(); 284363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien // Note that the default typeface is always present in the fallback list; 285363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien // this is an enhancement from pre-Minikin behavior. 286117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien for (int i = 0; i < fontConfig.families.size(); i++) { 287a87b07d7fafd59ae26073a80cd742b17ea427ecdBen Wagner FontListParser.Family f = fontConfig.families.get(i); 288117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien if (i == 0 || f.name == null) { 289117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien familyList.add(makeFamilyFromParsed(f)); 290117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien } 291363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien } 292363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien sFallbackFonts = familyList.toArray(new FontFamily[familyList.size()]); 293363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien setDefault(Typeface.createFromFamilies(sFallbackFonts)); 294363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien 2959a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien Map<String, Typeface> systemFonts = new HashMap<String, Typeface>(); 296117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien for (int i = 0; i < fontConfig.families.size(); i++) { 297363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien Typeface typeface; 298a87b07d7fafd59ae26073a80cd742b17ea427ecdBen Wagner FontListParser.Family f = fontConfig.families.get(i); 299117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien if (f.name != null) { 300117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien if (i == 0) { 301117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien // The first entry is the default typeface; no sense in 302117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien // duplicating the corresponding FontFamily. 303117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien typeface = sDefaultTypeface; 304117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien } else { 305117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien FontFamily fontFamily = makeFamilyFromParsed(f); 306117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien FontFamily[] families = { fontFamily }; 307117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien typeface = Typeface.createFromFamiliesWithDefault(families); 308117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien } 309117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien systemFonts.put(f.name, typeface); 310363e21b4518d7059638df2821b8a0947f74eaf2cRaph Levien } 311117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien } 312117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien for (FontListParser.Alias alias : fontConfig.aliases) { 313117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien Typeface base = systemFonts.get(alias.toName); 314117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien Typeface newFace = base; 315117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien int weight = alias.weight; 316117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien if (weight != 400) { 317117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien newFace = new Typeface(nativeCreateWeightAlias(base.native_instance, weight)); 3189a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 319117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien systemFonts.put(alias.name, newFace); 3209a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 3219a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien sSystemFontMap = systemFonts; 3229a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 3239a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } catch (RuntimeException e) { 324117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien Log.w(TAG, "Didn't create default family (most likely, non-Minikin build)", e); 3259a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien // TODO: normal in non-Minikin case, remove or make error when Minikin-only 3269a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } catch (FileNotFoundException e) { 327a87b07d7fafd59ae26073a80cd742b17ea427ecdBen Wagner Log.e(TAG, "Error opening " + configFilename, e); 3289a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } catch (IOException e) { 329a87b07d7fafd59ae26073a80cd742b17ea427ecdBen Wagner Log.e(TAG, "Error reading " + configFilename, e); 3309a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } catch (XmlPullParserException e) { 331a87b07d7fafd59ae26073a80cd742b17ea427ecdBen Wagner Log.e(TAG, "XML parse exception for " + configFilename, e); 3329a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien } 333baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta } 3349a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 335baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta static { 336baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta init(); 3379a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien // Set up defaults and typefaces exposed in public API 33846926698996d3857a650ed535024a88dbeaff1e1Romain Guy DEFAULT = create((String) null, 0); 33946926698996d3857a650ed535024a88dbeaff1e1Romain Guy DEFAULT_BOLD = create((String) null, Typeface.BOLD); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SANS_SERIF = create("sans-serif", 0); 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SERIF = create("serif", 0); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MONOSPACE = create("monospace", 0); 3439a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sDefaults = new Typeface[] { 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DEFAULT, 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DEFAULT_BOLD, 34746926698996d3857a650ed535024a88dbeaff1e1Romain Guy create((String) null, Typeface.ITALIC), 34846926698996d3857a650ed535024a88dbeaff1e1Romain Guy create((String) null, Typeface.BOLD_ITALIC), 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 350baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta 351baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta } 352baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta 353baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta private static File getSystemFontConfigLocation() { 354baef8c1ffe5c900fb0da9512654bf249b5fc9269Deepanshu Gupta return new File("/system/etc/"); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3579a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien @Override 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void finalize() throws Throwable { 35946926698996d3857a650ed535024a88dbeaff1e1Romain Guy try { 36046926698996d3857a650ed535024a88dbeaff1e1Romain Guy nativeUnref(native_instance); 361ffa84e008c712ceffa09d6b89a49882c88b3cca5Hans Boehm native_instance = 0; // Other finalizers can still call us. 36246926698996d3857a650ed535024a88dbeaff1e1Romain Guy } finally { 36346926698996d3857a650ed535024a88dbeaff1e1Romain Guy super.finalize(); 36446926698996d3857a650ed535024a88dbeaff1e1Romain Guy } 36546926698996d3857a650ed535024a88dbeaff1e1Romain Guy } 36646926698996d3857a650ed535024a88dbeaff1e1Romain Guy 36746926698996d3857a650ed535024a88dbeaff1e1Romain Guy @Override 36846926698996d3857a650ed535024a88dbeaff1e1Romain Guy public boolean equals(Object o) { 36946926698996d3857a650ed535024a88dbeaff1e1Romain Guy if (this == o) return true; 37046926698996d3857a650ed535024a88dbeaff1e1Romain Guy if (o == null || getClass() != o.getClass()) return false; 37146926698996d3857a650ed535024a88dbeaff1e1Romain Guy 37246926698996d3857a650ed535024a88dbeaff1e1Romain Guy Typeface typeface = (Typeface) o; 37346926698996d3857a650ed535024a88dbeaff1e1Romain Guy 37446926698996d3857a650ed535024a88dbeaff1e1Romain Guy return mStyle == typeface.mStyle && native_instance == typeface.native_instance; 37546926698996d3857a650ed535024a88dbeaff1e1Romain Guy } 37646926698996d3857a650ed535024a88dbeaff1e1Romain Guy 37746926698996d3857a650ed535024a88dbeaff1e1Romain Guy @Override 37846926698996d3857a650ed535024a88dbeaff1e1Romain Guy public int hashCode() { 37936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat /* 38036bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat * Modified method for hashCode with long native_instance derived from 38136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat * http://developer.android.com/reference/java/lang/Object.html 38236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat */ 38336bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat int result = 17; 38436bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat result = 31 * result + (int) (native_instance ^ (native_instance >>> 32)); 38546926698996d3857a650ed535024a88dbeaff1e1Romain Guy result = 31 * result + mStyle; 38646926698996d3857a650ed535024a88dbeaff1e1Romain Guy return result; 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 38936bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat private static native long nativeCreateFromTypeface(long native_instance, int style); 390117cbebe810613d4a6de034f02652cdbbfef4cdeRaph Levien private static native long nativeCreateWeightAlias(long native_instance, int weight); 39136bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat private static native void nativeUnref(long native_instance); 39236bef0bf30d6bae48cf3837df351075ca4fce654Ashok Bhat private static native int nativeGetStyle(long native_instance); 3931a73f732f91e97c9c66b808c245ddda36a10e987Raph Levien private static native long nativeCreateFromArray(long[] familyArray); 3949a5b61ccc83303ceeec2059f58c1977af9faa9e3Raph Levien private static native void nativeSetDefault(long native_instance); 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 396