[librsvg] structure.rs: Completely move NodeUse, NodeSymbol to Rust
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg] structure.rs: Completely move NodeUse, NodeSymbol to Rust
- Date: Tue, 16 May 2017 23:02:12 +0000 (UTC)
commit 2b1c4020c51015b3d6508e7fb477314db7a25139
Author: Federico Mena Quintero <federico gnome org>
Date: Tue May 16 18:01:22 2017 -0500
structure.rs: Completely move NodeUse, NodeSymbol to Rust
rsvg-structure.c is no more. Yay!
Makefile.am | 8 +-
rsvg-base.c | 4 +-
rsvg-cairo-render.c | 2 +-
rsvg-defs.h | 1 +
rsvg-image.c | 1 +
rsvg-structure.c | 240 -------------------------------------------------
rsvg-structure.h | 15 ++--
rust/src/lib.rs | 2 +
rust/src/strtod.rs | 174 -----------------------------------
rust/src/structure.rs | 221 +++++++++++++++++++++++++++++++++++++++++++++
10 files changed, 240 insertions(+), 428 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index a96208c..340e8e1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -41,7 +41,6 @@ librsvg_@RSVG_API_MAJOR_VERSION@_la_SOURCES = \
rsvg-mask.c \
rsvg-mask.h \
rsvg-shapes.h \
- rsvg-structure.c \
rsvg-structure.h \
rsvg-styles.c \
rsvg-styles.h \
@@ -76,21 +75,22 @@ RUST_SOURCES = \
rust/src/cnode.rs \
rust/src/drawing_ctx.rs \
rust/src/error.rs \
- rust/src/handle.rs \
rust/src/gradient.rs \
+ rust/src/handle.rs \
rust/src/length.rs \
+ rust/src/lib.rs \
rust/src/marker.rs \
rust/src/node.rs \
rust/src/paint_server.rs \
- rust/src/pt.rs \
rust/src/parsers.rs \
rust/src/parse_transform.lalrpop \
rust/src/path_builder.rs \
rust/src/path_parser.rs \
rust/src/pattern.rs \
rust/src/property_bag.rs \
- rust/src/state.rs \
+ rust/src/pt.rs \
rust/src/shapes.rs \
+ rust/src/state.rs \
rust/src/structure.rs \
rust/src/transform.rs \
rust/src/util.rs \
diff --git a/rsvg-base.c b/rsvg-base.c
index 23ef4da..114e8ec 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -327,13 +327,13 @@ static const NodeCreator node_creators[] = {
{ "subImageRef", FALSE, rsvg_new_image },
{ "svg", TRUE, rsvg_node_svg_new },
{ "switch", TRUE, rsvg_node_switch_new },
- { "symbol", TRUE, rsvg_new_symbol },
+ { "symbol", TRUE, rsvg_node_symbol_new },
{ "text", TRUE, rsvg_new_text },
/* "textPath", TRUE, */
/* "title", TRUE, */
{ "tref", TRUE, rsvg_new_tref },
{ "tspan", TRUE, rsvg_new_tspan },
- { "use", TRUE, rsvg_new_use },
+ { "use", TRUE, rsvg_node_use_new },
/* "view", FALSE, */
/* "vkern", FALSE, */
};
diff --git a/rsvg-cairo-render.c b/rsvg-cairo-render.c
index 48c3507..22a319c 100644
--- a/rsvg-cairo-render.c
+++ b/rsvg-cairo-render.c
@@ -32,7 +32,7 @@
#include <string.h>
#include "rsvg.h"
-#include "rsvg-private.h"
+#include "rsvg-defs.h"
#include "rsvg-cairo.h"
#include "rsvg-cairo-draw.h"
#include "rsvg-cairo-render.h"
diff --git a/rsvg-defs.h b/rsvg-defs.h
index 74c7925..b5dd0f7 100644
--- a/rsvg-defs.h
+++ b/rsvg-defs.h
@@ -32,6 +32,7 @@
#include <glib.h>
#include "rsvg.h"
+#include "rsvg-private.h"
G_BEGIN_DECLS
diff --git a/rsvg-image.c b/rsvg-image.c
index c8a4297..b43954f 100644
--- a/rsvg-image.c
+++ b/rsvg-image.c
@@ -35,6 +35,7 @@
#include <errno.h>
#include "rsvg-css.h"
#include "rsvg-io.h"
+#include "rsvg-styles.h"
cairo_surface_t *
rsvg_cairo_surface_new_from_href (RsvgHandle *handle,
diff --git a/rsvg-structure.h b/rsvg-structure.h
index 077ce63..aaa4311 100644
--- a/rsvg-structure.h
+++ b/rsvg-structure.h
@@ -31,16 +31,9 @@
#define RSVG_STRUCTURE_H
#include "rsvg-private.h"
-#include "rsvg-defs.h"
-#include "rsvg-styles.h"
G_BEGIN_DECLS
-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);
-
/* Implemented in rust/src/structure.rs */
G_GNUC_INTERNAL
RsvgNode *rsvg_node_group_new (const char *element_name, RsvgNode *parent);
@@ -59,6 +52,14 @@ RsvgNode *rsvg_node_svg_new (const char *element_name, RsvgNode *parent);
/* Implemented in rust/src/structure.rs */
G_GNUC_INTERNAL
+RsvgNode *rsvg_node_use_new (const char *element_name, RsvgNode *parent);
+
+/* Implemented in rust/src/structure.rs */
+G_GNUC_INTERNAL
+RsvgNode *rsvg_node_symbol_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 */
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 7e28e9e..deddb52 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -84,10 +84,12 @@ pub use structure::{
rsvg_node_group_new,
rsvg_node_defs_new,
rsvg_node_switch_new,
+ rsvg_node_symbol_new,
rsvg_node_svg_new,
rsvg_node_svg_get_size,
rsvg_node_svg_get_view_box,
rsvg_node_svg_apply_atts,
+ rsvg_node_use_new,
};
pub use transform::{
diff --git a/rust/src/structure.rs b/rust/src/structure.rs
index 83a13ef..b7c51dc 100644
--- a/rust/src/structure.rs
+++ b/rust/src/structure.rs
@@ -4,6 +4,7 @@ extern crate libc;
use self::glib::translate::*;
+use std::cell::RefCell;
use std::cell::Cell;
use std::ptr;
@@ -256,6 +257,212 @@ impl Drop for NodeSvg {
}
}
+/***** NodeUse *****/
+
+struct NodeUse {
+ link: RefCell<Option<String>>,
+ x: Cell<RsvgLength>,
+ y: Cell<RsvgLength>,
+ w: Cell<Option<RsvgLength>>,
+ h: Cell<Option<RsvgLength>>,
+}
+
+impl NodeUse {
+ fn new () -> NodeUse {
+ NodeUse {
+ link: RefCell::new (None),
+ x: Cell::new (RsvgLength::default ()),
+ y: Cell::new (RsvgLength::default ()),
+ w: Cell::new (None),
+ h: Cell::new (None)
+ }
+ }
+}
+
+impl NodeTrait for NodeUse {
+ fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
+ *self.link.borrow_mut () = property_bag::lookup (pbag, "xlink:href");
+
+ self.x.set (property_bag::length_or_default (pbag, "x", LengthDir::Horizontal)?);
+ self.y.set (property_bag::length_or_default (pbag, "y", LengthDir::Vertical)?);
+
+ let opt_w = property_bag::length_or_none (pbag, "width", LengthDir::Horizontal)?;
+ match opt_w {
+ Some (w) => {
+ if length_is_negative (&w) {
+ return Err (NodeError::value_error ("width", "Must not be negative"));
+ } else {
+ self.w.set (Some (w));
+ }
+ },
+
+ None => {
+ self.w.set (None);
+ }
+ }
+
+ let opt_h = property_bag::length_or_none (pbag, "height", LengthDir::Vertical)?;
+ match opt_h {
+ Some (h) => {
+ if length_is_negative (&h) {
+ return Err (NodeError::value_error ("height", "Must not be negative"));
+ } else {
+ self.h.set (Some (h));
+ }
+ },
+
+ None => {
+ self.h.set (None);
+ }
+ }
+
+ Ok (())
+ }
+
+ fn draw (&self, node: &RsvgNode, draw_ctx: *const RsvgDrawingCtx, dominate: i32) {
+ let link = self.link.borrow ();
+
+ if link.is_none () {
+ return;
+ }
+
+ let raw_child = drawing_ctx::acquire_node (draw_ctx, link.as_ref ().unwrap ());
+ if raw_child.is_null () {
+ return;
+ }
+
+ let child: &RsvgNode = unsafe { &*raw_child };
+ if Node::is_ancestor (node.clone (), child.clone ()) {
+ // or, if we're <use>'ing ourselves
+ drawing_ctx::release_node (draw_ctx, raw_child);
+ return;
+ }
+
+ let nx = self.x.get ().normalize (draw_ctx);
+ let ny = self.y.get ().normalize (draw_ctx);
+ let nw = self.w.get ().map (|l| l.normalize (draw_ctx));
+ let nh = self.h.get ().map (|l| l.normalize (draw_ctx));
+
+ // width or height set to 0 disables rendering of the element
+ // https://www.w3.org/TR/SVG/struct.html#UseElementWidthAttribute
+ if let Some (w) = nw {
+ if double_equals (w, 0.0) {
+ drawing_ctx::release_node (draw_ctx, raw_child);
+ return;
+ }
+ }
+
+ if let Some (h) = nh {
+ if double_equals (h, 0.0) {
+ drawing_ctx::release_node (draw_ctx, raw_child);
+ return;
+ }
+ }
+
+ drawing_ctx::state_reinherit_top (draw_ctx, node.get_state (), dominate);
+
+ let state = drawing_ctx::get_current_state (draw_ctx);
+
+ if child.get_type () != NodeType::Symbol {
+ let mut affine = drawing_ctx::get_current_state_affine (draw_ctx);
+ affine.translate (nx, ny);
+ drawing_ctx::set_current_state_affine (draw_ctx, affine);
+
+ let boxed_child = box_node (child.clone ());
+
+ drawing_ctx::push_discrete_layer (draw_ctx);
+ drawing_ctx::draw_node_from_stack (draw_ctx, boxed_child, 1);
+ drawing_ctx::pop_discrete_layer (draw_ctx);
+ } else {
+ child.with_impl (|symbol: &NodeSymbol| {
+ let vbox = symbol.vbox.get ();
+
+ if vbox.is_active () {
+ // If attributes ‘width’ and/or ‘height’ are not specified, [...] use values of '100%'
for these attributes.
+ // From https://www.w3.org/TR/SVG/struct.html#UseElement in "If the ‘use’ element
references a ‘symbol’ element"
+
+ let nw = nw.unwrap_or (RsvgLength::parse ("100%", LengthDir::Horizontal).unwrap
().normalize (draw_ctx));
+ let nh = nh.unwrap_or (RsvgLength::parse ("100%", LengthDir::Vertical).unwrap
().normalize (draw_ctx));
+
+ let (x, y, w, h) = symbol.preserve_aspect_ratio.get ().compute (vbox.rect.width,
vbox.rect.height,
+ nx, ny, nw, nh);
+
+ let mut affine = drawing_ctx::get_current_state_affine (draw_ctx);
+ affine.translate (x, y);
+ affine.scale (w / vbox.rect.width, h / vbox.rect.height);
+ affine.translate (-vbox.rect.x, -vbox.rect.y);
+ drawing_ctx::set_current_state_affine (draw_ctx, affine);
+
+ drawing_ctx::push_view_box (draw_ctx, vbox.rect.width, vbox.rect.height);
+
+ drawing_ctx::push_discrete_layer (draw_ctx);
+
+ if !drawing_ctx::state_is_overflow (state) || (!drawing_ctx::state_has_overflow (state)
+ && drawing_ctx::state_is_overflow
(child.get_state ())) {
+ drawing_ctx::add_clipping_rect (draw_ctx, vbox.rect.x, vbox.rect.y, vbox.rect.width,
vbox.rect.height);
+ }
+ } else {
+ let mut affine = drawing_ctx::get_current_state_affine (draw_ctx);
+ affine.translate (nx, ny);
+ drawing_ctx::set_current_state_affine (draw_ctx, affine);
+
+ drawing_ctx::push_discrete_layer (draw_ctx);
+ }
+
+ drawing_ctx::state_push (draw_ctx);
+
+ child.draw_children (draw_ctx, 1);
+
+ drawing_ctx::state_pop (draw_ctx);
+ drawing_ctx::pop_discrete_layer (draw_ctx);
+
+ if vbox.is_active () {
+ drawing_ctx::pop_view_box (draw_ctx);
+ }
+ });
+ }
+
+ drawing_ctx::release_node (draw_ctx, raw_child);
+ }
+
+ fn get_c_impl (&self) -> *const RsvgCNodeImpl {
+ unreachable! ();
+ }
+}
+
+/***** NodeSymbol *****/
+
+struct NodeSymbol {
+ preserve_aspect_ratio: Cell<AspectRatio>,
+ vbox: Cell<RsvgViewBox>
+}
+
+impl NodeSymbol {
+ fn new () -> NodeSymbol {
+ NodeSymbol {
+ preserve_aspect_ratio: Cell::new (AspectRatio::default ()),
+ vbox: Cell::new (RsvgViewBox::default ())
+ }
+ }
+}
+
+impl NodeTrait for NodeSymbol {
+ fn set_atts (&self, _: &RsvgNode, _: *const RsvgHandle, pbag: *const RsvgPropertyBag) -> NodeResult {
+ self.preserve_aspect_ratio.set (property_bag::parse_or_default (pbag, "preserveAspectRatio")?);
+ self.vbox.set (property_bag::parse_or_default (pbag, "viewBox")?);
+
+ Ok (())
+ }
+
+ fn draw (&self, _: &RsvgNode, _: *const RsvgDrawingCtx, _: i32) {
+ // nothing
+ }
+
+ fn get_c_impl (&self) -> *const RsvgCNodeImpl {
+ unreachable! ();
+ }
+}
+
/***** C Prototypes *****/
#[no_mangle]
@@ -287,6 +494,20 @@ pub extern fn rsvg_node_svg_new (_: *const libc::c_char, raw_parent: *const Rsvg
}
#[no_mangle]
+pub extern fn rsvg_node_use_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
+ boxed_node_new (NodeType::Use,
+ raw_parent,
+ Box::new (NodeUse::new ()))
+}
+
+#[no_mangle]
+pub extern fn rsvg_node_symbol_new (_: *const libc::c_char, raw_parent: *const RsvgNode) -> *const RsvgNode {
+ boxed_node_new (NodeType::Symbol,
+ raw_parent,
+ Box::new (NodeSymbol::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 };
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]