diff options
3 files changed, 57 insertions, 27 deletions
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 3ee97be360f0..9346a2f7ebb7 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt @@ -24,12 +24,30 @@ import android.graphics.Canvas import android.graphics.Typeface import android.graphics.fonts.Font import android.text.Layout +import android.text.TextPaint import android.util.LruCache private const val DEFAULT_ANIMATION_DURATION: Long = 300 private const val TYPEFACE_CACHE_MAX_ENTRIES = 5 typealias GlyphCallback = (TextAnimator.PositionedGlyph, Float) -> Unit + +interface TypefaceVariantCache { + fun getTypefaceForVariant(fvar: String, targetPaint: TextPaint): Typeface? +} + +class TypefaceVariantCacheImpl() : TypefaceVariantCache { + private val cache = LruCache<String, Typeface>(TYPEFACE_CACHE_MAX_ENTRIES) + override fun getTypefaceForVariant(fvar: String, targetPaint: TextPaint): Typeface? { + cache.get(fvar)?.let { + return it + } + + targetPaint.fontVariationSettings = fvar + return targetPaint.typeface?.also { cache.put(fvar, it) } + } +} + /** * This class provides text animation between two styles. * @@ -56,9 +74,19 @@ typealias GlyphCallback = (TextAnimator.PositionedGlyph, Float) -> Unit * ``` * </code> </pre> */ -class TextAnimator(layout: Layout, private val invalidateCallback: () -> Unit) { +class TextAnimator( + layout: Layout, + private val invalidateCallback: () -> Unit, +) { + var typefaceCache: TypefaceVariantCache = TypefaceVariantCacheImpl() + get() = field + set(value) { + field = value + textInterpolator.typefaceCache = value + } + // Following two members are for mutable for testing purposes. - public var textInterpolator: TextInterpolator = TextInterpolator(layout) + public var textInterpolator: TextInterpolator = TextInterpolator(layout, typefaceCache) public var animator: ValueAnimator = ValueAnimator.ofFloat(1f).apply { duration = DEFAULT_ANIMATION_DURATION @@ -68,9 +96,7 @@ class TextAnimator(layout: Layout, private val invalidateCallback: () -> Unit) { } addListener( object : AnimatorListenerAdapter() { - override fun onAnimationEnd(animation: Animator?) { - textInterpolator.rebase() - } + override fun onAnimationEnd(animation: Animator?) = textInterpolator.rebase() override fun onAnimationCancel(animation: Animator?) = textInterpolator.rebase() } ) @@ -116,8 +142,6 @@ class TextAnimator(layout: Layout, private val invalidateCallback: () -> Unit) { private val fontVariationUtils = FontVariationUtils() - private val typefaceCache = LruCache<String, Typeface>(TYPEFACE_CACHE_MAX_ENTRIES) - fun updateLayout(layout: Layout) { textInterpolator.layout = layout } @@ -220,12 +244,8 @@ class TextAnimator(layout: Layout, private val invalidateCallback: () -> Unit) { } if (!fvar.isNullOrBlank()) { - textInterpolator.targetPaint.typeface = typefaceCache.get(fvar) ?: run { - textInterpolator.targetPaint.fontVariationSettings = fvar - textInterpolator.targetPaint.typeface?.also { - typefaceCache.put(fvar, textInterpolator.targetPaint.typeface) - } - } + textInterpolator.targetPaint.typeface = + typefaceCache.getTypefaceForVariant(fvar, textInterpolator.targetPaint) } if (color != null) { @@ -304,7 +324,8 @@ class TextAnimator(layout: Layout, private val invalidateCallback: () -> Unit) { weight = weight, width = width, opticalSize = opticalSize, - roundness = roundness,) + roundness = roundness, + ) setTextStyle( fvar = fvar, textSize = textSize, diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt index 23f16f2a3137..a041926bf5d2 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt @@ -28,8 +28,10 @@ import com.android.internal.graphics.ColorUtils import java.lang.Math.max /** Provide text style linear interpolation for plain text. */ -class TextInterpolator(layout: Layout) { - +class TextInterpolator( + layout: Layout, + var typefaceCache: TypefaceVariantCache, +) { /** * Returns base paint used for interpolation. * diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/TextInterpolatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/TextInterpolatorTest.kt index 02d4ecd665fc..063757acc1a1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/animation/TextInterpolatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/TextInterpolatorTest.kt @@ -31,6 +31,7 @@ import android.text.TextPaint import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat +import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import java.io.File @@ -64,6 +65,7 @@ private val END_PAINT = TextPaint(PAINT).apply { @RunWith(AndroidTestingRunner::class) @SmallTest class TextInterpolatorTest : SysuiTestCase() { + lateinit var typefaceCache: TypefaceVariantCache private fun makeLayout( text: String, @@ -75,11 +77,16 @@ class TextInterpolatorTest : SysuiTestCase() { .setTextDirection(dir).build() } + @Before + fun setup() { + typefaceCache = TypefaceVariantCacheImpl() + } + @Test fun testStartState() { val layout = makeLayout(TEXT, PAINT) - val interp = TextInterpolator(layout) + val interp = TextInterpolator(layout, typefaceCache) interp.basePaint.set(START_PAINT) interp.onBasePaintModified() @@ -98,7 +105,7 @@ class TextInterpolatorTest : SysuiTestCase() { fun testEndState() { val layout = makeLayout(TEXT, PAINT) - val interp = TextInterpolator(layout) + val interp = TextInterpolator(layout, typefaceCache) interp.basePaint.set(START_PAINT) interp.onBasePaintModified() @@ -116,7 +123,7 @@ class TextInterpolatorTest : SysuiTestCase() { fun testMiddleState() { val layout = makeLayout(TEXT, PAINT) - val interp = TextInterpolator(layout) + val interp = TextInterpolator(layout, typefaceCache) interp.basePaint.set(START_PAINT) interp.onBasePaintModified() @@ -138,7 +145,7 @@ class TextInterpolatorTest : SysuiTestCase() { fun testRebase() { val layout = makeLayout(TEXT, PAINT) - val interp = TextInterpolator(layout) + val interp = TextInterpolator(layout, typefaceCache) interp.basePaint.set(START_PAINT) interp.onBasePaintModified() @@ -160,7 +167,7 @@ class TextInterpolatorTest : SysuiTestCase() { fun testBidi_LTR() { val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.LTR) - val interp = TextInterpolator(layout) + val interp = TextInterpolator(layout, typefaceCache) interp.basePaint.set(START_PAINT) interp.onBasePaintModified() @@ -180,7 +187,7 @@ class TextInterpolatorTest : SysuiTestCase() { fun testBidi_RTL() { val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.RTL) - val interp = TextInterpolator(layout) + val interp = TextInterpolator(layout, typefaceCache) interp.basePaint.set(START_PAINT) interp.onBasePaintModified() @@ -200,7 +207,7 @@ class TextInterpolatorTest : SysuiTestCase() { fun testGlyphCallback_Empty() { val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.RTL) - val interp = TextInterpolator(layout).apply { + val interp = TextInterpolator(layout, typefaceCache).apply { glyphFilter = { glyph, progress -> } } @@ -222,7 +229,7 @@ class TextInterpolatorTest : SysuiTestCase() { fun testGlyphCallback_Xcoordinate() { val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.RTL) - val interp = TextInterpolator(layout).apply { + val interp = TextInterpolator(layout, typefaceCache).apply { glyphFilter = { glyph, progress -> glyph.x += 30f } @@ -247,7 +254,7 @@ class TextInterpolatorTest : SysuiTestCase() { fun testGlyphCallback_Ycoordinate() { val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.RTL) - val interp = TextInterpolator(layout).apply { + val interp = TextInterpolator(layout, typefaceCache).apply { glyphFilter = { glyph, progress -> glyph.y += 30f } @@ -272,7 +279,7 @@ class TextInterpolatorTest : SysuiTestCase() { fun testGlyphCallback_TextSize() { val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.RTL) - val interp = TextInterpolator(layout).apply { + val interp = TextInterpolator(layout, typefaceCache).apply { glyphFilter = { glyph, progress -> glyph.textSize += 10f } @@ -297,7 +304,7 @@ class TextInterpolatorTest : SysuiTestCase() { fun testGlyphCallback_Color() { val layout = makeLayout(BIDI_TEXT, PAINT, TextDirectionHeuristics.RTL) - val interp = TextInterpolator(layout).apply { + val interp = TextInterpolator(layout, typefaceCache).apply { glyphFilter = { glyph, progress -> glyph.color = Color.RED } |