[librsvg] cnode.rs: New stub for having a node implemented in C, accessible from Rust
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] cnode.rs: New stub for having a node implemented in C, accessible from Rust
- Date: Fri, 17 Feb 2017 16:37:52 +0000 (UTC)
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]