[librsvg] structure.rs: Finish moving NodeSvg over to Rust. Yay!
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] structure.rs: Finish moving NodeSvg over to Rust. Yay!
- Date: Thu, 23 Mar 2017 00:44:33 +0000 (UTC)
commit 91ef809cb41fcf7b20f53bd236053b3a39f336a9
Author: Federico Mena Quintero <federico gnome org>
Date: Wed Mar 22 16:29:33 2017 -0600
structure.rs: Finish moving NodeSvg over to Rust. Yay!
rsvg-base.c | 8 +--
rsvg-structure.c | 193 -----------------------------------------------
rsvg-structure.h | 11 ++-
rust/src/lib.rs | 4 +
rust/src/structure.rs | 201 +++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 214 insertions(+), 203 deletions(-)
---
diff --git a/rsvg-base.c b/rsvg-base.c
index 07c59f5..23ef4da 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -325,7 +325,7 @@ static const NodeCreator node_creators[] = {
/* "style", FALSE, */
{ "subImage", FALSE, rsvg_node_group_new },
{ "subImageRef", FALSE, rsvg_new_image },
- { "svg", TRUE, rsvg_new_svg },
+ { "svg", TRUE, rsvg_node_svg_new },
{ "switch", TRUE, rsvg_node_switch_new },
{ "symbol", TRUE, rsvg_new_symbol },
{ "text", TRUE, rsvg_new_text },
@@ -843,12 +843,8 @@ rsvg_end_element (void *data, const xmlChar * xmlname)
/* FIXMEchpe: shouldn't this check that currentnode == treebase or sth like that? */
if (ctx->priv->treebase && !strcmp (name, "svg")) {
- RsvgNodeSvg *svg;
-
g_assert (rsvg_node_get_type (ctx->priv->treebase) == RSVG_NODE_TYPE_SVG);
- svg = rsvg_rust_cnode_get_impl (ctx->priv->treebase);
-
- _rsvg_node_svg_apply_atts (ctx->priv->treebase, svg, ctx);
+ rsvg_node_svg_apply_atts (ctx->priv->treebase, ctx);
}
}
}
diff --git a/rsvg-structure.c b/rsvg-structure.c
index 991e62a..7dc13c9 100644
--- a/rsvg-structure.c
+++ b/rsvg-structure.c
@@ -47,199 +47,6 @@ struct _RsvgNodeUse {
RsvgLength x, y, w, h;
};
-struct _RsvgNodeSvg {
- guint32 preserve_aspect_ratio;
- RsvgLength x, y, w, h;
- RsvgViewBox vbox;
- RsvgPropertyBag *atts;
-};
-
-static gboolean
-draw_child (RsvgNode *node, gpointer data)
-{
- RsvgDrawingCtx *ctx;
-
- ctx = data;
-
- rsvg_drawing_ctx_draw_node_from_stack (ctx, node, 0);
-
- return TRUE;
-}
-
-static void
-rsvg_node_svg_draw (RsvgNode *node, gpointer impl, RsvgDrawingCtx *ctx, int dominate)
-{
- RsvgNodeSvg *svg = impl;
- RsvgState *state;
- cairo_matrix_t affine, affine_old, affine_new;
- double nx, ny, nw, nh;
- RsvgNode *parent;
-
- nx = rsvg_length_normalize (&svg->x, ctx);
- ny = rsvg_length_normalize (&svg->y, ctx);
- nw = rsvg_length_normalize (&svg->w, ctx);
- nh = rsvg_length_normalize (&svg->h, ctx);
-
- rsvg_state_reinherit_top (ctx, rsvg_node_get_state (node), dominate);
-
- state = rsvg_current_state (ctx);
-
- affine_old = state->affine;
-
- if (svg->vbox.active) {
- double x = nx, y = ny, w = nw, h = nh;
- rsvg_aspect_ratio_compute (svg->preserve_aspect_ratio,
- svg->vbox.rect.width,
- svg->vbox.rect.height,
- &x, &y, &w, &h);
- cairo_matrix_init (&affine,
- w / svg->vbox.rect.width,
- 0,
- 0,
- h / svg->vbox.rect.height,
- x - svg->vbox.rect.x * w / svg->vbox.rect.width,
- y - svg->vbox.rect.y * h / svg->vbox.rect.height);
- cairo_matrix_multiply (&state->affine, &affine, &state->affine);
- rsvg_drawing_ctx_push_view_box (ctx, svg->vbox.rect.width, svg->vbox.rect.height);
- } else {
- cairo_matrix_init_translate (&affine, nx, ny);
- cairo_matrix_multiply (&state->affine, &affine, &state->affine);
- rsvg_drawing_ctx_push_view_box (ctx, nw, nh);
- }
-
- affine_new = state->affine;
-
- rsvg_push_discrete_layer (ctx);
-
- /* Bounding box addition must be AFTER the discrete layer push,
- which must be AFTER the transformation happens. */
- parent = rsvg_node_get_parent (node);
-
- if (!state->overflow && parent) {
- state->affine = affine_old;
- rsvg_drawing_ctx_add_clipping_rect (ctx, nx, ny, nw, nh);
- state->affine = affine_new;
- }
-
- parent = rsvg_node_unref (parent);
-
- rsvg_node_foreach_child (node, draw_child, ctx);
-
- rsvg_pop_discrete_layer (ctx);
- rsvg_drawing_ctx_pop_view_box (ctx);
-}
-
-static void
-rsvg_node_svg_set_atts (RsvgNode *node, gpointer impl, RsvgHandle *handle, RsvgPropertyBag *atts)
-{
- const char *value;
- RsvgNodeSvg *svg = impl;
- RsvgNode *parent;
-
- if ((value = rsvg_property_bag_lookup (atts, "viewBox")))
- svg->vbox = rsvg_css_parse_vbox (value);
-
- if ((value = rsvg_property_bag_lookup (atts, "preserveAspectRatio")))
- svg->preserve_aspect_ratio = rsvg_aspect_ratio_parse (value);
- if ((value = rsvg_property_bag_lookup (atts, "width")))
- svg->w = rsvg_length_parse (value, LENGTH_DIR_HORIZONTAL);
- if ((value = rsvg_property_bag_lookup (atts, "height")))
- svg->h = rsvg_length_parse (value, LENGTH_DIR_VERTICAL);
- /*
- * x & y attributes have no effect on outermost svg
- * http://www.w3.org/TR/SVG/struct.html#SVGElement
- */
- parent = rsvg_node_get_parent (node);
-
- if (parent) {
- if ((value = rsvg_property_bag_lookup (atts, "x")))
- svg->x = rsvg_length_parse (value, LENGTH_DIR_HORIZONTAL);
-
- if ((value = rsvg_property_bag_lookup (atts, "y")))
- svg->y = rsvg_length_parse (value, LENGTH_DIR_VERTICAL);
- }
-
- parent = rsvg_node_unref (parent);
-
- /*
- * style element is not loaded yet here, so we need to store those attribues
- * to be applied later.
- */
- svg->atts = rsvg_property_bag_dup (atts);
-}
-
-void
-rsvg_node_svg_get_size (RsvgNode *node, RsvgLength *out_width, RsvgLength *out_height)
-{
- RsvgNodeSvg *svg;
-
- g_assert (rsvg_node_get_type (node) == RSVG_NODE_TYPE_SVG);
- svg = rsvg_rust_cnode_get_impl (node);
-
- *out_width = svg->w;
- *out_height = svg->h;
-}
-
-RsvgViewBox
-rsvg_node_svg_get_view_box (RsvgNode *node)
-{
- RsvgNodeSvg *svg;
-
- g_assert (rsvg_node_get_type (node) == RSVG_NODE_TYPE_SVG);
- svg = rsvg_rust_cnode_get_impl (node);
-
- return svg->vbox;
-}
-
-void
-_rsvg_node_svg_apply_atts (RsvgNode *node, RsvgNodeSvg *svg, RsvgHandle *ctx)
-{
- const char *id = NULL, *klazz = NULL, *value;
- if (svg->atts && rsvg_property_bag_size (svg->atts)) {
- if ((value = rsvg_property_bag_lookup (svg->atts, "class")))
- klazz = value;
- if ((value = rsvg_property_bag_lookup (svg->atts, "id")))
- id = value;
- rsvg_parse_style_attrs (ctx, node, "svg", klazz, id, svg->atts);
- }
-}
-
-static void
-rsvg_node_svg_free (gpointer impl)
-{
- RsvgNodeSvg *svg = impl;
-
- if (svg->atts) {
- rsvg_property_bag_free (svg->atts);
- svg->atts = NULL;
- }
-
- g_free (svg);
-}
-
-RsvgNode *
-rsvg_new_svg (const char *element_name, RsvgNode *parent)
-{
- RsvgNodeSvg *svg;
-
- svg = g_new0 (RsvgNodeSvg, 1);
- svg->vbox.active = FALSE;
- svg->preserve_aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
- svg->x = rsvg_length_parse ("0", LENGTH_DIR_HORIZONTAL);
- svg->y = rsvg_length_parse ("0", LENGTH_DIR_VERTICAL);
- svg->w = rsvg_length_parse ("100%", LENGTH_DIR_HORIZONTAL);
- svg->h = rsvg_length_parse ("100%", LENGTH_DIR_VERTICAL);
- svg->atts = NULL;
-
- return rsvg_rust_cnode_new (RSVG_NODE_TYPE_SVG,
- parent,
- rsvg_state_new (),
- svg,
- rsvg_node_svg_set_atts,
- rsvg_node_svg_draw,
- rsvg_node_svg_free);
-}
-
static gboolean
rsvg_node_is_ancestor (RsvgNode *potential_ancestor, RsvgNode *descendant)
{
diff --git a/rsvg-structure.h b/rsvg-structure.h
index 2064366..077ce63 100644
--- a/rsvg-structure.h
+++ b/rsvg-structure.h
@@ -40,8 +40,6 @@ G_GNUC_INTERNAL
RsvgNode *rsvg_new_use (const char *element_name, RsvgNode *parent);
G_GNUC_INTERNAL
RsvgNode *rsvg_new_symbol (const char *element_name, RsvgNode *parent);
-G_GNUC_INTERNAL
-RsvgNode *rsvg_new_svg (const char *element_name, RsvgNode *parent);
/* Implemented in rust/src/structure.rs */
G_GNUC_INTERNAL
@@ -55,16 +53,21 @@ RsvgNode *rsvg_node_defs_new (const char *element_name, RsvgNode *parent);
G_GNUC_INTERNAL
RsvgNode *rsvg_node_switch_new (const char *element_name, RsvgNode *parent);
-typedef struct _RsvgNodeSvg RsvgNodeSvg;
+/* Implemented in rust/src/structure.rs */
+G_GNUC_INTERNAL
+RsvgNode *rsvg_node_svg_new (const char *element_name, RsvgNode *parent);
+/* Implemented in rust/src/structure.rs */
G_GNUC_INTERNAL
void rsvg_node_svg_get_size (RsvgNode *node, RsvgLength *out_width, RsvgLength *out_height);
+/* Implemented in rust/src/structure.rs */
G_GNUC_INTERNAL
RsvgViewBox rsvg_node_svg_get_view_box (RsvgNode *node);
+/* Implemented in rust/src/structure.rs */
G_GNUC_INTERNAL
-void _rsvg_node_svg_apply_atts (RsvgNode *node, RsvgNodeSvg *svg, RsvgHandle * ctx);
+void rsvg_node_svg_apply_atts (RsvgNode *node, RsvgHandle *handle);
G_END_DECLS
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index dbea38b..affdb7e 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -95,6 +95,10 @@ pub use structure::{
rsvg_node_group_new,
rsvg_node_defs_new,
rsvg_node_switch_new,
+ rsvg_node_svg_new,
+ rsvg_node_svg_get_size,
+ rsvg_node_svg_get_view_box,
+ rsvg_node_svg_apply_atts,
};
pub use transform::{
diff --git a/rust/src/structure.rs b/rust/src/structure.rs
index ca91d1e..a06d767 100644
--- a/rust/src/structure.rs
+++ b/rust/src/structure.rs
@@ -1,11 +1,25 @@
+extern crate glib;
+extern crate cairo;
extern crate libc;
+use self::glib::translate::*;
+
+use std::cell::Cell;
+use std::ptr;
+
+use aspect_ratio::*;
use drawing_ctx::RsvgDrawingCtx;
use drawing_ctx;
use handle::RsvgHandle;
+use length::*;
use node::*;
use property_bag;
use property_bag::*;
+use util::*;
+use viewbox::*;
+
+use self::cairo::MatrixTrait;
+
/***** NodeGroup *****/
@@ -95,6 +109,128 @@ impl NodeTrait for NodeSwitch {
}
}
+/***** NodeSvg *****/
+
+struct NodeSvg {
+ preserve_aspect_ratio: Cell<AspectRatio>,
+ x: Cell<RsvgLength>,
+ y: Cell<RsvgLength>,
+ w: Cell<RsvgLength>,
+ h: Cell<RsvgLength>,
+ vbox: Cell<RsvgViewBox>,
+ atts: Cell<*mut RsvgPropertyBag>
+}
+
+impl NodeSvg {
+ fn new () -> NodeSvg {
+ NodeSvg {
+ preserve_aspect_ratio: Cell::new (AspectRatio::default ()),
+ x: Cell::new (RsvgLength::parse ("0", LengthDir::Horizontal).unwrap ()),
+ y: Cell::new (RsvgLength::parse ("0", LengthDir::Vertical).unwrap ()),
+ w: Cell::new (RsvgLength::parse ("100%", LengthDir::Horizontal).unwrap ()),
+ h: Cell::new (RsvgLength::parse ("100%", LengthDir::Vertical).unwrap ()),
+ vbox: Cell::new (RsvgViewBox::default ()),
+ atts: Cell::new (ptr::null_mut ())
+ }
+ }
+}
+
+impl NodeTrait for NodeSvg {
+ fn set_atts (&self, node: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
+ self.preserve_aspect_ratio.set (property_bag::parse_or_default (pbag, "preserveAspectRatio")?);
+
+ // x & y attributes have no effect on outermost svg
+ // http://www.w3.org/TR/SVG/struct.html#SVGElement
+ if node.get_parent ().is_some () {
+ self.x.set (property_bag::length_or_default (pbag, "x", LengthDir::Horizontal)?);
+ self.y.set (property_bag::length_or_default (pbag, "y", LengthDir::Vertical)?);
+ }
+
+ self.w.set (property_bag::length_or_value (pbag, "width", LengthDir::Horizontal, "100%")?);
+ self.h.set (property_bag::length_or_value (pbag, "height", LengthDir::Vertical, "100%")?);
+
+ self.vbox.set (property_bag::parse_or_default (pbag, "viewBox")?);
+
+ // The "style" sub-element is not loaded yet here, so we need
+ // to store other attributes to be applied later.
+ self.atts.set (property_bag::dup (pbag));
+
+ Ok (())
+ }
+
+ fn draw (&self, node: &RsvgNode, draw_ctx: *const RsvgDrawingCtx, dominate: i32) {
+ let nx = self.x.get ().normalize (draw_ctx);
+ let ny = self.y.get ().normalize (draw_ctx);
+ let nw = self.w.get ().normalize (draw_ctx);
+ let nh = self.h.get ().normalize (draw_ctx);
+
+ drawing_ctx::state_reinherit_top (draw_ctx, node.get_state (), dominate);
+
+ let state = drawing_ctx::get_current_state (draw_ctx);
+
+ let affine_old = drawing_ctx::get_current_state_affine (draw_ctx);
+
+ let vbox = self.vbox.get ();
+
+ if vbox.active {
+ // viewBox width==0 or height==0 disables rendering of the element
+ // https://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute
+ if double_equals (vbox.rect.width, 0.0) || double_equals (vbox.rect.height, 0.0) {
+ return;
+ }
+
+ let (x, y, w, h) = self.preserve_aspect_ratio.get ().compute (vbox.rect.width, vbox.rect.height,
+ nx, ny, nw, nh);
+
+ let affine = cairo::Matrix::new (w / vbox.rect.width,
+ 0.0,
+ 0.0,
+ h / vbox.rect.height,
+ x - vbox.rect.x * w / vbox.rect.width,
+ y - vbox.rect.y * h / vbox.rect.height);
+
+ drawing_ctx::set_current_state_affine (draw_ctx, cairo::Matrix::multiply (&affine, &affine_old));
+
+ drawing_ctx::push_view_box (draw_ctx, vbox.rect.width, vbox.rect.height);
+ } else {
+ let mut affine = affine_old;
+ affine.translate (nx, ny);
+
+ drawing_ctx::set_current_state_affine (draw_ctx, affine);
+ drawing_ctx::push_view_box (draw_ctx, nw, nh);
+ }
+
+ let affine_new = drawing_ctx::get_current_state_affine (draw_ctx);
+
+ drawing_ctx::push_discrete_layer (draw_ctx);
+
+ // Bounding box addition must be AFTER the discrete layer
+ // push, which must be AFTER the transformation happens.
+
+ if !drawing_ctx::state_is_overflow (state) && node.get_parent ().is_some () {
+ drawing_ctx::set_current_state_affine (draw_ctx, affine_old);
+ drawing_ctx::add_clipping_rect (draw_ctx, nx, ny, nw, nh);
+ drawing_ctx::set_current_state_affine (draw_ctx, affine_new);
+ }
+
+ node.draw_children (draw_ctx, -1); // dominate==-1 so it won't reinherit or push a layer
+
+ drawing_ctx::pop_discrete_layer (draw_ctx);
+ drawing_ctx::pop_view_box (draw_ctx);
+ }
+
+ fn get_c_impl (&self) -> *const RsvgCNodeImpl {
+ unreachable! ();
+ }
+}
+
+impl Drop for NodeSvg {
+ fn drop (&mut self) {
+ property_bag::free (self.atts.get ());
+ self.atts.set (ptr::null_mut ());
+ }
+}
+
/***** C Prototypes *****/
#[no_mangle]
@@ -117,3 +253,68 @@ pub extern fn rsvg_node_switch_new (_: *const libc::c_char, raw_parent: *const R
raw_parent,
Box::new (NodeSwitch::new ()))
}
+
+#[no_mangle]
+pub extern fn rsvg_node_svg_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
+ boxed_node_new (NodeType::Svg,
+ raw_parent,
+ Box::new (NodeSvg::new ()))
+}
+
+#[no_mangle]
+pub extern fn rsvg_node_svg_get_size (raw_node: *const RsvgNode, out_width: *mut RsvgLength, out_height:
*mut RsvgLength) {
+ assert! (!raw_node.is_null ());
+ let node: &RsvgNode = unsafe { & *raw_node };
+
+ assert! (!out_width.is_null ());
+ assert! (!out_height.is_null ());
+
+ node.with_impl (|svg: &NodeSvg| {
+ unsafe {
+ *out_width = svg.w.get ();
+ *out_height = svg.h.get ();
+ }
+ });
+}
+
+#[no_mangle]
+pub extern fn rsvg_node_svg_get_view_box (raw_node: *const RsvgNode) -> RsvgViewBox {
+ assert! (!raw_node.is_null ());
+ let node: &RsvgNode = unsafe { & *raw_node };
+
+ let mut vbox = RsvgViewBox::default ();
+
+ node.with_impl (|svg: &NodeSvg| {
+ vbox = svg.vbox.get ();
+ });
+
+ vbox
+}
+
+extern "C" {
+ fn rsvg_parse_style_attrs (handle: *const RsvgHandle,
+ node: *const RsvgNode,
+ tag: *const libc::c_char,
+ class: *const libc::c_char,
+ id: *const libc::c_char,
+ pbag: *const RsvgPropertyBag);
+}
+
+#[no_mangle]
+pub extern fn rsvg_node_svg_apply_atts (raw_node: *const RsvgNode, handle: *const RsvgHandle) {
+ assert! (!raw_node.is_null ());
+ let node: &RsvgNode = unsafe { & *raw_node };
+
+ node.with_impl (|svg: &NodeSvg| {
+ let pbag = svg.atts.get ();
+ let class = property_bag::lookup (pbag, "class");
+ let id = property_bag::lookup (pbag, "id");
+
+ unsafe { rsvg_parse_style_attrs (handle,
+ raw_node,
+ str::to_glib_none ("svg").0,
+ class.map_or (ptr::null (), |s| String::to_glib_none (&s).0),
+ id.map_or (ptr::null (), |s| String::to_glib_none (&s).0),
+ pbag); }
+ });
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]