[librsvg: 37/45] Go back to having NodeLinearGradient and NodeRadialGradient



commit 6adabd496ff4448c5be45aa66f540ee9a5091c6d
Author: Federico Mena Quintero <federico gnome org>
Date:   Mon Sep 30 17:24:03 2019 -0500

    Go back to having NodeLinearGradient and NodeRadialGradient

 rsvg_internals/src/create_node.rs |   6 +-
 rsvg_internals/src/drawing_ctx.rs |  10 +-
 rsvg_internals/src/gradient.rs    | 265 +++++++++++++++++++++-----------------
 rsvg_internals/src/node.rs        |   3 +-
 4 files changed, 158 insertions(+), 126 deletions(-)
---
diff --git a/rsvg_internals/src/create_node.rs b/rsvg_internals/src/create_node.rs
index 32011d58..da7e520a 100644
--- a/rsvg_internals/src/create_node.rs
+++ b/rsvg_internals/src/create_node.rs
@@ -22,7 +22,7 @@ use crate::filters::{
     turbulence::Turbulence,
 };
 
-use crate::gradient::{NodeGradient, NodeStop};
+use crate::gradient::{NodeLinearGradient, NodeRadialGradient, NodeStop};
 use crate::image::NodeImage;
 use crate::link::NodeLink;
 use crate::marker::NodeMarker;
