summaryrefslogtreecommitdiffstats
path: root/graphics/java/android/graphics/Typeface.java
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/java/android/graphics/Typeface.java')
-rw-r--r--graphics/java/android/graphics/Typeface.java183
1 files changed, 168 insertions, 15 deletions
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index db42314..4e9788a 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -25,7 +25,6 @@ import android.util.SparseArray;
import org.xmlpull.v1.XmlPullParserException;
import java.io.File;
-import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
@@ -68,6 +67,8 @@ public class Typeface {
static final String FONTS_CONFIG = "fonts.xml";
+ static final String SANS_SERIF_FAMILY_NAME = "sans-serif";
+
/**
* @hide
*/
@@ -81,6 +82,13 @@ public class Typeface {
private int mStyle = 0;
+ // Typefaces that we can garbage collect when changing fonts, and so we don't break public APIs
+ private static Typeface DEFAULT_INTERNAL;
+ private static Typeface DEFAULT_BOLD_INTERNAL;
+ private static Typeface SANS_SERIF_INTERNAL;
+ private static Typeface SERIF_INTERNAL;
+ private static Typeface MONOSPACE_INTERNAL;
+
private static void setDefault(Typeface t) {
sDefaultTypeface = t;
nativeSetDefault(t.native_instance);
@@ -228,7 +236,10 @@ public class Typeface {
for (int i = 0; i < families.length; i++) {
ptrArray[i] = families[i].mNativePtr;
}
- return new Typeface(nativeCreateFromArray(ptrArray));
+
+
+ Typeface typeface = new Typeface(nativeCreateFromArray(ptrArray));
+ return typeface;
}
/**
@@ -267,18 +278,111 @@ public class Typeface {
return fontFamily;
}
+ /**
+ * Adds the family from src with the name familyName as a fallback font in dst
+ * @param src Source font config
+ * @param dst Destination font config
+ * @param familyName Name of family to add as a fallback
+ */
+ private static void addFallbackFontsForFamilyName(FontListParser.Config src,
+ FontListParser.Config dst, String familyName) {
+ for (Family srcFamily : src.families) {
+ if (familyName.equals(srcFamily.name)) {
+ // set the name to null so that it will be added as a fallback
+ srcFamily.name = null;
+ dst.families.add(srcFamily);
+ return;
+ }
+ }
+ }
+
+ /**
+ * Adds any font families in src that do not exist in dst
+ * @param src Source font config
+ * @param dst Destination font config
+ */
+ private static void addMissingFontFamilies(FontListParser.Config src,
+ FontListParser.Config dst) {
+ final int N = dst.families.size();
+ // add missing families
+ for (Family srcFamily : src.families) {
+ boolean addFamily = true;
+ for (int i = 0; i < N && addFamily; i++) {
+ final Family dstFamily = dst.families.get(i);
+ final String dstFamilyName = dstFamily.name;
+ if (dstFamilyName != null && dstFamilyName.equals(srcFamily.name)) {
+ addFamily = false;
+ break;
+ }
+ }
+ if (addFamily) {
+ dst.families.add(srcFamily);
+ }
+ }
+ }
+
+ /**
+ * Adds any aliases in src that do not exist in dst
+ * @param src Source font config
+ * @param dst Destination font config
+ */
+ private static void addMissingFontAliases(FontListParser.Config src,
+ FontListParser.Config dst) {
+ final int N = dst.aliases.size();
+ // add missing aliases
+ for (FontListParser.Alias alias : src.aliases) {
+ boolean addAlias = true;
+ for (int i = 0; i < N && addAlias; i++) {
+ final String dstAliasName = dst.aliases.get(i).name;
+ if (dstAliasName != null && dstAliasName.equals(alias.name)) {
+ addAlias = false;
+ break;
+ }
+ }
+ if (addAlias) {
+ dst.aliases.add(alias);
+ }
+ }
+ }
+
/*
* (non-Javadoc)
*
* This should only be called once, from the static class initializer block.
*/
- private static void init() {
+ private static void init(boolean forceSystemFonts) {
// Load font config and initialize Minikin state
File systemFontConfigLocation = getSystemFontConfigLocation();
- File configFilename = new File(systemFontConfigLocation, FONTS_CONFIG);
+ File themeFontConfigLocation = getThemeFontConfigLocation();
+
+ File systemConfigFile = new File(systemFontConfigLocation, FONTS_CONFIG);
+ File themeConfigFile = new File(themeFontConfigLocation, FONTS_CONFIG);
+ File configFile = null;
+ File fontDir;
+
+ if (!forceSystemFonts && themeConfigFile.exists()) {
+ configFile = themeConfigFile;
+ fontDir = getThemeFontDirLocation();
+ } else {
+ configFile = systemConfigFile;
+ fontDir = getSystemFontDirLocation();
+ }
+
try {
- FileInputStream fontsIn = new FileInputStream(configFilename);
- FontListParser.Config fontConfig = FontListParser.parse(fontsIn);
+ FontListParser.Config fontConfig = FontListParser.parse(configFile,
+ fontDir.getAbsolutePath());
+ FontListParser.Config systemFontConfig = null;
+
+ // If the fonts are coming from a theme, we will need to make sure that we include
+ // any font families from the system fonts that the theme did not include.
+ // NOTE: All the system font families without names ALWAYS get added.
+ if (configFile == themeConfigFile) {
+ systemFontConfig = FontListParser.parse(systemConfigFile,
+ getSystemFontDirLocation().getAbsolutePath());
+ addMissingFontFamilies(systemFontConfig, fontConfig);
+ addMissingFontAliases(systemFontConfig, fontConfig);
+ addFallbackFontsForFamilyName(systemFontConfig, fontConfig, SANS_SERIF_FAMILY_NAME);
+ }
List<FontFamily> familyList = new ArrayList<FontFamily>();
// Note that the default typeface is always present in the fallback list;
@@ -289,6 +393,7 @@ public class Typeface {
familyList.add(makeFamilyFromParsed(f));
}
}
+
sFallbackFonts = familyList.toArray(new FontFamily[familyList.size()]);
setDefault(Typeface.createFromFamilies(sFallbackFonts));
@@ -324,22 +429,58 @@ public class Typeface {
Log.w(TAG, "Didn't create default family (most likely, non-Minikin build)", e);
// TODO: normal in non-Minikin case, remove or make error when Minikin-only
} catch (FileNotFoundException e) {
- Log.e(TAG, "Error opening " + configFilename);
+ Log.e(TAG, "Error opening " + configFile, e);
} catch (IOException e) {
- Log.e(TAG, "Error reading " + configFilename);
+ Log.e(TAG, "Error reading " + configFile, e);
} catch (XmlPullParserException e) {
- Log.e(TAG, "XML parse exception for " + configFilename);
+ Log.e(TAG, "XML parse exception for " + configFile, e);
}
}
+ /** @hide */
+ public static void recreateDefaults() {
+ recreateDefaults(false);
+ }
+
+ /**
+ * Clears caches in java and skia.
+ * Skia will then reparse font config
+ * @hide
+ */
+ public static void recreateDefaults(boolean forceSystemFonts) {
+ sTypefaceCache.clear();
+ sSystemFontMap.clear();
+ init(forceSystemFonts);
+
+ DEFAULT_INTERNAL = create((String) null, 0);
+ DEFAULT_BOLD_INTERNAL = create((String) null, Typeface.BOLD);
+ SANS_SERIF_INTERNAL = create("sans-serif", 0);
+ SERIF_INTERNAL = create("serif", 0);
+ MONOSPACE_INTERNAL = create("monospace", 0);
+
+ DEFAULT.native_instance = DEFAULT_INTERNAL.native_instance;
+ DEFAULT_BOLD.native_instance = DEFAULT_BOLD_INTERNAL.native_instance;
+ SANS_SERIF.native_instance = SANS_SERIF_INTERNAL.native_instance;
+ SERIF.native_instance = SERIF_INTERNAL.native_instance;
+ MONOSPACE.native_instance = MONOSPACE_INTERNAL.native_instance;
+ sDefaults[2] = create((String) null, Typeface.ITALIC);
+ sDefaults[3] = create((String) null, Typeface.BOLD_ITALIC);
+ }
+
static {
- init();
+ init(false);
// Set up defaults and typefaces exposed in public API
- DEFAULT = create((String) null, 0);
- DEFAULT_BOLD = create((String) null, Typeface.BOLD);
- SANS_SERIF = create("sans-serif", 0);
- SERIF = create("serif", 0);
- MONOSPACE = create("monospace", 0);
+ DEFAULT_INTERNAL = create((String) null, 0);
+ DEFAULT_BOLD_INTERNAL = create((String) null, Typeface.BOLD);
+ SANS_SERIF_INTERNAL = create("sans-serif", 0);
+ SERIF_INTERNAL = create("serif", 0);
+ MONOSPACE_INTERNAL = create("monospace", 0);
+
+ DEFAULT = new Typeface(DEFAULT_INTERNAL.native_instance);
+ DEFAULT_BOLD = new Typeface(DEFAULT_BOLD_INTERNAL.native_instance);
+ SANS_SERIF = new Typeface(SANS_SERIF_INTERNAL.native_instance);
+ SERIF = new Typeface(SERIF_INTERNAL.native_instance);
+ MONOSPACE = new Typeface(MONOSPACE_INTERNAL.native_instance);
sDefaults = new Typeface[] {
DEFAULT,
@@ -354,6 +495,18 @@ public class Typeface {
return new File("/system/etc/");
}
+ private static File getSystemFontDirLocation() {
+ return new File("/system/fonts/");
+ }
+
+ private static File getThemeFontConfigLocation() {
+ return new File("/data/system/theme/fonts/");
+ }
+
+ private static File getThemeFontDirLocation() {
+ return new File("/data/system/theme/fonts/");
+ }
+
@Override
protected void finalize() throws Throwable {
try {