Loading packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt +15 −4 Original line number Diff line number Diff line Loading @@ -82,6 +82,10 @@ class TypefaceVariantCacheImpl(var baseTypeface: Typeface, override val animatio } } interface TextAnimatorListener : TextInterpolatorListener { fun onInvalidate() {} } /** * This class provides text animation between two styles. * Loading Loading @@ -110,13 +114,19 @@ class TypefaceVariantCacheImpl(var baseTypeface: Typeface, override val animatio class TextAnimator( layout: Layout, private val typefaceCache: TypefaceVariantCache, private val invalidateCallback: () -> Unit = {}, private val listener: TextAnimatorListener? = null, ) { @VisibleForTesting var textInterpolator = TextInterpolator(layout, typefaceCache) var textInterpolator = TextInterpolator(layout, typefaceCache, listener) @VisibleForTesting var createAnimator: () -> ValueAnimator = { ValueAnimator.ofFloat(1f) } var animator: ValueAnimator? = null val progress: Float get() = textInterpolator.progress val linearProgress: Float get() = textInterpolator.linearProgress val fontVariationUtils = FontVariationUtils() sealed class PositionedGlyph { Loading Loading @@ -288,8 +298,9 @@ class TextAnimator( animator = buildAnimator(animation).apply { start() } } else { textInterpolator.progress = 1f textInterpolator.linearProgress = 1f textInterpolator.rebase() invalidateCallback() listener?.onInvalidate() } } Loading @@ -302,7 +313,7 @@ class TextAnimator( addUpdateListener { textInterpolator.progress = it.animatedValue as Float textInterpolator.linearProgress = it.currentPlayTime / it.duration.toFloat() invalidateCallback() listener?.onInvalidate() } addListener( Loading packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt +17 −1 Original line number Diff line number Diff line Loading @@ -27,8 +27,19 @@ import android.util.MathUtils import com.android.internal.graphics.ColorUtils import java.lang.Math.max interface TextInterpolatorListener { fun onPaintModified() {} fun onRebased() {} } /** Provide text style linear interpolation for plain text. */ class TextInterpolator(layout: Layout, var typefaceCache: TypefaceVariantCache) { class TextInterpolator( layout: Layout, var typefaceCache: TypefaceVariantCache, private val listener: TextInterpolatorListener? = null, ) { /** * Returns base paint used for interpolation. * Loading Loading @@ -136,6 +147,7 @@ class TextInterpolator(layout: Layout, var typefaceCache: TypefaceVariantCache) */ fun onTargetPaintModified() { updatePositionsAndFonts(shapeText(layout, targetPaint), updateBase = false) listener?.onPaintModified() } /** Loading @@ -146,6 +158,7 @@ class TextInterpolator(layout: Layout, var typefaceCache: TypefaceVariantCache) */ fun onBasePaintModified() { updatePositionsAndFonts(shapeText(layout, basePaint), updateBase = true) listener?.onPaintModified() } /** Loading Loading @@ -204,6 +217,7 @@ class TextInterpolator(layout: Layout, var typefaceCache: TypefaceVariantCache) */ fun rebase() { if (progress == 0f) { listener?.onRebased() return } else if (progress == 1f) { basePaint.set(targetPaint) Loading Loading @@ -233,6 +247,8 @@ class TextInterpolator(layout: Layout, var typefaceCache: TypefaceVariantCache) } progress = 0f linearProgress = 0f listener?.onRebased() } /** Loading packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt +8 −1 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import com.android.app.animation.Interpolators import com.android.internal.annotations.VisibleForTesting import com.android.systemui.animation.GlyphCallback import com.android.systemui.animation.TextAnimator import com.android.systemui.animation.TextAnimatorListener import com.android.systemui.animation.TypefaceVariantCacheImpl import com.android.systemui.customization.R import com.android.systemui.log.core.LogLevel Loading Loading @@ -100,7 +101,13 @@ constructor( @VisibleForTesting var textAnimatorFactory: (Layout, () -> Unit) -> TextAnimator = { layout, invalidateCb -> val cache = TypefaceVariantCacheImpl(layout.paint.typeface, NUM_CLOCK_FONT_ANIMATION_STEPS) TextAnimator(layout, cache, invalidateCb) TextAnimator( layout, cache, object : TextAnimatorListener { override fun onInvalidate() = invalidateCb() }, ) } // Used by screenshot tests to provide stability Loading packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt +29 −19 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ import android.graphics.PorterDuff import android.graphics.PorterDuffXfermode import android.graphics.Rect import android.os.VibrationEffect import android.text.Layout import android.text.TextPaint import android.util.AttributeSet import android.util.Log Loading @@ -39,6 +38,7 @@ import com.android.app.animation.Interpolators import com.android.internal.annotations.VisibleForTesting import com.android.systemui.animation.GSFAxes import com.android.systemui.animation.TextAnimator import com.android.systemui.animation.TextAnimatorListener import com.android.systemui.customization.R import com.android.systemui.plugins.clocks.ClockFontAxisSetting import com.android.systemui.plugins.clocks.ClockFontAxisSetting.Companion.replace Loading Loading @@ -175,11 +175,6 @@ open class SimpleDigitalClockTextView( private val typefaceCache = clockCtx.typefaceCache.getVariantCache("") @VisibleForTesting var textAnimatorFactory: (Layout, () -> Unit) -> TextAnimator = { layout, invalidateCb -> TextAnimator(layout, typefaceCache, invalidateCb) } var verticalAlignment: VerticalAlignment = VerticalAlignment.BASELINE var horizontalAlignment: HorizontalAlignment = HorizontalAlignment.CENTER Loading Loading @@ -247,7 +242,18 @@ open class SimpleDigitalClockTextView( val layout = this.layout if (layout != null) { if (!this::textAnimator.isInitialized) { textAnimator = textAnimatorFactory(layout, ::invalidate) textAnimator = TextAnimator( layout, typefaceCache, object : TextAnimatorListener { override fun onInvalidate() = invalidate() override fun onRebased() = updateTextBounds() override fun onPaintModified() = updateTextBounds() }, ) setInterpolatorPaint() } else { textAnimator.updateLayout(layout) Loading @@ -272,7 +278,7 @@ open class SimpleDigitalClockTextView( override fun onDraw(canvas: Canvas) { logger.onDraw(textAnimator.textInterpolator.shapedText) val interpProgress = getInterpolatedProgress() val interpProgress = textAnimator.progress val interpBounds = getInterpolatedTextBounds(interpProgress) if (interpProgress != drawnProgress) { drawnProgress = interpProgress Loading Loading @@ -336,7 +342,6 @@ open class SimpleDigitalClockTextView( interpolator = aodDozingInterpolator, ), ) updateTextBoundsForTextAnimator() if (!isAnimated) { requestLayout() Loading Loading @@ -367,11 +372,9 @@ open class SimpleDigitalClockTextView( duration = CHARGE_ANIMATION_DURATION, ), ) updateTextBoundsForTextAnimator() }, ), ) updateTextBoundsForTextAnimator() } fun animateFidget(x: Float, y: Float) = animateFidget(0L) Loading Loading @@ -401,11 +404,9 @@ open class SimpleDigitalClockTextView( interpolator = FIDGET_INTERPOLATOR, ), ) updateTextBoundsForTextAnimator() }, ), ) updateTextBoundsForTextAnimator() } fun refreshText() { Loading @@ -428,12 +429,8 @@ open class SimpleDigitalClockTextView( id == R.id.MINUTE_SECOND_DIGIT } private fun getInterpolatedProgress(): Float { return textAnimator.animator?.let { it.animatedValue as Float } ?: 1f } /** Returns the interpolated text bounding rect based on interpolation progress */ private fun getInterpolatedTextBounds(progress: Float = getInterpolatedProgress()): VRectF { private fun getInterpolatedTextBounds(progress: Float = textAnimator.progress): VRectF { if (progress <= 0f) { return prevTextBounds } else if (!textAnimator.isRunning || progress >= 1f) { Loading Loading @@ -487,6 +484,15 @@ open class SimpleDigitalClockTextView( MeasureSpec.makeMeasureSpec(measureBounds.x.roundToInt(), mode.x), MeasureSpec.makeMeasureSpec(measureBounds.y.roundToInt(), mode.y), ) logger.d({ val size = VPointF.fromLong(long1) val mode = VPoint.fromLong(long2) "setInterpolatedSize(size=$size, mode=$mode)" }) { long1 = measureBounds.toLong() long2 = mode.toLong() } } /** Set the location of the view to match the interpolated text bounds */ Loading Loading @@ -514,6 +520,9 @@ open class SimpleDigitalClockTextView( targetRect.bottom.roundToInt(), ) onViewBoundsChanged?.let { it(targetRect) } logger.d({ "setInterpolatedLocation(${VRectF.fromLong(long1)})" }) { long1 = targetRect.toLong() } return targetRect } Loading Loading @@ -616,7 +625,8 @@ open class SimpleDigitalClockTextView( * rebase if previous animator is canceled so basePaint will store the state we transition from * and targetPaint will store the state we transition to */ private fun updateTextBoundsForTextAnimator() { private fun updateTextBounds() { drawnProgress = null prevTextBounds = textAnimator.textInterpolator.basePaint.getTextBounds(text) targetTextBounds = textAnimator.textInterpolator.targetPaint.getTextBounds(text) } Loading packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockLogger.kt +3 −3 Original line number Diff line number Diff line Loading @@ -55,9 +55,9 @@ class ClockLogger(private val view: View?, buffer: MessageBuffer, tag: String) : } fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { d({ "onLayout($bool1, ${VRect(long1.toULong())})" }) { d({ "onLayout($bool1, ${VRect.fromLong(long1)})" }) { bool1 = changed long1 = VRect(left, top, right, bottom).data.toLong() long1 = VRect(left, top, right, bottom).toLong() } } Loading Loading @@ -116,7 +116,7 @@ class ClockLogger(private val view: View?, buffer: MessageBuffer, tag: String) : } fun animateFidget(x: Float, y: Float) { d({ "animateFidget(${VPointF(long1.toULong())})" }) { long1 = VPointF(x, y).data.toLong() } d({ "animateFidget(${VPointF.fromLong(long1)})" }) { long1 = VPointF(x, y).toLong() } } companion object { Loading Loading
packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt +15 −4 Original line number Diff line number Diff line Loading @@ -82,6 +82,10 @@ class TypefaceVariantCacheImpl(var baseTypeface: Typeface, override val animatio } } interface TextAnimatorListener : TextInterpolatorListener { fun onInvalidate() {} } /** * This class provides text animation between two styles. * Loading Loading @@ -110,13 +114,19 @@ class TypefaceVariantCacheImpl(var baseTypeface: Typeface, override val animatio class TextAnimator( layout: Layout, private val typefaceCache: TypefaceVariantCache, private val invalidateCallback: () -> Unit = {}, private val listener: TextAnimatorListener? = null, ) { @VisibleForTesting var textInterpolator = TextInterpolator(layout, typefaceCache) var textInterpolator = TextInterpolator(layout, typefaceCache, listener) @VisibleForTesting var createAnimator: () -> ValueAnimator = { ValueAnimator.ofFloat(1f) } var animator: ValueAnimator? = null val progress: Float get() = textInterpolator.progress val linearProgress: Float get() = textInterpolator.linearProgress val fontVariationUtils = FontVariationUtils() sealed class PositionedGlyph { Loading Loading @@ -288,8 +298,9 @@ class TextAnimator( animator = buildAnimator(animation).apply { start() } } else { textInterpolator.progress = 1f textInterpolator.linearProgress = 1f textInterpolator.rebase() invalidateCallback() listener?.onInvalidate() } } Loading @@ -302,7 +313,7 @@ class TextAnimator( addUpdateListener { textInterpolator.progress = it.animatedValue as Float textInterpolator.linearProgress = it.currentPlayTime / it.duration.toFloat() invalidateCallback() listener?.onInvalidate() } addListener( Loading
packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt +17 −1 Original line number Diff line number Diff line Loading @@ -27,8 +27,19 @@ import android.util.MathUtils import com.android.internal.graphics.ColorUtils import java.lang.Math.max interface TextInterpolatorListener { fun onPaintModified() {} fun onRebased() {} } /** Provide text style linear interpolation for plain text. */ class TextInterpolator(layout: Layout, var typefaceCache: TypefaceVariantCache) { class TextInterpolator( layout: Layout, var typefaceCache: TypefaceVariantCache, private val listener: TextInterpolatorListener? = null, ) { /** * Returns base paint used for interpolation. * Loading Loading @@ -136,6 +147,7 @@ class TextInterpolator(layout: Layout, var typefaceCache: TypefaceVariantCache) */ fun onTargetPaintModified() { updatePositionsAndFonts(shapeText(layout, targetPaint), updateBase = false) listener?.onPaintModified() } /** Loading @@ -146,6 +158,7 @@ class TextInterpolator(layout: Layout, var typefaceCache: TypefaceVariantCache) */ fun onBasePaintModified() { updatePositionsAndFonts(shapeText(layout, basePaint), updateBase = true) listener?.onPaintModified() } /** Loading Loading @@ -204,6 +217,7 @@ class TextInterpolator(layout: Layout, var typefaceCache: TypefaceVariantCache) */ fun rebase() { if (progress == 0f) { listener?.onRebased() return } else if (progress == 1f) { basePaint.set(targetPaint) Loading Loading @@ -233,6 +247,8 @@ class TextInterpolator(layout: Layout, var typefaceCache: TypefaceVariantCache) } progress = 0f linearProgress = 0f listener?.onRebased() } /** Loading
packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt +8 −1 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import com.android.app.animation.Interpolators import com.android.internal.annotations.VisibleForTesting import com.android.systemui.animation.GlyphCallback import com.android.systemui.animation.TextAnimator import com.android.systemui.animation.TextAnimatorListener import com.android.systemui.animation.TypefaceVariantCacheImpl import com.android.systemui.customization.R import com.android.systemui.log.core.LogLevel Loading Loading @@ -100,7 +101,13 @@ constructor( @VisibleForTesting var textAnimatorFactory: (Layout, () -> Unit) -> TextAnimator = { layout, invalidateCb -> val cache = TypefaceVariantCacheImpl(layout.paint.typeface, NUM_CLOCK_FONT_ANIMATION_STEPS) TextAnimator(layout, cache, invalidateCb) TextAnimator( layout, cache, object : TextAnimatorListener { override fun onInvalidate() = invalidateCb() }, ) } // Used by screenshot tests to provide stability Loading
packages/SystemUI/customization/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextView.kt +29 −19 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ import android.graphics.PorterDuff import android.graphics.PorterDuffXfermode import android.graphics.Rect import android.os.VibrationEffect import android.text.Layout import android.text.TextPaint import android.util.AttributeSet import android.util.Log Loading @@ -39,6 +38,7 @@ import com.android.app.animation.Interpolators import com.android.internal.annotations.VisibleForTesting import com.android.systemui.animation.GSFAxes import com.android.systemui.animation.TextAnimator import com.android.systemui.animation.TextAnimatorListener import com.android.systemui.customization.R import com.android.systemui.plugins.clocks.ClockFontAxisSetting import com.android.systemui.plugins.clocks.ClockFontAxisSetting.Companion.replace Loading Loading @@ -175,11 +175,6 @@ open class SimpleDigitalClockTextView( private val typefaceCache = clockCtx.typefaceCache.getVariantCache("") @VisibleForTesting var textAnimatorFactory: (Layout, () -> Unit) -> TextAnimator = { layout, invalidateCb -> TextAnimator(layout, typefaceCache, invalidateCb) } var verticalAlignment: VerticalAlignment = VerticalAlignment.BASELINE var horizontalAlignment: HorizontalAlignment = HorizontalAlignment.CENTER Loading Loading @@ -247,7 +242,18 @@ open class SimpleDigitalClockTextView( val layout = this.layout if (layout != null) { if (!this::textAnimator.isInitialized) { textAnimator = textAnimatorFactory(layout, ::invalidate) textAnimator = TextAnimator( layout, typefaceCache, object : TextAnimatorListener { override fun onInvalidate() = invalidate() override fun onRebased() = updateTextBounds() override fun onPaintModified() = updateTextBounds() }, ) setInterpolatorPaint() } else { textAnimator.updateLayout(layout) Loading @@ -272,7 +278,7 @@ open class SimpleDigitalClockTextView( override fun onDraw(canvas: Canvas) { logger.onDraw(textAnimator.textInterpolator.shapedText) val interpProgress = getInterpolatedProgress() val interpProgress = textAnimator.progress val interpBounds = getInterpolatedTextBounds(interpProgress) if (interpProgress != drawnProgress) { drawnProgress = interpProgress Loading Loading @@ -336,7 +342,6 @@ open class SimpleDigitalClockTextView( interpolator = aodDozingInterpolator, ), ) updateTextBoundsForTextAnimator() if (!isAnimated) { requestLayout() Loading Loading @@ -367,11 +372,9 @@ open class SimpleDigitalClockTextView( duration = CHARGE_ANIMATION_DURATION, ), ) updateTextBoundsForTextAnimator() }, ), ) updateTextBoundsForTextAnimator() } fun animateFidget(x: Float, y: Float) = animateFidget(0L) Loading Loading @@ -401,11 +404,9 @@ open class SimpleDigitalClockTextView( interpolator = FIDGET_INTERPOLATOR, ), ) updateTextBoundsForTextAnimator() }, ), ) updateTextBoundsForTextAnimator() } fun refreshText() { Loading @@ -428,12 +429,8 @@ open class SimpleDigitalClockTextView( id == R.id.MINUTE_SECOND_DIGIT } private fun getInterpolatedProgress(): Float { return textAnimator.animator?.let { it.animatedValue as Float } ?: 1f } /** Returns the interpolated text bounding rect based on interpolation progress */ private fun getInterpolatedTextBounds(progress: Float = getInterpolatedProgress()): VRectF { private fun getInterpolatedTextBounds(progress: Float = textAnimator.progress): VRectF { if (progress <= 0f) { return prevTextBounds } else if (!textAnimator.isRunning || progress >= 1f) { Loading Loading @@ -487,6 +484,15 @@ open class SimpleDigitalClockTextView( MeasureSpec.makeMeasureSpec(measureBounds.x.roundToInt(), mode.x), MeasureSpec.makeMeasureSpec(measureBounds.y.roundToInt(), mode.y), ) logger.d({ val size = VPointF.fromLong(long1) val mode = VPoint.fromLong(long2) "setInterpolatedSize(size=$size, mode=$mode)" }) { long1 = measureBounds.toLong() long2 = mode.toLong() } } /** Set the location of the view to match the interpolated text bounds */ Loading Loading @@ -514,6 +520,9 @@ open class SimpleDigitalClockTextView( targetRect.bottom.roundToInt(), ) onViewBoundsChanged?.let { it(targetRect) } logger.d({ "setInterpolatedLocation(${VRectF.fromLong(long1)})" }) { long1 = targetRect.toLong() } return targetRect } Loading Loading @@ -616,7 +625,8 @@ open class SimpleDigitalClockTextView( * rebase if previous animator is canceled so basePaint will store the state we transition from * and targetPaint will store the state we transition to */ private fun updateTextBoundsForTextAnimator() { private fun updateTextBounds() { drawnProgress = null prevTextBounds = textAnimator.textInterpolator.basePaint.getTextBounds(text) targetTextBounds = textAnimator.textInterpolator.targetPaint.getTextBounds(text) } Loading
packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockLogger.kt +3 −3 Original line number Diff line number Diff line Loading @@ -55,9 +55,9 @@ class ClockLogger(private val view: View?, buffer: MessageBuffer, tag: String) : } fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { d({ "onLayout($bool1, ${VRect(long1.toULong())})" }) { d({ "onLayout($bool1, ${VRect.fromLong(long1)})" }) { bool1 = changed long1 = VRect(left, top, right, bottom).data.toLong() long1 = VRect(left, top, right, bottom).toLong() } } Loading Loading @@ -116,7 +116,7 @@ class ClockLogger(private val view: View?, buffer: MessageBuffer, tag: String) : } fun animateFidget(x: Float, y: Float) { d({ "animateFidget(${VPointF(long1.toULong())})" }) { long1 = VPointF(x, y).data.toLong() } d({ "animateFidget(${VPointF.fromLong(long1)})" }) { long1 = VPointF(x, y).toLong() } } companion object { Loading