[librsvg] structure.rs: Finish moving NodeSvg over to Rust. Yay!



commit 91ef809cb41fcf7b20f53bd236053b3a39f336a9
Author: Federico Mena Quintero <federico gnome org>
Date:   Wed Mar 22 16:29:33 2017 -0600

    structure.rs: Finish moving NodeSvg over to Rust.  Yay!

 rsvg-base.c           |    8 +--
 rsvg-structure.c      |  193 -----------------------------------------------
 rsvg-structure.h      |   11 ++-
 rust/src/lib.rs       |    4 +
 rust/src/structure.rs |  201 +++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 214 insertions(+), 203 deletions(-)
---
diff --git a/rsvg-base.c b/rsvg-base.c
index 07c59f5..23ef4da 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -325,7 +325,7 @@ static const NodeCreator node_creators[] = {
     /* "style",              FALSE, */
     { "subImage",            FALSE, rsvg_node_group_new },
     { "subImageRef",         FALSE, rsvg_new_image },
-    { "svg",                 TRUE,  rsvg_new_svg },
+    { "svg",                 TRUE,  rsvg_node_svg_new },
     { "switch",              TRUE,  rsvg_node_switch_new },
     { "symbol",              TRUE,  rsvg_new_symbol },
     { "text",                TRUE,  rsvg_new_text },
@@ -843,12 +843,8 @@ rsvg_end_element (void *data, const xmlChar * xmlname)
 
         /* FIXMEchpe: shouldn't this check that currentnode == treebase or sth like that? */
         if (ctx->priv->treebase && !strcmp (name, "svg")) {
-            RsvgNodeSvg *svg;
-
             g_assert (rsvg_node_get_type (ctx->priv->treebase) == RSVG_NODE_TYPE_SVG);
-            svg = rsvg_rust_cnode_get_impl (ctx->priv->treebase);
-
-            _rsvg_node_svg_apply_atts (ctx->priv->treebase, svg, ctx);
+            rsvg_node_svg_apply_atts (ctx->priv->treebase, ctx);
         }
     }
 }
diff --git a/rsvg-structure.c b/rsvg-structure.c
index 991e62a..7dc13c9 100644
--- a/rsvg-structure.c
+++ b/rsvg-structure.c
@@ -47,199 +47,6 @@ struct _RsvgNodeUse {
     RsvgLength x, y, w, h;
 };
 
