From 79a09ee6140f04126417ee7a198b228ccd8be9c9 Mon Sep 17 00:00:00 2001 From: Jonathan Johnson Date: Tue, 12 Dec 2023 19:27:41 -0800 Subject: [PATCH] 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. --- examples/container-shadow.rs | 4 +- src/widgets/container.rs | 102 ++++++++++++++++++++--------------- 2 files changed, 63 insertions(+), 43 deletions(-) diff --git a/examples/container-shadow.rs b/examples/container-shadow.rs index 81a6685..76b2b6a 100644 --- a/examples/container-shadow.rs +++ b/examples/container-shadow.rs @@ -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() } diff --git a/src/widgets/container.rs b/src/widgets/container.rs index 07d8f38..61cd624 100644 --- a/src/widgets/container.rs +++ b/src/widgets/container.rs @@ -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),