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

Commit ebb3b96c authored by Seigo Nonaka's avatar Seigo Nonaka Committed by Android (Google) Code Review
Browse files

Merge "Redesign the fallback XML syntax to be able to have static and variable font." into main

parents 0744deb6 4035d7e5
Loading
Loading
Loading
Loading
+38 −26
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.fonts.FontFamily.Builder.VariableFontFamilyType;
import android.graphics.fonts.FontStyle;
import android.graphics.fonts.FontVariationAxis;
import android.icu.util.ULocale;
@@ -240,6 +239,23 @@ public final class FontConfig implements Parcelable {
        private final @IntRange(from = 0) int mIndex;
        private final @NonNull String mFontVariationSettings;
        private final @Nullable String mFontFamilyName;
        private final @VarTypeAxes int mVarTypeAxes;

        /** @hide */
        @Retention(SOURCE)
        @IntDef(prefix = { "VAR_TYPE_AXES_" }, value = {
                VAR_TYPE_AXES_NONE,
                VAR_TYPE_AXES_WGHT,
                VAR_TYPE_AXES_ITAL,
        })
        public @interface VarTypeAxes {}

        /** @hide */
        public static final int VAR_TYPE_AXES_NONE = 0;
        /** @hide */
        public static final int VAR_TYPE_AXES_WGHT = 1;
        /** @hide */
        public static final int VAR_TYPE_AXES_ITAL = 2;

        /**
         * Construct a Font instance.
@@ -248,7 +264,8 @@ public final class FontConfig implements Parcelable {
         */
        public Font(@NonNull File file, @Nullable File originalFile, @NonNull String postScriptName,
                @NonNull FontStyle style, @IntRange(from = 0) int index,
                @NonNull String fontVariationSettings, @Nullable String fontFamilyName) {
                @NonNull String fontVariationSettings, @Nullable String fontFamilyName,
                @VarTypeAxes int varTypeAxes) {
            mFile = file;
            mOriginalFile = originalFile;
            mPostScriptName = postScriptName;
@@ -256,6 +273,7 @@ public final class FontConfig implements Parcelable {
            mIndex = index;
            mFontVariationSettings = fontVariationSettings;
            mFontFamilyName = fontFamilyName;
            mVarTypeAxes = varTypeAxes;
        }

        @Override
@@ -273,6 +291,7 @@ public final class FontConfig implements Parcelable {
            dest.writeInt(mIndex);
            dest.writeString8(mFontVariationSettings);
            dest.writeString8(mFontFamilyName);
            dest.writeInt(mVarTypeAxes);
        }

        public static final @NonNull Creator<Font> CREATOR = new Creator<Font>() {
@@ -288,9 +307,10 @@ public final class FontConfig implements Parcelable {
                int index = source.readInt();
                String varSettings = source.readString8();
                String fallback = source.readString8();
                int varTypeAxes = source.readInt();

                return new Font(path, originalPath, postScriptName, new FontStyle(weight, slant),
                        index, varSettings, fallback);
                        index, varSettings, fallback, varTypeAxes);
            }

            @Override
@@ -365,6 +385,15 @@ public final class FontConfig implements Parcelable {
            return mPostScriptName;
        }

        /**
         * Returns the list of supported axes tags for variable family type resolution.
         *
         * @hide
         */
        public @VarTypeAxes int getVarTypeAxes() {
            return mVarTypeAxes;
        }

        /**
         * Returns the list of axes associated to this font.
         * @deprecated Use getFontVariationSettings
@@ -408,13 +437,14 @@ public final class FontConfig implements Parcelable {
                    && Objects.equals(mOriginalFile, font.mOriginalFile)
                    && Objects.equals(mStyle, font.mStyle)
                    && Objects.equals(mFontVariationSettings, font.mFontVariationSettings)
                    && Objects.equals(mFontFamilyName, font.mFontFamilyName);
                    && Objects.equals(mFontFamilyName, font.mFontFamilyName)
                    && mVarTypeAxes == font.mVarTypeAxes;
        }

        @Override
        public int hashCode() {
            return Objects.hash(mFile, mOriginalFile, mStyle, mIndex, mFontVariationSettings,
                    mFontFamilyName);
                    mFontFamilyName, mVarTypeAxes);
        }

        @Override
@@ -426,6 +456,7 @@ public final class FontConfig implements Parcelable {
                    + ", mIndex=" + mIndex
                    + ", mFontVariationSettings='" + mFontVariationSettings + '\''
                    + ", mFontFamilyName='" + mFontFamilyName + '\''
                    + ", mVarTypeAxes='" + mVarTypeAxes + '\''
                    + '}';
        }
    }
@@ -549,7 +580,6 @@ public final class FontConfig implements Parcelable {
        private final @NonNull List<Font> mFonts;
        private final @NonNull LocaleList mLocaleList;
        private final @Variant int mVariant;
        private final int mVariableFontFamilyType;

        /** @hide */
        @Retention(SOURCE)
@@ -589,11 +619,10 @@ public final class FontConfig implements Parcelable {
         * @hide Only system server can create this instance and passed via IPC.
         */
        public FontFamily(@NonNull List<Font> fonts, @NonNull LocaleList localeList,
                @Variant int variant, int variableFontFamilyType) {
                @Variant int variant) {
            mFonts = fonts;
            mLocaleList = localeList;
            mVariant = variant;
            mVariableFontFamilyType = variableFontFamilyType;
        }

        /**
@@ -644,20 +673,6 @@ public final class FontConfig implements Parcelable {
            return mVariant;
        }

        /**
         * Returns the font family type.
         *
         * @see Builder#VARIABLE_FONT_FAMILY_TYPE_NONE
         * @see Builder#VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ITAL
         * @see Builder#VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ONLY
         * @see Builder#VARIABLE_FONT_FAMILY_TYPE_TWO_FONTS_WGHT
         * @hide
         * @return variable font family type.
         */
        public @VariableFontFamilyType int getVariableFontFamilyType() {
            return mVariableFontFamilyType;
        }

        @Override
        public int describeContents() {
            return 0;
@@ -668,7 +683,6 @@ public final class FontConfig implements Parcelable {
            dest.writeTypedList(mFonts, flags);
            dest.writeString8(mLocaleList.toLanguageTags());
            dest.writeInt(mVariant);
            dest.writeInt(mVariableFontFamilyType);
        }

        public static final @NonNull Creator<FontFamily> CREATOR = new Creator<FontFamily>() {
@@ -679,10 +693,8 @@ public final class FontConfig implements Parcelable {
                source.readTypedList(fonts, Font.CREATOR);
                String langTags = source.readString8();
                int variant = source.readInt();
                int varFamilyType = source.readInt();

                return new FontFamily(fonts, LocaleList.forLanguageTags(langTags), variant,
                        varFamilyType);
                return new FontFamily(fonts, LocaleList.forLanguageTags(langTags), variant);
            }

            @Override
+105 −34
Original line number Diff line number Diff line
@@ -22,14 +22,18 @@ import static android.graphics.fonts.FontStyle.FONT_WEIGHT_NORMAL;
import static android.text.FontConfig.FontFamily.VARIANT_COMPACT;
import static android.text.FontConfig.FontFamily.VARIANT_DEFAULT;
import static android.text.FontConfig.FontFamily.VARIANT_ELEGANT;
import static android.graphics.fonts.FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE;
import static android.graphics.fonts.FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ONLY;
import static android.graphics.fonts.FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ITAL;
import static android.graphics.fonts.FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_TWO_FONTS_WGHT;

import static com.google.common.truth.Truth.assertThat;

import static junit.framework.Assert.fail;

import android.graphics.fonts.FontCustomizationParser;
import android.graphics.fonts.FontFamily;
import android.graphics.fonts.FontStyle;
import android.graphics.fonts.SystemFonts;
import android.os.LocaleList;
import android.text.FontConfig;
import android.util.Xml;
@@ -64,9 +68,9 @@ public final class FontListParserTest {
        FontConfig.NamedFamilyList expected = new FontConfig.NamedFamilyList(
                Collections.singletonList(new FontConfig.FontFamily(
                    Arrays.asList(new FontConfig.Font(new File("test.ttf"), null, "test",
                        new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 0, "", null)),
                    LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT,
                        FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE)), "sans-serif");
                            new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 0, "", null,
                            FontConfig.Font.VAR_TYPE_AXES_NONE)),
                    LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT)), "sans-serif");
        FontConfig.NamedFamilyList family = readNamedFamily(xml);
        assertThat(family).isEqualTo(expected);
    }
