[librsvg: 2/4] Use separate structs for light source nodes



commit 92f6d900a38aa42fa5e84c4edb3abb1870571294
Author: Paolo Borelli <pborelli gnome org>
Date:   Sat Oct 12 10:41:18 2019 +0200

    Use separate structs for light source nodes
    
    This way they can be created with default()

 rsvg_internals/src/create_node.rs                |  11 +-
 rsvg_internals/src/filters/light/light_source.rs | 285 ++++++++++-------------
 rsvg_internals/src/filters/light/lighting.rs     |  54 +++--
 3 files changed, 163 insertions(+), 187 deletions(-)
---
diff --git a/rsvg_internals/src/create_node.rs b/rsvg_internals/src/create_node.rs
index 2b722d0f..a63279c0 100644
--- a/rsvg_internals/src/create_node.rs
+++ b/rsvg_internals/src/create_node.rs
@@ -13,7 +13,10 @@ use crate::filters::{
     flood::Flood,
     gaussian_blur::GaussianBlur,
     image::Image,
-    light::{light_source::LightSource, lighting::Lighting},
+    light::{
+        light_source::DistantLight, light_source::PointLight, light_source::SpotLight,
+        lighting::Lighting,
+    },
     merge::{Merge, MergeNode},
     morphology::Morphology,
     node::NodeFilter,
@@ -66,7 +69,7 @@ mod creators {
     n!(create_convolve_matrix,           FeConvolveMatrix,           ConvolveMatrix::default);
     n!(create_defs,                      Defs,                       NodeNonRendering::default);
     n!(create_diffuse_lighting,          FeDiffuseLighting,          Lighting::new_diffuse);
-    n!(create_distant_light,             FeDistantLight,             LightSource::new_distant_light);
+    n!(create_distant_light,             FeDistantLight,             DistantLight::default);
     n!(create_displacement_map,          FeDisplacementMap,          DisplacementMap::default);
     n!(create_ellipse,                   Ellipse,                    NodeEllipse::default);
     n!(create_filter,                    Filter,                     NodeFilter::default);
@@ -87,13 +90,13 @@ mod creators {
     n!(create_offset,                    FeOffset,                   Offset::default);
     n!(create_path,                      Path,                       NodePath::default);
     n!(create_pattern,                   Pattern,                    NodePattern::default);
-    n!(create_point_light,               FePointLight,               LightSource::new_point_light);
+    n!(create_point_light,               FePointLight,               PointLight::default);
     n!(create_polygon,                   Polygon,                    NodePoly::new_closed);
     n!(create_polyline,                  Polyline,                   NodePoly::new_open);
     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,                FeSpotLight,                LightSource::new_spot_light);
+    n!(create_spot_light,                FeSpotLight,                SpotLight::default);
     n!(create_stop,                      Stop,                       NodeStop::default);
     n!(create_style,                     Style,                      NodeStyle::default);
     n!(create_svg,                       Svg,                        NodeSvg::default);
diff --git a/rsvg_internals/src/filters/light/light_source.rs 
b/rsvg_internals/src/filters/light/light_source.rs
index e8661346..1665ee79 100644
--- a/rsvg_internals/src/filters/light/light_source.rs
+++ b/rsvg_internals/src/filters/light/light_source.rs
@@ -9,32 +9,8 @@ use crate::parsers;
 use crate::property_bag::PropertyBag;
 use crate::util::clamp;
 
-/// A light source node (`feDistantLight`, `fePointLight` or `feSpotLight`).
-#[derive(Clone)]
+/// A light source with affine transformations applied.
 pub enum LightSource {
-    Distant {
-        azimuth: f64,
-        elevation: f64,
-    },
-    Point {
-        x: f64,
-        y: f64,
-        z: f64,
-    },
-    Spot {
-        x: f64,
-        y: f64,
-        z: f64,
-        points_at_x: f64,
-        points_at_y: f64,
-        points_at_z: f64,
-        specular_exponent: f64,
-        limiting_cone_angle: Option<f64>,
-    },
-}
-
-/// A light source node with affine transformations applied.
-pub enum TransformedLightSource {
     Distant {
         azimuth: f64,
         elevation: f64,
@@ -51,92 +27,11 @@ pub enum TransformedLightSource {
 }
 
 impl LightSource {
-    /// Constructs a new `feDistantLight` with empty properties.
-    #[inline]
-    pub fn new_distant_light() -> LightSource {
-        LightSource::Distant {
-            azimuth: 0.0,
-            elevation: 0.0,
-        }
-    }
-
-    /// Constructs a new `fePointLight` with empty properties.
-    #[inline]
-    pub fn new_point_light() -> LightSource {
-        LightSource::Point {
-            x: 0.0,
-            y: 0.0,
-            z: 0.0,
-        }
-    }
-
-    /// Constructs a new `feSpotLight` with empty properties.
-    #[inline]
-    pub fn new_spot_light() -> LightSource {
-        LightSource::Spot {
-            x: 0.0,
-            y: 0.0,
-            z: 0.0,
-            points_at_x: 0.0,
-            points_at_y: 0.0,
-            points_at_z: 0.0,
-            specular_exponent: 0.0,
-            limiting_cone_angle: None,
-        }
-    }
-
-    /// Returns a `TransformedLightSource` according to the given `FilterContext`.
-    #[inline]
-    pub fn transform(&self, ctx: &FilterContext) -> TransformedLightSource {
-        match *self {
-            LightSource::Distant { azimuth, elevation } => {
-                TransformedLightSource::Distant { azimuth, elevation }
-            }
-            LightSource::Point { x, y, z } => {
-                let (x, y) = ctx.paffine().transform_point(x, y);
-                let z = ctx.transform_dist(z);
-
-                TransformedLightSource::Point {
-                    origin: Vector3::new(x, y, z),
-                }
-            }
-            LightSource::Spot {
-                x,
-                y,
-                z,
-                points_at_x,
-                points_at_y,
-                points_at_z,
-                specular_exponent,
-                limiting_cone_angle,
-            } => {
-                let (x, y) = ctx.paffine().transform_point(x, y);
-                let z = ctx.transform_dist(z);
-                let (points_at_x, points_at_y) =
-                    ctx.paffine().transform_point(points_at_x, points_at_y);
-                let points_at_z = ctx.transform_dist(points_at_z);
-
-                let origin = Vector3::new(x, y, z);
-                let mut direction = Vector3::new(points_at_x, points_at_y, points_at_z) - origin;
-                let _ = direction.try_normalize_mut(0.0);
-
-                TransformedLightSource::Spot {
-                    origin,
-                    direction,
-                    specular_exponent,
-                    limiting_cone_angle,
-                }
-            }
-        }
-    }
-}
-
-impl TransformedLightSource {
     /// Returns the unit (or null) vector from the image sample to the light.
     #[inline]
     pub fn vector(&self, x: f64, y: f64, z: f64) -> Vector3<f64> {
         match self {
-            TransformedLightSource::Distant { azimuth, elevation } => {
+            LightSource::Distant { azimuth, elevation } => {
                 let azimuth = azimuth.to_radians();
                 let elevation = elevation.to_radians();
                 Vector3::new(
@@ -145,8 +40,7 @@ impl TransformedLightSource {
                     elevation.sin(),
                 )
             }
-            TransformedLightSource::Point { origin }
-            | TransformedLightSource::Spot { origin, .. } => {
+            LightSource::Point { origin } | LightSource::Spot { origin, .. } => {
                 let mut v = origin - Vector3::new(x, y, z);
                 let _ = v.try_normalize_mut(0.0);
                 v
@@ -162,7 +56,7 @@ impl TransformedLightSource {
         light_vector: Vector3<f64>,
     ) -> cssparser::RGBA {
         match self {
-            TransformedLightSource::Spot {
+            LightSource::Spot {
                 direction,
                 specular_exponent,
                 limiting_cone_angle,
@@ -194,60 +88,127 @@ impl TransformedLightSource {
     }
 }
 
-impl NodeTrait for LightSource {
+#[derive(Default)]
+pub struct DistantLight {
+    azimuth: f64,
+    elevation: f64,
+}
+
+impl DistantLight {
+    pub fn transform(&self, _ctx: &FilterContext) -> LightSource {
+        LightSource::Distant {
+            azimuth: self.azimuth,
+            elevation: self.elevation,
+        }
+    }
+}
+
+impl NodeTrait for DistantLight {
     fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
         for (attr, value) in pbag.iter() {
-            match *self {
-                LightSource::Distant {
-                    ref mut azimuth,
-                    ref mut elevation,
-                } => match attr {
-                    local_name!("azimuth") => *azimuth = parsers::number(value).attribute(attr)?,
-                    local_name!("elevation") => {
-                        *elevation = parsers::number(value).attribute(attr)?
-                    }
-                    _ => (),
-                },
-                LightSource::Point {
-                    ref mut x,
-                    ref mut y,
-                    ref mut z,
-                } => match attr {
-                    local_name!("x") => *x = parsers::number(value).attribute(attr)?,
-                    local_name!("y") => *y = parsers::number(value).attribute(attr)?,
-                    local_name!("z") => *z = parsers::number(value).attribute(attr)?,
-                    _ => (),
-                },
-                LightSource::Spot {
-                    ref mut x,
-                    ref mut y,
-                    ref mut z,
-                    ref mut points_at_x,
-                    ref mut points_at_y,
-                    ref mut points_at_z,
-                    ref mut specular_exponent,
-                    ref mut limiting_cone_angle,
-                } => match attr {
-                    local_name!("x") => *x = parsers::number(value).attribute(attr)?,
-                    local_name!("y") => *y = parsers::number(value).attribute(attr)?,
-                    local_name!("z") => *z = parsers::number(value).attribute(attr)?,
-                    local_name!("pointsAtX") => {
-                        *points_at_x = parsers::number(value).attribute(attr)?
-                    }
-                    local_name!("pointsAtY") => {
-                        *points_at_y = parsers::number(value).attribute(attr)?
-                    }
-                    local_name!("pointsAtZ") => {
-                        *points_at_z = parsers::number(value).attribute(attr)?
-                    }
-                    local_name!("specularExponent") => {
-                        *specular_exponent = parsers::number(value).attribute(attr)?
-                    }
-                    local_name!("limitingConeAngle") => {
-                        *limiting_cone_angle = Some(parsers::number(value).attribute(attr)?)
-                    }
-                    _ => (),
-                },
+            match attr {
+                local_name!("azimuth") => self.azimuth = parsers::number(value).attribute(attr)?,
+                local_name!("elevation") => {
+                    self.elevation = parsers::number(value).attribute(attr)?
+                }
+                _ => (),
+            }
+        }
+
+        Ok(())
+    }
+}
+
+#[derive(Default)]
+pub struct PointLight {
+    x: f64,
+    y: f64,
+    z: f64,
+}
+
+impl PointLight {
+    pub fn transform(&self, ctx: &FilterContext) -> LightSource {
+        let (x, y) = ctx.paffine().transform_point(self.x, self.y);
+        let z = ctx.transform_dist(self.z);
+
+        LightSource::Point {
+            origin: Vector3::new(x, y, z),
+        }
+    }
+}
+
+impl NodeTrait for PointLight {
+    fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+        for (attr, value) in pbag.iter() {
+            match attr {
+                local_name!("x") => self.x = parsers::number(value).attribute(attr)?,
+                local_name!("y") => self.y = parsers::number(value).attribute(attr)?,
+                local_name!("z") => self.z = parsers::number(value).attribute(attr)?,
+                _ => (),
+            }
+        }
+
+        Ok(())
+    }
+}
+
+#[derive(Default)]
+pub struct SpotLight {
+    x: f64,
+    y: f64,
+    z: f64,
+    points_at_x: f64,
+    points_at_y: f64,
+    points_at_z: f64,
+    specular_exponent: f64,
+    limiting_cone_angle: Option<f64>,
+}
+
+impl SpotLight {
+    pub fn transform(&self, ctx: &FilterContext) -> LightSource {
+        let (x, y) = ctx.paffine().transform_point(self.x, self.y);
+        let z = ctx.transform_dist(self.z);
+        let (points_at_x, points_at_y) = ctx
+            .paffine()
+            .transform_point(self.points_at_x, self.points_at_y);
+        let points_at_z = ctx.transform_dist(self.points_at_z);
+
+        let origin = Vector3::new(x, y, z);
+        let mut direction = Vector3::new(points_at_x, points_at_y, points_at_z) - origin;
+        let _ = direction.try_normalize_mut(0.0);
+
+        LightSource::Spot {
+            origin,
+            direction,
+            specular_exponent: self.specular_exponent,
+            limiting_cone_angle: self.limiting_cone_angle,
+        }
+    }
+}
+
+impl NodeTrait for SpotLight {
+    fn set_atts(&mut self, _: Option<&RsvgNode>, pbag: &PropertyBag<'_>) -> NodeResult {
+        for (attr, value) in pbag.iter() {
+            match attr {
+                local_name!("x") => self.x = parsers::number(value).attribute(attr)?,
+                local_name!("y") => self.y = parsers::number(value).attribute(attr)?,
+                local_name!("z") => self.z = parsers::number(value).attribute(attr)?,
+                local_name!("pointsAtX") => {
+                    self.points_at_x = parsers::number(value).attribute(attr)?
+                }
+                local_name!("pointsAtY") => {
+                    self.points_at_y = parsers::number(value).attribute(attr)?
+                }
+                local_name!("pointsAtZ") => {
+                    self.points_at_z = parsers::number(value).attribute(attr)?
+                }
+                local_name!("specularExponent") => {
+                    self.specular_exponent = parsers::number(value).attribute(attr)?
+                }
+                local_name!("limitingConeAngle") => {
+                    self.limiting_cone_angle = Some(parsers::number(value).attribute(attr)?)
+                }
+                _ => (),
             }
         }
 
diff --git a/rsvg_internals/src/filters/light/lighting.rs b/rsvg_internals/src/filters/light/lighting.rs
index 3d3d01bc..4e01de46 100644
--- a/rsvg_internals/src/filters/light/lighting.rs
+++ b/rsvg_internals/src/filters/light/lighting.rs
@@ -17,7 +17,10 @@ use crate::filters::{
         bottom_row_normal,
         interior_normal,
         left_column_normal,
+        light_source::DistantLight,
         light_source::LightSource,
+        light_source::PointLight,
+        light_source::SpotLight,
         right_column_normal,
         top_left_normal,
         top_right_normal,
@@ -209,27 +212,7 @@ impl Filter for Lighting {
             cssparser::Color::RGBA(rgba) => rgba,
         };
 
-        let mut light_sources = node
-            .children()
-            .rev()
-            .filter(|c| match c.borrow().get_type() {
-                NodeType::FeDistantLight | NodeType::FePointLight | NodeType::FeSpotLight => true,
-                _ => false,
-            });
-
-        let light_source = light_sources.next();
-        if light_source.is_none() || light_sources.next().is_some() {
-            return Err(FilterError::InvalidLightSourceCount);
-        }
-
-        let light_source = light_source.unwrap();
-        if light_source.borrow().is_in_error() {
-            return Err(FilterError::ChildNodeInError);
-        }
-
-        let node_data = light_source.borrow();
-        let light_source = node_data.get_impl::<LightSource>().transform(ctx);
-
+        let light_source = find_light_source(node, ctx)?;
         let mut input_surface = input.surface().clone();
 
         if let Some((ox, oy)) = scale {
@@ -487,6 +470,35 @@ impl Filter for Lighting {
     }
 }
 
+fn find_light_source(node: &RsvgNode, ctx: &FilterContext) -> Result<LightSource, FilterError> {
+    let mut light_sources = node
+        .children()
+        .rev()
+        .filter(|c| match c.borrow().get_type() {
+            NodeType::FeDistantLight | NodeType::FePointLight | NodeType::FeSpotLight => true,
+            _ => false,
+        });
+
+    let node = light_sources.next();
+    if node.is_none() || light_sources.next().is_some() {
+        return Err(FilterError::InvalidLightSourceCount);
+    }
+
+    let node = node.unwrap();
+    if node.borrow().is_in_error() {
+        return Err(FilterError::ChildNodeInError);
+    }
+
+    let light_source = match node.borrow().get_type() {
+        NodeType::FeDistantLight => node.borrow().get_impl::<DistantLight>().transform(ctx),
+        NodeType::FePointLight => node.borrow().get_impl::<PointLight>().transform(ctx),
+        NodeType::FeSpotLight => node.borrow().get_impl::<SpotLight>().transform(ctx),
+        _ => unreachable!(),
+    };
+
+    Ok(light_source)
+}
+
 impl Default for Lighting {
     #[inline]
     fn default() -> Self {


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