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

Commit 55b6a818 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Check updatable font dir in FontListParser."

parents 368efbc3 87036d61
Loading
Loading
Loading
Loading
+51 −14
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ public class TypefaceSystemFallbackTest {
    private static final String TEST_FONT_DIR;
    private static final String TEST_OEM_XML;
    private static final String TEST_OEM_DIR;
    private static final String TEST_UPDATABLE_FONT_DIR;

    private static final float GLYPH_1EM_WIDTH;
    private static final float GLYPH_2EM_WIDTH;
@@ -82,9 +83,11 @@ public class TypefaceSystemFallbackTest {
        TEST_FONTS_XML = new File(cacheDir, "fonts.xml").getAbsolutePath();
        TEST_OEM_DIR = cacheDir.getAbsolutePath() + "/oem_fonts/";
        TEST_OEM_XML = new File(cacheDir, "fonts_customization.xml").getAbsolutePath();
        TEST_UPDATABLE_FONT_DIR = cacheDir.getAbsolutePath() + "/updatable_fonts/";

        new File(TEST_FONT_DIR).mkdirs();
        new File(TEST_OEM_DIR).mkdirs();
        new File(TEST_UPDATABLE_FONT_DIR).mkdirs();

        final AssetManager am =
                InstrumentationRegistry.getInstrumentation().getContext().getAssets();
@@ -103,18 +106,11 @@ public class TypefaceSystemFallbackTest {
                InstrumentationRegistry.getInstrumentation().getContext().getAssets();
        for (final String fontFile : TEST_FONT_FILES) {
            final String sourceInAsset = "fonts/" + fontFile;
            final File outInCache = new File(TEST_FONT_DIR, fontFile);
            try (InputStream is = am.open(sourceInAsset)) {
                Files.copy(is, outInCache.toPath(), StandardCopyOption.REPLACE_EXISTING);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            final File outOemInCache = new File(TEST_OEM_DIR, fontFile);
            try (InputStream is = am.open(sourceInAsset)) {
                Files.copy(is, outOemInCache.toPath(), StandardCopyOption.REPLACE_EXISTING);
            } catch (IOException e) {
                throw new RuntimeException(e);
            copyAssetToFile(sourceInAsset, new File(TEST_FONT_DIR, fontFile));
            copyAssetToFile(sourceInAsset, new File(TEST_OEM_DIR, fontFile));
        }
        for (final File fontFile : new File(TEST_UPDATABLE_FONT_DIR).listFiles()) {
            fontFile.delete();
        }
    }

@@ -124,7 +120,20 @@ public class TypefaceSystemFallbackTest {
            final File outInCache = new File(TEST_FONT_DIR, fontFile);
            outInCache.delete();
            final File outOemInCache = new File(TEST_OEM_DIR, fontFile);
            outInCache.delete();
            outOemInCache.delete();
        }
        for (final File fontFile : new File(TEST_UPDATABLE_FONT_DIR).listFiles()) {
            fontFile.delete();
        }
    }

    private static void copyAssetToFile(String sourceInAsset, File out) {
        final AssetManager am =
                InstrumentationRegistry.getInstrumentation().getContext().getAssets();
        try (InputStream is = am.open(sourceInAsset)) {
            Files.copy(is, out.toPath(), StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

@@ -138,7 +147,7 @@ public class TypefaceSystemFallbackTest {
        }

        final FontConfig.Alias[] aliases = SystemFonts.buildSystemFallback(TEST_FONTS_XML,
                TEST_FONT_DIR, oemCustomization, fallbackMap);
                TEST_FONT_DIR, TEST_UPDATABLE_FONT_DIR, oemCustomization, fallbackMap);
        Typeface.initSystemDefaultTypefaces(fontMap, fallbackMap, aliases);
    }

@@ -835,4 +844,32 @@ public class TypefaceSystemFallbackTest {
                + "</fonts-modification>";
        readFontCustomization(oemXml);
    }


    @Test
    public void testBuildSystemFallback_UpdatableFont() {
        final String xml = "<?xml version='1.0' encoding='UTF-8'?>"
                + "<familyset>"
                + "  <family name='test'>"
                + "    <font weight='400' style='normal'>a3em.ttf</font>"
                + "  </family>"
                + "</familyset>";
        final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
        final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
        final FontCustomizationParser.Result oemCustomization =
                new FontCustomizationParser.Result();

        // Install all2em.ttf as a3em.ttf
        copyAssetToFile("fonts/all2em.ttf", new File(TEST_UPDATABLE_FONT_DIR, "a3em.ttf"));
        buildSystemFallback(xml, oemCustomization, fontMap, fallbackMap);

        final Paint paint = new Paint();

        final Typeface sansSerifTypeface = fontMap.get("test");
        assertNotNull(sansSerifTypeface);
        paint.setTypeface(sansSerifTypeface);
        assertEquals(GLYPH_2EM_WIDTH, paint.measureText("a"), 0.0f);
        assertEquals(GLYPH_2EM_WIDTH, paint.measureText("b"), 0.0f);
        assertEquals(GLYPH_2EM_WIDTH, paint.measureText("c"), 0.0f);
    }
}
+27 −13
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.graphics;

import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.fonts.FontVariationAxis;
import android.os.Build;
@@ -25,6 +26,7 @@ import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
@@ -41,26 +43,26 @@ public class FontListParser {
    /* Parse fallback list (no names) */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public static FontConfig parse(InputStream in) throws XmlPullParserException, IOException {
        return parse(in, "/system/fonts");
        return parse(in, "/system/fonts", null);
    }

    /**
     * Parse the fonts.xml
     */
    public static FontConfig parse(InputStream in, String fontDir)
            throws XmlPullParserException, IOException {
    public static FontConfig parse(InputStream in, String fontDir,
            @Nullable String updatableFontDir) throws XmlPullParserException, IOException {
        try {
            XmlPullParser parser = Xml.newPullParser();
            parser.setInput(in, null);
            parser.nextTag();
            return readFamilies(parser, fontDir);
            return readFamilies(parser, fontDir, updatableFontDir);
        } finally {
            in.close();
        }
    }

    private static FontConfig readFamilies(XmlPullParser parser, String fontDir)
            throws XmlPullParserException, IOException {
    private static FontConfig readFamilies(XmlPullParser parser, String fontDir,
            @Nullable String updatableFontDir) throws XmlPullParserException, IOException {
        List<FontConfig.Family> families = new ArrayList<>();
        List<FontConfig.Alias> aliases = new ArrayList<>();

@@ -69,7 +71,7 @@ public class FontListParser {
            if (parser.getEventType() != XmlPullParser.START_TAG) continue;
            String tag = parser.getName();
            if (tag.equals("family")) {
                families.add(readFamily(parser, fontDir));
                families.add(readFamily(parser, fontDir, updatableFontDir));
            } else if (tag.equals("alias")) {
                aliases.add(readAlias(parser));
            } else {
@@ -83,8 +85,8 @@ public class FontListParser {
    /**
     * Reads a family element
     */
    public static FontConfig.Family readFamily(XmlPullParser parser, String fontDir)
            throws XmlPullParserException, IOException {
    public static FontConfig.Family readFamily(XmlPullParser parser, String fontDir,
            @Nullable String updatableFontDir) throws XmlPullParserException, IOException {
        final String name = parser.getAttributeValue(null, "name");
        final String lang = parser.getAttributeValue("", "lang");
        final String variant = parser.getAttributeValue(null, "variant");
@@ -93,7 +95,7 @@ public class FontListParser {
            if (parser.getEventType() != XmlPullParser.START_TAG) continue;
            final String tag = parser.getName();
            if (tag.equals("font")) {
                fonts.add(readFont(parser, fontDir));
                fonts.add(readFont(parser, fontDir, updatableFontDir));
            } else {
                skip(parser);
            }
@@ -114,8 +116,8 @@ public class FontListParser {
    private static final Pattern FILENAME_WHITESPACE_PATTERN =
            Pattern.compile("^[ \\n\\r\\t]+|[ \\n\\r\\t]+$");

    private static FontConfig.Font readFont(XmlPullParser parser, String fontDir)
            throws XmlPullParserException, IOException {
    private static FontConfig.Font readFont(XmlPullParser parser, String fontDir,
            @Nullable String updatableFontDir) throws XmlPullParserException, IOException {
        String indexStr = parser.getAttributeValue(null, "index");
        int index = indexStr == null ? 0 : Integer.parseInt(indexStr);
        List<FontVariationAxis> axes = new ArrayList<FontVariationAxis>();
@@ -137,10 +139,22 @@ public class FontListParser {
            }
        }
        String sanitizedName = FILENAME_WHITESPACE_PATTERN.matcher(filename).replaceAll("");
        return new FontConfig.Font(fontDir + sanitizedName, index, axes.toArray(
        String fontName = findFontFile(sanitizedName, fontDir, updatableFontDir);
        return new FontConfig.Font(fontName, index, axes.toArray(
                new FontVariationAxis[axes.size()]), weight, isItalic, fallbackFor);
    }

    private static String findFontFile(String fileName, String fontDir,
            @Nullable String updatableFontDir) {
        if (updatableFontDir != null) {
            String updatableFontName = updatableFontDir + fileName;
            if (new File(updatableFontName).exists()) {
                return updatableFontName;
            }
        }
        return fontDir + fileName;
    }

    private static FontVariationAxis readAxis(XmlPullParser parser)
            throws XmlPullParserException, IOException {
        String tagStr = parser.getAttributeValue(null, "tag");
+1 −1
Original line number Diff line number Diff line
@@ -97,7 +97,7 @@ public class FontCustomizationParser {
            throw new IllegalArgumentException("customizationType must be specified");
        }
        if (customizationType.equals("new-named-family")) {
            out.mAdditionalNamedFamilies.add(FontListParser.readFamily(parser, fontDir));
            out.mAdditionalNamedFamilies.add(FontListParser.readFamily(parser, fontDir, null));
        } else {
            throw new IllegalArgumentException("Unknown customizationType=" + customizationType);
        }
+27 −3
Original line number Diff line number Diff line
@@ -91,7 +91,9 @@ public final class SystemFonts {
        final FontCustomizationParser.Result oemCustomization =
                readFontCustomization("/product/etc/fonts_customization.xml", "/product/fonts/");
        Map<String, FontFamily[]> map = new ArrayMap<>();
        buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/", oemCustomization, map);
        // TODO: use updated fonts
        buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/", null /* updatableFontDir */,
                oemCustomization, map);
        Set<Font> res = new HashSet<>();
        for (FontFamily[] families : map.values()) {
            for (FontFamily family : families) {
@@ -225,12 +227,27 @@ public final class SystemFonts {
        fallbackListMap.put(familyName, fallback);
    }

    /**
     * @see #buildSystemFallback(String, String, String, FontCustomizationParser.Result, Map)
     * @hide
     */
    @VisibleForTesting
    public static FontConfig.Alias[] buildSystemFallback(@NonNull String xmlPath,
            @NonNull String fontDir,
            @NonNull FontCustomizationParser.Result oemCustomization,
            @NonNull Map<String, FontFamily[]> fallbackMap) {
        return buildSystemFallback(xmlPath, fontDir, null /* updatableFontDir */,
                oemCustomization, fallbackMap);
    }

    /**
     * Build the system fallback from xml file.
     *
     * @param xmlPath A full path string to the fonts.xml file.
     * @param fontDir A full path string to the system font directory. This must end with
     *                slash('/').
     * @param updatableFontDir A full path string to the updatable system font directory. This
     *                           must end with slash('/').
     * @param fallbackMap An output system fallback map. Caller must pass empty map.
     * @return a list of aliases
     * @hide
@@ -238,11 +255,12 @@ public final class SystemFonts {
    @VisibleForTesting
    public static FontConfig.Alias[] buildSystemFallback(@NonNull String xmlPath,
            @NonNull String fontDir,
            @Nullable String updatableFontDir,
            @NonNull FontCustomizationParser.Result oemCustomization,
            @NonNull Map<String, FontFamily[]> fallbackMap) {
        try {
            final FileInputStream fontsIn = new FileInputStream(xmlPath);
            final FontConfig fontConfig = FontListParser.parse(fontsIn, fontDir);
            final FontConfig fontConfig = FontListParser.parse(fontsIn, fontDir, updatableFontDir);

            final HashMap<String, ByteBuffer> bufferCache = new HashMap<String, ByteBuffer>();
            final FontConfig.Family[] xmlFamilies = fontConfig.getFamilies();
@@ -306,11 +324,17 @@ public final class SystemFonts {
    /** @hide */
    public static @NonNull Pair<FontConfig.Alias[], Map<String, FontFamily[]>>
            initializePreinstalledFonts() {
        return initializeSystemFonts(null);
    }

    /** @hide */
    public static Pair<FontConfig.Alias[], Map<String, FontFamily[]>>
            initializeSystemFonts(@Nullable String updatableFontDir) {
        final FontCustomizationParser.Result oemCustomization =
                readFontCustomization("/product/etc/fonts_customization.xml", "/product/fonts/");
        Map<String, FontFamily[]> map = new ArrayMap<>();
        FontConfig.Alias[] aliases = buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/",
                oemCustomization, map);
                updatableFontDir, oemCustomization, map);
        synchronized (LOCK) {
            sFamilyMap = map;
        }