diff --git a/api/current.txt b/api/current.txt
index 6d491cdac3f2b..2eafbadfe84a7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -12731,6 +12731,7 @@ package android.graphics {
method public int getFontMetricsInt(android.graphics.Paint.FontMetricsInt);
method public android.graphics.Paint.FontMetricsInt getFontMetricsInt();
method public float getFontSpacing();
+ method public java.lang.String getFontVariationSettings();
method public int getHinting();
method public float getLetterSpacing();
method public android.graphics.MaskFilter getMaskFilter();
@@ -12788,6 +12789,7 @@ package android.graphics {
method public void setFilterBitmap(boolean);
method public void setFlags(int);
method public void setFontFeatureSettings(java.lang.String);
+ method public void setFontVariationSettings(java.lang.String);
method public void setHinting(int);
method public void setLetterSpacing(float);
method public void setLinearText(boolean);
@@ -49983,6 +49985,7 @@ package android.widget {
method public int getExtendedPaddingTop();
method public android.text.InputFilter[] getFilters();
method public java.lang.String getFontFeatureSettings();
+ method public java.lang.String getFontVariationSettings();
method public boolean getFreezesText();
method public int getGravity();
method public int getHighlightColor();
@@ -50092,6 +50095,7 @@ package android.widget {
method public void setExtractedText(android.view.inputmethod.ExtractedText);
method public void setFilters(android.text.InputFilter[]);
method public void setFontFeatureSettings(java.lang.String);
+ method public void setFontVariationSettings(java.lang.String);
method protected boolean setFrame(int, int, int, int);
method public void setFreezesText(boolean);
method public void setGravity(int);
diff --git a/api/system-current.txt b/api/system-current.txt
index 7a08e8a7c977f..08b7431030b6a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -13293,6 +13293,7 @@ package android.graphics {
method public int getFontMetricsInt(android.graphics.Paint.FontMetricsInt);
method public android.graphics.Paint.FontMetricsInt getFontMetricsInt();
method public float getFontSpacing();
+ method public java.lang.String getFontVariationSettings();
method public int getHinting();
method public float getLetterSpacing();
method public android.graphics.MaskFilter getMaskFilter();
@@ -13350,6 +13351,7 @@ package android.graphics {
method public void setFilterBitmap(boolean);
method public void setFlags(int);
method public void setFontFeatureSettings(java.lang.String);
+ method public void setFontVariationSettings(java.lang.String);
method public void setHinting(int);
method public void setLetterSpacing(float);
method public void setLinearText(boolean);
@@ -53749,6 +53751,7 @@ package android.widget {
method public int getExtendedPaddingTop();
method public android.text.InputFilter[] getFilters();
method public java.lang.String getFontFeatureSettings();
+ method public java.lang.String getFontVariationSettings();
method public boolean getFreezesText();
method public int getGravity();
method public int getHighlightColor();
@@ -53858,6 +53861,7 @@ package android.widget {
method public void setExtractedText(android.view.inputmethod.ExtractedText);
method public void setFilters(android.text.InputFilter[]);
method public void setFontFeatureSettings(java.lang.String);
+ method public void setFontVariationSettings(java.lang.String);
method protected boolean setFrame(int, int, int, int);
method public void setFreezesText(boolean);
method public void setGravity(int);
diff --git a/api/test-current.txt b/api/test-current.txt
index cd335e771a097..f4a6af96f174f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -12765,6 +12765,7 @@ package android.graphics {
method public int getFontMetricsInt(android.graphics.Paint.FontMetricsInt);
method public android.graphics.Paint.FontMetricsInt getFontMetricsInt();
method public float getFontSpacing();
+ method public java.lang.String getFontVariationSettings();
method public int getHinting();
method public float getLetterSpacing();
method public android.graphics.MaskFilter getMaskFilter();
@@ -12822,6 +12823,7 @@ package android.graphics {
method public void setFilterBitmap(boolean);
method public void setFlags(int);
method public void setFontFeatureSettings(java.lang.String);
+ method public void setFontVariationSettings(java.lang.String);
method public void setHinting(int);
method public void setLetterSpacing(float);
method public void setLinearText(boolean);
@@ -50303,6 +50305,7 @@ package android.widget {
method public int getExtendedPaddingTop();
method public android.text.InputFilter[] getFilters();
method public java.lang.String getFontFeatureSettings();
+ method public java.lang.String getFontVariationSettings();
method public boolean getFreezesText();
method public int getGravity();
method public int getHighlightColor();
@@ -50412,6 +50415,7 @@ package android.widget {
method public void setExtractedText(android.view.inputmethod.ExtractedText);
method public void setFilters(android.text.InputFilter[]);
method public void setFontFeatureSettings(java.lang.String);
+ method public void setFontVariationSettings(java.lang.String);
method protected boolean setFrame(int, int, int, int);
method public void setFreezesText(boolean);
method public void setGravity(int);
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 51b5b13c10d31..60382a0b83b55 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3432,6 +3432,20 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return mTextPaint.getFontFeatureSettings();
}
+ /**
+ * Returns the font variation settings.
+ *
+ * @return the currently set font variation settings. Returns null if no variation is
+ * specified.
+ *
+ * @see #setFontVariationSettings(String)
+ * @see Paint#setFontVariationSettings(String) Paint.setFontVariationSettings(String)
+ */
+ @Nullable
+ public String getFontVariationSettings() {
+ return mTextPaint.getFontVariationSettings();
+ }
+
/**
* Sets the break strategy for breaking paragraphs into lines. The default value for
* TextView is {@link Layout#BREAK_STRATEGY_HIGH_QUALITY}, and the default value for
@@ -3538,6 +3552,41 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
+ /**
+ * Sets TrueType or OpenType font variation settings. The settings string is constructed from
+ * multiple pairs of axis tag and style values. The axis tag must contain four ASCII characters
+ * and must be wrapped with single quotes (U+0027) or double quotes (U+0022). Axis strings that
+ * are longer or shorter than four characters, or contain characters outside of U+0020..U+007E
+ * are invalid. If a specified axis name is not defined in the font, the settings will be
+ * ignored.
+ *
+ *
+ * textView.setFontVariationSettings("'wdth' 1.0");
+ * textView.setFontVariationSettings("'AX ' 1.8, 'FB ' 2.0");
+ *
+ *
+ * @param fontVariationSettings font variation settings. You can pass null or empty string as
+ * no variation settings.
+ *
+ * @see #getFontVariationSettings()
+ * @see Paint#getFontVariationSettings() Paint.getFontVariationSettings()
+ */
+ public void setFontVariationSettings(@Nullable String fontVariationSettings) {
+ final String existingSettings = mTextPaint.getFontVariationSettings();
+ if (fontVariationSettings == existingSettings
+ || (fontVariationSettings != null
+ && fontVariationSettings.equals(existingSettings))) {
+ return;
+ }
+ mTextPaint.setFontVariationSettings(fontVariationSettings);
+
+ if (mLayout != null) {
+ nullLayouts();
+ requestLayout();
+ invalidate();
+ }
+ }
+
/**
* Sets the text color for all the states (normal, selected,
* focused) to be this color.
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 327f142fc319e..cf9441b5c69c6 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -118,6 +118,7 @@ LOCAL_SRC_FILES:= \
android/graphics/ColorFilter.cpp \
android/graphics/DrawFilter.cpp \
android/graphics/FontFamily.cpp \
+ android/graphics/FontUtils.cpp \
android/graphics/CreateJavaOutputStreamAdaptor.cpp \
android/graphics/GIFMovie.cpp \
android/graphics/GraphicBuffer.cpp \
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 0c863fd6eca86..6ec658b9b916e 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -30,6 +30,7 @@
#include
#include
#include "Utils.h"
+#include "FontUtils.h"
#include
#include
@@ -149,16 +150,6 @@ static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong builderPtr,
return true;
}
-static struct {
- jmethodID mGet;
- jmethodID mSize;
-} gListClassInfo;
-
-static struct {
- jfieldID mTag;
- jfieldID mStyleValue;
-} gAxisClassInfo;
-
static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong builderPtr,
jobject font, jint ttcIndex, jobject listOfAxis, jint weight, jboolean isItalic) {
NPE_CHECK_RETURN_ZERO(env, font);
@@ -167,20 +158,22 @@ static jboolean FontFamily_addFontWeightStyle(JNIEnv* env, jobject clazz, jlong
std::unique_ptr skiaAxes;
int skiaAxesLength = 0;
if (listOfAxis) {
- jint listSize = env->CallIntMethod(listOfAxis, gListClassInfo.mSize);
+ ListHelper list(env, listOfAxis);
+ jint listSize = list.size();
skiaAxes.reset(new SkFontMgr::FontParameters::Axis[listSize]);
skiaAxesLength = listSize;
for (jint i = 0; i < listSize; ++i) {
- jobject axisObject = env->CallObjectMethod(listOfAxis, gListClassInfo.mGet, i);
+ jobject axisObject = list.get(i);
if (!axisObject) {
skiaAxes[i].fTag = 0;
skiaAxes[i].fStyleValue = 0;
continue;
}
+ AxisHelper axis(env, axisObject);
- jint tag = env->GetIntField(axisObject, gAxisClassInfo.mTag);
- jfloat stylevalue = env->GetFloatField(axisObject, gAxisClassInfo.mStyleValue);
+ jint tag = axis.getTag();
+ jfloat stylevalue = axis.getStyleValue();
skiaAxes[i].fTag = tag;
skiaAxes[i].fStyleValue = SkFloatToScalar(stylevalue);
}
@@ -291,14 +284,7 @@ int register_android_graphics_FontFamily(JNIEnv* env)
int err = RegisterMethodsOrDie(env, "android/graphics/FontFamily", gFontFamilyMethods,
NELEM(gFontFamilyMethods));
- jclass listClass = FindClassOrDie(env, "java/util/List");
- gListClassInfo.mGet = GetMethodIDOrDie(env, listClass, "get", "(I)Ljava/lang/Object;");
- gListClassInfo.mSize = GetMethodIDOrDie(env, listClass, "size", "()I");
-
- jclass axisClass = FindClassOrDie(env, "android/text/FontConfig$Axis");
- gAxisClassInfo.mTag = GetFieldIDOrDie(env, axisClass, "mTag", "I");
- gAxisClassInfo.mStyleValue = GetFieldIDOrDie(env, axisClass, "mStyleValue", "F");
-
+ init_FontUtils(env);
return err;
}
diff --git a/core/jni/android/graphics/FontUtils.h b/core/jni/android/graphics/FontUtils.h
new file mode 100644
index 0000000000000..8f44b1e82de8b
--- /dev/null
+++ b/core/jni/android/graphics/FontUtils.h
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#ifndef _ANDROID_GRAPHICS_FONT_UTILS_H_
+#define _ANDROID_GRAPHICS_FONT_UTILS_H_
+
+#include
+
+namespace android {
+
+// Utility wrapper for java.util.List
+class ListHelper {
+public:
+ ListHelper(JNIEnv* env, jobject list) : mEnv(env), mList(list) {}
+
+ jint size() const;
+ jobject get(jint index) const;
+
+private:
+ JNIEnv* mEnv;
+ jobject mList;
+};
+
+// Utility wrapper for android.graphics.FontConfig$Axis
+class AxisHelper {
+public:
+ AxisHelper(JNIEnv* env, jobject axis) : mEnv(env), mAxis(axis) {}
+
+ jint getTag() const;
+ jfloat getStyleValue() const;
+
+private:
+ JNIEnv* mEnv;
+ jobject mAxis;
+};
+
+void init_FontUtils(JNIEnv* env);
+
+}; // namespace android
+
+#endif // _ANDROID_GRAPHICS_FONT_UTILS_H_
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index c920b8d653ab3..0a0fce3ecfabf 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -17,12 +17,14 @@
#include "jni.h"
#include "core_jni_helpers.h"
+#include "FontUtils.h"
#include "GraphicsJNI.h"
#include "ScopedPrimitiveArray.h"
#include "SkTypeface.h"
#include
#include
#include
+#include
using namespace android;
@@ -40,6 +42,23 @@ static jlong Typeface_createFromTypeface(JNIEnv* env, jobject, jlong familyHandl
return reinterpret_cast(face);
}
+static jlong Typeface_createFromTypefaceWithVariation(JNIEnv* env, jobject, jlong familyHandle,
+ jobject listOfAxis) {
+ std::vector variations;
+ ListHelper list(env, listOfAxis);
+ for (jint i = 0; i < list.size(); i++) {
+ jobject axisObject = list.get(i);
+ if (axisObject == nullptr) {
+ continue;
+ }
+ AxisHelper axis(env, axisObject);
+ variations.push_back(minikin::FontVariation(axis.getTag(), axis.getStyleValue()));
+ }
+ Typeface* baseTypeface = reinterpret_cast(familyHandle);
+ Typeface* result = Typeface::createFromTypefaceWithVariation(baseTypeface, variations);
+ return reinterpret_cast(result);
+}
+
static jlong Typeface_createWeightAlias(JNIEnv* env, jobject, jlong familyHandle, jint weight) {
Typeface* family = reinterpret_cast(familyHandle);
Typeface* face = Typeface::createWeightAlias(family, weight);
@@ -77,6 +96,8 @@ static void Typeface_setDefault(JNIEnv *env, jobject, jlong faceHandle) {
static const JNINativeMethod gTypefaceMethods[] = {
{ "nativeCreateFromTypeface", "(JI)J", (void*)Typeface_createFromTypeface },
+ { "nativeCreateFromTypefaceWithVariation", "(JLjava/util/List;)J",
+ (void*)Typeface_createFromTypefaceWithVariation },
{ "nativeCreateWeightAlias", "(JI)J", (void*)Typeface_createWeightAlias },
{ "nativeUnref", "(J)V", (void*)Typeface_unref },
{ "nativeGetStyle", "(J)I", (void*)Typeface_getStyle },
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index 4ec564ac58099..b757842c4f3fb 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -22,6 +22,7 @@ import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import android.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import java.io.IOException;
@@ -52,9 +53,12 @@ public class FontListParser {
// Note that a well-formed variation contains a four-character tag and a float as styleValue,
// with spacers in between. The tag is enclosd either by double quotes or single quotes.
@VisibleForTesting
- public static FontConfig.Axis[] parseFontVariationSettings(String settings) {
- String[] settingList = settings.split(",");
+ public static ArrayList parseFontVariationSettings(@Nullable String settings) {
ArrayList axisList = new ArrayList<>();
+ if (settings == null) {
+ return axisList;
+ }
+ String[] settingList = settings.split(",");
settingLoop:
for (String setting : settingList) {
int pos = 0;
@@ -98,7 +102,7 @@ public class FontListParser {
tagString.charAt(3));
axisList.add(new FontConfig.Axis(tag, styleValue));
}
- return axisList.toArray(new FontConfig.Axis[axisList.size()]);
+ return axisList;
}
@VisibleForTesting
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 7815ae16e7e2c..4ee0c34139686 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -71,6 +71,7 @@ public class Paint {
private LocaleList mLocales;
private String mFontFeatureSettings;
+ private String mFontVariationSettings;
private static final Object sCacheLock = new Object();
@@ -1493,6 +1494,37 @@ public class Paint {
nSetFontFeatureSettings(mNativePaint, settings);
}
+ /**
+ * Returns the font variation settings.
+ *
+ * @return the paint's currently set font variation settings. Default is null.
+ *
+ * @see #setFontVariationSettings(String)
+ */
+ public String getFontVariationSettings() {
+ return mFontVariationSettings;
+ }
+
+ /**
+ * Set font variation settings.
+ *
+ * @param settings font variation settings, e.g. "'wdth' 300, 'wght' 1.8"
+ *
+ * @see #getFontVariationSettings()
+ *
+ * @param settings the font variation settings. You can pass null or empty string as no
+ * variation settings.
+ */
+ public void setFontVariationSettings(String settings) {
+ settings = TextUtils.nullIfEmpty(settings);
+ if (settings == mFontVariationSettings
+ || (settings != null && settings.equals(mFontVariationSettings))) {
+ return;
+ }
+ mFontVariationSettings = settings;
+ setTypeface(Typeface.createFromTypefaceWithVariation(mTypeface, settings));
+ }
+
/**
* Get the current value of hyphen edit.
*
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 38e806134c93a..f1f141acf91a6 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -31,6 +31,7 @@ import android.util.Log;
import android.util.LongSparseArray;
import android.util.LruCache;
import android.util.SparseArray;
+import android.graphics.FontListParser;
import com.android.internal.annotations.GuardedBy;
@@ -349,6 +350,15 @@ public class Typeface {
return typeface;
}
+ /** @hide */
+ public static Typeface createFromTypefaceWithVariation(Typeface family,
+ String fontVariationSettings) {
+ final long ni = family == null ? 0 : family.native_instance;
+ ArrayList axes =
+ FontListParser.parseFontVariationSettings(fontVariationSettings);
+ return new Typeface(nativeCreateFromTypefaceWithVariation(ni, axes));
+ }
+
/**
* Returns one of the default typeface objects, based on the specified style
*
@@ -625,6 +635,8 @@ public class Typeface {
}
private static native long nativeCreateFromTypeface(long native_instance, int style);
+ private static native long nativeCreateFromTypefaceWithVariation(
+ long native_instance, List axes);
private static native long nativeCreateWeightAlias(long native_instance, int weight);
private static native void nativeUnref(long native_instance);
private static native int nativeGetStyle(long native_instance);
diff --git a/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java b/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
index 2b4e6c27f193a..c7a46a3697720 100644
--- a/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
+++ b/graphics/tests/graphicstests/src/android/graphics/VariationParserTest.java
@@ -18,9 +18,8 @@ package android.graphics;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.FontConfig;
-import junit.framework.TestCase;
-
import java.util.List;
+import junit.framework.TestCase;
public class VariationParserTest extends TestCase {
@@ -28,92 +27,92 @@ public class VariationParserTest extends TestCase {
@SmallTest
public void testParseFontVariationSetting() {
int tag = FontListParser.makeTag('w', 'd', 't', 'h');
- FontConfig.Axis[] axis = FontListParser.parseFontVariationSettings("'wdth' 1");
- assertEquals(tag, axis[0].getTag());
- assertEquals(1.0f, axis[0].getStyleValue());
+ List axes = FontListParser.parseFontVariationSettings("'wdth' 1");
+ assertEquals(tag, axes.get(0).getTag());
+ assertEquals(1.0f, axes.get(0).getStyleValue());
- axis = FontListParser.parseFontVariationSettings("\"wdth\" 100");
- assertEquals(tag, axis[0].getTag());
- assertEquals(100.0f, axis[0].getStyleValue());
+ axes = FontListParser.parseFontVariationSettings("\"wdth\" 100");
+ assertEquals(tag, axes.get(0).getTag());
+ assertEquals(100.0f, axes.get(0).getStyleValue());
- axis = FontListParser.parseFontVariationSettings(" 'wdth' 100");
- assertEquals(tag, axis[0].getTag());
- assertEquals(100.0f, axis[0].getStyleValue());
+ axes = FontListParser.parseFontVariationSettings(" 'wdth' 100");
+ assertEquals(tag, axes.get(0).getTag());
+ assertEquals(100.0f, axes.get(0).getStyleValue());
- axis = FontListParser.parseFontVariationSettings("\t'wdth' 0.5");
- assertEquals(tag, axis[0].getTag());
- assertEquals(0.5f, axis[0].getStyleValue());
+ axes = FontListParser.parseFontVariationSettings("\t'wdth' 0.5");
+ assertEquals(tag, axes.get(0).getTag());
+ assertEquals(0.5f, axes.get(0).getStyleValue());
tag = FontListParser.makeTag('A', 'X', ' ', ' ');
- axis = FontListParser.parseFontVariationSettings("'AX ' 1");
- assertEquals(tag, axis[0].getTag());
- assertEquals(1.0f, axis[0].getStyleValue());
+ axes = FontListParser.parseFontVariationSettings("'AX ' 1");
+ assertEquals(tag, axes.get(0).getTag());
+ assertEquals(1.0f, axes.get(0).getStyleValue());
- axis = FontListParser.parseFontVariationSettings("'AX '\t1");
- assertEquals(tag, axis[0].getTag());
- assertEquals(1.0f, axis[0].getStyleValue());
+ axes = FontListParser.parseFontVariationSettings("'AX '\t1");
+ assertEquals(tag, axes.get(0).getTag());
+ assertEquals(1.0f, axes.get(0).getStyleValue());
- axis = FontListParser.parseFontVariationSettings("'AX '\n1");
- assertEquals(tag, axis[0].getTag());
- assertEquals(1.0f, axis[0].getStyleValue());
+ axes = FontListParser.parseFontVariationSettings("'AX '\n1");
+ assertEquals(tag, axes.get(0).getTag());
+ assertEquals(1.0f, axes.get(0).getStyleValue());
- axis = FontListParser.parseFontVariationSettings("'AX '\r1");
- assertEquals(tag, axis[0].getTag());
- assertEquals(1.0f, axis[0].getStyleValue());
+ axes = FontListParser.parseFontVariationSettings("'AX '\r1");
+ assertEquals(tag, axes.get(0).getTag());
+ assertEquals(1.0f, axes.get(0).getStyleValue());
- axis = FontListParser.parseFontVariationSettings("'AX '\r\t\n 1");
- assertEquals(tag, axis[0].getTag());
- assertEquals(1.0f, axis[0].getStyleValue());
+ axes = FontListParser.parseFontVariationSettings("'AX '\r\t\n 1");
+ assertEquals(tag, axes.get(0).getTag());
+ assertEquals(1.0f, axes.get(0).getStyleValue());
// Test for invalid input
- axis = FontListParser.parseFontVariationSettings("");
- assertEquals(0, axis.length);
- axis = FontListParser.parseFontVariationSettings("invalid_form");
- assertEquals(0, axis.length);
+ axes = FontListParser.parseFontVariationSettings("");
+ assertEquals(0, axes.size());
+ axes = FontListParser.parseFontVariationSettings("invalid_form");
+ assertEquals(0, axes.size());
// Test with invalid tag
- axis = FontListParser.parseFontVariationSettings("'' 1");
- assertEquals(0, axis.length);
- axis = FontListParser.parseFontVariationSettings("'invalid' 1");
- assertEquals(0, axis.length);
+ axes = FontListParser.parseFontVariationSettings("'' 1");
+ assertEquals(0, axes.size());
+ axes = FontListParser.parseFontVariationSettings("'invalid' 1");
+ assertEquals(0, axes.size());
// Test with invalid styleValue
- axis = FontListParser.parseFontVariationSettings("'wdth' ");
- assertEquals(0, axis.length);
- axis = FontListParser.parseFontVariationSettings("'wdth' x");
- assertEquals(0, axis.length);
- axis = FontListParser.parseFontVariationSettings("'wdth' \t");
- assertEquals(0, axis.length);
- axis = FontListParser.parseFontVariationSettings("'wdth' \n\r");
- assertEquals(0, axis.length);
+ axes = FontListParser.parseFontVariationSettings("'wdth' ");
+ assertEquals(0, axes.size());
+ axes = FontListParser.parseFontVariationSettings("'wdth' x");
+ assertEquals(0, axes.size());
+ axes = FontListParser.parseFontVariationSettings("'wdth' \t");
+ assertEquals(0, axes.size());
+ axes = FontListParser.parseFontVariationSettings("'wdth' \n\r");
+ assertEquals(0, axes.size());
}
@SmallTest
public void testParseFontVariationStyleSettings() {
- FontConfig.Axis[] axis =
+ List axes =
FontListParser.parseFontVariationSettings("'wdth' 10,'AX '\r1");
int tag1 = FontListParser.makeTag('w', 'd', 't', 'h');
int tag2 = FontListParser.makeTag('A', 'X', ' ', ' ');
- assertEquals(tag1, axis[0].getTag());
- assertEquals(10.0f, axis[0].getStyleValue());
- assertEquals(tag2, axis[1].getTag());
- assertEquals(1.0f, axis[1].getStyleValue());
+ assertEquals(tag1, axes.get(0).getTag());
+ assertEquals(10.0f, axes.get(0).getStyleValue());
+ assertEquals(tag2, axes.get(1).getTag());
+ assertEquals(1.0f, axes.get(1).getStyleValue());
// Test only spacers are allowed before tag
- axis = FontListParser.parseFontVariationSettings(" 'wdth' 10,ab'wdth' 1");
+ axes = FontListParser.parseFontVariationSettings(" 'wdth' 10,ab'wdth' 1");
tag1 = FontListParser.makeTag('w', 'd', 't', 'h');
- assertEquals(tag1, axis[0].getTag());
- assertEquals(10.0f, axis[0].getStyleValue());
- assertEquals(1, axis.length);
+ assertEquals(tag1, axes.get(0).getTag());
+ assertEquals(10.0f, axes.get(0).getStyleValue());
+ assertEquals(1, axes.size());
}
@SmallTest
public void testInvalidTagCharacters() {
- FontConfig.Axis[] axis =
+ List axes =
FontListParser.parseFontVariationSettings("'\u0000\u0000\u0000\u0000' 10");
- assertEquals(0, axis.length);
- axis = FontListParser.parseFontVariationSettings("'\u3042\u3044\u3046\u3048' 10");
- assertEquals(0, axis.length);
+ assertEquals(0, axes.size());
+ axes = FontListParser.parseFontVariationSettings("'\u3042\u3044\u3046\u3048' 10");
+ assertEquals(0, axes.size());
}
@SmallTest
diff --git a/libs/hwui/hwui/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index 956f66ed22cbd..6a003794fb283 100644
--- a/libs/hwui/hwui/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -17,7 +17,8 @@
#include "MinikinSkia.h"
#include
-
+#include
+#include
#include
#include
@@ -86,6 +87,28 @@ int MinikinFontSkia::GetFontIndex() const {
return mTtcIndex;
}
+minikin::MinikinFont* MinikinFontSkia::createFontWithVariation(
+ const std::vector& variations) const {
+ SkFontMgr::FontParameters params;
+
+ int ttcIndex;
+ SkStreamAsset* stream = mTypeface->openStream(&ttcIndex);
+ LOG_ALWAYS_FATAL_IF(stream == nullptr, "openStream failed");
+
+ params.setCollectionIndex(ttcIndex);
+ std::vector skAxes;
+ skAxes.resize(variations.size());
+ for (size_t i = 0; i < variations.size(); i++) {
+ skAxes[i].fTag = variations[i].axisTag;
+ skAxes[i].fStyleValue = SkFloatToScalar(variations[i].value);
+ }
+ params.setAxes(skAxes.data(), skAxes.size());
+ sk_sp fm(SkFontMgr::RefDefault());
+ sk_sp face(fm->createFromStream(stream, params));
+
+ return new MinikinFontSkia(std::move(face), mFontData, mFontSize, ttcIndex);
+}
+
uint32_t MinikinFontSkia::packPaintFlags(const SkPaint* paint) {
uint32_t flags = paint->getFlags();
SkPaint::Hinting hinting = paint->getHinting();
diff --git a/libs/hwui/hwui/MinikinSkia.h b/libs/hwui/hwui/MinikinSkia.h
index 3ee916c6e8b11..249b0cbe44de9 100644
--- a/libs/hwui/hwui/MinikinSkia.h
+++ b/libs/hwui/hwui/MinikinSkia.h
@@ -44,6 +44,8 @@ public:
const void* GetFontData() const;
size_t GetFontSize() const;
int GetFontIndex() const;
+ minikin::MinikinFont* createFontWithVariation(
+ const std::vector&) const;
static uint32_t packPaintFlags(const SkPaint* paint);
static void unpackPaintFlags(SkPaint* paint, uint32_t paintFlags);
diff --git a/libs/hwui/hwui/Typeface.cpp b/libs/hwui/hwui/Typeface.cpp
index 9041b44db849f..b69b0cb29efef 100644
--- a/libs/hwui/hwui/Typeface.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -62,7 +62,7 @@ Typeface* Typeface::resolveDefault(Typeface* src) {
Typeface* Typeface::createFromTypeface(Typeface* src, SkTypeface::Style style) {
Typeface* resolvedFace = Typeface::resolveDefault(src);
Typeface* result = new Typeface;
- if (result != 0) {
+ if (result != nullptr) {
result->fFontCollection = resolvedFace->fFontCollection;
result->fFontCollection->Ref();
result->fSkiaStyle = style;
@@ -72,10 +72,30 @@ Typeface* Typeface::createFromTypeface(Typeface* src, SkTypeface::Style style) {
return result;
}
+Typeface* Typeface::createFromTypefaceWithVariation(Typeface* src,
+ const std::vector& variations) {
+ Typeface* resolvedFace = Typeface::resolveDefault(src);
+ Typeface* result = new Typeface();
+ if (result != nullptr) {
+ result->fFontCollection =
+ resolvedFace->fFontCollection->createCollectionWithVariation(variations);
+ if (result->fFontCollection == nullptr) {
+ // None of passed axes are supported by this collection.
+ // So we will reuse the same collection with incrementing reference count.
+ result->fFontCollection = resolvedFace->fFontCollection;
+ result->fFontCollection->Ref();
+ }
+ result->fSkiaStyle = resolvedFace->fSkiaStyle;
+ result->fBaseWeight = resolvedFace->fBaseWeight;
+ resolveStyle(result);
+ }
+ return result;
+}
+
Typeface* Typeface::createWeightAlias(Typeface* src, int weight) {
Typeface* resolvedFace = Typeface::resolveDefault(src);
Typeface* result = new Typeface;
- if (result != 0) {
+ if (result != nullptr) {
result->fFontCollection = resolvedFace->fFontCollection;
result->fFontCollection->Ref();
result->fSkiaStyle = resolvedFace->fSkiaStyle;
diff --git a/libs/hwui/hwui/Typeface.h b/libs/hwui/hwui/Typeface.h
index 1be630c1e9780..4392ebc36badf 100644
--- a/libs/hwui/hwui/Typeface.h
+++ b/libs/hwui/hwui/Typeface.h
@@ -43,6 +43,9 @@ struct ANDROID_API Typeface {
static Typeface* createFromTypeface(Typeface* src, SkTypeface::Style style);
+ static Typeface* createFromTypefaceWithVariation(Typeface* src,
+ const std::vector& variations);
+
static Typeface* createWeightAlias(Typeface* src, int baseweight);
static Typeface* createFromFamilies(const std::vector& families);