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)
Loading