diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt index fdab7490e476f..a08b59829de2f 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt @@ -23,6 +23,7 @@ import android.animation.ValueAnimator import android.graphics.Canvas import android.graphics.Typeface import android.graphics.fonts.Font +import android.graphics.fonts.FontVariationAxis import android.text.Layout import android.util.SparseArray @@ -215,13 +216,40 @@ class TextAnimator(layout: Layout, private val invalidateCallback: () -> Unit) { textInterpolator.targetPaint.textSize = textSize } if (weight >= 0) { - // Paint#setFontVariationSettings creates Typeface instance from scratch. To reduce the - // memory impact, cache the typeface result. - textInterpolator.targetPaint.typeface = - typefaceCache.getOrElse(weight) { - textInterpolator.targetPaint.fontVariationSettings = "'$TAG_WGHT' $weight" - textInterpolator.targetPaint.typeface + val fontVariationArray = + FontVariationAxis.fromFontVariationSettings( + textInterpolator.targetPaint.fontVariationSettings + ) + if (fontVariationArray.isNullOrEmpty()) { + textInterpolator.targetPaint.typeface = + typefaceCache.getOrElse(weight) { + textInterpolator.targetPaint.fontVariationSettings = "'$TAG_WGHT' $weight" + textInterpolator.targetPaint.typeface + } + } else { + val idx = fontVariationArray.indexOfFirst { it.tag == "$TAG_WGHT" } + if (idx == -1) { + val updatedFontVariation = + textInterpolator.targetPaint.fontVariationSettings + ",'$TAG_WGHT' $weight" + textInterpolator.targetPaint.typeface = + typefaceCache.getOrElse(weight) { + textInterpolator.targetPaint.fontVariationSettings = + updatedFontVariation + textInterpolator.targetPaint.typeface + } + } else { + fontVariationArray[idx] = FontVariationAxis( + "$TAG_WGHT", weight.toFloat()) + val updatedFontVariation = + FontVariationAxis.toFontVariationSettings(fontVariationArray) + textInterpolator.targetPaint.typeface = + typefaceCache.getOrElse(weight) { + textInterpolator.targetPaint.fontVariationSettings = + updatedFontVariation + textInterpolator.targetPaint.typeface + } } + } } if (color != null) { textInterpolator.targetPaint.color = color diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/TextAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/TextAnimatorTest.kt index ed0cd7ed9b24a..31d0d1292fe7c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/animation/TextAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/TextAnimatorTest.kt @@ -19,6 +19,7 @@ package com.android.systemui.animation import android.animation.AnimatorListenerAdapter import android.animation.ValueAnimator import android.graphics.Typeface +import android.graphics.fonts.FontVariationAxis import android.testing.AndroidTestingRunner import android.text.Layout import android.text.StaticLayout @@ -178,4 +179,71 @@ class TextAnimatorTest : SysuiTestCase() { assertThat(paint.typeface).isSameInstanceAs(prevTypeface) } + + @Test + fun testSetTextStyle_addWeight() { + testWeightChange("", 100, FontVariationAxis.fromFontVariationSettings("'wght' 100")!!) + } + + @Test + fun testSetTextStyle_changeWeight() { + testWeightChange( + "'wght' 500", + 100, + FontVariationAxis.fromFontVariationSettings("'wght' 100")!! + ) + } + + @Test + fun testSetTextStyle_addWeightWithOtherAxis() { + testWeightChange( + "'wdth' 100", + 100, + FontVariationAxis.fromFontVariationSettings("'wght' 100, 'wdth' 100")!! + ) + } + + @Test + fun testSetTextStyle_changeWeightWithOtherAxis() { + testWeightChange( + "'wght' 500, 'wdth' 100", + 100, + FontVariationAxis.fromFontVariationSettings("'wght' 100, 'wdth' 100")!! + ) + } + + private fun testWeightChange( + initialFontVariationSettings: String, + weight: Int, + expectedFontVariationSettings: Array + ) { + val layout = makeLayout("Hello, World", PAINT) + val valueAnimator = mock(ValueAnimator::class.java) + val textInterpolator = mock(TextInterpolator::class.java) + val paint = + TextPaint().apply { + typeface = Typeface.createFromFile("/system/fonts/Roboto-Regular.ttf") + fontVariationSettings = initialFontVariationSettings + } + `when`(textInterpolator.targetPaint).thenReturn(paint) + + val textAnimator = + TextAnimator(layout, {}).apply { + this.textInterpolator = textInterpolator + this.animator = valueAnimator + } + textAnimator.setTextStyle(weight = weight, animate = false) + + val resultFontVariationList = + FontVariationAxis.fromFontVariationSettings( + textInterpolator.targetPaint.fontVariationSettings + ) + expectedFontVariationSettings.forEach { expectedAxis -> + val resultAxis = resultFontVariationList?.filter { it.tag == expectedAxis.tag }?.get(0) + assertThat(resultAxis).isNotNull() + if (resultAxis != null) { + assertThat(resultAxis.styleValue).isEqualTo(expectedAxis.styleValue) + } + } + } }