diff options
author | 2024-01-20 12:39:41 +0100 | |
---|---|---|
committer | 2024-01-20 12:39:52 +0100 | |
commit | 4d502012b3e3ed9d9ef80f21078d53d182cdaa1b (patch) | |
tree | dcc2b276e0d1c840ab941c624d59bb09cf890861 /tiny_skia | |
parent | 370b2f6df799c948188d3949e34112258b2a8498 (diff) | |
download | iced-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.rs | 195 |
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; } |