Skip transparent shadows in iced_tiny_skia
This commit is contained in:
parent
370b2f6df7
commit
4d502012b3
1 changed files with 103 additions and 96 deletions
|
|
@ -186,104 +186,91 @@ impl Backend {
|
||||||
let path = rounded_rectangle(*bounds, fill_border_radius);
|
let path = rounded_rectangle(*bounds, fill_border_radius);
|
||||||
|
|
||||||
if let Some(shadow) = shadow {
|
if let Some(shadow) = shadow {
|
||||||
fn smoothstep(a: f32, b: f32, x: f32) -> f32 {
|
if shadow.color.a > 0.0 {
|
||||||
let x = ((x - a) / (b - a)).clamp(0.0, 1.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;
|
||||||
|
|
||||||
x * x * (3.0 - 2.0 * x)
|
let radii = fill_border_radius
|
||||||
}
|
.into_iter()
|
||||||
|
.map(|radius| radius * scale_factor)
|
||||||
fn rounded_box_sdf(
|
.collect::<Vec<_>>();
|
||||||
to_center: Vector,
|
let (x, y, width, height) = (
|
||||||
size: Size,
|
shadow_bounds.x as u32,
|
||||||
radii: &[f32],
|
shadow_bounds.y as u32,
|
||||||
) -> f32 {
|
shadow_bounds.width as u32,
|
||||||
let radius =
|
shadow_bounds.height as u32,
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.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,
|
|
||||||
)
|
|
||||||
}) {
|
|
||||||
pixels.draw_pixmap(
|
|
||||||
x as i32,
|
|
||||||
y as i32,
|
|
||||||
pixmap.as_ref(),
|
|
||||||
&tiny_skia::PixmapPaint::default(),
|
|
||||||
tiny_skia::Transform::default(),
|
|
||||||
None,
|
|
||||||
);
|
);
|
||||||
|
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()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.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,
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
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 {
|
impl iced_graphics::Backend for Backend {
|
||||||
type Primitive = primitive::Custom;
|
type Primitive = primitive::Custom;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue