Commit 53dca862 authored by Saurav Sachidanand's avatar Saurav Sachidanand Committed by Federico Mena Quintero

Move node creation to Rust

parent b11261f7
......@@ -101,6 +101,7 @@ RUST_SRC = \
rsvg_internals/src/length.rs \
rsvg_internals/src/lib.rs \
rsvg_internals/src/link.rs \
rsvg_internals/src/load.rs \
rsvg_internals/src/marker.rs \
rsvg_internals/src/mask.rs \
rsvg_internals/src/node.rs \
......
......@@ -291,143 +291,6 @@ free_element_name_stack (RsvgLoad *load)
load->element_name_stack = NULL;
}
typedef RsvgNode *(* CreateNodeFn) (const char *element_name, RsvgNode *parent);
typedef struct {
const char *element_name;
gboolean supports_class_attribute; /* from https://www.w3.org/TR/SVG/attindex.html#RegularAttributes */
CreateNodeFn create_fn;
} NodeCreator;
/* Keep these sorted by element_name!
*
* Lines in comments are elements that we don't support.
*/
static const NodeCreator node_creators[] = {
{ "a", TRUE, rsvg_node_link_new },
/* "altGlyph", TRUE, */
/* "altGlyphDef", FALSE, */
/* "altGlyphItem", FALSE, */
/* "animate", FALSE, */
/* "animateColor", FALSE, */
/* "animateMotion", FALSE, */
/* "animateTransform", FALSE, */
{ "circle", TRUE, rsvg_node_circle_new },
{ "clipPath", TRUE, rsvg_node_clip_path_new },
/* "color-profile", FALSE, */
{ "conicalGradient", TRUE, rsvg_node_radial_gradient_new },
/* "cursor", FALSE, */
{ "defs", TRUE, rsvg_node_defs_new },
/* "desc", TRUE, */
{ "ellipse", TRUE, rsvg_node_ellipse_new },
{ "feBlend", TRUE, rsvg_new_filter_primitive_blend },
{ "feColorMatrix", TRUE, rsvg_new_filter_primitive_color_matrix },
{ "feComponentTransfer", TRUE, rsvg_new_filter_primitive_component_transfer },
{ "feComposite", TRUE, rsvg_new_filter_primitive_composite },
{ "feConvolveMatrix", TRUE, rsvg_new_filter_primitive_convolve_matrix },
{ "feDiffuseLighting", TRUE, rsvg_new_filter_primitive_diffuse_lighting },
{ "feDisplacementMap", TRUE, rsvg_new_filter_primitive_displacement_map },
{ "feDistantLight", FALSE, rsvg_new_node_light_source },
{ "feFlood", TRUE, rsvg_new_filter_primitive_flood },
{ "feFuncA", FALSE, rsvg_new_node_component_transfer_function },
{ "feFuncB", FALSE, rsvg_new_node_component_transfer_function },
{ "feFuncG", FALSE, rsvg_new_node_component_transfer_function },
{ "feFuncR", FALSE, rsvg_new_node_component_transfer_function },
{ "feGaussianBlur", TRUE, rsvg_new_filter_primitive_gaussian_blur },
{ "feImage", TRUE, rsvg_new_filter_primitive_image },
{ "feMerge", TRUE, rsvg_new_filter_primitive_merge },
{ "feMergeNode", FALSE, rsvg_new_filter_primitive_merge_node },
{ "feMorphology", TRUE, rsvg_new_filter_primitive_erode },
{ "feOffset", TRUE, rsvg_new_filter_primitive_offset },
{ "fePointLight", FALSE, rsvg_new_node_light_source },
{ "feSpecularLighting", TRUE, rsvg_new_filter_primitive_specular_lighting },
{ "feSpotLight", FALSE, rsvg_new_node_light_source },
{ "feTile", TRUE, rsvg_new_filter_primitive_tile },
{ "feTurbulence", TRUE, rsvg_new_filter_primitive_turbulence },
{ "filter", TRUE, rsvg_new_filter },
/* "font", TRUE, */
/* "font-face", FALSE, */
/* "font-face-format", FALSE, */
/* "font-face-name", FALSE, */
/* "font-face-src", FALSE, */
/* "font-face-uri", FALSE, */
/* "foreignObject", TRUE, */
{ "g", TRUE, rsvg_node_group_new },
/* "glyph", TRUE, */
/* "glyphRef", TRUE, */
/* "hkern", FALSE, */
{ "image", TRUE, rsvg_node_image_new },
{ "line", TRUE, rsvg_node_line_new },
{ "linearGradient", TRUE, rsvg_node_linear_gradient_new },
{ "marker", TRUE, rsvg_node_marker_new },
{ "mask", TRUE, rsvg_node_mask_new },
/* "metadata", FALSE, */
/* "missing-glyph", TRUE, */
/* "mpath" FALSE, */
{ "multiImage", FALSE, rsvg_node_switch_new }, /* hack to make multiImage sort-of work */
{ "path", TRUE, rsvg_node_path_new },
{ "pattern", TRUE, rsvg_node_pattern_new },
{ "polygon", TRUE, rsvg_node_polygon_new },
{ "polyline", TRUE, rsvg_node_polyline_new },
{ "radialGradient", TRUE, rsvg_node_radial_gradient_new },
{ "rect", TRUE, rsvg_node_rect_new },
/* "script", FALSE, */
/* "set", FALSE, */
{ "stop", TRUE, rsvg_node_stop_new },
/* "style", FALSE, */
{ "subImage", FALSE, rsvg_node_group_new },
{ "subImageRef", FALSE, rsvg_node_image_new },
{ "svg", TRUE, rsvg_node_svg_new },
{ "switch", TRUE, rsvg_node_switch_new },
{ "symbol", TRUE, rsvg_node_symbol_new },
{ "text", TRUE, rsvg_node_text_new },
/* "textPath", TRUE, */
/* "title", TRUE, */
{ "tref", TRUE, rsvg_node_tref_new },
{ "tspan", TRUE, rsvg_node_tspan_new },
{ "use", TRUE, rsvg_node_use_new },
/* "view", FALSE, */
/* "vkern", FALSE, */
};
/* Whenever we encounter a node we don't understand, represent it as a defs.
* This is like a group, but it doesn't do any rendering of children. The
* effect is that we will ignore all children of unknown elements.
*/
static const NodeCreator default_node_creator = { NULL, TRUE, rsvg_node_defs_new };
/* Used from bsearch() */
static int
compare_node_creators_fn (const void *a, const void *b)
{
const NodeCreator *na = a;
const NodeCreator *nb = b;
return strcmp (na->element_name, nb->element_name);
}
static const NodeCreator *
get_node_creator_for_element_name (const char *name)
{
NodeCreator key;
const NodeCreator *result;
key.element_name = name;
key.supports_class_attribute = FALSE;
key.create_fn = NULL;
result = bsearch (&key,
node_creators,
G_N_ELEMENTS (node_creators),
sizeof (NodeCreator),
compare_node_creators_fn);
if (result == NULL)
result = &default_node_creator;
return result;
}
static void
node_set_atts (RsvgNode *node,
RsvgHandle *handle,
......@@ -481,13 +344,10 @@ node_set_atts (RsvgNode *node,
static void
standard_element_start (RsvgLoad *load, const char *name, RsvgPropertyBag * atts)
{
const NodeCreator *creator;
RsvgNode *newnode = NULL;
creator = get_node_creator_for_element_name (name);
g_assert (creator != NULL && creator->create_fn != NULL);
newnode = creator->create_fn (name, load->currentnode);
gboolean supports_class_attribute;
RsvgNode *newnode;
newnode = rsvg_load_new_node(name, load->currentnode, &supports_class_attribute);
g_assert (newnode != NULL);
g_assert (rsvg_node_get_type (newnode) != RSVG_NODE_TYPE_INVALID);
......@@ -505,7 +365,7 @@ standard_element_start (RsvgLoad *load, const char *name, RsvgPropertyBag * atts
load->currentnode = rsvg_node_ref (newnode);
node_set_atts (newnode, load->handle, name, creator->supports_class_attribute, atts);
node_set_atts (newnode, load->handle, name, supports_class_attribute, atts);
newnode = rsvg_node_unref (newnode);
}
......
......@@ -34,6 +34,10 @@
G_BEGIN_DECLS
/* Implemented in rust/src/load.rs */
G_GNUC_INTERNAL
RsvgNode *rsvg_load_new_node (const char *element_name, RsvgNode *parent, gboolean *supports_class_attribute);
/* Implemented in rust/src/structure.rs */
G_GNUC_INTERNAL
RsvgNode *rsvg_node_group_new (const char *element_name, RsvgNode *parent);
......
......@@ -79,6 +79,8 @@ pub use image::rsvg_node_image_new;
pub use link::rsvg_node_link_new;
pub use load::rsvg_load_new_node;
pub use marker::rsvg_node_marker_new;
pub use mask::rsvg_node_mask_new;
......@@ -182,6 +184,7 @@ mod image;
mod iri;
mod length;
mod link;
mod load;
mod marker;
mod mask;
mod node;
......
use glib::translate::*;
use glib_sys;
use libc;
use node::*;
use std::collections::HashMap;
use super::*;
use util;
#[allow(improper_ctypes)]
extern "C" {
fn rsvg_new_filter_primitive_blend(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_filter_primitive_color_matrix(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_filter_primitive_component_transfer(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_filter_primitive_composite(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_filter_primitive_convolve_matrix(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_filter_primitive_diffuse_lighting(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_filter_primitive_displacement_map(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_node_light_source(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_filter_primitive_flood(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_node_component_transfer_function(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_filter_primitive_gaussian_blur(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_filter_primitive_image(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_filter_primitive_merge(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_filter_primitive_erode(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_filter_primitive_merge_node(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_filter_primitive_offset(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_filter_primitive_specular_lighting(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_filter_primitive_tile(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_filter_primitive_turbulence(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
fn rsvg_new_filter(_: *const libc::c_char, _: *const RsvgNode) -> *const RsvgNode;
}
type NodeCreateFn = unsafe extern "C" fn(*const libc::c_char, *const RsvgNode) -> *const RsvgNode;
lazy_static! {
// Lines in comments are elements that we don't support.
static ref NODE_CREATORS: HashMap<&'static str, (bool, NodeCreateFn)> = {
let mut h = HashMap::new();
h.insert("a", (true, rsvg_node_link_new as NodeCreateFn));
/* h.insert("altGlyph", (true, as NodeCreateFn)); */
/* h.insert("altGlyphDef", (false, as NodeCreateFn)); */
/* h.insert("altGlyphItem", (false, as NodeCreateFn)); */
/* h.insert("animate", (false, as NodeCreateFn)); */
/* h.insert("animateColor", (false, as NodeCreateFn)); */
/* h.insert("animateMotion", (false, as NodeCreateFn)); */
/* h.insert("animateTransform", (false, as NodeCreateFn)); */
h.insert("circle", (true, rsvg_node_circle_new as NodeCreateFn));
h.insert("clipPath", (true, rsvg_node_clip_path_new as NodeCreateFn));
/* h.insert("color-profile", (false, as NodeCreateFn)); */
h.insert("conicalGradient", (true, rsvg_node_radial_gradient_new as NodeCreateFn));
/* h.insert("cursor", (false, as NodeCreateFn)); */
h.insert("defs", (true, rsvg_node_defs_new as NodeCreateFn));
/* h.insert("desc", (true, as NodeCreateFn)); */
h.insert("ellipse", (true, rsvg_node_ellipse_new as NodeCreateFn));
h.insert("feBlend", (true, rsvg_new_filter_primitive_blend as NodeCreateFn));
h.insert("feColorMatrix", (true, rsvg_new_filter_primitive_color_matrix as NodeCreateFn));
h.insert("feComponentTransfer", (true, rsvg_new_filter_primitive_component_transfer as NodeCreateFn));
h.insert("feComposite", (true, rsvg_new_filter_primitive_composite as NodeCreateFn));
h.insert("feConvolveMatrix", (true, rsvg_new_filter_primitive_convolve_matrix as NodeCreateFn));
h.insert("feDiffuseLighting", (true, rsvg_new_filter_primitive_diffuse_lighting as NodeCreateFn));
h.insert("feDisplacementMap", (true, rsvg_new_filter_primitive_displacement_map as NodeCreateFn));
h.insert("feDistantLight", (false, rsvg_new_node_light_source as NodeCreateFn));
h.insert("feFlood", (true, rsvg_new_filter_primitive_flood as NodeCreateFn));
h.insert("feFuncA", (false, rsvg_new_node_component_transfer_function as NodeCreateFn));
h.insert("feFuncB", (false, rsvg_new_node_component_transfer_function as NodeCreateFn));
h.insert("feFuncG", (false, rsvg_new_node_component_transfer_function as NodeCreateFn));
h.insert("feFuncR", (false, rsvg_new_node_component_transfer_function as NodeCreateFn));
h.insert("feGaussianBlur", (true, rsvg_new_filter_primitive_gaussian_blur as NodeCreateFn));
h.insert("feImage", (true, rsvg_new_filter_primitive_image as NodeCreateFn));
h.insert("feMerge", (true, rsvg_new_filter_primitive_merge as NodeCreateFn));
h.insert("feMergeNode", (false, rsvg_new_filter_primitive_merge_node as NodeCreateFn));
h.insert("feMorphology", (true, rsvg_new_filter_primitive_erode as NodeCreateFn));
h.insert("feOffset", (true, rsvg_new_filter_primitive_offset as NodeCreateFn));
h.insert("fePointLight", (false, rsvg_new_node_light_source as NodeCreateFn));
h.insert("feSpecularLighting", (true, rsvg_new_filter_primitive_specular_lighting as NodeCreateFn));
h.insert("feSpotLight", (false, rsvg_new_node_light_source as NodeCreateFn));
h.insert("feTile", (true, rsvg_new_filter_primitive_tile as NodeCreateFn));
h.insert("feTurbulence", (true, rsvg_new_filter_primitive_turbulence as NodeCreateFn));
h.insert("filter", (true, rsvg_new_filter as NodeCreateFn));
/* h.insert("font", (true, as NodeCreateFn)); */
/* h.insert("font-face", (false, as NodeCreateFn)); */
/* h.insert("font-face-format", (false, as NodeCreateFn)); */
/* h.insert("font-face-name", (false, as NodeCreateFn)); */
/* h.insert("font-face-src", (false, as NodeCreateFn)); */
/* h.insert("font-face-uri", (false, as NodeCreateFn)); */
/* h.insert("foreignObject", (true, as NodeCreateFn)); */
h.insert("g", (true, rsvg_node_group_new as NodeCreateFn));
/* h.insert("glyph", (true, as NodeCreateFn)); */
/* h.insert("glyphRef", (true, as NodeCreateFn)); */
/* h.insert("hkern", (false, as NodeCreateFn)); */
h.insert("image", (true, rsvg_node_image_new as NodeCreateFn));
h.insert("line", (true, rsvg_node_line_new as NodeCreateFn));
h.insert("linearGradient", (true, rsvg_node_linear_gradient_new as NodeCreateFn));
h.insert("marker", (true, rsvg_node_marker_new as NodeCreateFn));
h.insert("mask", (true, rsvg_node_mask_new as NodeCreateFn));
/* h.insert("metadata", (false, as NodeCreateFn)); */
/* h.insert("missing-glyph", (true, as NodeCreateFn)); */
/* h.insert("mpath", (false, as NodeCreateFn)); */
h.insert("multiImage", (false, rsvg_node_switch_new as NodeCreateFn)); /* hack to make multiImage sort-of work */
h.insert("path", (true, rsvg_node_path_new as NodeCreateFn));
h.insert("pattern", (true, rsvg_node_pattern_new as NodeCreateFn));
h.insert("polygon", (true, rsvg_node_polygon_new as NodeCreateFn));
h.insert("polyline", (true, rsvg_node_polyline_new as NodeCreateFn));
h.insert("radialGradient", (true, rsvg_node_radial_gradient_new as NodeCreateFn));
h.insert("rect", (true, rsvg_node_rect_new as NodeCreateFn));
/* h.insert("script", (false, as NodeCreateFn)); */
/* h.insert("set", (false, as NodeCreateFn)); */
h.insert("stop", (true, rsvg_node_stop_new as NodeCreateFn));
/* h.insert("style", (false, as NodeCreateFn)); */
h.insert("subImage", (false, rsvg_node_group_new as NodeCreateFn));
h.insert("subImageRef", (false, rsvg_node_image_new as NodeCreateFn));
h.insert("svg", (true, rsvg_node_svg_new as NodeCreateFn));
h.insert("switch", (true, rsvg_node_switch_new as NodeCreateFn));
h.insert("symbol", (true, rsvg_node_symbol_new as NodeCreateFn));
h.insert("text", (true, rsvg_node_text_new as NodeCreateFn));
/* h.insert("textPath", (true, as NodeCreateFn)); */
/* h.insert("title", (true, as NodeCreateFn)); */
h.insert("tref", (true, rsvg_node_tref_new as NodeCreateFn));
h.insert("tspan", (true, rsvg_node_tspan_new as NodeCreateFn));
h.insert("use", (true, rsvg_node_use_new as NodeCreateFn));
/* h.insert("view", (false, as NodeCreateFn)); */
/* h.insert("vkern", (false, as NodeCreateFn)); */
h
};
}
#[no_mangle]
pub extern "C" fn rsvg_load_new_node(
_name: *const libc::c_char,
parent: *const RsvgNode,
supports_class_attribute: *mut glib_sys::gboolean
) -> *const RsvgNode {
assert!(!_name.is_null());
assert!(!supports_class_attribute.is_null());
let name = unsafe { util::utf8_cstr(_name) };
let creator = match NODE_CREATORS.get(name) {
Some(c) => c,
/* Whenever we encounter a node we don't understand, represent it as a defs.
* This is like a group, but it doesn't do any rendering of children. The
* effect is that we will ignore all children of unknown elements.
*/
None => &(true, rsvg_node_defs_new as NodeCreateFn)
};
unsafe {
*supports_class_attribute = creator.0.to_glib();
creator.1(_name, parent)
}
}
\ No newline at end of file
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