From af5997a21507a51dc01bc5b05366450a91c38893 Mon Sep 17 00:00:00 2001 From: T-256 Date: Thu, 2 Jan 2025 03:53:57 +0330 Subject: [PATCH 1/5] fix shadow rendering for tiny-skia backend --- tiny_skia/src/window/compositor.rs | 34 ++++++++++++++++-------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 6c144be0d2..931adf46ac 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -1,6 +1,5 @@ use crate::core::{Color, Rectangle, Size}; use crate::graphics::compositor::{self, Information}; -use crate::graphics::damage; use crate::graphics::error::{self, Error}; use crate::graphics::{self, Viewport}; use crate::{Layer, Renderer, Settings}; @@ -154,7 +153,7 @@ pub fn present>( .buffer_mut() .map_err(|_| compositor::SurfaceError::Lost)?; - let last_layers = { + let _last_layers = { let age = buffer.age(); surface.max_age = surface.max_age.max(age); @@ -167,18 +166,21 @@ pub fn present>( } }; - let damage = last_layers - .and_then(|last_layers| { - (surface.background_color == background_color).then(|| { - damage::diff( - last_layers, - renderer.layers(), - |layer| vec![layer.bounds], - Layer::damage, - ) - }) - }) - .unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]); + // TODO + // let damage = last_layers + // .and_then(|last_layers| { + // (surface.background_color == background_color).then(|| { + // damage::diff( + // last_layers, + // renderer.layers(), + // |layer| vec![layer.bounds], + // Layer::damage, + // ) + // }) + // }) + // .unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]); + + let damage = vec![Rectangle::with_size(viewport.logical_size())]; if damage.is_empty() { return Ok(()); @@ -187,8 +189,8 @@ pub fn present>( surface.layer_stack.push_front(renderer.layers().to_vec()); surface.background_color = background_color; - let damage = - damage::group(damage, Rectangle::with_size(viewport.logical_size())); + // let damage = + // damage::group(damage, Rectangle::with_size(viewport.logical_size())); let mut pixels = tiny_skia::PixmapMut::from_bytes( bytemuck::cast_slice_mut(&mut buffer), From 93b12a55baee241fe75a0b03b20a7e9f3ffc6052 Mon Sep 17 00:00:00 2001 From: T-256 Date: Thu, 2 Jan 2025 14:40:58 +0330 Subject: [PATCH 2/5] Computing damages from bounds with shadow --- core/src/renderer.rs | 18 ++++++++++++++++ tiny_skia/src/engine.rs | 7 +----- tiny_skia/src/layer.rs | 2 +- tiny_skia/src/window/compositor.rs | 34 ++++++++++++++---------------- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/core/src/renderer.rs b/core/src/renderer.rs index 68e070e84d..a78dd70201 100644 --- a/core/src/renderer.rs +++ b/core/src/renderer.rs @@ -87,6 +87,24 @@ impl Default for Quad { } } +impl Quad { + /// Calculates bounds area with [`Shadow`] expandation. + pub fn bounds_with_shadow(&self) -> Rectangle { + let shadow = self.shadow; + + if shadow.color.a > 0.0 { + Rectangle { + x: self.bounds.x + shadow.offset.x - shadow.blur_radius, + y: self.bounds.y + shadow.offset.y - shadow.blur_radius, + width: self.bounds.width + shadow.blur_radius * 2.0, + height: self.bounds.height + shadow.blur_radius * 2.0, + } + } else { + self.bounds + } + } +} + /// The styling attributes of a [`Renderer`]. #[derive(Debug, Clone, Copy, PartialEq)] pub struct Style { diff --git a/tiny_skia/src/engine.rs b/tiny_skia/src/engine.rs index 196c36cf16..7a2e2a2642 100644 --- a/tiny_skia/src/engine.rs +++ b/tiny_skia/src/engine.rs @@ -76,12 +76,7 @@ impl Engine { let shadow = quad.shadow; if shadow.color.a > 0.0 { - let shadow_bounds = Rectangle { - x: quad.bounds.x + shadow.offset.x - shadow.blur_radius, - y: quad.bounds.y + shadow.offset.y - shadow.blur_radius, - width: quad.bounds.width + shadow.blur_radius * 2.0, - height: quad.bounds.height + shadow.blur_radius * 2.0, - } * transformation; + let shadow_bounds = quad.bounds_with_shadow() * transformation; let radii = fill_border_radius .into_iter() diff --git a/tiny_skia/src/layer.rs b/tiny_skia/src/layer.rs index bdfd4d388a..3d5bc599a5 100644 --- a/tiny_skia/src/layer.rs +++ b/tiny_skia/src/layer.rs @@ -183,7 +183,7 @@ impl Layer { &previous.quads, ¤t.quads, |(quad, _)| { - quad.bounds + quad.bounds_with_shadow() .expand(1.0) .intersection(¤t.bounds) .into_iter() diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 931adf46ac..6c144be0d2 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -1,5 +1,6 @@ use crate::core::{Color, Rectangle, Size}; use crate::graphics::compositor::{self, Information}; +use crate::graphics::damage; use crate::graphics::error::{self, Error}; use crate::graphics::{self, Viewport}; use crate::{Layer, Renderer, Settings}; @@ -153,7 +154,7 @@ pub fn present>( .buffer_mut() .map_err(|_| compositor::SurfaceError::Lost)?; - let _last_layers = { + let last_layers = { let age = buffer.age(); surface.max_age = surface.max_age.max(age); @@ -166,21 +167,18 @@ pub fn present>( } }; - // TODO - // let damage = last_layers - // .and_then(|last_layers| { - // (surface.background_color == background_color).then(|| { - // damage::diff( - // last_layers, - // renderer.layers(), - // |layer| vec![layer.bounds], - // Layer::damage, - // ) - // }) - // }) - // .unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]); - - let damage = vec![Rectangle::with_size(viewport.logical_size())]; + let damage = last_layers + .and_then(|last_layers| { + (surface.background_color == background_color).then(|| { + damage::diff( + last_layers, + renderer.layers(), + |layer| vec![layer.bounds], + Layer::damage, + ) + }) + }) + .unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]); if damage.is_empty() { return Ok(()); @@ -189,8 +187,8 @@ pub fn present>( surface.layer_stack.push_front(renderer.layers().to_vec()); surface.background_color = background_color; - // let damage = - // damage::group(damage, Rectangle::with_size(viewport.logical_size())); + let damage = + damage::group(damage, Rectangle::with_size(viewport.logical_size())); let mut pixels = tiny_skia::PixmapMut::from_bytes( bytemuck::cast_slice_mut(&mut buffer), From e77100a5de4447823ea74541946df2ddc6d9f0e6 Mon Sep 17 00:00:00 2001 From: B0ney <40839054+B0ney@users.noreply.github.com> Date: Tue, 7 Jan 2025 13:35:56 +0000 Subject: [PATCH 3/5] tiny_skia: apply `clip_mask` to shadows (#1) --- tiny_skia/src/engine.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tiny_skia/src/engine.rs b/tiny_skia/src/engine.rs index 7a2e2a2642..e7c721bf33 100644 --- a/tiny_skia/src/engine.rs +++ b/tiny_skia/src/engine.rs @@ -143,7 +143,7 @@ impl Engine { pixmap.as_ref(), &tiny_skia::PixmapPaint::default(), tiny_skia::Transform::default(), - None, + clip_mask, ); } } From 8e130653317a4910a6fd80258f5e02680b5e26e5 Mon Sep 17 00:00:00 2001 From: B0ney <40839054+B0ney@users.noreply.github.com> Date: Tue, 7 Jan 2025 16:11:45 +0000 Subject: [PATCH 4/5] tiny_skia: fix incorrect shadow clipping (#2) --- tiny_skia/src/engine.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tiny_skia/src/engine.rs b/tiny_skia/src/engine.rs index e7c721bf33..53382e489f 100644 --- a/tiny_skia/src/engine.rs +++ b/tiny_skia/src/engine.rs @@ -44,16 +44,17 @@ impl Engine { quad.bounds.height.is_normal(), "Quad with non-normal height!" ); + let physical_bounds_with_shadow = quad.bounds_with_shadow() * transformation; - let physical_bounds = quad.bounds * transformation; - - if !clip_bounds.intersects(&physical_bounds) { + if !clip_bounds.intersects(&physical_bounds_with_shadow) { return; } - let clip_mask = (!physical_bounds.is_within(&clip_bounds)) + let clip_mask = (!physical_bounds_with_shadow.is_within(&clip_bounds)) .then_some(clip_mask as &_); + let physical_bounds = quad.bounds * transformation; + let transform = into_transform(transformation); // Make sure the border radius is not larger than the bounds From 72546bb4a854e4960cdcdc664e3b6d17626a8204 Mon Sep 17 00:00:00 2001 From: T-256 Date: Tue, 7 Jan 2025 19:43:59 +0330 Subject: [PATCH 5/5] cargo fmt --- tiny_skia/src/engine.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tiny_skia/src/engine.rs b/tiny_skia/src/engine.rs index 53382e489f..843e3fe8c4 100644 --- a/tiny_skia/src/engine.rs +++ b/tiny_skia/src/engine.rs @@ -44,7 +44,8 @@ impl Engine { quad.bounds.height.is_normal(), "Quad with non-normal height!" ); - let physical_bounds_with_shadow = quad.bounds_with_shadow() * transformation; + let physical_bounds_with_shadow = + quad.bounds_with_shadow() * transformation; if !clip_bounds.intersects(&physical_bounds_with_shadow) { return;