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

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

Merge "Decouple font collection logic from fallback building logic"

parents 257ac460 48230317
Loading
Loading
Loading
Loading
+3 −6
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ import static org.junit.Assert.assertTrue;

import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.fonts.Font;
import android.graphics.fonts.FontCustomizationParser;
import android.graphics.fonts.FontFamily;
import android.graphics.fonts.SystemFonts;
@@ -49,7 +48,6 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Locale;

@SmallTest
@@ -133,14 +131,14 @@ public class TypefaceSystemFallbackTest {
    private static void buildSystemFallback(String xml,
            FontCustomizationParser.Result oemCustomization, ArrayMap<String, Typeface> fontMap,
            ArrayMap<String, FontFamily[]> fallbackMap) {
        final ArrayList<Font> availableFonts = new ArrayList<>();
        try (FileOutputStream fos = new FileOutputStream(TEST_FONTS_XML)) {
            fos.write(xml.getBytes(Charset.forName("UTF-8")));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

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

@@ -156,12 +154,11 @@ public class TypefaceSystemFallbackTest {
    public void testBuildSystemFallback() {
        final ArrayMap<String, Typeface> fontMap = new ArrayMap<>();
        final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
        final ArrayList<Font> availableFonts = new ArrayList<>();
        final FontCustomizationParser.Result oemCustomization =
                new FontCustomizationParser.Result();

        final FontConfig.Alias[] aliases = SystemFonts.buildSystemFallback(SYSTEM_FONTS_XML,
                SYSTEM_FONT_DIR, oemCustomization, fallbackMap, availableFonts);
                SYSTEM_FONT_DIR, oemCustomization, fallbackMap);

        assertNotNull(aliases);
        assertFalse(fallbackMap.isEmpty());
+6 −2
Original line number Diff line number Diff line
@@ -23,8 +23,11 @@ import static org.junit.Assert.assertTrue;
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.graphics.fonts.FontFamily;
import android.graphics.fonts.SystemFonts;
import android.os.SharedMemory;
import android.text.FontConfig;
import android.util.Pair;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
@@ -195,8 +198,9 @@ public class TypefaceTest {
    @Test
    public void testSerialize() throws Exception {
        HashMap<String, Typeface> systemFontMap = new HashMap<>();
        Typeface.initSystemDefaultTypefaces(systemFontMap, SystemFonts.getRawSystemFallbackMap(),
                SystemFonts.getAliases());
        Pair<FontConfig.Alias[], Map<String, FontFamily[]>> res =
                SystemFonts.initializePreinstalledFonts();
        Typeface.initSystemDefaultTypefaces(systemFontMap, res.second, res.first);
        SharedMemory sharedMemory = Typeface.serializeFontMap(systemFontMap);
        Map<String, Typeface> copiedFontMap =
                Typeface.deserializeFontMap(sharedMemory.mapReadOnly().order(ByteOrder.BIG_ENDIAN));
+1 −4
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ import android.annotation.NonNull;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Typeface;
import android.graphics.fonts.Font;
import android.graphics.fonts.FontCustomizationParser;
import android.graphics.fonts.FontFamily;
import android.graphics.fonts.SystemFonts;
@@ -35,7 +34,6 @@ import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;

public class FontFallbackSetup implements AutoCloseable {
    private final String[] mTestFontFiles;
@@ -78,11 +76,10 @@ public class FontFallbackSetup implements AutoCloseable {
        }

        final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>();
        final ArrayList<Font> availableFonts = new ArrayList<>();
        final FontCustomizationParser.Result oemCustomization =
                new FontCustomizationParser.Result();
        final FontConfig.Alias[] aliases = SystemFonts.buildSystemFallback(testFontsXml,
                mTestFontsDir, oemCustomization, fallbackMap, availableFonts);
                mTestFontsDir, oemCustomization, fallbackMap);
        Typeface.initSystemDefaultTypefaces(mFontMap, fallbackMap, aliases);
    }

+4 −2
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import android.text.FontConfig;
import android.util.Base64;
import android.util.LongSparseArray;
import android.util.LruCache;
import android.util.Pair;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
@@ -1321,8 +1322,9 @@ public class Typeface {
    /** @hide */
    public static void loadPreinstalledSystemFontMap() {
        final HashMap<String, Typeface> systemFontMap = new HashMap<>();
        initSystemDefaultTypefaces(systemFontMap, SystemFonts.getRawSystemFallbackMap(),
                SystemFonts.getAliases());
        Pair<FontConfig.Alias[], Map<String, FontFamily[]>> pair =
                SystemFonts.initializePreinstalledFonts();
        initSystemDefaultTypefaces(systemFontMap, pair.second, pair.first);
        setSystemFontMap(systemFontMap);
    }

+41 −47
Original line number Diff line number Diff line
@@ -22,7 +22,9 @@ import android.graphics.FontListParser;
import android.text.FontConfig;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Pair;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;

@@ -51,9 +53,9 @@ public final class SystemFonts {

    private SystemFonts() {}  // Do not instansiate.

    private static final Map<String, FontFamily[]> sSystemFallbackMap;
    private static final FontConfig.Alias[] sAliases;
    private static final List<Font> sAvailableFonts;
    private static final Object LOCK = new Object();
    private static @GuardedBy("sLock") Set<Font> sAvailableFonts;
    private static @GuardedBy("sLock") Map<String, FontFamily[]> sFamilyMap;

    /**
     * Returns all available font files in the system.
@@ -61,29 +63,24 @@ public final class SystemFonts {
     * @return a set of system fonts
     */
    public static @NonNull Set<Font> getAvailableFonts() {
        HashSet<Font> set = new HashSet<>();
        set.addAll(sAvailableFonts);
        return set;
        synchronized (LOCK) {
            if (sAvailableFonts != null) {
                return sAvailableFonts;
            }

    /**
     * Returns raw system fallback map.
     *
     * This method is intended to be used only by Typeface static initializer.
     * @hide
     */
    public static @NonNull Map<String, FontFamily[]> getRawSystemFallbackMap() {
        return sSystemFallbackMap;
            Set<Font> set = new HashSet<>();

            for (FontFamily[] items : sFamilyMap.values()) {
                for (FontFamily family : items) {
                    for (int i = 0; i < family.getSize(); ++i) {
                        set.add(family.getFont(i));
                    }
                }
            }

    /**
     * Returns a list of aliases.
     *
     * This method is intended to be used only by Typeface static initializer.
     * @hide
     */
    public static @NonNull FontConfig.Alias[] getAliases() {
        return sAliases;
            sAvailableFonts = Collections.unmodifiableSet(set);
            return sAvailableFonts;
        }
    }

    private static @Nullable ByteBuffer mmap(@NonNull String fullPath) {
@@ -98,8 +95,7 @@ public final class SystemFonts {

    private static void pushFamilyToFallback(@NonNull FontConfig.Family xmlFamily,
            @NonNull ArrayMap<String, ArrayList<FontFamily>> fallbackMap,
            @NonNull Map<String, ByteBuffer> cache,
            @NonNull ArrayList<Font> availableFonts) {
            @NonNull Map<String, ByteBuffer> cache) {

        final String languageTags = xmlFamily.getLanguages();
        final int variant = xmlFamily.getVariant();
@@ -123,7 +119,7 @@ public final class SystemFonts {
        }

        final FontFamily defaultFamily = defaultFonts.isEmpty() ? null : createFontFamily(
                xmlFamily.getName(), defaultFonts, languageTags, variant, cache, availableFonts);
                xmlFamily.getName(), defaultFonts, languageTags, variant, cache);

        // Insert family into fallback map.
        for (int i = 0; i < fallbackMap.size(); i++) {
@@ -135,8 +131,7 @@ public final class SystemFonts {
                }
            } else {
                final FontFamily family = createFontFamily(
                        xmlFamily.getName(), fallback, languageTags, variant, cache,
                        availableFonts);
                        xmlFamily.getName(), fallback, languageTags, variant, cache);
                if (family != null) {
                    fallbackMap.valueAt(i).add(family);
                } else if (defaultFamily != null) {
@@ -152,8 +147,7 @@ public final class SystemFonts {
            @NonNull List<FontConfig.Font> fonts,
            @NonNull String languageTags,
            @FontConfig.Family.Variant int variant,
            @NonNull Map<String, ByteBuffer> cache,
            @NonNull ArrayList<Font> availableFonts) {
            @NonNull Map<String, ByteBuffer> cache) {
        if (fonts.size() == 0) {
            return null;
        }
@@ -187,7 +181,6 @@ public final class SystemFonts {
                throw new RuntimeException(e);  // Never reaches here
            }

            availableFonts.add(font);
            if (b == null) {
                b = new FontFamily.Builder(font);
            } else {
@@ -199,12 +192,11 @@ public final class SystemFonts {

    private static void appendNamedFamily(@NonNull FontConfig.Family xmlFamily,
            @NonNull HashMap<String, ByteBuffer> bufferCache,
            @NonNull ArrayMap<String, ArrayList<FontFamily>> fallbackListMap,
            @NonNull ArrayList<Font> availableFonts) {
            @NonNull ArrayMap<String, ArrayList<FontFamily>> fallbackListMap) {
        final String familyName = xmlFamily.getName();
        final FontFamily family = createFontFamily(
                familyName, Arrays.asList(xmlFamily.getFonts()),
                xmlFamily.getLanguages(), xmlFamily.getVariant(), bufferCache, availableFonts);
                xmlFamily.getLanguages(), xmlFamily.getVariant(), bufferCache);
        if (family == null) {
            return;
        }
@@ -227,8 +219,7 @@ public final class SystemFonts {
    public static FontConfig.Alias[] buildSystemFallback(@NonNull String xmlPath,
            @NonNull String fontDir,
            @NonNull FontCustomizationParser.Result oemCustomization,
            @NonNull ArrayMap<String, FontFamily[]> fallbackMap,
            @NonNull ArrayList<Font> availableFonts) {
            @NonNull Map<String, FontFamily[]> fallbackMap) {
        try {
            final FileInputStream fontsIn = new FileInputStream(xmlPath);
            final FontConfig fontConfig = FontListParser.parse(fontsIn, fontDir);
@@ -243,12 +234,12 @@ public final class SystemFonts {
                if (familyName == null) {
                    continue;
                }
                appendNamedFamily(xmlFamily, bufferCache, fallbackListMap, availableFonts);
                appendNamedFamily(xmlFamily, bufferCache, fallbackListMap);
            }

            for (int i = 0; i < oemCustomization.mAdditionalNamedFamilies.size(); ++i) {
                appendNamedFamily(oemCustomization.mAdditionalNamedFamilies.get(i),
                        bufferCache, fallbackListMap, availableFonts);
                        bufferCache, fallbackListMap);
            }

            // Then, add fallback fonts to the each fallback map.
@@ -257,7 +248,7 @@ public final class SystemFonts {
                // The first family (usually the sans-serif family) is always placed immediately
                // after the primary family in the fallback.
                if (i == 0 || xmlFamily.getName() == null) {
                    pushFamilyToFallback(xmlFamily, fallbackListMap, bufferCache, availableFonts);
                    pushFamilyToFallback(xmlFamily, fallbackListMap, bufferCache);
                }
            }

@@ -292,14 +283,17 @@ public final class SystemFonts {
        }
    }

    static {
        final ArrayMap<String, FontFamily[]> systemFallbackMap = new ArrayMap<>();
        final ArrayList<Font> availableFonts = new ArrayList<>();
    /** @hide */
    public static @NonNull Pair<FontConfig.Alias[], Map<String, FontFamily[]>>
            initializePreinstalledFonts() {
        final FontCustomizationParser.Result oemCustomization =
                readFontCustomization("/product/etc/fonts_customization.xml", "/product/fonts/");
        sAliases = buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/",
                oemCustomization, systemFallbackMap, availableFonts);
        sSystemFallbackMap = Collections.unmodifiableMap(systemFallbackMap);
        sAvailableFonts = Collections.unmodifiableList(availableFonts);
        Map<String, FontFamily[]> map = new ArrayMap<>();
        FontConfig.Alias[] aliases = buildSystemFallback("/system/etc/fonts.xml", "/system/fonts/",
                oemCustomization, map);
        synchronized (LOCK) {
            sFamilyMap = map;
        }
        return new Pair(aliases, map);
    }
}