@@ -76,7 +76,7 @@ mod creators {
     n!(create_image,                     Image,                      NodeImage::default);
     n!(create_fe_image,                  FeImage,                    Image::default);
     n!(create_line,                      Line,                       NodeLine::default);
-    n!(create_linear_gradient,           Gradient,                   NodeGradient::new_linear);
+    n!(create_linear_gradient,           LinearGradient,             NodeLinearGradient::default);
     n!(create_link,                      Link,                       NodeLink::default);
     n!(create_marker,                    Marker,                     NodeMarker::default);
     n!(create_mask,                      Mask,                       NodeMask::default);
@@ -90,7 +90,7 @@ mod creators {
     n!(create_point_light,               PointLight,                 LightSource::new_point_light);
     n!(create_polygon,                   Polygon,                    NodePoly::new_closed);
     n!(create_polyline,                  Polyline,                   NodePoly::new_open);
-    n!(create_radial_gradient,           Gradient,                   NodeGradient::new_radial);
+    n!(create_radial_gradient,           RadialGradient,             NodeRadialGradient::default);
     n!(create_rect,                      Rect,                       NodeRect::default);
     n!(create_specular_lighting,         FeSpecularLighting,         Lighting::new_specular);
     n!(create_spot_light,                SpotLight,                  LightSource::new_spot_light);
diff --git a/rsvg_internals/src/drawing_ctx.rs b/rsvg_internals/src/drawing_ctx.rs
index da4c1645..08cb19b6 100644
--- a/rsvg_internals/src/drawing_ctx.rs
+++ b/rsvg_internals/src/drawing_ctx.rs
@@ -13,7 +13,7 @@ use crate::coord_units::CoordUnits;
 use crate::dpi::Dpi;
 use crate::error::RenderingError;
 use crate::filters;
-use crate::gradient::NodeGradient;
+use crate::gradient::{NodeLinearGradient, NodeRadialGradient};
 use crate::length::Dasharray;
 use crate::mask::NodeMask;
 use crate::node::{CascadedValues, NodeDraw, NodeType, RsvgNode};
@@ -620,9 +620,13 @@ impl DrawingCtx {
                     let node = acquired.get();
 
                     had_paint_server = match node.borrow().get_type() {
-                        NodeType::Gradient => node
+                        NodeType::LinearGradient => node
                             .borrow()
-                            .get_impl::<NodeGradient>()
+                            .get_impl::<NodeLinearGradient>()
+                            .resolve_fallbacks_and_set_pattern(&node, self, opacity, bbox)?,
+                        NodeType::RadialGradient => node
+                            .borrow()
+                            .get_impl::<NodeRadialGradient>()
                             .resolve_fallbacks_and_set_pattern(&node, self, opacity, bbox)?,
                         NodeType::Pattern => node
                             .borrow()
diff --git a/rsvg_internals/src/gradient.rs b/rsvg_internals/src/gradient.rs
index bb9f1f42..78bfe474 100644
--- a/rsvg_internals/src/gradient.rs
+++ b/rsvg_internals/src/gradient.rs
@@ -185,56 +185,6 @@ enum Variant {
 }
 
 impl UnresolvedVariant {
-    fn default_linear() -> UnresolvedVariant {
-        UnresolvedVariant::Linear {
-            x1: Default::default(),
-            y1: Default::default(),
-            x2: Default::default(),
-            y2: Default::default(),
-        }
-    }
-
-    fn default_radial() -> UnresolvedVariant {
-        UnresolvedVariant::Radial {
-            cx: Default::default(),
-            cy: Default::default(),
-            r: Default::default(),
-            fx: Default::default(),
-            fy: Default::default(),
-        }
-    }
-
-    fn set_atts(&mut self, pbag: &PropertyBag<'_>) -> NodeResult {
-        match self {
-            &mut UnresolvedVariant::Linear { ref mut x1, ref mut y1, ref mut x2, ref mut y2 } => {
-                for (attr, value) in pbag.iter() {
-                    match attr {
-                        local_name!("x1") => *x1 = Some(attr.parse(value)?),
-                        local_name!("y1") => *y1 = Some(attr.parse(value)?),
-                        local_name!("x2") => *x2 = Some(attr.parse(value)?),
-                        local_name!("y2") => *y2 = Some(attr.parse(value)?),
-                        _ => (),
-                    }
-                }
-            }
-
-            &mut UnresolvedVariant::Radial { ref mut cx, ref mut cy, ref mut r, ref mut fx, ref mut fy } => {
-                for (attr, value) in pbag.iter() {
-                    match attr {
-                        local_name!("cx") => *cx = Some(attr.parse(value)?),
-                        local_name!("cy") => *cy = Some(attr.parse(value)?),
-                        local_name!("r") => *r = Some(attr.parse(value)?),
-                        local_name!("fx") => *fx = Some(attr.parse(value)?),
-                        local_name!("fy") => *fy = Some(attr.parse(value)?),
-                        _ => (),
-                    }
-                }
-            }
-        }
-
-        Ok(())
-    }
-
     fn to_resolved(self) -> Variant {
         assert!(self.is_resolved());
 
@@ -345,12 +295,31 @@ impl Variant {
     }
 }
 
-pub struct NodeGradient {
+#[derive(Default)]
+pub struct NodeLinearGradient {
     units: Option<GradientUnits>,
     affine: Option<cairo::Matrix>,
     spread: Option<SpreadMethod>,
 
-    variant: UnresolvedVariant,
+    x1: Option<LengthHorizontal>,
+    y1: Option<LengthVertical>,
+    x2: Option<LengthHorizontal>,
+    y2: Option<LengthVertical>,
+
+    fallback: Option<Fragment>,
+}
+
+#[derive(Default)]
+pub struct NodeRadialGradient {
+    units: Option<GradientUnits>,
+    affine: Option<cairo::Matrix>,
+    spread: Option<SpreadMethod>,
+
+    cx: Option<LengthHorizontal>,
+    cy: Option<LengthVertical>,
+    r: Option<LengthBoth>,
+    fx: Option<LengthHorizontal>,
+    fy: Option<LengthVertical>,
 
     fallback: Option<Fragment>,
 }
@@ -448,7 +417,9 @@ impl UnresolvedGradient {
     }
 
     fn add_color_stops_from_node(&mut self, node: &RsvgNode) {
-        assert!(node.borrow().get_type() == NodeType::Gradient);
+        let node_type = node.borrow().get_type();
+
+        assert!(node_type == NodeType::LinearGradient || node_type == NodeType::RadialGradient);
 
         for child_node in node.children() {
             let child = child_node.borrow();
@@ -508,34 +479,44 @@ struct Unresolved {
     fallback: Option<Fragment>,
 }
 
-impl NodeGradient {
-    pub fn new_linear() -> NodeGradient {
-        NodeGradient {
-            units: Default::default(),
-            affine: Default::default(),
-            spread: Default::default(),
-            variant: UnresolvedVariant::default_linear(),
-            fallback: Default::default(),
-        }
-    }
+impl NodeLinearGradient {
+    fn get_unresolved(&self, node: &RsvgNode) -> Unresolved {
+        let mut gradient = UnresolvedGradient {
+            units: self.units,
+            affine: self.affine,
+            spread: self.spread,
+            stops: None,
+            variant: UnresolvedVariant::Linear {
+                x1: self.x1,
+                y1: self.y1,
+                x2: self.x2,
+                y2: self.y2,
+            },
+        };
 
-    pub fn new_radial() -> NodeGradient {
-        NodeGradient {
-            units: Default::default(),
-            affine: Default::default(),
-            spread: Default::default(),
-            variant: UnresolvedVariant::default_radial(),
-            fallback: Default::default(),
+        gradient.add_color_stops_from_node(node);
+
+        Unresolved {
+            gradient,
+            fallback: self.fallback.clone(),
         }
     }
+}
 
+impl NodeRadialGradient {
     fn get_unresolved(&self, node: &RsvgNode) -> Unresolved {
         let mut gradient = UnresolvedGradient {
             units: self.units,
             affine: self.affine,
             spread: self.spread,
             stops: None,
-            variant: self.variant,
+            variant: UnresolvedVariant::Radial {
+                cx: self.cx,
+                cy: self.cy,
+                r: self.r,
+                fx: self.fx,
+                fy: self.fy,
+            },
         };
 
         gradient.add_color_stops_from_node(node);
@@ -547,27 +528,45 @@ impl NodeGradient {
     }
 }
 
-impl NodeTrait for NodeGradient {
+impl NodeTrait for NodeLinearGradient {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
             match attr {
                 local_name!("gradientUnits") => self.units = Some(attr.parse(value)?),
                 local_name!("gradientTransform") => self.affine = Some(attr.parse(value)?),
                 local_name!("spreadMethod") => self.spread = Some(attr.parse(value)?),
+                local_name!("xlink:href") => {
+                    self.fallback = Some(Fragment::parse(value).attribute(attr)?)
+                }
+                local_name!("x1") => self.x1 = Some(attr.parse(value)?),
+                local_name!("y1") => self.y1 = Some(attr.parse(value)?),
+                local_name!("x2") => self.x2 = Some(attr.parse(value)?),
+                local_name!("y2") => self.y2 = Some(attr.parse(value)?),
+
                 _ => (),
             }
         }
 
-        match self.variant {
-            UnresolvedVariant::Linear { .. } => self.variant.set_atts(pbag)?,
-            UnresolvedVariant::Radial { .. } => self.variant.set_atts(pbag)?,
-        }
+        Ok(())
+    }
+}
 
+impl NodeTrait for NodeRadialGradient {
+    fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
             match attr {
+                local_name!("gradientUnits") => self.units = Some(attr.parse(value)?),
+                local_name!("gradientTransform") => self.affine = Some(attr.parse(value)?),
+                local_name!("spreadMethod") => self.spread = Some(attr.parse(value)?),
                 local_name!("xlink:href") => {
                     self.fallback = Some(Fragment::parse(value).attribute(attr)?)
                 }
+                local_name!("cx") => self.cx = Some(attr.parse(value)?),
+                local_name!("cy") => self.cy = Some(attr.parse(value)?),
+                local_name!("r") => self.r = Some(attr.parse(value)?),
+                local_name!("fx") => self.fx = Some(attr.parse(value)?),
+                local_name!("fy") => self.fy = Some(attr.parse(value)?),
+
                 _ => (),
             }
         }
@@ -576,46 +575,74 @@ impl NodeTrait for NodeGradient {
     }
 }
 
-impl PaintSource for NodeGradient {
-    type Resolved = Gradient;
-
-    fn resolve(
-        &self,
-        node: &RsvgNode,
-        draw_ctx: &mut DrawingCtx,
-    ) -> Result<Self::Resolved, PaintServerError> {
-        let Unresolved { mut gradient, mut fallback } = self.get_unresolved(node);
-
-        let mut stack = NodeStack::new();
-
-        while !gradient.is_resolved() {
-            if let Some(fragment) = fallback {
-                let acquired = acquire_gradient(draw_ctx, &fragment)?;
-                let acquired_node = acquired.get();
-
-                if stack.contains(acquired_node) {
-                    return Err(PaintServerError::CircularReference(fragment.clone()));
+macro_rules! impl_paint_source {
+    ($gradient:ty, $node_type:pat, $other_gradient:ty, $other_type:pat,) => {
+        impl PaintSource for $gradient {
+            type Resolved = Gradient;
+
+            fn resolve(
+                &self,
+                node: &RsvgNode,
+                draw_ctx: &mut DrawingCtx,
+            ) -> Result<Self::Resolved, PaintServerError> {
+                let Unresolved { mut gradient, mut fallback } = self.get_unresolved(node);
+
+                let mut stack = NodeStack::new();
+
+                while !gradient.is_resolved() {
+                    if let Some(fragment) = fallback {
+                        let acquired = acquire_gradient(draw_ctx, &fragment)?;
+                        let acquired_node = acquired.get();
+
+                        if stack.contains(acquired_node) {
+                            return Err(PaintServerError::CircularReference(fragment.clone()));
+                        }
+
+                        let borrowed_node = acquired_node.borrow();
+                        let unresolved = match borrowed_node.get_type() {
+                            $node_type => {
+                                let a_gradient = borrowed_node.get_impl::<$gradient>();
+                                a_gradient.get_unresolved(&acquired_node)
+                            }
+
+                            $other_type => {
+                                let a_gradient = borrowed_node.get_impl::<$other_gradient>();
+                                a_gradient.get_unresolved(&acquired_node)
+                            }
+
+                            _ => unreachable!()
+                        };
+
+                        gradient = gradient.resolve_from_fallback(&unresolved.gradient);
+                        fallback = unresolved.fallback;
+
+                        stack.push(acquired_node);
+                    } else {
+                        gradient = gradient.resolve_from_defaults();
+                        break;
+                    }
                 }
 
-                let borrowed_node = acquired_node.borrow();
-                let a_gradient = borrowed_node.get_impl::<NodeGradient>();
-
-                let unresolved = a_gradient.get_unresolved(&acquired_node);
-
-                gradient = gradient.resolve_from_fallback(&unresolved.gradient);
-                fallback = unresolved.fallback;
-
-                stack.push(acquired_node);
-            } else {
-                gradient = gradient.resolve_from_defaults();
-                break;
+                Ok(gradient.to_resolved())
             }
         }
-
-        Ok(gradient.to_resolved())
     }
 }
 
+impl_paint_source!(
+    NodeLinearGradient,
+    NodeType::LinearGradient,
+    NodeRadialGradient,
+    NodeType::RadialGradient,
+);
+
+impl_paint_source!(
+    NodeRadialGradient,
+    NodeType::RadialGradient,
+    NodeLinearGradient,
+    NodeType::LinearGradient,
+);
+
 impl ResolvedPaintSource for Gradient {
     fn set_pattern_on_draw_context(
         self,
@@ -711,10 +738,10 @@ fn acquire_gradient<'a>(
         .and_then(|acquired| {
             let node_type = acquired.get().borrow().get_type();
 
-            if node_type == NodeType::Gradient {
-                Ok(acquired)
-            } else {
-                Err(PaintServerError::InvalidLinkType(fragment.clone()))
+            match node_type {
+                NodeType::LinearGradient => Ok(acquired),
+                NodeType::RadialGradient => Ok(acquired),
+                _ => Err(PaintServerError::InvalidLinkType(fragment.clone()))
             }
         })
 }
@@ -756,29 +783,29 @@ mod tests {
     #[test]
     fn gradient_resolved_from_defaults_is_really_resolved() {
         let node = RsvgNode::new(NodeData::new(
-            NodeType::Gradient,
+            NodeType::LinearGradient,
             local_name!("linearGradient"),
             None,
             None,
-            Box::new(NodeGradient::new_linear())
+            Box::new(NodeLinearGradient::default())
         ));
 
         let borrow = node.borrow();
-        let g = borrow.get_impl::<NodeGradient>();
+        let g = borrow.get_impl::<NodeLinearGradient>();
         let Unresolved { gradient, .. } = g.get_unresolved(&node);
         let gradient = gradient.resolve_from_defaults();
         assert!(gradient.is_resolved());
 
         let node = RsvgNode::new(NodeData::new(
-            NodeType::Gradient,
+            NodeType::RadialGradient,
             local_name!("radialGradient"),
             None,
             None,
-            Box::new(NodeGradient::new_radial())
+            Box::new(NodeRadialGradient::default())
         ));
 
         let borrow = node.borrow();
-        let g = borrow.get_impl::<NodeGradient>();
+        let g = borrow.get_impl::<NodeRadialGradient>();
         let Unresolved { gradient, .. } = g.get_unresolved(&node);
         let gradient = gradient.resolve_from_defaults();
         assert!(gradient.is_resolved());
diff --git a/rsvg_internals/src/node.rs b/rsvg_internals/src/node.rs
index 7ff22d7a..fa3f7b26 100644
--- a/rsvg_internals/src/node.rs
+++ b/rsvg_internals/src/node.rs
@@ -406,10 +406,10 @@ pub enum NodeType {
     DistantLight,
     Ellipse,
     Filter,
-    Gradient,
     Group,
     Image,
     Line,
+    LinearGradient,
     Link,
     Marker,
     Mask,
@@ -419,6 +419,7 @@ pub enum NodeType {
     PointLight,
     Polygon,
     Polyline,
+    RadialGradient,
     Rect,
     SpotLight,
     Stop,


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