summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Ledbetter <john.ledbetter@gmail.com>2021-06-10 09:21:09 -0400
committerFederico Mena Quintero <federico@gnome.org>2023-02-09 13:15:53 -0600
commitc5025d955b364b46a8062764e9057123d6fe8a58 (patch)
treef9660434c7adff9d72ada34832f97dc7dd3d96dc
parent91c059331352775e879f3dea13c68b52965ae901 (diff)
downloadlibrsvg-c5025d955b364b46a8062764e9057123d6fe8a58.tar.gz
FilterEffect::resolve: return Array of ResolvedPrimitives
This change allows us to return filters composed of multiple ResolvedPrimitives, specifically for the FeDropShadow filter element. Part-of: <https://gitlab.gnome.org/GNOME/librsvg/-/merge_requests/793>
-rw-r--r--src/filter.rs52
-rw-r--r--src/filters/blend.rs6
-rw-r--r--src/filters/color_matrix.rs6
-rw-r--r--src/filters/component_transfer.rs6
-rw-r--r--src/filters/composite.rs6
-rw-r--r--src/filters/convolve_matrix.rs6
-rw-r--r--src/filters/displacement_map.rs6
-rw-r--r--src/filters/flood.rs6
-rw-r--r--src/filters/gaussian_blur.rs6
-rw-r--r--src/filters/image.rs6
-rw-r--r--src/filters/lighting.rs18
-rw-r--r--src/filters/merge.rs9
-rw-r--r--src/filters/mod.rs2
-rw-r--r--src/filters/morphology.rs6
-rw-r--r--src/filters/offset.rs6
-rw-r--r--src/filters/tile.rs6
-rw-r--r--src/filters/turbulence.rs6
17 files changed, 83 insertions, 76 deletions
diff --git a/src/filter.rs b/src/filter.rs
index ebab3099..9f7d5312 100644
--- a/src/filter.rs
+++ b/src/filter.rs
@@ -10,7 +10,7 @@ use crate::drawing_ctx::{DrawingCtx, ViewParams};
use crate::element::{set_attribute, Draw, Element, SetAttributes};
use crate::error::ValueErrorKind;
use crate::filter_func::FilterFunction;
-use crate::filters::{FilterResolveError, FilterSpec, UserSpacePrimitive};
+use crate::filters::{FilterResolveError, FilterSpec};
use crate::length::*;
use crate::node::{Node, NodeBorrow};
use crate::parsers::{Parse, ParseValue};
@@ -179,38 +179,44 @@ fn extract_filter_from_filter_node(
let primitive_view_params = filter_view_params.get(user_space_filter.primitive_units);
- let primitives = filter_node
+ let primitive_nodes = filter_node
.children()
.filter(|c| c.is_element())
// Keep only filter primitives (those that implement the Filter trait)
- .filter(|c| c.borrow_element().as_filter_effect().is_some())
- .map(|primitive_node| {
- let elt = primitive_node.borrow_element();
- let effect = elt.as_filter_effect().unwrap();
+ .filter(|c| c.borrow_element().as_filter_effect().is_some());
- let primitive_name = format!("{primitive_node}");
+ let mut user_space_primitives = Vec::new();
- let primitive_values = elt.get_computed_values();
- let params = NormalizeParams::new(primitive_values, primitive_view_params);
+ for primitive_node in primitive_nodes {
+ let elt = primitive_node.borrow_element();
+ let effect = elt.as_filter_effect().unwrap();
- effect
- .resolve(acquired_nodes, &primitive_node)
- .map_err(|e| {
- rsvg_log!(
- session,
- "(filter primitive {} returned an error: {})",
- primitive_name,
- e
- );
+ let primitive_name = format!("{primitive_node}");
+
+ let primitive_values = elt.get_computed_values();
+ let params = NormalizeParams::new(primitive_values, primitive_view_params);
+
+ let primitives = match effect.resolve(acquired_nodes, &primitive_node) {
+ Ok(primitives) => primitives,
+ Err(e) => {
+ rsvg_log!(
+ session,
+ "(filter primitive {} returned an error: {})",
+ primitive_name,
e
- })
- .map(|primitive| primitive.into_user_space(&params))
- })
- .collect::<Result<Vec<UserSpacePrimitive>, FilterResolveError>>()?;
+ );
+ return Err(e);
+ }
+ };
+
+ for p in primitives {
+ user_space_primitives.push(p.into_user_space(&params));
+ }
+ }
Ok(FilterSpec {
user_space_filter,
- primitives,
+ primitives: user_space_primitives,
})
}
diff --git a/src/filters/blend.rs b/src/filters/blend.rs
index 4baf4476..28a8be25 100644
--- a/src/filters/blend.rs
+++ b/src/filters/blend.rs
@@ -113,17 +113,17 @@ impl FilterEffect for FeBlend {
&self,
_acquired_nodes: &mut AcquiredNodes<'_>,
node: &Node,
- ) -> Result<ResolvedPrimitive, FilterResolveError> {
+ ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> {
let cascaded = CascadedValues::new_from_node(node);
let values = cascaded.get();
let mut params = self.params.clone();
params.color_interpolation_filters = values.color_interpolation_filters();
- Ok(ResolvedPrimitive {
+ Ok(vec![ResolvedPrimitive {
primitive: self.base.clone(),
params: PrimitiveParams::Blend(params),
- })
+ }])
}
}
diff --git a/src/filters/color_matrix.rs b/src/filters/color_matrix.rs
index 7bb3689f..b06cac1f 100644
--- a/src/filters/color_matrix.rs
+++ b/src/filters/color_matrix.rs
@@ -315,17 +315,17 @@ impl FilterEffect for FeColorMatrix {
&self,
_acquired_nodes: &mut AcquiredNodes<'_>,
node: &Node,
- ) -> Result<ResolvedPrimitive, FilterResolveError> {
+ ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> {
let cascaded = CascadedValues::new_from_node(node);
let values = cascaded.get();
let mut params = self.params.clone();
params.color_interpolation_filters = values.color_interpolation_filters();
- Ok(ResolvedPrimitive {
+ Ok(vec![ResolvedPrimitive {
primitive: self.base.clone(),
params: PrimitiveParams::ColorMatrix(params),
- })
+ }])
}
}
diff --git a/src/filters/component_transfer.rs b/src/filters/component_transfer.rs
index 02efa6ca..ae358d72 100644
--- a/src/filters/component_transfer.rs
+++ b/src/filters/component_transfer.rs
@@ -385,7 +385,7 @@ impl FilterEffect for FeComponentTransfer {
&self,
_acquired_nodes: &mut AcquiredNodes<'_>,
node: &Node,
- ) -> Result<ResolvedPrimitive, FilterResolveError> {
+ ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> {
let cascaded = CascadedValues::new_from_node(node);
let values = cascaded.get();
@@ -393,10 +393,10 @@ impl FilterEffect for FeComponentTransfer {
params.functions = get_functions(node)?;
params.color_interpolation_filters = values.color_interpolation_filters();
- Ok(ResolvedPrimitive {
+ Ok(vec![ResolvedPrimitive {
primitive: self.base.clone(),
params: PrimitiveParams::ComponentTransfer(params),
- })
+ }])
}
}
diff --git a/src/filters/composite.rs b/src/filters/composite.rs
index c05468e8..2be0e261 100644
--- a/src/filters/composite.rs
+++ b/src/filters/composite.rs
@@ -133,17 +133,17 @@ impl FilterEffect for FeComposite {
&self,
_acquired_nodes: &mut AcquiredNodes<'_>,
node: &Node,
- ) -> Result<ResolvedPrimitive, FilterResolveError> {
+ ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> {
let cascaded = CascadedValues::new_from_node(node);
let values = cascaded.get();
let mut params = self.params.clone();
params.color_interpolation_filters = values.color_interpolation_filters();
- Ok(ResolvedPrimitive {
+ Ok(vec![ResolvedPrimitive {
primitive: self.base.clone(),
params: PrimitiveParams::Composite(params),
- })
+ }])
}
}
diff --git a/src/filters/convolve_matrix.rs b/src/filters/convolve_matrix.rs
index db9dc047..a445e733 100644
--- a/src/filters/convolve_matrix.rs
+++ b/src/filters/convolve_matrix.rs
@@ -321,17 +321,17 @@ impl FilterEffect for FeConvolveMatrix {
&self,
_acquired_nodes: &mut AcquiredNodes<'_>,
node: &Node,
- ) -> Result<ResolvedPrimitive, FilterResolveError> {
+ ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> {
let cascaded = CascadedValues::new_from_node(node);
let values = cascaded.get();
let mut params = self.params.clone();
params.color_interpolation_filters = values.color_interpolation_filters();
- Ok(ResolvedPrimitive {
+ Ok(vec![ResolvedPrimitive {
primitive: self.base.clone(),
params: PrimitiveParams::ConvolveMatrix(params),
- })
+ }])
}
}
diff --git a/src/filters/displacement_map.rs b/src/filters/displacement_map.rs
index d8781d80..e3396e5a 100644
--- a/src/filters/displacement_map.rs
+++ b/src/filters/displacement_map.rs
@@ -168,17 +168,17 @@ impl FilterEffect for FeDisplacementMap {
&self,
_acquired_nodes: &mut AcquiredNodes<'_>,
node: &Node,
- ) -> Result<ResolvedPrimitive, FilterResolveError> {
+ ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> {
let cascaded = CascadedValues::new_from_node(node);
let values = cascaded.get();
let mut params = self.params.clone();
params.color_interpolation_filters = values.color_interpolation_filters();
- Ok(ResolvedPrimitive {
+ Ok(vec![ResolvedPrimitive {
primitive: self.base.clone(),
params: PrimitiveParams::DisplacementMap(params),
- })
+ }])
}
}
diff --git a/src/filters/flood.rs b/src/filters/flood.rs
index 50838207..cd158f62 100644
--- a/src/filters/flood.rs
+++ b/src/filters/flood.rs
@@ -52,11 +52,11 @@ impl FilterEffect for FeFlood {
&self,
_acquired_nodes: &mut AcquiredNodes<'_>,
node: &Node,
- ) -> Result<ResolvedPrimitive, FilterResolveError> {
+ ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> {
let cascaded = CascadedValues::new_from_node(node);
let values = cascaded.get();
- Ok(ResolvedPrimitive {
+ Ok(vec![ResolvedPrimitive {
primitive: self.base.clone(),
params: PrimitiveParams::Flood(Flood {
color: resolve_color(
@@ -65,6 +65,6 @@ impl FilterEffect for FeFlood {
values.color().0,
),
}),
- })
+ }])
}
}
diff --git a/src/filters/gaussian_blur.rs b/src/filters/gaussian_blur.rs
index d44e5ae0..e6ae3b68 100644
--- a/src/filters/gaussian_blur.rs
+++ b/src/filters/gaussian_blur.rs
@@ -271,16 +271,16 @@ impl FilterEffect for FeGaussianBlur {
&self,
_acquired_nodes: &mut AcquiredNodes<'_>,
node: &Node,
- ) -> Result<ResolvedPrimitive, FilterResolveError> {
+ ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> {
let cascaded = CascadedValues::new_from_node(node);
let values = cascaded.get();
let mut params = self.params.clone();
params.color_interpolation_filters = values.color_interpolation_filters();
- Ok(ResolvedPrimitive {
+ Ok(vec![ResolvedPrimitive {
primitive: self.base.clone(),
params: PrimitiveParams::GaussianBlur(params),
- })
+ }])
}
}
diff --git a/src/filters/image.rs b/src/filters/image.rs
index a926c952..c3f19c8f 100644
--- a/src/filters/image.rs
+++ b/src/filters/image.rs
@@ -180,7 +180,7 @@ impl FilterEffect for FeImage {
&self,
acquired_nodes: &mut AcquiredNodes<'_>,
node: &Node,
- ) -> Result<ResolvedPrimitive, FilterResolveError> {
+ ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> {
let cascaded = CascadedValues::new_from_node(node);
let feimage_values = cascaded.get().clone();
@@ -199,13 +199,13 @@ impl FilterEffect for FeImage {
}
};
- Ok(ResolvedPrimitive {
+ Ok(vec![ResolvedPrimitive {
primitive: self.base.clone(),
params: PrimitiveParams::Image(Image {
aspect: self.params.aspect,
source,
feimage_values: Box::new(feimage_values),
}),
- })
+ }])
}
}
diff --git a/src/filters/lighting.rs b/src/filters/lighting.rs
index e222de22..6a0b52ee 100644
--- a/src/filters/lighting.rs
+++ b/src/filters/lighting.rs
@@ -705,7 +705,7 @@ macro_rules! impl_lighting_filter {
&self,
_acquired_nodes: &mut AcquiredNodes<'_>,
node: &Node,
- ) -> Result<ResolvedPrimitive, FilterResolveError> {
+ ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> {
let mut sources = node.children().rev().filter(|c| {
c.is_element()
&& matches!(
@@ -740,7 +740,7 @@ macro_rules! impl_lighting_filter {
let cascaded = CascadedValues::new_from_node(node);
let values = cascaded.get();
- Ok(ResolvedPrimitive {
+ Ok(vec![ResolvedPrimitive {
primitive: self.base.clone(),
params: PrimitiveParams::$params_name($params_name {
params: self.params.clone(),
@@ -754,7 +754,7 @@ macro_rules! impl_lighting_filter {
color_interpolation_filters: values.color_interpolation_filters(),
},
}),
- })
+ }])
}
}
};
@@ -1045,8 +1045,8 @@ mod tests {
let node = document.lookup_internal_node("diffuse_distant").unwrap();
let lighting = borrow_element_as!(node, FeDiffuseLighting);
- let ResolvedPrimitive { params, .. } =
- lighting.resolve(&mut acquired_nodes, &node).unwrap();
+ let resolved = lighting.resolve(&mut acquired_nodes, &node).unwrap();
+ let ResolvedPrimitive { params, .. } = resolved.first().unwrap();
let diffuse_lighting = match params {
PrimitiveParams::DiffuseLighting(l) => l,
_ => unreachable!(),
@@ -1061,8 +1061,8 @@ mod tests {
let node = document.lookup_internal_node("specular_point").unwrap();
let lighting = borrow_element_as!(node, FeSpecularLighting);
- let ResolvedPrimitive { params, .. } =
- lighting.resolve(&mut acquired_nodes, &node).unwrap();
+ let resolved = lighting.resolve(&mut acquired_nodes, &node).unwrap();
+ let ResolvedPrimitive { params, .. } = resolved.first().unwrap();
let specular_lighting = match params {
PrimitiveParams::SpecularLighting(l) => l,
_ => unreachable!(),
@@ -1078,8 +1078,8 @@ mod tests {
let node = document.lookup_internal_node("diffuse_spot").unwrap();
let lighting = borrow_element_as!(node, FeDiffuseLighting);
- let ResolvedPrimitive { params, .. } =
- lighting.resolve(&mut acquired_nodes, &node).unwrap();
+ let resolved = lighting.resolve(&mut acquired_nodes, &node).unwrap();
+ let ResolvedPrimitive { params, .. } = resolved.first().unwrap();
let diffuse_lighting = match params {
PrimitiveParams::DiffuseLighting(l) => l,
_ => unreachable!(),
diff --git a/src/filters/merge.rs b/src/filters/merge.rs
index 56292406..f76f9dd0 100644
--- a/src/filters/merge.rs
+++ b/src/filters/merge.rs
@@ -145,13 +145,13 @@ impl FilterEffect for FeMerge {
&self,
_acquired_nodes: &mut AcquiredNodes<'_>,
node: &Node,
- ) -> Result<ResolvedPrimitive, FilterResolveError> {
- Ok(ResolvedPrimitive {
+ ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> {
+ Ok(vec![ResolvedPrimitive {
primitive: self.base.clone(),
params: PrimitiveParams::Merge(Merge {
merge_nodes: resolve_merge_nodes(node)?,
}),
- })
+ }])
}
}
@@ -199,7 +199,8 @@ mod tests {
let node = document.lookup_internal_node("merge").unwrap();
let merge = borrow_element_as!(node, FeMerge);
- let ResolvedPrimitive { params, .. } = merge.resolve(&mut acquired_nodes, &node).unwrap();
+ let resolved = merge.resolve(&mut acquired_nodes, &node).unwrap();
+ let ResolvedPrimitive { params, .. } = resolved.first().unwrap();
let params = match params {
PrimitiveParams::Merge(m) => m,
_ => unreachable!(),
diff --git a/src/filters/mod.rs b/src/filters/mod.rs
index 0bd1cefa..8b0f37d5 100644
--- a/src/filters/mod.rs
+++ b/src/filters/mod.rs
@@ -37,7 +37,7 @@ pub trait FilterEffect: SetAttributes + Draw {
&self,
acquired_nodes: &mut AcquiredNodes<'_>,
node: &Node,
- ) -> Result<ResolvedPrimitive, FilterResolveError>;
+ ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError>;
}
// Filter Effects do not need to draw themselves
diff --git a/src/filters/morphology.rs b/src/filters/morphology.rs
index 519efca7..b69b01d4 100644
--- a/src/filters/morphology.rs
+++ b/src/filters/morphology.rs
@@ -181,11 +181,11 @@ impl FilterEffect for FeMorphology {
&self,
_acquired_nodes: &mut AcquiredNodes<'_>,
_node: &Node,
- ) -> Result<ResolvedPrimitive, FilterResolveError> {
- Ok(ResolvedPrimitive {
+ ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> {
+ Ok(vec![ResolvedPrimitive {
primitive: self.base.clone(),
params: PrimitiveParams::Morphology(self.params.clone()),
- })
+ }])
}
}
diff --git a/src/filters/offset.rs b/src/filters/offset.rs
index 27698b05..49a2be19 100644
--- a/src/filters/offset.rs
+++ b/src/filters/offset.rs
@@ -91,10 +91,10 @@ impl FilterEffect for FeOffset {
&self,
_acquired_nodes: &mut AcquiredNodes<'_>,
_node: &Node,
- ) -> Result<ResolvedPrimitive, FilterResolveError> {
- Ok(ResolvedPrimitive {
+ ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> {
+ Ok(vec![ResolvedPrimitive {
primitive: self.base.clone(),
params: PrimitiveParams::Offset(self.params.clone()),
- })
+ }])
}
}
diff --git a/src/filters/tile.rs b/src/filters/tile.rs
index e3bf940a..358b996b 100644
--- a/src/filters/tile.rs
+++ b/src/filters/tile.rs
@@ -100,10 +100,10 @@ impl FilterEffect for FeTile {
&self,
_acquired_nodes: &mut AcquiredNodes<'_>,
_node: &Node,
- ) -> Result<ResolvedPrimitive, FilterResolveError> {
- Ok(ResolvedPrimitive {
+ ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> {
+ Ok(vec![ResolvedPrimitive {
primitive: self.base.clone(),
params: PrimitiveParams::Tile(self.params.clone()),
- })
+ }])
}
}
diff --git a/src/filters/turbulence.rs b/src/filters/turbulence.rs
index 32035f5d..191c51ae 100644
--- a/src/filters/turbulence.rs
+++ b/src/filters/turbulence.rs
@@ -432,17 +432,17 @@ impl FilterEffect for FeTurbulence {
&self,
_acquired_nodes: &mut AcquiredNodes<'_>,
node: &Node,
- ) -> Result<ResolvedPrimitive, FilterResolveError> {
+ ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> {
let cascaded = CascadedValues::new_from_node(node);
let values = cascaded.get();
let mut params = self.params.clone();
params.color_interpolation_filters = values.color_interpolation_filters();
- Ok(ResolvedPrimitive {
+ Ok(vec![ResolvedPrimitive {
primitive: self.base.clone(),
params: PrimitiveParams::Turbulence(params),
- })
+ }])
}
}