[librsvg] cnode.rs: New stub for having a node implemented in C, accessible from Rust



commit df6eb69fe45f6d8dfe5fa04ae583aa9603276edc
Author: Federico Mena Quintero <federico gnome org>
Date:   Thu Jan 26 13:11:14 2017 -0600

    cnode.rs: New stub for having a node implemented in C, accessible from Rust
    
    node.rs: The node_impl needs to be a Box<NodeTrait>, as the actual
    implementation will live in the heap:  can't have a lifetime specifier
    there.
    
    We also have a new rsvg_rust_cnode_new() to create nodes from C and wrap
    the C structures that will actually implement them.

 rust/src/cnode.rs  |   74 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 rust/src/lib.rs    |    9 ++++++
 rust/src/node.rs   |   67 ++++++++++++++++++++++++++---------------------
 rust/src/shapes.rs |    4 +-
 4 files changed, 122 insertions(+), 32 deletions(-)
---
diff --git a/rust/src/cnode.rs b/rust/src/cnode.rs
new file mode 100644
index 0000000..c998f66
--- /dev/null
+++ b/rust/src/cnode.rs
@@ -0,0 +1,74 @@
+use drawing_ctx::RsvgDrawingCtx;
+use handle::*;
+use node::*;
+use property_bag::RsvgPropertyBag;
+use state::RsvgState;
+use std::rc::Rc;
+use std::rc::Weak;
+use std::cell::RefCell;
+
+/* A *const RsvgCNodeImpl is just an opaque pointer to the C code's
+ * struct for a particular node type.
+ */
+pub enum RsvgCNodeImpl {}
+
+type CNodeSetAtts = unsafe extern "C" fn (node: *const RsvgRcNode, node_impl: *const RsvgCNodeImpl, handle: 
*const RsvgHandle, pbag: *const RsvgPropertyBag);
+type CNodeDraw = unsafe extern "C" fn (node: *const RsvgRcNode, node_impl: *const RsvgCNodeImpl, draw_ctx: 
*const RsvgDrawingCtx, dominate: i32);
+type CNodeFree = unsafe extern "C" fn (node_impl: *const RsvgCNodeImpl);
+
+struct CNode {
+    c_node_impl: *const RsvgCNodeImpl,
+
+    set_atts_fn: CNodeSetAtts,
+    draw_fn:     CNodeDraw,
+    free_fn:     CNodeFree,
+}
+
+impl NodeTrait for CNode {
+    fn set_atts (&self, node: &RsvgRcNode, handle: *const RsvgHandle, pbag: *const RsvgPropertyBag) {
+        unsafe { (self.set_atts_fn) (node as *const RsvgRcNode, self.c_node_impl, handle, pbag); }
+    }
+
+    fn draw (&self, node: &RsvgRcNode, draw_ctx: *const RsvgDrawingCtx, dominate: i32) {
+        unsafe { (self.draw_fn) (node as *const RsvgRcNode, self.c_node_impl, draw_ctx, dominate); }
+    }
+}
+
+impl Drop for CNode {
+    fn drop (&mut self) {
+        unsafe { (self.free_fn) (self.c_node_impl); }
+    }
+}
+
+#[no_mangle]
+pub extern fn rsvg_rust_cnode_new (node_type:   NodeType,
+                                   raw_parent:  *const RsvgRcNode,
+                                   state:       *mut RsvgState,
+                                   c_node_impl: *const RsvgCNodeImpl,
+                                   set_atts_fn: CNodeSetAtts,
+                                   draw_fn:     CNodeDraw,
+                                   free_fn:     CNodeFree) -> *const RsvgRcNode {
+    assert! (!state.is_null ());
+    assert! (!c_node_impl.is_null ());
+
+    let parent: Option<Weak<RefCell<Node>>> = unsafe {
+        if raw_parent.is_null () {
+            None
+        } else {
+            Some (Rc::downgrade (&*(raw_parent as *const RsvgRcNode)))
+        }
+    };
+
+    let cnode = CNode {
+        c_node_impl: c_node_impl,
+        set_atts_fn: set_atts_fn,
+        draw_fn:     draw_fn,
+        free_fn:     free_fn
+    };
+
+    &Rc::new (RefCell::new (Node::new (node_type,
+                                        parent,
+                                        state,
+                                       Box::new (cnode))))
+        as *const RsvgRcNode
+}
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index cfb6bc2..031b34a 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -56,6 +56,14 @@ pub use length::{
 
 pub use node::{
     rsvg_node_get_type,
+    rsvg_node_get_parent,
+    rsvg_node_unref,
+    rsvg_node_get_state,
+    rsvg_node_add_child,
+};
+
+pub use cnode::{
+    rsvg_rust_cnode_new,
 };
 
 pub use viewbox::{
@@ -71,6 +79,7 @@ pub use pattern::{
 
 mod aspect_ratio;
 mod bbox;
+mod cnode;
 mod drawing_ctx;
 mod handle;
 mod gradient;
diff --git a/rust/src/node.rs b/rust/src/node.rs
index 35873fe..2591d5e 100644
--- a/rust/src/node.rs
+++ b/rust/src/node.rs
@@ -2,11 +2,9 @@ extern crate libc;
 
 use std::rc::Rc;
 use std::rc::Weak;
-use std::cell::Cell;
 use std::cell::RefCell;
 use std::ptr;
 
-use drawing_ctx;
 use drawing_ctx::RsvgDrawingCtx;
 
 use handle::RsvgHandle;
@@ -15,20 +13,26 @@ use property_bag::RsvgPropertyBag;
 
 use state::RsvgState;
 
+/* A const *RsvgNode is just a pointer for the C code's benefit: it
+ * points to a RsvgRcNode, which is our refcounted Rust representation
+ * of nodes.
+ */
+pub enum RsvgNode {}
+
+/* This is just to take a pointer to an Rc<RefCell<Node>> */
+pub type RsvgRcNode = Rc<RefCell<Node>>;
+
 pub trait NodeTrait {
-    fn set_atts (&self, handle: *const RsvgHandle, pbag: *const RsvgPropertyBag);
-    fn draw (&self, draw_ctx: *const RsvgDrawingCtx, dominate: i32);
+    fn set_atts (&self, node: &RsvgRcNode, handle: *const RsvgHandle, pbag: *const RsvgPropertyBag);
+    fn draw (&self, node: &RsvgRcNode, draw_ctx: *const RsvgDrawingCtx, dominate: i32);
 }
 
-// strong Rc<Node> references in the toplevel RsvgHandle.all_nodes array
-// weak references elsewhere inside of Node
-
-pub struct Node<'a> {
+pub struct Node {
     node_type: NodeType,
-    parent:    Option<Weak<RefCell<Node<'a>>>>, // optional; weak ref to parent-made-mutable
-    children:  Vec<Rc<RefCell<Node<'a>>>>,   // strong references to children-made-mutable through RefCell
+    parent:    Option<Weak<RefCell<Node>>>, // optional; weak ref to parent-made-mutable
+    children:  Vec<Rc<RefCell<Node>>>,   // strong references to children-made-mutable through RefCell
     state:     *mut RsvgState,
-    node_impl: &'a NodeTrait
+    node_impl: Box<NodeTrait>
 }
 
 /* Keep this in sync with rsvg-private.h:RsvgNodeType */
@@ -88,11 +92,11 @@ pub enum NodeType {
     FilterPrimitiveLast                /* just a marker; not a valid type */
 }
 
-impl<'a> Node<'a> {
+impl Node {
     pub fn new (node_type: NodeType,
-                parent:    Option<Weak<RefCell<Node<'a>>>>,
+                parent:    Option<Weak<RefCell<Node>>>,
                 state:     *mut RsvgState,
-                node_impl: &'a NodeTrait) -> Node<'a> {
+                node_impl: Box<NodeTrait>) -> Node {
         Node {
             node_type: node_type,
             parent:    parent,
@@ -110,53 +114,56 @@ impl<'a> Node<'a> {
         self.state
     }
 
-    pub fn add_child (&mut self, child: &Rc<RefCell<Node<'a>>>) {
+    pub fn add_child (&mut self, child: &Rc<RefCell<Node>>) {
         self.children.push (child.clone ());
     }
 }
 
-pub enum RsvgNode {}
-
-/* This is just to take a pointer to an Rc<RefCell<Node<'a>>> */
-type RsvgRcNode<'a> = Rc<RefCell<Node<'a>>>;
-
 #[no_mangle]
-pub extern fn rsvg_node_get_type<'a> (raw_node: *const RsvgRcNode<'a>) -> NodeType {
+pub extern fn rsvg_node_get_type (raw_node: *const RsvgRcNode) -> NodeType {
     assert! (!raw_node.is_null ());
-    let node: &RsvgRcNode<'a> = unsafe { & *raw_node };
+    let node: &RsvgRcNode = unsafe { & *raw_node };
 
     node.borrow ().get_type ()
 }
 
 #[no_mangle]
-pub extern fn rsvg_node_get_parent<'a> (raw_node: *const RsvgRcNode<'a>) -> *const RsvgRcNode<'a> {
+pub extern fn rsvg_node_get_parent (raw_node: *const RsvgRcNode) -> *const RsvgRcNode {
     assert! (!raw_node.is_null ());
-    let rc_node: &RsvgRcNode<'a> = unsafe { & *raw_node };
+    let rc_node: &RsvgRcNode = unsafe { & *raw_node };
 
     match rc_node.borrow ().parent {
         None => { ptr::null () }
 
         Some (ref weak_node) => {
             let strong_node = weak_node.upgrade ().unwrap ();
-            &strong_node as *const RsvgRcNode<'a>
+            &strong_node as *const RsvgRcNode
         }
     }
 }
 
 #[no_mangle]
-pub extern fn rsvg_node_get_state<'a> (raw_node: *const RsvgRcNode<'a>) -> *mut RsvgState {
+pub extern fn rsvg_node_unref (raw_node: *const RsvgRcNode) {
+    assert! (!raw_node.is_null ());
+    let rc_node: &RsvgRcNode = unsafe { & *raw_node };
+
+    drop (rc_node);
+}
+
+#[no_mangle]
+pub extern fn rsvg_node_get_state (raw_node: *const RsvgRcNode) -> *mut RsvgState {
     assert! (!raw_node.is_null ());
-    let rc_node: &RsvgRcNode<'a> = unsafe { & *raw_node };
+    let rc_node: &RsvgRcNode = unsafe { & *raw_node };
 
     rc_node.borrow ().get_state ()
 }
 
 #[no_mangle]
-pub extern fn rsvg_node_add_child<'a> (raw_node: *mut RsvgRcNode<'a>, raw_child: *const RsvgRcNode<'a>) {
+pub extern fn rsvg_node_add_child (raw_node: *mut RsvgRcNode, raw_child: *const RsvgRcNode) {
     assert! (!raw_node.is_null ());
     assert! (!raw_child.is_null ());
-    let rc_node: &mut RsvgRcNode<'a> = unsafe { &mut *raw_node };
-    let rc_child: &RsvgRcNode<'a> = unsafe { & *raw_child };
+    let rc_node: &mut RsvgRcNode = unsafe { &mut *raw_node };
+    let rc_child: &RsvgRcNode = unsafe { & *raw_child };
 
     rc_node.borrow_mut ().add_child (rc_child);
 }
diff --git a/rust/src/shapes.rs b/rust/src/shapes.rs
index 57fd1f8..5b61ba9 100644
--- a/rust/src/shapes.rs
+++ b/rust/src/shapes.rs
@@ -25,7 +25,7 @@ impl NodePath {
 }
 
 impl NodeTrait for NodePath {
-    fn set_atts (&self, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) {
+    fn set_atts (&self, node: &RsvgRcNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) {
         if let Some (value) = property_bag::lookup (pbag, "d") {
             let mut builder = self.builder.borrow_mut ();
 
@@ -36,7 +36,7 @@ impl NodeTrait for NodePath {
         }
     }
 
-    fn draw (&self, draw_ctx: *const RsvgDrawingCtx, dominate: i32) {
+    fn draw (&self, node: &RsvgRcNode, draw_ctx: *const RsvgDrawingCtx, dominate: i32) {
         drawing_ctx::state_reinherit_top (draw_ctx, self.state, dominate);
         drawing_ctx::render_path_builder (draw_ctx, & *self.builder.borrow ());
     }


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