aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-04-22 18:03:18 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-04-22 18:03:18 +0000
commit277548eceb563886b86a9c042d345b8256869c70 (patch)
treef63e6c0aaf4365705fbb07b9849dcfe54be59ca5
parent668168d1b65ff99f5c1c1d36bd913efb23883a32 (diff)
parent25be894a213a79c42c9c08c171c3dd8b8d5ce564 (diff)
downloadsupport-277548eceb563886b86a9c042d345b8256869c70.tar.gz
Merge cherrypicks of ['android-review.googlesource.com/3032063'] into androidx-compose-release.
Change-Id: I8cbf783e5b48a837ccd011430426fd301a4eb072
-rw-r--r--compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/SaversTest.kt116
-rw-r--r--compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Savers.kt56
2 files changed, 106 insertions, 66 deletions
diff --git a/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/SaversTest.kt b/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/SaversTest.kt
index 8365149116c..48a534f3f50 100644
--- a/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/SaversTest.kt
+++ b/compose/ui/ui-text/src/androidUnitTest/kotlin/androidx/compose/ui/text/SaversTest.kt
@@ -46,16 +46,17 @@ class SaversTest {
@Test
fun test_TextUnit() {
val original = 2.sp
- val saved = with(TextUnit.Saver) { defaultSaverScope.save(original) }
+ val saved = save(original, TextUnit.Saver, defaultSaverScope)
+ val restored: TextUnit? = restore(saved, TextUnit.Saver)
- assertThat(TextUnit.Saver.restore(saved!!)).isEqualTo(original)
+ assertThat(restored).isEqualTo(original)
}
@Test
fun test_TextUnit_unspecified() {
val original = TextUnit.Unspecified
- val saved = with(TextUnit.Saver) { defaultSaverScope.save(original) }
- val restored = TextUnit.Saver.restore(saved!!)
+ val saved = save(original, TextUnit.Saver, defaultSaverScope)
+ val restored: TextUnit? = restore(saved, TextUnit.Saver)
assertThat(restored).isEqualTo(original)
}
@@ -63,16 +64,17 @@ class SaversTest {
@Test
fun test_Offset() {
val original = Offset(10f, 10f)
- val saved = with(Offset.Saver) { defaultSaverScope.save(original) }
+ val saved = save(original, Offset.Saver, defaultSaverScope)
+ val restored: Offset? = restore(saved, Offset.Saver)
- assertThat(Offset.Saver.restore(saved!!)).isEqualTo(original)
+ assertThat(restored).isEqualTo(original)
}
@Test
fun test_Offset_Unspecified() {
val original = Offset.Unspecified
- val saved = with(Offset.Saver) { defaultSaverScope.save(original) }
- val restored = Offset.Saver.restore(saved!!)
+ val saved = save(original, Offset.Saver, defaultSaverScope)
+ val restored: Offset? = restore(saved, Offset.Saver)
assertThat(restored).isEqualTo(original)
}
@@ -80,8 +82,8 @@ class SaversTest {
@Test
fun test_Offset_Infinite() {
val original = Offset.Infinite
- val saved = with(Offset.Saver) { defaultSaverScope.save(original) }
- val restored = Offset.Saver.restore(saved!!)
+ val saved = save(original, Offset.Saver, defaultSaverScope)
+ val restored: Offset? = restore(saved, Offset.Saver)
assertThat(restored).isEqualTo(original)
}
@@ -89,16 +91,17 @@ class SaversTest {
@Test
fun test_Color() {
val original = Color.Yellow
- val saved = with(Color.Saver) { defaultSaverScope.save(original) }
+ val saved = save(original, Color.Saver, defaultSaverScope)
+ val restored: Color? = restore(saved, Color.Saver)
- assertThat(Color.Saver.restore(saved!!)).isEqualTo(original)
+ assertThat(restored).isEqualTo(original)
}
@Test
fun test_Color_Unspecified() {
val original = Color.Unspecified
- val saved = with(Color.Saver) { defaultSaverScope.save(original) }
- val restored = Color.Saver.restore(saved!!)
+ val saved = save(original, Color.Saver, defaultSaverScope)
+ val restored: Color? = restore(saved, Color.Saver)
assertThat(restored).isEqualTo(original)
}
@@ -106,8 +109,8 @@ class SaversTest {
@Test
fun test_Shadow() {
val original = Shadow(color = Color.Blue, offset = Offset(5f, 5f), blurRadius = 2f)
- val saved = with(Shadow.Saver) { defaultSaverScope.save(original) }
- val restored = Shadow.Saver.restore(saved!!)
+ val saved = save(original, Shadow.Saver, defaultSaverScope)
+ val restored: Shadow? = restore(saved, Shadow.Saver)
assertThat(restored).isEqualTo(original)
}
@@ -115,8 +118,8 @@ class SaversTest {
@Test
fun test_Shadow_None() {
val original = Shadow.None
- val saved = with(Shadow.Saver) { defaultSaverScope.save(original) }
- val restored = Shadow.Saver.restore(saved!!)
+ val saved = save(original, Shadow.Saver, defaultSaverScope)
+ val restored: Shadow? = restore(saved, Shadow.Saver)
assertThat(restored).isEqualTo(original)
}
@@ -124,8 +127,8 @@ class SaversTest {
@Test
fun test_ParagraphStyle() {
val original = ParagraphStyle()
- val saved = with(ParagraphStyleSaver) { defaultSaverScope.save(original) }
- val restored = ParagraphStyleSaver.restore(saved!!)
+ val saved = save(original, ParagraphStyleSaver, defaultSaverScope)
+ val restored: ParagraphStyle? = restore(saved, ParagraphStyleSaver)
assertThat(restored).isEqualTo(original)
}
@@ -133,8 +136,8 @@ class SaversTest {
@Test
fun test_ParagraphStyle_with_a_nonnull_value() {
val original = ParagraphStyle(textDirection = TextDirection.Rtl)
- val saved = with(ParagraphStyleSaver) { defaultSaverScope.save(original) }
- val restored = ParagraphStyleSaver.restore(saved!!)
+ val saved = save(original, ParagraphStyleSaver, defaultSaverScope)
+ val restored: ParagraphStyle? = restore(saved, ParagraphStyleSaver)
assertThat(restored).isEqualTo(original)
}
@@ -147,8 +150,8 @@ class SaversTest {
lineHeight = 10.sp,
textIndent = TextIndent(firstLine = 2.sp, restLine = 3.sp)
)
- val saved = with(ParagraphStyleSaver) { defaultSaverScope.save(original) }
- val restored = ParagraphStyleSaver.restore(saved!!)
+ val saved = save(original, ParagraphStyleSaver, defaultSaverScope)
+ val restored: ParagraphStyle? = restore(saved, ParagraphStyleSaver)
assertThat(restored).isEqualTo(original)
}
@@ -156,8 +159,8 @@ class SaversTest {
@Test
fun test_SpanStyle() {
val original = SpanStyle()
- val saved = with(SpanStyleSaver) { defaultSaverScope.save(original) }
- val restored = SpanStyleSaver.restore(saved!!)
+ val saved = save(original, SpanStyleSaver, defaultSaverScope)
+ val restored: SpanStyle? = restore(saved, SpanStyleSaver)
assertThat(restored).isEqualTo(original)
}
@@ -165,8 +168,8 @@ class SaversTest {
@Test
fun test_SpanStyle_with_a_nonnull_value() {
val original = SpanStyle(baselineShift = BaselineShift.Subscript)
- val saved = with(SpanStyleSaver) { defaultSaverScope.save(original) }
- val restored = SpanStyleSaver.restore(saved!!)
+ val saved = save(original, SpanStyleSaver, defaultSaverScope)
+ val restored: SpanStyle? = restore(saved, SpanStyleSaver)
assertThat(restored).isEqualTo(original)
}
@@ -193,8 +196,8 @@ class SaversTest {
textDecoration = TextDecoration.LineThrough,
shadow = Shadow(color = Color.Red, offset = Offset(2f, 2f), blurRadius = 4f)
)
- val saved = with(SpanStyleSaver) { defaultSaverScope.save(original) }
- val restored = SpanStyleSaver.restore(saved!!)
+ val saved = save(original, SpanStyleSaver, defaultSaverScope)
+ val restored: SpanStyle? = restore(saved, SpanStyleSaver)
assertThat(restored).isEqualTo(original)
}
@@ -202,33 +205,35 @@ class SaversTest {
@Test
fun test_FontWeight() {
val original = FontWeight(123)
- val saved = with(FontWeight.Saver) { defaultSaverScope.save(original) }
+ val saved = save(original, FontWeight.Saver, defaultSaverScope)
+ val restored: FontWeight? = restore(saved, FontWeight.Saver)
- assertThat(FontWeight.Saver.restore(saved!!)).isEqualTo(original)
+ assertThat(restored).isEqualTo(original)
}
@Test
fun test_FontWeight_w100() {
val original = FontWeight.W100
- val saved = with(FontWeight.Saver) { defaultSaverScope.save(original) }
+ val saved = save(original, FontWeight.Saver, defaultSaverScope)
+ val restored: FontWeight? = restore(saved, FontWeight.Saver)
- val restored = FontWeight.Saver.restore(saved!!)
assertThat(restored).isEqualTo(original)
}
@Test
fun test_BaselineShift() {
val original = BaselineShift(2f)
- val saved = with(BaselineShift.Saver) { defaultSaverScope.save(original) }
+ val saved = save(original, BaselineShift.Saver, defaultSaverScope)
+ val restored: BaselineShift? = restore(saved, BaselineShift.Saver)
- assertThat(BaselineShift.Saver.restore(saved!!)).isEqualTo(original)
+ assertThat(restored).isEqualTo(original)
}
@Test
fun test_BaselineShift_None() {
val original = BaselineShift.None
- val saved = with(BaselineShift.Saver) { defaultSaverScope.save(original) }
- val restored = BaselineShift.Saver.restore(saved!!)
+ val saved = save(original, BaselineShift.Saver, defaultSaverScope)
+ val restored: BaselineShift? = restore(saved, BaselineShift.Saver)
assertThat(restored).isEqualTo(original)
}
@@ -238,25 +243,26 @@ class SaversTest {
val original = TextDecoration.combine(
listOf(TextDecoration.LineThrough, TextDecoration.Underline)
)
- val saved = with(TextDecoration.Saver) { defaultSaverScope.save(original) }
+ val saved = save(original, TextDecoration.Saver, defaultSaverScope)
+ val restored: TextDecoration? = restore(saved, TextDecoration.Saver)
- assertThat(TextDecoration.Saver.restore(saved!!)).isEqualTo(original)
+ assertThat(restored).isEqualTo(original)
}
@Test
fun test_TextDecoration_None() {
val original = TextDecoration.None
- val saved = with(TextDecoration.Saver) { defaultSaverScope.save(original) }
+ val saved = save(original, TextDecoration.Saver, defaultSaverScope)
+ val restored: TextDecoration? = restore(saved, TextDecoration.Saver)
- val restored = TextDecoration.Saver.restore(saved!!)
assertThat(restored).isEqualTo(original)
}
@Test
fun testSaveRestore_lineThrough() {
val original = TextDecoration.LineThrough
- val saved = with(TextDecoration.Saver) { defaultSaverScope.save(original) }
- val restored = TextDecoration.Saver.restore(saved!!)
+ val saved = save(original, TextDecoration.Saver, defaultSaverScope)
+ val restored: TextDecoration? = restore(saved, TextDecoration.Saver)
assertThat(restored).isEqualTo(original)
}
@@ -264,8 +270,8 @@ class SaversTest {
@Test
fun testSaveRestore_underline() {
val original = TextDecoration.Underline
- val saved = with(TextDecoration.Saver) { defaultSaverScope.save(original) }
- val restored = TextDecoration.Saver.restore(saved!!)
+ val saved = save(original, TextDecoration.Saver, defaultSaverScope)
+ val restored: TextDecoration? = restore(saved, TextDecoration.Saver)
assertThat(restored).isEqualTo(original)
}
@@ -273,16 +279,17 @@ class SaversTest {
@Test
fun test_TextGeometricTransform() {
val original = TextGeometricTransform(1f, 2f)
- val saved = with(TextGeometricTransform.Saver) { defaultSaverScope.save(original) }
+ val saved = save(original, TextGeometricTransform.Saver, defaultSaverScope)
+ val restored: TextGeometricTransform? = restore(saved, TextGeometricTransform.Saver)
- assertThat(TextGeometricTransform.Saver.restore(saved!!)).isEqualTo(original)
+ assertThat(restored).isEqualTo(original)
}
@Test
fun test_TextGeometricTransform_None() {
val original = TextGeometricTransform.None
- val saved = with(TextGeometricTransform.Saver) { defaultSaverScope.save(original) }
- val restored = TextGeometricTransform.Saver.restore(saved!!)
+ val saved = save(original, TextGeometricTransform.Saver, defaultSaverScope)
+ val restored: TextGeometricTransform? = restore(saved, TextGeometricTransform.Saver)
assertThat(restored).isEqualTo(original)
}
@@ -290,16 +297,17 @@ class SaversTest {
@Test
fun test_TextIndent() {
val original = TextIndent(1.sp, 2.sp)
- val saved = with(TextIndent.Saver) { defaultSaverScope.save(original) }
+ val saved = save(original, TextIndent.Saver, defaultSaverScope)
+ val restored: TextIndent? = restore(saved, TextIndent.Saver)
- assertThat(TextIndent.Saver.restore(saved!!)).isEqualTo(original)
+ assertThat(restored).isEqualTo(original)
}
@Test
fun test_TextIndent_None() {
val original = TextIndent.None
- val saved = with(TextIndent.Saver) { defaultSaverScope.save(original) }
- val restored = TextIndent.Saver.restore(saved!!)
+ val saved = save(original, TextIndent.Saver, defaultSaverScope)
+ val restored: TextIndent? = restore(saved, TextIndent.Saver)
assertThat(restored).isEqualTo(original)
}
diff --git a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Savers.kt b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Savers.kt
index 52ae36990dd..298553d6e4c 100644
--- a/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Savers.kt
+++ b/compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Savers.kt
@@ -21,6 +21,8 @@ import androidx.compose.runtime.saveable.SaverScope
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shadow
+import androidx.compose.ui.graphics.isUnspecified
+import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.intl.Locale
import androidx.compose.ui.text.intl.LocaleList
@@ -28,7 +30,6 @@ import androidx.compose.ui.text.style.BaselineShift
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextGeometricTransform
import androidx.compose.ui.text.style.TextIndent
-import androidx.compose.ui.unit.ExperimentalUnitApi
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.util.fastMap
@@ -52,11 +53,31 @@ internal inline fun <T : Saver<Original, Saveable>, Original, Saveable, reified
value: Saveable?,
saver: T
): Result? {
- if (value == false) return null
+ // Most of the types we save are nullable. However, value classes are usually not but instead
+ // have a special Unspecified value. In that case we delegate handling of the "false"
+ // value restoration to the corresponding saver that will restore "false" as an Unspecified
+ // of the corresponding type.
+ if (value == false && saver !is NonNullValueClassSaver<*, *>) return null
return value?.let { with(saver) { restore(value) } as Result }
}
/**
+ * Use for non-null value classes where the Unspecified value needs to be separately handled,
+ * for example as in the [OffsetSaver]
+ */
+private interface NonNullValueClassSaver<Original, Saveable : Any> : Saver<Original, Saveable>
+private fun <Original, Saveable : Any> NonNullValueClassSaver(
+ save: SaverScope.(value: Original) -> Saveable?,
+ restore: (value: Saveable) -> Original?
+): NonNullValueClassSaver<Original, Saveable> {
+ return object : NonNullValueClassSaver<Original, Saveable> {
+ override fun SaverScope.save(value: Original) = save.invoke(this, value)
+
+ override fun restore(value: Saveable) = restore.invoke(value)
+ }
+}
+
+/**
* Utility function to save nullable values that does not require a Saver.
*/
internal fun <T> save(value: T?): T? {
@@ -355,30 +376,41 @@ private val ShadowSaver = Saver<Shadow, Any>(
internal val Color.Companion.Saver: Saver<Color, Any>
get() = ColorSaver
-private val ColorSaver = Saver<Color, Any>(
- save = { it.value },
- restore = { Color(it as ULong) }
+private val ColorSaver = NonNullValueClassSaver<Color, Any>(
+ save = {
+ if (it.isUnspecified) { false } else { it.toArgb() }
+ },
+ restore = {
+ if (it == false) { Color.Unspecified } else { Color(it as Int) }
+ }
)
internal val TextUnit.Companion.Saver: Saver<TextUnit, Any>
get() = TextUnitSaver
-@OptIn(ExperimentalUnitApi::class)
-private val TextUnitSaver = Saver<TextUnit, Any>(
+private val TextUnitSaver = NonNullValueClassSaver<TextUnit, Any>(
save = {
- arrayListOf(save(it.value), save(it.type))
+ if (it == TextUnit.Unspecified) {
+ false
+ } else {
+ arrayListOf(save(it.value), save(it.type))
+ }
},
restore = {
- @Suppress("UNCHECKED_CAST")
- val list = it as List<Any>
- TextUnit(restore(list[0])!!, restore(list[1])!!)
+ if (it == false) {
+ TextUnit.Unspecified
+ } else {
+ @Suppress("UNCHECKED_CAST")
+ val list = it as List<Any>
+ TextUnit(restore(list[0])!!, restore(list[1])!!)
+ }
}
)
internal val Offset.Companion.Saver: Saver<Offset, Any>
get() = OffsetSaver
-private val OffsetSaver = Saver<Offset, Any>(
+private val OffsetSaver = NonNullValueClassSaver<Offset, Any>(
save = {
if (it == Offset.Unspecified) {
false