Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 178006a0 authored by Xavier Ducrohet's avatar Xavier Ducrohet
Browse files

Layoutlib now parses system_fonts.xml instead of its own.

Also parse fallback_fonts.
This lets layoutlib automatically use the same fonts as the base
platforms, for instance it now uses the new ICS fonts.

Change-Id: Id6e778dc0e3f2a9112601e0eaf8499a9713ec433
parent 3c1951c4
Loading
Loading
Loading
Loading

data/fonts/fonts.xml

deleted100644 → 0
+0 −48
Original line number Original line Diff line number Diff line
<?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>
+1 −11
Original line number Original line Diff line number Diff line
@@ -26,7 +26,6 @@ import android.content.res.AssetManager;


import java.awt.Font;
import java.awt.Font;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.List;


/**
/**
@@ -50,7 +49,6 @@ public final class Typeface_Delegate {


    // ---- delegate helper data ----
    // ---- delegate helper data ----
    private static final String DEFAULT_FAMILY = "sans-serif";
    private static final String DEFAULT_FAMILY = "sans-serif";
    private static final int[] STYLE_BUFFER = new int[1];


    private static FontLoader sFontLoader;
    private static FontLoader sFontLoader;
    private static final List<Typeface_Delegate> sPostInitDelegate =
    private static final List<Typeface_Delegate> sPostInitDelegate =
@@ -178,14 +176,6 @@ public final class Typeface_Delegate {
    }
    }


    private void init() {
    private void init() {
        STYLE_BUFFER[0] = mStyle;
        mFonts = sFontLoader.getFont(mFamily, 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];
        }
    }
    }
}
}
+134 −168
Original line number Original line Diff line number Diff line
@@ -23,17 +23,13 @@ import org.xml.sax.helpers.DefaultHandler;
import android.graphics.Typeface;
import android.graphics.Typeface;


import java.awt.Font;
import java.awt.Font;
import java.awt.FontFormatException;
import java.io.File;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.HashSet;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Set;


import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.ParserConfigurationException;
@@ -47,49 +43,53 @@ import javax.xml.parsers.SAXParserFactory;
 * fonts.xml file located alongside the ttf files.
 * fonts.xml file located alongside the ttf files.
 */
 */
public final class FontLoader {
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_FAMILYSET = "familyset";
    private static final String NODE_FONT = "font";
    private static final String NODE_FAMILY = "family";
    private static final String NODE_NAME = "name";
    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_EXT = ".ttf";
    private static final String FONT_SUFFIX_BOLD = "-Bold.ttf";

    private static final String FONT_SUFFIX_ITALIC = "-Italic.ttf";
    private static final String[] FONT_STYLE_DEFAULT = { "", "-Regular" };
    private static final String FONT_SUFFIX_BOLDITALIC = "-BoldItalic.ttf";
    private static final String[] FONT_STYLE_BOLD = { "-Bold" };

    private static final String[] FONT_STYLE_ITALIC = { "-Italic" };
    // This must match the values of Typeface styles so that we can use them for indices in this
    private static final String[] FONT_STYLE_BOLDITALIC = { "-BoldItalic" };
    // array.

    private static final int[] AWT_STYLES = new int[] {
    // list of font style, in the order matching the Typeface Font style
        Font.PLAIN,
    private static final String[][] FONT_STYLES = {
        Font.BOLD,
        FONT_STYLE_DEFAULT,
        Font.ITALIC,
        FONT_STYLE_BOLD,
        Font.BOLD | Font.ITALIC
        FONT_STYLE_ITALIC,
        FONT_STYLE_BOLDITALIC
    };
    };
    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 static final List<FontInfo> mMainFonts = new ArrayList<FontInfo>();
    private final Map<String, Map<Integer, Font>> mTtfToFontMap =
    private static final List<FontInfo> mFallbackFonts = new ArrayList<FontInfo>();
        new HashMap<String, Map<Integer, Font>>();

    private List<Font> mFallBackFonts = null;