@@ -82,12 +86,11 @@ public final class FontListParserTest {
                Arrays.asList(
                        new FontConfig.Font(new File("test.ttf"), null, "test",
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                0, "", null),
                                0, "", null, FontConfig.Font.VAR_TYPE_AXES_NONE),
                        new FontConfig.Font(new File("test.ttf"), null, "test",
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                0, "", "serif")),
                LocaleList.forLanguageTags("en"), VARIANT_DEFAULT,
                FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE);
                                0, "", "serif", FontConfig.Font.VAR_TYPE_AXES_NONE)),
                LocaleList.forLanguageTags("en"), VARIANT_DEFAULT);

        FontConfig.FontFamily family = readFamily(xml);
        assertThat(family).isEqualTo(expected);
@@ -103,9 +106,8 @@ public final class FontListParserTest {
                Arrays.asList(
                        new FontConfig.Font(new File("test.ttf"), null, "test",
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                0, "", null)),
                LocaleList.forLanguageTags("en"), VARIANT_COMPACT,
                FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE);
                                0, "", null, FontConfig.Font.VAR_TYPE_AXES_NONE)),
                LocaleList.forLanguageTags("en"), VARIANT_COMPACT);

        FontConfig.FontFamily family = readFamily(xml);
        assertThat(family).isEqualTo(expected);
