From 0215e044919b7c64747768d2b759e666c3bfba00 Mon Sep 17 00:00:00 2001 From: Christian Persch Date: Fri, 16 Sep 2011 21:57:26 +0200 Subject: Use cairo_path_t Parse the path into a cairo_path_t structure instead of inventing an own one. --- Makefile.am | 2 - rsvg-base.c | 14 ++- rsvg-bpath-util.c | 169 ---------------------------------- rsvg-bpath-util.h | 70 --------------- rsvg-cairo-clip.c | 24 ++--- rsvg-cairo-draw.c | 24 ++--- rsvg-cairo-draw.h | 2 +- rsvg-marker.c | 79 +++++++++------- rsvg-marker.h | 2 +- rsvg-path.c | 264 ++++++++++++++++++++++++++++++++++++++---------------- rsvg-path.h | 9 +- rsvg-private.h | 3 +- 12 files changed, 273 insertions(+), 389 deletions(-) delete mode 100644 rsvg-bpath-util.c delete mode 100644 rsvg-bpath-util.h 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 #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 -*/ - -#include "config.h" -#include "rsvg-bpath-util.h" - -#include -#include -#include - -#include - -/* 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 - - 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 -*/ - -#ifndef RSVG_BPATH_UTIL_H -#define RSVG_BPATH_UTIL_H - -#include -#include - -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 @@ -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 */ +#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 #include @@ -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 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 +#include 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 #include "rsvg.h" -#include "rsvg-bpath-util.h" #include #include @@ -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); -- cgit v1.2.1