Merge "Layoutlib now parses system_fonts.xml instead of its own."
This commit is contained in:
committed by
Android (Google) Code Review
commit
0bb83a2839
@@ -1,48 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2008 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<!--
|
||||
This is only used by the layoutlib to display
|
||||
layouts in ADT.
|
||||
-->
|
||||
<fonts>
|
||||
<font ttf="DroidSans">
|
||||
<name>sans-serif</name>
|
||||
<name>arial</name>
|
||||
<name>helvetica</name>
|
||||
<name>tahoma</name>
|
||||
<name>verdana</name>
|
||||
</font>
|
||||
<font ttf="DroidSerif">
|
||||
<name>serif</name>
|
||||
<name>times</name>
|
||||
<name>times new roman</name>
|
||||
<name>palatino</name>
|
||||
<name>georgia</name>
|
||||
<name>baskerville</name>
|
||||
<name>goudy</name>
|
||||
<name>fantasy</name>
|
||||
<name>cursive</name>
|
||||
<name>ITC Stone Serif</name>
|
||||
</font>
|
||||
<font ttf="DroidSansMono">
|
||||
<name>monospace</name>
|
||||
<name>courier</name>
|
||||
<name>courier new</name>
|
||||
<name>monaco</name>
|
||||
</font>
|
||||
<fallback ttf="DroidSansFallback" />
|
||||
<fallback ttf="MTLmr3m" />
|
||||
</fonts>
|
||||
@@ -26,7 +26,6 @@ import android.content.res.AssetManager;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -50,7 +49,6 @@ public final class Typeface_Delegate {
|
||||
|
||||
// ---- delegate helper data ----
|
||||
private static final String DEFAULT_FAMILY = "sans-serif";
|
||||
private static final int[] STYLE_BUFFER = new int[1];
|
||||
|
||||
private static FontLoader sFontLoader;
|
||||
private static final List<Typeface_Delegate> sPostInitDelegate =
|
||||
@@ -178,14 +176,6 @@ public final class Typeface_Delegate {
|
||||
}
|
||||
|
||||
private void init() {
|
||||
STYLE_BUFFER[0] = mStyle;
|
||||
Font font = sFontLoader.getFont(mFamily, STYLE_BUFFER);
|
||||
if (font != null) {
|
||||
List<Font> list = new ArrayList<Font>();
|
||||
list.add(font);
|
||||
list.addAll(sFontLoader.getFallBackFonts());
|
||||
mFonts = Collections.unmodifiableList(list);
|
||||
mStyle = STYLE_BUFFER[0];
|
||||
}
|
||||
mFonts = sFontLoader.getFont(mFamily, mStyle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,17 +23,13 @@ import org.xml.sax.helpers.DefaultHandler;
|
||||
import android.graphics.Typeface;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.FontFormatException;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
@@ -47,49 +43,53 @@ import javax.xml.parsers.SAXParserFactory;
|
||||
* fonts.xml file located alongside the ttf files.
|
||||
*/
|
||||
public final class FontLoader {
|
||||
private static final String FONTS_DEFINITIONS = "fonts.xml";
|
||||
private static final String FONTS_SYSTEM = "system_fonts.xml";
|
||||
private static final String FONTS_VENDOR = "vendor_fonts.xml";
|
||||
private static final String FONTS_FALLBACK = "fallback_fonts.xml";
|
||||
|
||||
private static final String NODE_FONTS = "fonts";
|
||||
private static final String NODE_FONT = "font";
|
||||
private static final String NODE_FAMILYSET = "familyset";
|
||||
private static final String NODE_FAMILY = "family";
|
||||
private static final String NODE_NAME = "name";
|
||||
private static final String NODE_FALLBACK = "fallback";
|
||||
private static final String NODE_FILE = "file";
|
||||
|
||||
private static final String ATTR_TTF = "ttf";
|
||||
private static final String FONT_SUFFIX_NONE = ".ttf";
|
||||
private static final String FONT_SUFFIX_REGULAR = "-Regular.ttf";
|
||||
private static final String FONT_SUFFIX_BOLD = "-Bold.ttf";
|
||||
private static final String FONT_SUFFIX_ITALIC = "-Italic.ttf";
|
||||
private static final String FONT_SUFFIX_BOLDITALIC = "-BoldItalic.ttf";
|
||||
|
||||
private static final String FONT_EXT = ".ttf";
|
||||
|
||||
private static final String[] FONT_STYLE_DEFAULT = { "", "-Regular" };
|
||||
private static final String[] FONT_STYLE_BOLD = { "-Bold" };
|
||||
private static final String[] FONT_STYLE_ITALIC = { "-Italic" };
|
||||
private static final String[] FONT_STYLE_BOLDITALIC = { "-BoldItalic" };
|
||||
|
||||
// list of font style, in the order matching the Typeface Font style
|
||||
private static final String[][] FONT_STYLES = {
|
||||
FONT_STYLE_DEFAULT,
|
||||
FONT_STYLE_BOLD,
|
||||
FONT_STYLE_ITALIC,
|
||||
FONT_STYLE_BOLDITALIC
|
||||
// This must match the values of Typeface styles so that we can use them for indices in this
|
||||
// array.
|
||||
private static final int[] AWT_STYLES = new int[] {
|
||||
Font.PLAIN,
|
||||
Font.BOLD,
|
||||
Font.ITALIC,
|
||||
Font.BOLD | Font.ITALIC
|
||||
};
|
||||
private static int[] DERIVE_BOLD_ITALIC = new int[] {
|
||||
Typeface.ITALIC, Typeface.BOLD, Typeface.NORMAL
|
||||
};
|
||||
private static int[] DERIVE_ITALIC = new int[] { Typeface.NORMAL };
|
||||
private static int[] DERIVE_BOLD = new int[] { Typeface.NORMAL };
|
||||
|
||||
private final Map<String, String> mFamilyToTtf = new HashMap<String, String>();
|
||||
private final Map<String, Map<Integer, Font>> mTtfToFontMap =
|
||||
new HashMap<String, Map<Integer, Font>>();
|
||||
|
||||
private List<Font> mFallBackFonts = null;
|
||||
private static final List<FontInfo> mMainFonts = new ArrayList<FontInfo>();
|
||||
private static final List<FontInfo> mFallbackFonts = new ArrayList<FontInfo>();
|
||||
|
||||
public static FontLoader create(String fontOsLocation) {
|
||||
try {
|
||||
SAXParserFactory parserFactory = SAXParserFactory.newInstance();
|
||||
parserFactory.setNamespaceAware(true);
|
||||
|
||||
SAXParser parser = parserFactory.newSAXParser();
|
||||
File f = new File(fontOsLocation + File.separator + FONTS_DEFINITIONS);
|
||||
// parse the system fonts
|
||||
FontHandler handler = parseFontFile(parserFactory, fontOsLocation, FONTS_SYSTEM);
|
||||
List<FontInfo> systemFonts = handler.getFontList();
|
||||
|
||||
FontDefinitionParser definitionParser = new FontDefinitionParser(
|
||||
fontOsLocation + File.separator);
|
||||
parser.parse(new FileInputStream(f), definitionParser);
|
||||
|
||||
return definitionParser.getFontLoader();
|
||||
// parse the fallback fonts
|
||||
handler = parseFontFile(parserFactory, fontOsLocation, FONTS_FALLBACK);
|
||||
List<FontInfo> fallbackFonts = handler.getFontList();
|
||||
|
||||
return new FontLoader(systemFonts, fallbackFonts);
|
||||
} catch (ParserConfigurationException e) {
|
||||
// return null below
|
||||
} catch (SAXException e) {
|
||||
@@ -103,35 +103,22 @@ public final class FontLoader {
|
||||
return null;
|
||||
}
|
||||
|
||||
private FontLoader(List<FontInfo> fontList, List<String> fallBackList) {
|
||||
for (FontInfo info : fontList) {
|
||||
for (String family : info.families) {
|
||||
mFamilyToTtf.put(family, info.ttf);
|
||||
}
|
||||
}
|
||||
private static FontHandler parseFontFile(SAXParserFactory parserFactory,
|
||||
String fontOsLocation, String fontFileName)
|
||||
throws ParserConfigurationException, SAXException, IOException, FileNotFoundException {
|
||||
|
||||
ArrayList<Font> list = new ArrayList<Font>();
|
||||
for (String path : fallBackList) {
|
||||
File f = new File(path + FONT_EXT);
|
||||
if (f.isFile()) {
|
||||
try {
|
||||
Font font = Font.createFont(Font.TRUETYPE_FONT, f);
|
||||
if (font != null) {
|
||||
list.add(font);
|
||||
}
|
||||
} catch (FontFormatException e) {
|
||||
// skip this font name
|
||||
} catch (IOException e) {
|
||||
// skip this font name
|
||||
}
|
||||
}
|
||||
}
|
||||
SAXParser parser = parserFactory.newSAXParser();
|
||||
File f = new File(fontOsLocation, fontFileName);
|
||||
|
||||
mFallBackFonts = Collections.unmodifiableList(list);
|
||||
FontHandler definitionParser = new FontHandler(
|
||||
fontOsLocation + File.separator);
|
||||
parser.parse(new FileInputStream(f), definitionParser);
|
||||
return definitionParser;
|
||||
}
|
||||
|
||||
public List<Font> getFallBackFonts() {
|
||||
return mFallBackFonts;
|
||||
private FontLoader(List<FontInfo> fontList, List<FontInfo> fallBackList) {
|
||||
mMainFonts.addAll(fontList);
|
||||
mFallbackFonts.addAll(fallBackList);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,96 +130,32 @@ public final class FontLoader {
|
||||
* the method returns.
|
||||
* @return the font object or null if no match could be found.
|
||||
*/
|
||||
public synchronized Font getFont(String family, int[] style) {
|
||||
public synchronized List<Font> getFont(String family, int style) {
|
||||
List<Font> result = new ArrayList<Font>();
|
||||
|
||||
if (family == null) {
|
||||
return null;
|
||||
return result;
|
||||
}
|
||||
|
||||
// get the ttf name from the family
|
||||
String ttf = mFamilyToTtf.get(family);
|
||||
|
||||
if (ttf == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// get the font from the ttf
|
||||
Map<Integer, Font> styleMap = mTtfToFontMap.get(ttf);
|
||||
|
||||
if (styleMap == null) {
|
||||
styleMap = new HashMap<Integer, Font>();
|
||||
mTtfToFontMap.put(ttf, styleMap);
|
||||
}
|
||||
|
||||
Font f = styleMap.get(style[0]);
|
||||
|
||||
if (f != null) {
|
||||
return f;
|
||||
}
|
||||
|
||||
// if it doesn't exist, we create it, and we can't, we try with a simpler style
|
||||
switch (style[0]) {
|
||||
case Typeface.NORMAL:
|
||||
f = getFont(ttf, FONT_STYLES[Typeface.NORMAL]);
|
||||
// get the font objects from the main list based on family.
|
||||
for (FontInfo info : mMainFonts) {
|
||||
if (info.families.contains(family)) {
|
||||
result.add(info.font[style]);
|
||||
break;
|
||||
case Typeface.BOLD:
|
||||
case Typeface.ITALIC:
|
||||
f = getFont(ttf, FONT_STYLES[style[0]]);
|
||||
if (f == null) {
|
||||
f = getFont(ttf, FONT_STYLES[Typeface.NORMAL]);
|
||||
style[0] = Typeface.NORMAL;
|
||||
}
|
||||
break;
|
||||
case Typeface.BOLD_ITALIC:
|
||||
f = getFont(ttf, FONT_STYLES[style[0]]);
|
||||
if (f == null) {
|
||||
f = getFont(ttf, FONT_STYLES[Typeface.BOLD]);
|
||||
if (f != null) {
|
||||
style[0] = Typeface.BOLD;
|
||||
} else {
|
||||
f = getFont(ttf, FONT_STYLES[Typeface.ITALIC]);
|
||||
if (f != null) {
|
||||
style[0] = Typeface.ITALIC;
|
||||
} else {
|
||||
f = getFont(ttf, FONT_STYLES[Typeface.NORMAL]);
|
||||
style[0] = Typeface.NORMAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (f != null) {
|
||||
styleMap.put(style[0], f);
|
||||
return f;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Font getFont(String ttf, String[] fontFileSuffix) {
|
||||
for (String suffix : fontFileSuffix) {
|
||||
String name = ttf + suffix + FONT_EXT;
|
||||
|
||||
File f = new File(name);
|
||||
if (f.isFile()) {
|
||||
try {
|
||||
Font font = Font.createFont(Font.TRUETYPE_FONT, f);
|
||||
if (font != null) {
|
||||
return font;
|
||||
}
|
||||
} catch (FontFormatException e) {
|
||||
// skip this font name
|
||||
} catch (IOException e) {
|
||||
// skip this font name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
// add all the fallback fonts
|
||||
for (FontInfo info : mFallbackFonts) {
|
||||
result.add(info.font[style]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private final static class FontInfo {
|
||||
String ttf;
|
||||
final Font[] font = new Font[4]; // Matches the 4 type-face styles.
|
||||
final Set<String> families;
|
||||
|
||||
FontInfo() {
|
||||
@@ -240,21 +163,20 @@ public final class FontLoader {
|
||||
}
|
||||
}
|
||||
|
||||
private final static class FontDefinitionParser extends DefaultHandler {
|
||||
private final static class FontHandler extends DefaultHandler {
|
||||
private final String mOsFontsLocation;
|
||||
|
||||
private FontInfo mFontInfo = null;
|
||||
private final StringBuilder mBuilder = new StringBuilder();
|
||||
private List<FontInfo> mFontList;
|
||||
private List<String> mFallBackList;
|
||||
private List<FontInfo> mFontList = new ArrayList<FontInfo>();
|
||||
|
||||
private FontDefinitionParser(String osFontsLocation) {
|
||||
private FontHandler(String osFontsLocation) {
|
||||
super();
|
||||
mOsFontsLocation = osFontsLocation;
|
||||
}
|
||||
|
||||
FontLoader getFontLoader() {
|
||||
return new FontLoader(mFontList, mFallBackList);
|
||||
public List<FontInfo> getFontList() {
|
||||
return mFontList;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -263,26 +185,11 @@ public final class FontLoader {
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String name, Attributes attributes)
|
||||
throws SAXException {
|
||||
if (NODE_FONTS.equals(localName)) {
|
||||
if (NODE_FAMILYSET.equals(localName)) {
|
||||
mFontList = new ArrayList<FontInfo>();
|
||||
mFallBackList = new ArrayList<String>();
|
||||
} else if (NODE_FONT.equals(localName)) {
|
||||
} else if (NODE_FAMILY.equals(localName)) {
|
||||
if (mFontList != null) {
|
||||
String ttf = attributes.getValue(ATTR_TTF);
|
||||
if (ttf != null) {
|
||||
mFontInfo = new FontInfo();
|
||||
mFontInfo.ttf = mOsFontsLocation + ttf;
|
||||
mFontList.add(mFontInfo);
|
||||
}
|
||||
}
|
||||
} else if (NODE_NAME.equals(localName)) {
|
||||
// do nothing, we'll handle the name in the endElement
|
||||
} else if (NODE_FALLBACK.equals(localName)) {
|
||||
if (mFallBackList != null) {
|
||||
String ttf = attributes.getValue(ATTR_TTF);
|
||||
if (ttf != null) {
|
||||
mFallBackList.add(mOsFontsLocation + ttf);
|
||||
}
|
||||
mFontInfo = new FontInfo();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,21 +211,80 @@ public final class FontLoader {
|
||||
*/
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String name) throws SAXException {
|
||||
if (NODE_FONTS.equals(localName)) {
|
||||
// top level, do nothing
|
||||
} else if (NODE_FONT.equals(localName)) {
|
||||
mFontInfo = null;
|
||||
if (NODE_FAMILY.equals(localName)) {
|
||||
if (mFontInfo != null) {
|
||||
// if has a normal font file, add to the list
|
||||
if (mFontInfo.font[Typeface.NORMAL] != null) {
|
||||
mFontList.add(mFontInfo);
|
||||
|
||||
// create missing font styles, order is important.
|
||||
if (mFontInfo.font[Typeface.BOLD_ITALIC] == null) {
|
||||
computeDerivedFont(Typeface.BOLD_ITALIC, DERIVE_BOLD_ITALIC);
|
||||
}
|
||||
if (mFontInfo.font[Typeface.ITALIC] == null) {
|
||||
computeDerivedFont(Typeface.ITALIC, DERIVE_ITALIC);
|
||||
}
|
||||
if (mFontInfo.font[Typeface.BOLD] == null) {
|
||||
computeDerivedFont(Typeface.BOLD, DERIVE_BOLD);
|
||||
}
|
||||
}
|
||||
|
||||
mFontInfo = null;
|
||||
}
|
||||
} else if (NODE_NAME.equals(localName)) {
|
||||
// handle a new name for an existing Font Info
|
||||
if (mFontInfo != null) {
|
||||
String family = trimXmlWhitespaces(mBuilder.toString());
|
||||
mFontInfo.families.add(family);
|
||||
}
|
||||
} else if (NODE_FALLBACK.equals(localName)) {
|
||||
// nothing to do here.
|
||||
} else if (NODE_FILE.equals(localName)) {
|
||||
// handle a new file for an existing Font Info
|
||||
if (mFontInfo != null) {
|
||||
String fileName = trimXmlWhitespaces(mBuilder.toString());
|
||||
Font font = getFont(fileName);
|
||||
if (font != null) {
|
||||
if (fileName.endsWith(FONT_SUFFIX_REGULAR)) {
|
||||
mFontInfo.font[Typeface.NORMAL] = font;
|
||||
} else if (fileName.endsWith(FONT_SUFFIX_BOLD)) {
|
||||
mFontInfo.font[Typeface.BOLD] = font;
|
||||
} else if (fileName.endsWith(FONT_SUFFIX_ITALIC)) {
|
||||
mFontInfo.font[Typeface.ITALIC] = font;
|
||||
} else if (fileName.endsWith(FONT_SUFFIX_BOLDITALIC)) {
|
||||
mFontInfo.font[Typeface.BOLD_ITALIC] = font;
|
||||
} else if (fileName.endsWith(FONT_SUFFIX_NONE)) {
|
||||
mFontInfo.font[Typeface.NORMAL] = font;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Font getFont(String fileName) {
|
||||
try {
|
||||
File file = new File(mOsFontsLocation, fileName);
|
||||
if (file.exists()) {
|
||||
return Font.createFont(Font.TRUETYPE_FONT, file);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void computeDerivedFont( int toCompute, int[] basedOnList) {
|
||||
for (int basedOn : basedOnList) {
|
||||
if (mFontInfo.font[basedOn] != null) {
|
||||
mFontInfo.font[toCompute] =
|
||||
mFontInfo.font[basedOn].deriveFont(AWT_STYLES[toCompute]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// we really shouldn't stop there. This means we don't have a NORMAL font...
|
||||
assert false;
|
||||
}
|
||||
|
||||
private String trimXmlWhitespaces(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user