From e2afdc98de5b31dc4cf8983a27850df86a536bf8 Mon Sep 17 00:00:00 2001 From: sanlorng Date: Wed, 17 Apr 2024 21:12:01 +0800 Subject: [PATCH 1/4] [fluent] remove dp convert twice. --- .../com/konyaco/fluent/background/Layer.kt | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/fluent/src/commonMain/kotlin/com/konyaco/fluent/background/Layer.kt b/fluent/src/commonMain/kotlin/com/konyaco/fluent/background/Layer.kt index 2f3e0d7f..b065d31f 100644 --- a/fluent/src/commonMain/kotlin/com/konyaco/fluent/background/Layer.kt +++ b/fluent/src/commonMain/kotlin/com/konyaco/fluent/background/Layer.kt @@ -28,6 +28,8 @@ import androidx.compose.ui.unit.dp import com.konyaco.fluent.FluentTheme import com.konyaco.fluent.LocalContentColor import com.konyaco.fluent.ProvideTextStyle +import kotlin.math.floor +import kotlin.math.roundToInt import kotlin.math.sqrt /** @@ -143,12 +145,12 @@ private value class BackgroundPaddingShape(private val borderShape: CornerBasedS override fun createOutline(size: Size, layoutDirection: LayoutDirection, density: Density): Outline { return with(density) { - val circular = borderShape == CircleShape + val circular = borderShape == CircleShape && size.height == size.width val paddingPx = when { circular -> calcCircularPadding(density) else -> calcPadding(density) - }.toPx() - createInnerOutline(size, density, layoutDirection, paddingPx) + } + createInnerOutline(size, density, layoutDirection, paddingPx.roundToInt().toFloat()) } } @@ -207,23 +209,23 @@ private value class BackgroundPaddingShape(private val borderShape: CornerBasedS * when density is not integer or `(density % 1) < 0.5` */ @Stable -private fun calcPadding(density: Density): Dp { +private fun calcPadding(density: Density): Float { val remainder = density.density % 1f return with(density) { when { - remainder == 0f -> 1.dp - else -> (1.dp.toPx() - remainder + 1).toDp() + remainder == 0f -> 1.dp.toPx() + else -> 1.dp.toPx() - remainder + 1 } } } @Stable -private fun calcCircularPadding(density: Density): Dp { +private fun calcCircularPadding(density: Density): Float { val remainder = density.density % 1f return with(density) { - if (remainder == 0f) 1.dp - else (1.dp.toPx() - remainder + 1).toDp() + if (remainder == 0f) (1.dp.toPx() - 1f) + else floor(1.dp.toPx()) } } \ No newline at end of file From 0f26416ee43c75528c1110be2d778e383defe10f Mon Sep 17 00:00:00 2001 From: KonYaco Date: Thu, 18 Apr 2024 16:04:02 +0800 Subject: [PATCH 2/4] Update the way to eliminate gap --- .../com/konyaco/fluent/background/Layer.kt | 53 +++++++++++-------- .../gallery/screen/settings/SettingsScreen.kt | 47 +++++++++++++++- .../kotlin/com/konyaco/fluent/gallery/Main.kt | 2 +- 3 files changed, 79 insertions(+), 23 deletions(-) diff --git a/fluent/src/commonMain/kotlin/com/konyaco/fluent/background/Layer.kt b/fluent/src/commonMain/kotlin/com/konyaco/fluent/background/Layer.kt index b065d31f..b875ed70 100644 --- a/fluent/src/commonMain/kotlin/com/konyaco/fluent/background/Layer.kt +++ b/fluent/src/commonMain/kotlin/com/konyaco/fluent/background/Layer.kt @@ -20,7 +20,9 @@ import androidx.compose.ui.geometry.Size import androidx.compose.ui.geometry.translate import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Outline +import androidx.compose.ui.graphics.ShaderBrush import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.LayoutDirection @@ -28,8 +30,8 @@ import androidx.compose.ui.unit.dp import com.konyaco.fluent.FluentTheme import com.konyaco.fluent.LocalContentColor import com.konyaco.fluent.ProvideTextStyle +import kotlin.math.ceil import kotlin.math.floor -import kotlin.math.roundToInt import kotlin.math.sqrt /** @@ -123,7 +125,17 @@ private fun Modifier.layer( if (border != null) { val backgroundShape = if (backgroundSizing == BackgroundSizing.InnerBorderEdge && shape is CornerBasedShape) { - BackgroundPaddingShape(shape) + val brush = border.brush + // FIXME(Workaround): If the border color has alpha channel, shrink padding to not cover the content background + val hasAlpha = if (brush is SolidColor) { + brush.value.alpha < 1f + } else if (brush is ShaderBrush) { + // TODO: Detect if there are transparent colors in gradient. + true + } else { + false + } + BackgroundPaddingShape(shape, cover = !hasAlpha) } else { shape } @@ -140,17 +152,19 @@ private fun Modifier.layer( * keep padding for background */ @Immutable -@JvmInline -private value class BackgroundPaddingShape(private val borderShape: CornerBasedShape) : Shape { +private class BackgroundPaddingShape( + private val borderShape: CornerBasedShape, + private val cover: Boolean +) : Shape { override fun createOutline(size: Size, layoutDirection: LayoutDirection, density: Density): Outline { return with(density) { val circular = borderShape == CircleShape && size.height == size.width val paddingPx = when { - circular -> calcCircularPadding(density) - else -> calcPadding(density) + circular -> calcCircularPadding(density, cover) + else -> calcPadding(density, cover) } - createInnerOutline(size, density, layoutDirection, paddingPx.roundToInt().toFloat()) + createInnerOutline(size, density, layoutDirection, paddingPx) } } @@ -204,28 +218,25 @@ private value class BackgroundPaddingShape(private val borderShape: CornerBasedS } } -/** - * This is a workaround solution to eliminate 1 pixel gap - * when density is not integer or `(density % 1) < 0.5` - */ @Stable -private fun calcPadding(density: Density): Float { - val remainder = density.density % 1f - +private fun calcPadding(density: Density, cover: Boolean): Float { return with(density) { - when { - remainder == 0f -> 1.dp.toPx() - else -> 1.dp.toPx() - remainder + 1 - } + if (cover) ceil(1.dp.toPx()) // cover + else ceil(1.dp.toPx())// do not cover } } @Stable -private fun calcCircularPadding(density: Density): Float { +private fun calcCircularPadding(density: Density, cover: Boolean): Float { val remainder = density.density % 1f return with(density) { - if (remainder == 0f) (1.dp.toPx() - 1f) - else floor(1.dp.toPx()) + if (remainder == 0f) { + if (cover) floor(1.dp.toPx()) - 0.5f // cover + else floor(1.dp.toPx()) - 0.15f// do not cover + } else { + if (cover) floor(1.dp.toPx()) // overlap + else floor(1.dp.toPx()) + 0.85f// do not cover + } } } \ No newline at end of file diff --git a/gallery/src/commonMain/kotlin/com/konyaco/fluent/gallery/screen/settings/SettingsScreen.kt b/gallery/src/commonMain/kotlin/com/konyaco/fluent/gallery/screen/settings/SettingsScreen.kt index 45a4c433..051daa55 100644 --- a/gallery/src/commonMain/kotlin/com/konyaco/fluent/gallery/screen/settings/SettingsScreen.kt +++ b/gallery/src/commonMain/kotlin/com/konyaco/fluent/gallery/screen/settings/SettingsScreen.kt @@ -340,7 +340,52 @@ private fun Content() { }, backgroundSizing = BackgroundSizing.OuterBorderEdge ) - + Layer( + modifier = Modifier.size(32.dp), + shape = CircleShape, + color = FluentTheme.colors.fillAccent.default, + border = BorderStroke(1.dp, FluentTheme.colors.fillAccent.default), + backgroundSizing = BackgroundSizing.InnerBorderEdge, + content = {} + ) + Layer( + shape = CircleShape, + color = FluentTheme.colors.fillAccent.default, + border = BorderStroke(1.dp, FluentTheme.colors.fillAccent.default), + content = { Box(Modifier.size(height = 32.dp, width = 64.dp))}, + backgroundSizing = BackgroundSizing.InnerBorderEdge + ) + Layer( + shape = CircleShape, +// modifier = Modifier.size(32.dp), + color = FluentTheme.colors.controlStrong.default, + border = BorderStroke(1.dp, FluentTheme.colors.controlStrong.default), + backgroundSizing = BackgroundSizing.InnerBorderEdge, + content = { Box(Modifier.size(32.dp)) } + ) + Layer( + shape = CircleShape, + modifier = Modifier.size(64.dp, 32.dp), + color = FluentTheme.colors.controlStrong.default, + border = BorderStroke(1.dp, FluentTheme.colors.controlStrong.default), + backgroundSizing = BackgroundSizing.InnerBorderEdge, + content = {} + ) + Layer( + shape = RoundedCornerShape(4.dp), + color = FluentTheme.colors.fillAccent.default, + border = BorderStroke(1.dp, FluentTheme.colors.fillAccent.default), + content = { Box(Modifier.size(height = 32.dp, width = 64.dp))}, + backgroundSizing = BackgroundSizing.InnerBorderEdge + ) + Layer( + shape = RoundedCornerShape(4.dp), + modifier = Modifier.size(64.dp, 32.dp), + color = FluentTheme.colors.controlStrong.default, + border = BorderStroke(1.dp, FluentTheme.colors.controlStrong.default), + backgroundSizing = BackgroundSizing.InnerBorderEdge, + content = {} + ) Card(Modifier) { Box(Modifier.size(32.dp)) } diff --git a/gallery/src/desktopMain/kotlin/com/konyaco/fluent/gallery/Main.kt b/gallery/src/desktopMain/kotlin/com/konyaco/fluent/gallery/Main.kt index f5f64993..b265ad93 100644 --- a/gallery/src/desktopMain/kotlin/com/konyaco/fluent/gallery/Main.kt +++ b/gallery/src/desktopMain/kotlin/com/konyaco/fluent/gallery/Main.kt @@ -22,7 +22,7 @@ fun main() = application { title = "Compose Fluent Design Gallery", icon = painterResource(Res.drawable.icon) ) { - GalleryTheme { + GalleryTheme(false) { //TODO Make Window transparent. WindowStyle( isDarkTheme = LocalStore.current.darkMode, From 7cdb0d39bf099a8b1599bb9729367644ea102577 Mon Sep 17 00:00:00 2001 From: KonYaco Date: Thu, 18 Apr 2024 16:05:47 +0800 Subject: [PATCH 3/4] Rollback main --- .../src/desktopMain/kotlin/com/konyaco/fluent/gallery/Main.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gallery/src/desktopMain/kotlin/com/konyaco/fluent/gallery/Main.kt b/gallery/src/desktopMain/kotlin/com/konyaco/fluent/gallery/Main.kt index b265ad93..f5f64993 100644 --- a/gallery/src/desktopMain/kotlin/com/konyaco/fluent/gallery/Main.kt +++ b/gallery/src/desktopMain/kotlin/com/konyaco/fluent/gallery/Main.kt @@ -22,7 +22,7 @@ fun main() = application { title = "Compose Fluent Design Gallery", icon = painterResource(Res.drawable.icon) ) { - GalleryTheme(false) { + GalleryTheme { //TODO Make Window transparent. WindowStyle( isDarkTheme = LocalStore.current.darkMode, From 945f587772949006f644a1fa1ceb1eea6f290d55 Mon Sep 17 00:00:00 2001 From: KonYaco Date: Thu, 18 Apr 2024 16:10:49 +0800 Subject: [PATCH 4/4] Update the way to eliminate gap --- .../commonMain/kotlin/com/konyaco/fluent/background/Layer.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fluent/src/commonMain/kotlin/com/konyaco/fluent/background/Layer.kt b/fluent/src/commonMain/kotlin/com/konyaco/fluent/background/Layer.kt index b875ed70..d7481eeb 100644 --- a/fluent/src/commonMain/kotlin/com/konyaco/fluent/background/Layer.kt +++ b/fluent/src/commonMain/kotlin/com/konyaco/fluent/background/Layer.kt @@ -221,7 +221,7 @@ private class BackgroundPaddingShape( @Stable private fun calcPadding(density: Density, cover: Boolean): Float { return with(density) { - if (cover) ceil(1.dp.toPx()) // cover + if (cover) ceil(1.dp.toPx()) - 0.5f // cover else ceil(1.dp.toPx())// do not cover } }