diff options
author | Roozbeh Pournader <roozbeh@google.com> | 2017-08-09 09:42:20 -0700 |
---|---|---|
committer | Roozbeh Pournader <roozbeh@google.com> | 2017-08-11 12:34:26 -0700 |
commit | 99975a3e25e11f5c5958d8a901d37902087c75fd (patch) | |
tree | a78def3c7c7b984a6e3668879d08e3d25595ec3e | |
parent | a7d731d5fecbac339a37ad963253b651b1ba7046 (diff) |
Support multiple languages per font in fonts.xml
Minikin already supports multiple languages specified per font in
I7f13b51464c9b01982bb573251d77052b9ddbd70. This CL adds a couple of
such cases into fonts.xml and clarifies in the method and the
variable names and parameters that the frameworks is handling a
multi-language string when it is.
Fixes: 26687969
Test: make -j checkbuild
Test: bit FrameworksCoreTests:android.graphics.TypefaceSystemFallbackTest
Change-Id: Ifa540a95f87921983f9069330d1dd0892538a8df
-rw-r--r-- | core/java/android/text/FontConfig.java | 12 | ||||
-rw-r--r-- | core/jni/android/graphics/FontFamily.cpp | 6 | ||||
-rw-r--r-- | core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java | 55 | ||||
-rw-r--r-- | data/fonts/fonts.xml | 8 | ||||
-rw-r--r-- | graphics/java/android/graphics/FontFamily.java | 16 | ||||
-rw-r--r-- | graphics/java/android/graphics/FontListParser.java | 13 | ||||
-rw-r--r-- | graphics/java/android/graphics/Typeface.java | 15 |
7 files changed, 87 insertions, 38 deletions
diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java index 029f66e1d670..4654e83c1af6 100644 --- a/core/java/android/text/FontConfig.java +++ b/core/java/android/text/FontConfig.java @@ -175,7 +175,7 @@ public final class FontConfig { public static final class Family { private final @NonNull String mName; private final @NonNull Font[] mFonts; - private final @NonNull String mLanguage; + private final @NonNull String[] mLanguages; /** @hide */ @Retention(SOURCE) @@ -209,11 +209,11 @@ public final class FontConfig { // See frameworks/minikin/include/minikin/FontFamily.h private final @Variant int mVariant; - public Family(@NonNull String name, @NonNull Font[] fonts, @NonNull String language, + public Family(@NonNull String name, @NonNull Font[] fonts, @NonNull String[] languages, @Variant int variant) { mName = name; mFonts = fonts; - mLanguage = language; + mLanguages = languages; mVariant = variant; } @@ -232,10 +232,10 @@ public final class FontConfig { } /** - * Returns the language for this family. May be null. + * Returns the languages for this family. May be null. */ - public @Nullable String getLanguage() { - return mLanguage; + public @Nullable String[] getLanguages() { + return mLanguages; } /** diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp index 4cf2b562b9ee..0ba27f61d3a0 100644 --- a/core/jni/android/graphics/FontFamily.cpp +++ b/core/jni/android/graphics/FontFamily.cpp @@ -51,10 +51,10 @@ struct NativeFamilyBuilder { std::vector<minikin::FontVariation> axes; }; -static jlong FontFamily_initBuilder(JNIEnv* env, jobject clazz, jstring lang, jint variant) { +static jlong FontFamily_initBuilder(JNIEnv* env, jobject clazz, jstring langs, jint variant) { NativeFamilyBuilder* builder; - if (lang != nullptr) { - ScopedUtfChars str(env, lang); + if (langs != nullptr) { + ScopedUtfChars str(env, langs); builder = new NativeFamilyBuilder( minikin::FontStyle::registerLanguageList(str.c_str()), variant); } else { diff --git a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java index ca4f7d43caf4..417faf220d39 100644 --- a/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java +++ b/core/tests/coretests/src/android/graphics/TypefaceSystemFallbackTest.java @@ -40,6 +40,7 @@ import java.io.InputStream; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.StandardCopyOption; +import java.util.Locale; @SmallTest @RunWith(AndroidJUnit4.class) @@ -128,7 +129,7 @@ public class TypefaceSystemFallbackTest { @Test public void testBuildSystemFallback_NonExistentFontShouldBeIgnored() { final String xml = "<?xml version='1.0' encoding='UTF-8'?>" - + "<familyset version='22'>" + + "<familyset>" + " <family name='sans-serif'>" + " <font weight='400' style='normal'>a3em.ttf</font>" + " <font weight='400' style='normal'>NoSuchFont.ttf</font>" @@ -154,7 +155,7 @@ public class TypefaceSystemFallbackTest { @Test public void testBuildSystemFallback_NamedFamily() { final String xml = "<?xml version='1.0' encoding='UTF-8'?>" - + "<familyset version='22'>" + + "<familyset>" + " <family name='sans-serif'>" + " <font weight='400' style='normal'>a3em.ttf</font>" + " </family>" @@ -200,7 +201,7 @@ public class TypefaceSystemFallbackTest { @Test public void testBuildSystemFallback_defaultFallback() { final String xml = "<?xml version='1.0' encoding='UTF-8'?>" - + "<familyset version='22'>" + + "<familyset>" + " <family name='sans-serif'>" + " <font weight='400' style='normal'>no_coverage.ttf</font>" + " </family>" @@ -239,7 +240,7 @@ public class TypefaceSystemFallbackTest { @Test public void testBuildSystemFallback_namedFallbackFamily() { final String xml = "<?xml version='1.0' encoding='UTF-8'?>" - + "<familyset version='22'>" + + "<familyset>" + " <family name='sans-serif'>" + " <font weight='400' style='normal'>no_coverage.ttf</font>" + " </family>" @@ -291,7 +292,7 @@ public class TypefaceSystemFallbackTest { @Test public void testBuildSystemFallback_namedFallbackFamily2() { final String xml = "<?xml version='1.0' encoding='UTF-8'?>" - + "<familyset version='22'>" + + "<familyset>" + " <family name='sans-serif'>" + " <font weight='400' style='normal'>no_coverage.ttf</font>" + " </family>" @@ -341,7 +342,7 @@ public class TypefaceSystemFallbackTest { @Test public void testBuildSystemFallback_ImplicitSansSerifFallback() { final String xml = "<?xml version='1.0' encoding='UTF-8'?>" - + "<familyset version='22'>" + + "<familyset>" + " <family name='sans-serif'>" + " <font weight='400' style='normal'>a3em.ttf</font>" + " </family>" @@ -380,7 +381,7 @@ public class TypefaceSystemFallbackTest { @Test public void testBuildSystemFallback_ElegantFallback() { final String xml = "<?xml version='1.0' encoding='UTF-8'?>" - + "<familyset version='22'>" + + "<familyset>" + " <family name='sans-serif'>" + " <font weight='400' style='normal'>no_coverage.ttf</font>" + " </family>" @@ -418,7 +419,7 @@ public class TypefaceSystemFallbackTest { @Test public void testBuildSystemFallback_ElegantFallback_customFallback() { final String xml = "<?xml version='1.0' encoding='UTF-8'?>" - + "<familyset version='22'>" + + "<familyset>" + " <family name='sans-serif'>" + " <font weight='400' style='normal'>no_coverage.ttf</font>" + " </family>" @@ -466,4 +467,42 @@ public class TypefaceSystemFallbackTest { assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f); assertEquals(GLYPH_3EM_WIDTH, paint.measureText("c"), 0.0f); } + + @Test + public void testBuildSystemFallback_multiLingualFamilies() { + final String xml = "<?xml version='1.0' encoding='UTF-8'?>" + + "<familyset>" + + " <family name='sans-serif'>" + + " <font weight='400' style='normal'>no_coverage.ttf</font>" + + " </family>" + + " <family lang='de'>" + + " <font weight='400' style='normal'>a3em.ttf</font>" + + " </family>" + + " <family lang='it fr'>" + + " <font weight='400' style='normal'>b3em.ttf</font>" + + " </family>" + + "</familyset>"; + final ArrayMap<String, Typeface> fontMap = new ArrayMap<>(); + final ArrayMap<String, FontFamily[]> fallbackMap = new ArrayMap<>(); + + buildSystemFallback(xml, fontMap, fallbackMap); + + final Paint paint = new Paint(); + paint.setTypeface(fontMap.get("sans-serif")); + + paint.setTextLocale(Locale.GERMANY); + assertEquals(GLYPH_3EM_WIDTH, paint.measureText("a"), 0.0f); + assertEquals(GLYPH_1EM_WIDTH, paint.measureText("b"), 0.0f); + assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f); + + paint.setTextLocale(Locale.ITALY); + assertEquals(GLYPH_1EM_WIDTH, paint.measureText("a"), 0.0f); + assertEquals(GLYPH_3EM_WIDTH, paint.measureText("b"), 0.0f); + assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f); + + paint.setTextLocale(Locale.FRANCE); + assertEquals(GLYPH_1EM_WIDTH, paint.measureText("a"), 0.0f); + assertEquals(GLYPH_3EM_WIDTH, paint.measureText("b"), 0.0f); + assertEquals(GLYPH_1EM_WIDTH, paint.measureText("c"), 0.0f); + } } diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml index ae93608726a3..209f364e041b 100644 --- a/data/fonts/fonts.xml +++ b/data/fonts/fonts.xml @@ -19,7 +19,7 @@ effectively add 300 to the weight, this ensures that 900 is the bold paired with the 500 weight, ensuring adequate contrast. --> -<familyset version="22"> +<familyset version="23"> <!-- first font is default --> <family name="sans-serif"> <font weight="100" style="normal">Roboto-Thin.ttf</font> @@ -128,8 +128,7 @@ <font weight="400" style="normal">NotoSansArmenian-Regular.ttf</font> <font weight="700" style="normal">NotoSansArmenian-Bold.ttf</font> </family> - <!-- TODO: add Geok --> - <family lang="und-Geor"> + <family lang="und-Geor und-Geok"> <font weight="400" style="normal">NotoSansGeorgian-Regular.ttf</font> <font weight="700" style="normal">NotoSansGeorgian-Bold.ttf</font> </family> @@ -474,8 +473,7 @@ <family lang="zh-Hans"> <font weight="400" style="normal" index="2">NotoSansCJK-Regular.ttc</font> </family> - <!-- TODO: Add Bopo --> - <family lang="zh-Hant"> + <family lang="zh-Hant zh-Bopo"> <font weight="400" style="normal" index="3">NotoSansCJK-Regular.ttc</font> </family> <family lang="ja"> diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java index d9a77e752823..d77e6012fb46 100644 --- a/graphics/java/android/graphics/FontFamily.java +++ b/graphics/java/android/graphics/FontFamily.java @@ -16,9 +16,11 @@ package android.graphics; +import android.annotation.Nullable; import android.content.res.AssetManager; import android.graphics.fonts.FontVariationAxis; import android.text.FontConfig; +import android.text.TextUtils; import android.util.Log; import dalvik.annotation.optimization.CriticalNative; @@ -48,8 +50,16 @@ public class FontFamily { mBuilderPtr = nInitBuilder(null, 0); } - public FontFamily(String lang, int variant) { - mBuilderPtr = nInitBuilder(lang, variant); + public FontFamily(@Nullable String[] langs, int variant) { + final String langsString; + if (langs == null || langs.length == 0) { + langsString = null; + } else if (langs.length == 1) { + langsString = langs[0]; + } else { + langsString = TextUtils.join(",", langs); + } + mBuilderPtr = nInitBuilder(langsString, variant); } /** @@ -174,7 +184,7 @@ public class FontFamily { return nAddFont(builderPtr, font, ttcIndex, -1, -1); } - private static native long nInitBuilder(String lang, int variant); + private static native long nInitBuilder(String langs, int variant); @CriticalNative private static native long nCreateFamily(long mBuilderPtr); diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java index 80a9324d04f3..9f672e30e05b 100644 --- a/graphics/java/android/graphics/FontListParser.java +++ b/graphics/java/android/graphics/FontListParser.java @@ -74,13 +74,14 @@ public class FontListParser { private static FontConfig.Family readFamily(XmlPullParser parser) throws XmlPullParserException, IOException { - String name = parser.getAttributeValue(null, "name"); - String lang = parser.getAttributeValue(null, "lang"); - String variant = parser.getAttributeValue(null, "variant"); - List<FontConfig.Font> fonts = new ArrayList<FontConfig.Font>(); + final String name = parser.getAttributeValue(null, "name"); + final String lang = parser.getAttributeValue(null, "lang"); + final String[] langs = lang == null ? null : lang.split("\\s+"); + final String variant = parser.getAttributeValue(null, "variant"); + final List<FontConfig.Font> fonts = new ArrayList<FontConfig.Font>(); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) continue; - String tag = parser.getName(); + final String tag = parser.getName(); if (tag.equals("font")) { fonts.add(readFont(parser)); } else { @@ -95,7 +96,7 @@ public class FontListParser { intVariant = FontConfig.Family.VARIANT_ELEGANT; } } - return new FontConfig.Family(name, fonts.toArray(new FontConfig.Font[fonts.size()]), lang, + return new FontConfig.Family(name, fonts.toArray(new FontConfig.Font[fonts.size()]), langs, intVariant); } diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index 3a8dfb014d5d..7496fa6abf47 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -929,9 +929,9 @@ public class Typeface { } private static @Nullable FontFamily createFontFamily( - String familyName, List<FontConfig.Font> fonts, String languageTag, int variant, + String familyName, List<FontConfig.Font> fonts, String[] languageTags, int variant, Map<String, ByteBuffer> cache, String fontDir) { - final FontFamily family = new FontFamily(languageTag, variant); + final FontFamily family = new FontFamily(languageTags, variant); for (int i = 0; i < fonts.size(); i++) { final FontConfig.Font font = fonts.get(i); final String fullPath = fontDir + font.getFontName(); @@ -952,7 +952,8 @@ public class Typeface { } } if (!family.freeze()) { - Log.e(TAG, "Unable to load Family: " + familyName + " : " + languageTag); + Log.e(TAG, "Unable to load Family: " + familyName + " : " + + Arrays.toString(languageTags)); return null; } return family; @@ -963,7 +964,7 @@ public class Typeface { Map<String, ByteBuffer> cache, String fontDir) { - final String languageTag = xmlFamily.getLanguage(); + final String[] languageTags = xmlFamily.getLanguages(); final int variant = xmlFamily.getVariant(); final ArrayList<FontConfig.Font> defaultFonts = new ArrayList<>(); @@ -985,7 +986,7 @@ public class Typeface { } final FontFamily defaultFamily = defaultFonts.isEmpty() ? null : createFontFamily( - xmlFamily.getName(), defaultFonts, languageTag, variant, cache, fontDir); + xmlFamily.getName(), defaultFonts, languageTags, variant, cache, fontDir); // Insert family into fallback map. for (int i = 0; i < fallbackMap.size(); i++) { @@ -997,7 +998,7 @@ public class Typeface { } } else { final FontFamily family = createFontFamily( - xmlFamily.getName(), fallback, languageTag, variant, cache, fontDir); + xmlFamily.getName(), fallback, languageTags, variant, cache, fontDir); if (family != null) { fallbackMap.valueAt(i).add(family); } @@ -1034,7 +1035,7 @@ public class Typeface { } final FontFamily family = createFontFamily( xmlFamily.getName(), Arrays.asList(xmlFamily.getFonts()), - xmlFamily.getLanguage(), xmlFamily.getVariant(), bufferCache, fontDir); + xmlFamily.getLanguages(), xmlFamily.getVariant(), bufferCache, fontDir); if (family == null) { continue; } |