1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.graphics;
18 
19 import android.util.Xml;
20 
21 import org.xmlpull.v1.XmlPullParser;
22 import org.xmlpull.v1.XmlPullParserException;
23 
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.util.ArrayList;
27 import java.util.List;
28 
29 /**
30  * Parser for font config files.
31  *
32  * @hide
33  */
34 public class FontListParser {
35 
36     public static class Config {
Config()37         Config() {
38             families = new ArrayList<Family>();
39             aliases = new ArrayList<Alias>();
40         }
41         public List<Family> families;
42         public List<Alias> aliases;
43     }
44 
45     public static class Font {
Font(String fontName, int weight, boolean isItalic)46         Font(String fontName, int weight, boolean isItalic) {
47             this.fontName = fontName;
48             this.weight = weight;
49             this.isItalic = isItalic;
50         }
51         public String fontName;
52         public int weight;
53         public boolean isItalic;
54     }
55 
56     public static class Alias {
57         public String name;
58         public String toName;
59         public int weight;
60     }
61 
62     public static class Family {
Family(String name, List<Font> fonts, String lang, String variant)63         public Family(String name, List<Font> fonts, String lang, String variant) {
64             this.name = name;
65             this.fonts = fonts;
66             this.lang = lang;
67             this.variant = variant;
68         }
69 
70         public String name;
71         public List<Font> fonts;
72         public String lang;
73         public String variant;
74     }
75 
76     /* Parse fallback list (no names) */
parse(InputStream in)77     public static Config parse(InputStream in) throws XmlPullParserException, IOException {
78         try {
79             XmlPullParser parser = Xml.newPullParser();
80             parser.setInput(in, null);
81             parser.nextTag();
82             return readFamilies(parser);
83         } finally {
84             in.close();
85         }
86     }
87 
readFamilies(XmlPullParser parser)88     private static Config readFamilies(XmlPullParser parser)
89             throws XmlPullParserException, IOException {
90         Config config = new Config();
91         parser.require(XmlPullParser.START_TAG, null, "familyset");
92         while (parser.next() != XmlPullParser.END_TAG) {
93             if (parser.getEventType() != XmlPullParser.START_TAG) continue;
94             if (parser.getName().equals("family")) {
95                 config.families.add(readFamily(parser));
96             } else if (parser.getName().equals("alias")) {
97                 config.aliases.add(readAlias(parser));
98             } else {
99                 skip(parser);
100             }
101         }
102         return config;
103     }
104 
readFamily(XmlPullParser parser)105     private static Family readFamily(XmlPullParser parser)
106             throws XmlPullParserException, IOException {
107         String name = parser.getAttributeValue(null, "name");
108         String lang = parser.getAttributeValue(null, "lang");
109         String variant = parser.getAttributeValue(null, "variant");
110         List<Font> fonts = new ArrayList<Font>();
111         while (parser.next() != XmlPullParser.END_TAG) {
112             if (parser.getEventType() != XmlPullParser.START_TAG) continue;
113             String tag = parser.getName();
114             if (tag.equals("font")) {
115                 String weightStr = parser.getAttributeValue(null, "weight");
116                 int weight = weightStr == null ? 400 : Integer.parseInt(weightStr);
117                 boolean isItalic = "italic".equals(parser.getAttributeValue(null, "style"));
118                 String filename = parser.nextText();
119                 String fullFilename = "/system/fonts/" + filename;
120                 fonts.add(new Font(fullFilename, weight, isItalic));
121             } else {
122                 skip(parser);
123             }
124         }
125         return new Family(name, fonts, lang, variant);
126     }
127 
readAlias(XmlPullParser parser)128     private static Alias readAlias(XmlPullParser parser)
129             throws XmlPullParserException, IOException {
130         Alias alias = new Alias();
131         alias.name = parser.getAttributeValue(null, "name");
132         alias.toName = parser.getAttributeValue(null, "to");
133         String weightStr = parser.getAttributeValue(null, "weight");
134         if (weightStr == null) {
135             alias.weight = 400;
136         } else {
137             alias.weight = Integer.parseInt(weightStr);
138         }
139         skip(parser);  // alias tag is empty, ignore any contents and consume end tag
140         return alias;
141     }
142 
skip(XmlPullParser parser)143     private static void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
144         int depth = 1;
145         while (depth > 0) {
146             switch (parser.next()) {
147             case XmlPullParser.START_TAG:
148                 depth++;
149                 break;
150             case XmlPullParser.END_TAG:
151                 depth--;
152                 break;
153             }
154         }
155     }
156 }
157