[librsvg] pattern.rs: Fully implement NodePattern in Rust. Yay!



commit 3cf93f386adb02806c5c0e4a1b88bd2aa7b36ad8
Author: Federico Mena Quintero <federico gnome org>
Date:   Mon May 22 07:54:23 2017 -0500

    pattern.rs: Fully implement NodePattern in Rust. Yay!
    
    We had an auxiliary Pattern structure, which is what the patterns
    machinery used to resolve patterns at rendering time.  However, the SVG
    data for patterns was still being kept in the C code.  Now we have a
    Rust NodePattern, as expected, and the C code does not have any patterns
    machinery anymore (other than RsvgPaintServer's to actually call up the
    pattern.)

 rsvg-base.c         |    2 +-
 rsvg-cairo-draw.c   |   20 +----
 rsvg-paint-server.c |  116 -------------------------
 rsvg-paint-server.h |   48 +----------
 rust/src/lib.rs     |    4 +-
 rust/src/pattern.rs |  236 +++++++++++++++++++++++++--------------------------
 6 files changed, 122 insertions(+), 304 deletions(-)
---
diff --git a/rsvg-base.c b/rsvg-base.c
index 3b966f2..6cc74c7 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -314,7 +314,7 @@ static const NodeCreator node_creators[] = {
     /* "mpath"               FALSE, */
     { "multiImage",          FALSE, rsvg_node_switch_new }, /* hack to make multiImage sort-of work */
     { "path",                TRUE,  rsvg_node_path_new },
-    { "pattern",             TRUE,  rsvg_new_pattern },
+    { "pattern",             TRUE,  rsvg_node_pattern_new },
     { "polygon",             TRUE,  rsvg_node_polygon_new },
     { "polyline",            TRUE,  rsvg_node_polyline_new },
     { "radialGradient",      TRUE,  rsvg_new_radial_gradient },
diff --git a/rsvg-cairo-draw.c b/rsvg-cairo-draw.c
index 0d6c292..0e2de5e 100644
--- a/rsvg-cairo-draw.c
+++ b/rsvg-cairo-draw.c
@@ -176,24 +176,6 @@ _set_source_rsvg_solid_color (RsvgDrawingCtx * ctx,
     cairo_set_source_rgba (cr, r, g, b, a);
 }
 
-static gboolean
-_set_source_rsvg_pattern (RsvgDrawingCtx *ctx,
-                          RsvgNode *node,
-                          RsvgBbox bbox)
-{
-    Pattern *pattern;
-    gboolean result;
-
-    pattern = rsvg_pattern_node_to_rust_pattern (node);
-    g_assert (pattern != NULL);
-
-    result = pattern_resolve_fallbacks_and_set_pattern (pattern, ctx, bbox);
-
-    pattern_destroy (pattern);
-
-    return result;
-}
-
 /* note: _set_source_rsvg_paint_server does not change cairo's CTM */
 static gboolean
 _set_source_rsvg_paint_server (RsvgDrawingCtx * ctx,
@@ -221,7 +203,7 @@ _set_source_rsvg_paint_server (RsvgDrawingCtx * ctx,
             _set_source_rsvg_radial_gradient (ctx, node, opacity, bbox);
             had_paint_server = TRUE;
         } else if (rsvg_node_get_type (node) == RSVG_NODE_TYPE_PATTERN) {
-            if (_set_source_rsvg_pattern (ctx, node, bbox)) {
+            if (pattern_resolve_fallbacks_and_set_pattern (node, ctx, bbox)) {
                 had_paint_server = TRUE;
             } else {
                 use_alternate = TRUE;
diff --git a/rsvg-paint-server.c b/rsvg-paint-server.c
index 98714ac..a92f6d1 100644
--- a/rsvg-paint-server.c
+++ b/rsvg-paint-server.c
@@ -493,119 +493,3 @@ rsvg_new_radial_gradient (const char *element_name, RsvgNode *parent)
                                 rsvg_paint_server_draw,
                                 rsvg_radial_gradient_free);
 }
-
-static void
-rsvg_pattern_set_atts (RsvgNode *node, gpointer impl, RsvgHandle *handle, RsvgPropertyBag *atts)
-{
-    RsvgPattern *pattern = impl;
-    const char *value;
-
-    if ((value = rsvg_property_bag_lookup (atts, "viewBox"))) {
-        pattern->vbox = rsvg_css_parse_vbox (value);
-        pattern->hasvbox = TRUE;
-    }
-    if ((value = rsvg_property_bag_lookup (atts, "x"))) {
-        pattern->x = rsvg_length_parse (value, LENGTH_DIR_HORIZONTAL);
-        pattern->hasx = TRUE;
-    }
-    if ((value = rsvg_property_bag_lookup (atts, "y"))) {
-        pattern->y = rsvg_length_parse (value, LENGTH_DIR_VERTICAL);
-        pattern->hasy = TRUE;
-    }
-    if ((value = rsvg_property_bag_lookup (atts, "width"))) {
-        pattern->width = rsvg_length_parse (value, LENGTH_DIR_HORIZONTAL);
-        pattern->haswidth = TRUE;
-    }
-    if ((value = rsvg_property_bag_lookup (atts, "height"))) {
-        pattern->height = rsvg_length_parse (value, LENGTH_DIR_VERTICAL);
-        pattern->hasheight = TRUE;
-    }
-    g_free (pattern->fallback);
-    pattern->fallback = g_strdup (rsvg_property_bag_lookup (atts, "xlink:href"));
-    if ((value = rsvg_property_bag_lookup (atts, "patternTransform"))) {
-        if (rsvg_parse_transform (&pattern->affine, value)) {
-            pattern->hastransform = TRUE;
-        } else {
-            rsvg_node_set_attribute_parse_error (node,
-                                                 "patternTransform",
-                                                 "Invalid transformation");
-        }
-    }
-    if ((value = rsvg_property_bag_lookup (atts, "patternUnits"))) {
-        if (!strcmp (value, "userSpaceOnUse"))
-            pattern->obj_bbox = FALSE;
-        else if (!strcmp (value, "objectBoundingBox"))
-            pattern->obj_bbox = TRUE;
-        pattern->hasbbox = TRUE;
-    }
-    if ((value = rsvg_property_bag_lookup (atts, "patternContentUnits"))) {
-        if (!strcmp (value, "userSpaceOnUse"))
-            pattern->obj_cbbox = FALSE;
-        else if (!strcmp (value, "objectBoundingBox"))
-            pattern->obj_cbbox = TRUE;
-        pattern->hascbox = TRUE;
-    }
-    if ((value = rsvg_property_bag_lookup (atts, "preserveAspectRatio"))) {
-        pattern->preserve_aspect_ratio = rsvg_aspect_ratio_parse (value);
-        pattern->hasaspect = TRUE;
-    }
-}
-
-static void
-rsvg_pattern_free (gpointer impl)
-{
-    RsvgPattern *self = impl;
-
-    g_free (self->fallback);
-    g_free (self);
-}
-
-
-RsvgNode *
-rsvg_new_pattern (const char *element_name, RsvgNode *parent)
-{
-    RsvgPattern *pattern = g_new0 (RsvgPattern, 1);
-    cairo_matrix_init_identity (&pattern->affine);
-    pattern->obj_bbox = TRUE;
-    pattern->obj_cbbox = FALSE;
-    pattern->x = pattern->y = pattern->width = pattern->height = rsvg_length_parse ("0", LENGTH_DIR_BOTH);
-    pattern->fallback = NULL;
-    pattern->preserve_aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
-    pattern->vbox.active = FALSE;
-    pattern->hasx = pattern->hasy = pattern->haswidth = pattern->hasheight = pattern->hasbbox =
-        pattern->hascbox = pattern->hasvbox = pattern->hasaspect = pattern->hastransform = FALSE;
-
-    return rsvg_rust_cnode_new (RSVG_NODE_TYPE_PATTERN,
-                                parent,
-                                rsvg_state_new (),
-                                pattern,
-                                rsvg_pattern_set_atts,
-                                rsvg_paint_server_draw,
-                                rsvg_pattern_free);
-}
-
-Pattern *
-rsvg_pattern_node_to_rust_pattern (RsvgNode *node)
-{
-    RsvgPattern *pnode;
-    Pattern *pattern;
-
-    if (rsvg_node_get_type (node) != RSVG_NODE_TYPE_PATTERN)
-        return NULL; /* FIXME: make this always return a Pattern; make the checks in the caller */
-
-    pnode = rsvg_rust_cnode_get_impl (node);
-
-    pattern = pattern_new (pnode->hasx         ? &pnode->x : NULL,
-                           pnode->hasy         ? &pnode->y : NULL,
-                           pnode->haswidth     ? &pnode->width : NULL,
-                           pnode->hasheight    ? &pnode->height : NULL,
-                           pnode->hasbbox      ? &pnode->obj_bbox : NULL,
-                           pnode->hascbox      ? &pnode->obj_cbbox : NULL,
-                           pnode->hasvbox      ? &pnode->vbox : NULL,
-                           pnode->hastransform ? &pnode->affine : NULL,
-                           pnode->hasaspect    ? &pnode->preserve_aspect_ratio : NULL,
-                           pnode->fallback,
-                           node);
-
-    return pattern;
-}
diff --git a/rsvg-paint-server.h b/rsvg-paint-server.h
index 63b967f..dc152e9 100644
--- a/rsvg-paint-server.h
+++ b/rsvg-paint-server.h
@@ -36,7 +36,6 @@ typedef struct _RsvgGradientStop RsvgGradientStop;
 typedef struct _RsvgGradientStops RsvgGradientStops;
 typedef struct _RsvgLinearGradient RsvgLinearGradient;
 typedef struct _RsvgRadialGradient RsvgRadialGradient;
-typedef struct _RsvgPattern RsvgPattern;
 typedef struct _RsvgSolidColor RsvgSolidColor;
 
 typedef struct _RsvgPaintServer RsvgPaintServer;
@@ -126,57 +125,16 @@ void gradient_resolve_fallbacks_and_set_pattern (Gradient       *gradient,
 G_GNUC_INTERNAL
 Gradient *rsvg_gradient_node_to_rust_gradient (RsvgNode *node);
 
-struct _RsvgPattern {
-    gboolean obj_cbbox;
-    gboolean obj_bbox;
-    cairo_matrix_t affine; /* user space to actual at time of gradient def */
-    RsvgLength x, y, width, height;
-    RsvgViewBox vbox;
-    guint32 preserve_aspect_ratio;
-    int hasx:1;
-    int hasy:1;
-    int hasvbox:1;
-    int haswidth:1;
-    int hasheight:1;
-    int hasaspect:1;
-    int hascbox:1;
-    int hasbbox:1;
-    int hastransform:1;
-    char *fallback;
-};
-
-/* This is a Rust pattern from rust/src/pattern.rs */
-typedef struct _Pattern Pattern;
-
 /* Implemented in rust/src/pattern.rs */
 G_GNUC_INTERNAL
-Pattern *
-pattern_new (RsvgLength     *x,
-             RsvgLength     *y,
-             RsvgLength     *width,
-             RsvgLength     *height,
-             gboolean       *obj_bbox,
-             gboolean       *obj_cbbox,
-             RsvgViewBox    *vbox,
-             cairo_matrix_t *affine,
-             guint32        *preserve_aspect_ratio,
-             const char     *fallback_name,
-             RsvgNode       *node);
+RsvgNode *rsvg_node_pattern_new (const char *element_name, RsvgNode *parent);
 
 /* Implemented in rust/src/pattern.rs */
 G_GNUC_INTERNAL
-void pattern_destroy (Pattern *pattern);
-
-/* Implemented in rust/src/pattern.rs */
-G_GNUC_INTERNAL
-gboolean pattern_resolve_fallbacks_and_set_pattern (Pattern        *pattern,
+gboolean pattern_resolve_fallbacks_and_set_pattern (RsvgNode       *node,
                                                     RsvgDrawingCtx *draw_ctx,
                                                     RsvgBbox        bbox);
 
-G_GNUC_INTERNAL
-Pattern *rsvg_pattern_node_to_rust_pattern (RsvgNode *node);
-
-
 struct _RsvgSolidColor {
     gboolean currentcolor;
     guint32 argb;
@@ -223,8 +181,6 @@ G_GNUC_INTERNAL
 RsvgNode *rsvg_new_radial_gradient  (const char *element_name, RsvgNode *parent);
 G_GNUC_INTERNAL
 RsvgNode *rsvg_new_stop                (const char *element_name, RsvgNode *parent);
-G_GNUC_INTERNAL
-RsvgNode *rsvg_new_pattern      (const char *element_name, RsvgNode *parent);
 
 
 G_END_DECLS
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 1662759..242b4b3 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -1,5 +1,6 @@
 extern crate libc;
 extern crate glib;
+extern crate cairo;
 
 #[macro_use]
 extern crate bitflags;
@@ -78,8 +79,7 @@ pub use path_builder::{
 };
 
 pub use pattern::{
-    pattern_new,
-    pattern_destroy,
+    rsvg_node_pattern_new,
     pattern_resolve_fallbacks_and_set_pattern,
 };
 
diff --git a/rust/src/pattern.rs b/rust/src/pattern.rs
index 053db37..bbea49d 100644
--- a/rust/src/pattern.rs
+++ b/rust/src/pattern.rs
@@ -5,6 +5,7 @@ extern crate glib_sys;
 extern crate glib;
 
 use std::cell::RefCell;
+use std::rc::*;
 use std::str::FromStr;
 use self::glib::translate::*;
 
@@ -17,7 +18,6 @@ use handle::RsvgHandle;
 use length::*;
 use node::*;
 use paint_server::*;
-use parsers::ParseError;
 use property_bag;
 use property_bag::*;
 use util::*;
@@ -28,6 +28,7 @@ use self::cairo::enums::*;
 use self::cairo::SurfacePattern;
 use self::cairo::Pattern as CairoPattern;
 
+#[derive(Clone)]
 pub struct Pattern {
     pub units:                 Option<PaintServerUnits>,
     pub content_units:         Option<PatternContentUnits>,
@@ -40,8 +41,26 @@ pub struct Pattern {
     pub width:                 Option<RsvgLength>,
     pub height:                Option<RsvgLength>,
 
-    // We just use c_node to see if the C implementation has children
-    pub c_node:                *const RsvgNode
+    // Point back to our corresponding node, or to the fallback node which has children
+    pub node:                  Option<Weak<Node>>
+}
+
+impl Default for Pattern {
+    fn default () -> Pattern {
+        Pattern {
+            units:                 None,
+            content_units:         None,
+            vbox:                  None,
+            preserve_aspect_ratio: None,
+            affine:                None,
+            fallback:              None,
+            x:                     None,
+            y:                     None,
+            width:                 None,
+            height:                None,
+            node:                  None
+        }
+    }
 }
 
 // A pattern's patternUnits attribute (in our Pattern::units field) defines the coordinate
@@ -72,18 +91,15 @@ impl FromStr for PatternContentUnits {
     }
 }
 
-extern "C" {
-    fn rsvg_pattern_node_to_rust_pattern (node: *const RsvgNode) -> *mut Pattern;
-}
-
-fn pattern_node_has_children (raw_node: *const RsvgNode) -> bool {
-    assert! (!raw_node.is_null ());
-    let node: &RsvgNode = unsafe { & *raw_node };
+fn node_has_children (node: &Option<Weak<Node>>) -> bool {
+    match *node {
+        None => false,
 
-    if node.get_type () == NodeType::Pattern {
-        node.children.borrow ().len () > 0
-    } else {
-        false
+        Some (ref weak) => {
+            let ref strong_node = weak.clone ().upgrade ().unwrap ();
+            let has_children = strong_node.children.borrow ().len () > 0;
+            has_children
+        }
     }
 }
 
@@ -121,7 +137,7 @@ impl Pattern {
             self.y.is_some () &&
             self.width.is_some () &&
             self.height.is_some () &&
-            pattern_node_has_children (self.c_node)
+            node_has_children (&self.node)
     }
 
     fn resolve_from_defaults (&mut self) {
@@ -140,8 +156,9 @@ impl Pattern {
 
         self.fallback = None;
 
-        // We don't resolve the children here - instead, we'll just
-        // NOP if there are no children at drawing time.
+        if !node_has_children (&self.node) {
+            self.node = None;
+        }
     }
 
     fn resolve_from_fallback (&mut self, fallback: &Pattern) {
@@ -155,48 +172,76 @@ impl Pattern {
         fallback_to! (self.width,                 fallback.width);
         fallback_to! (self.height,                fallback.height);
 
-        self.fallback = clone_fallback_name (&fallback.fallback);
+        self.fallback = fallback.fallback.clone ();
 
-        if !pattern_node_has_children (self.c_node) {
-            self.c_node = fallback.c_node;
+        if !node_has_children (&self.node) {
+            self.node = fallback.node.clone ();
         }
     }
 }
 
-impl Clone for Pattern {
-    fn clone (&self) -> Self {
-        Pattern {
-            units:                 self.units,
-            content_units:         self.content_units,
-            vbox:                  self.vbox,
-            preserve_aspect_ratio: self.preserve_aspect_ratio,
-            affine:                self.affine,
-            fallback:              clone_fallback_name (&self.fallback),
-            x:                     self.x,
-            y:                     self.y,
-            width:                 self.width,
-            height:                self.height,
-            c_node:                self.c_node
+struct NodePattern {
+    pattern: RefCell<Pattern>
+}
+
+impl NodePattern {
+    fn new () -> NodePattern {
+        NodePattern {
+            pattern: RefCell::new (Pattern::default ())
         }
     }
 }
 
+impl NodeTrait for NodePattern {
+    fn set_atts (&self, node: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
+        let mut p = self.pattern.borrow_mut ();
+
+        p.node = Some (Rc::downgrade (node));
+
+        p.units         = property_bag::parse_or_none (pbag, "patternUnits")?;
+        p.content_units = property_bag::parse_or_none (pbag, "patternContentUnits")?;
+        p.vbox          = property_bag::parse_or_none (pbag, "viewBox")?;
+
+        p.preserve_aspect_ratio = property_bag::parse_or_none (pbag, "preserveAspectRatio")?;
+
+        p.affine = property_bag::transform_or_none (pbag, "patternTransform")?;
+
+        p.fallback = property_bag::lookup (pbag, "xlink:href");
+
+        p.x      = property_bag::length_or_none (pbag, "x", LengthDir::Horizontal)?;
+        p.y      = property_bag::length_or_none (pbag, "y", LengthDir::Vertical)?;
+        p.width  = property_bag::length_or_none (pbag, "width", LengthDir::Horizontal)?;
+        p.height = property_bag::length_or_none (pbag, "height", LengthDir::Vertical)?;
+
+        Ok (())
+    }
+
+    fn draw (&self, _: &RsvgNode, _: *const RsvgDrawingCtx, _: i32) {
+        // nothing; paint servers are handled specially
+    }
+
+    fn get_c_impl (&self) -> *const RsvgCNodeImpl {
+        unreachable! ();
+    }
+}
+
 trait FallbackSource {
-    fn get_fallback (&mut self, name: &str) -> Option<Box<Pattern>>;
+    fn get_fallback (&mut self, name: &str) -> Option<RsvgNode>;
 }
 
 fn resolve_pattern (pattern: &Pattern, fallback_source: &mut FallbackSource) -> Pattern {
     let mut result = pattern.clone ();
 
     while !result.is_resolved () {
-        let mut opt_fallback: Option<Box<Pattern>> = None;
+        let mut opt_fallback: Option<RsvgNode> = None;
 
         if let Some (ref fallback_name) = result.fallback {
             opt_fallback = fallback_source.get_fallback (&**fallback_name);
         }
 
-        if let Some (fallback_pattern) = opt_fallback {
-            result.resolve_from_fallback (&*fallback_pattern);
+        if let Some (fallback_node) = opt_fallback {
+            fallback_node.with_impl (|i: &NodePattern|
+                                     result.resolve_from_fallback (&*i.pattern.borrow ()));
         } else {
             result.resolve_from_defaults ();
             break;
@@ -229,32 +274,18 @@ impl Drop for NodeFallbackSource {
 }
 
 impl FallbackSource for NodeFallbackSource {
-    fn get_fallback (&mut self, name: &str) -> Option<Box<Pattern>> {
-        let fallback_node = drawing_ctx::acquire_node (self.draw_ctx, name);
-
-        if fallback_node.is_null () {
-            return None;
-        }
-
-        self.acquired_nodes.push (fallback_node);
+    fn get_fallback (&mut self, name: &str) -> Option<RsvgNode> {
+        let raw_fallback_node = drawing_ctx::acquire_node_of_type (self.draw_ctx, name, NodeType::Pattern);
 
-        let raw_fallback_pattern = unsafe { rsvg_pattern_node_to_rust_pattern (fallback_node) };
-
-        if raw_fallback_pattern.is_null () {
+        if raw_fallback_node.is_null () {
             return None;
         }
 
-        let fallback_pattern = unsafe { Box::from_raw (raw_fallback_pattern) };
+        self.acquired_nodes.push (raw_fallback_node);
 
-        return Some (fallback_pattern);
-    }
-}
+        let fallback_node: &RsvgNode = unsafe { & *raw_fallback_node };
 
-fn paint_server_units_from_gboolean (v: glib_sys::gboolean) -> PaintServerUnits {
-    if from_glib (v) {
-        PaintServerUnits::ObjectBoundingBox
-    } else {
-        PaintServerUnits::UserSpaceOnUse
+        Some (fallback_node.clone ())
     }
 }
 
@@ -263,7 +294,7 @@ fn set_pattern_on_draw_context (pattern: &Pattern,
                                 bbox:     &RsvgBbox) -> bool {
     assert! (pattern.is_resolved ());
 
-    if !pattern_node_has_children (pattern.c_node) {
+    if !node_has_children (&pattern.node) {
         return false;
     }
 
@@ -404,7 +435,7 @@ fn set_pattern_on_draw_context (pattern: &Pattern,
     drawing_ctx::set_current_state_affine (draw_ctx, caffine);
 
     // Draw everything
-    let pattern_node: &RsvgNode = unsafe { & *pattern.c_node };
+    let pattern_node = pattern.node.clone ().unwrap ().upgrade ().unwrap ();
     pattern_node.draw_children (draw_ctx, 2);
 
     // Return to the original coordinate system and rendering context
@@ -432,73 +463,38 @@ fn set_pattern_on_draw_context (pattern: &Pattern,
     true
 }
 
-#[no_mangle]
-pub unsafe extern fn pattern_new (x: *const RsvgLength,
-                                  y: *const RsvgLength,
-                                  width: *const RsvgLength,
-                                  height: *const RsvgLength,
-                                  obj_bbox: *const glib_sys::gboolean,
-                                  obj_cbbox: *const glib_sys::gboolean,
-                                  vbox: *const RsvgViewBox,
-                                  affine: *const cairo::Matrix,
-                                  preserve_aspect_ratio: *const u32,
-                                  fallback_name: *const libc::c_char,
-                                  c_node: *const RsvgNode) -> *mut Pattern {
-    assert! (!c_node.is_null ());
-
-    let my_x         = { if x.is_null ()      { None } else { Some (*x) } };
-    let my_y         = { if y.is_null ()      { None } else { Some (*y) } };
-    let my_width     = { if width.is_null ()  { None } else { Some (*width) } };
-    let my_height    = { if height.is_null () { None } else { Some (*height) } };
-
-    let my_units         = { if obj_bbox.is_null ()  { None } else { Some (paint_server_units_from_gboolean 
(*obj_bbox)) } };
-    let my_content_units = { if obj_cbbox.is_null () { None } else { Some (PatternContentUnits 
(paint_server_units_from_gboolean (*obj_cbbox))) } };
-    let my_vbox          = { if vbox.is_null ()      { None } else { Some (*vbox) } };
-
-    let my_affine    = { if affine.is_null () { None } else { Some (*affine) } };
-
-    let my_preserve_aspect_ratio = { if preserve_aspect_ratio.is_null () { None } else { Some 
(AspectRatio::from_u32 (*preserve_aspect_ratio)) } };
-
-    let my_fallback_name = { if fallback_name.is_null () { None } else { Some (String::from_glib_none 
(fallback_name)) } };
-
-    let pattern = Pattern {
-        units:                 my_units,
-        content_units:         my_content_units,
-        vbox:                  my_vbox,
-        preserve_aspect_ratio: my_preserve_aspect_ratio,
-        affine:                my_affine,
-        fallback:              my_fallback_name,
-        x:                     my_x,
-        y:                     my_y,
-        width:                 my_width,
-        height:                my_height,
-        c_node:                c_node
-    };
-
-    let boxed_pattern = Box::new (pattern);
-
-    Box::into_raw (boxed_pattern)
+fn resolve_fallbacks_and_set_pattern (pattern:  &Pattern,
+                                      draw_ctx: *mut RsvgDrawingCtx,
+                                      bbox:     RsvgBbox) -> bool {
+    let mut fallback_source = NodeFallbackSource::new (draw_ctx);
+
+    let resolved = resolve_pattern (pattern, &mut fallback_source);
+
+    set_pattern_on_draw_context (&resolved, draw_ctx, &bbox)
 }
 
 #[no_mangle]
-pub unsafe extern fn pattern_destroy (raw_pattern: *mut Pattern) {
-    assert! (!raw_pattern.is_null ());
-
-    let _ = Box::from_raw (raw_pattern);
+pub extern fn rsvg_node_pattern_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode 
{
+    boxed_node_new (NodeType::Pattern,
+                    raw_parent,
+                    Box::new (NodePattern::new ()))
 }
 
 #[no_mangle]
-pub extern fn pattern_resolve_fallbacks_and_set_pattern (raw_pattern: *mut Pattern,
-                                                         draw_ctx:    *mut RsvgDrawingCtx,
-                                                         bbox:        RsvgBbox) -> glib_sys::gboolean {
-    assert! (!raw_pattern.is_null ());
-    let pattern: &mut Pattern = unsafe { &mut (*raw_pattern) };
+pub extern fn pattern_resolve_fallbacks_and_set_pattern (raw_node: *const RsvgNode,
+                                                         draw_ctx: *mut RsvgDrawingCtx,
+                                                         bbox:     RsvgBbox) -> glib_sys::gboolean {
+    assert! (!raw_node.is_null ());
+    let node: &RsvgNode = unsafe { & *raw_node };
 
-    let mut fallback_source = NodeFallbackSource::new (draw_ctx);
+    assert! (node.get_type () == NodeType::Pattern);
 
-    let resolved = resolve_pattern (pattern, &mut fallback_source);
+    let mut did_set_pattern = false;
+
+    node.with_impl (|node_pattern: &NodePattern| {
+        let pattern = &*node_pattern.pattern.borrow ();
+        did_set_pattern = resolve_fallbacks_and_set_pattern (pattern, draw_ctx, bbox);
+    });
 
-    set_pattern_on_draw_context (&resolved,
-                                 draw_ctx,
-                                 &bbox).to_glib ()
+    did_set_pattern.to_glib ()
 }


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