diff options
| author | 2014-08-25 13:47:16 -0700 | |
|---|---|---|
| committer | 2014-08-26 19:37:45 -0700 | |
| commit | 117cbebe810613d4a6de034f02652cdbbfef4cde (patch) | |
| tree | 163e0944d265b23001c9644c570a04f47ae3b030 /graphics/java/android | |
| parent | 0db4f35e0bbc25ee25ebe2d57174893217248597 (diff) | |
New weight-aware font config
Parse new fonts.xml config file, and resolve weight selection based on
the base weight of the font (as defined by a weight alias specified in
the config file) and the requested bold flag. This change improves the
appearance of bold spans for alternate weights of Roboto.
In addition, this patch enables weight selection for fallback fonts.
For example, if an additional font with a weight of 100 is added to the
Hebrew font family in the fallback list, then requesting
"sans-serif-thin" would select that font for Hebrew text.
Bug: 14538154
Change-Id: I99a04fad4f7bf01c75726e760d42735dd9003496
Diffstat (limited to 'graphics/java/android')
| -rw-r--r-- | graphics/java/android/graphics/FontFamily.java | 8 | ||||
| -rw-r--r-- | graphics/java/android/graphics/FontListParser.java | 107 | ||||
| -rw-r--r-- | graphics/java/android/graphics/Typeface.java | 64 |
3 files changed, 107 insertions, 72 deletions
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java index 11d3165fdc29..b8b7e76e3b20 100644 --- a/graphics/java/android/graphics/FontFamily.java +++ b/graphics/java/android/graphics/FontFamily.java @@ -18,8 +18,6 @@ package android.graphics; import android.content.res.AssetManager; -import java.io.File; - /** * A family of typefaces with different styles. * @@ -64,6 +62,10 @@ public class FontFamily { return nAddFont(mNativePtr, path); } + public boolean addFontWeightStyle(String path, int weight, boolean style) { + return nAddFontWeightStyle(mNativePtr, path, weight, style); + } + public boolean addFontFromAsset(AssetManager mgr, String path) { return nAddFontFromAsset(mNativePtr, mgr, path); } @@ -71,6 +73,8 @@ public class FontFamily { private static native long nCreateFamily(String lang, int variant); private static native void nUnrefFamily(long nativePtr); private static native boolean nAddFont(long nativeFamily, String path); + private static native boolean nAddFontWeightStyle(long nativeFamily, String path, + int weight, boolean isItalic); private static native boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr, String path); } diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java index a863a06121fc..97081f9c77fd 100644 --- a/graphics/java/android/graphics/FontListParser.java +++ b/graphics/java/android/graphics/FontListParser.java @@ -33,23 +33,48 @@ import java.util.List; */ public class FontListParser { + public static class Config { + Config() { + families = new ArrayList<Family>(); + aliases = new ArrayList<Alias>(); + } + public List<Family> families; + public List<Alias> aliases; + } + + public static class Font { + Font(String fontName, int weight, boolean isItalic) { + this.fontName = fontName; + this.weight = weight; + this.isItalic = isItalic; + } + public String fontName; + public int weight; + public boolean isItalic; + } + + public static class Alias { + public String name; + public String toName; + public int weight; + } + public static class Family { - public Family(List<String> names, List<String> fontFiles, String lang, String variant) { - this.names = names; - this.fontFiles = fontFiles; + public Family(String name, List<Font> fonts, String lang, String variant) { + this.name = name; + this.fonts = fonts; this.lang = lang; this.variant = variant; } - public List<String> names; - // todo: need attributes for font files - public List<String> fontFiles; + public String name; + public List<Font> fonts; public String lang; public String variant; } /* Parse fallback list (no names) */ - public static List<Family> parse(InputStream in) throws XmlPullParserException, IOException { + public static Config parse(InputStream in) throws XmlPullParserException, IOException { try { XmlPullParser parser = Xml.newPullParser(); parser.setInput(in, null); @@ -60,57 +85,59 @@ public class FontListParser { } } - private static List<Family> readFamilies(XmlPullParser parser) + private static Config readFamilies(XmlPullParser parser) throws XmlPullParserException, IOException { - List<Family> families = new ArrayList<Family>(); + Config config = new Config(); parser.require(XmlPullParser.START_TAG, null, "familyset"); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) continue; if (parser.getName().equals("family")) { - families.add(readFamily(parser)); + config.families.add(readFamily(parser)); + } else if (parser.getName().equals("alias")) { + config.aliases.add(readAlias(parser)); } else { skip(parser); } } - return families; + return config; } private static Family readFamily(XmlPullParser parser) throws XmlPullParserException, IOException { - List<String> names = null; - List<String> fontFiles = new ArrayList<String>(); - String lang = null; - String variant = null; + String name = parser.getAttributeValue(null, "name"); + String lang = parser.getAttributeValue(null, "lang"); + String variant = parser.getAttributeValue(null, "variant"); + List<Font> fonts = new ArrayList<Font>(); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) continue; String tag = parser.getName(); - if (tag.equals("fileset")) { - while (parser.next() != XmlPullParser.END_TAG) { - if (parser.getEventType() != XmlPullParser.START_TAG) continue; - if (parser.getName().equals("file")) { - if (lang == null) { - lang = parser.getAttributeValue(null, "lang"); - } - if (variant == null) { - variant = parser.getAttributeValue(null, "variant"); - } - String filename = parser.nextText(); - String fullFilename = "/system/fonts/" + filename; - fontFiles.add(fullFilename); - } - } - } else if (tag.equals("nameset")) { - names = new ArrayList<String>(); - while (parser.next() != XmlPullParser.END_TAG) { - if (parser.getEventType() != XmlPullParser.START_TAG) continue; - if (parser.getName().equals("name")) { - String name = parser.nextText(); - names.add(name); - } - } + if (tag.equals("font")) { + String weightStr = parser.getAttributeValue(null, "weight"); + int weight = weightStr == null ? 400 : Integer.parseInt(weightStr); + boolean isItalic = "italic".equals(parser.getAttributeValue(null, "style")); + String filename = parser.nextText(); + String fullFilename = "/system/fonts/" + filename; + fonts.add(new Font(fullFilename, weight, isItalic)); + } else { + skip(parser); } } - return new Family(names, fontFiles, lang, variant); + return new Family(name, fonts, lang, variant); + } + + private static Alias readAlias(XmlPullParser parser) + throws XmlPullParserException, IOException { + Alias alias = new Alias(); + alias.name = parser.getAttributeValue(null, "name"); + alias.toName = parser.getAttributeValue(null, "to"); + String weightStr = parser.getAttributeValue(null, "weight"); + if (weightStr == null) { + alias.weight = 400; + } else { + alias.weight = Integer.parseInt(weightStr); + } + skip(parser); // alias tag is empty, ignore any contents and consume end tag + return alias; } private static void skip(XmlPullParser parser) throws XmlPullParserException, IOException { diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index 568d3f2aad4e..db42314447ff 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -66,8 +66,7 @@ public class Typeface { static Map<String, Typeface> sSystemFontMap; static FontFamily[] sFallbackFonts; - static final String SYSTEM_FONTS_CONFIG = "system_fonts.xml"; - static final String FALLBACK_FONTS_CONFIG = "fallback_fonts.xml"; + static final String FONTS_CONFIG = "fonts.xml"; /** * @hide @@ -261,10 +260,9 @@ public class Typeface { } private static FontFamily makeFamilyFromParsed(FontListParser.Family family) { - // TODO: expand to handle attributes like lang and variant FontFamily fontFamily = new FontFamily(family.lang, family.variant); - for (String fontFile : family.fontFiles) { - fontFamily.addFont(fontFile); + for (FontListParser.Font font : family.fonts) { + fontFamily.addFontWeightStyle(font.fontName, font.weight, font.isItalic); } return fontFamily; } @@ -277,48 +275,53 @@ public class Typeface { private static void init() { // Load font config and initialize Minikin state File systemFontConfigLocation = getSystemFontConfigLocation(); - File systemConfigFilename = new File(systemFontConfigLocation, SYSTEM_FONTS_CONFIG); - File configFilename = new File(systemFontConfigLocation, FALLBACK_FONTS_CONFIG); + File configFilename = new File(systemFontConfigLocation, FONTS_CONFIG); try { - // TODO: throws an exception non-Minikin builds, to fail early; - // remove when Minikin-only - new FontFamily(); + FileInputStream fontsIn = new FileInputStream(configFilename); + FontListParser.Config fontConfig = FontListParser.parse(fontsIn); - FileInputStream systemIn = new FileInputStream(systemConfigFilename); - List<FontListParser.Family> systemFontConfig = FontListParser.parse(systemIn); - - FileInputStream fallbackIn = new FileInputStream(configFilename); List<FontFamily> familyList = new ArrayList<FontFamily>(); // Note that the default typeface is always present in the fallback list; // this is an enhancement from pre-Minikin behavior. - familyList.add(makeFamilyFromParsed(systemFontConfig.get(0))); - for (Family f : FontListParser.parse(fallbackIn)) { - familyList.add(makeFamilyFromParsed(f)); + for (int i = 0; i < fontConfig.families.size(); i++) { + Family f = fontConfig.families.get(i); + if (i == 0 || f.name == null) { + familyList.add(makeFamilyFromParsed(f)); + } } sFallbackFonts = familyList.toArray(new FontFamily[familyList.size()]); setDefault(Typeface.createFromFamilies(sFallbackFonts)); Map<String, Typeface> systemFonts = new HashMap<String, Typeface>(); - for (int i = 0; i < systemFontConfig.size(); i++) { + for (int i = 0; i < fontConfig.families.size(); i++) { Typeface typeface; - Family f = systemFontConfig.get(i); - if (i == 0) { - // The first entry is the default typeface; no sense in duplicating - // the corresponding FontFamily. - typeface = sDefaultTypeface; - } else { - FontFamily fontFamily = makeFamilyFromParsed(f); - FontFamily[] families = { fontFamily }; - typeface = Typeface.createFromFamiliesWithDefault(families); + Family f = fontConfig.families.get(i); + if (f.name != null) { + if (i == 0) { + // The first entry is the default typeface; no sense in + // duplicating the corresponding FontFamily. + typeface = sDefaultTypeface; + } else { + FontFamily fontFamily = makeFamilyFromParsed(f); + FontFamily[] families = { fontFamily }; + typeface = Typeface.createFromFamiliesWithDefault(families); + } + systemFonts.put(f.name, typeface); } - for (String name : f.names) { - systemFonts.put(name, typeface); + } + for (FontListParser.Alias alias : fontConfig.aliases) { + Typeface base = systemFonts.get(alias.toName); + Typeface newFace = base; + int weight = alias.weight; + if (weight != 400) { + newFace = new Typeface(nativeCreateWeightAlias(base.native_instance, weight)); } + systemFonts.put(alias.name, newFace); } sSystemFontMap = systemFonts; } catch (RuntimeException e) { - Log.w(TAG, "Didn't create default family (most likely, non-Minikin build)"); + 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); @@ -383,6 +386,7 @@ public class Typeface { } private static native long nativeCreateFromTypeface(long native_instance, int style); + private static native long nativeCreateWeightAlias(long native_instance, int weight); private static native void nativeUnref(long native_instance); private static native int nativeGetStyle(long native_instance); private static native long nativeCreateFromArray(long[] familyArray); |