summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Persch <chpe@gnome.org>2011-09-16 21:57:26 +0200
committerChristian Persch <chpe@gnome.org>2011-11-07 20:01:55 +0100
commit0215e044919b7c64747768d2b759e666c3bfba00 (patch)
tree62dfc3d12bf21124beced7511ae83c711514b476
parente773e772bbc6706103268bb96d43d0d9eaecc425 (diff)
downloadlibrsvg-0215e044919b7c64747768d2b759e666c3bfba00.tar.gz
Use cairo_path_t
Parse the path into a cairo_path_t structure instead of inventing an own one.
-rw-r--r--Makefile.am2
-rw-r--r--rsvg-base.c14
-rw-r--r--rsvg-bpath-util.c169
-rw-r--r--rsvg-bpath-util.h70
-rw-r--r--rsvg-cairo-clip.c24
-rw-r--r--rsvg-cairo-draw.c24
-rw-r--r--rsvg-cairo-draw.h2
-rw-r--r--rsvg-marker.c79
-rw-r--r--rsvg-marker.h2
-rw-r--r--rsvg-path.c264
-rw-r--r--rsvg-path.h9
-rw-r--r--rsvg-private.h3
12 files changed, 273 insertions, 389 deletions
diff --git a/Makefile.am b/Makefile.am
index 482cab97..d0a367dd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -33,8 +33,6 @@ enum_sources = \
librsvg_@RSVG_API_MAJOR_VERSION@_la_SOURCES = \
librsvg-features.c \
- rsvg-bpath-util.c \
- rsvg-bpath-util.h \
rsvg-css.c \
rsvg-css.h \
rsvg-defs.c \
diff --git a/rsvg-base.c b/rsvg-base.c
index 1e1f88a3..b59e6998 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -54,7 +54,6 @@
#include <gsf/gsf-utils.h>
#endif
-#include "rsvg-bpath-util.h"
#include "rsvg-path.h"
#include "rsvg-paint-server.h"
#include "rsvg-xml.h"
@@ -2063,15 +2062,14 @@ rsvg_push_discrete_layer (RsvgDrawingCtx * ctx)
void
rsvg_render_path (RsvgDrawingCtx * ctx, const char *d)
{
- /* todo: store and use the bpath higher up */
- RsvgBpathDef *bpath_def;
+ /* todo: store and use the path higher up */
+ cairo_path_t *path;
- bpath_def = rsvg_parse_path (d);
+ path = rsvg_parse_path (d);
- ctx->render->render_path (ctx, bpath_def);
- rsvg_render_markers (bpath_def, ctx);
-
- rsvg_bpath_def_free (bpath_def);
+ ctx->render->render_path (ctx, path);
+ rsvg_render_markers (ctx, path);
+ rsvg_cairo_path_destroy (path);
}
void
diff --git a/rsvg-bpath-util.c b/rsvg-bpath-util.c
deleted file mode 100644
index db2ca9a0..00000000
--- a/rsvg-bpath-util.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* vim: set sw=4 sts=4 ts=4 expandtab: */
-/*
- rsvg-bpath-util.c: Data structure and convenience functions for creating bezier paths.
-
- Copyright (C) 2000 Eazel, Inc.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this program; if not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- Author: Raph Levien <raph@artofcode.com>
-*/
-
-#include "config.h"
-#include "rsvg-bpath-util.h"
-
-#include <stdio.h>
-#include <math.h>
-#include <string.h>
-
-#include <glib.h>
-
-/* This is adapted from gnome-canvas-bpath-util in libgnomeprint
- (originally developed as part of Gill). */
-
-RsvgBpathDef *
-rsvg_bpath_def_new (void)
-{
- RsvgBpathDef *bpd;
-
- bpd = g_new (RsvgBpathDef, 1);
- bpd->n_bpath = 0;
- bpd->n_bpath_max = 16;
- bpd->moveto_idx = -1;
- bpd->bpath = g_new (RsvgBpath, bpd->n_bpath_max);
-
- return bpd;
-}
-
-void
-rsvg_bpath_def_free (RsvgBpathDef * bpd)
-{
- g_return_if_fail (bpd != NULL);
-
- g_free (bpd->bpath);
- g_free (bpd);
-}
-
-void
-rsvg_bpath_def_moveto (RsvgBpathDef * bpd, double x, double y)
-{
- RsvgBpath *bpath;
- int n_bpath;
-
- g_return_if_fail (bpd != NULL);
-
- /* if the last command was a moveto then change that last moveto instead of
- creating a new one */
- bpath = bpd->bpath;
- n_bpath = bpd->n_bpath;
-
- if (n_bpath > 0)
- if (bpath[n_bpath - 1].code == CAIRO_PATH_MOVE_TO) {
- bpath[n_bpath - 1].x3 = x;
- bpath[n_bpath - 1].y3 = y;
- bpd->moveto_idx = n_bpath - 1;
- return;
- }
-
- n_bpath = bpd->n_bpath++;
-
- if (n_bpath == bpd->n_bpath_max)
- bpd->bpath = g_realloc (bpd->bpath, (bpd->n_bpath_max <<= 1) * sizeof (RsvgBpath));
- bpath = bpd->bpath;
- bpath[n_bpath].code = CAIRO_PATH_MOVE_TO;
- bpath[n_bpath].x3 = x;
- bpath[n_bpath].y3 = y;
- bpd->moveto_idx = n_bpath;
-}
-
-void
-rsvg_bpath_def_lineto (RsvgBpathDef * bpd, double x, double y)
-{
- RsvgBpath *bpath;
- int n_bpath;
-
- g_return_if_fail (bpd != NULL);
- g_return_if_fail (bpd->moveto_idx >= 0);
-
- n_bpath = bpd->n_bpath++;
-
- if (n_bpath == bpd->n_bpath_max)
- bpd->bpath = g_realloc (bpd->bpath, (bpd->n_bpath_max <<= 1) * sizeof (RsvgBpath));
- bpath = bpd->bpath;
- bpath[n_bpath].code = CAIRO_PATH_LINE_TO;
- bpath[n_bpath].x3 = x;
- bpath[n_bpath].y3 = y;
-}
-
-void
-rsvg_bpath_def_curveto (RsvgBpathDef * bpd, double x1, double y1, double x2, double y2, double x3,
- double y3)
-{
- RsvgBpath *bpath;
- int n_bpath;
-
- g_return_if_fail (bpd != NULL);
- g_return_if_fail (bpd->moveto_idx >= 0);
-
- n_bpath = bpd->n_bpath++;
-
- if (n_bpath == bpd->n_bpath_max)
- bpd->bpath = g_realloc (bpd->bpath, (bpd->n_bpath_max <<= 1) * sizeof (RsvgBpath));
- bpath = bpd->bpath;
- bpath[n_bpath].code = CAIRO_PATH_CURVE_TO;
- bpath[n_bpath].x1 = x1;
- bpath[n_bpath].y1 = y1;
- bpath[n_bpath].x2 = x2;
- bpath[n_bpath].y2 = y2;
- bpath[n_bpath].x3 = x3;
- bpath[n_bpath].y3 = y3;
-}
-
-static void
-rsvg_bpath_def_replicate (RsvgBpathDef * bpd, int index)
-{
- RsvgBpath *bpath;
- int n_bpath;
-
- n_bpath = bpd->n_bpath++;
-
- if (n_bpath == bpd->n_bpath_max)
- bpd->bpath = g_realloc (bpd->bpath, (bpd->n_bpath_max <<= 1) * sizeof (RsvgBpath));
- bpath = bpd->bpath;
- bpath[n_bpath] = bpath[index];
-}
-
-void
-rsvg_bpath_def_closepath (RsvgBpathDef * bpd)
-{
- RsvgBpath *bpath;
-
- g_return_if_fail (bpd != NULL);
- g_return_if_fail (bpd->moveto_idx >= 0);
- g_return_if_fail (bpd->n_bpath > 0);
-
- rsvg_bpath_def_replicate (bpd, bpd->moveto_idx);
- bpath = bpd->bpath;
-
- bpath[bpd->n_bpath - 1].code = CAIRO_PATH_CLOSE_PATH;
- bpd->moveto_idx = bpd->n_bpath - 1;
-}
-
-void
-rsvg_bpath_def_finish (RsvgBpathDef *bpd)
-{
-}
diff --git a/rsvg-bpath-util.h b/rsvg-bpath-util.h
deleted file mode 100644
index bb2cee68..00000000
--- a/rsvg-bpath-util.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* vim: set sw=4 sts=4 ts=4 expandtab: */
-/*
- rsvg-bpath-util.h: Path utility functions
-
- Copyright (C) 2000 Eazel, Inc.
- Copyright (C) 2002 Dom Lachowicz <cinamod@hotmail.com>
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this program; if not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- Author: Raph Levien <raph@artofcode.com>
-*/
-
-#ifndef RSVG_BPATH_UTIL_H
-#define RSVG_BPATH_UTIL_H
-
-#include <glib.h>
-#include <cairo.h>
-
-G_BEGIN_DECLS
-
-typedef struct _RsvgBpath RsvgBpath;
-struct _RsvgBpath {
- /*< public > */
- cairo_path_data_type_t code;
- double x1;
- double y1;
- double x2;
- double y2;
- double x3;
- double y3;
-};
-
-typedef struct _RsvgBpathDef RsvgBpathDef;
-
-struct _RsvgBpathDef {
- RsvgBpath *bpath;
- int n_bpath;
- int n_bpath_max;
- int moveto_idx;
-};
-
-RsvgBpathDef *rsvg_bpath_def_new (void);
-
-void rsvg_bpath_def_free (RsvgBpathDef * bpd);
-
-void rsvg_bpath_def_moveto (RsvgBpathDef * bpd, double x, double y);
-void rsvg_bpath_def_lineto (RsvgBpathDef * bpd, double x, double y);
-void rsvg_bpath_def_curveto (RsvgBpathDef * bpd,
- double x1, double y1, double x2, double y2, double x3, double y3);
-void rsvg_bpath_def_closepath (RsvgBpathDef * bpd);
-
-void rsvg_bpath_def_finish (RsvgBpathDef * bpd);
-
-G_END_DECLS
-
-#endif
diff --git a/rsvg-cairo-clip.c b/rsvg-cairo-clip.c
index 341ccf5f..3d66c59e 100644
--- a/rsvg-cairo-clip.c
+++ b/rsvg-cairo-clip.c
@@ -31,7 +31,6 @@
#include "rsvg-cairo-clip.h"
#include "rsvg-cairo-render.h"
#include "rsvg-styles.h"
-#include "rsvg-bpath-util.h"
#include "rsvg-path.h"
#include <math.h>
@@ -62,14 +61,13 @@ rsvg_cairo_clip_apply_affine (RsvgCairoClipRender *render, cairo_matrix_t *affin
}
static void
-rsvg_cairo_clip_render_path (RsvgDrawingCtx * ctx, const RsvgBpathDef * bpath_def)
+rsvg_cairo_clip_render_path (RsvgDrawingCtx * ctx, const cairo_path_t *path)
{
RsvgCairoClipRender *render = RSVG_CAIRO_CLIP_RENDER (ctx->render);
RsvgCairoRender *cairo_render = &render->super;
RsvgState *state = rsvg_current_state (ctx);
cairo_t *cr;
- RsvgBpath *bpath;
- int i;
+ const cairo_path_data_t *data, *end;
cr = cairo_render->cr;
@@ -77,21 +75,23 @@ rsvg_cairo_clip_render_path (RsvgDrawingCtx * ctx, const RsvgBpathDef * bpath_de
cairo_set_fill_rule (cr, rsvg_current_state (ctx)->clip_rule);
- for (i = 0; i < bpath_def->n_bpath; i++) {
- bpath = &bpath_def->bpath[i];
-
- switch (bpath->code) {
+ end = &path->data[path->num_data];
+ for (data = &path->data[0]; data < end; data += data->header.length) {
+ switch (data[0].header.type) {
case CAIRO_PATH_CLOSE_PATH:
cairo_close_path (cr);
- /* fall-through */
+ break;
case CAIRO_PATH_MOVE_TO:
- cairo_move_to (cr, bpath->x3, bpath->y3);
+ cairo_move_to (cr, data[1].point.x, data[1].point.y);
break;
case CAIRO_PATH_CURVE_TO:
- cairo_curve_to (cr, bpath->x1, bpath->y1, bpath->x2, bpath->y2, bpath->x3, bpath->y3);
+ cairo_curve_to (cr,
+ data[1].point.x, data[1].point.y,
+ data[2].point.x, data[2].point.y,
+ data[3].point.x, data[3].point.y);
break;
case CAIRO_PATH_LINE_TO:
- cairo_line_to (cr, bpath->x3, bpath->y3);
+ cairo_line_to (cr, data[1].point.x, data[1].point.y);
break;
}
}
diff --git a/rsvg-cairo-draw.c b/rsvg-cairo-draw.c
index faa32945..7062a7e7 100644
--- a/rsvg-cairo-draw.c
+++ b/rsvg-cairo-draw.c
@@ -31,7 +31,6 @@
#include "rsvg-cairo-render.h"
#include "rsvg-cairo-clip.h"
#include "rsvg-styles.h"
-#include "rsvg-bpath-util.h"
#include "rsvg-path.h"
#include "rsvg-filter.h"
#include "rsvg-structure.h"
@@ -437,16 +436,15 @@ rsvg_cairo_render_pango_layout (RsvgDrawingCtx * ctx, PangoLayout * layout, doub
}
void
-rsvg_cairo_render_path (RsvgDrawingCtx * ctx, const RsvgBpathDef * bpath_def)
+rsvg_cairo_render_path (RsvgDrawingCtx * ctx, const cairo_path_t *path)
{
RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
RsvgState *state = rsvg_current_state (ctx);
cairo_t *cr;
- RsvgBpath *bpath;
- int i;
int need_tmpbuf = 0;
RsvgBbox bbox;
double backup_tolerance;
+ const cairo_path_data_t *data, *end;
if (state->fill == NULL && state->stroke == NULL)
return;
@@ -471,21 +469,23 @@ rsvg_cairo_render_path (RsvgDrawingCtx * ctx, const RsvgBpathDef * bpath_def)
cairo_set_dash (cr, state->dash.dash, state->dash.n_dash,
_rsvg_css_normalize_length (&state->dash.offset, ctx, 'o'));
- for (i = 0; i < bpath_def->n_bpath; i++) {
- bpath = &bpath_def->bpath[i];
-
- switch (bpath->code) {
+ end = &path->data[path->num_data];
+ for (data = &path->data[0]; data < end; data += data->header.length) {
+ switch (data[0].header.type) {
case CAIRO_PATH_CLOSE_PATH:
cairo_close_path (cr);
- /* fall-through */
+ break;
case CAIRO_PATH_MOVE_TO:
- cairo_move_to (cr, bpath->x3, bpath->y3);
+ cairo_move_to (cr, data[1].point.x, data[1].point.y);
break;
case CAIRO_PATH_CURVE_TO:
- cairo_curve_to (cr, bpath->x1, bpath->y1, bpath->x2, bpath->y2, bpath->x3, bpath->y3);
+ cairo_curve_to (cr,
+ data[1].point.x, data[1].point.y,
+ data[2].point.x, data[2].point.y,
+ data[3].point.x, data[3].point.y);
break;
case CAIRO_PATH_LINE_TO:
- cairo_line_to (cr, bpath->x3, bpath->y3);
+ cairo_line_to (cr, data[1].point.x, data[1].point.y);
break;
}
}
diff --git a/rsvg-cairo-draw.h b/rsvg-cairo-draw.h
index 1fd1630f..c1644988 100644
--- a/rsvg-cairo-draw.h
+++ b/rsvg-cairo-draw.h
@@ -36,7 +36,7 @@ PangoContext *rsvg_cairo_create_pango_context (RsvgDrawingCtx *ctx);
void rsvg_cairo_render_pango_layout (RsvgDrawingCtx *ctx, PangoLayout *layout,
double x, double y);
void rsvg_cairo_render_path (RsvgDrawingCtx *ctx,
- const RsvgBpathDef * path);
+ const cairo_path_t *path);
void rsvg_cairo_render_image (RsvgDrawingCtx *ctx, const GdkPixbuf * img,
double x, double y, double w, double h);
void rsvg_cairo_push_discrete_layer (RsvgDrawingCtx *ctx);
diff --git a/rsvg-marker.c b/rsvg-marker.c
index d9d3bfe5..ad363f32 100644
--- a/rsvg-marker.c
+++ b/rsvg-marker.c
@@ -23,6 +23,8 @@
Authors: Caleb Moore <c.moore@student.unsw.edu.au>
*/
+#include "config.h"
+
#include "rsvg-marker.h"
#include "rsvg-private.h"
#include "rsvg-styles.h"
@@ -32,6 +34,7 @@
#include "rsvg-filter.h"
#include "rsvg-mask.h"
#include "rsvg-image.h"
+#include "rsvg-path.h"
#include <string.h>
#include <math.h>
@@ -208,14 +211,11 @@ rsvg_marker_parse (const RsvgDefs * defs, const char *str)
}
void
-rsvg_render_markers (const RsvgBpathDef * bpath_def, RsvgDrawingCtx * ctx)
+rsvg_render_markers (RsvgDrawingCtx * ctx,
+ const cairo_path_t *path)
{
- int i;
- int n_bpath, n_bpath_minus_1;
-
double x, y;
double lastx, lasty;
- double nextx, nexty;
double linewidth;
cairo_path_data_type_t code, nextcode;
@@ -223,6 +223,8 @@ rsvg_render_markers (const RsvgBpathDef * bpath_def, RsvgDrawingCtx * ctx)
RsvgMarker *startmarker;
RsvgMarker *middlemarker;
RsvgMarker *endmarker;
+ cairo_path_data_t *data, *nextdata, *end;
+ cairo_path_data_t nextp;
state = rsvg_current_state (ctx);
@@ -239,35 +241,44 @@ rsvg_render_markers (const RsvgBpathDef * bpath_def, RsvgDrawingCtx * ctx)
x = 0;
y = 0;
- nextx = bpath_def->bpath[0].x3;
- nexty = bpath_def->bpath[0].y3;
- nextcode = bpath_def->bpath[0].code;
- n_bpath = bpath_def->n_bpath;
- n_bpath_minus_1 = n_bpath - 1;
+ if (path->num_data <= 0)
+ return;
+
+ end = &path->data[path->num_data];
+ data = &path->data[0];
+ nextcode = data[0].header.type;
+ if (data[0].header.length > 1)
+ nextp = data[data[0].header.length - 1];
+ else
+ nextp.point.x = nextp.point.y = 0.;
- for (i = 0; i < n_bpath; i++) {
+ for ( ; data < end; data = nextdata) {
lastx = x;
lasty = y;
- x = nextx;
- y = nexty;
+ x = nextp.point.x;
+ y = nextp.point.y;
code = nextcode;
- if (i == n_bpath_minus_1) {
- nextcode = CAIRO_PATH_MOVE_TO;
+ nextdata = data + data->header.length;
+ if (nextdata < end) {
+ nextcode = nextdata->header.type;
+ if (nextdata->header.length > 1) {
+ nextp = nextdata[nextdata->header.length - 1];
+ } else {
+ /* keep nextp unchanged */
+ }
} else {
- nextx = bpath_def->bpath[i + 1].x3;
- nexty = bpath_def->bpath[i + 1].y3;
- nextcode = bpath_def->bpath[i + 1].code;
+ nextcode = CAIRO_PATH_MOVE_TO;
}
- if (nextcode == CAIRO_PATH_CLOSE_PATH ||
- nextcode == CAIRO_PATH_MOVE_TO) {
+ if (nextcode == CAIRO_PATH_MOVE_TO ||
+ code == CAIRO_PATH_CLOSE_PATH) {
if (endmarker) {
if (code == CAIRO_PATH_CURVE_TO) {
rsvg_marker_render (endmarker, x, y,
- atan2 (y - bpath_def->bpath[i].y2,
- x - bpath_def->bpath[i].x2),
+ atan2 (y - data[2].point.y,
+ x - data[2].point.x),
linewidth, ctx);
} else {
rsvg_marker_render (endmarker, x, y,
@@ -275,20 +286,20 @@ rsvg_render_markers (const RsvgBpathDef * bpath_def, RsvgDrawingCtx * ctx)
linewidth, ctx);
}
}
- } else if (code == CAIRO_PATH_CLOSE_PATH ||
- code == CAIRO_PATH_MOVE_TO) {
+ } else if (code == CAIRO_PATH_MOVE_TO ||
+ code == CAIRO_PATH_CLOSE_PATH) {
if (startmarker) {
if (nextcode == CAIRO_PATH_CURVE_TO) {
rsvg_marker_render (startmarker, x, y,
- atan2 (bpath_def->bpath[i + 1].y1 - y,
- bpath_def->bpath[i + 1].x1 - x),
+ atan2 (nextdata[1].point.y - y,
+ nextdata[1].point.x - x),
linewidth,
ctx);
} else {
rsvg_marker_render (startmarker, x, y,
- atan2 (nexty - y, nextx - x),
+ atan2 (nextp.point.y - y, nextp.point.x - x),
linewidth,
- ctx);
+ ctx);
}
}
} else {
@@ -296,18 +307,18 @@ rsvg_render_markers (const RsvgBpathDef * bpath_def, RsvgDrawingCtx * ctx)
double xdifin, ydifin, xdifout, ydifout, intot, outtot, angle;
if (code == CAIRO_PATH_CURVE_TO) {
- xdifin = x - bpath_def->bpath[i].x2;
- ydifin = y - bpath_def->bpath[i].y2;
+ xdifin = x - data[2].point.x;
+ ydifin = y - data[2].point.y;
} else {
xdifin = x - lastx;
ydifin = y - lasty;
}
if (nextcode == CAIRO_PATH_CURVE_TO) {
- xdifout = bpath_def->bpath[i+1].x1 - x;
- ydifout = bpath_def->bpath[i+1].y1 - y;
+ xdifout = nextdata[1].point.x - x;
+ ydifout = nextdata[1].point.y - y;
} else {
- xdifout = nextx - x;
- ydifout = nexty - y;
+ xdifout = nextp.point.x - x;
+ ydifout = nextp.point.y - y;
}
intot = sqrt (xdifin * xdifin + ydifin * ydifin);
diff --git a/rsvg-marker.h b/rsvg-marker.h
index 1b2d3c3e..b7b362e3 100644
--- a/rsvg-marker.h
+++ b/rsvg-marker.h
@@ -46,7 +46,7 @@ RsvgNode *rsvg_new_marker (void);
void rsvg_marker_render (RsvgMarker * self, gdouble x, gdouble y,
gdouble orient, gdouble linewidth, RsvgDrawingCtx * ctx);
RsvgNode *rsvg_marker_parse (const RsvgDefs * defs, const char *str);
-void rsvg_render_markers (const RsvgBpathDef * bpath_def, RsvgDrawingCtx * ctx);
+void rsvg_render_markers (RsvgDrawingCtx *ctx, const cairo_path_t *path);
G_END_DECLS
diff --git a/rsvg-path.c b/rsvg-path.c
index 8c92d975..9a468804 100644
--- a/rsvg-path.c
+++ b/rsvg-path.c
@@ -4,6 +4,7 @@
rsvg-path.c: Parse SVG path element data into bezier path.
Copyright (C) 2000 Eazel, Inc.
+ Copyright © 2011 Christian Persch
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
@@ -36,7 +37,7 @@
#include "rsvg-private.h"
-/* This module parses an SVG path element into an RsvgBpathDef.
+/* This module parses an SVG path element into an cairo_path_t.
At present, there is no support for <marker> or any other contextual
information from the SVG file. The API will need to change rather
@@ -48,15 +49,112 @@
typedef struct _RSVGParsePathCtx RSVGParsePathCtx;
struct _RSVGParsePathCtx {
- RsvgBpathDef *bpath;
- double cpx, cpy; /* current point */
- double rpx, rpy; /* reflection point (for 's' and 't' commands) */
+ GArray *path_data;
+ int last_move_to_index;
+
+ cairo_path_data_t cp; /* current point */
+ cairo_path_data_t rp; /* reflection point (for 's' and 't' commands) */
char cmd; /* current command (lowercase) */
int param; /* parameter number */
gboolean rel; /* true if relative coords */
double params[7]; /* parameters that have been parsed */
};
+static inline void
+rsvg_path_ensure_capacity (RSVGParsePathCtx *ctx,
+ int additional_capacity)
+{
+}
+
+static inline void
+rsvg_path_add_element (RSVGParsePathCtx *ctx,
+ cairo_path_data_t *data)
+{
+ g_array_append_val (ctx->path_data, *data);
+}
+
+static void
+rsvg_path_moveto (RSVGParsePathCtx *ctx,
+ double x,
+ double y)
+{
+ cairo_path_data_t data;
+
+ rsvg_path_ensure_capacity (ctx, 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;
+
+ data.point.x = x;
+ data.point.y = y;
+ rsvg_path_add_element (ctx, &data);
+}
+
+static void
+rsvg_path_lineto (RSVGParsePathCtx *ctx,
+ double x,
+ double y)
+{
+ cairo_path_data_t data;
+
+ rsvg_path_ensure_capacity (ctx, 2);
+
+ data.header.type = CAIRO_PATH_LINE_TO;
+ data.header.length = 2;
+ rsvg_path_add_element (ctx, &data);
+ data.point.x = x;
+ data.point.y = y;
+ rsvg_path_add_element (ctx, &data);
+}
+
+static void
+rsvg_path_curveto (RSVGParsePathCtx *ctx,
+ double x1,
+ double y1,
+ double x2,
+ double y2,
+ double x3,
+ double y3)
+{
+ cairo_path_data_t data;
+
+ rsvg_path_ensure_capacity (ctx, 4);
+
+ data.header.type = CAIRO_PATH_CURVE_TO;
+ data.header.length = 4;
+ rsvg_path_add_element (ctx, &data);
+ data.point.x = x1;
+ data.point.y = y1;
+ rsvg_path_add_element (ctx, &data);
+ data.point.x = x2;
+ data.point.y = y2;
+ rsvg_path_add_element (ctx, &data);
+ data.point.x = x3;
+ data.point.y = y3;
+ rsvg_path_add_element (ctx, &data);
+}
+
+static void
+rsvg_path_close_path (RSVGParsePathCtx *ctx)
+{
+ cairo_path_data_t data;
+
+ rsvg_path_ensure_capacity (ctx, 1);
+
+ data.header.type = CAIRO_PATH_CLOSE_PATH;
+ data.header.length = 1;
+ rsvg_path_add_element (ctx, &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);
+
+ rsvg_path_moveto (ctx, moveto[1].point.x, moveto[1].point.y);
+ }
+}
+
static void
rsvg_path_arc_segment (RSVGParsePathCtx * ctx,
double xc, double yc,
@@ -81,7 +179,7 @@ rsvg_path_arc_segment (RSVGParsePathCtx * ctx,
x2 = x3 + rx*(t * sin (th1));
y2 = y3 + ry*(-t * cos (th1));
- rsvg_bpath_def_curveto (ctx->bpath,
+ rsvg_path_curveto (ctx,
xc + cosf*x1 - sinf*y1,
yc + sinf*x1 + cosf*y1,
xc + cosf*x2 - sinf*y2,
@@ -122,8 +220,8 @@ rsvg_path_arc (RSVGParsePathCtx * ctx,
int i, n_segs;
/* Start and end of path segment */
- x1 = ctx->cpx;
- y1 = ctx->cpy;
+ x1 = ctx->cp.point.x;
+ y1 = ctx->cp.point.y;
x2 = x;
y2 = y;
@@ -139,7 +237,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_bpath_def_lineto (ctx->bpath, x, y);
+ rsvg_path_lineto (ctx, x, y);
return;
}
@@ -216,8 +314,8 @@ rsvg_path_arc (RSVGParsePathCtx * ctx,
theta1 + (i + 1) * delta_theta / n_segs,
rx, ry, x_axis_rotation);
- ctx->cpx = x;
- ctx->cpy = y;
+ ctx->cp.point.x = x;
+ ctx->cp.point.y = y;
}
@@ -233,11 +331,11 @@ rsvg_parse_path_default_xy (RSVGParsePathCtx * ctx, int n_params)
if (i > 2)
ctx->params[i] = ctx->params[i - 2];
else if (i == 1)
- ctx->params[i] = ctx->cpy;
+ ctx->params[i] = ctx->cp.point.y;
else if (i == 0)
/* we shouldn't get here (usually ctx->param > 0 as
precondition) */
- ctx->params[i] = ctx->cpx;
+ ctx->params[i] = ctx->cp.point.x;
}
} else {
for (i = ctx->param; i < n_params; i++)
@@ -255,9 +353,9 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
/* moveto */
if (ctx->param == 2 || final) {
rsvg_parse_path_default_xy (ctx, 2);
- rsvg_bpath_def_moveto (ctx->bpath, ctx->params[0], ctx->params[1]);
- ctx->cpx = ctx->rpx = ctx->params[0];
- ctx->cpy = ctx->rpy = ctx->params[1];
+ rsvg_path_moveto (ctx, 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;
ctx->cmd = 'l'; /* implicit linetos after a moveto */
}
@@ -266,9 +364,9 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
/* lineto */
if (ctx->param == 2 || final) {
rsvg_parse_path_default_xy (ctx, 2);
- rsvg_bpath_def_lineto (ctx->bpath, ctx->params[0], ctx->params[1]);
- ctx->cpx = ctx->rpx = ctx->params[0];
- ctx->cpy = ctx->rpy = ctx->params[1];
+ rsvg_path_lineto (ctx, 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;
}
break;
@@ -282,11 +380,11 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
y2 = ctx->params[3];
x3 = ctx->params[4];
y3 = ctx->params[5];
- rsvg_bpath_def_curveto (ctx->bpath, x1, y1, x2, y2, x3, y3);
- ctx->rpx = x2;
- ctx->rpy = y2;
- ctx->cpx = x3;
- ctx->cpy = y3;
+ rsvg_path_curveto (ctx, x1, y1, x2, y2, x3, y3);
+ ctx->rp.point.x = x2;
+ ctx->rp.point.y = y2;
+ ctx->cp.point.x = x3;
+ ctx->cp.point.y = y3;
ctx->param = 0;
}
break;
@@ -294,33 +392,33 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
/* smooth curveto */
if (ctx->param == 4 || final) {
rsvg_parse_path_default_xy (ctx, 4);
- x1 = 2 * ctx->cpx - ctx->rpx;
- y1 = 2 * ctx->cpy - ctx->rpy;
+ x1 = 2 * ctx->cp.point.x - ctx->rp.point.x;
+ y1 = 2 * ctx->cp.point.y - ctx->rp.point.y;
x2 = ctx->params[0];
y2 = ctx->params[1];
x3 = ctx->params[2];
y3 = ctx->params[3];
- rsvg_bpath_def_curveto (ctx->bpath, x1, y1, x2, y2, x3, y3);
- ctx->rpx = x2;
- ctx->rpy = y2;
- ctx->cpx = x3;
- ctx->cpy = y3;
+ rsvg_path_curveto (ctx, x1, y1, x2, y2, x3, y3);
+ ctx->rp.point.x = x2;
+ ctx->rp.point.y = y2;
+ ctx->cp.point.x = x3;
+ ctx->cp.point.y = y3;
ctx->param = 0;
}
break;
case 'h':
/* horizontal lineto */
if (ctx->param == 1) {
- rsvg_bpath_def_lineto (ctx->bpath, ctx->params[0], ctx->cpy);
- ctx->cpx = ctx->rpx = ctx->params[0];
+ rsvg_path_lineto (ctx, ctx->params[0], ctx->cp.point.y);
+ ctx->cp.point.x = ctx->rp.point.x = ctx->params[0];
ctx->param = 0;
}
break;
case 'v':
/* vertical lineto */
if (ctx->param == 1) {
- rsvg_bpath_def_lineto (ctx->bpath, ctx->cpx, ctx->params[0]);
- ctx->cpy = ctx->rpy = ctx->params[0];
+ rsvg_path_lineto (ctx, ctx->cp.point.x, ctx->params[0]);
+ ctx->cp.point.y = ctx->rp.point.y = ctx->params[0];
ctx->param = 0;
}
break;
@@ -333,17 +431,17 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
if (ctx->param == 4 || final) {
rsvg_parse_path_default_xy (ctx, 4);
/* raise quadratic bezier to cubic */
- x1 = (ctx->cpx + 2 * ctx->params[0]) * (1.0 / 3.0);
- y1 = (ctx->cpy + 2 * ctx->params[1]) * (1.0 / 3.0);
+ x1 = (ctx->cp.point.x + 2 * ctx->params[0]) * (1.0 / 3.0);
+ y1 = (ctx->cp.point.y + 2 * ctx->params[1]) * (1.0 / 3.0);
x3 = ctx->params[2];
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_bpath_def_curveto (ctx->bpath, x1, y1, x2, y2, x3, y3);
- ctx->rpx = ctx->params[0];
- ctx->rpy = ctx->params[1];
- ctx->cpx = x3;
- ctx->cpy = y3;
+ rsvg_path_curveto (ctx, 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;
ctx->param = 0;
}
break;
@@ -352,41 +450,41 @@ rsvg_parse_path_do_cmd (RSVGParsePathCtx * ctx, gboolean final)
if (ctx->param == 2 || final) {
double xc, yc; /* quadratic control point */
- xc = 2 * ctx->cpx - ctx->rpx;
- yc = 2 * ctx->cpy - ctx->rpy;
+ xc = 2 * ctx->cp.point.x - ctx->rp.point.x;
+ yc = 2 * ctx->cp.point.y - ctx->rp.point.y;
/* generate a quadratic bezier with control point = xc, yc */
- x1 = (ctx->cpx + 2 * xc) * (1.0 / 3.0);
- y1 = (ctx->cpy + 2 * yc) * (1.0 / 3.0);
+ x1 = (ctx->cp.point.x + 2 * xc) * (1.0 / 3.0);
+ y1 = (ctx->cp.point.y + 2 * yc) * (1.0 / 3.0);
x3 = ctx->params[0];
y3 = ctx->params[1];
x2 = (x3 + 2 * xc) * (1.0 / 3.0);
y2 = (y3 + 2 * yc) * (1.0 / 3.0);
- rsvg_bpath_def_curveto (ctx->bpath, x1, y1, x2, y2, x3, y3);
- ctx->rpx = xc;
- ctx->rpy = yc;
- ctx->cpx = x3;
- ctx->cpy = y3;
+ rsvg_path_curveto (ctx, x1, y1, x2, y2, x3, y3);
+ ctx->rp.point.x = xc;
+ ctx->rp.point.y = yc;
+ ctx->cp.point.x = x3;
+ ctx->cp.point.y = y3;
ctx->param = 0;
} else if (final) {
if (ctx->param > 2) {
rsvg_parse_path_default_xy (ctx, 4);
/* raise quadratic bezier to cubic */
- x1 = (ctx->cpx + 2 * ctx->params[0]) * (1.0 / 3.0);
- y1 = (ctx->cpy + 2 * ctx->params[1]) * (1.0 / 3.0);
+ x1 = (ctx->cp.point.x + 2 * ctx->params[0]) * (1.0 / 3.0);
+ y1 = (ctx->cp.point.y + 2 * ctx->params[1]) * (1.0 / 3.0);
x3 = ctx->params[2];
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_bpath_def_curveto (ctx->bpath, x1, y1, x2, y2, x3, y3);
- ctx->rpx = ctx->params[0];
- ctx->rpy = ctx->params[1];
- ctx->cpx = x3;
- ctx->cpy = y3;
+ rsvg_path_curveto (ctx, 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_bpath_def_lineto (ctx->bpath, ctx->params[0], ctx->params[1]);
- ctx->cpx = ctx->rpx = ctx->params[0];
- ctx->cpy = ctx->rpy = ctx->params[1];
+ rsvg_path_lineto (ctx, 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;
}
@@ -422,25 +520,25 @@ rsvg_path_end_of_number (RSVGParsePathCtx * ctx, double val, int sign, int exp_s
/* rule: even-numbered params are x-relative, odd-numbered
are y-relative */
if ((ctx->param & 1) == 0)
- val += ctx->cpx;
+ val += ctx->cp.point.x;
else if ((ctx->param & 1) == 1)
- val += ctx->cpy;
+ val += ctx->cp.point.y;
break;
case 'a':
/* rule: sixth and seventh are x and y, rest are not
relative */
if (ctx->param == 5)
- val += ctx->cpx;
+ val += ctx->cp.point.x;
else if (ctx->param == 6)
- val += ctx->cpy;
+ val += ctx->cp.point.y;
break;
case 'h':
/* rule: x-relative */
- val += ctx->cpx;
+ val += ctx->cp.point.x;
break;
case 'v':
/* rule: y-relative */
- val += ctx->cpy;
+ val += ctx->cp.point.y;
break;
}
}
@@ -533,10 +631,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_bpath_def_closepath (ctx->bpath);
+ rsvg_path_close_path (ctx);
- ctx->cpx = ctx->rpx = ctx->bpath->bpath[ctx->bpath->n_bpath - 1].x3;
- ctx->cpy = ctx->rpy = ctx->bpath->bpath[ctx->bpath->n_bpath - 1].y3;
+ ctx->cp = ctx->rp = g_array_index (ctx->path_data, cairo_path_data_t, ctx->path_data->len - 1);
} else if (c >= 'A' && c <= 'Z' && c != 'E') {
if (ctx->param)
rsvg_parse_path_do_cmd (ctx, TRUE);
@@ -552,14 +649,17 @@ rsvg_parse_path_data (RSVGParsePathCtx * ctx, const char *data)
}
}
-RsvgBpathDef *
+cairo_path_t *
rsvg_parse_path (const char *path_str)
{
RSVGParsePathCtx ctx;
+ cairo_path_t *path;
- ctx.bpath = rsvg_bpath_def_new ();
- ctx.cpx = 0.0;
- ctx.cpy = 0.0;
+ ctx.path_data = g_array_sized_new (FALSE, FALSE, sizeof (cairo_path_data_t), 32);
+ ctx.last_move_to_index = -1;
+
+ ctx.cp.point.x = 0.0;
+ ctx.cp.point.y = 0.0;
ctx.cmd = 0;
ctx.param = 0;
@@ -568,7 +668,21 @@ rsvg_parse_path (const char *path_str)
if (ctx.param)
rsvg_parse_path_do_cmd (&ctx, TRUE);
- rsvg_bpath_def_finish (ctx.bpath);
+ 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;
+}
+
+void
+rsvg_cairo_path_destroy (cairo_path_t *path)
+{
+ if (path == NULL)
+ return;
- return ctx.bpath;
+ g_free (path->data);
+ g_free (path);
}
diff --git a/rsvg-path.h b/rsvg-path.h
index df4f50d8..255f60ba 100644
--- a/rsvg-path.h
+++ b/rsvg-path.h
@@ -27,12 +27,15 @@
#ifndef RSVG_PATH_H
#define RSVG_PATH_H
-#include "rsvg-bpath-util.h"
+#include <glib.h>
+#include <cairo.h>
G_BEGIN_DECLS
-RsvgBpathDef *rsvg_parse_path (const char *path_str);
+cairo_path_t *rsvg_parse_path (const char *path_str);
+
+void rsvg_cairo_path_destroy (cairo_path_t *path);
G_END_DECLS
-#endif /* RSVG_PATH_H */
+#endif /* RSVG_PATH_H */
diff --git a/rsvg-private.h b/rsvg-private.h
index eb6becff..ce123026 100644
--- a/rsvg-private.h
+++ b/rsvg-private.h
@@ -30,7 +30,6 @@
#include <cairo.h>
#include "rsvg.h"
-#include "rsvg-bpath-util.h"
#include <libxml/SAX.h>
#include <libxml/xmlmemory.h>
@@ -218,7 +217,7 @@ struct RsvgRender {
PangoContext *(*create_pango_context) (RsvgDrawingCtx * ctx);
void (*render_pango_layout) (RsvgDrawingCtx * ctx, PangoLayout *layout,
double x, double y);
- void (*render_path) (RsvgDrawingCtx * ctx, const RsvgBpathDef * path);
+ void (*render_path) (RsvgDrawingCtx * ctx, const cairo_path_t *path);
void (*render_image) (RsvgDrawingCtx * ctx, const GdkPixbuf * pixbuf,
double x, double y, double w, double h);
void (*pop_discrete_layer) (RsvgDrawingCtx * ctx);