@@ -121,9 +123,8 @@ public final class FontListParserTest {
                Arrays.asList(
                        new FontConfig.Font(new File("test.ttf"), null, "test",
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                0, "", null)),
                LocaleList.forLanguageTags("en"), VARIANT_ELEGANT,
                FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE);
                                0, "", null, FontConfig.Font.VAR_TYPE_AXES_NONE)),
                LocaleList.forLanguageTags("en"), VARIANT_ELEGANT);

        FontConfig.FontFamily family = readFamily(xml);
        assertThat(family).isEqualTo(expected);
@@ -140,13 +141,15 @@ public final class FontListParserTest {
        FontConfig.NamedFamilyList expected = new FontConfig.NamedFamilyList(
                Collections.singletonList(new FontConfig.FontFamily(Arrays.asList(
                      new FontConfig.Font(new File("normal.ttf"), null, "test",
                        new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 0, "", null),
                            new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 0, "", null,
                              FontConfig.Font.VAR_TYPE_AXES_NONE),
                      new FontConfig.Font(new File("weight.ttf"), null, "test",
                        new FontStyle(100, FONT_SLANT_UPRIGHT), 0, "", null),
                            new FontStyle(100, FONT_SLANT_UPRIGHT), 0, "", null,
                              FontConfig.Font.VAR_TYPE_AXES_NONE),
                      new FontConfig.Font(new File("italic.ttf"), null, "test",
                        new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_ITALIC), 0, "", null)),
                    LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT,
                        FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE)), "sans-serif");
                            new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_ITALIC), 0, "", null,
                              FontConfig.Font.VAR_TYPE_AXES_NONE)),
                    LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT)), "sans-serif");
        FontConfig.NamedFamilyList family = readNamedFamily(xml);
        assertThat(family).isEqualTo(expected);
    }
@@ -168,12 +171,13 @@ public final class FontListParserTest {
                Collections.singletonList(new FontConfig.FontFamily(Arrays.asList(
                        new FontConfig.Font(new File("test-VF.ttf"), null, "test",
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                0, "'wdth' 100.0,'wght' 200.0", null),
                                0, "'wdth' 100.0,'wght' 200.0", null,
                                FontConfig.Font.VAR_TYPE_AXES_NONE),
                        new FontConfig.Font(new File("test-VF.ttf"), null, "test",
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                0, "'wdth' 400.0,'wght' 700.0", null)),
                        LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT,
                        FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE)),
                                0, "'wdth' 400.0,'wght' 700.0", null,
                                FontConfig.Font.VAR_TYPE_AXES_NONE)),
                        LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT)),
                "sans-serif");
        FontConfig.NamedFamilyList family = readNamedFamily(xml);
        assertThat(family).isEqualTo(expected);