-struct _RsvgNodeSvg {
-    guint32 preserve_aspect_ratio;
-    RsvgLength x, y, w, h;
-    RsvgViewBox vbox;
-    RsvgPropertyBag *atts;
-};
-
-static gboolean
-draw_child (RsvgNode *node, gpointer data)
-{
-    RsvgDrawingCtx *ctx;
-
-    ctx = data;
-
-    rsvg_drawing_ctx_draw_node_from_stack (ctx, node, 0);
-
-    return TRUE;
-}
-
-static void
-rsvg_node_svg_draw (RsvgNode *node, gpointer impl, RsvgDrawingCtx *ctx, int dominate)
-{
-    RsvgNodeSvg *svg = impl;
-    RsvgState *state;
-    cairo_matrix_t affine, affine_old, affine_new;
-    double nx, ny, nw, nh;
-    RsvgNode *parent;
-
-    nx = rsvg_length_normalize (&svg->x, ctx);
-    ny = rsvg_length_normalize (&svg->y, ctx);
-    nw = rsvg_length_normalize (&svg->w, ctx);
-    nh = rsvg_length_normalize (&svg->h, ctx);
-
-    rsvg_state_reinherit_top (ctx, rsvg_node_get_state (node), dominate);
-
-    state = rsvg_current_state (ctx);
-
-    affine_old = state->affine;
-
-    if (svg->vbox.active) {
-        double x = nx, y = ny, w = nw, h = nh;
-        rsvg_aspect_ratio_compute (svg->preserve_aspect_ratio,
-                                   svg->vbox.rect.width,
-                                   svg->vbox.rect.height,
-                                   &x, &y, &w, &h);
-        cairo_matrix_init (&affine,
-                           w / svg->vbox.rect.width,
-                           0,
-                           0,
-                           h / svg->vbox.rect.height,
-                           x - svg->vbox.rect.x * w / svg->vbox.rect.width,
-                           y - svg->vbox.rect.y * h / svg->vbox.rect.height);
-        cairo_matrix_multiply (&state->affine, &affine, &state->affine);
-        rsvg_drawing_ctx_push_view_box (ctx, svg->vbox.rect.width, svg->vbox.rect.height);
-    } else {
-        cairo_matrix_init_translate (&affine, nx, ny);
-        cairo_matrix_multiply (&state->affine, &affine, &state->affine);
-        rsvg_drawing_ctx_push_view_box (ctx, nw, nh);
-    }
-
-    affine_new = state->affine;
-
-    rsvg_push_discrete_layer (ctx);
-
-    /* Bounding box addition must be AFTER the discrete layer push,
-       which must be AFTER the transformation happens. */
-    parent = rsvg_node_get_parent (node);
-
-    if (!state->overflow && parent) {
-        state->affine = affine_old;
-        rsvg_drawing_ctx_add_clipping_rect (ctx, nx, ny, nw, nh);
-        state->affine = affine_new;
-    }
-
-    parent = rsvg_node_unref (parent);
-
-    rsvg_node_foreach_child (node, draw_child, ctx);
-
-    rsvg_pop_discrete_layer (ctx);
-    rsvg_drawing_ctx_pop_view_box (ctx);
-}
-
-static void
-rsvg_node_svg_set_atts (RsvgNode *node, gpointer impl, RsvgHandle *handle, RsvgPropertyBag *atts)
-{
-    const char *value;
-    RsvgNodeSvg *svg = impl;
-    RsvgNode *parent;
-
-    if ((value = rsvg_property_bag_lookup (atts, "viewBox")))
-        svg->vbox = rsvg_css_parse_vbox (value);
-
-    if ((value = rsvg_property_bag_lookup (atts, "preserveAspectRatio")))
-        svg->preserve_aspect_ratio = rsvg_aspect_ratio_parse (value);
-    if ((value = rsvg_property_bag_lookup (atts, "width")))
-        svg->w = rsvg_length_parse (value, LENGTH_DIR_HORIZONTAL);
-    if ((value = rsvg_property_bag_lookup (atts, "height")))
-        svg->h = rsvg_length_parse (value, LENGTH_DIR_VERTICAL);
-    /*
-     * x & y attributes have no effect on outermost svg
-     * http://www.w3.org/TR/SVG/struct.html#SVGElement
-     */
-    parent = rsvg_node_get_parent (node);
-
-    if (parent) {
-        if ((value = rsvg_property_bag_lookup (atts, "x")))
-            svg->x = rsvg_length_parse (value, LENGTH_DIR_HORIZONTAL);
-
-        if ((value = rsvg_property_bag_lookup (atts, "y")))
-            svg->y = rsvg_length_parse (value, LENGTH_DIR_VERTICAL);
-    }
-
-    parent = rsvg_node_unref (parent);
-
-    /*
-     * style element is not loaded yet here, so we need to store those attribues
-     * to be applied later.
-     */
-    svg->atts = rsvg_property_bag_dup (atts);
-}
-
-void
-rsvg_node_svg_get_size (RsvgNode *node, RsvgLength *out_width, RsvgLength *out_height)
-{
-    RsvgNodeSvg *svg;
-
-    g_assert (rsvg_node_get_type (node) == RSVG_NODE_TYPE_SVG);
-    svg = rsvg_rust_cnode_get_impl (node);
-
-    *out_width  = svg->w;
-    *out_height = svg->h;
-}
-
-RsvgViewBox
-rsvg_node_svg_get_view_box (RsvgNode *node)
-{
-    RsvgNodeSvg *svg;
-
-    g_assert (rsvg_node_get_type (node) == RSVG_NODE_TYPE_SVG);
-    svg = rsvg_rust_cnode_get_impl (node);
-
-    return svg->vbox;
-}
-
-void
-_rsvg_node_svg_apply_atts (RsvgNode *node, RsvgNodeSvg *svg, RsvgHandle *ctx)
-{
-    const char *id = NULL, *klazz = NULL, *value;
-    if (svg->atts && rsvg_property_bag_size (svg->atts)) {
-        if ((value = rsvg_property_bag_lookup (svg->atts, "class")))
-            klazz = value;
-        if ((value = rsvg_property_bag_lookup (svg->atts, "id")))
-            id = value;
-        rsvg_parse_style_attrs (ctx, node, "svg", klazz, id, svg->atts);
-    }
-}
-
-static void
-rsvg_node_svg_free (gpointer impl)
-{
-    RsvgNodeSvg *svg = impl;
-
-    if (svg->atts) {
-        rsvg_property_bag_free (svg->atts);
-        svg->atts = NULL;
-    }
-
-    g_free (svg);
-}
-
-RsvgNode *
-rsvg_new_svg (const char *element_name, RsvgNode *parent)
-{
-    RsvgNodeSvg *svg;
-
-    svg = g_new0 (RsvgNodeSvg, 1);
-    svg->vbox.active = FALSE;
-    svg->preserve_aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
-    svg->x = rsvg_length_parse ("0", LENGTH_DIR_HORIZONTAL);
-    svg->y = rsvg_length_parse ("0", LENGTH_DIR_VERTICAL);
-    svg->w = rsvg_length_parse ("100%", LENGTH_DIR_HORIZONTAL);
-    svg->h = rsvg_length_parse ("100%", LENGTH_DIR_VERTICAL);
-    svg->atts = NULL;
-
-    return rsvg_rust_cnode_new (RSVG_NODE_TYPE_SVG,
-                                parent,
-                                rsvg_state_new (),
-                                svg,
-                                rsvg_node_svg_set_atts,
-                                rsvg_node_svg_draw,
-                                rsvg_node_svg_free);
-}
-
 static gboolean
 rsvg_node_is_ancestor (RsvgNode *potential_ancestor, RsvgNode *descendant)
 {
diff --git a/rsvg-structure.h b/rsvg-structure.h
index 2064366..077ce63 100644
--- a/rsvg-structure.h
+++ b/rsvg-structure.h
@@ -40,8 +40,6 @@ 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);
-G_GNUC_INTERNAL
-RsvgNode *rsvg_new_svg (const char *element_name, RsvgNode *parent);
 
 /* Implemented in rust/src/structure.rs */
 G_GNUC_INTERNAL
