summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jordan Demeulenaere <jdemeulenaere@google.com> 2024-12-04 10:44:27 +0100
committer Jordan Demeulenaere <jdemeulenaere@google.com> 2024-12-04 10:56:50 +0100
commitc352ec75c90656c85d5743318a996b12d995a6bc (patch)
treeabb70d4e0ae3a6e0af273000141b2e0841bbf7e2
parent2874563914f1a2101900b2d2589dbca4609ea925 (diff)
Convert interpolated colors to original color space
This CL fixes a crash that can happen when animating a Color using animateElementColorAsState(): the interpolated Color will end up in the Oklab color space (instead of the original color space), which is not supported by the Android platform. Bug: 382043554 Test: atest AnimatedSharedAsStateTest Flag: com.android.systemui.scene_container Change-Id: I6b32af10534f6112560bc174e734c00ce442688b
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt8
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt12
2 files changed, 16 insertions, 4 deletions
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
index 0fc88b22a4d0..a4237f36ab58 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
@@ -225,7 +225,7 @@ fun ElementScope<*>.animateElementColorAsState(value: Color, key: ValueKey): Ani
return animateElementValueAsState(value, key, SharedColorType, canOverflow = false)
}
-private object SharedColorType : SharedValueType<Color, ColorDelta> {
+internal object SharedColorType : SharedValueType<Color, ColorDelta> {
override val unspecifiedValue: Color = Color.Unspecified
override val zeroDeltaValue: ColorDelta = ColorDelta(0f, 0f, 0f, 0f)
@@ -255,17 +255,17 @@ private object SharedColorType : SharedValueType<Color, ColorDelta> {
alpha = aOklab.alpha + b.alpha * bWeight,
colorSpace = ColorSpaces.Oklab,
)
- .convert(aOklab.colorSpace)
+ .convert(a.colorSpace)
}
}
/**
- * Represents the diff between two colors in the same color space.
+ * Represents the diff between two colors in the Oklab color space.
*
* Note: This class is necessary because Color() checks the bounds of its values and UncheckedColor
* is internal.
*/
-private class ColorDelta(val red: Float, val green: Float, val blue: Float, val alpha: Float)
+internal class ColorDelta(val red: Float, val green: Float, val blue: Float, val alpha: Float)
@Composable
internal fun <T> animateSharedValueAsState(
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt
index 3644b3069fb3..2fd1d8d8573a 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/AnimatedSharedAsStateTest.kt
@@ -18,7 +18,10 @@ package com.android.compose.animation.scene
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.tween
+import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
@@ -495,4 +498,13 @@ class AnimatedSharedAsStateTest {
assertThat(lastValues[SceneA]).isWithin(0.001f).of(100f)
assertThat(lastValues[SceneB]).isWithin(0.001f).of(100f)
}
+
+ @Test
+ fun interpolatedColor() {
+ val a = Color.Red
+ val b = Color.Green
+ val delta = SharedColorType.diff(b, a) // b - a
+ val interpolated = SharedColorType.addWeighted(a, delta, 0.5f) // a + (b - a) * 0.5f
+ rule.setContent { Box(Modifier.fillMaxSize().background(interpolated)) }
+ }
}