summaryrefslogtreecommitdiffstats
path: root/tiny_skia
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-01-20 12:39:41 +0100
committerLibravatar Héctor Ramón Jiménez <hector@hecrj.dev>2024-01-20 12:39:52 +0100
commit4d502012b3e3ed9d9ef80f21078d53d182cdaa1b (patch)
treedcc2b276e0d1c840ab941c624d59bb09cf890861 /tiny_skia
parent370b2f6df799c948188d3949e34112258b2a8498 (diff)
downloadiced-4d502012b3e3ed9d9ef80f21078d53d182cdaa1b.tar.gz
iced-4d502012b3e3ed9d9ef80f21078d53d182cdaa1b.tar.bz2
iced-4d502012b3e3ed9d9ef80f21078d53d182cdaa1b.zip
Skip transparent shadows in `iced_tiny_skia`
Diffstat (limited to 'tiny_skia')
-rw-r--r--tiny_skia/src/backend.rs195
1 files changed, 101 insertions, 94 deletions
diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs
index 5321d8c6..bad6221f 100644
--- a/tiny_skia/src/backend.rs
+++ b/tiny_skia/src/backend.rs
@@ -186,104 +186,91 @@ impl Backend {
let path = rounded_rectangle(*bounds, fill_border_radius);
if let Some(shadow) = shadow {
- fn smoothstep(a: f32, b: f32, x: f32) -> f32 {
- let x = ((x - a) / (b - a)).clamp(0.0, 1.0);
-
- x * x * (3.0 - 2.0 * x)
- }
-
- fn rounded_box_sdf(
- to_center: Vector,
- size: Size,
- radii: &[f32],
- ) -> f32 {
- let radius =
- match (to_center.x > 0.0, to_center.y > 0.0) {
- (true, true) => radii[2],
- (true, false) => radii[1],
- (false, true) => radii[3],
- (false, false) => radii[0],
- };
-
- let x = (to_center.x.abs() - size.width() + radius)
- .max(0.0);
- let y = (to_center.y.abs() - size.height() + radius)
- .max(0.0);
-
- (x.powf(2.0) + y.powf(2.0)).sqrt() - radius
- }
+ if shadow.color.a > 0.0 {
+ let shadow_bounds = (Rectangle {
+ x: bounds.x + shadow.offset.x - shadow.blur_radius,
+ y: bounds.y + shadow.offset.y - shadow.blur_radius,
+ width: bounds.width + shadow.blur_radius * 2.0,
+ height: bounds.height + shadow.blur_radius * 2.0,
+ } + translation)
+ * scale_factor;
+
+ let radii = fill_border_radius
+ .into_iter()
+ .map(|radius| radius * scale_factor)
+ .collect::<Vec<_>>();
+ let (x, y, width, height) = (
+ shadow_bounds.x as u32,
+ shadow_bounds.y as u32,
+ shadow_bounds.width as u32,
+ shadow_bounds.height as u32,
+ );
+ let half_width = physical_bounds.width / 2.0;
+ let half_height = physical_bounds.height / 2.0;
- let shadow_bounds = (Rectangle {
- x: bounds.x + shadow.offset.x - shadow.blur_radius,
- y: bounds.y + shadow.offset.y - shadow.blur_radius,
- width: bounds.width + shadow.blur_radius * 2.0,
- height: bounds.height + shadow.blur_radius * 2.0,
- } + translation)
- * scale_factor;
-
- let radii = fill_border_radius
- .into_iter()
- .map(|radius| radius * scale_factor)
- .collect::<Vec<_>>();
- let (x, y, width, height) = (
- shadow_bounds.x as u32,
- shadow_bounds.y as u32,
- shadow_bounds.width as u32,
- shadow_bounds.height as u32,
- );
- let half_width = physical_bounds.width / 2.0;
- let half_height = physical_bounds.height / 2.0;
-
- let colors = (y..y + height)
- .flat_map(|y| {
- (x..x + width).map(move |x| (x as f32, y as f32))
- })
- .filter_map(|(x, y)| {
- Size::from_wh(half_width, half_height).map(|size| {
- let shadow_distance = rounded_box_sdf(
- Vector::new(
- x - physical_bounds.position().x
- - (shadow.offset.x * scale_factor)
- - half_width,
- y - physical_bounds.position().y
- - (shadow.offset.y * scale_factor)
- - half_height,
- ),
- size,
- &radii,
- );
- let shadow_alpha = 1.0
- - smoothstep(
- -shadow.blur_radius * scale_factor,
- shadow.blur_radius * scale_factor,
- shadow_distance,
- );
-
- let mut color = into_color(shadow.color);
- color.apply_opacity(shadow_alpha);
-
- color.to_color_u8().premultiply()
+ let colors = (y..y + height)
+ .flat_map(|y| {
+ (x..x + width)
+ .map(move |x| (x as f32, y as f32))
})
- })
- .collect();
+ .filter_map(|(x, y)| {
+ Size::from_wh(half_width, half_height).map(
+ |size| {
+ let shadow_distance = rounded_box_sdf(
+ Vector::new(
+ x - physical_bounds
+ .position()
+ .x
+ - (shadow.offset.x
+ * scale_factor)
+ - half_width,
+ y - physical_bounds
+ .position()
+ .y
+ - (shadow.offset.y
+ * scale_factor)
+ - half_height,
+ ),
+ size,
+ &radii,
+ );
+ let shadow_alpha = 1.0
+ - smoothstep(
+ -shadow.blur_radius
+ * scale_factor,
+ shadow.blur_radius
+ * scale_factor,
+ shadow_distance,
+ );
+
+ let mut color =
+ into_color(shadow.color);
+ color.apply_opacity(shadow_alpha);
+
+ color.to_color_u8().premultiply()
+ },
+ )
+ })
+ .collect();
- if let Some(pixmap) = tiny_skia::IntSize::from_wh(
- width, height,
- )
- .and_then(|size| {
- tiny_skia::Pixmap::from_vec(
- bytemuck::cast_vec(colors),
- size,
+ if let Some(pixmap) = tiny_skia::IntSize::from_wh(
+ width, height,
)
- }) {
- pixels.draw_pixmap(
- x as i32,
- y as i32,
- pixmap.as_ref(),
- &tiny_skia::PixmapPaint::default(),
- tiny_skia::Transform::default(),
- None,
- );
+ .and_then(|size| {
+ tiny_skia::Pixmap::from_vec(
+ bytemuck::cast_vec(colors),
+ size,
+ )
+ }) {
+ pixels.draw_pixmap(
+ x as i32,
+ y as i32,
+ pixmap.as_ref(),
+ &tiny_skia::PixmapPaint::default(),
+ tiny_skia::Transform::default(),
+ None,
+ );
+ }
}
}
@@ -969,6 +956,26 @@ fn adjust_clip_mask(clip_mask: &mut tiny_skia::Mask, bounds: Rectangle) {
);
}
+fn smoothstep(a: f32, b: f32, x: f32) -> f32 {
+ let x = ((x - a) / (b - a)).clamp(0.0, 1.0);
+
+ x * x * (3.0 - 2.0 * x)
+}
+
+fn rounded_box_sdf(to_center: Vector, size: Size, radii: &[f32]) -> f32 {
+ let radius = match (to_center.x > 0.0, to_center.y > 0.0) {
+ (true, true) => radii[2],
+ (true, false) => radii[1],
+ (false, true) => radii[3],
+ (false, false) => radii[0],
+ };
+
+ let x = (to_center.x.abs() - size.width() + radius).max(0.0);
+ let y = (to_center.y.abs() - size.height() + radius).max(0.0);
+
+ (x.powf(2.0) + y.powf(2.0)).sqrt() - radius
+}
+
impl iced_graphics::Backend for Backend {
type Primitive = primitive::Custom;
}