@@ -55,16 +53,21 @@ RsvgNode *rsvg_node_defs_new (const char *element_name, RsvgNode *parent);
 G_GNUC_INTERNAL
 RsvgNode *rsvg_node_switch_new (const char *element_name, RsvgNode *parent);
 
-typedef struct _RsvgNodeSvg RsvgNodeSvg;
+/* Implemented in rust/src/structure.rs */
+G_GNUC_INTERNAL
+RsvgNode *rsvg_node_svg_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 */
 G_GNUC_INTERNAL
 RsvgViewBox rsvg_node_svg_get_view_box (RsvgNode *node);
 
+/* Implemented in rust/src/structure.rs */
 G_GNUC_INTERNAL
-void _rsvg_node_svg_apply_atts  (RsvgNode *node, RsvgNodeSvg *svg, RsvgHandle * ctx);
+void rsvg_node_svg_apply_atts (RsvgNode *node, RsvgHandle *handle);
 
 G_END_DECLS
 
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index dbea38b..affdb7e 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -95,6 +95,10 @@ pub use structure::{
     rsvg_node_group_new,
     rsvg_node_defs_new,
     rsvg_node_switch_new,
+    rsvg_node_svg_new,
+    rsvg_node_svg_get_size,
+    rsvg_node_svg_get_view_box,
+    rsvg_node_svg_apply_atts,
 };
 
 pub use transform::{
diff --git a/rust/src/structure.rs b/rust/src/structure.rs
index ca91d1e..a06d767 100644
--- a/rust/src/structure.rs
+++ b/rust/src/structure.rs
@@ -1,11 +1,25 @@
+extern crate glib;
+extern crate cairo;
 extern crate libc;
 
+use self::glib::translate::*;
+
+use std::cell::Cell;
+use std::ptr;
+
+use aspect_ratio::*;
 use drawing_ctx::RsvgDrawingCtx;
 use drawing_ctx;
 use handle::RsvgHandle;
+use length::*;
 use node::*;
 use property_bag;
 use property_bag::*;
+use util::*;
+use viewbox::*;
+
+use self::cairo::MatrixTrait;
+
 
 /***** NodeGroup *****/
 
@@ -95,6 +109,128 @@ impl NodeTrait for NodeSwitch {
     }
 }
 
