diff --git a/.gitignore b/.gitignore
index aa724b7..28a82e3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,4 @@
.externalNativeBuild
.cxx
local.properties
+/.kotlin
diff --git a/.idea/artifacts/app.xml b/.idea/artifacts/app.xml
new file mode 100644
index 0000000..ed2bb0f
--- /dev/null
+++ b/.idea/artifacts/app.xml
@@ -0,0 +1,8 @@
+
+
+ $PROJECT_DIR$/app/build/libs
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/artifacts/app_desktop.xml b/.idea/artifacts/app_desktop.xml
new file mode 100644
index 0000000..ff875ba
--- /dev/null
+++ b/.idea/artifacts/app_desktop.xml
@@ -0,0 +1,8 @@
+
+
+ $PROJECT_DIR$/app/build/libs
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/artifacts/app_js.xml b/.idea/artifacts/app_js.xml
new file mode 100644
index 0000000..93a033e
--- /dev/null
+++ b/.idea/artifacts/app_js.xml
@@ -0,0 +1,8 @@
+
+
+ $PROJECT_DIR$/app/build/libs
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/artifacts/app_wasm_js.xml b/.idea/artifacts/app_wasm_js.xml
new file mode 100644
index 0000000..b7affd0
--- /dev/null
+++ b/.idea/artifacts/app_wasm_js.xml
@@ -0,0 +1,8 @@
+
+
+ $PROJECT_DIR$/app/build/libs
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/artifacts/backdrop.xml b/.idea/artifacts/backdrop.xml
new file mode 100644
index 0000000..6508176
--- /dev/null
+++ b/.idea/artifacts/backdrop.xml
@@ -0,0 +1,8 @@
+
+
+ $PROJECT_DIR$/backdrop/build/libs
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/artifacts/backdrop_desktop.xml b/.idea/artifacts/backdrop_desktop.xml
new file mode 100644
index 0000000..59e3ee8
--- /dev/null
+++ b/.idea/artifacts/backdrop_desktop.xml
@@ -0,0 +1,8 @@
+
+
+ $PROJECT_DIR$/backdrop/build/libs
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/artifacts/backdrop_js.xml b/.idea/artifacts/backdrop_js.xml
new file mode 100644
index 0000000..a9eda81
--- /dev/null
+++ b/.idea/artifacts/backdrop_js.xml
@@ -0,0 +1,8 @@
+
+
+ $PROJECT_DIR$/backdrop/build/libs
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/artifacts/backdrop_wasm_js.xml b/.idea/artifacts/backdrop_wasm_js.xml
new file mode 100644
index 0000000..342a789
--- /dev/null
+++ b/.idea/artifacts/backdrop_wasm_js.xml
@@ -0,0 +1,8 @@
+
+
+ $PROJECT_DIR$/backdrop/build/libs
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 73902b3..04ba6ce 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -9,8 +9,9 @@
diff --git a/README.md b/README.md
index 1cf42fc..cd8733f 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
-# Android Liquid Glass (Backdrop)
+# Liquid Glass (Backdrop)

-A customizable Liquid Glass effect library for Jetpack Compose.
+A customizable Liquid Glass effect library for Compose Multiplatform.
## Docs
@@ -15,17 +15,13 @@ A customizable Liquid Glass effect library for Jetpack Compose.
The library does not include any high-level components; you will need to create your own.
Below are some example components:
-- [LiquidButton](/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidButton.kt)
-- [LiquidToggle](/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidToggle.kt)
-- [LiquidSlider](/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidSlider.kt)
-- [LiquidBottomTabs](/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidBottomTabs.kt)
+- [LiquidButton](/androidApp/src/main/java/com/kyant/backdrop/catalog/components/LiquidButton.kt)
+- [LiquidToggle](/androidApp/src/main/java/com/kyant/backdrop/catalog/components/LiquidToggle.kt)
+- [LiquidSlider](/androidApp/src/main/java/com/kyant/backdrop/catalog/components/LiquidSlider.kt)
+- [LiquidBottomTabs](/androidApp/src/main/java/com/kyant/backdrop/catalog/components/LiquidBottomTabs.kt)
-## Demos
+## Demo
-- [Backdrop Catalog](./catalog/release/catalog-release.apk)
+- [Backdrop Catalog](./androidApp/release/catalog-release.apk)

