Port standard_element_start() to Rust

Now the create_fn in load.rs can deal with RsvgNode directly, instead
of boxed versions.
parent fb42d16c
......@@ -37,14 +37,6 @@ typedef enum {
LOAD_STATE_CLOSED
} LoadState;
/* Implemented in rsvg_internals/src/load.rs */
G_GNUC_INTERNAL
RsvgNode *rsvg_load_new_node (const char *element_name, RsvgNode *parent, RsvgPropertyBag *atts, RsvgDefs *defs);
/* Implemented in rsvg_internals/src/load.rs */
G_GNUC_INTERNAL
void rsvg_load_set_node_atts (RsvgHandle *handle, RsvgNode *node, RsvgPropertyBag atts);
/* Implemented in rsvg_internals/src/load.rs */
G_GNUC_INTERNAL
void rsvg_load_set_svg_node_atts (RsvgHandle *handle, RsvgNode *node);
......@@ -67,6 +59,7 @@ extern void rsvg_xml_state_push_element_name(RsvgXmlState *xml, const char *name
extern void rsvg_xml_state_pop_element_name(RsvgXmlState *xml);
extern gboolean rsvg_xml_state_topmost_element_name_is(RsvgXmlState *xml, const char *name);
extern void rsvg_xml_state_free_element_name_stack(RsvgXmlState *xml);
extern void rsvg_xml_state_standard_element_start(RsvgXmlState *xml, RsvgHandle *handle, const char *name, RsvgPropertyBag atts);
/* Holds the XML parsing state */
typedef struct {
......@@ -265,35 +258,6 @@ start_style (RsvgLoad *load, RsvgPropertyBag *atts)
rsvg_property_bag_iter_end (iter);
}
static void
standard_element_start (RsvgLoad *load, const char *name, RsvgPropertyBag * atts)
{
RsvgDefs *defs;
RsvgNode *current_node;
RsvgNode *newnode;
defs = rsvg_handle_get_defs(load->handle);
current_node = rsvg_xml_state_get_current_node (load->xml.rust_state);
newnode = rsvg_load_new_node (name, current_node, atts, defs);
rsvg_xml_state_push_element_name (load->xml.rust_state, name);
if (current_node) {
rsvg_node_add_child (current_node, newnode);
} else if (is_svg) {
rsvg_xml_state_set_root (load->xml.rust_state, newnode);
}
rsvg_xml_state_set_current_node (load->xml.rust_state, newnode);
current_node = rsvg_node_unref (current_node);
rsvg_load_set_node_atts (load->handle, newnode, atts);
newnode = rsvg_node_unref (newnode);
}
/* start xinclude */
typedef struct _RsvgSaxHandlerXinclude {
......@@ -333,8 +297,12 @@ xinclude_handler_start (RsvgSaxHandler * self, const char *name, RsvgPropertyBag
if (z->in_fallback) {
if (!strcmp (name, "xi:include"))
start_xinclude (z->load, atts);
else
standard_element_start (z->load, (const char *) name, atts);
else {
rsvg_xml_state_standard_element_start (z->load->xml.rust_state,
z->load->handle,
(const char *) name,
atts);
}
} else if (!strcmp (name, "xi:fallback")) {
z->in_fallback = TRUE;
}
......@@ -603,8 +571,12 @@ sax_start_element_cb (void *data, const xmlChar * name, const xmlChar ** atts)
start_style (load, bag);
else if (!strcmp ((const char *) name, "include")) /* xi:include */
start_xinclude (load, bag);
else
standard_element_start (load, (const char *) name, bag);
else {
rsvg_xml_state_standard_element_start (load->xml.rust_state,
load->handle,
(const char *) name,
bag);
}
}
rsvg_property_bag_free (bag);
......
......@@ -35,10 +35,10 @@ extern "C" {
) -> *mut u8;
}
pub fn get_defs<'a>(handle: *const RsvgHandle) -> &'a Defs {
pub fn get_defs<'a>(handle: *const RsvgHandle) -> &'a mut Defs {
unsafe {
let d = rsvg_handle_get_defs(handle);
&*(d as *const Defs)
&mut *(d as *mut Defs)
}
}
......
......@@ -44,7 +44,7 @@ pub use drawing_ctx::{
rsvg_drawing_ctx_new,
};
pub use load::{rsvg_load_new_node, rsvg_load_set_node_atts, rsvg_load_set_svg_node_atts};
pub use load::rsvg_load_set_svg_node_atts;
pub use node::{
rsvg_node_add_child,
......@@ -86,6 +86,7 @@ pub use xml::{
rsvg_xml_state_push_element_name,
rsvg_xml_state_set_current_node,
rsvg_xml_state_set_root,
rsvg_xml_state_standard_element_start,
rsvg_xml_state_steal_tree,
rsvg_xml_state_topmost_element_name_is,
};
......
use libc;
use std::collections::HashMap;
use attributes::Attribute;
use clip_path::NodeClipPath;
use defs::{Defs, RsvgDefs};
use defs::Defs;
use filters::{
blend::Blend,
color_matrix::ColorMatrix,
......@@ -35,7 +34,6 @@ use shapes::{NodeCircle, NodeEllipse, NodeLine, NodePath, NodePoly, NodeRect};
use stop::NodeStop;
use structure::{NodeDefs, NodeGroup, NodeSvg, NodeSwitch, NodeSymbol, NodeUse};
use text::{NodeTRef, NodeTSpan, NodeText};
use util::utf8_cstr;
macro_rules! node_create_fn {
($name:ident, $node_type:ident, $new_fn:expr) => {
......@@ -43,9 +41,9 @@ macro_rules! node_create_fn {
element_name: &str,
id: Option<&str>,
class: Option<&str>,
parent: *const RsvgNode,
) -> *const RsvgNode {
boxed_node_new(
parent: Option<&RsvgNode>,
) -> RsvgNode {
node_new(
NodeType::$node_type,
parent,
element_name,
......@@ -176,7 +174,8 @@ node_create_fn!(
);
node_create_fn!(create_use, Use, NodeUse::new);
type NodeCreateFn = fn(&str, Option<&str>, Option<&str>, *const RsvgNode) -> *const RsvgNode;
type NodeCreateFn =
fn(name: &str, id: Option<&str>, class: Option<&str>, parent: Option<&RsvgNode>) -> RsvgNode;
lazy_static! {
// Lines in comments are elements that we don't support.
......@@ -271,21 +270,12 @@ lazy_static! {
};
}
#[no_mangle]
pub extern "C" fn rsvg_load_new_node(
raw_name: *const libc::c_char,
parent: *const RsvgNode,
pbag: *const PropertyBag<'_>,
defs: *mut RsvgDefs,
) -> *const RsvgNode {
assert!(!raw_name.is_null());
assert!(!pbag.is_null());
assert!(!defs.is_null());
let name = unsafe { utf8_cstr(raw_name) };
let pbag = unsafe { &*pbag };
let defs = unsafe { &mut *(defs as *mut Defs) };
pub fn rsvg_load_new_node(
name: &str,
parent: Option<&RsvgNode>,
pbag: &PropertyBag,
defs: &mut Defs,
) -> RsvgNode {
let mut id = None;
let mut class = None;
......@@ -310,28 +300,20 @@ pub extern "C" fn rsvg_load_new_node(
};
let node = create_fn(name, id, class, parent);
assert!(!node.is_null());
if id.is_some() {
let n = unsafe { &*node };
defs.insert(id.unwrap(), n);
defs.insert(id.unwrap(), &node);
}
node
}
#[no_mangle]
pub extern "C" fn rsvg_load_set_node_atts(
pub fn rsvg_load_set_node_atts(
handle: *const RsvgHandle,
raw_node: *mut RsvgNode,
pbag: *const PropertyBag<'_>,
node: &RsvgNode,
tag: &str,
pbag: &PropertyBag,
) {
assert!(!raw_node.is_null());
assert!(!pbag.is_null());
let node: &RsvgNode = unsafe { &*raw_node };
let pbag = unsafe { &*pbag };
node.set_atts(node, handle, pbag);
// The "svg" node is special; it will load its id/class
......
......@@ -672,6 +672,29 @@ pub fn boxed_node_new(
)))
}
pub fn node_new(
node_type: NodeType,
parent: Option<&RsvgNode>,
element_name: &str,
id: Option<&str>,
class: Option<&str>,
node_impl: Box<NodeTrait>,
) -> RsvgNode {
Rc::new(Node::new(
node_type,
if let Some(parent) = parent {
Some(Rc::downgrade(parent))
} else {
None
},
element_name,
id,
class,
rsvg_state_new(),
node_impl,
))
}
impl Children {
fn new(next: Option<Rc<Node>>, next_back: Option<Rc<Node>>) -> Self {
Self { next, next_back }
......
......@@ -5,7 +5,10 @@ use std::rc::Rc;
use glib::translate::*;
use glib_sys;
use handle::{self, RsvgHandle};
use load::{rsvg_load_new_node, rsvg_load_set_node_atts};
use node::{box_node, Node, RsvgNode};
use property_bag::PropertyBag;
use tree::{RsvgTree, Tree};
use util::utf8_cstr;
......@@ -71,6 +74,36 @@ impl XmlState {
pub fn free_element_name_stack(&mut self) {
self.element_name_stack.clear();
}
pub fn standard_element_start(
&mut self,
handle: *const RsvgHandle,
name: &str,
pbag: &PropertyBag,
) {
let mut defs = handle::get_defs(handle);
let mut is_svg = false;
let new_node = rsvg_load_new_node(
name,
self.current_node.as_ref(),
pbag,
&mut defs,
&mut is_svg,
);
self.push_element_name(name);
if let Some(ref current_node) = self.current_node {
current_node.add_child(&new_node);
} else if is_svg {
self.set_root(&new_node);
}
self.set_current_node(Some(new_node.clone()));
rsvg_load_set_node_atts(handle, &new_node, name, pbag);
}
}
#[no_mangle]
......@@ -183,3 +216,22 @@ pub extern "C" fn rsvg_xml_state_free_element_name_stack(xml: *mut RsvgXmlState)
xml.free_element_name_stack();
}
#[no_mangle]
pub extern "C" fn rsvg_xml_state_standard_element_start(
xml: *mut RsvgXmlState,
handle: *const RsvgHandle,
name: *const libc::c_char,
pbag: *const PropertyBag,
) {
assert!(!xml.is_null());
let xml = unsafe { &mut *(xml as *mut XmlState) };
assert!(!name.is_null());
let name = unsafe { utf8_cstr(name) };
assert!(!pbag.is_null());
let pbag = unsafe { &*pbag };
xml.standard_element_start(handle, name, pbag);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment