Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 46df96f6 authored by Hawkwood Glazier's avatar Hawkwood Glazier Committed by Android (Google) Code Review
Browse files

Merge "Allow TextAnimator TypefaceCaches to be shared" into udc-dev

parents 53c93e84 b7aef990
Loading
Loading
Loading
Loading
+35 −14
Original line number Diff line number Diff line
@@ -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,
+4 −2
Original line number Diff line number Diff line
@@ -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.
     *
+18 −11
Original line number Diff line number Diff line
@@ -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
            }