[librsvg] Unfinished: Move the rest of rsvg-marker.c to Rust



commit fc90f896b813d711964ab289940f574ee5ecf44f
Author: Federico Mena Quintero <federico gnome org>
Date:   Mon Feb 27 11:15:17 2017 -0600

    Unfinished: Move the rest of rsvg-marker.c to Rust

 rsvg-base.c        |    2 +-
 rsvg-marker.c      |    4 +-
 rsvg-marker.h      |    6 ++
 rust/src/marker.rs |  171 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 179 insertions(+), 4 deletions(-)
---
diff --git a/rsvg-base.c b/rsvg-base.c
index 6fb33d3..8d8d9d3 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -307,7 +307,7 @@ static const NodeCreator node_creators[] = {
     { "image",               TRUE,  rsvg_new_image },
     { "line",                TRUE,  rsvg_node_line_new },
     { "linearGradient",      TRUE,  rsvg_new_linear_gradient },
-    { "marker",              TRUE,  rsvg_new_marker },
+    { "marker",              TRUE,  rsvg_node_marker_new },
     { "mask",                TRUE,  rsvg_new_mask },
     /* "metadata",           FALSE, */
     /* "missing-glyph",      TRUE,  */
diff --git a/rsvg-marker.c b/rsvg-marker.c
index 66e7ef7..9747d09 100644
--- a/rsvg-marker.c
+++ b/rsvg-marker.c
@@ -39,7 +39,7 @@
 #include <string.h>
 #include <math.h>
 #include <errno.h>
-
+#if 0
 typedef struct _RsvgMarker RsvgMarker;
 
 struct _RsvgMarker {
@@ -111,7 +111,7 @@ rsvg_new_marker (const char *element_name, RsvgNode *parent)
                                 rsvg_node_marker_draw,
                                 g_free);
 }
