summaryrefslogtreecommitdiff
path: root/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/FontLoader.java
diff options
context:
space:
mode:
Diffstat (limited to 'tools/layoutlib/bridge/src/com/android/layoutlib/bridge/FontLoader.java')
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/FontLoader.java142
1 files changed, 88 insertions, 54 deletions
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/FontLoader.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/FontLoader.java
index 1bdd1ccead0e..801503b89e0d 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/FontLoader.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/FontLoader.java
@@ -29,6 +29,7 @@ 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;
@@ -47,14 +48,13 @@ import javax.xml.parsers.SAXParserFactory;
*/
public final class FontLoader {
private static final String FONTS_DEFINITIONS = "fonts.xml";
-
+
private static final String NODE_FONTS = "fonts";
private static final String NODE_FONT = "font";
private static final String NODE_NAME = "name";
-
- private static final String ATTR_TTF = "ttf";
+ private static final String NODE_FALLBACK = "fallback";
- private static final String[] NODE_LEVEL = { NODE_FONTS, NODE_FONT, NODE_NAME };
+ private static final String ATTR_TTF = "ttf";
private static final String FONT_EXT = ".ttf";
@@ -62,7 +62,7 @@ public final class FontLoader {
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,
@@ -70,23 +70,25 @@ public final class FontLoader {
FONT_STYLE_ITALIC,
FONT_STYLE_BOLDITALIC
};
-
+
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;
+
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);
-
+
FontDefinitionParser definitionParser = new FontDefinitionParser(
fontOsLocation + File.separator);
parser.parse(new FileInputStream(f), definitionParser);
-
+
return definitionParser.getFontLoader();
} catch (ParserConfigurationException e) {
// return null below
@@ -101,12 +103,35 @@ public final class FontLoader {
return null;
}
- private FontLoader(List<FontInfo> fontList) {
+ private FontLoader(List<FontInfo> fontList, List<String> fallBackList) {
for (FontInfo info : fontList) {
for (String family : info.families) {
mFamilyToTtf.put(family, info.ttf);
}
}
+
+ 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
+ }
+ }
+ }
+
+ mFallBackFonts = Collections.unmodifiableList(list);
+ }
+
+ public List<Font> getFallBackFonts() {
+ return mFallBackFonts;
}
public synchronized Font getFont(String family, int[] style) {
@@ -116,25 +141,25 @@ public final class FontLoader {
// 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);
-
+
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:
@@ -178,7 +203,7 @@ public final class FontLoader {
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 {
@@ -193,14 +218,14 @@ public final class FontLoader {
}
}
}
-
+
return null;
}
private final static class FontInfo {
String ttf;
final Set<String> families;
-
+
FontInfo() {
families = new HashSet<String>();
}
@@ -208,19 +233,19 @@ public final class FontLoader {
private final static class FontDefinitionParser extends DefaultHandler {
private final String mOsFontsLocation;
-
- private int mDepth = 0;
+
private FontInfo mFontInfo = null;
private final StringBuilder mBuilder = new StringBuilder();
- private final List<FontInfo> mFontList = new ArrayList<FontInfo>();
-
+ private List<FontInfo> mFontList;
+ private List<String> mFallBackList;
+
private FontDefinitionParser(String osFontsLocation) {
super();
mOsFontsLocation = osFontsLocation;
}
-
+
FontLoader getFontLoader() {
- return new FontLoader(mFontList);
+ return new FontLoader(mFontList, mFallBackList);
}
/* (non-Javadoc)
@@ -229,10 +254,11 @@ public final class FontLoader {
@Override
public void startElement(String uri, String localName, String name, Attributes attributes)
throws SAXException {
- if (localName.equals(NODE_LEVEL[mDepth])) {
- mDepth++;
-
- if (mDepth == 2) { // font level.
+ if (NODE_FONTS.equals(localName)) {
+ mFontList = new ArrayList<FontInfo>();
+ mFallBackList = new ArrayList<String>();
+ } else if (NODE_FONT.equals(localName)) {
+ if (mFontList != null) {
String ttf = attributes.getValue(ATTR_TTF);
if (ttf != null) {
mFontInfo = new FontInfo();
@@ -240,42 +266,50 @@ public final class FontLoader {
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);
+ }
+ }
}
+ mBuilder.setLength(0);
+
super.startElement(uri, localName, name, attributes);
}
/* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
*/
- @SuppressWarnings("unused")
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
- if (mFontInfo != null) {
- mBuilder.append(ch, start, length);
- }
+ mBuilder.append(ch, start, length);
}
/* (non-Javadoc)
* @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
*/
- @SuppressWarnings("unused")
@Override
public void endElement(String uri, String localName, String name) throws SAXException {
- if (localName.equals(NODE_LEVEL[mDepth-1])) {
- mDepth--;
- if (mDepth == 2) { // end of a <name> node
- if (mFontInfo != null) {
- String family = trimXmlWhitespaces(mBuilder.toString());
- mFontInfo.families.add(family);
- mBuilder.setLength(0);
- }
- } else if (mDepth == 1) { // end of a <font> node
- mFontInfo = null;
+ if (NODE_FONTS.equals(localName)) {
+ // top level, do nothing
+ } else if (NODE_FONT.equals(localName)) {
+ 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.
}
}
-
+
private String trimXmlWhitespaces(String value) {
if (value == null) {
return null;
@@ -283,7 +317,7 @@ public final class FontLoader {
// look for carriage return and replace all whitespace around it by just 1 space.
int index;
-
+
while ((index = value.indexOf('\n')) != -1) {
// look for whitespace on each side
int left = index - 1;
@@ -294,7 +328,7 @@ public final class FontLoader {
break;
}
}
-
+
int right = index + 1;
int count = value.length();
while (right < count) {
@@ -304,7 +338,7 @@ public final class FontLoader {
break;
}
}
-
+
// remove all between left and right (non inclusive) and replace by a single space.
String leftString = null;
if (left >= 0) {
@@ -314,7 +348,7 @@ public final class FontLoader {
if (right < count) {
rightString = value.substring(right);
}
-
+
if (leftString != null) {
value = leftString;
if (rightString != null) {
@@ -324,24 +358,24 @@ public final class FontLoader {
value = rightString != null ? rightString : "";
}
}
-
+
// now we un-escape the string
int length = value.length();
char[] buffer = value.toCharArray();
-
+
for (int i = 0 ; i < length ; i++) {
if (buffer[i] == '\\') {
if (buffer[i+1] == 'n') {
// replace the char with \n
buffer[i+1] = '\n';
}
-
+
// offset the rest of the buffer since we go from 2 to 1 char
System.arraycopy(buffer, i+1, buffer, i, length - i - 1);
length--;
}
}
-
+
return new String(buffer, 0, length);
}