Shadow blur now can cause expansion

Rather than clip or cause shadows to be weirdly shaped, the shape is
adjusted if the blur radius is too large for the given geometry. This
ensures the shadows always draw correctly, but it also forces shadows to
render their full blur + spread gradients.
This commit is contained in:
Jonathan Johnson 2023-12-12 19:27:41 -08:00
parent a7efe9a3d5
commit 79a09ee614
No known key found for this signature in database
GPG key ID: A66D6A34D6620579
2 changed files with 63 additions and 43 deletions

View file

@ -63,6 +63,7 @@ fn main() -> gooey::Result {
.and(
"Preview"
.h3()
.align_left()
.and(
Space::clear()
.size(Size::squared(Lp::inches(2)))
@ -73,7 +74,8 @@ fn main() -> gooey::Result {
.into_rows(),
)
.into_columns()
.expand()
.contain()
.centered()
.pad()
.run()
}

View file

@ -266,7 +266,21 @@ impl Widget for Container {
.into_signed(),
);
child_size + padding_amount + child_shadow_offset_amount + shadow_spread * 2
let corner_radii = context.get(&CornerRadius).into_upx(context.gfx.scale());
let max_corner = corner_radii
.top_left
.max(corner_radii.top_right)
.max(corner_radii.bottom_left)
.max(corner_radii.bottom_right);
let max_blur = (child_size
.width
.min(child_size.height)
.saturating_sub(shadow.spread.into_unsigned())
/ 2)
.saturating_sub(max_corner);
let blur_overage = shadow.blur_radius.into_unsigned().saturating_sub(max_blur);
child_size + padding_amount + child_shadow_offset_amount + shadow_spread * 2 + blur_overage
}
fn root_behavior(
@ -315,14 +329,19 @@ fn render_shadow(
let shadow_color =
shadow_color.with_alpha_f32(shadow_color.alpha_f32() * background.alpha_f32());
let gradient_size = (shadow.spread + shadow.blur_radius)
.min(child_area.size.width)
.min(child_area.size.height);
let max_corner = corner_radii
.top_left
.max(corner_radii.top_right)
.max(corner_radii.bottom_left)
.max(corner_radii.bottom_right);
let max_blur =
(child_area.size.width.min(child_area.size.height) - shadow.spread) / 2 - max_corner;
let blur = shadow.blur_radius.min(max_blur);
let gradient_size = shadow.spread + blur;
if gradient_size > 0 {
let mut solid_area = Rect::new(
Point::squared(gradient_size),
child_area.size - shadow.blur_radius * 2,
);
let mut solid_area = Rect::new(Point::squared(gradient_size), child_area.size - blur * 2);
solid_area.origin += shadow.offset.max(Point::ZERO);
let transparent = shadow_color.with_alpha(0);
@ -370,18 +389,6 @@ fn render_shadow(
.filled(),
);
}
// Top Right
shadow_arc(
Point::new(solid_right_at_top, solid_top_at_right),
corner_radii.top_right,
gradient_size,
shadow_color,
transparent,
Angle::degrees(270),
context,
);
// Right
context.gfx.draw_shape(
&PathBuilder::new((Point::new(solid_right, solid_top_at_right), shadow_color))
@ -412,17 +419,6 @@ fn render_shadow(
.filled(),
);
// Bottom Right
shadow_arc(
Point::new(solid_right_at_bottom, solid_bottom_at_right),
corner_radii.bottom_right,
gradient_size,
shadow_color,
transparent,
Angle::degrees(0),
context,
);
// Bottom
context.gfx.draw_shape(
&PathBuilder::new((
@ -450,17 +446,6 @@ fn render_shadow(
.filled(),
);
// Bottom Left
shadow_arc(
Point::new(solid_left_at_bottom, solid_bottom_at_left),
corner_radii.bottom_left,
gradient_size,
shadow_color,
transparent,
Angle::degrees(90),
context,
);
// Left
context.gfx.draw_shape(
&PathBuilder::new((
@ -491,6 +476,39 @@ fn render_shadow(
.filled(),
);
// Top Right
shadow_arc(
Point::new(solid_right_at_top, solid_top_at_right),
corner_radii.top_right,
gradient_size,
shadow_color,
transparent,
Angle::degrees(270),
context,
);
// Bottom Right
shadow_arc(
Point::new(solid_right_at_bottom, solid_bottom_at_right),
corner_radii.bottom_right,
gradient_size,
shadow_color,
transparent,
Angle::degrees(0),
context,
);
// Bottom Left
shadow_arc(
Point::new(solid_left_at_bottom, solid_bottom_at_left),
corner_radii.bottom_left,
gradient_size,
shadow_color,
transparent,
Angle::degrees(90),
context,
);
// Top Left
shadow_arc(
Point::new(solid_left_at_top, solid_top_at_left),