[librsvg/rustification] rsvg-path: Make RsvgPathBuilder a heap object
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg/rustification] rsvg-path: Make RsvgPathBuilder a heap object
- Date: Mon, 31 Oct 2016 20:43:48 +0000 (UTC)
commit 32f2115e7a4a70a2f72cce87323605cdebae5bf2
Author: Federico Mena Quintero <federico gnome org>
Date: Mon Oct 31 13:45:22 2016 -0600
rsvg-path: Make RsvgPathBuilder a heap object
We introduce rsvg_path_builder_new() and rsvg_path_builder_destroy(),
and change rsvg_path_builder_finish() into an
rsvg_path_builder_copy_path() that does not destroy the builder while
extracting the path.
This will make it easier to have long-lived path builders, so that
callers can render to Cairo directoy from them instead of extracting the
path themselves.
rsvg-path.c | 79 ++++++++++++++++++++++++++++-------------
rsvg-path.h | 7 +++-
rsvg-shapes.c | 110 ++++++++++++++++++++++++++++++--------------------------
3 files changed, 118 insertions(+), 78 deletions(-)
---
diff --git a/rsvg-path.c b/rsvg-path.c
index 3a5295a..27dbb7b 100644
--- a/rsvg-path.c
+++ b/rsvg-path.c
@@ -47,7 +47,7 @@
typedef struct _RSVGParsePathCtx RSVGParsePathCtx;
struct _RSVGParsePathCtx {
- RsvgPathBuilder builder;
+ RsvgPathBuilder *builder;
cairo_path_data_t cp; /* current point */
cairo_path_data_t rp; /* reflection point (for 's' and 't' commands) */
@@ -70,14 +70,31 @@ rsvg_path_builder_add_element (RsvgPathBuilder *builder,
g_array_append_val (builder->path_data, *data);
}
+RsvgPathBuilder *
+rsvg_path_builder_new (void)
+{
+ RsvgPathBuilder *builder;
+
+ builder = g_new (RsvgPathBuilder, 1);
+
+ /* The starting capacity is just to avoid lots of little resizes while growing
+ * a small path. After that, it will grow as needed.
+ */
+ builder->path_data = g_array_sized_new (FALSE, FALSE, sizeof (cairo_path_data_t), 32);
+ builder->last_move_to_index = -1;
+
+ return builder;
+}
+
void
-rsvg_path_builder_init (RsvgPathBuilder *builder)
+rsvg_path_builder_destroy (RsvgPathBuilder *builder)
{
- /* The starting capacity is just to avoid lots of little resizes while growing
- * a small path. After that, it will grow as needed.
- */
- builder->path_data = g_array_sized_new (FALSE, FALSE, sizeof (cairo_path_data_t), 32);
- builder->last_move_to_index = -1;
+ g_assert (builder != NULL);
+
+ g_array_free (builder->path_data, TRUE);
+ builder->path_data = NULL;
+ builder->last_move_to_index = -1;
+ g_free (builder);
}
void
@@ -163,15 +180,22 @@ rsvg_path_builder_close_path (RsvgPathBuilder *builder)
}
cairo_path_t *
-rsvg_path_builder_finish (RsvgPathBuilder *builder)
+rsvg_path_builder_copy_path (RsvgPathBuilder *builder)
{
cairo_path_t *path;
+ int i;
path = g_new (cairo_path_t, 1);
path->status = CAIRO_STATUS_SUCCESS;
- path->data = (cairo_path_data_t *) builder->path_data->data; /* adopt array segment */
path->num_data = builder->path_data->len;
- g_array_free (builder->path_data, FALSE);
+ path->data = g_new (cairo_path_data_t, path->num_data);
+
+ for (i = 0; i < path->num_data; i++) {
+ cairo_path_data_t *data;
+
+ data = &g_array_index (builder->path_data, cairo_path_data_t, i);
+ path->data[i] = *data;
+ }
return path;
}
@@ -371,7 +395,7 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
/* moveto */
if (ctx->param == 2 || final) {
rsvg_parse_path_default_xy (ctx, 2);
- rsvg_path_builder_move_to (&ctx->builder, ctx->params[0], ctx->params[1]);
+ rsvg_path_builder_move_to (ctx->builder, ctx->params[0], ctx->params[1]);
ctx->cp.point.x = ctx->rp.point.x = ctx->params[0];
ctx->cp.point.y = ctx->rp.point.y = ctx->params[1];
ctx->param = 0;
@@ -382,7 +406,7 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
/* lineto */
if (ctx->param == 2 || final) {
rsvg_parse_path_default_xy (ctx, 2);
- rsvg_path_builder_line_to (&ctx->builder, ctx->params[0], ctx->params[1]);
+ rsvg_path_builder_line_to (ctx->builder, ctx->params[0], ctx->params[1]);
ctx->cp.point.x = ctx->rp.point.x = ctx->params[0];
ctx->cp.point.y = ctx->rp.point.y = ctx->params[1];
ctx->param = 0;
@@ -398,7 +422,7 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
y2 = ctx->params[3];
x3 = ctx->params[4];
y3 = ctx->params[5];
- rsvg_path_builder_curve_to (&ctx->builder, x1, y1, x2, y2, x3, y3);
+ rsvg_path_builder_curve_to (ctx->builder, x1, y1, x2, y2, x3, y3);
ctx->rp.point.x = x2;
ctx->rp.point.y = y2;
ctx->cp.point.x = x3;
@@ -416,7 +440,7 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
y2 = ctx->params[1];
x3 = ctx->params[2];
y3 = ctx->params[3];
- rsvg_path_builder_curve_to (&ctx->builder, x1, y1, x2, y2, x3, y3);
+ rsvg_path_builder_curve_to (ctx->builder, x1, y1, x2, y2, x3, y3);
ctx->rp.point.x = x2;
ctx->rp.point.y = y2;
ctx->cp.point.x = x3;
@@ -427,7 +451,7 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
case 'h':
/* horizontal lineto */
if (ctx->param == 1) {
- rsvg_path_builder_line_to (&ctx->builder, ctx->params[0], ctx->cp.point.y);
+ rsvg_path_builder_line_to (ctx->builder, ctx->params[0], ctx->cp.point.y);
ctx->cp.point.x = ctx->rp.point.x = ctx->params[0];
ctx->rp.point.y = ctx->cp.point.y;
ctx->param = 0;
@@ -436,7 +460,7 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
case 'v':
/* vertical lineto */
if (ctx->param == 1) {
- rsvg_path_builder_line_to (&ctx->builder, ctx->cp.point.x, ctx->params[0]);
+ rsvg_path_builder_line_to (ctx->builder, ctx->cp.point.x, ctx->params[0]);
ctx->rp.point.x = ctx->cp.point.x;
ctx->cp.point.y = ctx->rp.point.y = ctx->params[0];
ctx->param = 0;
@@ -457,7 +481,7 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
y3 = ctx->params[3];
x2 = (x3 + 2 * ctx->params[0]) * (1.0 / 3.0);
y2 = (y3 + 2 * ctx->params[1]) * (1.0 / 3.0);
- rsvg_path_builder_curve_to (&ctx->builder, x1, y1, x2, y2, x3, y3);
+ rsvg_path_builder_curve_to (ctx->builder, x1, y1, x2, y2, x3, y3);
ctx->rp.point.x = ctx->params[0];
ctx->rp.point.y = ctx->params[1];
ctx->cp.point.x = x3;
@@ -479,7 +503,7 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
y3 = ctx->params[1];
x2 = (x3 + 2 * xc) * (1.0 / 3.0);
y2 = (y3 + 2 * yc) * (1.0 / 3.0);
- rsvg_path_builder_curve_to (&ctx->builder, x1, y1, x2, y2, x3, y3);
+ rsvg_path_builder_curve_to (ctx->builder, x1, y1, x2, y2, x3, y3);
ctx->rp.point.x = xc;
ctx->rp.point.y = yc;
ctx->cp.point.x = x3;
@@ -495,14 +519,14 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
y3 = ctx->params[3];
x2 = (x3 + 2 * ctx->params[0]) * (1.0 / 3.0);
y2 = (y3 + 2 * ctx->params[1]) * (1.0 / 3.0);
- rsvg_path_builder_curve_to (&ctx->builder, x1, y1, x2, y2, x3, y3);
+ rsvg_path_builder_curve_to (ctx->builder, x1, y1, x2, y2, x3, y3);
ctx->rp.point.x = ctx->params[0];
ctx->rp.point.y = ctx->params[1];
ctx->cp.point.x = x3;
ctx->cp.point.y = y3;
} else {
rsvg_parse_path_default_xy (ctx, 2);
- rsvg_path_builder_line_to (&ctx->builder, ctx->params[0], ctx->params[1]);
+ rsvg_path_builder_line_to (ctx->builder, ctx->params[0], ctx->params[1]);
ctx->cp.point.x = ctx->rp.point.x = ctx->params[0];
ctx->cp.point.y = ctx->rp.point.y = ctx->params[1];
}
@@ -532,7 +556,7 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
x2 = ctx->params[5];
y2 = ctx->params[6];
- rsvg_path_builder_arc (&ctx->builder,
+ rsvg_path_builder_arc (ctx->builder,
x1, y1,
rx, ry,
x_axis_rotation,
@@ -715,9 +739,9 @@ rsvg_parse_path_data (RSVGParsePathCtx * ctx, const char *data)
} else if (c == 'z' || c == 'Z') {
if (ctx->param)
rsvg_parse_path_do_cmd (ctx, TRUE);
- rsvg_path_builder_close_path (&ctx->builder);
+ rsvg_path_builder_close_path (ctx->builder);
- ctx->cp = ctx->rp = g_array_index (ctx->builder.path_data, cairo_path_data_t,
ctx->builder.path_data->len - 1);
+ ctx->cp = ctx->rp = g_array_index (ctx->builder->path_data, cairo_path_data_t,
ctx->builder->path_data->len - 1);
} else if (c >= 'A' && c < 'Z' && c != 'E') {
if (ctx->param)
rsvg_parse_path_do_cmd (ctx, TRUE);
@@ -737,8 +761,9 @@ cairo_path_t *
rsvg_parse_path (const char *path_str)
{
RSVGParsePathCtx ctx;
+ cairo_path_t *path;
- rsvg_path_builder_init (&ctx.builder);
+ ctx.builder = rsvg_path_builder_new ();
ctx.cp.point.x = 0.0;
ctx.cp.point.y = 0.0;
@@ -752,7 +777,11 @@ rsvg_parse_path (const char *path_str)
if (ctx.param)
rsvg_parse_path_do_cmd (&ctx, TRUE);
- return rsvg_path_builder_finish (&ctx.builder);
+ path = rsvg_path_builder_copy_path (ctx.builder);
+
+ rsvg_path_builder_destroy (ctx.builder);
+
+ return path;
}
void
diff --git a/rsvg-path.h b/rsvg-path.h
index 25e67fa..68269e0 100644
--- a/rsvg-path.h
+++ b/rsvg-path.h
@@ -40,7 +40,10 @@ typedef struct {
} RsvgPathBuilder;
G_GNUC_INTERNAL
-void rsvg_path_builder_init (RsvgPathBuilder *builder);
+RsvgPathBuilder *rsvg_path_builder_new (void);
+
+G_GNUC_INTERNAL
+void rsvg_path_builder_destroy (RsvgPathBuilder *builder);
G_GNUC_INTERNAL
void rsvg_path_builder_move_to (RsvgPathBuilder *builder,
@@ -70,7 +73,7 @@ void rsvg_path_builder_arc (RsvgPathBuilder *builder,
G_GNUC_INTERNAL
void rsvg_path_builder_close_path (RsvgPathBuilder *builder);
G_GNUC_INTERNAL
-cairo_path_t *rsvg_path_builder_finish (RsvgPathBuilder *builder);
+cairo_path_t *rsvg_path_builder_copy_path (RsvgPathBuilder *builder);
G_GNUC_INTERNAL
cairo_path_t *rsvg_parse_path (const char *path_str);
G_GNUC_INTERNAL
diff --git a/rsvg-shapes.c b/rsvg-shapes.c
index b883474..102d40c 100644
--- a/rsvg-shapes.c
+++ b/rsvg-shapes.c
@@ -153,7 +153,7 @@ _rsvg_node_poly_build_path (const char *value,
{
double *pointlist;
guint pointlist_len, i;
- RsvgPathBuilder builder;
+ RsvgPathBuilder *builder;
cairo_path_t *path;
pointlist = rsvg_css_parse_number_list (value, &pointlist_len);
@@ -165,9 +165,9 @@ _rsvg_node_poly_build_path (const char *value,
return NULL;
}
- rsvg_path_builder_init (&builder);
+ builder = rsvg_path_builder_new ();
- rsvg_path_builder_move_to (&builder, pointlist[0], pointlist[1]);
+ rsvg_path_builder_move_to (builder, pointlist[0], pointlist[1]);
for (i = 2; i < pointlist_len; i += 2) {
double x, y;
@@ -183,15 +183,17 @@ _rsvg_node_poly_build_path (const char *value,
else
y = pointlist[i - 1];
- rsvg_path_builder_line_to (&builder, x, y);
+ rsvg_path_builder_line_to (builder, x, y);
}
if (close_path)
- rsvg_path_builder_close_path (&builder);
+ rsvg_path_builder_close_path (builder);
- path = rsvg_path_builder_finish (&builder);
+ path = rsvg_path_builder_copy_path (builder);
g_free (pointlist);
+ rsvg_path_builder_destroy (builder);
+
return path;
}
@@ -281,21 +283,23 @@ static void
_rsvg_node_line_draw (RsvgNode * overself, RsvgDrawingCtx * ctx, int dominate)
{
cairo_path_t *path;
- RsvgPathBuilder builder;
+ RsvgPathBuilder *builder;
RsvgNodeLine *self = (RsvgNodeLine *) overself;
double x1, y1, x2, y2;
- rsvg_path_builder_init (&builder);
+ builder = rsvg_path_builder_new ();
x1 = _rsvg_css_normalize_length (&self->x1, ctx, 'h');
y1 = _rsvg_css_normalize_length (&self->y1, ctx, 'v');
x2 = _rsvg_css_normalize_length (&self->x2, ctx, 'h');
y2 = _rsvg_css_normalize_length (&self->y2, ctx, 'v');
- rsvg_path_builder_move_to (&builder, x1, y1);
- rsvg_path_builder_line_to (&builder, x2, y2);
+ rsvg_path_builder_move_to (builder, x1, y1);
+ rsvg_path_builder_line_to (builder, x2, y2);
+
+ path = rsvg_path_builder_copy_path (builder);
- path = rsvg_path_builder_finish (&builder);
+ rsvg_path_builder_destroy (builder);
rsvg_state_reinherit_top (ctx, overself->state, dominate);
@@ -363,7 +367,7 @@ _rsvg_node_rect_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
{
double x, y, w, h, rx, ry;
double half_w, half_h;
- RsvgPathBuilder builder;
+ RsvgPathBuilder *builder;
cairo_path_t *path;
RsvgNodeRect *rect = (RsvgNodeRect *) self;
@@ -405,17 +409,17 @@ _rsvg_node_rect_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
else if (ry == 0)
rx = 0;
+ builder = rsvg_path_builder_new ();
+
if (rx == 0) {
/* Easy case, no rounded corners */
- rsvg_path_builder_init (&builder);
-
- rsvg_path_builder_move_to (&builder, x, y);
- rsvg_path_builder_line_to (&builder, x + w, y);
- rsvg_path_builder_line_to (&builder, x + w, y + h);
- rsvg_path_builder_line_to (&builder, x, y + h);
- rsvg_path_builder_line_to (&builder, x, y);
- rsvg_path_builder_close_path (&builder);
+ rsvg_path_builder_move_to (builder, x, y);
+ rsvg_path_builder_line_to (builder, x + w, y);
+ rsvg_path_builder_line_to (builder, x + w, y + h);
+ rsvg_path_builder_line_to (builder, x, y + h);
+ rsvg_path_builder_line_to (builder, x, y);
+ rsvg_path_builder_close_path (builder);
} else {
double top_x1, top_x2, top_y;
double bottom_x1, bottom_x2, bottom_y;
@@ -459,41 +463,41 @@ _rsvg_node_rect_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
right_y1 = left_y1;
right_y2 = left_y2;
- rsvg_path_builder_init (&builder);
+ rsvg_path_builder_move_to (builder, top_x1, top_y);
+ rsvg_path_builder_line_to (builder, top_x2, top_y);
- rsvg_path_builder_move_to (&builder, top_x1, top_y);
- rsvg_path_builder_line_to (&builder, top_x2, top_y);
-
- rsvg_path_builder_arc (&builder,
+ rsvg_path_builder_arc (builder,
top_x2, top_y,
rx, ry, 0, FALSE, TRUE,
right_x, right_y1);
- rsvg_path_builder_line_to (&builder, right_x, right_y2);
+ rsvg_path_builder_line_to (builder, right_x, right_y2);
- rsvg_path_builder_arc (&builder,
+ rsvg_path_builder_arc (builder,
right_x, right_y2,
rx, ry, 0, FALSE, TRUE,
bottom_x2, bottom_y);
- rsvg_path_builder_line_to (&builder, bottom_x1, bottom_y);
+ rsvg_path_builder_line_to (builder, bottom_x1, bottom_y);
- rsvg_path_builder_arc (&builder,
+ rsvg_path_builder_arc (builder,
bottom_x1, bottom_y,
rx, ry, 0, FALSE, TRUE,
left_x, left_y2);
- rsvg_path_builder_line_to (&builder, left_x, left_y1);
+ rsvg_path_builder_line_to (builder, left_x, left_y1);
- rsvg_path_builder_arc (&builder,
+ rsvg_path_builder_arc (builder,
left_x, left_y1,
rx, ry, 0, FALSE, TRUE,
top_x1, top_y);
- rsvg_path_builder_close_path (&builder);
+ rsvg_path_builder_close_path (builder);
}
- path = rsvg_path_builder_finish (&builder);
+ path = rsvg_path_builder_copy_path (builder);
+
+ rsvg_path_builder_destroy (builder);
rsvg_state_reinherit_top (ctx, self->state, dominate);
rsvg_render_path (ctx, path);
@@ -550,7 +554,7 @@ _rsvg_node_circle_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
cairo_path_t *path;
RsvgNodeCircle *circle = (RsvgNodeCircle *) self;
double cx, cy, r;
- RsvgPathBuilder builder;
+ RsvgPathBuilder *builder;
cx = _rsvg_css_normalize_length (&circle->cx, ctx, 'h');
cy = _rsvg_css_normalize_length (&circle->cy, ctx, 'v');
@@ -561,33 +565,35 @@ _rsvg_node_circle_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
/* approximate a circle using 4 bezier curves */
- rsvg_path_builder_init (&builder);
+ builder = rsvg_path_builder_new ();
- rsvg_path_builder_move_to (&builder, cx + r, cy);
+ rsvg_path_builder_move_to (builder, cx + r, cy);
- rsvg_path_builder_curve_to (&builder,
+ rsvg_path_builder_curve_to (builder,
cx + r, cy + r * RSVG_ARC_MAGIC,
cx + r * RSVG_ARC_MAGIC, cy + r,
cx, cy + r);
- rsvg_path_builder_curve_to (&builder,
+ rsvg_path_builder_curve_to (builder,
cx - r * RSVG_ARC_MAGIC, cy + r,
cx - r, cy + r * RSVG_ARC_MAGIC,
cx - r, cy);
- rsvg_path_builder_curve_to (&builder,
+ rsvg_path_builder_curve_to (builder,
cx - r, cy - r * RSVG_ARC_MAGIC,
cx - r * RSVG_ARC_MAGIC, cy - r,
cx, cy - r);
- rsvg_path_builder_curve_to (&builder,
+ rsvg_path_builder_curve_to (builder,
cx + r * RSVG_ARC_MAGIC, cy - r,
cx + r, cy - r * RSVG_ARC_MAGIC,
cx + r, cy);
- rsvg_path_builder_close_path (&builder);
+ rsvg_path_builder_close_path (builder);
- path = rsvg_path_builder_finish (&builder);
+ path = rsvg_path_builder_copy_path (builder);
+
+ rsvg_path_builder_destroy (builder);
rsvg_state_reinherit_top (ctx, self->state, dominate);
rsvg_render_path (ctx, path);
@@ -645,7 +651,7 @@ _rsvg_node_ellipse_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
RsvgNodeEllipse *ellipse = (RsvgNodeEllipse *) self;
cairo_path_t *path;
double cx, cy, rx, ry;
- RsvgPathBuilder builder;
+ RsvgPathBuilder *builder;
cx = _rsvg_css_normalize_length (&ellipse->cx, ctx, 'h');
cy = _rsvg_css_normalize_length (&ellipse->cy, ctx, 'v');
@@ -657,33 +663,35 @@ _rsvg_node_ellipse_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
/* approximate an ellipse using 4 bezier curves */
- rsvg_path_builder_init (&builder);
+ builder = rsvg_path_builder_new ();
- rsvg_path_builder_move_to (&builder, cx + rx, cy);
+ rsvg_path_builder_move_to (builder, cx + rx, cy);
- rsvg_path_builder_curve_to (&builder,
+ rsvg_path_builder_curve_to (builder,
cx + rx, cy - RSVG_ARC_MAGIC * ry,
cx + RSVG_ARC_MAGIC * rx, cy - ry,
cx, cy - ry);
- rsvg_path_builder_curve_to (&builder,
+ rsvg_path_builder_curve_to (builder,
cx - RSVG_ARC_MAGIC * rx, cy - ry,
cx - rx, cy - RSVG_ARC_MAGIC * ry,
cx - rx, cy);
- rsvg_path_builder_curve_to (&builder,
+ rsvg_path_builder_curve_to (builder,
cx - rx, cy + RSVG_ARC_MAGIC * ry,
cx - RSVG_ARC_MAGIC * rx, cy + ry,
cx, cy + ry);
- rsvg_path_builder_curve_to (&builder,
+ rsvg_path_builder_curve_to (builder,
cx + RSVG_ARC_MAGIC * rx, cy + ry,
cx + rx, cy + RSVG_ARC_MAGIC * ry,
cx + rx, cy);
- rsvg_path_builder_close_path (&builder);
+ rsvg_path_builder_close_path (builder);
+
+ path = rsvg_path_builder_copy_path (builder);
- path = rsvg_path_builder_finish (&builder);
+ rsvg_path_builder_destroy (builder);
rsvg_state_reinherit_top (ctx, self->state, dominate);
rsvg_render_path (ctx, path);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]