[librsvg/next: 28/31] Add utility to build a cairo_path_t
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg/next: 28/31] Add utility to build a cairo_path_t
- Date: Fri, 21 Oct 2011 21:23:12 +0000 (UTC)
commit fd59753a260bacb7981c513b2fc55f7c7e2360d5
Author: Christian Persch <chpe gnome org>
Date: Fri Sep 16 22:39:23 2011 +0200
Add utility to build a cairo_path_t
This will be used to avoid going through building a string then
parsing the string into a path in rsvg-shapes.c.
rsvg-path.c | 145 ++++++++++++++++++++++++++++++++---------------------------
rsvg-path.h | 25 ++++++++++
2 files changed, 104 insertions(+), 66 deletions(-)
---
diff --git a/rsvg-path.c b/rsvg-path.c
index 9a46880..604b64c 100644
--- a/rsvg-path.c
+++ b/rsvg-path.c
@@ -49,8 +49,7 @@
typedef struct _RSVGParsePathCtx RSVGParsePathCtx;
struct _RSVGParsePathCtx {
- GArray *path_data;
- int last_move_to_index;
+ RsvgPathBuilder builder;
cairo_path_data_t cp; /* current point */
cairo_path_data_t rp; /* reflection point (for 's' and 't' commands) */
@@ -61,100 +60,122 @@ struct _RSVGParsePathCtx {
};
static inline void
-rsvg_path_ensure_capacity (RSVGParsePathCtx *ctx,
- int additional_capacity)
+rsvg_path_builder_ensure_capacity (RsvgPathBuilder *builder,
+ int additional_capacity)
{
}
static inline void
-rsvg_path_add_element (RSVGParsePathCtx *ctx,
- cairo_path_data_t *data)
+rsvg_path_builder_add_element (RsvgPathBuilder *builder,
+ cairo_path_data_t *data)
{
- g_array_append_val (ctx->path_data, *data);
+ g_array_append_val (builder->path_data, *data);
}
-static void
-rsvg_path_moveto (RSVGParsePathCtx *ctx,
- double x,
- double y)
+void
+rsvg_path_builder_init (RsvgPathBuilder *builder,
+ int n_elements)
+{
+ builder->path_data = g_array_sized_new (FALSE, FALSE, sizeof (cairo_path_data_t), n_elements);
+ builder->last_move_to_index = -1;
+}
+
+void
+rsvg_path_builder_move_to (RsvgPathBuilder *builder,
+ double x,
+ double y)
{
cairo_path_data_t data;
- rsvg_path_ensure_capacity (ctx, 2);
+ rsvg_path_builder_ensure_capacity (builder, 2);
data.header.type = CAIRO_PATH_MOVE_TO;
data.header.length = 2;
- rsvg_path_add_element (ctx, &data);
- ctx->last_move_to_index = ctx->path_data->len - 1;
+ rsvg_path_builder_add_element (builder, &data);
+ builder->last_move_to_index = builder->path_data->len - 1;
data.point.x = x;
data.point.y = y;
- rsvg_path_add_element (ctx, &data);
+ rsvg_path_builder_add_element (builder, &data);
}
-static void
-rsvg_path_lineto (RSVGParsePathCtx *ctx,
- double x,
- double y)
+void
+rsvg_path_builder_line_to (RsvgPathBuilder *builder,
+ double x,
+ double y)
{
cairo_path_data_t data;
- rsvg_path_ensure_capacity (ctx, 2);
+ rsvg_path_builder_ensure_capacity (builder, 2);
data.header.type = CAIRO_PATH_LINE_TO;
data.header.length = 2;
- rsvg_path_add_element (ctx, &data);
+ rsvg_path_builder_add_element (builder, &data);
data.point.x = x;
data.point.y = y;
- rsvg_path_add_element (ctx, &data);
+ rsvg_path_builder_add_element (builder, &data);
}
-static void
-rsvg_path_curveto (RSVGParsePathCtx *ctx,
- double x1,
- double y1,
- double x2,
- double y2,
- double x3,
- double y3)
+void
+rsvg_path_builder_curve_to (RsvgPathBuilder *builder,
+ double x1,
+ double y1,
+ double x2,
+ double y2,
+ double x3,
+ double y3)
{
cairo_path_data_t data;
- rsvg_path_ensure_capacity (ctx, 4);
+ rsvg_path_builder_ensure_capacity (builder, 4);
data.header.type = CAIRO_PATH_CURVE_TO;
data.header.length = 4;
- rsvg_path_add_element (ctx, &data);
+ rsvg_path_builder_add_element (builder, &data);
data.point.x = x1;
data.point.y = y1;
- rsvg_path_add_element (ctx, &data);
+ rsvg_path_builder_add_element (builder, &data);
data.point.x = x2;
data.point.y = y2;
- rsvg_path_add_element (ctx, &data);
+ rsvg_path_builder_add_element (builder, &data);
data.point.x = x3;
data.point.y = y3;
- rsvg_path_add_element (ctx, &data);
+ rsvg_path_builder_add_element (builder, &data);
}
-static void
-rsvg_path_close_path (RSVGParsePathCtx *ctx)
+void
+rsvg_path_builder_close_path (RsvgPathBuilder *builder)
{
cairo_path_data_t data;
- rsvg_path_ensure_capacity (ctx, 1);
+ rsvg_path_builder_ensure_capacity (builder, 1);
data.header.type = CAIRO_PATH_CLOSE_PATH;
data.header.length = 1;
- rsvg_path_add_element (ctx, &data);
+ rsvg_path_builder_add_element (builder, &data);
/* Add a 'move-to' element */
- if (ctx->last_move_to_index >= 0) {
- cairo_path_data_t *moveto = &g_array_index (ctx->path_data, cairo_path_data_t, ctx->last_move_to_index);
+ if (builder->last_move_to_index >= 0) {
+ cairo_path_data_t *moveto = &g_array_index (builder->path_data, cairo_path_data_t, builder->last_move_to_index);
- rsvg_path_moveto (ctx, moveto[1].point.x, moveto[1].point.y);
+ rsvg_path_builder_move_to (builder, moveto[1].point.x, moveto[1].point.y);
}
}
+cairo_path_t *
+rsvg_path_builder_finish (RsvgPathBuilder *builder)
+{
+ cairo_path_t *path;
+
+ 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);
+
+ return path;
+}
+
static void
rsvg_path_arc_segment (RSVGParsePathCtx * ctx,
double xc, double yc,
@@ -179,7 +200,7 @@ rsvg_path_arc_segment (RSVGParsePathCtx * ctx,
x2 = x3 + rx*(t * sin (th1));
y2 = y3 + ry*(-t * cos (th1));
- rsvg_path_curveto (ctx,
+ rsvg_path_builder_curve_to (&ctx->builder,
xc + cosf*x1 - sinf*y1,
yc + sinf*x1 + cosf*y1,
xc + cosf*x2 - sinf*y2,
@@ -237,7 +258,7 @@ rsvg_path_arc (RSVGParsePathCtx * ctx,
/* Check the radius against floading point underflow.
See http://bugs.debian.org/508443 */
if ((fabs(rx) < DBL_EPSILON) || (fabs(ry) < DBL_EPSILON)) {
- rsvg_path_lineto (ctx, x, y);
+ rsvg_path_builder_line_to (&ctx->builder, x, y);
return;
}
@@ -353,7 +374,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_moveto (ctx, 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;
@@ -364,7 +385,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_lineto (ctx, 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;
@@ -380,7 +401,7 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
y2 = ctx->params[3];
x3 = ctx->params[4];
y3 = ctx->params[5];
- rsvg_path_curveto (ctx, 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;
@@ -398,7 +419,7 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
y2 = ctx->params[1];
x3 = ctx->params[2];
y3 = ctx->params[3];
- rsvg_path_curveto (ctx, 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;
@@ -409,7 +430,7 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
case 'h':
/* horizontal lineto */
if (ctx->param == 1) {
- rsvg_path_lineto (ctx, 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->param = 0;
}
@@ -417,7 +438,7 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
case 'v':
/* vertical lineto */
if (ctx->param == 1) {
- rsvg_path_lineto (ctx, ctx->cp.point.x, ctx->params[0]);
+ rsvg_path_builder_line_to (&ctx->builder, ctx->cp.point.x, ctx->params[0]);
ctx->cp.point.y = ctx->rp.point.y = ctx->params[0];
ctx->param = 0;
}
@@ -437,7 +458,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_curveto (ctx, 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;
@@ -459,7 +480,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_curveto (ctx, 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;
@@ -475,14 +496,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_curveto (ctx, 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_lineto (ctx, 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];
}
@@ -631,9 +652,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_close_path (ctx);
+ rsvg_path_builder_close_path (&ctx->builder);
- ctx->cp = ctx->rp = g_array_index (ctx->path_data, cairo_path_data_t, ctx->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);
@@ -653,10 +674,8 @@ cairo_path_t *
rsvg_parse_path (const char *path_str)
{
RSVGParsePathCtx ctx;
- cairo_path_t *path;
- ctx.path_data = g_array_sized_new (FALSE, FALSE, sizeof (cairo_path_data_t), 32);
- ctx.last_move_to_index = -1;
+ rsvg_path_builder_init (&ctx.builder, 32);
ctx.cp.point.x = 0.0;
ctx.cp.point.y = 0.0;
@@ -668,13 +687,7 @@ rsvg_parse_path (const char *path_str)
if (ctx.param)
rsvg_parse_path_do_cmd (&ctx, TRUE);
- path = g_new (cairo_path_t, 1);
- path->status = CAIRO_STATUS_SUCCESS;
- path->data = (cairo_path_data_t *) ctx.path_data->data; /* adopt array segment */
- path->num_data = ctx.path_data->len;
- g_array_free (ctx.path_data, FALSE);
-
- return path;
+ return rsvg_path_builder_finish (&ctx.builder);
}
void
diff --git a/rsvg-path.h b/rsvg-path.h
index 255f60b..a142cb0 100644
--- a/rsvg-path.h
+++ b/rsvg-path.h
@@ -32,6 +32,31 @@
G_BEGIN_DECLS
+typedef struct {
+ GArray *path_data;
+ int last_move_to_index;
+} RsvgPathBuilder;
+
+void rsvg_path_builder_init (RsvgPathBuilder *builder,
+ int n_elements);
+void rsvg_path_builder_move_to (RsvgPathBuilder *builder,
+ double x,
+ double y);
+void rsvg_path_builder_line_to (RsvgPathBuilder *builder,
+ double x,
+ double y);
+
+void rsvg_path_builder_curve_to (RsvgPathBuilder *builder,
+ double x1,
+ double y1,
+ double x2,
+ double y2,
+ double x3,
+ double y3);
+void rsvg_path_builder_close_path (RsvgPathBuilder *builder);
+
+cairo_path_t *rsvg_path_builder_finish (RsvgPathBuilder *builder);
+
cairo_path_t *rsvg_parse_path (const char *path_str);
void rsvg_cairo_path_destroy (cairo_path_t *path);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]