美文网首页
Android裁剪之fonts(字体库)浅析

Android裁剪之fonts(字体库)浅析

作者: 锄禾豆 | 来源:发表于2022-01-28 07:55 被阅读0次

源码

7.1

问题:
1.系统编译过程对应的/system/fonts资源来自?
注:
回答此问题,涉及很多编译方面的知识

例如,我们以Wifi only版为主:
build/target/product/generic_no_telephony.mk

$(call inherit-product-if-exists, frameworks/base/data/fonts/fonts.mk)
$(call inherit-product-if-exists, external/google-fonts/dancing-script/fonts.mk)
$(call inherit-product-if-exists, external/google-fonts/carrois-gothic-sc/fonts.mk)
$(call inherit-product-if-exists, external/google-fonts/coming-soon/fonts.mk)
$(call inherit-product-if-exists, external/google-fonts/cutive-mono/fonts.mk)
$(call inherit-product-if-exists, external/noto-fonts/fonts.mk)
$(call inherit-product-if-exists, external/naver-fonts/fonts.mk)
$(call inherit-product-if-exists, external/roboto-fonts/fonts.mk)

也就是说,我们的字体来源都是靠fonts.mk的集合。
如果裁剪涉及方案:
1.不进行编译。即从编译源头注销
2.裁剪fonts.mk中的部分模块
温馨提醒:
fonts.mk使用的是Android.mk的方式,也就是说,对于的字体仍需要耦合其他模块,所以需要重新生成一次。不然的话,可以直接使用PRODUCT_COPY_FILES

2.app在启动的时候,怎么进行字体的加载?
注:
回答此问题,涉及进程启动流程

1)进程启动,涉及资源文件加载
com.android.internal.os.ZygoteInit
main --> preload() --> preloadClasses()

private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";

private static void preloadClasses() {
        final VMRuntime runtime = VMRuntime.getRuntime();

        InputStream is;
        try {
            is = new FileInputStream(PRELOADED_CLASSES);
        } catch (FileNotFoundException e) {
            Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
            return;
        }

        ······

        try {
            BufferedReader br
                = new BufferedReader(new InputStreamReader(is), 256);

            String line;
            while ((line = br.readLine()) != null) {
                ·······
                try {
                    ·······
                    Class.forName(line, true, null);//初始化各种类,关键:Typeface
                    ······
                } catch (ClassNotFoundException e) {
                }
                ·······
            }

        } catch (IOException e) {
            Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
        } finally {
            ······
        }
    }

因为初始化类时,也会把类中的static结构初始化。
android.graphics.Typeface
    static {
        init();
        // Set up defaults and typefaces exposed in public API
        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,
            create((String) null, Typeface.ITALIC),
            create((String) null, Typeface.BOLD_ITALIC),
        };

    }
    
    private static File getSystemFontConfigLocation() {
        return new File("/system/etc/");
    }

    static final String FONTS_CONFIG = "fonts.xml";

    private static void init() {
        // Load font config and initialize Minikin state
        File systemFontConfigLocation = getSystemFontConfigLocation();
        File configFilename = new File(systemFontConfigLocation, FONTS_CONFIG);
        try {
            FileInputStream fontsIn = new FileInputStream(configFilename);
            FontListParser.Config fontConfig = FontListParser.parse(fontsIn);

            Map<String, ByteBuffer> bufferForPath = new HashMap<String, ByteBuffer>();

            List<FontFamily> familyList = new ArrayList<FontFamily>();
            // Note that the default typeface is always present in the fallback list;
            // this is an enhancement from pre-Minikin behavior.
            for (int i = 0; i < fontConfig.families.size(); i++) {
                FontListParser.Family f = fontConfig.families.get(i);
                if (i == 0 || f.name == null) {
                    familyList.add(makeFamilyFromParsed(f, bufferForPath));
                }
            }
            sFallbackFonts = familyList.toArray(new FontFamily[familyList.size()]);
            setDefault(Typeface.createFromFamilies(sFallbackFonts));

            Map<String, Typeface> systemFonts = new HashMap<String, Typeface>();
            for (int i = 0; i < fontConfig.families.size(); i++) {
                Typeface typeface;
                FontListParser.Family f = fontConfig.families.get(i);
                if (f.name != null) {
                    if (i == 0) {
                        // The first entry is the default typeface; no sense in
                        // duplicating the corresponding FontFamily.
                        typeface = sDefaultTypeface;
                    } else {
                        FontFamily fontFamily = makeFamilyFromParsed(f, bufferForPath);
                        FontFamily[] families = { fontFamily };
                        typeface = Typeface.createFromFamiliesWithDefault(families);
                    }
                    systemFonts.put(f.name, typeface);
                }
            }
            for (FontListParser.Alias alias : fontConfig.aliases) {
                Typeface base = systemFonts.get(alias.toName);
                Typeface newFace = base;
                int weight = alias.weight;
                if (weight != 400) {
                    newFace = new Typeface(nativeCreateWeightAlias(base.native_instance, weight));
                }
                systemFonts.put(alias.name, newFace);
            }
            sSystemFontMap = systemFonts;//sSystemFontMap数据来源于/system/etc/fonts.xml

        } catch (RuntimeException e) {
            Log.w(TAG, "Didn't create default family (most likely, non-Minikin build)", e);
            // TODO: normal in non-Minikin case, remove or make error when Minikin-only
        } catch (FileNotFoundException e) {
            Log.e(TAG, "Error opening " + configFilename, e);
        } catch (IOException e) {
            Log.e(TAG, "Error reading " + configFilename, e);
        } catch (XmlPullParserException e) {
            Log.e(TAG, "XML parse exception for " + configFilename, e);
        }
    }

总结:
尽管/system/fonts中有很多字体,但是如果/system/etc/fonts.xml中没有引用。
如果其他app也没有调用,那文件就是僵尸文件,完全可裁剪。

3.解读fonts.xml

1)fonts.xml来源于
frameworks\base\data\fonts\fonts.xml

2)
    <family lang="zh-Hans">
        <font weight="400" style="normal" index="2">NotoSansCJK-Regular.ttc</font>
    </family>
    
    lang对应的是支持的国家
    特别注意:'und' for 'undetermined'.
    frameworks/base/tools/fonts/fontchain_lint.py 涉及uud-**的转化

3) 支持的列表,可查:
external/skia/src/sfnt/SKOTTable_name.cpp  有对应的国家列表
frameworks/base/core/res/res/values/locale_config.xml  有对应的国家列表

相关文章

网友评论

      本文标题:Android裁剪之fonts(字体库)浅析

      本文链接:https://www.haomeiwen.com/subject/rtpthrtx.html