[librsvg: 3/20] filters: resolve() now returns the resolved Primitive as well




commit f2d1975f16631fc669e2794df84c90504c9b74c7
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Mar 16 11:51:51 2021 -0600

    filters: resolve() now returns the resolved Primitive as well
    
    And that resolved Primitive gets passed to render().  This lets us not
    have an extra copy of the Primitive in the resolved parameters for
    each primitive.
    
    This will also let us normalize primitives early, in the following commits.

 src/filters/blend.rs              | 25 +++++++++++----------
 src/filters/color_matrix.rs       | 23 ++++++++++----------
 src/filters/component_transfer.rs | 23 ++++++++++----------
 src/filters/composite.rs          | 33 ++++++++++++++--------------
 src/filters/convolve_matrix.rs    | 40 ++++++++++++++++++----------------
 src/filters/displacement_map.rs   | 29 ++++++++++++------------
 src/filters/flood.rs              | 26 ++++++++++++----------
 src/filters/gaussian_blur.rs      | 23 ++++++++++----------
 src/filters/image.rs              | 25 +++++++++++++++------
 src/filters/lighting.rs           | 46 +++++++++++++++++++--------------------
 src/filters/merge.rs              | 20 +++++++++--------
 src/filters/mod.rs                | 41 ++++++++++++++++++----------------
 src/filters/morphology.rs         | 26 +++++++++++++++-------
 src/filters/offset.rs             | 25 +++++++++++++++------
 src/filters/tile.rs               | 20 ++++++++++++-----
 src/filters/turbulence.rs         | 28 +++++++++++++-----------
 16 files changed, 255 insertions(+), 198 deletions(-)
