Android 5.0 system_fonts.xml檔案的解析過程

來源:互聯網
上載者:User

標籤:android   原始碼   xml   system_fonst.xml   

Android 5.0 system_fonts.xml檔案的解析過程首先看看看5.0 中familyset version="22" 的格式
 20     <family name="sans-serif"> 21         <font weight="100" style="normal">Roboto-Thin.ttf</font> 22         <font weight="100" style="italic">Roboto-ThinItalic.ttf</font> 23         <font weight="300" style="normal">Roboto-Light.ttf</font> 24         <font weight="300" style="italic">Roboto-LightItalic.ttf</font> 25         <font weight="400" style="normal">Roboto-Regular.ttf</font> 26         <font weight="400" style="italic">Roboto-Italic.ttf</font> 27         <font weight="500" style="normal">Roboto-Medium.ttf</font> 28         <font weight="500" style="italic">Roboto-MediumItalic.ttf</font> 29         <font weight="900" style="normal">Roboto-Black.ttf</font> 30         <font weight="900" style="italic">Roboto-BlackItalic.ttf</font> 31         <font weight="700" style="normal">Roboto-Bold.ttf</font> 32         <font weight="700" style="italic">Roboto-BoldItalic.ttf</font> 33     </family> 35     <!-- Note that aliases must come after the fonts they reference. --> 36     <alias name="sans-serif-thin" to="sans-serif" weight="100" /> 37     <alias name="sans-serif-light" to="sans-serif" weight="300" /> 38     <alias name="sans-serif-medium" to="sans-serif" weight="500" /> 39     <alias name="sans-serif-black" to="sans-serif" weight="900" /> 40     <alias name="arial" to="sans-serif" /> 41     <alias name="helvetica" to="sans-serif" /> 42     <alias name="tahoma" to="sans-serif" /> 43     <alias name="verdana" to="sans-serif" />
在Typeface.java中靜態類實現了對system_fonts.xml檔案的的解析過程一. system_fonts.xml檔案存在裝置的 /system/etc/system_fonts.xml 中二. Typyface檔案對system_fonts.xml檔案的解析過程需要兩個比較重要的資料結構:
  1. Font
public static class Font {        public String fontName;        //用於儲存Fontfile的檔案所在的Path        public int weight;             //新增加的欄位,表示字型大小        public boolean isItalic;       //是否為斜體    }
  1. Family
    public static class Family {        public String name;          //對應於Family的名字, eg:sans-serif        public List<Font> fonts;     //屬於該Family的Font集合        public String lang;          //語言屬性        public String variant;          }
再看看system_fonts.xml檔案的初始化代碼:
private static void init() {        // Load font config and initialize Minikin state        //以下根據設定檔的絕對路徑(/system/etc/system_fonts.xml)得到File對象,就沒什麼好分析的了        File systemFontConfigLocation = getSystemFontConfigLocation();        File configFilename = new File(systemFontConfigLocation, FONTS_CONFIG);        //無關代碼直接給省去了,直接分析解析代碼(剩餘的代碼後頭再進行分析)        try {            FileInputStream fontsIn = new FileInputStream(configFilename); //開啟檔案,沒什麼可以分析的            FontListParser.Config fontConfig = FontListParser.parse(fontsIn);//所有的核心都在這個parse中進行處理的            .....        } catch (RuntimeException e) {        ..............        }    }

要想知道parse到底幹了什麼,直接看原始碼

    /* Parse fallback list (no names) */    public static Config parse(InputStream in) throws XmlPullParserException, IOException {        try {            XmlPullParser parser = Xml.newPullParser(); //很明顯這個是一個Xml檔案解析工具類,不必要去深究了            parser.setInput(in, null);            parser.nextTag();            return readFamilies(parser); //重點分析這個函數        } finally {            in.close();        }    }

parse的在利用輸入資料流建立了Xml解析工具後,和行工作就轉交給readFamilies這個函數了

    private static Config readFamilies(XmlPullParser parser)            throws XmlPullParserException, IOException {        Config config = new Config(); //設定檔的所有解析結果都是儲存於這個變數中        parser.require(XmlPullParser.START_TAG, null, "familyset");        while (parser.next() != XmlPullParser.END_TAG) {            if (parser.getEventType() != XmlPullParser.START_TAG) continue;            //以下兩個if 條件可知,該解析只對 ‘family‘ 標籤和 ‘alias‘ 標籤裡的內容進行解析            if (parser.getName().equals("family")) {                config.families.add(readFamily(parser));            } else if (parser.getName().equals("alias")) {                config.aliases.add(readAlias(parser));            } else {                skip(parser);            }        }        return config;    }

從上面代碼可以知道,readFamilies針對family 和 alias 標籤裡的內容進行分析,其他內容都進行忽略處理,並且處理的結果都儲存的Config這個對象中

  1. 對與family 標籤中的內容進行解析的過程,readFamily函數的調用
    private static Family readFamily(XmlPullParser parser)            throws XmlPullParserException, IOException {        //family 標籤可能有三個屬性: 分別是name lang variant,所以以下三行完成對對應屬性的讀取        String name = parser.getAttributeValue(null, "name");        String lang = parser.getAttributeValue(null, "lang");        String variant = parser.getAttributeValue(null, "variant");        /* 1. 以family為父標籤,font可以為其子標籤,font標籤描述的是:ttf檔案的儲存路徑(path)、文字的大小(weight)、        *     style等特性.        *  2. family可以有多個font標籤,即在同一個family下的font是屬於同一字型族        */         List<Font> fonts = new ArrayList<Font>();        //該迴圈完成對屬於同一字型族的font屬性:weight , style , fullFilename(絕對路徑)的讀取        while (parser.next() != XmlPullParser.END_TAG) {            if (parser.getEventType() != XmlPullParser.START_TAG) continue;            String tag = parser.getName();            if (tag.equals("font")) {                String weightStr = parser.getAttributeValue(null, "weight");                //若weight屬性不存在,預設為400                int weight = weightStr == null ? 400 : Integer.parseInt(weightStr);                boolean isItalic = "italic".equals(parser.getAttributeValue(null, "style"));                String filename = parser.nextText();                String fullFilename = "/system/fonts/" + filename;                fonts.add(new Font(fullFilename, weight, isItalic));            } else {                skip(parser);            }        }        return new Family(name, fonts, lang, variant);    }
  1. 對 alias 標籤的內容的都取,readAlias. alias其實就是對family進行重新命名(alias只能對已知的family的名字進行重新命名)
eg :  名字為 sans-serif-thin的family必須在該句前出現<alias name="sans-serif-thin" to="sans-serif" weight="100" />
    private static Alias readAlias(XmlPullParser parser)            throws XmlPullParserException, IOException {        Alias alias = new Alias();        alias.name = parser.getAttributeValue(null, "name");        alias.toName = parser.getAttributeValue(null, "to");        String weightStr = parser.getAttributeValue(null, "weight");        if (weightStr == null) {            alias.weight = 400;        } else {            alias.weight = Integer.parseInt(weightStr);        }        skip(parser);  // alias tag is empty, ignore any contents and consume end tag        return alias;    }

就這樣,就完成了對xml檔案的解析

Android 5.0 system_fonts.xml檔案的解析過程

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.