diff options
author | Xavier Ducrohet <xav@android.com> | 2009-11-09 17:04:10 -0800 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2009-11-09 17:04:10 -0800 |
commit | 75cec67e3a29be7b8a3c4fa8eab64b0752f0b206 (patch) | |
tree | 1be7904b98853050111b6d45e9d6866a58985fee /tools | |
parent | 92885e0328a673fbe418030cae49c18c4a2903f2 (diff) | |
parent | 3969e50a2872014e459b802e2e654b901eecc574 (diff) | |
download | frameworks_base-75cec67e3a29be7b8a3c4fa8eab64b0752f0b206.zip frameworks_base-75cec67e3a29be7b8a3c4fa8eab64b0752f0b206.tar.gz frameworks_base-75cec67e3a29be7b8a3c4fa8eab64b0752f0b206.tar.bz2 |
am 3969e50a: am aa10b9fb: am e6ab011b: Merge change Ib12bcb7f into eclair
Merge commit '3969e50a2872014e459b802e2e654b901eecc574'
* commit '3969e50a2872014e459b802e2e654b901eecc574':
Support for fallback fonts in layoutlib.
Diffstat (limited to 'tools')
4 files changed, 333 insertions, 120 deletions
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas.java b/tools/layoutlib/bridge/src/android/graphics/Canvas.java index 3fa1d1d..4986c77 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Canvas.java +++ b/tools/layoutlib/bridge/src/android/graphics/Canvas.java @@ -26,6 +26,7 @@ import android.graphics.RectF; import android.graphics.Region; import android.graphics.Xfermode; import android.graphics.Paint.Align; +import android.graphics.Paint.FontInfo; import android.graphics.Paint.Style; import android.graphics.Region.Op; @@ -37,6 +38,7 @@ import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.geom.AffineTransform; import java.awt.image.BufferedImage; +import java.util.List; import java.util.Stack; import javax.microedition.khronos.opengles.GL; @@ -620,19 +622,21 @@ public class Canvas extends _Original_Canvas { */ @Override public void drawText(char[] text, int index, int count, float x, float y, Paint paint) { + // WARNING: the logic in this method is similar to Paint.measureText. + // Any change to this method should be reflected in Paint.measureText Graphics2D g = getGraphics2d(); g = (Graphics2D)g.create(); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g.setFont(paint.getFont()); - - // set the color. because this only handles RGB we have to handle the alpha separately + // set the color. because this only handles RGB, the alpha channel is handled + // as a composite. g.setColor(new Color(paint.getColor())); int alpha = paint.getAlpha(); float falpha = alpha / 255.f; g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha)); + // Paint.TextAlign indicates how the text is positioned relative to X. // LEFT is the default and there's nothing to do. if (paint.getTextAlign() != Align.LEFT) { @@ -644,9 +648,83 @@ public class Canvas extends _Original_Canvas { } } - g.drawChars(text, index, count, (int)x, (int)y); - - g.dispose(); + List<FontInfo> fonts = paint.getFonts(); + try { + if (fonts.size() > 0) { + FontInfo mainFont = fonts.get(0); + int i = index; + int lastIndex = index + count; + while (i < lastIndex) { + // always start with the main font. + int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex); + if (upTo == -1) { + // draw all the rest and exit. + g.setFont(mainFont.mFont); + g.drawChars(text, i, lastIndex - i, (int)x, (int)y); + return; + } else if (upTo > 0) { + // draw what's possible + g.setFont(mainFont.mFont); + g.drawChars(text, i, upTo - i, (int)x, (int)y); + + // compute the width that was drawn to increase x + x += mainFont.mMetrics.charsWidth(text, i, upTo - i); + + // move index to the first non displayed char. + i = upTo; + + // don't call continue at this point. Since it is certain the main font + // cannot display the font a index upTo (now ==i), we move on to the + // fallback fonts directly. + } + + // no char supported, attempt to read the next char(s) with the + // fallback font. In this case we only test the first character + // and then go back to test with the main font. + // Special test for 2-char characters. + boolean foundFont = false; + for (int f = 1 ; f < fonts.size() ; f++) { + FontInfo fontInfo = fonts.get(f); + + // need to check that the font can display the character. We test + // differently if the char is a high surrogate. + int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1; + upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount); + if (upTo == -1) { + // draw that char + g.setFont(fontInfo.mFont); + g.drawChars(text, i, charCount, (int)x, (int)y); + + // update x + x += fontInfo.mMetrics.charsWidth(text, i, charCount); + + // update the index in the text, and move on + i += charCount; + foundFont = true; + break; + + } + } + + // in case no font can display the char, display it with the main font. + // (it'll put a square probably) + if (foundFont == false) { + int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1; + + g.setFont(mainFont.mFont); + g.drawChars(text, i, charCount, (int)x, (int)y); + + // measure it to advance x + x += mainFont.mMetrics.charsWidth(text, i, charCount); + + // and move to the next chars. + i += charCount; + } + } + } + } finally { + g.dispose(); + } } /* (non-Javadoc) diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint.java b/tools/layoutlib/bridge/src/android/graphics/Paint.java index 2972ff3..86de56b 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Paint.java +++ b/tools/layoutlib/bridge/src/android/graphics/Paint.java @@ -26,6 +26,9 @@ import java.awt.Toolkit; import java.awt.font.FontRenderContext; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; /** * A paint implementation overridden by the LayoutLib bridge. @@ -44,10 +47,17 @@ public class Paint extends _Original_Paint { private Join mJoin = Join.MITER; private int mFlags = 0; - private Font mFont; + /** + * Class associating a {@link Font} and it's {@link java.awt.FontMetrics}. + */ + public static final class FontInfo { + Font mFont; + java.awt.FontMetrics mMetrics; + } + + private List<FontInfo> mFonts; private final FontRenderContext mFontContext = new FontRenderContext( new AffineTransform(), true, true); - private java.awt.FontMetrics mMetrics; @SuppressWarnings("hiding") public static final int ANTI_ALIAS_FLAG = _Original_Paint.ANTI_ALIAS_FLAG; @@ -201,10 +211,11 @@ public class Paint extends _Original_Paint { } /** - * Returns the {@link Font} object. + * Returns the list of {@link Font} objects. The first item is the main font, the rest + * are fall backs for characters not present in the main font. */ - public Font getFont() { - return mFont; + public List<FontInfo> getFonts() { + return mFonts; } private void initFont() { @@ -215,17 +226,29 @@ public class Paint extends _Original_Paint { /** * Update the {@link Font} object from the typeface, text size and scaling */ + @SuppressWarnings("deprecation") private void updateFontObject() { if (mTypeface != null) { - // get the typeface font object, and get our font object from it, based on the current size - mFont = mTypeface.getFont().deriveFont(mTextSize); - if (mScaleX != 1.0 || mSkewX != 0) { - // TODO: support skew - mFont = mFont.deriveFont(new AffineTransform( - mScaleX, mSkewX, 0, 0, 1, 0)); + // Get the fonts from the TypeFace object. + List<Font> fonts = mTypeface.getFonts(); + + // create new font objects as well as FontMetrics, based on the current text size + // and skew info. + ArrayList<FontInfo> infoList = new ArrayList<FontInfo>(fonts.size()); + for (Font font : fonts) { + FontInfo info = new FontInfo(); + info.mFont = font.deriveFont(mTextSize); + if (mScaleX != 1.0 || mSkewX != 0) { + // TODO: support skew + info.mFont = info.mFont.deriveFont(new AffineTransform( + mScaleX, mSkewX, 0, 0, 1, 0)); + } + info.mMetrics = Toolkit.getDefaultToolkit().getFontMetrics(info.mFont); + + infoList.add(info); } - mMetrics = Toolkit.getDefaultToolkit().getFontMetrics(mFont); + mFonts = Collections.unmodifiableList(infoList); } } @@ -310,34 +333,36 @@ public class Paint extends _Original_Paint { * @return the font's recommended interline spacing. */ public float getFontMetrics(FontMetrics metrics) { - if (mMetrics != null) { + if (mFonts.size() > 0) { + java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics; if (metrics != null) { - // ascent stuff should be negatif, but awt returns them as positive. - metrics.top = - mMetrics.getMaxAscent(); - metrics.ascent = - mMetrics.getAscent(); - metrics.descent = mMetrics.getDescent(); - metrics.bottom = mMetrics.getMaxDescent(); - metrics.leading = mMetrics.getLeading(); + // Android expects negative ascent so we invert the value from Java. + metrics.top = - javaMetrics.getMaxAscent(); + metrics.ascent = - javaMetrics.getAscent(); + metrics.descent = javaMetrics.getDescent(); + metrics.bottom = javaMetrics.getMaxDescent(); + metrics.leading = javaMetrics.getLeading(); } - return mMetrics.getHeight(); + return javaMetrics.getHeight(); } return 0; } public int getFontMetricsInt(FontMetricsInt metrics) { - if (mMetrics != null) { + if (mFonts.size() > 0) { + java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics; if (metrics != null) { - // ascent stuff should be negatif, but awt returns them as positive. - metrics.top = - mMetrics.getMaxAscent(); - metrics.ascent = - mMetrics.getAscent(); - metrics.descent = mMetrics.getDescent(); - metrics.bottom = mMetrics.getMaxDescent(); - metrics.leading = mMetrics.getLeading(); + // Android expects negative ascent so we invert the value from Java. + metrics.top = - javaMetrics.getMaxAscent(); + metrics.ascent = - javaMetrics.getAscent(); + metrics.descent = javaMetrics.getDescent(); + metrics.bottom = javaMetrics.getMaxDescent(); + metrics.leading = javaMetrics.getLeading(); } - return mMetrics.getHeight(); + return javaMetrics.getHeight(); } return 0; @@ -716,9 +741,10 @@ public class Paint extends _Original_Paint { */ @Override public float ascent() { - if (mMetrics != null) { - // ascent stuff should be negatif, but awt returns them as positive. - return - mMetrics.getAscent(); + if (mFonts.size() > 0) { + java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics; + // Android expects negative ascent so we invert the value from Java. + return - javaMetrics.getAscent(); } return 0; @@ -733,8 +759,9 @@ public class Paint extends _Original_Paint { */ @Override public float descent() { - if (mMetrics != null) { - return mMetrics.getDescent(); + if (mFonts.size() > 0) { + java.awt.FontMetrics javaMetrics = mFonts.get(0).mMetrics; + return javaMetrics.getDescent(); } return 0; @@ -750,10 +777,55 @@ public class Paint extends _Original_Paint { */ @Override public float measureText(char[] text, int index, int count) { - if (mFont != null && text != null && text.length > 0) { - Rectangle2D bounds = mFont.getStringBounds(text, index, index + count, mFontContext); - - return (float)bounds.getWidth(); + // WARNING: the logic in this method is similar to Canvas.drawText. + // Any change to this method should be reflected in Canvas.drawText + if (mFonts.size() > 0) { + FontInfo mainFont = mFonts.get(0); + int i = index; + int lastIndex = index + count; + float total = 0f; + while (i < lastIndex) { + // always start with the main font. + int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex); + if (upTo == -1) { + // shortcut to exit + return total + mainFont.mMetrics.charsWidth(text, i, lastIndex - i); + } else if (upTo > 0) { + total += mainFont.mMetrics.charsWidth(text, i, upTo - i); + i = upTo; + // don't call continue at this point. Since it is certain the main font + // cannot display the font a index upTo (now ==i), we move on to the + // fallback fonts directly. + } + + // no char supported, attempt to read the next char(s) with the + // fallback font. In this case we only test the first character + // and then go back to test with the main font. + // Special test for 2-char characters. + boolean foundFont = false; + for (int f = 1 ; f < mFonts.size() ; f++) { + FontInfo fontInfo = mFonts.get(f); + + // need to check that the font can display the character. We test + // differently if the char is a high surrogate. + int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1; + upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount); + if (upTo == -1) { + total += fontInfo.mMetrics.charsWidth(text, i, charCount); + i += charCount; + foundFont = true; + break; + + } + } + + // in case no font can display the char, measure it with the main font. + if (foundFont == false) { + int size = Character.isHighSurrogate(text[i]) ? 2 : 1; + total += mainFont.mMetrics.charsWidth(text, i, size); + i += size; + } + } } return 0; @@ -919,14 +991,30 @@ public class Paint extends _Original_Paint { @Override public int getTextWidths(char[] text, int index, int count, float[] widths) { - if (mMetrics != null) { + if (mFonts.size() > 0) { if ((index | count) < 0 || index + count > text.length || count > widths.length) { throw new ArrayIndexOutOfBoundsException(); } + // FIXME: handle multi-char characters. + // Need to figure out if the lengths of the width array takes into account + // multi-char characters. for (int i = 0; i < count; i++) { - widths[i] = mMetrics.charWidth(text[i + index]); + char c = text[i + index]; + boolean found = false; + for (FontInfo info : mFonts) { + if (info.mFont.canDisplay(c)) { + widths[i] = info.mMetrics.charWidth(c); + found = true; + break; + } + } + + if (found == false) { + // we stop there. + return i; + } } return count; @@ -1070,7 +1158,8 @@ public class Paint extends _Original_Paint { */ @Override public void getTextBounds(char[] text, int index, int count, Rect bounds) { - if (mFont != null) { + // FIXME + if (mFonts.size() > 0) { if ((index | count) < 0 || index + count > text.length) { throw new ArrayIndexOutOfBoundsException(); } @@ -1078,7 +1167,9 @@ public class Paint extends _Original_Paint { throw new NullPointerException("need bounds Rect"); } - Rectangle2D rect = mFont.getStringBounds(text, index, index + count, mFontContext); + FontInfo mainInfo = mFonts.get(0); + + Rectangle2D rect = mainInfo.mFont.getStringBounds(text, index, index + count, mFontContext); bounds.set(0, 0, (int)rect.getWidth(), (int)rect.getHeight()); } } diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface.java b/tools/layoutlib/bridge/src/android/graphics/Typeface.java index e878b04..af3adb5 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Typeface.java +++ b/tools/layoutlib/bridge/src/android/graphics/Typeface.java @@ -21,9 +21,12 @@ import com.android.layoutlib.bridge.FontLoader; import android.content.res.AssetManager; import java.awt.Font; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; /** - * Re-implementation of Typeface over java.awt + * Re-implementation of Typeface over java.awt */ public class Typeface { private static final String DEFAULT_FAMILY = "sans-serif"; @@ -46,11 +49,11 @@ public class Typeface { private static Typeface[] sDefaults; private static FontLoader mFontLoader; - + private final int mStyle; - private final Font mFont; + private final List<Font> mFonts; private final String mFamily; - + // Style public static final int NORMAL = _Original_Typeface.NORMAL; public static final int BOLD = _Original_Typeface.BOLD; @@ -58,12 +61,13 @@ public class Typeface { public static final int BOLD_ITALIC = _Original_Typeface.BOLD_ITALIC; /** - * Returns the underlying {@link Font} object. + * Returns the underlying {@link Font} objects. The first item in the list is the real + * font. Any other items are fallback fonts for characters not found in the first one. */ - public Font getFont() { - return mFont; + public List<Font> getFonts() { + return mFonts; } - + /** Returns the typeface's intrinsic style attributes */ public int getStyle() { return mStyle; @@ -94,9 +98,12 @@ public class Typeface { styleBuffer[0] = style; Font font = mFontLoader.getFont(familyName, styleBuffer); if (font != null) { - return new Typeface(familyName, styleBuffer[0], font); + ArrayList<Font> list = new ArrayList<Font>(); + list.add(font); + list.addAll(mFontLoader.getFallBackFonts()); + return new Typeface(familyName, styleBuffer[0], list); } - + return null; } @@ -115,7 +122,10 @@ public class Typeface { styleBuffer[0] = style; Font font = mFontLoader.getFont(family.mFamily, styleBuffer); if (font != null) { - return new Typeface(family.mFamily, styleBuffer[0], font); + ArrayList<Font> list = new ArrayList<Font>(); + list.add(font); + list.addAll(mFontLoader.getFallBackFonts()); + return new Typeface(family.mFamily, styleBuffer[0], list); } return null; @@ -129,7 +139,7 @@ public class Typeface { public static Typeface defaultFromStyle(int style) { return sDefaults[style]; } - + /** * Create a new typeface from the specified font data. * @param mgr The application's asset manager @@ -140,17 +150,17 @@ public class Typeface { return null; //return new Typeface(nativeCreateFromAsset(mgr, path)); } - + // don't allow clients to call this directly - private Typeface(String family, int style, Font f) { + private Typeface(String family, int style, List<Font> fonts) { mFamily = family; - mFont = f; + mFonts = Collections.unmodifiableList(fonts); mStyle = style; } - + public static void init(FontLoader fontLoader) { mFontLoader = fontLoader; - + DEFAULT = create(DEFAULT_FAMILY, NORMAL); DEFAULT_BOLD = create(DEFAULT_FAMILY, BOLD); SANS_SERIF = create("sans-serif", NORMAL); @@ -162,14 +172,14 @@ public class Typeface { create(DEFAULT_FAMILY, ITALIC), create(DEFAULT_FAMILY, BOLD_ITALIC), }; - + /* 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); - + sDefaults = new Typeface[] { DEFAULT, DEFAULT_BOLD, 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 1bdd1cc..801503b 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); } |