@@ -190,12 +194,11 @@ public final class FontListParserTest {
                Collections.singletonList(new FontConfig.FontFamily(Arrays.asList(
                        new FontConfig.Font(new File("test.ttc"), null, "test",
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                0, "", null),
                                0, "", null, FontConfig.Font.VAR_TYPE_AXES_NONE),
                        new FontConfig.Font(new File("test.ttc"), null, "test",
                                new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT),
                                1, "", null)),
                                LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT,
                        FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE)),
                                1, "", null, FontConfig.Font.VAR_TYPE_AXES_NONE)),
                                LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT)),
                "sans-serif");
        FontConfig.NamedFamilyList family = readNamedFamily(xml);
        assertThat(family).isEqualTo(expected);
@@ -211,11 +214,12 @@ public final class FontListParserTest {
        FontConfig.NamedFamilyList expected = new FontConfig.NamedFamilyList(
                Collections.singletonList(new FontConfig.FontFamily(Arrays.asList(
                      new FontConfig.Font(new File("test.ttc"), null, "foo",
                        new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 0, "", null),
                            new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 0, "", null,
                              FontConfig.Font.VAR_TYPE_AXES_NONE),
                      new FontConfig.Font(new File("test.ttc"), null, "test",
                        new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 1, "", null)),
                    LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT,
                        FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE)), "sans-serif");
                            new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 1, "", null,
                              FontConfig.Font.VAR_TYPE_AXES_NONE)),
                    LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT)), "sans-serif");
        FontConfig.NamedFamilyList family = readNamedFamily(xml);
        assertThat(family).isEqualTo(expected);
    }
