[librsvg: 1/2] load: move some chars handling logic to rust
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 1/2] load: move some chars handling logic to rust
- Date: Fri, 20 Jul 2018 02:21:07 +0000 (UTC)
commit 9e137b5389936782e0c18305a4d8dec482cd89c3
Author: Paolo Borelli <pborelli gnome org>
Date: Wed Jul 18 23:46:49 2018 +0200
load: move some chars handling logic to rust
librsvg/rsvg-load.c | 85 ++++++----------------------------------------
rsvg_internals/src/lib.rs | 2 +-
rsvg_internals/src/node.rs | 83 +++++++++++++++++++++++++++-----------------
rsvg_internals/src/text.rs | 8 +++++
4 files changed, 72 insertions(+), 106 deletions(-)
---
diff --git a/librsvg/rsvg-load.c b/librsvg/rsvg-load.c
index 7ba7c1b8..bf914806 100644
--- a/librsvg/rsvg-load.c
+++ b/librsvg/rsvg-load.c
@@ -625,97 +625,34 @@ sax_end_element_cb (void *data, const xmlChar * xmlname)
}
}
+/* Implemented in rust/src/node.rs */
+extern RsvgNode *rsvg_node_find_last_chars_child(RsvgNode *node, gboolean *accept_chars);
+
/* Implemented in rust/src/text.rs */
extern RsvgNode *rsvg_node_chars_new(RsvgNode *parent);
/* Implemented in rust/src/text.rs */
extern void rsvg_node_chars_append (RsvgNode *node, const char *text, gssize len);
-static gboolean
-node_is_text_or_tspan (RsvgNode *node)
-{
- RsvgNodeType type;
-
- if (!node) {
- return FALSE;
- }
-
- type = rsvg_node_get_type (node);
- return type == RSVG_NODE_TYPE_TEXT || type == RSVG_NODE_TYPE_TSPAN;
-}
-
-/* Finds the last chars child inside a given @node to which new characters can
- * be appended. @node can be null; in this case we'll return NULL as we didn't
- * find any children.
- */
-static RsvgNode *
-find_last_chars_child (RsvgNode *node)
-{
- RsvgNode *child = NULL;
-
- RsvgNode *temp;
- RsvgNodeChildrenIter *iter;
-
- if (node_is_text_or_tspan (node)) {
- /* find the last CHARS node in the text or tspan node, so that we can
- * coalesce the text, and thus avoid screwing up the Pango layouts.
- */
- iter = rsvg_node_children_iter_begin (node);
-
- while (rsvg_node_children_iter_next_back (iter, &temp)) {
- /* If a tspan node is encountered before any chars node
- * (which means there's a tspan node after any chars nodes,
- * because this is backwards iteration), return NULL.
- */
- if (rsvg_node_get_type (temp) == RSVG_NODE_TYPE_TSPAN) {
- temp = rsvg_node_unref (temp);
- break;
- } else if (rsvg_node_get_type (temp) == RSVG_NODE_TYPE_CHARS) {
- child = temp;
- break;
- } else {
- temp = rsvg_node_unref (temp);
- }
- }
-
- rsvg_node_children_iter_end (iter);
- }
-
- return child;
-}
-
-static RsvgNode *
-add_new_chars_child_to_current_node (RsvgLoad *load)
-{
- RsvgNode *node;
-
- node = rsvg_node_chars_new (load->currentnode);
- rsvg_add_node_to_handle (load->handle, node);
-
- if (load->currentnode) {
- rsvg_node_add_child (load->currentnode, node);
- }
-
- return node;
-}
-
static void
characters_impl (RsvgLoad *load, const char *ch, gssize len)
{
- RsvgNode *node = NULL;
+ RsvgNode *node;
+ gboolean accept_chars = FALSE;
- if (!ch || !len) {
+ if (!ch || !len || !load->currentnode) {
return;
}
- if (!node_is_text_or_tspan (load->currentnode)) {
+ node = rsvg_node_find_last_chars_child (load->currentnode, &accept_chars);
+ if (!accept_chars) {
return;
}
- node = find_last_chars_child (load->currentnode);
-
if (!node) {
- node = add_new_chars_child_to_current_node (load);
+ node = rsvg_node_chars_new (load->currentnode);
+ rsvg_add_node_to_handle (load->handle, node);
+ rsvg_node_add_child (load->currentnode, node);
}
g_assert (rsvg_node_get_type (node) == RSVG_NODE_TYPE_CHARS);
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 6bfca541..5b50a1b5 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -54,7 +54,7 @@ pub use node::{
rsvg_node_children_iter_begin,
rsvg_node_children_iter_end,
rsvg_node_children_iter_next,
- rsvg_node_children_iter_next_back,
+ rsvg_node_find_last_chars_child,
rsvg_node_get_parent,
rsvg_node_get_type,
rsvg_node_is_same,
diff --git a/rsvg_internals/src/node.rs b/rsvg_internals/src/node.rs
index 44c3a66d..078307b9 100644
--- a/rsvg_internals/src/node.rs
+++ b/rsvg_internals/src/node.rs
@@ -123,6 +123,10 @@ pub trait NodeTrait: Downcast {
/// from defaults in the node's `State`.
fn set_overridden_properties(&self, _state: &mut State) {}
+ fn accept_chars(&self) -> bool {
+ false
+ }
+
fn draw(
&self,
_node: &RsvgNode,
@@ -492,6 +496,30 @@ impl Node {
let state = self.get_state_mut();
state.values.overflow = SpecifiedValue::Specified(Overflow::Hidden);
}
+
+ pub fn accept_chars(&self) -> bool {
+ self.node_impl.accept_chars()
+ }
+
+ // find the last Chars node so that we can coalesce
+ // the text and avoid screwing up the Pango layouts
+ pub fn find_last_chars_child(&self) -> Option<Rc<Node>> {
+ for child in self.children().rev() {
+ match child.get_type() {
+ NodeType::Chars => return Some(child),
+
+ // If a node that accepts chars is encountered before
+ // any chars node (which means for instance that there
+ // is a tspan node after any chars nodes, because this
+ // is backwards iteration), return None.
+ _ if child.accept_chars() => return None,
+
+ _ => {}
+ }
+ }
+
+ None
+ }
}
// Sigh, rsvg_state_free() is only available if we are being linked into
@@ -691,6 +719,30 @@ pub extern "C" fn rsvg_node_set_attribute_parse_error(
}
}
+#[no_mangle]
+pub extern "C" fn rsvg_node_find_last_chars_child(
+ raw_node: *const RsvgNode,
+ out_accept_chars: *mut glib_sys::gboolean,
+) -> *mut RsvgNode {
+ assert!(!raw_node.is_null());
+ let node: &RsvgNode = unsafe { &*raw_node };
+
+ let accept_chars = node.accept_chars();
+
+ assert!(!out_accept_chars.is_null());
+ unsafe {
+ *out_accept_chars = accept_chars.to_glib();
+ }
+
+ if accept_chars {
+ if let Some(chars) = node.find_last_chars_child() {
+ return box_node(chars);
+ }
+ }
+
+ ptr::null_mut()
+}
+
#[no_mangle]
pub extern "C" fn rsvg_node_children_iter_begin(raw_node: *const RsvgNode) -> *mut Children {
assert!(!raw_node.is_null());
@@ -727,27 +779,6 @@ pub extern "C" fn rsvg_node_children_iter_next(
}
}
-#[no_mangle]
-pub extern "C" fn rsvg_node_children_iter_next_back(
- iter: *mut Children,
- out_child: *mut *mut RsvgNode,
-) -> glib_sys::gboolean {
- assert!(!iter.is_null());
-
- let iter = unsafe { &mut *iter };
- if let Some(child) = iter.next_back() {
- unsafe {
- *out_child = box_node(child);
- }
- true.to_glib()
- } else {
- unsafe {
- *out_child = ptr::null_mut();
- }
- false.to_glib()
- }
-}
-
#[no_mangle]
pub extern "C" fn rsvg_root_node_cascade(raw_node: *const RsvgNode) {
assert!(!raw_node.is_null());
@@ -977,15 +1008,5 @@ mod tests {
assert_eq!(result, true);
assert!(Rc::ptr_eq(unsafe { &*c }, &child));
rsvg_node_unref(c);
-
- let result: bool = from_glib(rsvg_node_children_iter_next_back(iter, &mut c));
- assert_eq!(result, true);
- assert!(Rc::ptr_eq(unsafe { &*c }, &second_child));
- rsvg_node_unref(c);
-
- let result: bool = from_glib(rsvg_node_children_iter_next(iter, &mut c));
- assert_eq!(result, false);
- let result: bool = from_glib(rsvg_node_children_iter_next_back(iter, &mut c));
- assert_eq!(result, false);
}
}
diff --git a/rsvg_internals/src/text.rs b/rsvg_internals/src/text.rs
index b4bfcc62..4dd63593 100644
--- a/rsvg_internals/src/text.rs
+++ b/rsvg_internals/src/text.rs
@@ -141,6 +141,10 @@ impl NodeTrait for NodeText {
Ok(())
}
+ fn accept_chars(&self) -> bool {
+ true
+ }
+
fn draw(
&self,
node: &RsvgNode,
@@ -359,6 +363,10 @@ impl NodeTrait for NodeTSpan {
Ok(())
}
+
+ fn accept_chars(&self) -> bool {
+ true
+ }
}
fn to_pango_units(v: f64) -> i32 {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]