[librsvg] structure.rs: Completely move NodeUse, NodeSymbol to Rust



commit 2b1c4020c51015b3d6508e7fb477314db7a25139
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue May 16 18:01:22 2017 -0500

    structure.rs: Completely move NodeUse, NodeSymbol to Rust
    
    rsvg-structure.c is no more.  Yay!

 Makefile.am           |    8 +-
 rsvg-base.c           |    4 +-
 rsvg-cairo-render.c   |    2 +-
 rsvg-defs.h           |    1 +
 rsvg-image.c          |    1 +
 rsvg-structure.c      |  240 -------------------------------------------------
 rsvg-structure.h      |   15 ++--
 rust/src/lib.rs       |    2 +
 rust/src/strtod.rs    |  174 -----------------------------------
 rust/src/structure.rs |  221 +++++++++++++++++++++++++++++++++++++++++++++
 10 files changed, 240 insertions(+), 428 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index a96208c..340e8e1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -41,7 +41,6 @@ librsvg_@RSVG_API_MAJOR_VERSION@_la_SOURCES = \
        rsvg-mask.c             \
        rsvg-mask.h             \
        rsvg-shapes.h           \
-       rsvg-structure.c        \
        rsvg-structure.h        \
        rsvg-styles.c           \
        rsvg-styles.h           \
@@ -76,21 +75,22 @@ RUST_SOURCES =                                      \
        rust/src/cnode.rs                       \
        rust/src/drawing_ctx.rs                 \
        rust/src/error.rs                       \
-       rust/src/handle.rs                      \
        rust/src/gradient.rs                    \
+       rust/src/handle.rs                      \
        rust/src/length.rs                      \
+       rust/src/lib.rs                         \
        rust/src/marker.rs                      \
        rust/src/node.rs                        \
        rust/src/paint_server.rs                \
-       rust/src/pt.rs                          \
        rust/src/parsers.rs                     \
        rust/src/parse_transform.lalrpop        \
        rust/src/path_builder.rs                \
        rust/src/path_parser.rs                 \
        rust/src/pattern.rs                     \
        rust/src/property_bag.rs                \
-       rust/src/state.rs                       \
+       rust/src/pt.rs                          \
        rust/src/shapes.rs                      \
+       rust/src/state.rs                       \
        rust/src/structure.rs                   \
        rust/src/transform.rs                   \
        rust/src/util.rs                        \
diff --git a/rsvg-base.c b/rsvg-base.c
index 23ef4da..114e8ec 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -327,13 +327,13 @@ static const NodeCreator node_creators[] = {
     { "subImageRef",         FALSE, rsvg_new_image },
     { "svg",                 TRUE,  rsvg_node_svg_new },
     { "switch",              TRUE,  rsvg_node_switch_new },
-    { "symbol",              TRUE,  rsvg_new_symbol },
+    { "symbol",              TRUE,  rsvg_node_symbol_new },
     { "text",                TRUE,  rsvg_new_text },
     /* "textPath",           TRUE,  */
     /* "title",              TRUE,  */
     { "tref",                TRUE,  rsvg_new_tref },
     { "tspan",               TRUE,  rsvg_new_tspan },
-    { "use",                 TRUE,  rsvg_new_use },
+    { "use",                 TRUE,  rsvg_node_use_new },
     /* "view",               FALSE, */
     /* "vkern",              FALSE, */
 };
diff --git a/rsvg-cairo-render.c b/rsvg-cairo-render.c
index 48c3507..22a319c 100644
--- a/rsvg-cairo-render.c
+++ b/rsvg-cairo-render.c
@@ -32,7 +32,7 @@
 #include <string.h>
 
 #include "rsvg.h"
-#include "rsvg-private.h"
+#include "rsvg-defs.h"
 #include "rsvg-cairo.h"
 #include "rsvg-cairo-draw.h"
 #include "rsvg-cairo-render.h"
diff --git a/rsvg-defs.h b/rsvg-defs.h
index 74c7925..b5dd0f7 100644
--- a/rsvg-defs.h
+++ b/rsvg-defs.h
@@ -32,6 +32,7 @@
 #include <glib.h>
 
 #include "rsvg.h"
