Update highlight implementation to use BlurMaskFilter
This commit is contained in:
1 parent
9dcfa0aa8c
commit
1810bc64f3
4 files changed
+42
-74
No files matched your search
@@ -25,7 +25,7 @@ private class BackdropElement(val backdrop: Backdrop) : ModifierNodeElement<Back
|
||||
}
|
||||
|
||||
override fun InspectorInfo.inspectableProperties() {
|
||||
name = "layerBackdrop"
|
||||
name = "backdrop"
|
||||
properties["backdrop"] = backdrop
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,9 @@ import androidx.compose.ui.unit.dp
|
||||
@Immutable
|
||||
data class Highlight(
|
||||
val width: Dp = 1f.dp,
|
||||
val color: Color = Color.White.copy(alpha = 0.38f),
|
||||
val color: Color = Color.White.copy(alpha = 0.25f),
|
||||
val blendMode: BlendMode = BlendMode.Plus,
|
||||
val blurRadius: Dp = width / 3f,
|
||||
val style: () -> HighlightStyle = DefaultHighlightStyle
|
||||
)
|
||||
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
package com.kyant.backdrop.highlight
|
||||
|
||||
import android.graphics.BlurMaskFilter
|
||||
import android.graphics.Paint
|
||||
import android.graphics.RectF
|
||||
import android.os.Build
|
||||
import androidx.compose.ui.draw.CacheDrawModifierNode
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.GraphicsLayerScope
|
||||
import androidx.compose.ui.graphics.Outline
|
||||
import androidx.compose.ui.graphics.asAndroidPath
|
||||
import androidx.compose.ui.graphics.asComposePaint
|
||||
import androidx.compose.ui.graphics.asComposeRenderEffect
|
||||
import androidx.compose.ui.graphics.drawscope.translate
|
||||
import androidx.compose.ui.graphics.isUnspecified
|
||||
import androidx.compose.ui.graphics.layer.GraphicsLayer
|
||||
import androidx.compose.ui.graphics.layer.drawLayer
|
||||
@@ -91,42 +90,43 @@ internal class HighlightNode(
|
||||
}
|
||||
|
||||
val size = size
|
||||
val strokeWidth = ceil(highlight.width.toPx().fastCoerceAtMost(size.minDimension / 2f))
|
||||
val borderSize = Size(size.width - strokeWidth, size.height - strokeWidth)
|
||||
val outline = shapeProvider.shape.createOutline(borderSize, layoutDirection, this)
|
||||
val outline = shapeProvider.shape.createOutline(size, layoutDirection, this)
|
||||
|
||||
paint.color = highlight.color.toArgb()
|
||||
paint.strokeWidth = strokeWidth
|
||||
val strokeWidth = ceil(highlight.width.toPx().fastCoerceAtMost(size.minDimension / 2f))
|
||||
paint.strokeWidth = strokeWidth * 2f
|
||||
val blurRadius = highlight.blurRadius.toPx()
|
||||
if (blurRadius > 0f) {
|
||||
paint.maskFilter = BlurMaskFilter(blurRadius, BlurMaskFilter.Blur.NORMAL)
|
||||
}
|
||||
paint.asComposePaint().blendMode = highlight.blendMode
|
||||
|
||||
graphicsLayer.blendMode = highlight.blendMode
|
||||
graphicsLayer.record {
|
||||
translate(strokeWidth / 2f, strokeWidth / 2f) {
|
||||
val canvas = drawContext.canvas.nativeCanvas
|
||||
val canvas = drawContext.canvas.nativeCanvas
|
||||
|
||||
when (outline) {
|
||||
is Outline.Rectangle -> {
|
||||
val rect = RectF(0f, 0f, borderSize.width, borderSize.height)
|
||||
canvas.drawRect(rect, paint)
|
||||
}
|
||||
when (outline) {
|
||||
is Outline.Rectangle -> {
|
||||
val rect = RectF(0f, 0f, size.width, size.height)
|
||||
canvas.drawRect(rect, paint)
|
||||
}
|
||||
|
||||
is Outline.Rounded -> {
|
||||
@Suppress("INVISIBLE_REFERENCE")
|
||||
val path = outline.roundRectPath?.asAndroidPath()
|
||||
if (path != null) {
|
||||
canvas.drawPath(path, paint)
|
||||
} else {
|
||||
val rect = with(outline.roundRect) { RectF(left, top, right, bottom) }
|
||||
val radius = outline.roundRect.topLeftCornerRadius.x
|
||||
canvas.drawRoundRect(rect, radius, radius, paint)
|
||||
}
|
||||
}
|
||||
|
||||
is Outline.Generic -> {
|
||||
val path = outline.path.asAndroidPath()
|
||||
is Outline.Rounded -> {
|
||||
@Suppress("INVISIBLE_REFERENCE")
|
||||
val path = outline.roundRectPath?.asAndroidPath()
|
||||
if (path != null) {
|
||||
canvas.drawPath(path, paint)
|
||||
} else {
|
||||
val rect = with(outline.roundRect) { RectF(left, top, right, bottom) }
|
||||
val radius = outline.roundRect.topLeftCornerRadius.x
|
||||
canvas.drawRoundRect(rect, radius, radius, paint)
|
||||
}
|
||||
}
|
||||
|
||||
is Outline.Generic -> {
|
||||
val path = outline.path.asAndroidPath()
|
||||
canvas.drawPath(path, paint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,6 +141,8 @@ internal class HighlightNode(
|
||||
})
|
||||
|
||||
private val layerBlock: GraphicsLayerScope.() -> Unit = {
|
||||
clip = true
|
||||
shape = shapeProvider.shape
|
||||
compositingStrategy = androidx.compose.ui.graphics.CompositingStrategy.Offscreen
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.kyant.backdrop.highlight
|
||||
|
||||
import android.graphics.RenderEffect
|
||||
import android.graphics.RuntimeShader
|
||||
import android.graphics.Shader
|
||||
import android.os.Build
|
||||
import androidx.annotation.FloatRange
|
||||
import androidx.annotation.RequiresApi
|
||||
@@ -24,22 +23,7 @@ interface HighlightStyle {
|
||||
data object Solid : HighlightStyle
|
||||
|
||||
@Immutable
|
||||
data object Soft : HighlightStyle {
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.S)
|
||||
override fun createRenderEffect(size: Size, width: Float): RenderEffect? {
|
||||
val blurRadiusPx = width / 2f
|
||||
return if (blurRadiusPx > 0f) {
|
||||
RenderEffect.createBlurEffect(
|
||||
blurRadiusPx,
|
||||
blurRadiusPx,
|
||||
Shader.TileMode.DECAL
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
data object Soft : HighlightStyle
|
||||
|
||||
@Immutable
|
||||
data class Dynamic(
|
||||
@@ -49,36 +33,17 @@ interface HighlightStyle {
|
||||
|
||||
@RequiresApi(Build.VERSION_CODES.S)
|
||||
override fun createRenderEffect(size: Size, width: Float): RenderEffect? {
|
||||
val blurRadiusPx = width / 2f
|
||||
val blurRenderEffect =
|
||||
if (blurRadiusPx > 0f) {
|
||||
RenderEffect.createBlurEffect(
|
||||
blurRadiusPx,
|
||||
blurRadiusPx,
|
||||
Shader.TileMode.DECAL
|
||||
)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
val highlightRenderEffect =
|
||||
RenderEffect.createRuntimeShaderEffect(
|
||||
RuntimeShader(DynamicHighlightShaderString).apply {
|
||||
setFloatUniform("size", size.width, size.height)
|
||||
setFloatUniform("angle", angle * (PI / 180f).toFloat())
|
||||
setFloatUniform("falloff", falloff)
|
||||
},
|
||||
"image"
|
||||
)
|
||||
|
||||
if (blurRenderEffect != null) {
|
||||
RenderEffect.createChainEffect(highlightRenderEffect, blurRenderEffect)
|
||||
} else {
|
||||
highlightRenderEffect
|
||||
}
|
||||
RenderEffect.createRuntimeShaderEffect(
|
||||
RuntimeShader(DynamicHighlightShaderString).apply {
|
||||
setFloatUniform("size", size.width, size.height)
|
||||
setFloatUniform("angle", angle * (PI / 180f).toFloat())
|
||||
setFloatUniform("falloff", falloff)
|
||||
},
|
||||
"image"
|
||||
)
|
||||
} else {
|
||||
blurRenderEffect
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user