From b7b457a575cdd103915994f640c50262ce30a7c5 Mon Sep 17 00:00:00 2001
From: Héctor Ramón Jiménez <hector@hecrj.dev>
Date: Sat, 20 Jan 2024 12:11:18 +0100
Subject: Make `shadow` optional in `renderer::Quad`

---
 core/src/renderer.rs             | 16 ++++++++++++++--
 core/src/shadow.rs               |  4 ++--
 examples/custom_quad/src/main.rs |  2 +-
 graphics/src/damage.rs           | 21 ++++++++++-----------
 graphics/src/primitive.rs        | 12 +++++-------
 graphics/src/renderer.rs         |  4 +---
 tiny_skia/src/backend.rs         | 24 +++++++++++-------------
 wgpu/src/layer.rs                | 20 +++++++++++++-------
 8 files changed, 57 insertions(+), 46 deletions(-)

diff --git a/core/src/renderer.rs b/core/src/renderer.rs
index 481048b0..1ca62559 100644
--- a/core/src/renderer.rs
+++ b/core/src/renderer.rs
@@ -5,7 +5,7 @@ mod null;
 #[cfg(debug_assertions)]
 pub use null::Null;
 
-use crate::{Background, BorderRadius, Color, Rectangle, Shadow, Vector};
+use crate::{Background, BorderRadius, Color, Rectangle, Shadow, Size, Vector};
 
 /// A component that can be used by widgets to draw themselves on a screen.
 pub trait Renderer: Sized {
@@ -47,7 +47,19 @@ pub struct Quad {
     pub border_color: Color,
 
     /// The shadow of the [`Quad`].
-    pub shadow: Shadow,
+    pub shadow: Option<Shadow>,
+}
+
+impl Default for Quad {
+    fn default() -> Self {
+        Self {
+            bounds: Rectangle::with_size(Size::ZERO),
+            border_radius: 0.0.into(),
+            border_width: 0.0,
+            border_color: Color::TRANSPARENT,
+            shadow: None,
+        }
+    }
 }
 
 /// The styling attributes of a [`Renderer`].
diff --git a/core/src/shadow.rs b/core/src/shadow.rs
index 238ea36a..de8ce1c3 100644
--- a/core/src/shadow.rs
+++ b/core/src/shadow.rs
@@ -2,7 +2,7 @@
 use crate::{Color, Vector};
 
 /// A shadow
-#[derive(Debug, Clone, Copy, PartialEq, Default)]
+#[derive(Debug, Clone, Copy, PartialEq)]
 pub struct Shadow {
     /// The color of the shadow
     pub color: Color,
@@ -10,6 +10,6 @@ pub struct Shadow {
     /// The offset of the shadow
     pub offset: Vector,
 
-    /// The blur_radius of the shadow
+    /// The blur radius of the shadow
     pub blur_radius: f32,
 }
diff --git a/examples/custom_quad/src/main.rs b/examples/custom_quad/src/main.rs
index 01f4aa10..e3f110bb 100644
--- a/examples/custom_quad/src/main.rs
+++ b/examples/custom_quad/src/main.rs
@@ -65,7 +65,7 @@ mod quad {
                     border_radius: self.radius.into(),
                     border_width: self.border_width,
                     border_color: Color::from_rgb(1.0, 0.0, 0.0),
-                    shadow: self.shadow,
+                    shadow: Some(self.shadow),
                 },
                 Color::BLACK,
             );
diff --git a/graphics/src/damage.rs b/graphics/src/damage.rs
index 2aec9b25..cced0c97 100644
--- a/graphics/src/damage.rs
+++ b/graphics/src/damage.rs
@@ -80,26 +80,25 @@ impl<T: Damage> Damage for Primitive<T> {
             }
             Self::Quad {
                 bounds,
-                shadow_offset,
-                shadow_blur_radius,
+                shadow: Some(shadow),
                 ..
             } => {
                 let bounds_with_shadow = Rectangle {
-                    x: bounds.x + shadow_offset.x.min(0.0) - shadow_blur_radius,
-                    y: bounds.y + shadow_offset.y.min(0.0) - shadow_blur_radius,
+                    x: bounds.x + shadow.offset.x.min(0.0) - shadow.blur_radius,
+                    y: bounds.y + shadow.offset.y.min(0.0) - shadow.blur_radius,
                     width: bounds.width
-                        + shadow_offset.x.abs()
-                        + shadow_blur_radius * 2.0,
+                        + shadow.offset.x.abs()
+                        + shadow.blur_radius * 2.0,
                     height: bounds.height
-                        + shadow_offset.y.abs()
-                        + shadow_blur_radius * 2.0,
+                        + shadow.offset.y.abs()
+                        + shadow.blur_radius * 2.0,
                 };
 
                 bounds_with_shadow.expand(1.0)
             }
-            Self::Image { bounds, .. } | Self::Svg { bounds, .. } => {
-                bounds.expand(1.0)
-            }
+            Self::Quad { bounds, .. }
+            | Self::Image { bounds, .. }
+            | Self::Svg { bounds, .. } => bounds.expand(1.0),
             Self::Clip { bounds, .. } => bounds.expand(1.0),
             Self::Group { primitives } => primitives
                 .iter()
diff --git a/graphics/src/primitive.rs b/graphics/src/primitive.rs
index 795d9609..a428c31a 100644
--- a/graphics/src/primitive.rs
+++ b/graphics/src/primitive.rs
@@ -3,7 +3,9 @@ use crate::core::alignment;
 use crate::core::image;
 use crate::core::svg;
 use crate::core::text;
-use crate::core::{Background, Color, Font, Pixels, Point, Rectangle, Vector};
+use crate::core::{
+    Background, Color, Font, Pixels, Point, Rectangle, Shadow, Vector,
+};
 use crate::text::editor;
 use crate::text::paragraph;
 
@@ -71,12 +73,8 @@ pub enum Primitive<T> {
         border_width: f32,
         /// The border color of the quad
         border_color: Color,
-        /// The shadow color of the quad
-        shadow_color: Color,
-        /// The shadow offset of the quad
-        shadow_offset: Vector,
-        /// The shadow blur radius of the quad
-        shadow_blur_radius: f32,
+        /// The [`Shadow`] of the quad
+        shadow: Option<Shadow>,
     },
     /// An image primitive
     Image {
diff --git a/graphics/src/renderer.rs b/graphics/src/renderer.rs
index bd640097..6f312331 100644
--- a/graphics/src/renderer.rs
+++ b/graphics/src/renderer.rs
@@ -127,9 +127,7 @@ impl<B: Backend, T> iced_core::Renderer for Renderer<B, T> {
             border_radius: quad.border_radius.into(),
             border_width: quad.border_width,
             border_color: quad.border_color,
-            shadow_color: quad.shadow.color,
-            shadow_offset: quad.shadow.offset,
-            shadow_blur_radius: quad.shadow.blur_radius,
+            shadow: quad.shadow,
         });
     }
 
diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs
index b62f20d5..ae1abc84 100644
--- a/tiny_skia/src/backend.rs
+++ b/tiny_skia/src/backend.rs
@@ -155,9 +155,7 @@ impl Backend {
                 border_radius,
                 border_width,
                 border_color,
-                shadow_color,
-                shadow_offset,
-                shadow_blur_radius,
+                shadow,
             } => {
                 let physical_bounds = (*bounds + translation) * scale_factor;
 
@@ -187,7 +185,7 @@ impl Backend {
                 }
                 let path = rounded_rectangle(*bounds, fill_border_radius);
 
-                if shadow_color.a > 0.0 {
+                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);
 
@@ -216,10 +214,10 @@ impl Backend {
                     }
 
                     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,
+                        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;
 
@@ -245,10 +243,10 @@ impl Backend {
                                 let shadow_distance = rounded_box_sdf(
                                     Vector::new(
                                         x - physical_bounds.position().x
-                                            - (shadow_offset.x * scale_factor)
+                                            - (shadow.offset.x * scale_factor)
                                             - half_width,
                                         y - physical_bounds.position().y
-                                            - (shadow_offset.y * scale_factor)
+                                            - (shadow.offset.y * scale_factor)
                                             - half_height,
                                     ),
                                     size,
@@ -256,12 +254,12 @@ impl Backend {
                                 );
                                 let shadow_alpha = 1.0
                                     - smoothstep(
-                                        -shadow_blur_radius * scale_factor,
-                                        *shadow_blur_radius * scale_factor,
+                                        -shadow.blur_radius * scale_factor,
+                                        shadow.blur_radius * scale_factor,
                                         shadow_distance,
                                     );
 
-                                let mut color = into_color(*shadow_color);
+                                let mut color = into_color(shadow.color);
                                 color.apply_opacity(shadow_alpha);
 
                                 color.to_color_u8().premultiply()
diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs
index 7b54601b..cb91878d 100644
--- a/wgpu/src/layer.rs
+++ b/wgpu/src/layer.rs
@@ -12,7 +12,9 @@ pub use text::Text;
 
 use crate::core;
 use crate::core::alignment;
-use crate::core::{Color, Font, Pixels, Point, Rectangle, Size, Vector};
+use crate::core::{
+    Color, Font, Pixels, Point, Rectangle, Shadow, Size, Vector,
+};
 use crate::graphics;
 use crate::graphics::color;
 use crate::graphics::Viewport;
@@ -198,12 +200,16 @@ impl<'a> Layer<'a> {
                 border_radius,
                 border_width,
                 border_color,
-                shadow_color,
-                shadow_offset,
-                shadow_blur_radius,
+                shadow,
             } => {
                 let layer = &mut layers[current_layer];
 
+                let shadow = shadow.unwrap_or_else(|| Shadow {
+                    color: Color::TRANSPARENT,
+                    offset: Vector::ZERO,
+                    blur_radius: 0.0,
+                });
+
                 let quad = Quad {
                     position: [
                         bounds.x + translation.x,
@@ -213,9 +219,9 @@ impl<'a> Layer<'a> {
                     border_color: color::pack(*border_color),
                     border_radius: *border_radius,
                     border_width: *border_width,
-                    shadow_color: shadow_color.into_linear(),
-                    shadow_offset: (*shadow_offset).into(),
-                    shadow_blur_radius: *shadow_blur_radius,
+                    shadow_color: shadow.color.into_linear(),
+                    shadow_offset: shadow.offset.into(),
+                    shadow_blur_radius: shadow.blur_radius,
                 };
 
                 layer.quads.add(quad, background);
-- 
cgit