-
+#endif
 static gboolean
 draw_child (RsvgNode *node, gpointer data)
 {
diff --git a/rsvg-marker.h b/rsvg-marker.h
index 1571235..8a6e392 100644
--- a/rsvg-marker.h
+++ b/rsvg-marker.h
@@ -30,8 +30,14 @@
 
 G_BEGIN_DECLS 
 
+#if 0
 G_GNUC_INTERNAL
 RsvgNode    *rsvg_new_marker       (const char *element_name, RsvgNode *node);
+#endif
+
+/* Implemented in rust/src/marker.rs */
+G_GNUC_INTERNAL
+RsvgNode *rsvg_node_marker_new (const char *element_name, RsvgNode *parent);
 
 G_GNUC_INTERNAL
 void rsvg_marker_render (const char * marker_name, gdouble xpos, gdouble ypos, gdouble orient, gdouble 
linewidth, RsvgDrawingCtx * ctx);
diff --git a/rust/src/marker.rs b/rust/src/marker.rs
index d3ea3a3..8145710 100644
--- a/rust/src/marker.rs
+++ b/rust/src/marker.rs
@@ -2,10 +2,171 @@ extern crate libc;
 extern crate cairo;
 extern crate cairo_sys;
 
+use std::cell::Cell;
 use std::f64::consts::*;
-use path_builder::*;
+use std::fmt;
+use std::ptr;
+use std::str::FromStr;
+
+use aspect_ratio::*;
 use drawing_ctx::RsvgDrawingCtx;
+use handle::RsvgHandle;
+use length::*;
+use node::*;
+use path_builder::*;
+use parsers;
+use property_bag;
+use property_bag::*;
 use util::*;
+use viewbox::*;
+
+// markerUnits attribute: https://www.w3.org/TR/SVG/painting.html#MarkerElement
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+enum MarkerUnits {
+    UserSpaceOnUse,
+    StrokeWidth
+}
+
+impl Default for MarkerUnits {
+    fn default () -> MarkerUnits {
+        MarkerUnits::StrokeWidth
+    }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+struct MarkerUnitsParseError;
+
+impl fmt::Display for MarkerUnitsParseError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "string must be \"userSpaceOnUse\" or \"strokeWidth\"".fmt (f)
+    }
+}
+
+impl FromStr for MarkerUnits {
+    type Err = MarkerUnitsParseError;
+
+    fn from_str (s: &str) -> Result <MarkerUnits, MarkerUnitsParseError> {
+        match s {
+            "userSpaceOnUse" => Ok (MarkerUnits::UserSpaceOnUse),
+            "strokeWidth"    => Ok (MarkerUnits::StrokeWidth),
+            _                => Err (MarkerUnitsParseError)
+        }
+    }
+}
+
+// orient attribute: https://www.w3.org/TR/SVG/painting.html#MarkerElement
+
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+enum MarkerOrient {
+    Auto,
+    Degrees (f64)
+}
+
+impl Default for MarkerOrient {
+    fn default () -> MarkerOrient {
+        MarkerOrient::Degrees (0.0)
+    }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq)]
+struct MarkerOrientParseError;
+
+impl fmt::Display for MarkerOrientParseError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "string must be \"auto\" or a CSS angle".fmt (f)
+    }
+}
+
+impl FromStr for MarkerOrient {
+    type Err = MarkerOrientParseError;
+
+    fn from_str (s: &str) -> Result <MarkerOrient, MarkerOrientParseError> {
+        match s {
+            "auto" => Ok (MarkerOrient::Auto),
+            _      => parsers::angle_degrees (s).map (
+                |degrees| MarkerOrient::Degrees (degrees) ).map_err (
+                |_| MarkerOrientParseError)
+        }
+    }
+}
+
+// NodeMarker
+
+struct NodeMarker {
+    units:  Cell<MarkerUnits>,
+    ref_x:  Cell<RsvgLength>,
+    ref_y:  Cell<RsvgLength>,
+    width:  Cell<RsvgLength>,
+    height: Cell<RsvgLength>,
+    orient: Cell<MarkerOrient>,
+    aspect: Cell<AspectRatio>,
+    vbox:   Cell<RsvgViewBox>
+}
+
+impl NodeMarker {
+    fn new () -> NodeMarker {
+        NodeMarker {
+            units:  Cell::new (MarkerUnits::default ()),
+            ref_x:  Cell::new (RsvgLength::default ()),
+            ref_y:  Cell::new (RsvgLength::default ()),
+            width:  Cell::new (NodeMarker::get_default_size ()),
+            height: Cell::new (NodeMarker::get_default_size ()),
+            orient: Cell::new (MarkerOrient::default ()),
+            aspect: Cell::new (AspectRatio::default ()),
+            vbox:   Cell::new (RsvgViewBox::default ())
+        }
+    }
+
+    fn get_default_size () -> RsvgLength {
+        // per the spec
+        RsvgLength::parse ("3", LengthDir::Both)
+    }
+}
+
+impl NodeTrait for NodeMarker {
+    fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) {
+        self.units.set (property_bag::lookup (pbag, "markerUnits").map_or (MarkerUnits::default (),
+                                                                           |v| MarkerUnits::from_str 
(&v).unwrap_or (MarkerUnits::default ())));
+
+        self.ref_x.set (property_bag::lookup (pbag, "refX").map_or (RsvgLength::default (),
+                                                                    |v| RsvgLength::parse (&v, 
LengthDir::Horizontal)));
+        self.ref_y.set (property_bag::lookup (pbag, "refY").map_or (RsvgLength::default (),
+                                                                    |v| RsvgLength::parse (&v, 
LengthDir::Vertical)));
+
+        self.width.set (property_bag::lookup (pbag, "markerWidth").map_or (NodeMarker::get_default_size (),
+                                                                           |v| RsvgLength::parse (&v, 
LengthDir::Horizontal)));
+        self.height.set (property_bag::lookup (pbag, "markerHeight").map_or (NodeMarker::get_default_size (),
+                                                                             |v| RsvgLength::parse (&v, 
LengthDir::Vertical)));
+
+        self.orient.set (property_bag::lookup (pbag, "orient").map_or (MarkerOrient::default (),
+                                                                       |v| MarkerOrient::from_str 
(&v).unwrap_or (MarkerOrient::default ())));
+
+        self.aspect.set (property_bag::lookup (pbag, "preserveAspectRatio").map_or (AspectRatio::default (),
+                                                                                    |v| 
AspectRatio::from_str (&v).unwrap_or (AspectRatio::default ())));
+
+        self.vbox.set (property_bag::lookup (pbag, "viewBox").map_or (RsvgViewBox::default (),
+                                                                      |v| RsvgViewBox::from_str 
(&v).unwrap_or (RsvgViewBox::default ())));
+    }
+
+    fn draw (&self, _: &RsvgNode, _: *const RsvgDrawingCtx, _: i32) {
+        // nothing; markers are drawn by their referencing shapes
+    }
+
+    fn get_c_impl (&self) -> *const RsvgCNodeImpl {
+        ptr::null ()
+    }
+}
+
+#[no_mangle]
+pub extern fn rsvg_node_marker_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
+    boxed_node_new (NodeType::Marker,
+                    raw_parent,
+                    Box::new (NodeMarker::new ()))
+}
+
+// Machinery to figure out marker orientations
 
 #[derive(Debug, PartialEq)]
 pub enum Segment {
@@ -854,4 +1015,12 @@ mod tests {
         assert_eq! ((40.0, 30.0), (v1x, v1y));
         assert_eq! ((40.0, 30.0), (v2x, v2y));
     }
+
+    #[test]
+    fn parses_marker_units () {
+        assert_eq! (MarkerUnits::from_str ("foo"), Err (MarkerUnitsParseError));
+
+        assert_eq! (MarkerUnits::from_str ("userSpaceOnUse"), Ok (MarkerUnits::UserSpaceOnUse));
+        assert_eq! (MarkerUnits::from_str ("strokeWidth"),    Ok (MarkerUnits::StrokeWidth));
+    }
 }


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