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

Commit 4c49b379 authored by Hawkwood Glazier's avatar Hawkwood Glazier Committed by Automerger Merge Worker
Browse files

Merge "Allow TextAnimator TypefaceCaches to be shared" into udc-dev am: 46df96f6

parents dad95a6a 46df96f6
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
            }