    public static FontLoader create(String fontOsLocation) {
    public static FontLoader create(String fontOsLocation) {
        try {
        try {
            SAXParserFactory parserFactory = SAXParserFactory.newInstance();
            SAXParserFactory parserFactory = SAXParserFactory.newInstance();
                parserFactory.setNamespaceAware(true);
                parserFactory.setNamespaceAware(true);


            SAXParser parser = parserFactory.newSAXParser();
            // parse the system fonts
            File f = new File(fontOsLocation + File.separator + FONTS_DEFINITIONS);
            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) {
        } catch (ParserConfigurationException e) {
            // return null below
            // return null below
        } catch (SAXException e) {
        } catch (SAXException e) {
@@ -103,35 +103,22 @@ public final class FontLoader {
        return null;
        return null;
    }
    }


    private FontLoader(List<FontInfo> fontList, List<String> fallBackList) {
    private static FontHandler parseFontFile(SAXParserFactory parserFactory,
        for (FontInfo info : fontList) {
            String fontOsLocation, String fontFileName)
            for (String family : info.families) {
            throws ParserConfigurationException, SAXException, IOException, FileNotFoundException {
                mFamilyToTtf.put(family, info.ttf);
            }
        }


        ArrayList<Font> list = new ArrayList<Font>();
        SAXParser parser = parserFactory.newSAXParser();
        for (String path : fallBackList) {
        File f = new File(fontOsLocation, fontFileName);
            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);
        FontHandler definitionParser = new FontHandler(
                fontOsLocation + File.separator);
        parser.parse(new FileInputStream(f), definitionParser);
        return definitionParser;
    }
    }


    public List<Font> getFallBackFonts() {
    private FontLoader(List<FontInfo> fontList, List<FontInfo> fallBackList) {
        return mFallBackFonts;
        mMainFonts.addAll(fontList);
        mFallbackFonts.addAll(fallBackList);
    }
    }


    /**
    /**
@@ -143,96 +130,32 @@ public final class FontLoader {
     *              the method returns.
     *              the method returns.
     * @return the font object or null if no match could be found.
     * @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) {
        if (family == null) {
        List<Font> result = new ArrayList<Font>();
            return null;
        }


        // get the ttf name from the family
        if (family == null) {
        String ttf = mFamilyToTtf.get(family);
            return result;

        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
        // get the font objects from the main list based on family.
        switch (style[0]) {
        for (FontInfo info : mMainFonts) {
            case Typeface.NORMAL:
            if (info.families.contains(family)) {
                f = getFont(ttf, FONT_STYLES[Typeface.NORMAL]);
                result.add(info.font[style]);
                break;
                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) {
        // add all the fallback fonts
            styleMap.put(style[0], f);
        for (FontInfo info : mFallbackFonts) {
            return f;
            result.add(info.font[style]);
        }
        }


        return null;
        return result;
    }

    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;
    }
    }


    private final static class FontInfo {
    private final static class FontInfo {
        String ttf;
        final Font[] font = new Font[4]; // Matches the 4 type-face styles.
        final Set<String> families;
        final Set<String> families;


        FontInfo() {
        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 final String mOsFontsLocation;


        private FontInfo mFontInfo = null;
        private FontInfo mFontInfo = null;
        private final StringBuilder mBuilder = new StringBuilder();
        private final StringBuilder mBuilder = new StringBuilder();
        private List<FontInfo> mFontList;
        private List<FontInfo> mFontList = new ArrayList<FontInfo>();
        private List<String> mFallBackList;


        private FontDefinitionParser(String osFontsLocation) {
        private FontHandler(String osFontsLocation) {
            super();
            super();
            mOsFontsLocation = osFontsLocation;
            mOsFontsLocation = osFontsLocation;
        }
        }


        FontLoader getFontLoader() {
        public List<FontInfo> getFontList() {
            return new FontLoader(mFontList, mFallBackList);
            return mFontList;
        }
        }


        /* (non-Javadoc)
        /* (non-Javadoc)
@@ -263,26 +185,11 @@ public final class FontLoader {
        @Override
        @Override
        public void startElement(String uri, String localName, String name, Attributes attributes)
        public void startElement(String uri, String localName, String name, Attributes attributes)
                throws SAXException {
                throws SAXException {
            if (NODE_FONTS.equals(localName)) {
            if (NODE_FAMILYSET.equals(localName)) {
                mFontList = new ArrayList<FontInfo>();
                mFontList = new ArrayList<FontInfo>();
                mFallBackList = new ArrayList<String>();
            } else if (NODE_FAMILY.equals(localName)) {
            } else if (NODE_FONT.equals(localName)) {
                if (mFontList != null) {
                if (mFontList != null) {
                    String ttf = attributes.getValue(ATTR_TTF);
                    if (ttf != null) {
                    mFontInfo = new FontInfo();
                    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);
                    }
                }
                }
            }
            }


@@ -304,20 +211,79 @@ public final class FontLoader {
         */
         */
        @Override
        @Override
        public void endElement(String uri, String localName, String name) throws SAXException {
        public void endElement(String uri, String localName, String name) throws SAXException {
            if (NODE_FONTS.equals(localName)) {
            if (NODE_FAMILY.equals(localName)) {
                // top level, do nothing
                if (mFontInfo != null) {
            } else if (NODE_FONT.equals(localName)) {
                    // 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;
                    mFontInfo = null;
                }
            } else if (NODE_NAME.equals(localName)) {
            } else if (NODE_NAME.equals(localName)) {
                // handle a new name for an existing Font Info
                // handle a new name for an existing Font Info
                if (mFontInfo != null) {
                if (mFontInfo != null) {
                    String family = trimXmlWhitespaces(mBuilder.toString());
                    String family = trimXmlWhitespaces(mBuilder.toString());
                    mFontInfo.families.add(family);
                    mFontInfo.families.add(family);
                }
                }
            } else if (NODE_FALLBACK.equals(localName)) {
            } else if (NODE_FILE.equals(localName)) {
                // nothing to do here.
                // 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) {
        private String trimXmlWhitespaces(String value) {
            if (value == null) {
            if (value == null) {