-
-- **(Deprecated)** [Liquid Glass Playground](./app/release/app-release.apk) (Android 13+)
-
-
diff --git a/catalog/.gitignore b/androidApp/.gitignore
similarity index 100%
rename from catalog/.gitignore
rename to androidApp/.gitignore
diff --git a/catalog/build.gradle.kts b/androidApp/build.gradle.kts
similarity index 86%
rename from catalog/build.gradle.kts
rename to androidApp/build.gradle.kts
index c1de45f..e1e46f0 100644
--- a/catalog/build.gradle.kts
+++ b/androidApp/build.gradle.kts
@@ -1,3 +1,5 @@
+import org.jetbrains.kotlin.gradle.dsl.JvmTarget
+
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.compose)
@@ -57,8 +59,8 @@ android {
}
kotlin {
- jvmToolchain(21)
compilerOptions {
+ jvmTarget = JvmTarget.JVM_11
freeCompilerArgs.addAll(
"-Xlambdas=class"
)
@@ -68,10 +70,10 @@ kotlin {
dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.activity.compose)
- implementation(libs.androidx.compose.foundation)
- implementation(libs.androidx.compose.ui)
- implementation(libs.androidx.compose.ui.graphics)
- implementation(libs.androidx.compose.material.ripple)
+ implementation(libs.compose.foundation)
+ implementation(libs.compose.ui)
+ implementation(libs.compose.ui.graphics)
+ implementation(libs.compose.material.ripple)
implementation(libs.kyant.shapes)
implementation(project(":backdrop"))
}
diff --git a/catalog/proguard-rules.pro b/androidApp/proguard-rules.pro
similarity index 100%
rename from catalog/proguard-rules.pro
rename to androidApp/proguard-rules.pro
diff --git a/catalog/release/baselineProfiles/0/catalog-release.dm b/androidApp/release/baselineProfiles/0/catalog-release.dm
similarity index 100%
rename from catalog/release/baselineProfiles/0/catalog-release.dm
rename to androidApp/release/baselineProfiles/0/catalog-release.dm
diff --git a/catalog/release/baselineProfiles/1/catalog-release.dm b/androidApp/release/baselineProfiles/1/catalog-release.dm
similarity index 100%
rename from catalog/release/baselineProfiles/1/catalog-release.dm
rename to androidApp/release/baselineProfiles/1/catalog-release.dm
diff --git a/catalog/release/catalog-release.apk b/androidApp/release/catalog-release.apk
similarity index 100%
rename from catalog/release/catalog-release.apk
rename to androidApp/release/catalog-release.apk
diff --git a/catalog/release/output-metadata.json b/androidApp/release/output-metadata.json
similarity index 100%
rename from catalog/release/output-metadata.json
rename to androidApp/release/output-metadata.json
diff --git a/catalog/src/main/AndroidManifest.xml b/androidApp/src/main/AndroidManifest.xml
similarity index 100%
rename from catalog/src/main/AndroidManifest.xml
rename to androidApp/src/main/AndroidManifest.xml
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/BackdropDemoScaffold.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/BackdropDemoScaffold.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/BackdropDemoScaffold.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/BackdropDemoScaffold.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/Block.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/Block.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/Block.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/Block.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/CatalogDestination.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/CatalogDestination.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/CatalogDestination.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/CatalogDestination.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/MainActivity.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/MainActivity.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/MainActivity.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/MainActivity.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/MainContent.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/MainContent.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/MainContent.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/MainContent.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/Ripple.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/Ripple.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/Ripple.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/Ripple.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidBottomTab.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/components/LiquidBottomTab.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidBottomTab.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/components/LiquidBottomTab.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidBottomTabs.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/components/LiquidBottomTabs.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidBottomTabs.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/components/LiquidBottomTabs.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidButton.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/components/LiquidButton.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidButton.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/components/LiquidButton.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidSlider.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/components/LiquidSlider.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidSlider.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/components/LiquidSlider.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidToggle.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/components/LiquidToggle.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/components/LiquidToggle.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/components/LiquidToggle.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/AdaptiveLuminanceGlassContent.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/AdaptiveLuminanceGlassContent.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/destinations/AdaptiveLuminanceGlassContent.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/AdaptiveLuminanceGlassContent.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/BottomTabsContent.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/BottomTabsContent.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/destinations/BottomTabsContent.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/BottomTabsContent.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ButtonsContent.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/ButtonsContent.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ButtonsContent.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/ButtonsContent.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ControlCenterContent.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/ControlCenterContent.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ControlCenterContent.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/ControlCenterContent.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/DialogContent.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/DialogContent.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/destinations/DialogContent.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/DialogContent.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/GlassPlaygroundContent.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/GlassPlaygroundContent.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/destinations/GlassPlaygroundContent.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/GlassPlaygroundContent.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/HomeContent.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/HomeContent.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/destinations/HomeContent.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/HomeContent.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/LazyScrollContainerContent.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/LazyScrollContainerContent.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/destinations/LazyScrollContainerContent.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/LazyScrollContainerContent.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/LockScreenContent.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/LockScreenContent.kt
similarity index 97%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/destinations/LockScreenContent.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/LockScreenContent.kt
index f157db9..b7f2334 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/LockScreenContent.kt
+++ b/androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/LockScreenContent.kt
@@ -26,7 +26,7 @@ import com.kyant.backdrop.catalog.utils.rememberSdfShader
import com.kyant.backdrop.drawPlainBackdrop
import com.kyant.backdrop.effects.blur
import com.kyant.backdrop.effects.colorControls
-import com.kyant.shapes.Capsule
+import com.kyant.shapes.Rectangle
@Composable
fun LockScreenContent() {
@@ -56,7 +56,7 @@ fun LockScreenContent() {
.draggable2D(rememberDraggable2DState { delta -> offset += delta })
.drawPlainBackdrop(
backdrop = backdrop,
- shape = { Capsule },
+ shape = { Rectangle },
effects = {
colorControls(brightness = -0.1f, contrast = 0.75f, saturation = 1.5f)
blur(2f.dp.toPx())
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/MagnifierContent.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/MagnifierContent.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/destinations/MagnifierContent.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/MagnifierContent.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ProgressiveBlurContent.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/ProgressiveBlurContent.kt
similarity index 69%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ProgressiveBlurContent.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/ProgressiveBlurContent.kt
index 48e157e..92d2ad4 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ProgressiveBlurContent.kt
+++ b/androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/ProgressiveBlurContent.kt
@@ -1,7 +1,5 @@
package com.kyant.backdrop.catalog.destinations
-import android.graphics.RenderEffect
-import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -14,14 +12,13 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
-import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.kyant.backdrop.catalog.BackdropDemoScaffold
import com.kyant.backdrop.drawPlainBackdrop
import com.kyant.backdrop.effects.blur
-import com.kyant.backdrop.effects.effect
+import com.kyant.backdrop.effects.runtimeShaderEffect
@Composable
fun ProgressiveBlurContent() {
@@ -41,12 +38,9 @@ fun ProgressiveBlurContent() {
shape = { RectangleShape },
effects = {
blur(4f.dp.toPx())
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- effect(
- RenderEffect.createRuntimeShaderEffect(
- obtainRuntimeShader(
- "AlphaMask",
- """
+ runtimeShaderEffect(
+ "AlphaMask",
+ """
uniform shader content;
uniform float2 size;
@@ -57,15 +51,12 @@ half4 main(float2 coord) {
float blurAlpha = smoothstep(size.y, size.y * 0.5, coord.y);
float tintAlpha = smoothstep(size.y, size.y * 0.5, coord.y);
return mix(content.eval(coord) * blurAlpha, tint * tintAlpha, tintIntensity);
-}"""
- ).apply {
- setFloatUniform("size", size.width, size.height)
- setColorUniform("tint", tintColor.toArgb())
- setFloatUniform("tintIntensity", 0.8f)
- },
- "content"
- )
- )
+}""",
+ "content"
+ ) {
+ setFloatUniform("size", size.width, size.height)
+ setColorUniform("tint", tintColor)
+ setFloatUniform("tintIntensity", 0.8f)
}
}
)
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ScrollContainerContent.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/ScrollContainerContent.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ScrollContainerContent.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/ScrollContainerContent.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/SliderContent.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/SliderContent.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/destinations/SliderContent.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/SliderContent.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ToggleContent.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/ToggleContent.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/destinations/ToggleContent.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/destinations/ToggleContent.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/utils/DampedDragAnimation.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/utils/DampedDragAnimation.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/utils/DampedDragAnimation.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/utils/DampedDragAnimation.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/utils/DragGestureInspector.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/utils/DragGestureInspector.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/utils/DragGestureInspector.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/utils/DragGestureInspector.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/utils/InteractiveHighlight.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/utils/InteractiveHighlight.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/utils/InteractiveHighlight.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/utils/InteractiveHighlight.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/utils/LoremIpsum.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/utils/LoremIpsum.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/utils/LoremIpsum.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/utils/LoremIpsum.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/utils/ProgressConverter.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/utils/ProgressConverter.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/utils/ProgressConverter.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/utils/ProgressConverter.kt
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/utils/SdfShader.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/utils/SdfShader.kt
similarity index 80%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/utils/SdfShader.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/utils/SdfShader.kt
index b5f38ee..153b197 100644
--- a/catalog/src/main/java/com/kyant/backdrop/catalog/utils/SdfShader.kt
+++ b/androidApp/src/main/java/com/kyant/backdrop/catalog/utils/SdfShader.kt
@@ -2,7 +2,6 @@ package com.kyant.backdrop.catalog.utils
import android.graphics.Bitmap
import android.graphics.BitmapShader
-import android.graphics.RenderEffect
import android.graphics.Shader
import android.graphics.drawable.BitmapDrawable
import android.os.Build
@@ -14,7 +13,8 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalResources
import androidx.compose.ui.unit.dp
import com.kyant.backdrop.BackdropEffectScope
-import com.kyant.backdrop.effects.effect
+import com.kyant.backdrop.asAndroidRuntimeShader
+import com.kyant.backdrop.effects.runtimeShaderEffect
import org.intellij.lang.annotations.Language
@Composable
@@ -39,15 +39,17 @@ class SdfShader(val sdfBitmap: Bitmap) {
lightAngle: Float = 45f
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- val shader =
- obtainRuntimeShader("SdfShader", createSdfShaderString()).apply {
- setInputBuffer("sdfTex", sdfTexture)
- setFloatUniform("size", size.width, size.height)
- setFloatUniform("sdfTexSize", sdfBitmap.width.toFloat(), sdfBitmap.height.toFloat())
- setFloatUniform("refractionHeight", refractionHeight)
- setFloatUniform("lightAngle", lightAngle)
- }
- effect(RenderEffect.createRuntimeShaderEffect(shader, "content"))
+ runtimeShaderEffect(
+ "SdfShader",
+ createSdfShaderString(),
+ "content"
+ ) {
+ asAndroidRuntimeShader().setInputBuffer("sdfTex", sdfTexture)
+ setFloatUniform("size", size.width, size.height)
+ setFloatUniform("sdfTexSize", sdfBitmap.width.toFloat(), sdfBitmap.height.toFloat())
+ setFloatUniform("refractionHeight", refractionHeight)
+ setFloatUniform("lightAngle", lightAngle)
+ }
}
}
}
diff --git a/catalog/src/main/java/com/kyant/backdrop/catalog/utils/UISensor.kt b/androidApp/src/main/java/com/kyant/backdrop/catalog/utils/UISensor.kt
similarity index 100%
rename from catalog/src/main/java/com/kyant/backdrop/catalog/utils/UISensor.kt
rename to androidApp/src/main/java/com/kyant/backdrop/catalog/utils/UISensor.kt
diff --git a/catalog/src/main/res/drawable-v24/ic_launcher_foreground.xml b/androidApp/src/main/res/drawable-v24/ic_launcher_foreground.xml
similarity index 100%
rename from catalog/src/main/res/drawable-v24/ic_launcher_foreground.xml
rename to androidApp/src/main/res/drawable-v24/ic_launcher_foreground.xml
diff --git a/catalog/src/main/res/drawable/flight_40px.xml b/androidApp/src/main/res/drawable/flight_40px.xml
similarity index 100%
rename from catalog/src/main/res/drawable/flight_40px.xml
rename to androidApp/src/main/res/drawable/flight_40px.xml
diff --git a/catalog/src/main/res/drawable/flower.jpg b/androidApp/src/main/res/drawable/flower.jpg
similarity index 100%
rename from catalog/src/main/res/drawable/flower.jpg
rename to androidApp/src/main/res/drawable/flower.jpg
diff --git a/catalog/src/main/res/drawable/ic_launcher_background.xml b/androidApp/src/main/res/drawable/ic_launcher_background.xml
similarity index 100%
rename from catalog/src/main/res/drawable/ic_launcher_background.xml
rename to androidApp/src/main/res/drawable/ic_launcher_background.xml
diff --git a/catalog/src/main/res/drawable/instagram_logo.xml b/androidApp/src/main/res/drawable/instagram_logo.xml
similarity index 100%
rename from catalog/src/main/res/drawable/instagram_logo.xml
rename to androidApp/src/main/res/drawable/instagram_logo.xml
diff --git a/catalog/src/main/res/drawable/sdf.webp b/androidApp/src/main/res/drawable/sdf.webp
similarity index 100%
rename from catalog/src/main/res/drawable/sdf.webp
rename to androidApp/src/main/res/drawable/sdf.webp
diff --git a/catalog/src/main/res/drawable/system_home_screen_light.webp b/androidApp/src/main/res/drawable/system_home_screen_light.webp
similarity index 100%
rename from catalog/src/main/res/drawable/system_home_screen_light.webp
rename to androidApp/src/main/res/drawable/system_home_screen_light.webp
diff --git a/catalog/src/main/res/drawable/wallpaper_light.webp b/androidApp/src/main/res/drawable/wallpaper_light.webp
similarity index 100%
rename from catalog/src/main/res/drawable/wallpaper_light.webp
rename to androidApp/src/main/res/drawable/wallpaper_light.webp
diff --git a/catalog/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
similarity index 100%
rename from catalog/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
rename to androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
diff --git a/catalog/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
similarity index 100%
rename from catalog/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
rename to androidApp/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
diff --git a/catalog/src/main/res/mipmap-hdpi/ic_launcher.webp b/androidApp/src/main/res/mipmap-hdpi/ic_launcher.webp
similarity index 100%
rename from catalog/src/main/res/mipmap-hdpi/ic_launcher.webp
rename to androidApp/src/main/res/mipmap-hdpi/ic_launcher.webp
diff --git a/catalog/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/androidApp/src/main/res/mipmap-hdpi/ic_launcher_round.webp
similarity index 100%
rename from catalog/src/main/res/mipmap-hdpi/ic_launcher_round.webp
rename to androidApp/src/main/res/mipmap-hdpi/ic_launcher_round.webp
diff --git a/catalog/src/main/res/mipmap-mdpi/ic_launcher.webp b/androidApp/src/main/res/mipmap-mdpi/ic_launcher.webp
similarity index 100%
rename from catalog/src/main/res/mipmap-mdpi/ic_launcher.webp
rename to androidApp/src/main/res/mipmap-mdpi/ic_launcher.webp
diff --git a/catalog/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/androidApp/src/main/res/mipmap-mdpi/ic_launcher_round.webp
similarity index 100%
rename from catalog/src/main/res/mipmap-mdpi/ic_launcher_round.webp
rename to androidApp/src/main/res/mipmap-mdpi/ic_launcher_round.webp
diff --git a/catalog/src/main/res/mipmap-xhdpi/ic_launcher.webp b/androidApp/src/main/res/mipmap-xhdpi/ic_launcher.webp
similarity index 100%
rename from catalog/src/main/res/mipmap-xhdpi/ic_launcher.webp
rename to androidApp/src/main/res/mipmap-xhdpi/ic_launcher.webp
diff --git a/catalog/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/androidApp/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
similarity index 100%
rename from catalog/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
rename to androidApp/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
diff --git a/catalog/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/androidApp/src/main/res/mipmap-xxhdpi/ic_launcher.webp
similarity index 100%
rename from catalog/src/main/res/mipmap-xxhdpi/ic_launcher.webp
rename to androidApp/src/main/res/mipmap-xxhdpi/ic_launcher.webp
diff --git a/catalog/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/androidApp/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
similarity index 100%
rename from catalog/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
rename to androidApp/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
diff --git a/catalog/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
similarity index 100%
rename from catalog/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
rename to androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
diff --git a/catalog/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
similarity index 100%
rename from catalog/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
rename to androidApp/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
diff --git a/catalog/src/main/res/values-night/themes.xml b/androidApp/src/main/res/values-night/themes.xml
similarity index 100%
rename from catalog/src/main/res/values-night/themes.xml
rename to androidApp/src/main/res/values-night/themes.xml
diff --git a/catalog/src/main/res/values/strings.xml b/androidApp/src/main/res/values/strings.xml
similarity index 100%
rename from catalog/src/main/res/values/strings.xml
rename to androidApp/src/main/res/values/strings.xml
diff --git a/catalog/src/main/res/values/themes.xml b/androidApp/src/main/res/values/themes.xml
similarity index 100%
rename from catalog/src/main/res/values/themes.xml
rename to androidApp/src/main/res/values/themes.xml
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
new file mode 100644
index 0000000..6119f54
--- /dev/null
+++ b/app/build.gradle.kts
@@ -0,0 +1,96 @@
+import org.jetbrains.compose.desktop.application.dsl.TargetFormat
+import org.jetbrains.kotlin.gradle.dsl.JvmTarget
+
+plugins {
+ alias(libs.plugins.android.multiplatform.library)
+ alias(libs.plugins.kotlin.multiplatform)
+ alias(libs.plugins.kotlin.compose)
+ alias(libs.plugins.jetbrains.compose)
+}
+
+kotlin {
+ androidLibrary {
+ compileSdk = 36
+ namespace = "com.kyant.backdrop.catalog"
+ compilerOptions {
+ jvmTarget = JvmTarget.JVM_11
+ }
+ }
+
+ jvm("desktop")
+
+ js(IR) {
+ browser()
+ }
+ wasmJs {
+ browser()
+ }
+
+ macosArm64()
+ iosArm64("iosArm64")
+ iosSimulatorArm64("iosSimulatorArm64")
+
+ sourceSets {
+ val commonMain by getting {
+ dependencies {
+ implementation(libs.compose.foundation)
+ implementation(libs.compose.ui)
+ implementation(libs.compose.ui.graphics)
+ implementation(libs.compose.material.ripple)
+ implementation(libs.kyant.shapes)
+ implementation(project(":backdrop"))
+ }
+ }
+
+ val skikoMain by creating {
+ dependsOn(commonMain)
+ }
+
+ val desktopMain by getting {
+ dependsOn(skikoMain)
+ dependencies {
+ implementation(compose.desktop.currentOs)
+ }
+ }
+
+ val macosArm64Main by getting {
+ dependsOn(skikoMain)
+ }
+
+ val iosMain by creating {
+ dependsOn(skikoMain)
+ }
+
+ val iosArm64Main by getting {
+ dependsOn(iosMain)
+ }
+
+ val iosSimulatorArm64Main by getting {
+ dependsOn(iosMain)
+ }
+
+ val jsMain by getting {
+ dependsOn(skikoMain)
+ }
+
+ val wasmJsMain by getting {
+ dependsOn(skikoMain)
+ }
+
+ all {
+ languageSettings.enableLanguageFeature("ContextParameters")
+ }
+ }
+}
+
+compose.desktop {
+ application {
+ mainClass = "com.kyant.backdrop.catalog.MainKt"
+
+ nativeDistributions {
+ targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
+ packageName = "com.kyant.backdrop.catalog"
+ packageVersion = "1.0.0"
+ }
+ }
+}
diff --git a/app/release/app-release.apk b/app/release/app-release.apk
deleted file mode 100644
index 3911184..0000000
Binary files a/app/release/app-release.apk and /dev/null differ
diff --git a/app/src/commonMain/kotlin/com/kyant/backdrop/catalog/MainContent.kt b/app/src/commonMain/kotlin/com/kyant/backdrop/catalog/MainContent.kt
new file mode 100644
index 0000000..0bc3362
--- /dev/null
+++ b/app/src/commonMain/kotlin/com/kyant/backdrop/catalog/MainContent.kt
@@ -0,0 +1,73 @@
+package com.kyant.backdrop.catalog
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.text.BasicText
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.drawBehind
+import androidx.compose.ui.graphics.Brush
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import com.kyant.backdrop.backdrops.layerBackdrop
+import com.kyant.backdrop.backdrops.rememberLayerBackdrop
+import com.kyant.backdrop.drawBackdrop
+import com.kyant.backdrop.effects.blur
+import com.kyant.backdrop.effects.colorControls
+import com.kyant.backdrop.effects.lens
+import com.kyant.shapes.RoundedRectangle
+
+@Composable
+fun MainContent() {
+ Box(
+ Modifier
+ .fillMaxSize(),
+ contentAlignment = Alignment.Center
+ ) {
+ val backdrop = rememberLayerBackdrop()
+
+ Box(
+ Modifier
+ .layerBackdrop(backdrop)
+ .drawBehind {
+ drawRect(
+ Brush.sweepGradient(
+ listOf(
+ Color(0xFFFF6D6D),
+ Color(0xFFFFD86D),
+ Color(0xFF6DFF8E),
+ Color(0xFF6DE1FF),
+ Color(0xFFFF6D6D),
+ )
+ )
+ )
+ drawRect(Color.Black.copy(alpha = 0.5f))
+ }
+ .fillMaxSize(),
+ contentAlignment = Alignment.Center
+ ) {
+ BasicText(
+ "This is the content behind the backdrop!",
+ style = TextStyle(fontSize = 20f.sp)
+ )
+ }
+
+ Box(
+ Modifier
+ .drawBackdrop(
+ backdrop,
+ { RoundedRectangle(32f.dp) },
+ {
+ colorControls(brightness = 0.2f, contrast = 1.5f, saturation = 1.5f)
+ blur(1f.dp.toPx())
+ lens(32f.dp.toPx(), 64f.dp.toPx())
+ }
+ )
+ .size(256f.dp)
+ )
+ }
+}
diff --git a/app/src/desktopMain/kotlin/com/kyant/backdrop/catalog/Main.kt b/app/src/desktopMain/kotlin/com/kyant/backdrop/catalog/Main.kt
new file mode 100644
index 0000000..4906cc7
--- /dev/null
+++ b/app/src/desktopMain/kotlin/com/kyant/backdrop/catalog/Main.kt
@@ -0,0 +1,17 @@
+package com.kyant.backdrop.catalog
+
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.window.Window
+import androidx.compose.ui.window.WindowPosition
+import androidx.compose.ui.window.application
+import androidx.compose.ui.window.rememberWindowState
+
+fun main() = application {
+ Window(
+ onCloseRequest = ::exitApplication,
+ state = rememberWindowState(position = WindowPosition.Aligned(Alignment.Center)),
+ title = "Backdrop Catalog",
+ ) {
+ MainContent()
+ }
+}
diff --git a/backdrop/build.gradle.kts b/backdrop/build.gradle.kts
index 4ae073d..ee03a36 100644
--- a/backdrop/build.gradle.kts
+++ b/backdrop/build.gradle.kts
@@ -1,57 +1,93 @@
+import org.jetbrains.kotlin.gradle.dsl.JvmTarget
+
plugins {
- alias(libs.plugins.android.library)
+ alias(libs.plugins.android.multiplatform.library)
+ alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.kotlin.compose)
+ alias(libs.plugins.jetbrains.compose)
id("com.vanniktech.maven.publish")
}
-android {
- namespace = "com.kyant.backdrop"
- compileSdk {
- version = release(36)
- }
- buildToolsVersion = "36.1.0"
-
- defaultConfig {
- minSdk = 21
- consumerProguardFiles("consumer-rules.pro")
- }
-
- buildTypes {
- release {
- isMinifyEnabled = false
- proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
+kotlin {
+ androidLibrary {
+ compileSdk = 36
+ namespace = "com.kyant.backdrop"
+ compilerOptions {
+ jvmTarget = JvmTarget.JVM_11
}
}
- buildFeatures {
- compose = true
- }
-}
-kotlin {
- jvmToolchain(21)
- compilerOptions {
- freeCompilerArgs.addAll(
- "-Xcontext-parameters"
- )
- }
-}
+ jvm("desktop")
-dependencies {
- implementation(libs.androidx.compose.foundation)
- implementation(libs.androidx.compose.ui)
- implementation(libs.androidx.compose.ui.graphics)
- implementation(libs.kyant.shapes)
+ js(IR) {
+ browser()
+ }
+ wasmJs {
+ browser()
+ }
+
+ macosArm64()
+ iosArm64("iosArm64")
+ iosSimulatorArm64("iosSimulatorArm64")
+
+ sourceSets {
+ val commonMain by getting {
+ dependencies {
+ implementation(libs.compose.foundation)
+ implementation(libs.compose.ui)
+ implementation(libs.compose.ui.graphics)
+ implementation(libs.kyant.shapes)
+ implementation("org.jetbrains:annotations:26.0.2-1")
+ }
+ }
+
+ val skikoMain by creating {
+ dependsOn(commonMain)
+ }
+
+ val desktopMain by getting {
+ dependsOn(skikoMain)
+ }
+
+ val macosArm64Main by getting {
+ dependsOn(skikoMain)
+ }
+
+ val iosMain by creating {
+ dependsOn(skikoMain)
+ }
+
+ val iosArm64Main by getting {
+ dependsOn(iosMain)
+ }
+
+ val iosSimulatorArm64Main by getting {
+ dependsOn(iosMain)
+ }
+
+ val jsMain by getting {
+ dependsOn(skikoMain)
+ }
+
+ val wasmJsMain by getting {
+ dependsOn(skikoMain)
+ }
+
+ all {
+ languageSettings.enableLanguageFeature("ContextParameters")
+ }
+ }
}
mavenPublishing {
publishToMavenCentral()
signAllPublications()
- coordinates("io.github.kyant0", "backdrop", "1.0.5")
+ coordinates("io.github.kyant0", "backdrop", "2.0.0-alpha01")
pom {
name.set("Backdrop")
- description.set("Jetpack Compose blur and Liquid Glass effects")
+ description.set("Compose Multiplatform Liquid Glass effects")
inceptionYear.set("2025")
url.set("https://github.com/Kyant0/AndroidLiquidGlass")
licenses {
diff --git a/backdrop/src/androidMain/kotlin/com/kyant/backdrop/RuntimeShader.kt b/backdrop/src/androidMain/kotlin/com/kyant/backdrop/RuntimeShader.kt
new file mode 100644
index 0000000..17b0a91
--- /dev/null
+++ b/backdrop/src/androidMain/kotlin/com/kyant/backdrop/RuntimeShader.kt
@@ -0,0 +1,65 @@
+package com.kyant.backdrop
+
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.toArgb
+import org.intellij.lang.annotations.Language
+
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+actual fun RuntimeShader(@Language("AGSL") shaderString: String): RuntimeShader {
+ val shader = android.graphics.RuntimeShader(shaderString)
+ return AndroidRuntimeShader(shader)
+}
+
+fun RuntimeShader.asAndroidRuntimeShader(): android.graphics.RuntimeShader {
+ return (this as AndroidRuntimeShader).shader
+}
+
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+internal class AndroidRuntimeShader(val shader: android.graphics.RuntimeShader) : RuntimeShader {
+
+ override fun setFloatUniform(name: String, value: Float) {
+ shader.setFloatUniform(name, value)
+ }
+
+ override fun setFloatUniform(name: String, value1: Float, value2: Float) {
+ shader.setFloatUniform(name, value1, value2)
+ }
+
+ override fun setFloatUniform(name: String, value1: Float, value2: Float, value3: Float) {
+ shader.setFloatUniform(name, value1, value2, value3)
+ }
+
+ override fun setFloatUniform(name: String, value1: Float, value2: Float, value3: Float, value4: Float) {
+ shader.setFloatUniform(name, value1, value2, value3, value4)
+ }
+
+ override fun setFloatUniform(name: String, values: FloatArray) {
+ shader.setFloatUniform(name, values)
+ }
+
+ override fun setIntUniform(name: String, value: Int) {
+ shader.setIntUniform(name, value)
+ }
+
+ override fun setIntUniform(name: String, value1: Int, value2: Int) {
+ shader.setIntUniform(name, value1, value2)
+ }
+
+ override fun setIntUniform(name: String, value1: Int, value2: Int, value3: Int) {
+ shader.setIntUniform(name, value1, value2, value3)
+ }
+
+ override fun setIntUniform(name: String, value1: Int, value2: Int, value3: Int, value4: Int) {
+ shader.setIntUniform(name, value1, value2, value3, value4)
+ }
+
+ override fun setIntUniform(name: String, values: IntArray) {
+ shader.setIntUniform(name, values)
+ }
+
+ override fun setColorUniform(name: String, color: Color) {
+ shader.setColorUniform(name, color.toArgb())
+ }
+}
diff --git a/backdrop/src/androidMain/kotlin/com/kyant/backdrop/internal/Paint.kt b/backdrop/src/androidMain/kotlin/com/kyant/backdrop/internal/Paint.kt
new file mode 100644
index 0000000..081428b
--- /dev/null
+++ b/backdrop/src/androidMain/kotlin/com/kyant/backdrop/internal/Paint.kt
@@ -0,0 +1,16 @@
+package com.kyant.backdrop.internal
+
+import android.graphics.BlurMaskFilter
+import androidx.compose.ui.graphics.Paint
+import com.kyant.backdrop.RuntimeShader
+import com.kyant.backdrop.asAndroidRuntimeShader
+
+internal actual fun Paint.blur(radius: Float) {
+ this.asFrameworkPaint().maskFilter =
+ if (radius > 0f) BlurMaskFilter(radius, BlurMaskFilter.Blur.NORMAL)
+ else null
+}
+
+internal actual fun Paint.setRuntimeShader(runtimeShader: RuntimeShader?) {
+ this.asFrameworkPaint().shader = runtimeShader?.asAndroidRuntimeShader()
+}
diff --git a/backdrop/src/androidMain/kotlin/com/kyant/backdrop/internal/PlatformCapabilities.kt b/backdrop/src/androidMain/kotlin/com/kyant/backdrop/internal/PlatformCapabilities.kt
new file mode 100644
index 0000000..12afcae
--- /dev/null
+++ b/backdrop/src/androidMain/kotlin/com/kyant/backdrop/internal/PlatformCapabilities.kt
@@ -0,0 +1,7 @@
+package com.kyant.backdrop.internal
+
+import android.os.Build
+
+internal actual fun isRenderEffectSupported(): Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
+
+internal actual fun isRuntimeShaderSupported(): Boolean = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
diff --git a/backdrop/src/androidMain/kotlin/com/kyant/backdrop/internal/RenderEffect.kt b/backdrop/src/androidMain/kotlin/com/kyant/backdrop/internal/RenderEffect.kt
new file mode 100644
index 0000000..22048e9
--- /dev/null
+++ b/backdrop/src/androidMain/kotlin/com/kyant/backdrop/internal/RenderEffect.kt
@@ -0,0 +1,50 @@
+package com.kyant.backdrop.internal
+
+import android.os.Build
+import androidx.annotation.RequiresApi
+import androidx.compose.ui.graphics.ColorFilter
+import androidx.compose.ui.graphics.RenderEffect
+import androidx.compose.ui.graphics.asAndroidColorFilter
+import androidx.compose.ui.graphics.asComposeRenderEffect
+import com.kyant.backdrop.RuntimeShader
+import com.kyant.backdrop.asAndroidRuntimeShader
+
+@RequiresApi(Build.VERSION_CODES.S)
+internal actual fun RenderEffect?.chain(other: RenderEffect): RenderEffect {
+ return if (this != null) {
+ android.graphics.RenderEffect.createChainEffect(
+ other.asAndroidRenderEffect(),
+ this.asAndroidRenderEffect()
+ ).asComposeRenderEffect()
+ } else {
+ other
+ }
+}
+
+@RequiresApi(Build.VERSION_CODES.TIRAMISU)
+internal actual fun RuntimeShaderEffect(
+ runtimeShader: RuntimeShader,
+ uniformShaderName: String
+): RenderEffect {
+ return android.graphics.RenderEffect.createRuntimeShaderEffect(
+ runtimeShader.asAndroidRuntimeShader(),
+ uniformShaderName
+ ).asComposeRenderEffect()
+}
+
+@RequiresApi(Build.VERSION_CODES.S)
+internal actual fun ColorFilterEffect(
+ renderEffect: RenderEffect?,
+ colorFilter: ColorFilter
+): RenderEffect {
+ return if (renderEffect != null) {
+ android.graphics.RenderEffect.createColorFilterEffect(
+ colorFilter.asAndroidColorFilter(),
+ renderEffect.asAndroidRenderEffect()
+ ).asComposeRenderEffect()
+ } else {
+ android.graphics.RenderEffect.createColorFilterEffect(
+ colorFilter.asAndroidColorFilter(),
+ ).asComposeRenderEffect()
+ }
+}
diff --git a/backdrop/src/main/java/com/kyant/backdrop/Backdrop.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/Backdrop.kt
similarity index 100%
rename from backdrop/src/main/java/com/kyant/backdrop/Backdrop.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/Backdrop.kt
diff --git a/backdrop/src/main/java/com/kyant/backdrop/BackdropEffectScope.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/BackdropEffectScope.kt
similarity index 91%
rename from backdrop/src/main/java/com/kyant/backdrop/BackdropEffectScope.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/BackdropEffectScope.kt
index a271d45..dc42af3 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/BackdropEffectScope.kt
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/BackdropEffectScope.kt
@@ -1,10 +1,7 @@
package com.kyant.backdrop
-import android.graphics.RenderEffect
-import android.graphics.RuntimeShader
-import android.os.Build
-import androidx.annotation.RequiresApi
import androidx.compose.ui.geometry.Size
+import androidx.compose.ui.graphics.RenderEffect
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.unit.Density
@@ -34,7 +31,6 @@ internal abstract class BackdropEffectScopeImpl : BackdropEffectScope, RuntimeSh
private val runtimeShaderCache = RuntimeShaderCacheImpl()
- @RequiresApi(Build.VERSION_CODES.TIRAMISU)
override fun obtainRuntimeShader(key: String, string: String): RuntimeShader {
return runtimeShaderCache.obtainRuntimeShader(key, string)
}
diff --git a/backdrop/src/main/java/com/kyant/backdrop/DrawBackdropModifier.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/DrawBackdropModifier.kt
similarity index 97%
rename from backdrop/src/main/java/com/kyant/backdrop/DrawBackdropModifier.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/DrawBackdropModifier.kt
index e970c24..f757129 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/DrawBackdropModifier.kt
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/DrawBackdropModifier.kt
@@ -1,6 +1,5 @@
package com.kyant.backdrop
-import android.os.Build
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
@@ -9,7 +8,6 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.GraphicsLayerScope
import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.graphics.asComposeRenderEffect
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.graphicsLayer
@@ -33,6 +31,9 @@ import androidx.compose.ui.unit.IntSize
import com.kyant.backdrop.backdrops.LayerBackdrop
import com.kyant.backdrop.highlight.Highlight
import com.kyant.backdrop.highlight.HighlightElement
+import com.kyant.backdrop.internal.ShapeProvider
+import com.kyant.backdrop.internal.isRenderEffectSupported
+import com.kyant.backdrop.internal.recordLayer
import com.kyant.backdrop.shadow.InnerShadow
import com.kyant.backdrop.shadow.InnerShadowElement
import com.kyant.backdrop.shadow.Shadow
@@ -357,11 +358,11 @@ private class DrawBackdropNode(
}
private fun updateEffects() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- effectScope.apply(effects)
- graphicsLayer?.renderEffect = effectScope.renderEffect?.asComposeRenderEffect()
- padding = effectScope.padding
- }
+ if (!isRenderEffectSupported()) return
+
+ effectScope.apply(effects)
+ graphicsLayer?.renderEffect = effectScope.renderEffect
+ padding = effectScope.padding
}
override fun onAttach() {
diff --git a/backdrop/src/commonMain/kotlin/com/kyant/backdrop/RuntimeShader.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/RuntimeShader.kt
new file mode 100644
index 0000000..7085c6e
--- /dev/null
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/RuntimeShader.kt
@@ -0,0 +1,23 @@
+package com.kyant.backdrop
+
+import androidx.compose.ui.graphics.Color
+import org.intellij.lang.annotations.Language
+
+expect fun RuntimeShader(@Language("AGSL") shaderString: String): RuntimeShader
+
+interface RuntimeShader {
+
+ fun setFloatUniform(name: String, value: Float)
+ fun setFloatUniform(name: String, value1: Float, value2: Float)
+ fun setFloatUniform(name: String, value1: Float, value2: Float, value3: Float)
+ fun setFloatUniform(name: String, value1: Float, value2: Float, value3: Float, value4: Float)
+ fun setFloatUniform(name: String, values: FloatArray)
+
+ fun setIntUniform(name: String, value: Int)
+ fun setIntUniform(name: String, value1: Int, value2: Int)
+ fun setIntUniform(name: String, value1: Int, value2: Int, value3: Int)
+ fun setIntUniform(name: String, value1: Int, value2: Int, value3: Int, value4: Int)
+ fun setIntUniform(name: String, values: IntArray)
+
+ fun setColorUniform(name: String, color: Color)
+}
diff --git a/backdrop/src/main/java/com/kyant/backdrop/RuntimeShaderCache.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/RuntimeShaderCache.kt
similarity index 60%
rename from backdrop/src/main/java/com/kyant/backdrop/RuntimeShaderCache.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/RuntimeShaderCache.kt
index f4a953b..f7067c1 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/RuntimeShaderCache.kt
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/RuntimeShaderCache.kt
@@ -1,24 +1,16 @@
package com.kyant.backdrop
-import android.graphics.RuntimeShader
-import android.os.Build
-import androidx.annotation.RequiresApi
import org.intellij.lang.annotations.Language
sealed interface RuntimeShaderCache {
- @RequiresApi(Build.VERSION_CODES.TIRAMISU)
- fun obtainRuntimeShader(
- key: String,
- @Language("AGSL") string: String
- ): RuntimeShader
+ fun obtainRuntimeShader(key: String, @Language("AGSL") string: String): RuntimeShader
}
internal class RuntimeShaderCacheImpl : RuntimeShaderCache {
private val runtimeShaders = mutableMapOf()
- @RequiresApi(Build.VERSION_CODES.TIRAMISU)
override fun obtainRuntimeShader(key: String, string: String): RuntimeShader {
return runtimeShaders.getOrPut(key) { RuntimeShader(string) }
}
diff --git a/backdrop/src/main/java/com/kyant/backdrop/backdrops/Backdrop.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/backdrops/Backdrop.kt
similarity index 100%
rename from backdrop/src/main/java/com/kyant/backdrop/backdrops/Backdrop.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/backdrops/Backdrop.kt
diff --git a/backdrop/src/main/java/com/kyant/backdrop/backdrops/CanvasBackdrop.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/backdrops/CanvasBackdrop.kt
similarity index 100%
rename from backdrop/src/main/java/com/kyant/backdrop/backdrops/CanvasBackdrop.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/backdrops/CanvasBackdrop.kt
diff --git a/backdrop/src/main/java/com/kyant/backdrop/backdrops/CombinedBackdrop.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/backdrops/CombinedBackdrop.kt
similarity index 100%
rename from backdrop/src/main/java/com/kyant/backdrop/backdrops/CombinedBackdrop.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/backdrops/CombinedBackdrop.kt
diff --git a/backdrop/src/main/java/com/kyant/backdrop/backdrops/EmptyBackdrop.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/backdrops/EmptyBackdrop.kt
similarity index 100%
rename from backdrop/src/main/java/com/kyant/backdrop/backdrops/EmptyBackdrop.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/backdrops/EmptyBackdrop.kt
diff --git a/backdrop/src/main/java/com/kyant/backdrop/backdrops/LayerBackdrop.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/backdrops/LayerBackdrop.kt
similarity index 98%
rename from backdrop/src/main/java/com/kyant/backdrop/backdrops/LayerBackdrop.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/backdrops/LayerBackdrop.kt
index 7e15110..787f532 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/backdrops/LayerBackdrop.kt
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/backdrops/LayerBackdrop.kt
@@ -17,7 +17,7 @@ import androidx.compose.ui.layout.LayoutCoordinates
import androidx.compose.ui.layout.positionInWindow
import androidx.compose.ui.unit.Density
import com.kyant.backdrop.Backdrop
-import com.kyant.backdrop.InverseLayerScope
+import com.kyant.backdrop.internal.InverseLayerScope
private val DefaultOnDraw: ContentDrawScope.() -> Unit = { drawContent() }
diff --git a/backdrop/src/main/java/com/kyant/backdrop/backdrops/LayerBackdropModifier.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/backdrops/LayerBackdropModifier.kt
similarity index 97%
rename from backdrop/src/main/java/com/kyant/backdrop/backdrops/LayerBackdropModifier.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/backdrops/LayerBackdropModifier.kt
index a0251cf..a38e9a8 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/backdrops/LayerBackdropModifier.kt
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/backdrops/LayerBackdropModifier.kt
@@ -8,7 +8,7 @@ import androidx.compose.ui.node.GlobalPositionAwareModifierNode
import androidx.compose.ui.node.ModifierNodeElement
import androidx.compose.ui.node.invalidateDraw
import androidx.compose.ui.platform.InspectorInfo
-import com.kyant.backdrop.recordLayer
+import com.kyant.backdrop.internal.recordLayer
fun Modifier.layerBackdrop(backdrop: LayerBackdrop): Modifier =
this then LayerBackdropElement(backdrop)
diff --git a/backdrop/src/commonMain/kotlin/com/kyant/backdrop/effects/Blur.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/effects/Blur.kt
new file mode 100644
index 0000000..5b3d2c2
--- /dev/null
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/effects/Blur.kt
@@ -0,0 +1,29 @@
+package com.kyant.backdrop.effects
+
+import androidx.annotation.FloatRange
+import androidx.compose.ui.graphics.BlurEffect
+import androidx.compose.ui.graphics.TileMode
+import com.kyant.backdrop.BackdropEffectScope
+import com.kyant.backdrop.internal.isRenderEffectSupported
+
+fun BackdropEffectScope.blur(
+ @FloatRange(from = 0.0) radius: Float,
+ edgeTreatment: TileMode = TileMode.Clamp
+) {
+ if (!isRenderEffectSupported()) return
+ if (radius <= 0f) return
+
+ if (edgeTreatment != TileMode.Clamp || renderEffect != null) {
+ if (radius > padding) {
+ padding = radius
+ }
+ }
+
+ renderEffect =
+ BlurEffect(
+ renderEffect,
+ radius,
+ radius,
+ edgeTreatment
+ )
+}
diff --git a/backdrop/src/main/java/com/kyant/backdrop/effects/ColorFilter.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/effects/ColorFilter.kt
similarity index 52%
rename from backdrop/src/main/java/com/kyant/backdrop/effects/ColorFilter.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/effects/ColorFilter.kt
index 57595ee..6ea34df 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/effects/ColorFilter.kt
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/effects/ColorFilter.kt
@@ -1,30 +1,17 @@
package com.kyant.backdrop.effects
-import android.graphics.ColorFilter
-import android.graphics.ColorMatrix
-import android.graphics.ColorMatrixColorFilter
-import android.graphics.RenderEffect
-import android.os.Build
import androidx.annotation.FloatRange
-import androidx.compose.ui.graphics.asAndroidColorFilter
+import androidx.compose.ui.graphics.ColorFilter
+import androidx.compose.ui.graphics.ColorMatrix
+import androidx.compose.ui.graphics.ColorMatrixColorFilter
import com.kyant.backdrop.BackdropEffectScope
-import com.kyant.backdrop.GammaAdjustmentShaderString
-import kotlin.math.pow
+import com.kyant.backdrop.internal.ColorFilterEffect
+import com.kyant.backdrop.internal.isRenderEffectSupported
fun BackdropEffectScope.colorFilter(colorFilter: ColorFilter) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return
+ if (!isRenderEffectSupported()) return
- val currentEffect = renderEffect
- renderEffect =
- if (currentEffect != null) {
- RenderEffect.createColorFilterEffect(colorFilter, currentEffect)
- } else {
- RenderEffect.createColorFilterEffect(colorFilter)
- }
-}
-
-fun BackdropEffectScope.colorFilter(colorFilter: androidx.compose.ui.graphics.ColorFilter) {
- colorFilter(colorFilter.asAndroidColorFilter())
+ renderEffect = ColorFilterEffect(renderEffect, colorFilter)
}
fun BackdropEffectScope.opacity(@FloatRange(from = 0.0, to = 1.0) alpha: Float) {
@@ -51,32 +38,10 @@ fun BackdropEffectScope.colorControls(
colorFilter(colorControlsColorFilter(brightness, contrast, saturation))
}
-fun BackdropEffectScope.vibrancy() {
- colorFilter(VibrantColorFilter)
-}
-
private val VibrantColorFilter = colorControlsColorFilter(saturation = 1.5f)
-fun BackdropEffectScope.exposureAdjustment(ev: Float) {
- val scale = 2f.pow(ev / 2.2f)
- val colorMatrix = ColorMatrix(
- floatArrayOf(
- scale, 0f, 0f, 0f, 0f,
- 0f, scale, 0f, 0f, 0f,
- 0f, 0f, scale, 0f, 0f,
- 0f, 0f, 0f, 1f, 0f
- )
- )
- colorFilter(ColorMatrixColorFilter(colorMatrix))
-}
-
-fun BackdropEffectScope.gammaAdjustment(power: Float) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return
-
- val shader = obtainRuntimeShader("GammaAdjustment", GammaAdjustmentShaderString).apply {
- setFloatUniform("power", power)
- }
- effect(RenderEffect.createRuntimeShaderEffect(shader, "content"))
+fun BackdropEffectScope.vibrancy() {
+ colorFilter(VibrantColorFilter)
}
private fun colorControlsColorFilter(
diff --git a/backdrop/src/main/java/com/kyant/backdrop/effects/Lens.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/effects/Lens.kt
similarity index 90%
rename from backdrop/src/main/java/com/kyant/backdrop/effects/Lens.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/effects/Lens.kt
index f4a4ef7..217901b 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/effects/Lens.kt
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/effects/Lens.kt
@@ -1,15 +1,15 @@
package com.kyant.backdrop.effects
-import android.graphics.RenderEffect
-import android.os.Build
import androidx.annotation.FloatRange
import androidx.compose.foundation.shape.CornerBasedShape
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.util.fastCoerceAtLeast
import androidx.compose.ui.util.fastCoerceAtMost
import com.kyant.backdrop.BackdropEffectScope
-import com.kyant.backdrop.RoundedRectRefractionShaderString
-import com.kyant.backdrop.RoundedRectRefractionWithDispersionShaderString
+import com.kyant.backdrop.internal.RoundedRectRefractionShaderString
+import com.kyant.backdrop.internal.RoundedRectRefractionWithDispersionShaderString
+import com.kyant.backdrop.internal.RuntimeShaderEffect
+import com.kyant.backdrop.internal.isRuntimeShaderSupported
import com.kyant.shapes.RoundedRectangularShape
fun BackdropEffectScope.lens(
@@ -18,7 +18,7 @@ fun BackdropEffectScope.lens(
depthEffect: Boolean = false,
chromaticAberration: Boolean = false
) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return
+ if (!isRuntimeShaderSupported()) return
if (refractionHeight <= 0f || refractionAmount <= 0f) return
if (padding > 0f) {
@@ -51,7 +51,7 @@ fun BackdropEffectScope.lens(
setFloatUniform("chromaticAberration", 1f)
}
}
- RenderEffect.createRuntimeShaderEffect(shader, "content")
+ RuntimeShaderEffect(shader, "content")
} else {
throwUnsupportedSDFException()
}
diff --git a/backdrop/src/commonMain/kotlin/com/kyant/backdrop/effects/RenderEffect.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/effects/RenderEffect.kt
new file mode 100644
index 0000000..df46441
--- /dev/null
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/effects/RenderEffect.kt
@@ -0,0 +1,34 @@
+package com.kyant.backdrop.effects
+
+import androidx.compose.ui.graphics.RenderEffect
+import com.kyant.backdrop.BackdropEffectScope
+import com.kyant.backdrop.RuntimeShader
+import com.kyant.backdrop.internal.RuntimeShaderEffect
+import com.kyant.backdrop.internal.chain
+import com.kyant.backdrop.internal.isRenderEffectSupported
+import com.kyant.backdrop.internal.isRuntimeShaderSupported
+import org.intellij.lang.annotations.Language
+import kotlin.contracts.ExperimentalContracts
+
+fun BackdropEffectScope.effect(effect: RenderEffect) {
+ if (!isRenderEffectSupported()) return
+
+ renderEffect = renderEffect.chain(effect)
+}
+
+@OptIn(ExperimentalContracts::class)
+fun BackdropEffectScope.runtimeShaderEffect(
+ key: String,
+ @Language("AGSL") shaderString: String,
+ uniformShaderName: String,
+ block: RuntimeShader.() -> Unit
+) {
+ if (!isRuntimeShaderSupported()) return
+
+ val effect =
+ RuntimeShaderEffect(
+ runtimeShader = obtainRuntimeShader(key, shaderString).apply(block),
+ uniformShaderName = uniformShaderName
+ )
+ renderEffect = renderEffect.chain(effect)
+}
diff --git a/backdrop/src/main/java/com/kyant/backdrop/highlight/Highlight.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/highlight/Highlight.kt
similarity index 100%
rename from backdrop/src/main/java/com/kyant/backdrop/highlight/Highlight.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/highlight/Highlight.kt
diff --git a/backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightModifier.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/highlight/HighlightModifier.kt
similarity index 85%
rename from backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightModifier.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/highlight/HighlightModifier.kt
index fdd66fa..0ecda10 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightModifier.kt
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/highlight/HighlightModifier.kt
@@ -1,7 +1,5 @@
package com.kyant.backdrop.highlight
-import android.graphics.BlurMaskFilter
-import android.os.Build
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Outline
import androidx.compose.ui.graphics.Paint
@@ -22,8 +20,11 @@ import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.util.fastCoerceAtMost
import com.kyant.backdrop.RuntimeShaderCacheImpl
-import com.kyant.backdrop.ShapeProvider
-import com.kyant.backdrop.clipOutline
+import com.kyant.backdrop.internal.ShapeProvider
+import com.kyant.backdrop.internal.blur
+import com.kyant.backdrop.internal.clipOutline
+import com.kyant.backdrop.internal.isRuntimeShaderSupported
+import com.kyant.backdrop.internal.setRuntimeShader
import kotlin.math.ceil
internal class HighlightElement(
@@ -149,22 +150,17 @@ internal class HighlightNode(
private fun DrawScope.configurePaint(highlight: Highlight) {
paint.color = highlight.style.color
- paint.strokeWidth =
- ceil(highlight.width.toPx().fastCoerceAtMost(size.minDimension / 2f)) * 2f
- val blurRadius = highlight.blurRadius.toPx()
- paint.asFrameworkPaint().maskFilter =
- if (blurRadius > 0f) {
- BlurMaskFilter(blurRadius, BlurMaskFilter.Blur.NORMAL)
- } else {
- null
- }
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- paint.shader = with(highlight.style) {
- createShader(
- shape = shapeProvider.shape,
- runtimeShaderCache = runtimeShaderCache
- )
- }
+ paint.strokeWidth = ceil(highlight.width.toPx().fastCoerceAtMost(size.minDimension / 2f)) * 2f
+ paint.blur(highlight.blurRadius.toPx())
+ if (isRuntimeShaderSupported()) {
+ val shader =
+ with(highlight.style) {
+ createShader(
+ shape = shapeProvider.shape,
+ runtimeShaderCache = runtimeShaderCache
+ )
+ }
+ paint.setRuntimeShader(shader)
}
}
}
diff --git a/backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightStyle.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/highlight/HighlightStyle.kt
similarity index 78%
rename from backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightStyle.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/highlight/HighlightStyle.kt
index 8b7934d..16ceb9a 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/highlight/HighlightStyle.kt
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/highlight/HighlightStyle.kt
@@ -1,22 +1,20 @@
package com.kyant.backdrop.highlight
-import android.os.Build
import androidx.annotation.FloatRange
-import androidx.annotation.RequiresApi
import androidx.compose.foundation.shape.CornerBasedShape
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Shader
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.drawscope.DrawScope
-import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.util.fastCoerceAtMost
-import com.kyant.backdrop.AmbientHighlightShaderString
-import com.kyant.backdrop.DefaultHighlightShaderString
+import com.kyant.backdrop.RuntimeShader
import com.kyant.backdrop.RuntimeShaderCache
+import com.kyant.backdrop.internal.AmbientHighlightShaderString
+import com.kyant.backdrop.internal.DefaultHighlightShaderString
+import com.kyant.backdrop.internal.isRuntimeShaderSupported
import kotlin.math.PI
@Immutable
@@ -26,11 +24,10 @@ interface HighlightStyle {
val blendMode: BlendMode
- @RequiresApi(Build.VERSION_CODES.S)
fun DrawScope.createShader(
shape: Shape,
runtimeShaderCache: RuntimeShaderCache
- ): Shader?
+ ): RuntimeShader?
@Immutable
data class Plain(
@@ -38,11 +35,10 @@ interface HighlightStyle {
override val blendMode: BlendMode = BlendMode.Plus
) : HighlightStyle {
- @RequiresApi(Build.VERSION_CODES.S)
override fun DrawScope.createShader(
shape: Shape,
runtimeShaderCache: RuntimeShaderCache
- ): Shader? = null
+ ): RuntimeShader? = null
}
@Immutable
@@ -53,33 +49,18 @@ interface HighlightStyle {
@param:FloatRange(from = 0.0) val falloff: Float = 1f
) : HighlightStyle {
- @Deprecated(
- "Use the constructor with color parameter instead.",
- ReplaceWith("HighlightStyle.Default(color = Color.White.copy(alpha = intensity), angle = angle, falloff = falloff)")
- )
- constructor(
- intensity: Float,
- angle: Float = 45f,
- falloff: Float = 1f
- ) : this(
- color = Color.White.copy(alpha = intensity),
- angle = angle,
- falloff = falloff
- )
-
- @RequiresApi(Build.VERSION_CODES.S)
override fun DrawScope.createShader(
shape: Shape,
runtimeShaderCache: RuntimeShaderCache
- ): Shader? {
- return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ ): RuntimeShader? {
+ return if (isRuntimeShaderSupported()) {
runtimeShaderCache.obtainRuntimeShader(
"Default",
DefaultHighlightShaderString
).apply {
setFloatUniform("size", size.width, size.height)
setFloatUniform("cornerRadii", getCornerRadii(shape))
- setColorUniform("color", color.copy(alpha = 1f).toArgb())
+ setColorUniform("color", color.copy(alpha = 1f))
setFloatUniform("angle", angle * (PI / 180f).toFloat())
setFloatUniform("falloff", falloff)
}
@@ -98,12 +79,11 @@ interface HighlightStyle {
override val blendMode: BlendMode = DrawScope.DefaultBlendMode
- @RequiresApi(Build.VERSION_CODES.S)
override fun DrawScope.createShader(
shape: Shape,
runtimeShaderCache: RuntimeShaderCache
- ): Shader? {
- return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ ): RuntimeShader? {
+ return if (isRuntimeShaderSupported()) {
runtimeShaderCache.obtainRuntimeShader(
"Ambient",
AmbientHighlightShaderString
diff --git a/backdrop/src/main/java/com/kyant/backdrop/InverseLayerScope.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/InverseLayerScope.kt
similarity index 99%
rename from backdrop/src/main/java/com/kyant/backdrop/InverseLayerScope.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/InverseLayerScope.kt
index 25941d0..f6827ff 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/InverseLayerScope.kt
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/InverseLayerScope.kt
@@ -1,4 +1,4 @@
-package com.kyant.backdrop
+package com.kyant.backdrop.internal
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
diff --git a/backdrop/src/main/java/com/kyant/backdrop/LayerRecorder.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/LayerRecorder.kt
similarity index 95%
rename from backdrop/src/main/java/com/kyant/backdrop/LayerRecorder.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/LayerRecorder.kt
index 82623b0..6876c11 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/LayerRecorder.kt
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/LayerRecorder.kt
@@ -1,4 +1,4 @@
-package com.kyant.backdrop
+package com.kyant.backdrop.internal
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.layer.GraphicsLayer
diff --git a/backdrop/src/main/java/com/kyant/backdrop/Outline.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/Outline.kt
similarity index 93%
rename from backdrop/src/main/java/com/kyant/backdrop/Outline.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/Outline.kt
index 9220e46..1a55526 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/Outline.kt
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/Outline.kt
@@ -1,4 +1,4 @@
-package com.kyant.backdrop
+package com.kyant.backdrop.internal
import androidx.compose.ui.graphics.Canvas
import androidx.compose.ui.graphics.Outline
diff --git a/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/Paint.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/Paint.kt
new file mode 100644
index 0000000..8274d69
--- /dev/null
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/Paint.kt
@@ -0,0 +1,8 @@
+package com.kyant.backdrop.internal
+
+import androidx.compose.ui.graphics.Paint
+import com.kyant.backdrop.RuntimeShader
+
+internal expect fun Paint.blur(radius: Float)
+
+internal expect fun Paint.setRuntimeShader(runtimeShader: RuntimeShader?)
diff --git a/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/Platform.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/Platform.kt
new file mode 100644
index 0000000..a2b48e8
--- /dev/null
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/Platform.kt
@@ -0,0 +1,5 @@
+package com.kyant.backdrop.internal
+
+internal expect fun isRenderEffectSupported(): Boolean
+
+internal expect fun isRuntimeShaderSupported(): Boolean
diff --git a/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/RenderEffect.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/RenderEffect.kt
new file mode 100644
index 0000000..2e94022
--- /dev/null
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/RenderEffect.kt
@@ -0,0 +1,17 @@
+package com.kyant.backdrop.internal
+
+import androidx.compose.ui.graphics.ColorFilter
+import androidx.compose.ui.graphics.RenderEffect
+import com.kyant.backdrop.RuntimeShader
+
+internal expect fun RenderEffect?.chain(other: RenderEffect): RenderEffect
+
+internal expect fun RuntimeShaderEffect(
+ runtimeShader: RuntimeShader,
+ uniformShaderName: String
+): RenderEffect
+
+internal expect fun ColorFilterEffect(
+ renderEffect: RenderEffect? = null,
+ colorFilter: ColorFilter
+): RenderEffect
diff --git a/backdrop/src/main/java/com/kyant/backdrop/Shaders.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/Shaders.kt
similarity index 94%
rename from backdrop/src/main/java/com/kyant/backdrop/Shaders.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/Shaders.kt
index 73fdcfe..a96e900 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/Shaders.kt
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/Shaders.kt
@@ -14,7 +14,7 @@
limitations under the License.
*/
-package com.kyant.backdrop
+package com.kyant.backdrop.internal
import org.intellij.lang.annotations.Language
@@ -202,17 +202,3 @@ half4 main(float2 coord) {
float t = step(0.0, d);
return half4(t, t, t, 1.0) * intensity;
}"""
-
-@Language("AGSL")
-internal const val GammaAdjustmentShaderString = """
-uniform shader content;
-
-uniform float power;
-
-half4 main(float2 coord) {
- half4 color = content.eval(coord);
- color.r = pow(color.r, power);
- color.g = pow(color.g, power);
- color.b = pow(color.b, power);
- return color;
-}"""
diff --git a/backdrop/src/main/java/com/kyant/backdrop/ShapeProvider.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/ShapeProvider.kt
similarity index 97%
rename from backdrop/src/main/java/com/kyant/backdrop/ShapeProvider.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/ShapeProvider.kt
index c79a776..7728916 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/ShapeProvider.kt
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/internal/ShapeProvider.kt
@@ -1,4 +1,4 @@
-package com.kyant.backdrop
+package com.kyant.backdrop.internal
import androidx.compose.runtime.Immutable
import androidx.compose.ui.geometry.Size
diff --git a/backdrop/src/main/java/com/kyant/backdrop/shadow/InnerShadow.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/shadow/InnerShadow.kt
similarity index 100%
rename from backdrop/src/main/java/com/kyant/backdrop/shadow/InnerShadow.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/shadow/InnerShadow.kt
diff --git a/backdrop/src/main/java/com/kyant/backdrop/shadow/InnerShadowModifier.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/shadow/InnerShadowModifier.kt
similarity index 92%
rename from backdrop/src/main/java/com/kyant/backdrop/shadow/InnerShadowModifier.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/shadow/InnerShadowModifier.kt
index 4c65d28..d20e678 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/shadow/InnerShadowModifier.kt
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/shadow/InnerShadowModifier.kt
@@ -1,6 +1,5 @@
package com.kyant.backdrop.shadow
-import android.os.Build
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.BlurEffect
@@ -20,8 +19,9 @@ import androidx.compose.ui.node.invalidateDraw
import androidx.compose.ui.node.requireGraphicsContext
import androidx.compose.ui.platform.InspectorInfo
import androidx.compose.ui.unit.Density
-import com.kyant.backdrop.ShapeProvider
-import com.kyant.backdrop.clipOutline
+import com.kyant.backdrop.internal.ShapeProvider
+import com.kyant.backdrop.internal.clipOutline
+import com.kyant.backdrop.internal.isRenderEffectSupported
internal class InnerShadowElement(
val shapeProvider: ShapeProvider,
@@ -78,7 +78,7 @@ internal class InnerShadowNode(
override fun ContentDrawScope.draw() {
drawContent()
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return
+ if (!isRenderEffectSupported()) return
val shadow = shadow() ?: return
@@ -151,14 +151,6 @@ internal class InnerShadowNode(
private fun DrawScope.configurePaint(shadow: InnerShadow) {
paint.color = shadow.color
}
-
- private fun DrawScope.drawMaskedShadow(outline: Outline, layer: GraphicsLayer) {
- val canvas = drawContext.canvas
- canvas.save()
- canvas.clipOutline(outline, clipPath)
- drawLayer(layer)
- canvas.restore()
- }
}
private val ShadowMaskPaint = Paint().apply {
diff --git a/backdrop/src/main/java/com/kyant/backdrop/shadow/Shadow.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/shadow/Shadow.kt
similarity index 100%
rename from backdrop/src/main/java/com/kyant/backdrop/shadow/Shadow.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/shadow/Shadow.kt
diff --git a/backdrop/src/main/java/com/kyant/backdrop/shadow/ShadowModifier.kt b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/shadow/ShadowModifier.kt
similarity index 92%
rename from backdrop/src/main/java/com/kyant/backdrop/shadow/ShadowModifier.kt
rename to backdrop/src/commonMain/kotlin/com/kyant/backdrop/shadow/ShadowModifier.kt
index 1d810dd..cd4b6e3 100644
--- a/backdrop/src/main/java/com/kyant/backdrop/shadow/ShadowModifier.kt
+++ b/backdrop/src/commonMain/kotlin/com/kyant/backdrop/shadow/ShadowModifier.kt
@@ -1,6 +1,5 @@
package com.kyant.backdrop.shadow
-import android.graphics.BlurMaskFilter
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Paint
@@ -18,7 +17,8 @@ import androidx.compose.ui.node.requireGraphicsContext
import androidx.compose.ui.platform.InspectorInfo
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.IntSize
-import com.kyant.backdrop.ShapeProvider
+import com.kyant.backdrop.internal.ShapeProvider
+import com.kyant.backdrop.internal.blur
import kotlin.math.ceil
internal class ShadowElement(
@@ -128,13 +128,7 @@ internal class ShadowNode(
private fun DrawScope.configurePaint(shadow: Shadow) {
paint.color = shadow.color
- val blurRadius = shadow.radius.toPx()
- paint.asFrameworkPaint().maskFilter =
- if (blurRadius > 0f) {
- BlurMaskFilter(blurRadius, BlurMaskFilter.Blur.NORMAL)
- } else {
- null
- }
+ paint.blur(shadow.radius.toPx())
}
}
diff --git a/backdrop/src/main/AndroidManifest.xml b/backdrop/src/main/AndroidManifest.xml
deleted file mode 100644
index a5918e6..0000000
--- a/backdrop/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/backdrop/src/main/java/com/kyant/backdrop/effects/Blur.kt b/backdrop/src/main/java/com/kyant/backdrop/effects/Blur.kt
deleted file mode 100644
index d3599f3..0000000
--- a/backdrop/src/main/java/com/kyant/backdrop/effects/Blur.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.kyant.backdrop.effects
-
-import android.graphics.RenderEffect
-import android.os.Build
-import androidx.annotation.FloatRange
-import androidx.compose.ui.graphics.TileMode
-import androidx.compose.ui.graphics.toAndroidTileMode
-import com.kyant.backdrop.BackdropEffectScope
-
-fun BackdropEffectScope.blur(
- @FloatRange(from = 0.0) radius: Float,
- edgeTreatment: TileMode = TileMode.Clamp
-) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return
- if (radius <= 0f) return
-
- if (edgeTreatment != TileMode.Clamp || renderEffect != null) {
- if (radius > padding) {
- padding = radius
- }
- }
-
- val currentEffect = renderEffect
- renderEffect =
- if (currentEffect != null) {
- RenderEffect.createBlurEffect(
- radius,
- radius,
- currentEffect,
- edgeTreatment.toAndroidTileMode()
- )
- } else {
- RenderEffect.createBlurEffect(
- radius,
- radius,
- edgeTreatment.toAndroidTileMode()
- )
- }
-}
diff --git a/backdrop/src/main/java/com/kyant/backdrop/effects/RenderEffect.kt b/backdrop/src/main/java/com/kyant/backdrop/effects/RenderEffect.kt
deleted file mode 100644
index bccbb90..0000000
--- a/backdrop/src/main/java/com/kyant/backdrop/effects/RenderEffect.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.kyant.backdrop.effects
-
-import android.graphics.RenderEffect
-import android.os.Build
-import com.kyant.backdrop.BackdropEffectScope
-
-fun BackdropEffectScope.effect(effect: RenderEffect) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return
-
- val currentEffect = renderEffect
- renderEffect =
- if (currentEffect != null) {
- RenderEffect.createChainEffect(effect, currentEffect)
- } else {
- effect
- }
-}
-
-fun BackdropEffectScope.effect(effect: androidx.compose.ui.graphics.RenderEffect) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) return
-
- effect(effect.asAndroidRenderEffect())
-}
diff --git a/backdrop/src/skikoMain/kotlin/com/kyant/backdrop/RuntimeShader.kt b/backdrop/src/skikoMain/kotlin/com/kyant/backdrop/RuntimeShader.kt
new file mode 100644
index 0000000..5f06639
--- /dev/null
+++ b/backdrop/src/skikoMain/kotlin/com/kyant/backdrop/RuntimeShader.kt
@@ -0,0 +1,64 @@
+package com.kyant.backdrop
+
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.colorspace.ColorSpaces
+import org.intellij.lang.annotations.Language
+import org.jetbrains.skia.RuntimeEffect
+import org.jetbrains.skia.RuntimeShaderBuilder
+
+actual fun RuntimeShader(@Language("AGSL") shaderString: String): RuntimeShader {
+ val shader = RuntimeShaderBuilder(RuntimeEffect.makeForShader(shaderString))
+ return SkikoRuntimeShader(shader)
+}
+
+fun RuntimeShader.asSkikoRuntimeShader(): RuntimeShaderBuilder {
+ return (this as SkikoRuntimeShader).shader
+}
+
+internal class SkikoRuntimeShader(val shader: RuntimeShaderBuilder) : RuntimeShader {
+
+ override fun setFloatUniform(name: String, value: Float) {
+ shader.uniform(name, value)
+ }
+
+ override fun setFloatUniform(name: String, value1: Float, value2: Float) {
+ shader.uniform(name, value1, value2)
+ }
+
+ override fun setFloatUniform(name: String, value1: Float, value2: Float, value3: Float) {
+ shader.uniform(name, value1, value2, value3)
+ }
+
+ override fun setFloatUniform(name: String, value1: Float, value2: Float, value3: Float, value4: Float) {
+ shader.uniform(name, value1, value2, value3, value4)
+ }
+
+ override fun setFloatUniform(name: String, values: FloatArray) {
+ shader.uniform(name, values)
+ }
+
+ override fun setIntUniform(name: String, value: Int) {
+ shader.uniform(name, value)
+ }
+
+ override fun setIntUniform(name: String, value1: Int, value2: Int) {
+ shader.uniform(name, value1, value2)
+ }
+
+ override fun setIntUniform(name: String, value1: Int, value2: Int, value3: Int) {
+ shader.uniform(name, value1, value2, value3)
+ }
+
+ override fun setIntUniform(name: String, value1: Int, value2: Int, value3: Int, value4: Int) {
+ shader.uniform(name, value1, value2, value3, value4)
+ }
+
+ override fun setIntUniform(name: String, values: IntArray) {
+ throw UnsupportedOperationException("Setting int array uniforms is not supported on Skia RuntimeShader.")
+ }
+
+ override fun setColorUniform(name: String, color: Color) {
+ val srgb = color.convert(ColorSpaces.Srgb)
+ shader.uniform(name, srgb.red, srgb.green, srgb.blue, srgb.alpha)
+ }
+}
diff --git a/backdrop/src/skikoMain/kotlin/com/kyant/backdrop/internal/Paint.kt b/backdrop/src/skikoMain/kotlin/com/kyant/backdrop/internal/Paint.kt
new file mode 100644
index 0000000..8b1b3e9
--- /dev/null
+++ b/backdrop/src/skikoMain/kotlin/com/kyant/backdrop/internal/Paint.kt
@@ -0,0 +1,17 @@
+package com.kyant.backdrop.internal
+
+import androidx.compose.ui.graphics.Paint
+import com.kyant.backdrop.RuntimeShader
+import com.kyant.backdrop.asSkikoRuntimeShader
+import org.jetbrains.skia.FilterBlurMode
+import org.jetbrains.skia.MaskFilter
+
+internal actual fun Paint.blur(radius: Float) {
+ this.asFrameworkPaint().maskFilter =
+ if (radius > 0f) MaskFilter.makeBlur(FilterBlurMode.NORMAL, radius)
+ else null
+}
+
+internal actual fun Paint.setRuntimeShader(runtimeShader: RuntimeShader?) {
+ this.asFrameworkPaint().shader = runtimeShader?.asSkikoRuntimeShader()?.makeShader()
+}
diff --git a/backdrop/src/skikoMain/kotlin/com/kyant/backdrop/internal/PlatformCapabilities.kt b/backdrop/src/skikoMain/kotlin/com/kyant/backdrop/internal/PlatformCapabilities.kt
new file mode 100644
index 0000000..fe10b51
--- /dev/null
+++ b/backdrop/src/skikoMain/kotlin/com/kyant/backdrop/internal/PlatformCapabilities.kt
@@ -0,0 +1,5 @@
+package com.kyant.backdrop.internal
+
+internal actual fun isRenderEffectSupported(): Boolean = true
+
+internal actual fun isRuntimeShaderSupported(): Boolean = true
diff --git a/backdrop/src/skikoMain/kotlin/com/kyant/backdrop/internal/RenderEffect.kt b/backdrop/src/skikoMain/kotlin/com/kyant/backdrop/internal/RenderEffect.kt
new file mode 100644
index 0000000..3a43d52
--- /dev/null
+++ b/backdrop/src/skikoMain/kotlin/com/kyant/backdrop/internal/RenderEffect.kt
@@ -0,0 +1,42 @@
+package com.kyant.backdrop.internal
+
+import androidx.compose.ui.graphics.ColorFilter
+import androidx.compose.ui.graphics.RenderEffect
+import androidx.compose.ui.graphics.asComposeRenderEffect
+import androidx.compose.ui.graphics.asSkiaColorFilter
+import com.kyant.backdrop.RuntimeShader
+import com.kyant.backdrop.asSkikoRuntimeShader
+import org.jetbrains.skia.ImageFilter
+
+internal actual fun RenderEffect?.chain(other: RenderEffect): RenderEffect {
+ return if (this != null) {
+ ImageFilter.makeCompose(
+ other.asSkiaImageFilter(),
+ this.asSkiaImageFilter()
+ ).asComposeRenderEffect()
+ } else {
+ other
+ }
+}
+
+internal actual fun RuntimeShaderEffect(
+ runtimeShader: RuntimeShader,
+ uniformShaderName: String
+): RenderEffect {
+ return ImageFilter.makeRuntimeShader(
+ runtimeShader.asSkikoRuntimeShader(),
+ uniformShaderName,
+ null
+ ).asComposeRenderEffect()
+}
+
+internal actual fun ColorFilterEffect(
+ renderEffect: RenderEffect?,
+ colorFilter: ColorFilter
+): RenderEffect {
+ return ImageFilter.makeColorFilter(
+ colorFilter.asSkiaColorFilter(),
+ renderEffect?.asSkiaImageFilter(),
+ null
+ ).asComposeRenderEffect()
+}
diff --git a/build.gradle.kts b/build.gradle.kts
index b765df2..8b94c5e 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,7 +1,9 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
- alias(libs.plugins.android.application) apply false
- alias(libs.plugins.android.library) apply false
+ alias(libs.plugins.kotlin.multiplatform) apply false
alias(libs.plugins.kotlin.compose) apply false
+ alias(libs.plugins.android.application) apply false
+ alias(libs.plugins.android.multiplatform.library) apply false
+ alias(libs.plugins.jetbrains.compose) apply false
id("com.vanniktech.maven.publish") version "0.36.0" apply false
}
diff --git a/gradle.properties b/gradle.properties
index 38d51de..dcad3d2 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -28,3 +28,4 @@ org.gradle.caching=true
# (Note that some plugins may not yet be compatible with the configuration cache.)
# https://docs.gradle.org/current/userguide/configuration_cache.html
org.gradle.configuration-cache=true
+org.jetbrains.compose.experimental.macos.enabled=true
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index fc99182..73919b7 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -4,19 +4,21 @@ kotlin = "2.3.0"
activity = "1.12.2"
core = "1.17.0"
-compose = "1.10.1"
-kyantShapes = "1.0.0"
+compose = "1.10.0"
+kyantShapes = "1.0.4"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activity" }
-androidx-compose-foundation = { group = "androidx.compose.foundation", name = "foundation", version.ref = "compose" }
-androidx-compose-ui = { group = "androidx.compose.ui", name = "ui", version.ref = "compose" }
-androidx-compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics", version.ref = "compose" }
-androidx-compose-material-ripple = { group = "androidx.compose.material", name = "material-ripple", version.ref = "compose" }
+compose-foundation = { group = "org.jetbrains.compose.foundation", name = "foundation", version.ref = "compose" }
+compose-ui = { group = "org.jetbrains.compose.ui", name = "ui", version.ref = "compose" }
+compose-ui-graphics = { group = "org.jetbrains.compose.ui", name = "ui-graphics", version.ref = "compose" }
+compose-material-ripple = { group = "org.jetbrains.compose.material", name = "material-ripple", version.ref = "compose" }
kyant-shapes = { group = "io.github.kyant0", name = "shapes", version.ref = "kyantShapes" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
-android-library = { id = "com.android.library", version.ref = "agp" }
+android-multiplatform-library = { id = "com.android.kotlin.multiplatform.library", version.ref = "agp" }
+kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
+jetbrains-compose = { id = "org.jetbrains.compose", version.ref = "compose" }
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 3f107f1..60e1bee 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -24,4 +24,5 @@ dependencyResolutionManagement {
rootProject.name = "Glass"
include(":backdrop")
-include(":catalog")
+include(":app")
+include(":androidApp")