[librsvg/next: 25/31] Use cairo_path_t



commit ed87e5ff0980050c37027041c17967b7ece66cc5
Author: Christian Persch <chpe gnome org>
Date:   Fri Sep 16 21:57:26 2011 +0200

    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(-)
---
diff --git a/Makefile.am b/Makefile.am
index a63cae5..b48747a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -31,8 +31,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 409823c..f473d69 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-cairo-clip.c b/rsvg-cairo-clip.c
index 341ccf5..3d66c59 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 faa3294..7062a7e 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 1fd1630..c164498 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 d9d3bfe..ad363f3 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 1b2d3c3..b7b362e 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 8c92d97..9a46880 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 df4f50d..255f60b 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 eb6becf..ce12302 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);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]