Loading core/java/android/text/FontConfig.java +22 −2 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ 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.os.Build; Loading Loading @@ -528,6 +529,7 @@ 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) Loading Loading @@ -567,10 +569,11 @@ 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) { @Variant int variant, int variableFontFamilyType) { mFonts = fonts; mLocaleList = localeList; mVariant = variant; mVariableFontFamilyType = variableFontFamilyType; } /** Loading Loading @@ -621,6 +624,20 @@ 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; Loading @@ -631,6 +648,7 @@ 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>() { Loading @@ -641,8 +659,10 @@ 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); return new FontFamily(fonts, LocaleList.forLanguageTags(langTags), variant, varFamilyType); } @Override Loading core/tests/coretests/src/android/graphics/FontListParserTest.java +31 −8 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ 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.os.LocaleList; import android.text.FontConfig; Loading Loading @@ -64,7 +65,8 @@ public final class FontListParserTest { 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)), "sans-serif"); LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE)), "sans-serif"); FontConfig.NamedFamilyList family = readNamedFamily(xml); assertThat(family).isEqualTo(expected); } Loading @@ -84,7 +86,8 @@ public final class FontListParserTest { new FontConfig.Font(new File("test.ttf"), null, "test", new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 0, "", "serif")), LocaleList.forLanguageTags("en"), VARIANT_DEFAULT); LocaleList.forLanguageTags("en"), VARIANT_DEFAULT, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE); FontConfig.FontFamily family = readFamily(xml); assertThat(family).isEqualTo(expected); Loading @@ -101,7 +104,8 @@ public final class FontListParserTest { new FontConfig.Font(new File("test.ttf"), null, "test", new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 0, "", null)), LocaleList.forLanguageTags("en"), VARIANT_COMPACT); LocaleList.forLanguageTags("en"), VARIANT_COMPACT, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE); FontConfig.FontFamily family = readFamily(xml); assertThat(family).isEqualTo(expected); Loading @@ -118,7 +122,8 @@ public final class FontListParserTest { new FontConfig.Font(new File("test.ttf"), null, "test", new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 0, "", null)), LocaleList.forLanguageTags("en"), VARIANT_ELEGANT); LocaleList.forLanguageTags("en"), VARIANT_ELEGANT, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE); FontConfig.FontFamily family = readFamily(xml); assertThat(family).isEqualTo(expected); Loading @@ -140,7 +145,8 @@ public final class FontListParserTest { new FontStyle(100, FONT_SLANT_UPRIGHT), 0, "", null), new FontConfig.Font(new File("italic.ttf"), null, "test", new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_ITALIC), 0, "", null)), LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT)), "sans-serif"); LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE)), "sans-serif"); FontConfig.NamedFamilyList family = readNamedFamily(xml); assertThat(family).isEqualTo(expected); } Loading @@ -166,7 +172,8 @@ public final class FontListParserTest { 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)), LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE)), "sans-serif"); FontConfig.NamedFamilyList family = readNamedFamily(xml); assertThat(family).isEqualTo(expected); Loading @@ -187,7 +194,8 @@ public final class FontListParserTest { new FontConfig.Font(new File("test.ttc"), null, "test", new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 1, "", null)), LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT)), LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE)), "sans-serif"); FontConfig.NamedFamilyList family = readNamedFamily(xml); assertThat(family).isEqualTo(expected); Loading @@ -206,7 +214,8 @@ public final class FontListParserTest { new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 0, "", null), new FontConfig.Font(new File("test.ttc"), null, "test", new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 1, "", null)), LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT)), "sans-serif"); LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE)), "sans-serif"); FontConfig.NamedFamilyList family = readNamedFamily(xml); assertThat(family).isEqualTo(expected); } Loading Loading @@ -372,6 +381,20 @@ public final class FontListParserTest { .isEqualTo("emoji.ttf"); } @Test 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>" + "</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); } private FontConfig readFamilies(String xml, boolean allowNonExisting) throws IOException, XmlPullParserException { ByteArrayInputStream buffer = new ByteArrayInputStream( Loading data/fonts/font_fallback.xml +82 −829 File changed.Preview size limit exceeded, changes collapsed. Show changes graphics/java/android/graphics/FontListParser.java +40 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ 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; Loading @@ -28,6 +32,7 @@ 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; Loading Loading @@ -256,6 +261,7 @@ 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; Loading @@ -278,12 +284,45 @@ 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); return new FontConfig.FontFamily(fonts, LocaleList.forLanguageTags(lang), intVariant, varFamilyType); } private static void throwIfAttributeExists(String attrName, XmlPullParser parser) { Loading graphics/java/android/graphics/fonts/FontFamily.java +34 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,10 @@ package android.graphics.fonts; import static com.android.text.flags.Flags.FLAG_DEPRECATE_FONTS_XML; import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -32,6 +35,7 @@ import dalvik.annotation.optimization.FastNative; import libcore.util.NativeAllocationRegistry; import java.lang.annotation.Retention; import java.util.ArrayList; import java.util.Set; Loading Loading @@ -184,32 +188,59 @@ public final class FontFamily { } /** * A special variable font family type that indicates `analyzeAndResolveVariableType` could * not be identified the variable font family type. * * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_UNKNOWN = -1; /** * A variable font family type that indicates no variable font family can be used. * * The font family is used as bundle of static fonts. * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_NONE = 0; /** * A variable font family type that indicates single font file can be used for multiple * weight. For the italic style, fake italic may be applied. * * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ONLY = 1; /** * A variable font family type that indicates single font file can be used for multiple * weight and italic. * * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ITAL = 2; /** * A variable font family type that indicates two font files are included in the family: * one can be used for upright with various weights, the other one can be used for italic * with various weights. * * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_TWO_FONTS_WGHT = 3; /** @hide */ @Retention(SOURCE) @IntDef(prefix = { "VARIABLE_FONT_FAMILY_TYPE_" }, value = { VARIABLE_FONT_FAMILY_TYPE_UNKNOWN, VARIABLE_FONT_FAMILY_TYPE_NONE, VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ONLY, VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ITAL, VARIABLE_FONT_FAMILY_TYPE_TWO_FONTS_WGHT }) public @interface VariableFontFamilyType {} /** * The registered italic axis used for adjusting requested style. * https://learn.microsoft.com/en-us/typography/opentype/spec/dvaraxistag_ital Loading @@ -222,7 +253,9 @@ public final class FontFamily { */ private static final int TAG_wght = 0x77676874; // w(0x77), g(0x67), h(0x68), t(0x74) private static int analyzeAndResolveVariableType(ArrayList<Font> fonts) { /** @hide */ public static @VariableFontFamilyType int analyzeAndResolveVariableType( ArrayList<Font> fonts) { if (fonts.size() > 2) { return VARIABLE_FONT_FAMILY_TYPE_UNKNOWN; } Loading Loading
core/java/android/text/FontConfig.java +22 −2 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ 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.os.Build; Loading Loading @@ -528,6 +529,7 @@ 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) Loading Loading @@ -567,10 +569,11 @@ 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) { @Variant int variant, int variableFontFamilyType) { mFonts = fonts; mLocaleList = localeList; mVariant = variant; mVariableFontFamilyType = variableFontFamilyType; } /** Loading Loading @@ -621,6 +624,20 @@ 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; Loading @@ -631,6 +648,7 @@ 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>() { Loading @@ -641,8 +659,10 @@ 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); return new FontFamily(fonts, LocaleList.forLanguageTags(langTags), variant, varFamilyType); } @Override Loading
core/tests/coretests/src/android/graphics/FontListParserTest.java +31 −8 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ 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.os.LocaleList; import android.text.FontConfig; Loading Loading @@ -64,7 +65,8 @@ public final class FontListParserTest { 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)), "sans-serif"); LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE)), "sans-serif"); FontConfig.NamedFamilyList family = readNamedFamily(xml); assertThat(family).isEqualTo(expected); } Loading @@ -84,7 +86,8 @@ public final class FontListParserTest { new FontConfig.Font(new File("test.ttf"), null, "test", new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 0, "", "serif")), LocaleList.forLanguageTags("en"), VARIANT_DEFAULT); LocaleList.forLanguageTags("en"), VARIANT_DEFAULT, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE); FontConfig.FontFamily family = readFamily(xml); assertThat(family).isEqualTo(expected); Loading @@ -101,7 +104,8 @@ public final class FontListParserTest { new FontConfig.Font(new File("test.ttf"), null, "test", new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 0, "", null)), LocaleList.forLanguageTags("en"), VARIANT_COMPACT); LocaleList.forLanguageTags("en"), VARIANT_COMPACT, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE); FontConfig.FontFamily family = readFamily(xml); assertThat(family).isEqualTo(expected); Loading @@ -118,7 +122,8 @@ public final class FontListParserTest { new FontConfig.Font(new File("test.ttf"), null, "test", new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 0, "", null)), LocaleList.forLanguageTags("en"), VARIANT_ELEGANT); LocaleList.forLanguageTags("en"), VARIANT_ELEGANT, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE); FontConfig.FontFamily family = readFamily(xml); assertThat(family).isEqualTo(expected); Loading @@ -140,7 +145,8 @@ public final class FontListParserTest { new FontStyle(100, FONT_SLANT_UPRIGHT), 0, "", null), new FontConfig.Font(new File("italic.ttf"), null, "test", new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_ITALIC), 0, "", null)), LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT)), "sans-serif"); LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE)), "sans-serif"); FontConfig.NamedFamilyList family = readNamedFamily(xml); assertThat(family).isEqualTo(expected); } Loading @@ -166,7 +172,8 @@ public final class FontListParserTest { 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)), LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE)), "sans-serif"); FontConfig.NamedFamilyList family = readNamedFamily(xml); assertThat(family).isEqualTo(expected); Loading @@ -187,7 +194,8 @@ public final class FontListParserTest { new FontConfig.Font(new File("test.ttc"), null, "test", new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 1, "", null)), LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT)), LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE)), "sans-serif"); FontConfig.NamedFamilyList family = readNamedFamily(xml); assertThat(family).isEqualTo(expected); Loading @@ -206,7 +214,8 @@ public final class FontListParserTest { new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 0, "", null), new FontConfig.Font(new File("test.ttc"), null, "test", new FontStyle(FONT_WEIGHT_NORMAL, FONT_SLANT_UPRIGHT), 1, "", null)), LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT)), "sans-serif"); LocaleList.getEmptyLocaleList(), VARIANT_DEFAULT, FontFamily.Builder.VARIABLE_FONT_FAMILY_TYPE_NONE)), "sans-serif"); FontConfig.NamedFamilyList family = readNamedFamily(xml); assertThat(family).isEqualTo(expected); } Loading Loading @@ -372,6 +381,20 @@ public final class FontListParserTest { .isEqualTo("emoji.ttf"); } @Test 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>" + "</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); } private FontConfig readFamilies(String xml, boolean allowNonExisting) throws IOException, XmlPullParserException { ByteArrayInputStream buffer = new ByteArrayInputStream( Loading
data/fonts/font_fallback.xml +82 −829 File changed.Preview size limit exceeded, changes collapsed. Show changes
graphics/java/android/graphics/FontListParser.java +40 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ 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; Loading @@ -28,6 +32,7 @@ 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; Loading Loading @@ -256,6 +261,7 @@ 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; Loading @@ -278,12 +284,45 @@ 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); return new FontConfig.FontFamily(fonts, LocaleList.forLanguageTags(lang), intVariant, varFamilyType); } private static void throwIfAttributeExists(String attrName, XmlPullParser parser) { Loading
graphics/java/android/graphics/fonts/FontFamily.java +34 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,10 @@ package android.graphics.fonts; import static com.android.text.flags.Flags.FLAG_DEPRECATE_FONTS_XML; import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; Loading @@ -32,6 +35,7 @@ import dalvik.annotation.optimization.FastNative; import libcore.util.NativeAllocationRegistry; import java.lang.annotation.Retention; import java.util.ArrayList; import java.util.Set; Loading Loading @@ -184,32 +188,59 @@ public final class FontFamily { } /** * A special variable font family type that indicates `analyzeAndResolveVariableType` could * not be identified the variable font family type. * * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_UNKNOWN = -1; /** * A variable font family type that indicates no variable font family can be used. * * The font family is used as bundle of static fonts. * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_NONE = 0; /** * A variable font family type that indicates single font file can be used for multiple * weight. For the italic style, fake italic may be applied. * * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ONLY = 1; /** * A variable font family type that indicates single font file can be used for multiple * weight and italic. * * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ITAL = 2; /** * A variable font family type that indicates two font files are included in the family: * one can be used for upright with various weights, the other one can be used for italic * with various weights. * * @see #buildVariableFamily() * @hide */ public static final int VARIABLE_FONT_FAMILY_TYPE_TWO_FONTS_WGHT = 3; /** @hide */ @Retention(SOURCE) @IntDef(prefix = { "VARIABLE_FONT_FAMILY_TYPE_" }, value = { VARIABLE_FONT_FAMILY_TYPE_UNKNOWN, VARIABLE_FONT_FAMILY_TYPE_NONE, VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ONLY, VARIABLE_FONT_FAMILY_TYPE_SINGLE_FONT_WGHT_ITAL, VARIABLE_FONT_FAMILY_TYPE_TWO_FONTS_WGHT }) public @interface VariableFontFamilyType {} /** * The registered italic axis used for adjusting requested style. * https://learn.microsoft.com/en-us/typography/opentype/spec/dvaraxistag_ital Loading @@ -222,7 +253,9 @@ public final class FontFamily { */ private static final int TAG_wght = 0x77676874; // w(0x77), g(0x67), h(0x68), t(0x74) private static int analyzeAndResolveVariableType(ArrayList<Font> fonts) { /** @hide */ public static @VariableFontFamilyType int analyzeAndResolveVariableType( ArrayList<Font> fonts) { if (fonts.size() > 2) { return VARIABLE_FONT_FAMILY_TYPE_UNKNOWN; } Loading