---
diff --git a/src/filters/blend.rs b/src/filters/blend.rs
index 827c636b..a6ad4d6b 100755
--- a/src/filters/blend.rs
+++ b/src/filters/blend.rs
@@ -46,7 +46,6 @@ pub struct FeBlend {
 
 /// Resolved `feBlend` primitive for rendering.
 pub struct Blend {
-    base: Primitive,
     in1: Input,
     in2: Input,
     mode: Mode,
@@ -85,6 +84,7 @@ impl SetAttributes for FeBlend {
 impl Blend {
     pub fn render(
         &self,
+        primitive: &Primitive,
         ctx: &FilterContext,
         acquired_nodes: &mut AcquiredNodes<'_>,
         draw_ctx: &mut DrawingCtx,
@@ -101,8 +101,7 @@ impl Blend {
             &self.in2,
             self.color_interpolation_filters,
         )?;
-        let bounds = self
-            .base
+        let bounds = primitive
             .get_bounds(ctx)?
             .add_input(&input_1)
             .add_input(&input_2)
@@ -115,24 +114,26 @@ impl Blend {
         )?;
 
         Ok(FilterResult {
-            name: self.base.result.clone(),
+            name: primitive.result.clone(),
             output: FilterOutput { surface, bounds },
         })
     }
 }
 
 impl FilterEffect for FeBlend {
-    fn resolve(&self, node: &Node) -> Result<PrimitiveParams, FilterError> {
+    fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
         let cascaded = CascadedValues::new_from_node(node);
         let values = cascaded.get();
 
-        Ok(PrimitiveParams::Blend(Blend {
-            base: self.base.clone(),
-            in1: self.in1.clone(),
-            in2: self.in2.clone(),
-            mode: self.mode,
-            color_interpolation_filters: values.color_interpolation_filters(),
-        }))
+        Ok((
+            self.base.clone(),
+            PrimitiveParams::Blend(Blend {
+                in1: self.in1.clone(),
+                in2: self.in2.clone(),
+                mode: self.mode,
+                color_interpolation_filters: values.color_interpolation_filters(),
+            }),
+        ))
     }
 }
 
diff --git a/src/filters/color_matrix.rs b/src/filters/color_matrix.rs
index 340b9645..eec92297 100644
--- a/src/filters/color_matrix.rs
+++ b/src/filters/color_matrix.rs
@@ -38,7 +38,6 @@ pub struct FeColorMatrix {
 
 /// Resolved `feColorMatrix` primitive for rendering.
 pub struct ColorMatrix {
-    base: Primitive,
     in1: Input,
     matrix: Matrix5<f64>,
     color_interpolation_filters: ColorInterpolationFilters,
@@ -151,6 +150,7 @@ impl SetAttributes for FeColorMatrix {
 impl ColorMatrix {
     pub fn render(
         &self,
+        primitive: &Primitive,
         ctx: &FilterContext,
         acquired_nodes: &mut AcquiredNodes<'_>,
         draw_ctx: &mut DrawingCtx,
@@ -161,8 +161,7 @@ impl ColorMatrix {
             &self.in1,
             self.color_interpolation_filters,
         )?;
-        let bounds = self
-            .base
+        let bounds = primitive
             .get_bounds(ctx)?
             .add_input(&input_1)
             .into_irect(ctx, draw_ctx);
@@ -207,7 +206,7 @@ impl ColorMatrix {
         });
 
         Ok(FilterResult {
-            name: self.base.result.clone(),
+            name: primitive.result.clone(),
             output: FilterOutput {
                 surface: surface.share()?,
                 bounds,
@@ -217,16 +216,18 @@ impl ColorMatrix {
 }
 
 impl FilterEffect for FeColorMatrix {
-    fn resolve(&self, node: &Node) -> Result<PrimitiveParams, FilterError> {
+    fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
         let cascaded = CascadedValues::new_from_node(node);
         let values = cascaded.get();
 
-        Ok(PrimitiveParams::ColorMatrix(ColorMatrix {
-            base: self.base.clone(),
-            in1: self.in1.clone(),
-            matrix: self.matrix,
-            color_interpolation_filters: values.color_interpolation_filters(),
-        }))
+        Ok((
+            self.base.clone(),
+            PrimitiveParams::ColorMatrix(ColorMatrix {
+                in1: self.in1.clone(),
+                matrix: self.matrix,
+                color_interpolation_filters: values.color_interpolation_filters(),
+            }),
+        ))
     }
 }
 
diff --git a/src/filters/component_transfer.rs b/src/filters/component_transfer.rs
index ec8f7403..4904405c 100644
--- a/src/filters/component_transfer.rs
+++ b/src/filters/component_transfer.rs
@@ -27,7 +27,6 @@ pub struct FeComponentTransfer {
 
 /// Resolved `feComponentTransfer` primitive for rendering.
 pub struct ComponentTransfer {
-    base: Primitive,
     in1: Input,
     functions: Functions,
     color_interpolation_filters: ColorInterpolationFilters,
@@ -298,6 +297,7 @@ macro_rules! get_func_x_node {
 impl ComponentTransfer {
     pub fn render(
         &self,
+        primitive: &Primitive,
         ctx: &FilterContext,
         acquired_nodes: &mut AcquiredNodes<'_>,
         draw_ctx: &mut DrawingCtx,
@@ -308,8 +308,7 @@ impl ComponentTransfer {
             &self.in1,
             self.color_interpolation_filters,
         )?;
-        let bounds = self
-            .base
+        let bounds = primitive
             .get_bounds(ctx)?
             .add_input(&input_1)
             .into_irect(ctx, draw_ctx);
@@ -368,7 +367,7 @@ impl ComponentTransfer {
         });
 
         Ok(FilterResult {
-            name: self.base.result.clone(),
+            name: primitive.result.clone(),
             output: FilterOutput {
                 surface: surface.share()?,
                 bounds,
@@ -378,16 +377,18 @@ impl ComponentTransfer {
 }
 
 impl FilterEffect for FeComponentTransfer {
-    fn resolve(&self, node: &Node) -> Result<PrimitiveParams, FilterError> {
+    fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
         let cascaded = CascadedValues::new_from_node(node);
         let values = cascaded.get();
 
-        Ok(PrimitiveParams::ComponentTransfer(ComponentTransfer {
-            base: self.base.clone(),
-            in1: self.in1.clone(),
-            functions: get_functions(node)?,
-            color_interpolation_filters: values.color_interpolation_filters(),
-        }))
+        Ok((
+            self.base.clone(),
+            PrimitiveParams::ComponentTransfer(ComponentTransfer {
+                in1: self.in1.clone(),
+                functions: get_functions(node)?,
+                color_interpolation_filters: values.color_interpolation_filters(),
+            }),
+        ))
     }
 }
 
diff --git a/src/filters/composite.rs b/src/filters/composite.rs
index 2dd297de..0a7b9b00 100644
--- a/src/filters/composite.rs
+++ b/src/filters/composite.rs
@@ -38,7 +38,6 @@ pub struct FeComposite {
 
 /// Resolved `feComposite` primitive for rendering.
 pub struct Composite {
-    base: Primitive,
     in1: Input,
     in2: Input,
     operator: Operator,
@@ -90,6 +89,7 @@ impl SetAttributes for FeComposite {
 impl Composite {
     pub fn render(
         &self,
+        primitive: &Primitive,
         ctx: &FilterContext,
         acquired_nodes: &mut AcquiredNodes<'_>,
         draw_ctx: &mut DrawingCtx,
@@ -106,8 +106,7 @@ impl Composite {
             &self.in2,
             self.color_interpolation_filters,
         )?;
-        let bounds = self
-            .base
+        let bounds = primitive
             .get_bounds(ctx)?
             .add_input(&input_1)
             .add_input(&input_2)
@@ -131,28 +130,30 @@ impl Composite {
         };
 
         Ok(FilterResult {
-            name: self.base.result.clone(),
+            name: primitive.result.clone(),
             output: FilterOutput { surface, bounds },
         })
     }
 }
 
 impl FilterEffect for FeComposite {
-    fn resolve(&self, node: &Node) -> Result<PrimitiveParams, FilterError> {
+    fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
         let cascaded = CascadedValues::new_from_node(node);
         let values = cascaded.get();
 
-        Ok(PrimitiveParams::Composite(Composite {
-            base: self.base.clone(),
-            in1: self.in1.clone(),
-            in2: self.in2.clone(),
-            operator: self.operator,
-            k1: self.k1,
-            k2: self.k2,
-            k3: self.k3,
-            k4: self.k4,
-            color_interpolation_filters: values.color_interpolation_filters(),
-        }))
+        Ok((
+            self.base.clone(),
+            PrimitiveParams::Composite(Composite {
+                in1: self.in1.clone(),
+                in2: self.in2.clone(),
+                operator: self.operator,
+                k1: self.k1,
+                k2: self.k2,
+                k3: self.k3,
+                k4: self.k4,
+                color_interpolation_filters: values.color_interpolation_filters(),
+            }),
+        ))
     }
 }
 
diff --git a/src/filters/convolve_matrix.rs b/src/filters/convolve_matrix.rs
index d9d853c3..f69ffa2b 100644
--- a/src/filters/convolve_matrix.rs
+++ b/src/filters/convolve_matrix.rs
@@ -38,8 +38,8 @@ pub struct FeConvolveMatrix {
     preserve_alpha: bool,
 }
 
+/// Resolved `feConvolveMatrix` primitive for rendering.
 pub struct ConvolveMatrix {
-    base: Primitive,
     in1: Input,
     order: (u32, u32),
     kernel_matrix: Option<DMatrix<f64>>,
@@ -140,6 +140,7 @@ impl SetAttributes for FeConvolveMatrix {
 impl ConvolveMatrix {
     pub fn render(
         &self,
+        primitive: &Primitive,
         ctx: &FilterContext,
         acquired_nodes: &mut AcquiredNodes<'_>,
         draw_ctx: &mut DrawingCtx,
@@ -152,8 +153,7 @@ impl ConvolveMatrix {
             &self.in1,
             self.color_interpolation_filters,
         )?;
-        let mut bounds = self
-            .base
+        let mut bounds = primitive
             .get_bounds(ctx)?
             .add_input(&input_1)
             .into_irect(ctx, draw_ctx);
@@ -298,31 +298,33 @@ impl ConvolveMatrix {
         }
 
         Ok(FilterResult {
-            name: self.base.result.clone(),
+            name: primitive.result.clone(),
             output: FilterOutput { surface, bounds },
         })
     }
 }
 
 impl FilterEffect for FeConvolveMatrix {
-    fn resolve(&self, node: &Node) -> Result<PrimitiveParams, FilterError> {
+    fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
         let cascaded = CascadedValues::new_from_node(node);
         let values = cascaded.get();
 
-        Ok(PrimitiveParams::ConvolveMatrix(ConvolveMatrix {
-            base: self.base.clone(),
-            in1: self.in1.clone(),
-            order: self.order,
-            kernel_matrix: self.kernel_matrix.clone(),
-            divisor: self.divisor,
-            bias: self.bias,
-            target_x: self.target_x,
-            target_y: self.target_y,
-            edge_mode: self.edge_mode,
-            kernel_unit_length: self.kernel_unit_length,
-            preserve_alpha: self.preserve_alpha,
-            color_interpolation_filters: values.color_interpolation_filters(),
-        }))
+        Ok((
+            self.base.clone(),
+            PrimitiveParams::ConvolveMatrix(ConvolveMatrix {
+                in1: self.in1.clone(),
+                order: self.order,
+                kernel_matrix: self.kernel_matrix.clone(),
+                divisor: self.divisor,
+                bias: self.bias,
+                target_x: self.target_x,
+                target_y: self.target_y,
+                edge_mode: self.edge_mode,
+                kernel_unit_length: self.kernel_unit_length,
+                preserve_alpha: self.preserve_alpha,
+                color_interpolation_filters: values.color_interpolation_filters(),
+            }),
+        ))
     }
 }
 
diff --git a/src/filters/displacement_map.rs b/src/filters/displacement_map.rs
index fc038a5d..b407ffa3 100644
--- a/src/filters/displacement_map.rs
+++ b/src/filters/displacement_map.rs
@@ -35,7 +35,6 @@ pub struct FeDisplacementMap {
 
 /// Resolved `feDisplacementMap` primitive for rendering.
 pub struct DisplacementMap {
-    base: Primitive,
     in1: Input,
     in2: Input,
     scale: f64,
@@ -85,6 +84,7 @@ impl SetAttributes for FeDisplacementMap {
 impl DisplacementMap {
     pub fn render(
         &self,
+        primitive: &Primitive,
         ctx: &FilterContext,
         acquired_nodes: &mut AcquiredNodes<'_>,
         draw_ctx: &mut DrawingCtx,
@@ -107,8 +107,7 @@ impl DisplacementMap {
             &self.in2,
             self.color_interpolation_filters,
         )?;
-        let bounds = self
-            .base
+        let bounds = primitive
             .get_bounds(ctx)?
             .add_input(&input_1)
             .add_input(&displacement_input)
@@ -158,7 +157,7 @@ impl DisplacementMap {
         })?;
 
         Ok(FilterResult {
-            name: self.base.result.clone(),
+            name: primitive.result.clone(),
             output: FilterOutput {
                 surface: surface.share()?,
                 bounds,
@@ -168,19 +167,21 @@ impl DisplacementMap {
 }
 
 impl FilterEffect for FeDisplacementMap {
-    fn resolve(&self, node: &Node) -> Result<PrimitiveParams, FilterError> {
+    fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
         let cascaded = CascadedValues::new_from_node(node);
         let values = cascaded.get();
 
-        Ok(PrimitiveParams::DisplacementMap(DisplacementMap {
-            base: self.base.clone(),
-            in1: self.in1.clone(),
-            in2: self.in2.clone(),
-            scale: self.scale,
-            x_channel_selector: self.x_channel_selector,
-            y_channel_selector: self.y_channel_selector,
-            color_interpolation_filters: values.color_interpolation_filters(),
-        }))
+        Ok((
+            self.base.clone(),
+            PrimitiveParams::DisplacementMap(DisplacementMap {
+                in1: self.in1.clone(),
+                in2: self.in2.clone(),
+                scale: self.scale,
+                x_channel_selector: self.x_channel_selector,
+                y_channel_selector: self.y_channel_selector,
+                color_interpolation_filters: values.color_interpolation_filters(),
+            }),
+        ))
     }
 }
 
diff --git a/src/filters/flood.rs b/src/filters/flood.rs
index bda861dc..113cc4f4 100644
--- a/src/filters/flood.rs
+++ b/src/filters/flood.rs
@@ -15,7 +15,6 @@ pub struct FeFlood {
 
 /// Resolved `feFlood` primitive for rendering.
 pub struct Flood {
-    base: Primitive,
     color: cssparser::RGBA,
 }
 
@@ -38,33 +37,36 @@ impl SetAttributes for FeFlood {
 impl Flood {
     pub fn render(
         &self,
+        primitive: &Primitive,
         ctx: &FilterContext,
         _acquired_nodes: &mut AcquiredNodes<'_>,
         draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
-        let bounds = self.base.get_bounds(ctx)?.into_irect(ctx, draw_ctx);
+        let bounds = primitive.get_bounds(ctx)?.into_irect(ctx, draw_ctx);
 
         let surface = ctx.source_graphic().flood(bounds, self.color)?;
 
         Ok(FilterResult {
-            name: self.base.result.clone(),
+            name: primitive.result.clone(),
             output: FilterOutput { surface, bounds },
         })
     }
 }
 
 impl FilterEffect for FeFlood {
-    fn resolve(&self, node: &Node) -> Result<PrimitiveParams, FilterError> {
+    fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
         let cascaded = CascadedValues::new_from_node(node);
         let values = cascaded.get();
 
-        Ok(PrimitiveParams::Flood(Flood {
-            base: self.base.clone(),
-            color: resolve_color(
-                &values.flood_color().0,
-                values.flood_opacity().0,
-                values.color().0,
-            ),
-        }))
+        Ok((
+            self.base.clone(),
+            PrimitiveParams::Flood(Flood {
+                color: resolve_color(
+                    &values.flood_color().0,
+                    values.flood_opacity().0,
+                    values.color().0,
+                ),
+            }),
+        ))
     }
 }
diff --git a/src/filters/gaussian_blur.rs b/src/filters/gaussian_blur.rs
index acafbab4..4f3e9c67 100644
--- a/src/filters/gaussian_blur.rs
+++ b/src/filters/gaussian_blur.rs
@@ -34,7 +34,6 @@ pub struct FeGaussianBlur {
 
 /// Resolved `feGaussianBlur` primitive for rendering.
 pub struct GaussianBlur {
-    base: Primitive,
     in1: Input,
     std_deviation: (f64, f64),
     color_interpolation_filters: ColorInterpolationFilters,
@@ -199,6 +198,7 @@ fn gaussian_blur(
 impl GaussianBlur {
     pub fn render(
         &self,
+        primitive: &Primitive,
         ctx: &FilterContext,
         acquired_nodes: &mut AcquiredNodes<'_>,
         draw_ctx: &mut DrawingCtx,
@@ -209,8 +209,7 @@ impl GaussianBlur {
             &self.in1,
             self.color_interpolation_filters,
         )?;
-        let bounds = self
-            .base
+        let bounds = primitive
             .get_bounds(ctx)?
             .add_input(&input_1)
             .into_irect(ctx, draw_ctx);
@@ -247,7 +246,7 @@ impl GaussianBlur {
         };
 
         Ok(FilterResult {
-            name: self.base.result.clone(),
+            name: primitive.result.clone(),
             output: FilterOutput {
                 surface: output_surface,
                 bounds,
@@ -257,15 +256,17 @@ impl GaussianBlur {
 }
 
 impl FilterEffect for FeGaussianBlur {
-    fn resolve(&self, node: &Node) -> Result<PrimitiveParams, FilterError> {
+    fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
         let cascaded = CascadedValues::new_from_node(node);
         let values = cascaded.get();
 
-        Ok(PrimitiveParams::GaussianBlur(GaussianBlur {
-            base: self.base.clone(),
-            in1: self.in1.clone(),
-            std_deviation: self.std_deviation,
-            color_interpolation_filters: values.color_interpolation_filters(),
-        }))
+        Ok((
+            self.base.clone(),
+            PrimitiveParams::GaussianBlur(GaussianBlur {
+                in1: self.in1.clone(),
+                std_deviation: self.std_deviation,
+                color_interpolation_filters: values.color_interpolation_filters(),
+            }),
+        ))
     }
 }
diff --git a/src/filters/image.rs b/src/filters/image.rs
index c26a83f9..85ae2a8e 100644
--- a/src/filters/image.rs
+++ b/src/filters/image.rs
@@ -23,7 +23,11 @@ pub struct FeImage {
     href: Option<String>,
 }
 
-pub type Image = FeImage;
+/// Resolved `feImage` primitive for rendering.
+pub struct Image {
+    aspect: AspectRatio,
+    href: Option<String>,
+}
 
 impl Default for FeImage {
     /// Constructs a new `FeImage` with empty properties.
@@ -37,7 +41,7 @@ impl Default for FeImage {
     }
 }
 
-impl FeImage {
+impl Image {
     /// Renders the filter if the source is an existing node.
     fn render_node(
         &self,
@@ -121,14 +125,15 @@ impl SetAttributes for FeImage {
     }
 }
 
-impl FeImage {
+impl Image {
     pub fn render(
         &self,
+        primitive: &Primitive,
         ctx: &FilterContext,
         acquired_nodes: &mut AcquiredNodes<'_>,
         draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
-        let bounds_builder = self.base.get_bounds(ctx)?;
+        let bounds_builder = primitive.get_bounds(ctx)?;
         let (bounds, unclipped_bounds) = bounds_builder.into_rect(ctx, draw_ctx);
 
         let href = self.href.as_ref().ok_or(FilterError::InvalidInput)?;
@@ -148,7 +153,7 @@ impl FeImage {
         }?;
 
         Ok(FilterResult {
-            name: self.base.result.clone(),
+            name: primitive.result.clone(),
             output: FilterOutput {
                 surface,
                 bounds: bounds.into(),
@@ -158,7 +163,13 @@ impl FeImage {
 }
 
 impl FilterEffect for FeImage {
-    fn resolve(&self, _node: &Node) -> Result<PrimitiveParams, FilterError> {
-        Ok(PrimitiveParams::Image(self.clone()))
+    fn resolve(&self, _node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
+        Ok((
+            self.base.clone(),
+            PrimitiveParams::Image(Image {
+                aspect: self.aspect.clone(),
+                href: self.href.clone(),
+            }),
+        ))
     }
 }
diff --git a/src/filters/lighting.rs b/src/filters/lighting.rs
index 8858804f..d50ef0af 100644
--- a/src/filters/lighting.rs
+++ b/src/filters/lighting.rs
@@ -71,7 +71,6 @@ struct Light {
 
 /// Resolved `feDiffuseLighting` primitive for rendering.
 pub struct DiffuseLighting {
-    base: Primitive,
     in1: Input,
     surface_scale: f64,
     kernel_unit_length: Option<(f64, f64)>,
@@ -81,7 +80,6 @@ pub struct DiffuseLighting {
 
 /// Resolved `feSpecularLighting` primitive for rendering.
 pub struct SpecularLighting {
-    base: Primitive,
     in1: Input,
     surface_scale: f64,
     kernel_unit_length: Option<(f64, f64)>,
@@ -432,6 +430,7 @@ macro_rules! impl_lighting_filter {
         impl $params_name {
             pub fn render(
                 &self,
+                primitive: &Primitive,
                 ctx: &FilterContext,
                 acquired_nodes: &mut AcquiredNodes<'_>,
                 draw_ctx: &mut DrawingCtx,
@@ -442,8 +441,7 @@ macro_rules! impl_lighting_filter {
                     &self.in1,
                     self.light.color_interpolation_filters,
                 )?;
-                let mut bounds = self
-                    .base
+                let mut bounds = primitive
                     .get_bounds(ctx)?
                     .add_input(&input_1)
                     .into_irect(ctx, draw_ctx);
@@ -637,14 +635,14 @@ macro_rules! impl_lighting_filter {
                 }
 
                 Ok(FilterResult {
-                    name: self.base.result.clone(),
+                    name: primitive.result.clone(),
                     output: FilterOutput { surface, bounds },
                 })
             }
         }
 
         impl FilterEffect for $lighting_type {
-            fn resolve(&self, node: &Node) -> Result<PrimitiveParams, FilterError> {
+            fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
                 let mut sources = node.children().rev().filter(|c| {
                     c.is_element()
                         && matches!(
@@ -677,20 +675,22 @@ macro_rules! impl_lighting_filter {
                 let cascaded = CascadedValues::new_from_node(node);
                 let values = cascaded.get();
 
-                Ok(PrimitiveParams::$params_name($params_name {
-                    base: self.base.clone(),
-                    in1: self.in1.clone(),
-                    surface_scale: self.surface_scale.clone(),
-                    kernel_unit_length: self.kernel_unit_length.clone(),
-
-                    $($specific_fields: self.$specific_fields.clone(),)+
-
-                    light: Light {
-                        source,
-                        lighting_color: resolve_color(&values.lighting_color().0, UnitInterval::clamp(1.0), 
values.color().0),
-                        color_interpolation_filters: values.color_interpolation_filters(),
-                    }
-                }))
+                Ok((
+                    self.base.clone(),
+                    PrimitiveParams::$params_name($params_name {
+                        in1: self.in1.clone(),
+                        surface_scale: self.surface_scale.clone(),
+                        kernel_unit_length: self.kernel_unit_length.clone(),
+
+                        $($specific_fields: self.$specific_fields.clone(),)+
+
+                            light: Light {
+                                source,
+                                lighting_color: resolve_color(&values.lighting_color().0, 
UnitInterval::clamp(1.0), values.color().0),
+                                color_interpolation_filters: values.color_interpolation_filters(),
+                            }
+                    })
+                ))
             }
         }
     };
@@ -991,7 +991,7 @@ mod tests {
 
         let node = document.lookup_internal_node("diffuse_distant").unwrap();
         let lighting = borrow_element_as!(node, FeDiffuseLighting);
-        let params = lighting.resolve(&node).unwrap();
+        let (_, params) = lighting.resolve(&node).unwrap();
         let diffuse_lighting = match params {
             PrimitiveParams::DiffuseLighting(l) => l,
             _ => unreachable!(),
@@ -1006,7 +1006,7 @@ mod tests {
 
         let node = document.lookup_internal_node("specular_point").unwrap();
         let lighting = borrow_element_as!(node, FeSpecularLighting);
-        let params = lighting.resolve(&node).unwrap();
+        let (_, params) = lighting.resolve(&node).unwrap();
         let specular_lighting = match params {
             PrimitiveParams::SpecularLighting(l) => l,
             _ => unreachable!(),
@@ -1022,7 +1022,7 @@ mod tests {
 
         let node = document.lookup_internal_node("diffuse_spot").unwrap();
         let lighting = borrow_element_as!(node, FeDiffuseLighting);
-        let params = lighting.resolve(&node).unwrap();
+        let (_, params) = lighting.resolve(&node).unwrap();
         let diffuse_lighting = match params {
             PrimitiveParams::DiffuseLighting(l) => l,
             _ => unreachable!(),
diff --git a/src/filters/merge.rs b/src/filters/merge.rs
index 96a43551..8a1f7ab0 100644
--- a/src/filters/merge.rs
+++ b/src/filters/merge.rs
@@ -26,7 +26,6 @@ pub struct FeMergeNode {
 
 /// Resolved `feMerge` primitive for rendering.
 pub struct Merge {
-    base: Primitive,
     merge_nodes: Vec<MergeNode>,
 }
 
@@ -98,12 +97,13 @@ impl MergeNode {
 impl Merge {
     pub fn render(
         &self,
+        primitive: &Primitive,
         ctx: &FilterContext,
         acquired_nodes: &mut AcquiredNodes<'_>,
         draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
         // Compute the filter bounds, taking each feMergeNode's input into account.
-        let mut bounds = self.base.get_bounds(ctx)?;
+        let mut bounds = primitive.get_bounds(ctx)?;
         for merge_node in &self.merge_nodes {
             let input = ctx.get_input(
                 acquired_nodes,
@@ -134,18 +134,20 @@ impl Merge {
         };
 
         Ok(FilterResult {
-            name: self.base.result.clone(),
+            name: primitive.result.clone(),
             output: FilterOutput { surface, bounds },
         })
     }
 }
 
 impl FilterEffect for FeMerge {
-    fn resolve(&self, node: &Node) -> Result<PrimitiveParams, FilterError> {
-        Ok(PrimitiveParams::Merge(Merge {
-            base: self.base.clone(),
-            merge_nodes: resolve_merge_nodes(node)?,
-        }))
+    fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
+        Ok((
+            self.base.clone(),
+            PrimitiveParams::Merge(Merge {
+                merge_nodes: resolve_merge_nodes(node)?,
+            }),
+        ))
     }
 }
 
@@ -196,7 +198,7 @@ mod tests {
 
         let node = document.lookup_internal_node("merge").unwrap();
         let merge = borrow_element_as!(node, FeMerge);
-        let params = merge.resolve(&node).unwrap();
+        let (_, params) = merge.resolve(&node).unwrap();
         let params = match params {
             PrimitiveParams::Merge(m) => m,
             _ => unreachable!(),
diff --git a/src/filters/mod.rs b/src/filters/mod.rs
index 80da1280..988a099a 100644
--- a/src/filters/mod.rs
+++ b/src/filters/mod.rs
@@ -30,7 +30,7 @@ use self::error::FilterError;
 
 /// A filter primitive interface.
 pub trait FilterEffect: SetAttributes + Draw {
-    fn resolve(&self, node: &Node) -> Result<PrimitiveParams, FilterError>;
+    fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError>;
 }
 
 // Filter Effects do not need to draw themselves
@@ -79,7 +79,7 @@ pub enum PrimitiveParams {
 
 /// The base filter primitive node containing common properties.
 #[derive(Clone)]
-struct Primitive {
+pub struct Primitive {
     x: Option<Length<Horizontal>>,
     y: Option<Length<Vertical>>,
     width: Option<ULength<Horizontal>>,
@@ -291,7 +291,9 @@ pub fn render(
 
         if let Err(err) = filter
             .resolve(&c)
-            .and_then(|params| render_primitive(&params, &filter_ctx, acquired_nodes, draw_ctx))
+            .and_then(|(primitive, params)| {
+                render_primitive(&primitive, &params, &filter_ctx, acquired_nodes, draw_ctx)
+            })
             .and_then(|result| filter_ctx.store_result(result))
         {
             rsvg_log!("(filter primitive {} returned an error: {})", c, err);
@@ -315,6 +317,7 @@ pub fn render(
 
 #[rustfmt::skip]
 fn render_primitive(
+    primitive: &Primitive,
     params: &PrimitiveParams,
     ctx: &FilterContext,
     acquired_nodes: &mut AcquiredNodes<'_>,
@@ -323,22 +326,22 @@ fn render_primitive(
     use PrimitiveParams::*;
 
     match params {
-        Blend(p)             => p.render(ctx, acquired_nodes, draw_ctx),
-        ColorMatrix(p)       => p.render(ctx, acquired_nodes, draw_ctx),
-        ComponentTransfer(p) => p.render(ctx, acquired_nodes, draw_ctx),
-        Composite(p)         => p.render(ctx, acquired_nodes, draw_ctx),
-        ConvolveMatrix(p)    => p.render(ctx, acquired_nodes, draw_ctx),
-        DiffuseLighting(p)   => p.render(ctx, acquired_nodes, draw_ctx),
-        DisplacementMap(p)   => p.render(ctx, acquired_nodes, draw_ctx),
-        Flood(p)             => p.render(ctx, acquired_nodes, draw_ctx),
-        GaussianBlur(p)      => p.render(ctx, acquired_nodes, draw_ctx),
-        Image(p)             => p.render(ctx, acquired_nodes, draw_ctx),
-        Merge(p)             => p.render(ctx, acquired_nodes, draw_ctx),
-        Morphology(p)        => p.render(ctx, acquired_nodes, draw_ctx),
-        Offset(p)            => p.render(ctx, acquired_nodes, draw_ctx),
-        SpecularLighting(p)  => p.render(ctx, acquired_nodes, draw_ctx),
-        Tile(p)              => p.render(ctx, acquired_nodes, draw_ctx),
-        Turbulence(p)        => p.render(ctx, acquired_nodes, draw_ctx),
+        Blend(p)             => p.render(primitive, ctx, acquired_nodes, draw_ctx),
+        ColorMatrix(p)       => p.render(primitive, ctx, acquired_nodes, draw_ctx),
+        ComponentTransfer(p) => p.render(primitive, ctx, acquired_nodes, draw_ctx),
+        Composite(p)         => p.render(primitive, ctx, acquired_nodes, draw_ctx),
+        ConvolveMatrix(p)    => p.render(primitive, ctx, acquired_nodes, draw_ctx),
+        DiffuseLighting(p)   => p.render(primitive, ctx, acquired_nodes, draw_ctx),
+        DisplacementMap(p)   => p.render(primitive, ctx, acquired_nodes, draw_ctx),
+        Flood(p)             => p.render(primitive, ctx, acquired_nodes, draw_ctx),
+        GaussianBlur(p)      => p.render(primitive, ctx, acquired_nodes, draw_ctx),
+        Image(p)             => p.render(primitive, ctx, acquired_nodes, draw_ctx),
+        Merge(p)             => p.render(primitive, ctx, acquired_nodes, draw_ctx),
+        Morphology(p)        => p.render(primitive, ctx, acquired_nodes, draw_ctx),
+        Offset(p)            => p.render(primitive, ctx, acquired_nodes, draw_ctx),
+        SpecularLighting(p)  => p.render(primitive, ctx, acquired_nodes, draw_ctx),
+        Tile(p)              => p.render(primitive, ctx, acquired_nodes, draw_ctx),
+        Turbulence(p)        => p.render(primitive, ctx, acquired_nodes, draw_ctx),
     }
 }
 
diff --git a/src/filters/morphology.rs b/src/filters/morphology.rs
index a0144ef5..b427575d 100644
--- a/src/filters/morphology.rs
+++ b/src/filters/morphology.rs
@@ -29,7 +29,6 @@ enum Operator {
 }
 
 /// The `feMorphology` filter primitive.
-#[derive(Clone)]
 pub struct FeMorphology {
     base: Primitive,
     in1: Input,
@@ -38,7 +37,11 @@ pub struct FeMorphology {
 }
 
 /// Resolved `feMorphology` primitive for rendering.
-pub type Morphology = FeMorphology;
+pub struct Morphology {
+    in1: Input,
+    operator: Operator,
+    radius: (f64, f64),
+}
 
 impl Default for FeMorphology {
     /// Constructs a new `Morphology` with empty properties.
@@ -72,9 +75,10 @@ impl SetAttributes for FeMorphology {
     }
 }
 
-impl FeMorphology {
+impl Morphology {
     pub fn render(
         &self,
+        primitive: &Primitive,
         ctx: &FilterContext,
         acquired_nodes: &mut AcquiredNodes<'_>,
         draw_ctx: &mut DrawingCtx,
@@ -93,8 +97,7 @@ impl FeMorphology {
             &self.in1,
             ColorInterpolationFilters::Auto,
         )?;
-        let bounds = self
-            .base
+        let bounds = primitive
             .get_bounds(ctx)?
             .add_input(&input_1)
             .into_irect(ctx, draw_ctx);
@@ -156,7 +159,7 @@ impl FeMorphology {
         });
 
         Ok(FilterResult {
-            name: self.base.result.clone(),
+            name: primitive.result.clone(),
             output: FilterOutput {
                 surface: surface.share()?,
                 bounds,
@@ -166,8 +169,15 @@ impl FeMorphology {
 }
 
 impl FilterEffect for FeMorphology {
-    fn resolve(&self, _node: &Node) -> Result<PrimitiveParams, FilterError> {
-        Ok(PrimitiveParams::Morphology(self.clone()))
+    fn resolve(&self, _node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
+        Ok((
+            self.base.clone(),
+            PrimitiveParams::Morphology(Morphology {
+                in1: self.in1.clone(),
+                operator: self.operator.clone(),
+                radius: self.radius,
+            }),
+        ))
     }
 }
 
diff --git a/src/filters/offset.rs b/src/filters/offset.rs
index c313a598..439313e9 100644
--- a/src/filters/offset.rs
+++ b/src/filters/offset.rs
@@ -21,7 +21,11 @@ pub struct FeOffset {
 }
 
 /// Resolved `feOffset` primitive for rendering.
-pub type Offset = FeOffset;
+pub struct Offset {
+    in1: Input,
+    dx: f64,
+    dy: f64,
+}
 
 impl Default for FeOffset {
     /// Constructs a new `Offset` with empty properties.
@@ -52,9 +56,10 @@ impl SetAttributes for FeOffset {
     }
 }
 
-impl FeOffset {
+impl Offset {
     pub fn render(
         &self,
+        primitive: &Primitive,
         ctx: &FilterContext,
         acquired_nodes: &mut AcquiredNodes<'_>,
         draw_ctx: &mut DrawingCtx,
@@ -72,8 +77,7 @@ impl FeOffset {
             &self.in1,
             ColorInterpolationFilters::Auto,
         )?;
-        let bounds = self
-            .base
+        let bounds = primitive
             .get_bounds(ctx)?
             .add_input(&input_1)
             .into_irect(ctx, draw_ctx);
@@ -83,14 +87,21 @@ impl FeOffset {
         let surface = input_1.surface().offset(bounds, dx, dy)?;
 
         Ok(FilterResult {
-            name: self.base.result.clone(),
+            name: primitive.result.clone(),
             output: FilterOutput { surface, bounds },
         })
     }
 }
 
 impl FilterEffect for FeOffset {
-    fn resolve(&self, _node: &Node) -> Result<PrimitiveParams, FilterError> {
-        Ok(PrimitiveParams::Offset(self.clone()))
+    fn resolve(&self, _node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
+        Ok((
+            self.base.clone(),
+            PrimitiveParams::Offset(Offset {
+                in1: self.in1.clone(),
+                dx: self.dx,
+                dy: self.dy,
+            }),
+        ))
     }
 }
diff --git a/src/filters/tile.rs b/src/filters/tile.rs
index 9e13dff8..e192361c 100644
--- a/src/filters/tile.rs
+++ b/src/filters/tile.rs
@@ -16,7 +16,9 @@ pub struct FeTile {
 }
 
 /// Resolved `feTile` primitive for rendering.
-pub type Tile = FeTile;
+pub struct Tile {
+    in1: Input,
+}
 
 impl Default for FeTile {
     /// Constructs a new `Tile` with empty properties.
@@ -36,9 +38,10 @@ impl SetAttributes for FeTile {
     }
 }
 
-impl FeTile {
+impl Tile {
     pub fn render(
         &self,
+        primitive: &Primitive,
         ctx: &FilterContext,
         acquired_nodes: &mut AcquiredNodes<'_>,
         draw_ctx: &mut DrawingCtx,
@@ -58,7 +61,7 @@ impl FeTile {
         )?;
 
         // feTile doesn't consider its inputs in the filter primitive subregion calculation.
-        let bounds = self.base.get_bounds(ctx)?.into_irect(ctx, draw_ctx);
+        let bounds = primitive.get_bounds(ctx)?.into_irect(ctx, draw_ctx);
 
         let surface = match input_1 {
             FilterInput::StandardInput(input_surface) => input_surface,
@@ -78,14 +81,19 @@ impl FeTile {
         };
 
         Ok(FilterResult {
-            name: self.base.result.clone(),
+            name: primitive.result.clone(),
             output: FilterOutput { surface, bounds },
         })
     }
 }
 
 impl FilterEffect for FeTile {
-    fn resolve(&self, _node: &Node) -> Result<PrimitiveParams, FilterError> {
-        Ok(PrimitiveParams::Tile(self.clone()))
+    fn resolve(&self, _node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
+        Ok((
+            self.base.clone(),
+            PrimitiveParams::Tile(Tile {
+                in1: self.in1.clone(),
+            }),
+        ))
     }
 }
diff --git a/src/filters/turbulence.rs b/src/filters/turbulence.rs
index 3b202f77..9f8fe9b4 100644
--- a/src/filters/turbulence.rs
+++ b/src/filters/turbulence.rs
@@ -44,7 +44,6 @@ pub struct FeTurbulence {
 
 /// Resolved `feTurbulence` primitive for rendering.
 pub struct Turbulence {
-    base: Primitive,
     base_frequency: (f64, f64),
     num_octaves: i32,
     seed: i32,
@@ -338,11 +337,12 @@ impl NoiseGenerator {
 impl Turbulence {
     pub fn render(
         &self,
+        primitive: &Primitive,
         ctx: &FilterContext,
         _acquired_nodes: &mut AcquiredNodes<'_>,
         draw_ctx: &mut DrawingCtx,
     ) -> Result<FilterResult, FilterError> {
-        let bounds = self.base.get_bounds(ctx)?.into_irect(ctx, draw_ctx);
+        let bounds = primitive.get_bounds(ctx)?.into_irect(ctx, draw_ctx);
 
         let affine = ctx.paffine().invert().unwrap();
 
@@ -402,7 +402,7 @@ impl Turbulence {
         });
 
         Ok(FilterResult {
-            name: self.base.result.clone(),
+            name: primitive.result.clone(),
             output: FilterOutput {
                 surface: surface.share()?,
                 bounds,
@@ -412,19 +412,21 @@ impl Turbulence {
 }
 
 impl FilterEffect for FeTurbulence {
-    fn resolve(&self, node: &Node) -> Result<PrimitiveParams, FilterError> {
+    fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError> {
         let cascaded = CascadedValues::new_from_node(node);
         let values = cascaded.get();
 
-        Ok(PrimitiveParams::Turbulence(Turbulence {
-            base: self.base.clone(),
-            base_frequency: self.base_frequency,
-            num_octaves: self.num_octaves,
-            seed: self.seed,
-            stitch_tiles: self.stitch_tiles,
-            type_: self.type_,
-            color_interpolation_filters: values.color_interpolation_filters(),
-        }))
+        Ok((
+            self.base.clone(),
+            PrimitiveParams::Turbulence(Turbulence {
+                base_frequency: self.base_frequency,
+                num_octaves: self.num_octaves,
+                seed: self.seed,
+                stitch_tiles: self.stitch_tiles,
+                type_: self.type_,
+                color_interpolation_filters: values.color_interpolation_filters(),
+            }),
+        ))
     }
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]