Skip to content

Commit

Permalink
Tweak public API
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisbanes committed Dec 7, 2023
1 parent 9fad7a6 commit abdcbc6
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 75 deletions.
25 changes: 22 additions & 3 deletions haze-jetpack-compose/api/api.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
// Signature format: 4.0
package dev.chrisbanes.haze {

@androidx.compose.runtime.Stable public final class HazeArea {
ctor public HazeArea();
method public androidx.compose.ui.geometry.Rect getBounds();
method public androidx.compose.ui.graphics.Shape getShape();
method public boolean isEmpty();
property public final androidx.compose.ui.geometry.Rect bounds;
property public final boolean isEmpty;
property public final androidx.compose.ui.graphics.Shape shape;
}

public final class HazeChildKt {
method public static androidx.compose.ui.Modifier hazeChild(androidx.compose.ui.Modifier, Object key, dev.chrisbanes.haze.HazeState state, optional androidx.compose.ui.graphics.Shape shape);
}

public final class HazeDefaults {
method public float getBlurRadius();
method public float getTintAlpha();
Expand All @@ -12,9 +26,14 @@ package dev.chrisbanes.haze {
}

public final class HazeKt {
method public static inline androidx.compose.ui.Modifier haze(androidx.compose.ui.Modifier, androidx.compose.ui.geometry.Rect![] area, long backgroundColor, optional long tint, optional float blurRadius, optional float noiseFactor);
method public static inline androidx.compose.ui.Modifier haze(androidx.compose.ui.Modifier, androidx.compose.ui.geometry.RoundRect![] area, long backgroundColor, optional long tint, optional float blurRadius, optional float noiseFactor);
method public static androidx.compose.ui.Modifier haze(androidx.compose.ui.Modifier, java.util.List<androidx.compose.ui.geometry.RoundRect> areas, long backgroundColor, optional long tint, optional float blurRadius, optional float noiseFactor);
method public static androidx.compose.ui.Modifier haze(androidx.compose.ui.Modifier, dev.chrisbanes.haze.HazeState state, long backgroundColor, optional long tint, optional float blurRadius, optional float noiseFactor);
}

@androidx.compose.runtime.Stable public final class HazeState {
ctor public HazeState();
method public java.util.Set<dev.chrisbanes.haze.HazeArea> getAreas();
method public void updateArea(Object key, androidx.compose.ui.geometry.Rect bounds, androidx.compose.ui.graphics.Shape shape);
property public final java.util.Set<dev.chrisbanes.haze.HazeArea> areas;
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class HazeState {
*/
private val _areas = mutableStateMapOf<Any, HazeArea>()

val areas: Map<Any, HazeArea> get() = _areas
val areas: Set<HazeArea> get() = _areas.values.toSet()

fun updateArea(key: Any, bounds: Rect, shape: Shape) {
_areas.getOrPut(key, ::HazeArea).apply {
Expand All @@ -41,12 +41,12 @@ class HazeState {
}
}

internal fun HazeState.updatePath(
internal fun HazeState.addAreasToPath(
path: Path,
layoutDirection: LayoutDirection,
density: Density,
) {
areas.values.asSequence()
areas.asSequence()
.filterNot { it.isEmpty }
.forEach { area ->
path.addOutline(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,32 +166,30 @@ internal class HazeNode31(
}

// We create a RenderNode for each of the areas we need to apply our effect to
return state.areas.values.asSequence()
.map { area ->
val bounds = area.boundsInLocal(boundsInRoot)

// We expand the area where our effect is applied to. This is necessary so that the blur
// effect is applied evenly to all edges. If we don't do this, the blur effect is much less
// visible on the edges of the area.
val expandedRect = bounds.inflate(blurRadiusPx)

val node = RenderNode("blur").apply {
setRenderEffect(effect)
setPosition(0, 0, expandedRect.width.toInt(), expandedRect.height.toInt())
translationX = expandedRect.left
translationY = expandedRect.top
}
return state.areas.asSequence().map { area ->
val bounds = area.boundsInLocal(boundsInRoot)

// We expand the area where our effect is applied to. This is necessary so that the blur
// effect is applied evenly to all edges. If we don't do this, the blur effect is much less
// visible on the edges of the area.
val expandedRect = bounds.inflate(blurRadiusPx)

val node = RenderNode("blur").apply {
setRenderEffect(effect)
setPosition(0, 0, expandedRect.width.toInt(), expandedRect.height.toInt())
translationX = expandedRect.left
translationY = expandedRect.top
}

EffectHolder(
renderNode = node,
renderNodeDrawArea = expandedRect,
area = bounds,
shape = area.shape,
).apply {
updatePath(layoutDirection, density)
}
EffectHolder(
renderNode = node,
renderNodeDrawArea = expandedRect,
area = bounds,
shape = area.shape,
).apply {
updatePath(layoutDirection, density)
}
.toList()
}.toList()
}

@SuppressLint("SuspiciousCompositionLocalModifierRead") // LocalContext will never change
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ internal class HazeNodeBase(

private fun updatePath(layoutDirection: LayoutDirection, density: Density) {
path.reset()
state.updatePath(path, layoutDirection, density)
state.addAreasToPath(path, layoutDirection, density)
pathDirty = false
}
}
25 changes: 22 additions & 3 deletions haze/api/api.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
// Signature format: 4.0
package dev.chrisbanes.haze {

@androidx.compose.runtime.Stable public final class HazeArea {
ctor public HazeArea();
method public androidx.compose.ui.geometry.Rect getBounds();
method public androidx.compose.ui.graphics.Shape getShape();
method public boolean isEmpty();
property public final androidx.compose.ui.geometry.Rect bounds;
property public final boolean isEmpty;
property public final androidx.compose.ui.graphics.Shape shape;
}

public final class HazeChildKt {
method public static androidx.compose.ui.Modifier hazeChild(androidx.compose.ui.Modifier, Object key, dev.chrisbanes.haze.HazeState state, optional androidx.compose.ui.graphics.Shape shape);
}

public final class HazeDefaults {
method public float getBlurRadius();
method public float getTintAlpha();
Expand All @@ -12,9 +26,14 @@ package dev.chrisbanes.haze {
}

public final class HazeKt {
method public static inline androidx.compose.ui.Modifier haze(androidx.compose.ui.Modifier, androidx.compose.ui.geometry.Rect![] area, long backgroundColor, optional long tint, optional float blurRadius, optional float noiseFactor);
method public static inline androidx.compose.ui.Modifier haze(androidx.compose.ui.Modifier, androidx.compose.ui.geometry.RoundRect![] area, long backgroundColor, optional long tint, optional float blurRadius, optional float noiseFactor);
method public static androidx.compose.ui.Modifier haze(androidx.compose.ui.Modifier, java.util.List<androidx.compose.ui.geometry.RoundRect> areas, long backgroundColor, optional long tint, optional float blurRadius, optional float noiseFactor);
method public static androidx.compose.ui.Modifier haze(androidx.compose.ui.Modifier, dev.chrisbanes.haze.HazeState state, long backgroundColor, optional long tint, optional float blurRadius, optional float noiseFactor);
}

@androidx.compose.runtime.Stable public final class HazeState {
ctor public HazeState();
method public java.util.Set<dev.chrisbanes.haze.HazeArea> getAreas();
method public void updateArea(Object key, androidx.compose.ui.geometry.Rect bounds, androidx.compose.ui.graphics.Shape shape);
property public final java.util.Set<dev.chrisbanes.haze.HazeArea> areas;
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ internal class HazeNodeBase(

private fun updatePath(layoutDirection: LayoutDirection, density: Density) {
path.reset()
state.updatePath(path, layoutDirection, density)
state.addAreasToPath(path, layoutDirection, density)
pathDirty = false
}
}
6 changes: 3 additions & 3 deletions haze/src/commonMain/kotlin/dev/chrisbanes/haze/Haze.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class HazeState {
*/
private val _areas = mutableStateMapOf<Any, HazeArea>()

val areas: Map<Any, HazeArea> get() = _areas
val areas: Set<HazeArea> get() = _areas.values.toSet()

fun updateArea(key: Any, bounds: Rect, shape: Shape) {
_areas.getOrPut(key, ::HazeArea).apply {
Expand All @@ -41,12 +41,12 @@ class HazeState {
}
}

internal fun HazeState.updatePath(
internal fun HazeState.addAreasToPath(
path: Path,
layoutDirection: LayoutDirection,
density: Density,
) {
areas.values.asSequence()
areas.asSequence()
.filterNot { it.isEmpty }
.forEach { area ->
path.addOutline(
Expand Down
72 changes: 35 additions & 37 deletions haze/src/skikoMain/kotlin/dev/chrisbanes/haze/HazeNode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -151,49 +151,47 @@ private class SkiaHazeNode(
val blurRadiusPx = with(density) { blurRadius.toPx() }
val blurFilter = createBlurImageFilter(blurRadiusPx)

val filters = state.areas.asSequence()
.map { it.value }
.map { area ->
val compositeShaderBuilder = RuntimeShaderBuilder(RUNTIME_SHADER).apply {
val areaLocalBounds = area.boundsInLocal(boundsInRoot)
uniform(
"rectangle",
areaLocalBounds.left,
areaLocalBounds.top,
areaLocalBounds.right,
areaLocalBounds.bottom,
)

when (val shape = area.shape) {
is CornerBasedShape -> {
uniform(
"radius",
shape.topStart.toPx(area.bounds.size, density),
shape.topEnd.toPx(area.bounds.size, density),
shape.bottomStart.toPx(area.bounds.size, density),
shape.bottomEnd.toPx(area.bounds.size, density),
)
}

else -> {
uniform("radius", 0f, 0f, 0f, 0f)
}
}
val filters = state.areas.asSequence().map { area ->
val compositeShaderBuilder = RuntimeShaderBuilder(RUNTIME_SHADER).apply {
val areaLocalBounds = area.boundsInLocal(boundsInRoot)
uniform(
"rectangle",
areaLocalBounds.left,
areaLocalBounds.top,
areaLocalBounds.right,
areaLocalBounds.bottom,
)

uniform("color", tint.red, tint.green, tint.blue, 1f)
uniform("colorShift", tint.alpha)
uniform("noiseFactor", noiseFactor)
when (val shape = area.shape) {
is CornerBasedShape -> {
uniform(
"radius",
shape.topStart.toPx(area.bounds.size, density),
shape.topEnd.toPx(area.bounds.size, density),
shape.bottomStart.toPx(area.bounds.size, density),
shape.bottomEnd.toPx(area.bounds.size, density),
)
}

child("noise", NOISE_SHADER)
else -> {
uniform("radius", 0f, 0f, 0f, 0f)
}
}

ImageFilter.makeRuntimeShader(
runtimeShaderBuilder = compositeShaderBuilder,
shaderNames = arrayOf("content", "blur"),
inputs = arrayOf(null, blurFilter),
)
uniform("color", tint.red, tint.green, tint.blue, 1f)
uniform("colorShift", tint.alpha)
uniform("noiseFactor", noiseFactor)

child("noise", NOISE_SHADER)
}

ImageFilter.makeRuntimeShader(
runtimeShaderBuilder = compositeShaderBuilder,
shaderNames = arrayOf("content", "blur"),
inputs = arrayOf(null, blurFilter),
)
}

return ImageFilter.makeMerge(
buildList {
// We need null as the first item, which tells Skia to draw the content without any filter.
Expand Down

0 comments on commit abdcbc6

Please sign in to comment.