Merge changes I6ecf6654,I25bdefcd
* changes:
Enable variation settings for fonts in XMLs
Enable the public TTC index attribute for fonts
diff --git a/compat/res-public/values/public_attrs.xml b/compat/res-public/values/public_attrs.xml
index e45f8c2..38d858e 100644
--- a/compat/res-public/values/public_attrs.xml
+++ b/compat/res-public/values/public_attrs.xml
@@ -26,4 +26,6 @@
<public type="attr" name="fontStyle"/>
<public type="attr" name="font"/>
<public type="attr" name="fontWeight"/>
+ <public type="attr" name="fontVariationSettings"/>
+ <public type="attr" name="ttcIndex"/>
</resources>
diff --git a/compat/res/values/attrs.xml b/compat/res/values/attrs.xml
index 04d7690..1a721a8 100644
--- a/compat/res/values/attrs.xml
+++ b/compat/res/values/attrs.xml
@@ -79,10 +79,19 @@
common values are 400 for regular weight and 700 for bold weight. If unspecified, the value
in the font's header tables will be used. -->
<attr name="fontWeight" format="integer" />
-
+ <!-- The variation settings to be applied to the font. The string should be in the following
+ format: "'tag1' value1, 'tag2' value2, ...". If the default variation settings should be
+ used, or the font used does not support variation settings, this attribute needs not be
+ specified. -->
+ <attr name="fontVariationSettings" format="string" />
+ <!-- The index of the font in the tcc font file. If the font file referenced is not in the
+ tcc format, this attribute needs not be specified. -->
+ <attr name="ttcIndex" format="integer" />
<!-- References to the framework attrs -->
<attr name="android:fontStyle" />
<attr name="android:font" />
<attr name="android:fontWeight" />
+ <attr name="android:fontVariationSettings" />
+ <attr name="android:ttcIndex" />
</declare-styleable>
</resources>
diff --git a/compat/src/main/java/android/support/v4/content/res/FontResourcesParserCompat.java b/compat/src/main/java/android/support/v4/content/res/FontResourcesParserCompat.java
index 8ad07d3..f597e68 100644
--- a/compat/src/main/java/android/support/v4/content/res/FontResourcesParserCompat.java
+++ b/compat/src/main/java/android/support/v4/content/res/FontResourcesParserCompat.java
@@ -102,13 +102,17 @@
private final @NonNull String mFileName;
private int mWeight;
private boolean mItalic;
+ private String mVariationSettings;
+ private int mTtcIndex;
private int mResourceId;
public FontFileResourceEntry(@NonNull String fileName, int weight, boolean italic,
- int resourceId) {
+ @Nullable String variationSettings, int ttcIndex, int resourceId) {
mFileName = fileName;
mWeight = weight;
mItalic = italic;
+ mVariationSettings = variationSettings;
+ mTtcIndex = ttcIndex;
mResourceId = resourceId;
}
@@ -124,6 +128,14 @@
return mItalic;
}
+ public @Nullable String getVariationSettings() {
+ return mVariationSettings;
+ }
+
+ public int getTtcIndex() {
+ return mTtcIndex;
+ }
+
public int getResourceId() {
return mResourceId;
}
@@ -260,6 +272,15 @@
? R.styleable.FontFamilyFont_fontStyle
: R.styleable.FontFamilyFont_android_fontStyle;
boolean isItalic = ITALIC == array.getInt(styleAttr, 0);
+ final int ttcIndexAttr = array.hasValue(R.styleable.FontFamilyFont_ttcIndex)
+ ? R.styleable.FontFamilyFont_ttcIndex
+ : R.styleable.FontFamilyFont_android_ttcIndex;
+ final int variationSettingsAttr =
+ array.hasValue(R.styleable.FontFamilyFont_fontVariationSettings)
+ ? R.styleable.FontFamilyFont_fontVariationSettings
+ : R.styleable.FontFamilyFont_android_fontVariationSettings;
+ String variationSettings = array.getString(variationSettingsAttr);
+ int ttcIndex = array.getInt(ttcIndexAttr, 0);
final int resourceAttr = array.hasValue(R.styleable.FontFamilyFont_font)
? R.styleable.FontFamilyFont_font
: R.styleable.FontFamilyFont_android_font;
@@ -269,7 +290,8 @@
while (parser.next() != XmlPullParser.END_TAG) {
skip(parser);
}
- return new FontFileResourceEntry(filename, weight, isItalic, resourceId);
+ return new FontFileResourceEntry(filename, weight, isItalic, variationSettings, ttcIndex,
+ resourceId);
}
private static void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
diff --git a/compat/src/main/java/android/support/v4/graphics/TypefaceCompat.java b/compat/src/main/java/android/support/v4/graphics/TypefaceCompat.java
index 734f183..b763101 100644
--- a/compat/src/main/java/android/support/v4/graphics/TypefaceCompat.java
+++ b/compat/src/main/java/android/support/v4/graphics/TypefaceCompat.java
@@ -32,6 +32,7 @@
import android.support.v4.content.res.FontResourcesParserCompat.FontFamilyFilesResourceEntry;
import android.support.v4.content.res.FontResourcesParserCompat.ProviderResourceEntry;
import android.support.v4.content.res.ResourcesCompat;
+import android.support.v4.os.BuildCompat;
import android.support.v4.provider.FontsContractCompat;
import android.support.v4.provider.FontsContractCompat.FontInfo;
import android.support.v4.util.LruCache;
@@ -45,7 +46,7 @@
private static final TypefaceCompatImpl sTypefaceCompatImpl;
static {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ if (BuildCompat.isAtLeastP()) {
sTypefaceCompatImpl = new TypefaceCompatApi28Impl();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
sTypefaceCompatImpl = new TypefaceCompatApi26Impl();
diff --git a/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi24Impl.java b/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi24Impl.java
index 89a6ec4..a8c1988 100644
--- a/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi24Impl.java
+++ b/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi24Impl.java
@@ -159,8 +159,7 @@
if (buffer == null) {
return null;
}
- // TODO: support ttc index.
- if (!addFontWeightStyle(family, buffer, 0, e.getWeight(), e.isItalic())) {
+ if (!addFontWeightStyle(family, buffer, e.getTtcIndex(), e.getWeight(), e.isItalic())) {
return null;
}
}
diff --git a/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi26Impl.java b/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi26Impl.java
index 4260c55..955284e 100644
--- a/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi26Impl.java
+++ b/compat/src/main/java/android/support/v4/graphics/TypefaceCompatApi26Impl.java
@@ -61,6 +61,7 @@
private static final String FREEZE_METHOD = "freeze";
private static final String ABORT_CREATION_METHOD = "abortCreation";
private static final int RESOLVE_BY_FONT_TABLE = -1;
+ private static final String DEFAULT_FAMILY = "sans-serif";
protected final Class mFontFamily;
protected final Constructor mFontFamilyCtor;
@@ -133,11 +134,11 @@
* boolean isAsset, int ttcIndex, int weight, int isItalic, FontVariationAxis[] axes)
*/
private boolean addFontFromAssetManager(Context context, Object family, String fileName,
- int ttcIndex, int weight, int style) {
+ int ttcIndex, int weight, int style, @Nullable FontVariationAxis[] axes) {
try {
final Boolean result = (Boolean) mAddFontFromAssetManager.invoke(family,
context.getAssets(), fileName, 0 /* cookie */, false /* isAsset */, ttcIndex,
- weight, style, null /* axes */);
+ weight, style, axes);
return result.booleanValue();
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
@@ -206,9 +207,9 @@
}
Object fontFamily = newFamily();
for (final FontFileResourceEntry fontFile : entry.getEntries()) {
- // TODO: Add ttc and variation font support. (b/37853920)
if (!addFontFromAssetManager(context, fontFamily, fontFile.getFileName(),
- 0 /* ttcIndex */, fontFile.getWeight(), fontFile.isItalic() ? 1 : 0)) {
+ fontFile.getTtcIndex(), fontFile.getWeight(), fontFile.isItalic() ? 1 : 0,
+ FontVariationAxis.fromFontVariationSettings(fontFile.getVariationSettings()))) {
abortCreation(fontFamily);
return null;
}
@@ -285,7 +286,7 @@
Object fontFamily = newFamily();
if (!addFontFromAssetManager(context, fontFamily, path,
0 /* ttcIndex */, RESOLVE_BY_FONT_TABLE /* weight */,
- RESOLVE_BY_FONT_TABLE /* italic */)) {
+ RESOLVE_BY_FONT_TABLE /* italic */, null /* axes */)) {
abortCreation(fontFamily);
return null;
}
diff --git a/compat/tests/java/android/support/v4/content/res/FontResourcesParserCompatTest.java b/compat/tests/java/android/support/v4/content/res/FontResourcesParserCompatTest.java
index 6120eed..f503d99 100644
--- a/compat/tests/java/android/support/v4/content/res/FontResourcesParserCompatTest.java
+++ b/compat/tests/java/android/support/v4/content/res/FontResourcesParserCompatTest.java
@@ -63,7 +63,7 @@
@Test
public void testParse() throws XmlPullParserException, IOException {
@SuppressLint("ResourceType")
- XmlResourceParser parser = mResources.getXml(R.font.samplexmlfont);
+ XmlResourceParser parser = mResources.getXml(R.font.samplexmlfontforparsing);
FamilyResourceEntry result = FontResourcesParserCompat.parse(parser, mResources);
@@ -74,18 +74,26 @@
FontFileResourceEntry font1 = fileEntries[0];
assertEquals(400, font1.getWeight());
assertEquals(false, font1.isItalic());
+ assertEquals("'wdth' 0.8", font1.getVariationSettings());
+ assertEquals(0, font1.getTtcIndex());
assertEquals(R.font.samplefont, font1.getResourceId());
FontFileResourceEntry font2 = fileEntries[1];
assertEquals(400, font2.getWeight());
assertEquals(true, font2.isItalic());
+ assertEquals("'contrast' 0.5", font2.getVariationSettings());
+ assertEquals(1, font2.getTtcIndex());
assertEquals(R.font.samplefont2, font2.getResourceId());
FontFileResourceEntry font3 = fileEntries[2];
assertEquals(700, font3.getWeight());
assertEquals(false, font3.isItalic());
+ assertEquals("'wdth' 500.0, 'wght' 300.0", font3.getVariationSettings());
+ assertEquals(2, font3.getTtcIndex());
assertEquals(R.font.samplefont3, font3.getResourceId());
FontFileResourceEntry font4 = fileEntries[3];
assertEquals(700, font4.getWeight());
assertEquals(true, font4.isItalic());
+ assertEquals(null, font4.getVariationSettings());
+ assertEquals(0, font4.getTtcIndex());
assertEquals(R.font.samplefont4, font4.getResourceId());
}
@@ -98,7 +106,7 @@
}
@SuppressLint("ResourceType")
- XmlResourceParser parser = mResources.getXml(R.font.samplexmlfont2);
+ XmlResourceParser parser = mResources.getXml(R.font.samplexmlfontforparsing2);
FamilyResourceEntry result = FontResourcesParserCompat.parse(parser, mResources);
@@ -109,18 +117,26 @@
FontFileResourceEntry font1 = fileEntries[0];
assertEquals(400, font1.getWeight());
assertEquals(false, font1.isItalic());
+ assertEquals("'wdth' 0.8", font1.getVariationSettings());
+ assertEquals(0, font1.getTtcIndex());
assertEquals(R.font.samplefont, font1.getResourceId());
FontFileResourceEntry font2 = fileEntries[1];
assertEquals(400, font2.getWeight());
assertEquals(true, font2.isItalic());
+ assertEquals("'contrast' 0.5", font2.getVariationSettings());
+ assertEquals(1, font2.getTtcIndex());
assertEquals(R.font.samplefont2, font2.getResourceId());
FontFileResourceEntry font3 = fileEntries[2];
assertEquals(700, font3.getWeight());
assertEquals(false, font3.isItalic());
+ assertEquals("'wdth' 500.0, 'wght' 300.0", font3.getVariationSettings());
+ assertEquals(2, font3.getTtcIndex());
assertEquals(R.font.samplefont3, font3.getResourceId());
FontFileResourceEntry font4 = fileEntries[3];
assertEquals(700, font4.getWeight());
assertEquals(true, font4.isItalic());
+ assertEquals(null, font4.getVariationSettings());
+ assertEquals(0, font4.getTtcIndex());
assertEquals(R.font.samplefont4, font4.getResourceId());
}
diff --git a/compat/tests/java/android/support/v4/graphics/TypefaceCompatTest.java b/compat/tests/java/android/support/v4/graphics/TypefaceCompatTest.java
index dff4c33..9c27966 100644
--- a/compat/tests/java/android/support/v4/graphics/TypefaceCompatTest.java
+++ b/compat/tests/java/android/support/v4/graphics/TypefaceCompatTest.java
@@ -31,6 +31,7 @@
import android.content.res.Resources;
import android.graphics.Paint;
import android.graphics.Typeface;
+import android.os.Build;
import android.support.annotation.NonNull;
import android.support.compat.test.R;
import android.support.test.InstrumentationRegistry;
@@ -356,6 +357,81 @@
assertEquals(R.font.large_d, getSelectedFontResourceId(typeface));
}
+ private Typeface getLargerTypeface(String text, Typeface typeface1, Typeface typeface2) {
+ Paint p1 = new Paint();
+ p1.setTypeface(typeface1);
+ float width1 = p1.measureText(text);
+ Paint p2 = new Paint();
+ p2.setTypeface(typeface2);
+ float width2 = p2.measureText(text);
+
+ if (width1 > width2) {
+ return typeface1;
+ } else if (width1 < width2) {
+ return typeface2;
+ } else {
+ assertTrue(false);
+ return null;
+ }
+ }
+
+ @Test
+ public void testCreateFromResourcesFamilyXml_resourceTtcFont() throws Exception {
+ // Here we test that building typefaces by indexing in font collections works correctly.
+ // We want to ensure that the built typefaces correspond to the fonts with the right index.
+ // sample_font_collection.ttc contains two fonts (with indices 0 and 1). The first one has
+ // glyph "a" of 3em width, and all the other glyphs 1em. The second one has glyph "b" of
+ // 3em width, and all the other glyphs 1em. Hence, we can compare the width of these
+ // glyphs to assert that ttc indexing works.
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
+ // Creating typefaces with ttc index was only supported in the API starting with N.
+ return;
+ }
+ final FamilyResourceEntry entry1 = FontResourcesParserCompat.parse(
+ mResources.getXml(R.font.ttctestfont1), mResources);
+ Typeface typeface1 = TypefaceCompat.createFromResourcesFamilyXml(mContext, entry1,
+ mResources, R.font.ttctestfont1, Typeface.NORMAL, null /* callback */,
+ null /*handler */, false /* isXmlRequest */);
+ assertNotNull(typeface1);
+ final FamilyResourceEntry entry2 = FontResourcesParserCompat.parse(
+ mResources.getXml(R.font.ttctestfont2), mResources);
+ Typeface typeface2 = TypefaceCompat.createFromResourcesFamilyXml(mContext, entry2,
+ mResources, R.font.ttctestfont2, Typeface.NORMAL, null /* callback */,
+ null /*handler */, false /* isXmlRequest */);
+ assertNotNull(typeface2);
+
+ assertEquals(getLargerTypeface("a", typeface1, typeface2), typeface1);
+ assertEquals(getLargerTypeface("b", typeface1, typeface2), typeface2);
+ }
+
+ @Test
+ public void testCreateFromResourcesFamilyXml_resourceFontWithVariationSettings()
+ throws Exception {
+ // Here we test that specifying variation settings for fonts in XMLs works correctly.
+ // We build typefaces from two families containing one font each, using the same font
+ // resource, but having different values for the 'wdth' tag. Then we measure the painted
+ // text to ensure that the tag affects the text width. The font resource used supports
+ // the 'wdth' axis for the dash (-) character.
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+ // Variation settings are only supported on O and newer.
+ return;
+ }
+ final FamilyResourceEntry entry1 = FontResourcesParserCompat.parse(
+ mResources.getXml(R.font.variationsettingstestfont1), mResources);
+ Typeface typeface1 = TypefaceCompat.createFromResourcesFamilyXml(mContext, entry1,
+ mResources, R.font.variationsettingstestfont1, Typeface.NORMAL, null /* callback */,
+ null /*handler */, false /* isXmlRequest */);
+ assertNotNull(typeface1);
+ final FamilyResourceEntry entry2 = FontResourcesParserCompat.parse(
+ mResources.getXml(R.font.variationsettingstestfont2), mResources);
+ Typeface typeface2 = TypefaceCompat.createFromResourcesFamilyXml(mContext, entry2,
+ mResources, R.font.variationsettingstestfont2, Typeface.NORMAL, null /* callback */,
+ null /*handler */, false /* isXmlRequest */);
+ assertNotNull(typeface2);
+
+ assertEquals(getLargerTypeface("-", typeface1, typeface2), typeface2);
+ }
+
@Test
public void testCreateFromResourcesFontFile() {
Typeface typeface = TypefaceCompat.createFromResourcesFontFile(mContext, mResources,
diff --git a/compat/tests/res/font/sample_font_collection.ttc b/compat/tests/res/font/sample_font_collection.ttc
new file mode 100644
index 0000000..9252f3d
--- /dev/null
+++ b/compat/tests/res/font/sample_font_collection.ttc
Binary files differ
diff --git a/compat/tests/res/font/samplexmlfontforparsing.xml b/compat/tests/res/font/samplexmlfontforparsing.xml
new file mode 100644
index 0000000..a96385c
--- /dev/null
+++ b/compat/tests/res/font/samplexmlfontforparsing.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <font app:fontStyle="normal" app:fontWeight="400" app:fontVariationSettings="'wdth' 0.8"
+ app:font="@font/samplefont" app:ttcIndex="0" />
+ <font app:fontStyle="italic" app:fontWeight="400" app:fontVariationSettings="'contrast' 0.5"
+ app:font="@font/samplefont2" app:ttcIndex="1" />
+ <font app:fontStyle="normal" app:fontWeight="700" app:fontVariationSettings="'wdth' 500.0, 'wght' 300.0"
+ app:font="@font/samplefont3" app:ttcIndex="2" />
+ <font app:fontStyle="italic" app:fontWeight="700" app:font="@font/samplefont4" />
+</font-family>
diff --git a/compat/tests/res/font/samplexmlfontforparsing2.xml b/compat/tests/res/font/samplexmlfontforparsing2.xml
new file mode 100644
index 0000000..eb310ba
--- /dev/null
+++ b/compat/tests/res/font/samplexmlfontforparsing2.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2017 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<font-family xmlns:android="http://schemas.android.com/apk/res/android" >
+ <font android:fontStyle="normal" android:fontWeight="400" android:fontVariationSettings="'wdth' 0.8"
+ android:font="@font/samplefont" android:ttcIndex="0" />
+ <font android:fontStyle="italic" android:fontWeight="400" android:fontVariationSettings="'contrast' 0.5"
+ android:font="@font/samplefont2" android:ttcIndex="1" />
+ <font android:fontStyle="normal" android:fontWeight="700" android:fontVariationSettings="'wdth' 500.0, 'wght' 300.0"
+ android:font="@font/samplefont3" android:ttcIndex="2" />
+ <font android:fontStyle="italic" android:fontWeight="700" android:font="@font/samplefont4" />
+</font-family>
diff --git a/compat/tests/res/font/ttctestfont1.xml b/compat/tests/res/font/ttctestfont1.xml
new file mode 100644
index 0000000..a2b75e3
--- /dev/null
+++ b/compat/tests/res/font/ttctestfont1.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
+ <font app:font="@font/sample_font_collection" app:ttcIndex="0" />
+</font-family>
diff --git a/compat/tests/res/font/ttctestfont2.xml b/compat/tests/res/font/ttctestfont2.xml
new file mode 100644
index 0000000..e64ed6a
--- /dev/null
+++ b/compat/tests/res/font/ttctestfont2.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
+ <font app:font="@font/sample_font_collection" app:ttcIndex="1" />
+</font-family>
diff --git a/compat/tests/res/font/variable_width_dash_font.ttf b/compat/tests/res/font/variable_width_dash_font.ttf
new file mode 100644
index 0000000..f7a256a
--- /dev/null
+++ b/compat/tests/res/font/variable_width_dash_font.ttf
Binary files differ
diff --git a/compat/tests/res/font/variationsettingstestfont1.xml b/compat/tests/res/font/variationsettingstestfont1.xml
new file mode 100644
index 0000000..39052a6
--- /dev/null
+++ b/compat/tests/res/font/variationsettingstestfont1.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
+ <font app:font="@font/variable_width_dash_font" app:fontVariationSettings="'wdth' 100.0" />
+</font-family>
diff --git a/compat/tests/res/font/variationsettingstestfont2.xml b/compat/tests/res/font/variationsettingstestfont2.xml
new file mode 100644
index 0000000..90382d0
--- /dev/null
+++ b/compat/tests/res/font/variationsettingstestfont2.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
+ <font app:font="@font/variable_width_dash_font" app:fontVariationSettings="'wdth' 500.0" />
+</font-family>