diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-04-22 18:03:18 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2024-04-22 18:03:18 +0000 |
commit | 277548eceb563886b86a9c042d345b8256869c70 (patch) | |
tree | f63e6c0aaf4365705fbb07b9849dcfe54be59ca5 | |
parent | 668168d1b65ff99f5c1c1d36bd913efb23883a32 (diff) | |
parent | 25be894a213a79c42c9c08c171c3dd8b8d5ce564 (diff) | |
download | support-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.kt | 116 | ||||
-rw-r--r-- | compose/ui/ui-text/src/commonMain/kotlin/androidx/compose/ui/text/Savers.kt | 56 |
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 |