From 73bcce5cd82f94bc9203da1a94ff998618da28ae Mon Sep 17 00:00:00 2001 From: Kyant0 Date: Tue, 16 Sep 2025 11:16:49 +0800 Subject: [PATCH] Small clean --- .../com/kyant/backdrop/BackdropEffectScope.kt | 18 --- .../kyant/backdrop/BackdropShapeProvider.kt | 4 +- ...Backdrop.kt => ContentBackdropModifier.kt} | 0 .../java/com/kyant/backdrop/effects/Lens.kt | 105 ++++++++++++------ 4 files changed, 72 insertions(+), 55 deletions(-) rename backdrop/src/main/java/com/kyant/backdrop/{ContentBackdrop.kt => ContentBackdropModifier.kt} (100%) diff --git a/backdrop/src/main/java/com/kyant/backdrop/BackdropEffectScope.kt b/backdrop/src/main/java/com/kyant/backdrop/BackdropEffectScope.kt index 5ced2cd..6ced457 100644 --- a/backdrop/src/main/java/com/kyant/backdrop/BackdropEffectScope.kt +++ b/backdrop/src/main/java/com/kyant/backdrop/BackdropEffectScope.kt @@ -4,7 +4,6 @@ import android.graphics.RenderEffect import android.graphics.RuntimeShader import android.os.Build import androidx.annotation.RequiresApi -import androidx.compose.foundation.shape.CornerBasedShape import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.mutableStateOf @@ -25,23 +24,6 @@ interface BackdropEffectScope : Density { var renderEffect: RenderEffect? - val cornerRadii: FloatArray - get() { - val shape = shape - require(shape is CornerBasedShape) { "Only CornerBasedShape is supported." } - val isLtr = layoutDirection == LayoutDirection.Ltr - return floatArrayOf( - if (isLtr) shape.topStart.toPx(size, this) - else shape.topEnd.toPx(size, this), - if (isLtr) shape.topEnd.toPx(size, this) - else shape.topStart.toPx(size, this), - if (isLtr) shape.bottomEnd.toPx(size, this) - else shape.bottomStart.toPx(size, this), - if (isLtr) shape.bottomStart.toPx(size, this) - else shape.bottomEnd.toPx(size, this) - ) - } - @RequiresApi(Build.VERSION_CODES.TIRAMISU) fun obtainRuntimeShader(key: String, string: String): RuntimeShader } diff --git a/backdrop/src/main/java/com/kyant/backdrop/BackdropShapeProvider.kt b/backdrop/src/main/java/com/kyant/backdrop/BackdropShapeProvider.kt index 0550b4d..edc70ab 100644 --- a/backdrop/src/main/java/com/kyant/backdrop/BackdropShapeProvider.kt +++ b/backdrop/src/main/java/com/kyant/backdrop/BackdropShapeProvider.kt @@ -15,9 +15,7 @@ internal interface BackdropShapeProvider { } @Immutable -internal class CachedBackdropShapeProvider( - val shapeProvider: () -> Shape -) : BackdropShapeProvider { +internal class CachedBackdropShapeProvider(val shapeProvider: () -> Shape) : BackdropShapeProvider { private var _outline: Outline? = null private var _size: Size = Size.Unspecified diff --git a/backdrop/src/main/java/com/kyant/backdrop/ContentBackdrop.kt b/backdrop/src/main/java/com/kyant/backdrop/ContentBackdropModifier.kt similarity index 100% rename from backdrop/src/main/java/com/kyant/backdrop/ContentBackdrop.kt rename to backdrop/src/main/java/com/kyant/backdrop/ContentBackdropModifier.kt diff --git a/backdrop/src/main/java/com/kyant/backdrop/effects/Lens.kt b/backdrop/src/main/java/com/kyant/backdrop/effects/Lens.kt index 76f46b9..6f8bb82 100644 --- a/backdrop/src/main/java/com/kyant/backdrop/effects/Lens.kt +++ b/backdrop/src/main/java/com/kyant/backdrop/effects/Lens.kt @@ -2,6 +2,8 @@ package com.kyant.backdrop.effects import android.graphics.RenderEffect import android.os.Build +import androidx.compose.foundation.shape.CornerBasedShape +import androidx.compose.ui.unit.LayoutDirection import com.kyant.backdrop.BackdropEffectScope import com.kyant.backdrop.DispersionShaderString import com.kyant.backdrop.RefractionShaderString @@ -14,15 +16,21 @@ fun BackdropEffectScope.refraction( if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return if (height <= 0f || amount <= 0f) return - val shader = obtainRuntimeShader("Refraction", RefractionShaderString).apply { - setFloatUniform("size", size.width, size.height) - setFloatUniform("cornerRadii", cornerRadii) - setFloatUniform("refractionHeight", height) - setFloatUniform("refractionAmount", -amount) - setFloatUniform("depthEffect", if (hasDepthEffect) 1f else 0f) - } + val cornerRadii = cornerRadii + val effect = + if (cornerRadii != null) { + val shader = obtainRuntimeShader("Refraction", RefractionShaderString).apply { + setFloatUniform("size", size.width, size.height) + setFloatUniform("cornerRadii", cornerRadii) + setFloatUniform("refractionHeight", height) + setFloatUniform("refractionAmount", -amount) + setFloatUniform("depthEffect", if (hasDepthEffect) 1f else 0f) + } + RenderEffect.createRuntimeShaderEffect(shader, "image") + } else { + throwUnsupportedSDFException() + } - val effect = RenderEffect.createRuntimeShaderEffect(shader, "image") effect(effect) } @@ -33,14 +41,19 @@ fun BackdropEffectScope.dispersion( if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return if (height <= 0f || amount <= 0f) return - val shader = obtainRuntimeShader("Dispersion", DispersionShaderString).apply { - setFloatUniform("size", size.width, size.height) - setFloatUniform("cornerRadii", cornerRadii) - setFloatUniform("dispersionHeight", height) - setFloatUniform("dispersionAmount", amount) - } - - val effect = RenderEffect.createRuntimeShaderEffect(shader, "image") + val cornerRadii = cornerRadii + val effect = + if (cornerRadii != null) { + val shader = obtainRuntimeShader("Dispersion", DispersionShaderString).apply { + setFloatUniform("size", size.width, size.height) + setFloatUniform("cornerRadii", cornerRadii) + setFloatUniform("dispersionHeight", height) + setFloatUniform("dispersionAmount", amount) + } + RenderEffect.createRuntimeShaderEffect(shader, "image") + } else { + throwUnsupportedSDFException() + } effect(effect) } @@ -54,24 +67,48 @@ fun BackdropEffectScope.refractionWithDispersion( if (height <= 0f || amount <= 0f) return val cornerRadii = cornerRadii + val effect = + if (cornerRadii != null) { + val refractionShader = obtainRuntimeShader("Refraction", RefractionShaderString).apply { + setFloatUniform("size", size.width, size.height) + setFloatUniform("cornerRadii", cornerRadii) + setFloatUniform("refractionHeight", height) + setFloatUniform("refractionAmount", -amount) + setFloatUniform("depthEffect", if (hasDepthEffect) 1f else 0f) + } + val dispersionShader = obtainRuntimeShader("Dispersion", DispersionShaderString).apply { + setFloatUniform("size", size.width, size.height) + setFloatUniform("cornerRadii", cornerRadii) + setFloatUniform("dispersionHeight", height * dispersionIntensity) + setFloatUniform("dispersionAmount", amount * dispersionIntensity) + } + RenderEffect.createChainEffect( + RenderEffect.createRuntimeShaderEffect(dispersionShader, "image"), + RenderEffect.createRuntimeShaderEffect(refractionShader, "image") + ) + } else { + throwUnsupportedSDFException() + } - val refractionShader = obtainRuntimeShader("Refraction", RefractionShaderString).apply { - setFloatUniform("size", size.width, size.height) - setFloatUniform("cornerRadii", cornerRadii) - setFloatUniform("refractionHeight", height) - setFloatUniform("refractionAmount", -amount) - setFloatUniform("depthEffect", if (hasDepthEffect) 1f else 0f) - } - val dispersionShader = obtainRuntimeShader("Dispersion", DispersionShaderString).apply { - setFloatUniform("size", size.width, size.height) - setFloatUniform("cornerRadii", cornerRadii) - setFloatUniform("dispersionHeight", height * dispersionIntensity) - setFloatUniform("dispersionAmount", amount * dispersionIntensity) - } - - val effect = RenderEffect.createChainEffect( - RenderEffect.createRuntimeShaderEffect(dispersionShader, "image"), - RenderEffect.createRuntimeShaderEffect(refractionShader, "image") - ) effect(effect) } + +private val BackdropEffectScope.cornerRadii: FloatArray? + get() { + val shape = shape as? CornerBasedShape ?: return null + val isLtr = layoutDirection == LayoutDirection.Ltr + return floatArrayOf( + if (isLtr) shape.topStart.toPx(size, this) + else shape.topEnd.toPx(size, this), + if (isLtr) shape.topEnd.toPx(size, this) + else shape.topStart.toPx(size, this), + if (isLtr) shape.bottomEnd.toPx(size, this) + else shape.bottomStart.toPx(size, this), + if (isLtr) shape.bottomStart.toPx(size, this) + else shape.bottomEnd.toPx(size, this) + ) + } + +private fun throwUnsupportedSDFException(): Nothing { + throw UnsupportedOperationException("Only CornerBasedShape is supported in lens effects.") +}