@@ -385,14 +389,81 @@ public final class FontListParserTest {
    public void varFamilyType() throws Exception {
        String xml = "<?xml version='1.0' encoding='UTF-8'?>"
                + "<familyset>"
                + "  <family name='sans-serif' varFamilyType='1'>"
                + "    <font>test.ttf</font>"
                + "  <family name='sans-serif'>"
                + "    <font supportedAxes='wght'>test.ttf</font>"
                + "    <font supportedAxes='ital'>test.ttf</font>"
                + "    <font supportedAxes='wght,ital'>test.ttf</font>"
                + "  </family>"
                + "</familyset>";
        FontConfig config = readFamilies(xml, true /* include non-existing font files */);
        List<FontConfig.FontFamily> families = config.getFontFamilies();
        assertThat(families.size()).isEqualTo(1);  // legacy one should be ignored.
        assertThat(families.get(0).getVariableFontFamilyType()).isEqualTo(1);
        assertThat(families.get(0).getFontList().get(0).getVarTypeAxes())
                .isEqualTo(FontConfig.Font.VAR_TYPE_AXES_WGHT);
        assertThat(families.get(0).getFontList().get(1).getVarTypeAxes())
                .isEqualTo(FontConfig.Font.VAR_TYPE_AXES_ITAL);
        assertThat(families.get(0).getFontList().get(2).getVarTypeAxes())
                .isEqualTo(FontConfig.Font.VAR_TYPE_AXES_WGHT | FontConfig.Font.VAR_TYPE_AXES_ITAL);
    }

    @Test
    public void varFamilyTypeRsolve() throws Exception {
        String xml = "<?xml version='1.0' encoding='UTF-8'?>"
                + "<familyset>"
                + "  <family name='sans-serif'>"
                + "    <font style='normal' supportedAxes='wght'>test.ttf</font>"
                + "  </family>"
                + "  <family>"
                + "    <font style='normal' supportedAxes='wght'>test.ttf</font>"
                + "    <font style='italic' supportedAxes='wght'>test.ttf</font>"
                + "  </family>"
                + "  <family>"
                + "    <font supportedAxes='wght,ital'>test.ttf</font>"
                + "  </family>"
                + "  <family>"
                + "    <font supportedAxes='ital'>test.ttf</font>"
                + "  </family>"
                + "  <family>"
                + "    <font>test.ttf</font>"
                + "  </family>"
                + "</familyset>";
        FontConfig config = readFamilies(xml, true /* include non-existing font files */);
        List<FontConfig.FontFamily> families = config.getFontFamilies();
        assertThat(families.size()).isEqualTo(5);
        assertThat(SystemFonts.resolveVarFamilyType(families.get(0), null))
                .isEqualTo(VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ONLY);
        assertThat(SystemFonts.resolveVarFamilyType(families.get(1), null))
                .isEqualTo(VARIABLE_FONT_FAMILY_TYPE_TWO_FONTS_WGHT);
        assertThat(SystemFonts.resolveVarFamilyType(families.get(2), null))
                .isEqualTo(VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ITAL);
        assertThat(SystemFonts.resolveVarFamilyType(families.get(3), null))
                .isEqualTo(VARIABLE_FONT_FAMILY_TYPE_NONE);
        assertThat(SystemFonts.resolveVarFamilyType(families.get(4), null))
                .isEqualTo(VARIABLE_FONT_FAMILY_TYPE_NONE);
    }

    @Test
    public void varFamilyTypeRsolve_ForName() throws Exception {
        String xml = "<?xml version='1.0' encoding='UTF-8'?>"
                + "<familyset>"
                + "  <family name='sans-serif'>"
                + "    <font style='normal' supportedAxes='wght'>test.ttf</font>"
                + "  </family>"
                + "  <family name='serif'>"
                + "    <font style='normal' supportedAxes='wght'>test.ttf</font>"
                + "  </family>"
                + "  <family>"
                + "    <font style='normal' supportedAxes='wght'>test.ttf</font>"
                + "    <font fallbackFor='serif' supportedAxes='wght,ital'>test.ttf</font>"
                + "  </family>"
                + "</familyset>";
        FontConfig config = readFamilies(xml, true /* include non-existing font files */);
        List<FontConfig.FontFamily> families = config.getFontFamilies();
        assertThat(families.size()).isEqualTo(2);
        assertThat(SystemFonts.resolveVarFamilyType(families.get(1), null))
                .isEqualTo(VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ONLY);
        assertThat(SystemFonts.resolveVarFamilyType(families.get(1), "serif"))
                .isEqualTo(VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ITAL);
    }

    private FontConfig readFamilies(String xml, boolean allowNonExisting)
+143 −82

File changed.

Preview size limit exceeded, changes collapsed.

+163 −218

File changed.

Preview size limit exceeded, changes collapsed.

+21 −41
Original line number Diff line number Diff line
@@ -16,10 +16,6 @@

package android.graphics;

import static android.graphics.fonts.FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE;
import static android.graphics.fonts.FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ITAL;
import static android.graphics.fonts.FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ONLY;
import static android.graphics.fonts.FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_TWO_FONTS_WGHT;
import static android.text.FontConfig.NamedFamilyList;

import android.annotation.NonNull;
@@ -32,7 +28,6 @@ import android.os.Build;
import android.os.LocaleList;
import android.text.FontConfig;
import android.util.ArraySet;
import android.util.Log;
import android.util.Xml;

import org.xmlpull.v1.XmlPullParser;
@@ -65,6 +60,7 @@ public class FontListParser {
    private static final String VARIANT_ELEGANT = "elegant";

    // XML constants for Font.
    public static final String ATTR_SUPPORTED_AXES = "supportedAxes";
    public static final String ATTR_INDEX = "index";
    public static final String ATTR_WEIGHT = "weight";
    public static final String ATTR_POSTSCRIPT_NAME = "postScriptName";
@@ -78,6 +74,10 @@ public class FontListParser {
    public static final String ATTR_TAG = "tag";
    public static final String ATTR_STYLEVALUE = "stylevalue";

    // The tag string for variable font type resolution.
    private static final String TAG_WGHT = "wght";
    private static final String TAG_ITAL = "ital";

    /* Parse fallback list (no names) */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    public static FontConfig parse(InputStream in) throws XmlPullParserException, IOException {
@@ -263,7 +263,6 @@ public class FontListParser {
        final String lang = parser.getAttributeValue("", "lang");
        final String variant = parser.getAttributeValue(null, "variant");
        final String ignore = parser.getAttributeValue(null, "ignore");
        final String varFamilyTypeStr = parser.getAttributeValue(null, "varFamilyType");
        final List<FontConfig.Font> fonts = new ArrayList<>();
        while (keepReading(parser)) {
            if (parser.getEventType() != XmlPullParser.START_TAG) continue;
@@ -286,45 +285,12 @@ public class FontListParser {
                intVariant = FontConfig.FontFamily.VARIANT_ELEGANT;
            }
        }
        int varFamilyType = VARIABLE_FONT_FAMILY_TYPE_NONE;
        if (varFamilyTypeStr != null) {
            varFamilyType = Integer.parseInt(varFamilyTypeStr);
            if (varFamilyType <= -1 || varFamilyType > 3) {
                Log.e(TAG, "Error: unexpected varFamilyType value: " + varFamilyTypeStr);
                varFamilyType = VARIABLE_FONT_FAMILY_TYPE_NONE;
            }

            // validation but don't read font content for performance reasons.
            switch (varFamilyType) {
                case VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ONLY:
                    if (fonts.size() != 1) {
                        Log.e(TAG, "Error: Single font support wght axis, but two or more fonts are"
                                + " included in the font family.");
                        varFamilyType = VARIABLE_FONT_FAMILY_TYPE_NONE;
                    }
                    break;
                case VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ITAL:
                    if (fonts.size() != 1) {
                        Log.e(TAG, "Error: Single font support both ital and wght axes, but two or"
                                + " more fonts are included in the font family.");
                        varFamilyType = VARIABLE_FONT_FAMILY_TYPE_NONE;
                    }
                    break;
                case VARIABLE_FONT_FAMILY_TYPE_TWO_FONTS_WGHT:
                    if (fonts.size() != 2) {
                        Log.e(TAG, "Error: two fonts that support wght axis, but one or three or"
                                + " more fonts are included in the font family.");
                        varFamilyType = VARIABLE_FONT_FAMILY_TYPE_NONE;
                    }
            }
        }

        boolean skip = (ignore != null && (ignore.equals("true") || ignore.equals("1")));
        if (skip || fonts.isEmpty()) {
            return null;
        }
        return new FontConfig.FontFamily(fonts, LocaleList.forLanguageTags(lang), intVariant,
                varFamilyType);
        return new FontConfig.FontFamily(fonts, LocaleList.forLanguageTags(lang), intVariant);
    }

    private static void throwIfAttributeExists(String attrName, XmlPullParser parser) {
@@ -407,6 +373,7 @@ public class FontListParser {
        boolean isItalic = STYLE_ITALIC.equals(parser.getAttributeValue(null, ATTR_STYLE));
        String fallbackFor = parser.getAttributeValue(null, ATTR_FALLBACK_FOR);
        String postScriptName = parser.getAttributeValue(null, ATTR_POSTSCRIPT_NAME);
        final String supportedAxes = parser.getAttributeValue(null, ATTR_SUPPORTED_AXES);
        StringBuilder filename = new StringBuilder();
        while (keepReading(parser)) {
            if (parser.getEventType() == XmlPullParser.TEXT) {
@@ -422,6 +389,18 @@ public class FontListParser {
        }
        String sanitizedName = FILENAME_WHITESPACE_PATTERN.matcher(filename).replaceAll("");

        int varTypeAxes = 0;
        if (supportedAxes != null) {
            for (String tag : supportedAxes.split(",")) {
                String strippedTag = tag.strip();
                if (strippedTag.equals(TAG_WGHT)) {
                    varTypeAxes |= FontConfig.Font.VAR_TYPE_AXES_WGHT;
                } else if (strippedTag.equals(TAG_ITAL)) {
                    varTypeAxes |= FontConfig.Font.VAR_TYPE_AXES_ITAL;
                }
            }
        }

        if (postScriptName == null) {
            // If post script name was not provided, assume the file name is same to PostScript
            // name.
@@ -462,7 +441,8 @@ public class FontListParser {
                ),
                index,
                varSettings,
                fallbackFor);
                fallbackFor,
                varTypeAxes);
    }

    private static String findUpdatedFontFile(String psName,
Loading