+/***** NodeSvg *****/
+
+struct NodeSvg {
+    preserve_aspect_ratio: Cell<AspectRatio>,
+    x:                     Cell<RsvgLength>,
+    y:                     Cell<RsvgLength>,
+    w:                     Cell<RsvgLength>,
+    h:                     Cell<RsvgLength>,
+    vbox:                  Cell<RsvgViewBox>,
+    atts:                  Cell<*mut RsvgPropertyBag>
+}
+
+impl NodeSvg {
+    fn new () -> NodeSvg {
+        NodeSvg {
+            preserve_aspect_ratio: Cell::new (AspectRatio::default ()),
+            x:                     Cell::new (RsvgLength::parse ("0", LengthDir::Horizontal).unwrap ()),
+            y:                     Cell::new (RsvgLength::parse ("0", LengthDir::Vertical).unwrap ()),
+            w:                     Cell::new (RsvgLength::parse ("100%", LengthDir::Horizontal).unwrap ()),
+            h:                     Cell::new (RsvgLength::parse ("100%", LengthDir::Vertical).unwrap ()),
+            vbox:                  Cell::new (RsvgViewBox::default ()),
+            atts:                  Cell::new (ptr::null_mut ())
+        }
+    }
+}
+
+impl NodeTrait for NodeSvg {
+    fn set_atts (&self, node: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
+        self.preserve_aspect_ratio.set (property_bag::parse_or_default (pbag, "preserveAspectRatio")?);
+
+        // x & y attributes have no effect on outermost svg
+        // http://www.w3.org/TR/SVG/struct.html#SVGElement
+        if node.get_parent ().is_some () {
+            self.x.set (property_bag::length_or_default (pbag, "x", LengthDir::Horizontal)?);
+            self.y.set (property_bag::length_or_default (pbag, "y", LengthDir::Vertical)?);
+        }
+
+        self.w.set (property_bag::length_or_value (pbag, "width", LengthDir::Horizontal, "100%")?);
+        self.h.set (property_bag::length_or_value (pbag, "height", LengthDir::Vertical, "100%")?);
+
+        self.vbox.set (property_bag::parse_or_default (pbag, "viewBox")?);
+
+        // The "style" sub-element is not loaded yet here, so we need
+        // to store other attributes to be applied later.
+        self.atts.set (property_bag::dup (pbag));
+
+        Ok (())
+    }
+
+    fn draw (&self, node: &RsvgNode, draw_ctx: *const RsvgDrawingCtx, dominate: i32) {
+        let nx = self.x.get ().normalize (draw_ctx);
+        let ny = self.y.get ().normalize (draw_ctx);
+        let nw = self.w.get ().normalize (draw_ctx);
+        let nh = self.h.get ().normalize (draw_ctx);
+
+        drawing_ctx::state_reinherit_top (draw_ctx, node.get_state (), dominate);
+
+        let state = drawing_ctx::get_current_state (draw_ctx);
+
+        let affine_old = drawing_ctx::get_current_state_affine (draw_ctx);
+
+        let vbox = self.vbox.get ();
+
+        if vbox.active {
+            // viewBox width==0 or height==0 disables rendering of the element
+            // https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
+            if double_equals (vbox.rect.width, 0.0) || double_equals (vbox.rect.height, 0.0) {
+                return;
+            }
+
+            let (x, y, w, h) = self.preserve_aspect_ratio.get ().compute (vbox.rect.width, vbox.rect.height,
+                                                                          nx, ny, nw, nh);
+
+            let affine = cairo::Matrix::new (w / vbox.rect.width,
+                                             0.0,
+                                             0.0,
+                                             h / vbox.rect.height,
+                                             x - vbox.rect.x * w / vbox.rect.width,
+                                             y - vbox.rect.y * h / vbox.rect.height);
+
+            drawing_ctx::set_current_state_affine (draw_ctx, cairo::Matrix::multiply (&affine, &affine_old));
+
+            drawing_ctx::push_view_box (draw_ctx, vbox.rect.width, vbox.rect.height);
+        } else {
+            let mut affine = affine_old;
+            affine.translate (nx, ny);
+
+            drawing_ctx::set_current_state_affine (draw_ctx, affine);
+            drawing_ctx::push_view_box (draw_ctx, nw, nh);
+        }
+
+        let affine_new = drawing_ctx::get_current_state_affine (draw_ctx);
+
+        drawing_ctx::push_discrete_layer (draw_ctx);
+
+        // Bounding box addition must be AFTER the discrete layer
+        // push, which must be AFTER the transformation happens.
+
+        if !drawing_ctx::state_is_overflow (state) && node.get_parent ().is_some () {
+            drawing_ctx::set_current_state_affine (draw_ctx, affine_old);
+            drawing_ctx::add_clipping_rect (draw_ctx, nx, ny, nw, nh);
+            drawing_ctx::set_current_state_affine (draw_ctx, affine_new);
+        }
+
+        node.draw_children (draw_ctx, -1); // dominate==-1 so it won't reinherit or push a layer
+
+        drawing_ctx::pop_discrete_layer (draw_ctx);
+        drawing_ctx::pop_view_box (draw_ctx);
+    }
+
+    fn get_c_impl (&self) -> *const RsvgCNodeImpl {
+        unreachable! ();
+    }
+}
+
+impl Drop for NodeSvg {
+    fn drop (&mut self) {
+        property_bag::free (self.atts.get ());
+        self.atts.set (ptr::null_mut ());
+    }
+}
+
 /***** C Prototypes *****/
 
 #[no_mangle]
