[librsvg/rustification] Use an iterator function rsvg_node_foreach_child() throughout
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg/rustification] Use an iterator function rsvg_node_foreach_child() throughout
- Date: Fri, 25 Nov 2016 22:38:39 +0000 (UTC)
commit 852a2a3a827cf6922819802a7c67926f6880999c
Author: Federico Mena Quintero <federico gnome org>
Date: Tue Nov 22 16:02:50 2016 -0600
Use an iterator function rsvg_node_foreach_child() throughout
This is instead of iterating through the node->children GPtrArray by
hand.
rsvg-base.c | 52 +++++++++---
rsvg-private.h | 9 ++
rsvg-structure.c | 72 ++++++++++-------
rsvg-text.c | 239 +++++++++++++++++++++++++++++++++++------------------
4 files changed, 248 insertions(+), 124 deletions(-)
---
diff --git a/rsvg-base.c b/rsvg-base.c
index 9b6f651..6f9275c 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -445,6 +445,25 @@ rsvg_node_get_parent (RsvgNode *node)
return node->parent;
}
+void
+rsvg_node_foreach_child (RsvgNode *node, RsvgNodeForeachChildFn fn, gpointer data)
+{
+ guint len;
+ guint i;
+
+ len = node->children->len;
+
+ for (i = 0; i < len; i++) {
+ RsvgNode *child;
+ gboolean next;
+
+ child = g_ptr_array_index (node->children, i);
+ next = fn (child, data);
+ if (!next)
+ break;
+ }
+}
+
/* extra (title, desc, metadata) */
static void
@@ -885,6 +904,22 @@ rsvg_new_node_chars (const char *text,
return self;
}
+static gboolean
+find_last_chars_node (RsvgNode *node, gpointer data)
+{
+ RsvgNode **dest;
+
+ dest = data;
+
+ if (RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_CHARS) {
+ *dest = node;
+ } else if (RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_TSPAN) {
+ *dest = NULL;
+ }
+
+ return TRUE;
+}
+
static void
rsvg_characters_impl (RsvgHandle * ctx, const xmlChar * ch, int len)
{
@@ -895,22 +930,13 @@ rsvg_characters_impl (RsvgHandle * ctx, const xmlChar * ch, int len)
if (ctx->priv->currentnode) {
RsvgNodeType type = RSVG_NODE_TYPE (ctx->priv->currentnode);
- if (type == RSVG_NODE_TYPE_TSPAN ||
- type == RSVG_NODE_TYPE_TEXT) {
- guint i;
-
+ if (type == RSVG_NODE_TYPE_TSPAN || type == RSVG_NODE_TYPE_TEXT) {
/* 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 */
self = NULL;
- for (i = 0; i < ctx->priv->currentnode->children->len; i++) {
- RsvgNode *node = g_ptr_array_index (ctx->priv->currentnode->children, i);
- if (RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_CHARS) {
- self = (RsvgNodeChars*)node;
- }
- else if (RSVG_NODE_TYPE (node) == RSVG_NODE_TYPE_TSPAN) {
- self = NULL;
- }
- }
+ rsvg_node_foreach_child (ctx->priv->currentnode,
+ find_last_chars_node,
+ &self);
if (self != NULL) {
if (!g_utf8_validate ((char *) ch, len, NULL)) {
diff --git a/rsvg-private.h b/rsvg-private.h
index a5d55a8..313433b 100644
--- a/rsvg-private.h
+++ b/rsvg-private.h
@@ -346,6 +346,15 @@ RsvgState *rsvg_node_get_state (RsvgNode *node);
G_GNUC_INTERNAL
RsvgNode *rsvg_node_get_parent (RsvgNode *node);
+/* Used to iterate among a node's children with rsvg_node_foreach_child().
+ * If this caller-supplied function returns FALSE, iteration will stop.
+ * Otherwise, iteration will continue to the next child node.
+ */
+typedef gboolean (* RsvgNodeForeachChildFn) (RsvgNode *node, gpointer data);
+
+G_GNUC_INTERNAL
+void rsvg_node_foreach_child (RsvgNode *node, RsvgNodeForeachChildFn fn, gpointer data);
+
struct _RsvgNodeChars {
RsvgNode super;
GString *contents;
diff --git a/rsvg-structure.c b/rsvg-structure.c
index ab6ec6d..5feb18b 100644
--- a/rsvg-structure.c
+++ b/rsvg-structure.c
@@ -22,8 +22,8 @@
Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
- Authors: Raph Levien <raph artofcode com>,
- Dom Lachowicz <cinamod hotmail com>,
+ Authors: Raph Levien <raph artofcode com>,
+ Dom Lachowicz <cinamod hotmail com>,
Caleb Moore <c moore student unsw edu au>
*/
@@ -55,21 +55,32 @@ rsvg_node_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
ctx->drawsub_stack = stacksave;
}
+static gboolean
+draw_child (RsvgNode *node, gpointer data)
+{
+ RsvgDrawingCtx *ctx;
+
+ ctx = data;
+
+ rsvg_state_push (ctx);
+ rsvg_node_draw (node, ctx, 0);
+ rsvg_state_pop (ctx);
+
+ return TRUE;
+}
+
/* generic function for drawing all of the children of a particular node */
void
_rsvg_node_draw_children (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
{
- guint i;
if (dominate != -1) {
rsvg_state_reinherit_top (ctx, rsvg_node_get_state (self), dominate);
rsvg_push_discrete_layer (ctx);
}
- for (i = 0; i < self->children->len; i++) {
- rsvg_state_push (ctx);
- rsvg_node_draw (g_ptr_array_index (self->children, i), ctx, 0);
- rsvg_state_pop (ctx);
- }
+
+ rsvg_node_foreach_child (self, draw_child, ctx);
+
if (dominate != -1)
rsvg_pop_discrete_layer (ctx);
}
@@ -233,7 +244,6 @@ rsvg_node_svg_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
RsvgNodeSvg *sself;
RsvgState *state;
cairo_matrix_t affine, affine_old, affine_new;
- guint i;
double nx, ny, nw, nh;
sself = (RsvgNodeSvg *) self;
@@ -272,7 +282,7 @@ rsvg_node_svg_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
rsvg_push_discrete_layer (ctx);
- /* Bounding box addition must be AFTER the discrete layer push,
+ /* Bounding box addition must be AFTER the discrete layer push,
which must be AFTER the transformation happens. */
if (!state->overflow && rsvg_node_get_parent (self)) {
state->affine = affine_old;
@@ -280,11 +290,7 @@ rsvg_node_svg_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
state->affine = affine_new;
}
- for (i = 0; i < self->children->len; i++) {
- rsvg_state_push (ctx);
- rsvg_node_draw (g_ptr_array_index (self->children, i), ctx, 0);
- rsvg_state_pop (ctx);
- }
+ rsvg_node_foreach_child (self, draw_child, ctx);
rsvg_pop_discrete_layer (ctx);
rsvg_drawing_ctx_pop_view_box (ctx);
@@ -305,9 +311,9 @@ rsvg_node_svg_set_atts (RsvgNode * self, RsvgHandle * ctx, RsvgPropertyBag * att
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
+ * http://www.w3.org/TR/SVG/struct.html#SVGElement
*/
if (rsvg_node_get_parent (self)) {
if ((value = rsvg_property_bag_lookup (atts, "x")))
@@ -453,26 +459,32 @@ rsvg_new_defs (const char *element_name)
return &group->super;
}
+static gboolean
+draw_child_if_cond_true_and_stop (RsvgNode *node, gpointer data)
+{
+ RsvgDrawingCtx *ctx;
+
+ ctx = data;
+
+ if (rsvg_node_get_state (node)->cond_true) {
+ rsvg_state_push (ctx);
+ rsvg_node_draw (node, ctx, 0);
+ rsvg_state_pop (ctx);
+
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
static void
_rsvg_node_switch_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
{
- guint i;
-
rsvg_state_reinherit_top (ctx, rsvg_node_get_state (self), dominate);
rsvg_push_discrete_layer (ctx);
- for (i = 0; i < self->children->len; i++) {
- RsvgNode *drawable = g_ptr_array_index (self->children, i);
-
- if (rsvg_node_get_state (drawable)->cond_true) {
- rsvg_state_push (ctx);
- rsvg_node_draw (g_ptr_array_index (self->children, i), ctx, 0);
- rsvg_state_pop (ctx);
-
- break; /* only render the 1st one */
- }
- }
+ rsvg_node_foreach_child (self, draw_child_if_cond_true_and_stop, ctx);
rsvg_pop_discrete_layer (ctx);
}
diff --git a/rsvg-text.c b/rsvg-text.c
index ee81ebf..79b0c9a 100644
--- a/rsvg-text.c
+++ b/rsvg-text.c
@@ -156,111 +156,188 @@ _rsvg_node_text_set_atts (RsvgNode * self, RsvgHandle * ctx, RsvgPropertyBag * a
static void
rsvg_text_render_text (RsvgDrawingCtx * ctx, const char *text, gdouble * x, gdouble * y);
-
static void
- _rsvg_node_text_type_tspan (RsvgNodeText * self, RsvgDrawingCtx * ctx,
- gdouble * x, gdouble * y, gboolean * lastwasspace,
- gboolean usetextonly);
+_rsvg_node_text_type_children (RsvgNode * self, RsvgDrawingCtx * ctx,
+ gdouble * x, gdouble * y, gboolean * lastwasspace,
+ gboolean usetextonly);
static void
- _rsvg_node_text_type_tref (RsvgNodeTref * self, RsvgDrawingCtx * ctx,
+_rsvg_node_text_type_tspan (RsvgNodeText * self, RsvgDrawingCtx * ctx,
gdouble * x, gdouble * y, gboolean * lastwasspace,
gboolean usetextonly);
+static void
+_rsvg_node_text_type_tref (RsvgNodeTref * self, RsvgDrawingCtx * ctx,
+ gdouble * x, gdouble * y, gboolean * lastwasspace,
+ gboolean usetextonly);
+
+typedef struct {
+ RsvgDrawingCtx *ctx;
+ gdouble *x;
+ gdouble *y;
+ gboolean *lastwasspace;
+ gboolean usetextonly;
+} DrawTextClosure;
+
+static gboolean
+draw_text_child (RsvgNode *node, gpointer data)
+{
+ DrawTextClosure *closure;
+ RsvgNodeType type = RSVG_NODE_TYPE (node);
+
+ closure = data;
+
+ if (type == RSVG_NODE_TYPE_CHARS) {
+ RsvgNodeChars *chars = (RsvgNodeChars *) node;
+ GString *str = _rsvg_text_chomp (rsvg_current_state (closure->ctx), chars->contents,
closure->lastwasspace);
+ rsvg_text_render_text (closure->ctx, str->str, closure->x, closure->y);
+ g_string_free (str, TRUE);
+ } else {
+ if (closure->usetextonly) {
+ _rsvg_node_text_type_children (node,
+ closure->ctx,
+ closure->x,
+ closure->y,
+ closure->lastwasspace,
+ closure->usetextonly);
+ } else {
+ if (type == RSVG_NODE_TYPE_TSPAN) {
+ RsvgNodeText *tspan = (RsvgNodeText *) node;
+ rsvg_state_push (closure->ctx);
+ _rsvg_node_text_type_tspan (tspan,
+ closure->ctx,
+ closure->x,
+ closure->y,
+ closure->lastwasspace,
+ closure->usetextonly);
+ rsvg_state_pop (closure->ctx);
+ } else if (type == RSVG_NODE_TYPE_TREF) {
+ RsvgNodeTref *tref = (RsvgNodeTref *) node;
+ _rsvg_node_text_type_tref (tref,
+ closure->ctx,
+ closure->x,
+ closure->y,
+ closure->lastwasspace,
+ closure->usetextonly);
+ }
+ }
+ }
+
+ return TRUE;
+}
+
/* This function is responsible of selecting render for a text element including its children and giving it
the drawing context */
static void
_rsvg_node_text_type_children (RsvgNode * self, RsvgDrawingCtx * ctx,
gdouble * x, gdouble * y, gboolean * lastwasspace,
gboolean usetextonly)
{
- guint i;
+ DrawTextClosure closure;
rsvg_push_discrete_layer (ctx);
- for (i = 0; i < self->children->len; i++) {
- RsvgNode *node = g_ptr_array_index (self->children, i);
- RsvgNodeType type = RSVG_NODE_TYPE (node);
-
- if (type == RSVG_NODE_TYPE_CHARS) {
- RsvgNodeChars *chars = (RsvgNodeChars *) node;
- GString *str = _rsvg_text_chomp (rsvg_current_state (ctx), chars->contents, lastwasspace);
- rsvg_text_render_text (ctx, str->str, x, y);
- g_string_free (str, TRUE);
- } else {
- if (usetextonly) {
- _rsvg_node_text_type_children (node, ctx, x, y, lastwasspace,
- usetextonly);
- } else {
- if (type == RSVG_NODE_TYPE_TSPAN) {
- RsvgNodeText *tspan = (RsvgNodeText *) node;
- rsvg_state_push (ctx);
- _rsvg_node_text_type_tspan (tspan, ctx, x, y, lastwasspace,
- usetextonly);
- rsvg_state_pop (ctx);
- } else if (type == RSVG_NODE_TYPE_TREF) {
- RsvgNodeTref *tref = (RsvgNodeTref *) node;
- _rsvg_node_text_type_tref (tref, ctx, x, y, lastwasspace,
- usetextonly);
- }
- }
- }
- }
+
+ closure.ctx = ctx;
+ closure.x = x;
+ closure.y = y;
+ closure.lastwasspace = lastwasspace;
+ closure.usetextonly = usetextonly;
+
+ rsvg_node_foreach_child (self, draw_text_child, &closure);
+
rsvg_pop_discrete_layer (ctx);
}
-static int
- _rsvg_node_text_length_tref (RsvgNodeTref * self, RsvgDrawingCtx * ctx,
+static gboolean
+_rsvg_node_text_length_children (RsvgNode * self, RsvgDrawingCtx * ctx,
+ gdouble * length, gboolean * lastwasspace,
+ gboolean usetextonly);
+
+static gboolean
+_rsvg_node_text_length_tref (RsvgNodeTref * self, RsvgDrawingCtx * ctx,
+ gdouble * x, gboolean * lastwasspace,
+ gboolean usetextonly);
+
+static gboolean
+_rsvg_node_text_length_tspan (RsvgNodeText * self, RsvgDrawingCtx * ctx,
gdouble * x, gboolean * lastwasspace,
gboolean usetextonly);
-static int
- _rsvg_node_text_length_tspan (RsvgNodeText * self, RsvgDrawingCtx * ctx,
- gdouble * x, gboolean * lastwasspace,
- gboolean usetextonly);
-
static gdouble rsvg_text_length_text_as_string (RsvgDrawingCtx * ctx, const char *text);
-static int
-_rsvg_node_text_length_children (RsvgNode * self, RsvgDrawingCtx * ctx,
- gdouble * length, gboolean * lastwasspace,
- gboolean usetextonly)
+typedef struct {
+ RsvgDrawingCtx *ctx;
+ gdouble *length;
+ gboolean *lastwasspace;
+ gboolean usetextonly;
+ gboolean done;
+} ChildrenLengthClosure;
+
+static gboolean
+compute_child_length (RsvgNode *node, gpointer data)
{
- guint i;
- int out = FALSE;
- for (i = 0; i < self->children->len; i++) {
- RsvgNode *node = g_ptr_array_index (self->children, i);
- RsvgNodeType type = RSVG_NODE_TYPE (node);
-
- rsvg_state_push (ctx);
- rsvg_state_reinherit_top (ctx, rsvg_node_get_state (node), 0);
- if (type == RSVG_NODE_TYPE_CHARS) {
- RsvgNodeChars *chars = (RsvgNodeChars *) node;
- GString *str = _rsvg_text_chomp (rsvg_current_state (ctx), chars->contents, lastwasspace);
- *length += rsvg_text_length_text_as_string (ctx, str->str);
- g_string_free (str, TRUE);
+ ChildrenLengthClosure *closure;
+ RsvgNodeType type = RSVG_NODE_TYPE (node);
+ gboolean done;
+
+ closure = data;
+ done = FALSE;
+
+ rsvg_state_push (closure->ctx);
+ rsvg_state_reinherit_top (closure->ctx, rsvg_node_get_state (node), 0);
+
+ if (type == RSVG_NODE_TYPE_CHARS) {
+ RsvgNodeChars *chars = (RsvgNodeChars *) node;
+ GString *str = _rsvg_text_chomp (rsvg_current_state (closure->ctx), chars->contents,
closure->lastwasspace);
+ *closure->length += rsvg_text_length_text_as_string (closure->ctx, str->str);
+ g_string_free (str, TRUE);
+ } else {
+ if (closure->usetextonly) {
+ done = _rsvg_node_text_length_children (node,
+ closure->ctx,
+ closure->length,
+ closure->lastwasspace,
+ closure->usetextonly);
} else {
- if (usetextonly) {
- out = _rsvg_node_text_length_children(node, ctx, length,
- lastwasspace,
- usetextonly);
- } else {
- if (type == RSVG_NODE_TYPE_TSPAN) {
- RsvgNodeText *tspan = (RsvgNodeText *) node;
- out = _rsvg_node_text_length_tspan (tspan, ctx, length,
- lastwasspace,
- usetextonly);
- } else if (type == RSVG_NODE_TYPE_TREF) {
- RsvgNodeTref *tref = (RsvgNodeTref *) node;
- out = _rsvg_node_text_length_tref (tref, ctx, length,
- lastwasspace,
- usetextonly);
- }
+ if (type == RSVG_NODE_TYPE_TSPAN) {
+ RsvgNodeText *tspan = (RsvgNodeText *) node;
+ done = _rsvg_node_text_length_tspan (tspan,
+ closure->ctx,
+ closure->length,
+ closure->lastwasspace,
+ closure->usetextonly);
+ } else if (type == RSVG_NODE_TYPE_TREF) {
+ RsvgNodeTref *tref = (RsvgNodeTref *) node;
+ done = _rsvg_node_text_length_tref (tref,
+ closure->ctx,
+ closure->length,
+ closure->lastwasspace,
+ closure->usetextonly);
}
}
- rsvg_state_pop (ctx);
- if (out)
- break;
}
- return out;
+
+ rsvg_state_pop (closure->ctx);
+
+ closure->done = done;
+ return !done;
+}
+
+static gboolean
+_rsvg_node_text_length_children (RsvgNode * self, RsvgDrawingCtx * ctx,
+ gdouble * length, gboolean * lastwasspace,
+ gboolean usetextonly)
+{
+ ChildrenLengthClosure closure;
+
+ closure.ctx = ctx;
+ closure.length = length;
+ closure.lastwasspace = lastwasspace;
+ closure.usetextonly = usetextonly;
+ closure.done = FALSE;
+
+ rsvg_node_foreach_child (self, compute_child_length, &closure);
+
+ return closure.done;
}
@@ -360,7 +437,7 @@ _rsvg_node_text_type_tspan (RsvgNodeText * self, RsvgDrawingCtx * ctx,
usetextonly);
}
-static int
+static gboolean
_rsvg_node_text_length_tspan (RsvgNodeText * self,
RsvgDrawingCtx * ctx, gdouble * length,
gboolean * lastwasspace, gboolean usetextonly)
@@ -415,7 +492,7 @@ _rsvg_node_text_type_tref (RsvgNodeTref * self, RsvgDrawingCtx * ctx,
rsvg_release_node (ctx, link);
}
-static int
+static gboolean
_rsvg_node_text_length_tref (RsvgNodeTref * self, RsvgDrawingCtx * ctx, gdouble * x,
gboolean * lastwasspace, gboolean usetextonly)
{
@@ -526,7 +603,7 @@ rsvg_text_create_layout (RsvgDrawingCtx * ctx, const char *text, PangoContext *
attribute = pango_attr_letter_spacing_new (rsvg_length_normalize (&state->letter_spacing, ctx) *
PANGO_SCALE);
attribute->start_index = 0;
attribute->end_index = G_MAXINT;
- pango_attr_list_insert (attr_list, attribute);
+ pango_attr_list_insert (attr_list, attribute);
if (state->has_font_decor && text) {
if (state->font_decor & TEXT_UNDERLINE) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]