Store font variation settings into native Paint
The stored font variation settings is not yet used.
Bug: 361260253
Test: TreeHugger
Flag: com.android.text.flags.typeface_redesign
Change-Id: Idba2995b472c6036077b2cb88abcf59149a89d34
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index b866382..68d8ebb 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -41,6 +41,7 @@
import android.text.TextUtils;
import com.android.internal.annotations.GuardedBy;
+import com.android.text.flags.Flags;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
@@ -2000,6 +2001,14 @@
}
/**
+ * A change ID for new font variation settings management.
+ * @hide
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = 36)
+ public static final long NEW_FONT_VARIATION_MANAGEMENT = 361260253L;
+
+ /**
* 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
@@ -2028,12 +2037,16 @@
* </li>
* </ul>
*
+ * <p>Note: If the application that targets API 35 or before, this function mutates the
+ * underlying typeface instance.
+ *
* @param fontVariationSettings font variation settings. You can pass null or empty string as
* no variation settings.
*
- * @return true if the given settings is effective to at least one font file underlying this
- * typeface. This function also returns true for empty settings string. Otherwise
- * returns false
+ * @return If the application that targets API 36 or later and is running on devices API 36 or
+ * later, this function always returns true. Otherwise, this function returns true if
+ * the given settings is effective to at least one font file underlying this typeface.
+ * This function also returns true for empty settings string. Otherwise returns false.
*
* @throws IllegalArgumentException If given string is not a valid font variation settings
* format
@@ -2042,6 +2055,26 @@
* @see FontVariationAxis
*/
public boolean setFontVariationSettings(String fontVariationSettings) {
+ final boolean useFontVariationStore = Flags.typefaceRedesign()
+ && CompatChanges.isChangeEnabled(NEW_FONT_VARIATION_MANAGEMENT);
+ if (useFontVariationStore) {
+ FontVariationAxis[] axes =
+ FontVariationAxis.fromFontVariationSettings(fontVariationSettings);
+ if (axes == null) {
+ nSetFontVariationOverride(mNativePaint, 0);
+ mFontVariationSettings = null;
+ return true;
+ }
+
+ long builderPtr = nCreateFontVariationBuilder(axes.length);
+ for (int i = 0; i < axes.length; ++i) {
+ nAddFontVariationToBuilder(builderPtr, axes[i].getOpenTypeTagValue(),
+ axes[i].getStyleValue());
+ }
+ nSetFontVariationOverride(mNativePaint, builderPtr);
+ mFontVariationSettings = fontVariationSettings;
+ return true;
+ }
final String settings = TextUtils.nullIfEmpty(fontVariationSettings);
if (settings == mFontVariationSettings
|| (settings != null && settings.equals(mFontVariationSettings))) {
@@ -3829,7 +3862,12 @@
private static native void nSetTextSize(long paintPtr, float textSize);
@CriticalNative
private static native boolean nEqualsForTextMeasurement(long leftPaintPtr, long rightPaintPtr);
-
+ @CriticalNative
+ private static native long nCreateFontVariationBuilder(int size);
+ @CriticalNative
+ private static native void nAddFontVariationToBuilder(long builderPtr, int tag, float value);
+ @CriticalNative
+ private static native void nSetFontVariationOverride(long paintPtr, long builderPtr);
// Following Native methods are kept for old Robolectric JNI signature used by
// SystemUIGoogleRoboRNGTests
diff --git a/libs/hwui/hwui/Paint.h b/libs/hwui/hwui/Paint.h
index 708f96e..7eb849f 100644
--- a/libs/hwui/hwui/Paint.h
+++ b/libs/hwui/hwui/Paint.h
@@ -159,6 +159,14 @@
return SkSamplingOptions(this->filterMode());
}
+ void setVariationOverride(minikin::VariationSettings&& varSettings) {
+ mFontVariationOverride = std::move(varSettings);
+ }
+
+ const minikin::VariationSettings& getFontVariationOverride() const {
+ return mFontVariationOverride;
+ }
+
// The Java flags (Paint.java) no longer fit into the native apis directly.
// These methods handle converting to and from them and the native representations
// in android::Paint.
@@ -179,6 +187,7 @@
float mLetterSpacing = 0;
float mWordSpacing = 0;
std::vector<minikin::FontFeature> mFontFeatureSettings;
+ minikin::VariationSettings mFontVariationOverride;
uint32_t mMinikinLocaleListId;
std::optional<minikin::FamilyVariant> mFamilyVariant;
uint32_t mHyphenEdit = 0;
diff --git a/libs/hwui/hwui/PaintImpl.cpp b/libs/hwui/hwui/PaintImpl.cpp
index c32ea01..6dfcedc 100644
--- a/libs/hwui/hwui/PaintImpl.cpp
+++ b/libs/hwui/hwui/PaintImpl.cpp
@@ -39,6 +39,7 @@
, mLetterSpacing(paint.mLetterSpacing)
, mWordSpacing(paint.mWordSpacing)
, mFontFeatureSettings(paint.mFontFeatureSettings)
+ , mFontVariationOverride(paint.mFontVariationOverride)
, mMinikinLocaleListId(paint.mMinikinLocaleListId)
, mFamilyVariant(paint.mFamilyVariant)
, mHyphenEdit(paint.mHyphenEdit)
@@ -59,6 +60,7 @@
mLetterSpacing = other.mLetterSpacing;
mWordSpacing = other.mWordSpacing;
mFontFeatureSettings = other.mFontFeatureSettings;
+ mFontVariationOverride = other.mFontVariationOverride;
mMinikinLocaleListId = other.mMinikinLocaleListId;
mFamilyVariant = other.mFamilyVariant;
mHyphenEdit = other.mHyphenEdit;
@@ -76,6 +78,7 @@
return static_cast<const SkPaint&>(a) == static_cast<const SkPaint&>(b) && a.mFont == b.mFont &&
a.mLooper == b.mLooper && a.mLetterSpacing == b.mLetterSpacing &&
a.mWordSpacing == b.mWordSpacing && a.mFontFeatureSettings == b.mFontFeatureSettings &&
+ a.mFontVariationOverride == b.mFontVariationOverride &&
a.mMinikinLocaleListId == b.mMinikinLocaleListId &&
a.mFamilyVariant == b.mFamilyVariant && a.mHyphenEdit == b.mHyphenEdit &&
a.mTypeface == b.mTypeface && a.mAlign == b.mAlign &&
diff --git a/libs/hwui/jni/Paint.cpp b/libs/hwui/jni/Paint.cpp
index 286f06a..da23792 100644
--- a/libs/hwui/jni/Paint.cpp
+++ b/libs/hwui/jni/Paint.cpp
@@ -1127,6 +1127,36 @@
return leftMinikinPaint == rightMinikinPaint;
}
+ struct VariationBuilder {
+ std::vector<minikin::FontVariation> varSettings;
+ };
+
+ static jlong createFontVariationBuilder(CRITICAL_JNI_PARAMS_COMMA jint size) {
+ VariationBuilder* builder = new VariationBuilder();
+ builder->varSettings.reserve(size);
+ return reinterpret_cast<jlong>(builder);
+ }
+
+ static void addFontVariationToBuilder(CRITICAL_JNI_PARAMS_COMMA jlong builderPtr, jint tag,
+ jfloat value) {
+ VariationBuilder* builder = reinterpret_cast<VariationBuilder*>(builderPtr);
+ builder->varSettings.emplace_back(static_cast<minikin::AxisTag>(tag), value);
+ }
+
+ static void setFontVariationOverride(CRITICAL_JNI_PARAMS_COMMA jlong paintHandle,
+ jlong builderPtr) {
+ Paint* paint = reinterpret_cast<Paint*>(paintHandle);
+ if (builderPtr == 0) {
+ paint->setVariationOverride(minikin::VariationSettings());
+ return;
+ }
+
+ VariationBuilder* builder = reinterpret_cast<VariationBuilder*>(builderPtr);
+ paint->setVariationOverride(
+ minikin::VariationSettings(builder->varSettings, false /* sorted */));
+ delete builder;
+ }
+
}; // namespace PaintGlue
static const JNINativeMethod methods[] = {
@@ -1235,6 +1265,9 @@
{"nSetShadowLayer", "(JFFFJJ)V", (void*)PaintGlue::setShadowLayer},
{"nHasShadowLayer", "(J)Z", (void*)PaintGlue::hasShadowLayer},
{"nEqualsForTextMeasurement", "(JJ)Z", (void*)PaintGlue::equalsForTextMeasurement},
+ {"nCreateFontVariationBuilder", "(I)J", (void*)PaintGlue::createFontVariationBuilder},
+ {"nAddFontVariationToBuilder", "(JIF)V", (void*)PaintGlue::addFontVariationToBuilder},
+ {"nSetFontVariationOverride", "(JJ)V", (void*)PaintGlue::setFontVariationOverride},
};
int register_android_graphics_Paint(JNIEnv* env) {