@@ -117,3 +253,68 @@ pub extern fn rsvg_node_switch_new (_: *const libc::c_char, raw_parent: *const R
                     raw_parent,
                     Box::new (NodeSwitch::new ()))
 }
+
+#[no_mangle]
+pub extern fn rsvg_node_svg_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
+    boxed_node_new (NodeType::Svg,
+                    raw_parent,
+                    Box::new (NodeSvg::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 };
+
+    assert! (!out_width.is_null ());
+    assert! (!out_height.is_null ());
+
+    node.with_impl (|svg: &NodeSvg| {
+        unsafe {
+            *out_width  = svg.w.get ();
+            *out_height = svg.h.get ();
+        }
+    });
+}
+
+#[no_mangle]
+pub extern fn rsvg_node_svg_get_view_box (raw_node: *const RsvgNode) -> RsvgViewBox {
+    assert! (!raw_node.is_null ());
+    let node: &RsvgNode = unsafe { & *raw_node };
+
+    let mut vbox = RsvgViewBox::default ();
+
+    node.with_impl (|svg: &NodeSvg| {
+        vbox = svg.vbox.get ();
+    });
+
+    vbox
+}
+
+extern "C" {
+    fn rsvg_parse_style_attrs (handle: *const RsvgHandle,
+                               node:   *const RsvgNode,
+                               tag:    *const libc::c_char,
+                               class:  *const libc::c_char,
+                               id:     *const libc::c_char,
+                               pbag:   *const RsvgPropertyBag);
+}
+
+#[no_mangle]
+pub extern fn rsvg_node_svg_apply_atts (raw_node: *const RsvgNode, handle: *const RsvgHandle) {
+    assert! (!raw_node.is_null ());
+    let node: &RsvgNode = unsafe { & *raw_node };
+
+    node.with_impl (|svg: &NodeSvg| {
+        let pbag = svg.atts.get ();
+        let class = property_bag::lookup (pbag, "class");
+        let id = property_bag::lookup (pbag, "id");
+
+        unsafe { rsvg_parse_style_attrs (handle,
+                                         raw_node,
+                                         str::to_glib_none ("svg").0,
+                                         class.map_or (ptr::null (), |s| String::to_glib_none (&s).0),
+                                         id.map_or (ptr::null (), |s| String::to_glib_none (&s).0),
+                                         pbag); }
+    });
+}


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