+#include "rsvg-private.h"
 
 G_BEGIN_DECLS 
 
diff --git a/rsvg-image.c b/rsvg-image.c
index c8a4297..b43954f 100644
--- a/rsvg-image.c
+++ b/rsvg-image.c
@@ -35,6 +35,7 @@
 #include <errno.h>
 #include "rsvg-css.h"
 #include "rsvg-io.h"
+#include "rsvg-styles.h"
 
 cairo_surface_t *
 rsvg_cairo_surface_new_from_href (RsvgHandle *handle,
diff --git a/rsvg-structure.h b/rsvg-structure.h
index 077ce63..aaa4311 100644
--- a/rsvg-structure.h
+++ b/rsvg-structure.h
@@ -31,16 +31,9 @@
 #define RSVG_STRUCTURE_H
 
 #include "rsvg-private.h"
-#include "rsvg-defs.h"
-#include "rsvg-styles.h"
 
 G_BEGIN_DECLS 
 
-G_GNUC_INTERNAL
-RsvgNode *rsvg_new_use (const char *element_name, RsvgNode *parent);
-G_GNUC_INTERNAL
-RsvgNode *rsvg_new_symbol (const char *element_name, RsvgNode *parent);
-
 /* Implemented in rust/src/structure.rs */
 G_GNUC_INTERNAL
 RsvgNode *rsvg_node_group_new (const char *element_name, RsvgNode *parent);
@@ -59,6 +52,14 @@ RsvgNode *rsvg_node_svg_new (const char *element_name, RsvgNode *parent);
 
 /* Implemented in rust/src/structure.rs */
 G_GNUC_INTERNAL
+RsvgNode *rsvg_node_use_new (const char *element_name, RsvgNode *parent);
+
+/* Implemented in rust/src/structure.rs */
+G_GNUC_INTERNAL
+RsvgNode *rsvg_node_symbol_new (const char *element_name, RsvgNode *parent);
+
+/* Implemented in rust/src/structure.rs */
+G_GNUC_INTERNAL
 void rsvg_node_svg_get_size (RsvgNode *node, RsvgLength *out_width, RsvgLength *out_height);
 
 /* Implemented in rust/src/structure.rs */
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 7e28e9e..deddb52 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -84,10 +84,12 @@ pub use structure::{
     rsvg_node_group_new,
     rsvg_node_defs_new,
     rsvg_node_switch_new,
+    rsvg_node_symbol_new,
     rsvg_node_svg_new,
     rsvg_node_svg_get_size,
     rsvg_node_svg_get_view_box,
     rsvg_node_svg_apply_atts,
+    rsvg_node_use_new,
 };
 
 pub use transform::{
diff --git a/rust/src/structure.rs b/rust/src/structure.rs
index 83a13ef..b7c51dc 100644
--- a/rust/src/structure.rs
+++ b/rust/src/structure.rs
@@ -4,6 +4,7 @@ extern crate libc;
 
 use self::glib::translate::*;
 
+use std::cell::RefCell;
 use std::cell::Cell;
 use std::ptr;
 
@@ -256,6 +257,212 @@ impl Drop for NodeSvg {
     }
 }
 
+/***** NodeUse *****/
+
+struct NodeUse {
+    link: RefCell<Option<String>>,
+    x:    Cell<RsvgLength>,
+    y:    Cell<RsvgLength>,
+    w:    Cell<Option<RsvgLength>>,
+    h:    Cell<Option<RsvgLength>>,
+}
+
+impl NodeUse {
+    fn new () -> NodeUse {
+        NodeUse {
+            link: RefCell::new (None),
+            x:    Cell::new (RsvgLength::default ()),
+            y:    Cell::new (RsvgLength::default ()),
+            w:    Cell::new (None),
+            h:    Cell::new (None)
+        }
+    }
+}
+
+impl NodeTrait for NodeUse {
+    fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
+        *self.link.borrow_mut () = property_bag::lookup (pbag, "xlink:href");
+
+        self.x.set (property_bag::length_or_default (pbag, "x", LengthDir::Horizontal)?);
+        self.y.set (property_bag::length_or_default (pbag, "y", LengthDir::Vertical)?);
+
+        let opt_w = property_bag::length_or_none (pbag, "width", LengthDir::Horizontal)?;
+        match opt_w {
+            Some (w) => {
+                if length_is_negative (&w) {
+                    return Err (NodeError::value_error ("width", "Must not be negative"));
+                } else {
+                    self.w.set (Some (w));
+                }
+            },
+
+            None => {
+                self.w.set (None);
+            }
+        }
+
+        let opt_h = property_bag::length_or_none (pbag, "height", LengthDir::Vertical)?;
+        match opt_h {
+            Some (h) => {
+                if length_is_negative (&h) {
+                    return Err (NodeError::value_error ("height", "Must not be negative"));
+                } else {
+                    self.h.set (Some (h));
+                }
+            },
+
+            None => {
+                self.h.set (None);
+            }
+        }
+
+        Ok (())
+    }
+
+    fn draw (&self, node: &RsvgNode, draw_ctx: *const RsvgDrawingCtx, dominate: i32) {
+        let link = self.link.borrow ();
+
+        if link.is_none () {
+            return;
+        }
+
+        let raw_child = drawing_ctx::acquire_node (draw_ctx, link.as_ref ().unwrap ());
+        if raw_child.is_null () {
+            return;
+        }
+
+        let child: &RsvgNode = unsafe { &*raw_child };
+        if Node::is_ancestor (node.clone (), child.clone ()) {
+            // or, if we're <use>'ing ourselves
+            drawing_ctx::release_node (draw_ctx, raw_child);
+            return;
+        }
+
+        let nx = self.x.get ().normalize (draw_ctx);
+        let ny = self.y.get ().normalize (draw_ctx);
+        let nw = self.w.get ().map (|l| l.normalize (draw_ctx));
+        let nh = self.h.get ().map (|l| l.normalize (draw_ctx));
+
+        // width or height set to 0 disables rendering of the element
+        // https://www.w3.org/TR/SVG/struct.html#UseElementWidthAttribute
+        if let Some (w) = nw {
+            if double_equals (w, 0.0) {
+                drawing_ctx::release_node (draw_ctx, raw_child);
+                return;
+            }
+        }
+
+        if let Some (h) = nh {
+            if double_equals (h, 0.0) {
+                drawing_ctx::release_node (draw_ctx, raw_child);
+                return;
+            }
+        }
+
+        drawing_ctx::state_reinherit_top (draw_ctx, node.get_state (), dominate);
+
+        let state = drawing_ctx::get_current_state (draw_ctx);
+
+        if child.get_type () != NodeType::Symbol {
+            let mut affine = drawing_ctx::get_current_state_affine (draw_ctx);
+            affine.translate (nx, ny);
+            drawing_ctx::set_current_state_affine (draw_ctx, affine);
+
+            let boxed_child = box_node (child.clone ());
+
+            drawing_ctx::push_discrete_layer (draw_ctx);
+            drawing_ctx::draw_node_from_stack (draw_ctx, boxed_child, 1);
+            drawing_ctx::pop_discrete_layer (draw_ctx);
+        } else {
+            child.with_impl (|symbol: &NodeSymbol| {
+                let vbox = symbol.vbox.get ();
+
+                if vbox.is_active () {
+                    // If attributes ‘width’ and/or ‘height’ are not specified, [...] use values of '100%' 
for these attributes.
+                    // From https://www.w3.org/TR/SVG/struct.html#UseElement in "If the ‘use’ element 
references a ‘symbol’ element"
+
+                    let nw = nw.unwrap_or (RsvgLength::parse ("100%", LengthDir::Horizontal).unwrap 
().normalize (draw_ctx));
+                    let nh = nh.unwrap_or (RsvgLength::parse ("100%", LengthDir::Vertical).unwrap 
().normalize (draw_ctx));
+
+                    let (x, y, w, h) = symbol.preserve_aspect_ratio.get ().compute (vbox.rect.width, 
vbox.rect.height,
+                                                                                    nx, ny, nw, nh);
+
+                    let mut affine = drawing_ctx::get_current_state_affine (draw_ctx);
+                    affine.translate (x, y);
+                    affine.scale (w / vbox.rect.width, h / vbox.rect.height);
+                    affine.translate (-vbox.rect.x, -vbox.rect.y);
+                    drawing_ctx::set_current_state_affine (draw_ctx, affine);
+
+                    drawing_ctx::push_view_box (draw_ctx, vbox.rect.width, vbox.rect.height);
+
+                    drawing_ctx::push_discrete_layer (draw_ctx);
+
+                    if !drawing_ctx::state_is_overflow (state) || (!drawing_ctx::state_has_overflow (state)
+                                                                   && drawing_ctx::state_is_overflow 
(child.get_state ())) {
+                        drawing_ctx::add_clipping_rect (draw_ctx, vbox.rect.x, vbox.rect.y, vbox.rect.width, 
vbox.rect.height);
+                    }
+                } else {
+                    let mut affine = drawing_ctx::get_current_state_affine (draw_ctx);
+                    affine.translate (nx, ny);
+                    drawing_ctx::set_current_state_affine (draw_ctx, affine);
+
+                    drawing_ctx::push_discrete_layer (draw_ctx);
+                }
+
+                drawing_ctx::state_push (draw_ctx);
+
+                child.draw_children (draw_ctx, 1);
+
+                drawing_ctx::state_pop (draw_ctx);
+                drawing_ctx::pop_discrete_layer (draw_ctx);
+
+                if vbox.is_active () {
+                    drawing_ctx::pop_view_box (draw_ctx);
+                }
+            });
+        }
+
+        drawing_ctx::release_node (draw_ctx, raw_child);
+    }
+
+    fn get_c_impl (&self) -> *const RsvgCNodeImpl {
+        unreachable! ();
+    }
+}
+
+/***** NodeSymbol *****/
+
+struct NodeSymbol {
+    preserve_aspect_ratio: Cell<AspectRatio>,
+    vbox:                  Cell<RsvgViewBox>
+}
+
+impl NodeSymbol {
+    fn new () -> NodeSymbol {
+        NodeSymbol {
+            preserve_aspect_ratio: Cell::new (AspectRatio::default ()),
+            vbox:                  Cell::new (RsvgViewBox::default ())
+        }
+    }
+}
+
+impl NodeTrait for NodeSymbol {
+    fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
+        self.preserve_aspect_ratio.set (property_bag::parse_or_default (pbag, "preserveAspectRatio")?);
+        self.vbox.set (property_bag::parse_or_default (pbag, "viewBox")?);
+
+        Ok (())
+    }
+
+    fn draw (&self, _: &RsvgNode, _: *const RsvgDrawingCtx, _: i32) {
+        // nothing
+    }
+
+    fn get_c_impl (&self) -> *const RsvgCNodeImpl {
+        unreachable! ();
+    }
+}
+
 /***** C Prototypes *****/
 
 #[no_mangle]
@@ -287,6 +494,20 @@ pub extern fn rsvg_node_svg_new (_: *const libc::c_char, raw_parent: *const Rsvg
 }
 
 #[no_mangle]
+pub extern fn rsvg_node_use_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
+    boxed_node_new (NodeType::Use,
+                    raw_parent,
+                    Box::new (NodeUse::new ()))
+}
+
+#[no_mangle]
+pub extern fn rsvg_node_symbol_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
+    boxed_node_new (NodeType::Symbol,
+                    raw_parent,
+                    Box::new (NodeSymbol::new ()))
+}
+
+#[no_mangle]
 pub extern fn rsvg_node_svg_get_size (raw_node: *const RsvgNode, out_width: *mut RsvgLength, out_height: 
*mut RsvgLength) {
     assert! (!raw_node.is_null ());
     let node: &RsvgNode = unsafe { & *raw_node };


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