[cairo-commit] cairo/src Makefile.am, 1.45, 1.46 cairo-arc-private.h, NONE, 1.1 cairo-arc.c, NONE, 1.1 cairo-ft-font.c, 1.55, 1.56 cairo-gstate-private.h, 1.5, 1.6 cairo-gstate.c, 1.113, 1.114 cairo-path-data-private.h, 1.3, 1.4 cairo-path-data.c, 1.2, 1.3 cairo-path.c, 1.24, 1.25 cairo-private.h, 1.1, 1.2 cairo.c, 1.80, 1.81 cairo.h, 1.103, 1.104 cairoint.h, 1.128, 1.129

Carl Worth commit at pdx.freedesktop.org
Tue Apr 26 12:38:08 PDT 2005


Committed by: cworth

Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv6704/src

Modified Files:
	Makefile.am cairo-ft-font.c cairo-gstate-private.h 
	cairo-gstate.c cairo-path-data-private.h cairo-path-data.c 
	cairo-path.c cairo-private.h cairo.c cairo.h cairoint.h 
Added Files:
	cairo-arc-private.h cairo-arc.c 
Log Message:

        Originally: 2005-04-19  Carl Worth  <cworth at cworth.org>

        * src/cairo.h: Add cairo_stroke_preserve, cairo_fill_preserve,
        and cairo_clip_preserve.

        * src/cairoint.h:
        * src/cairo-gstate-private.h:
        * src/cairo-gstate.c: Rip the path out of cairo_gstate_t.

        * src/cairo-private.h: Add path to cairo_t.

        * src/cairo.c: Bring in most of the path code that used to live in
        cairo-gstate.c

        * src/Makefile.am:
        * src/cairo-arc-private.h:
        * src/cairo-arc.c: Move arc generation code into its own file.

        * src/cairo-path-data-private.h:
        * src/cairo-path-data.c: Accept path+ctm_inverse+tolerance instead
        of gstate. Absorb flattening and device space->user space
        conversion that used to be in _cairo_gstate_intepret_path.

        * src/cairo-path.c: Prefer cairo_fixed_t parameters over
        ciaro_point_t for cross-file interfaces.

        * src/cairo-ft-font.c: Track changes in _cairo_path_fixed
        interfaces.

        * test/fill-and-stroke.c: (draw): Port to use cairo_fill_preserve
        rather than cairo_save/cairo_restore which no longer work for
        saving the path.

        * test/get-and-set.c: (settings_set), (settings_get),
        (settings_equal): Remove get and set of current point since it is
        no longer affected by cairo_save and cairo_restore. Add get and
        set testing for cairo_matrix_t.


Index: Makefile.am
===================================================================
RCS file: /cvs/cairo/cairo/src/Makefile.am,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- Makefile.am	23 Apr 2005 00:32:12 -0000	1.45
+++ Makefile.am	26 Apr 2005 19:38:06 -0000	1.46
@@ -78,6 +78,7 @@
 libcairo_la_SOURCES = 		\
 	cairo.c			\
 	cairo.h			\
+	cairo-arc.c		\
 	cairo-array.c		\
 	cairo-cache.c		\
 	cairo-color.c		\

--- NEW FILE: cairo-arc-private.h ---
(This appears to be a binary file; contents omitted.)

--- NEW FILE: cairo-arc.c ---
(This appears to be a binary file; contents omitted.)

Index: cairo-ft-font.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-ft-font.c,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -d -r1.55 -r1.56
--- cairo-ft-font.c	8 Apr 2005 20:14:17 -0000	1.55
+++ cairo-ft-font.c	26 Apr 2005 19:38:06 -0000	1.56
@@ -1181,13 +1181,13 @@
 _move_to (FT_Vector *to, void *closure)
 {
     cairo_path_fixed_t *path = closure;
-    cairo_point_t point;
+    cairo_fixed_t x, y;
 
-    point.x = _cairo_fixed_from_26_6 (to->x);
-    point.y = _cairo_fixed_from_26_6 (to->y);
+    x = _cairo_fixed_from_26_6 (to->x);
+    y = _cairo_fixed_from_26_6 (to->y);
 
     _cairo_path_fixed_close_path (path);
-    _cairo_path_fixed_move_to (path, &point);
+    _cairo_path_fixed_move_to (path, x, y);
 
     return 0;
 }
@@ -1196,12 +1196,12 @@
 _line_to (FT_Vector *to, void *closure)
 {
     cairo_path_fixed_t *path = closure;
-    cairo_point_t point;
+    cairo_fixed_t x, y;
 
-    point.x = _cairo_fixed_from_26_6 (to->x);
-    point.y = _cairo_fixed_from_26_6 (to->y);
+    x = _cairo_fixed_from_26_6 (to->x);
+    y = _cairo_fixed_from_26_6 (to->y);
 
-    _cairo_path_fixed_line_to (path, &point);
+    _cairo_path_fixed_line_to (path, x, y);
 
     return 0;
 }
@@ -1211,25 +1211,30 @@
 {
     cairo_path_fixed_t *path = closure;
 
-    cairo_point_t p0, p1, p2, p3;
+    cairo_fixed_t x0, y0;
+    cairo_fixed_t x1, y1;
+    cairo_fixed_t x2, y2;
+    cairo_fixed_t x3, y3;
     cairo_point_t conic;
 
-    _cairo_path_fixed_get_current_point (path, &p0);
+    _cairo_path_fixed_get_current_point (path, &x0, &y0);
 
     conic.x = _cairo_fixed_from_26_6 (control->x);
     conic.y = _cairo_fixed_from_26_6 (control->y);
 
-    p3.x = _cairo_fixed_from_26_6 (to->x);
-    p3.y = _cairo_fixed_from_26_6 (to->y);
+    x3 = _cairo_fixed_from_26_6 (to->x);
+    y3 = _cairo_fixed_from_26_6 (to->y);
 
-    p1.x = p0.x + 2.0/3.0 * (conic.x - p0.x);
-    p1.y = p0.y + 2.0/3.0 * (conic.y - p0.y);
+    x1 = x0 + 2.0/3.0 * (conic.x - x0);
+    y1 = y0 + 2.0/3.0 * (conic.y - y0);
 
-    p2.x = p3.x + 2.0/3.0 * (conic.x - p3.x);
-    p2.y = p3.y + 2.0/3.0 * (conic.y - p3.y);
+    x2 = x3 + 2.0/3.0 * (conic.x - x3);
+    y2 = y3 + 2.0/3.0 * (conic.y - y3);
 
     _cairo_path_fixed_curve_to (path,
-				&p1, &p2, &p3);
+				x1, y1,
+				x2, y2,
+				x3, y3);
 
     return 0;
 }
@@ -1238,18 +1243,23 @@
 _cubic_to (FT_Vector *control1, FT_Vector *control2, FT_Vector *to, void *closure)
 {
     cairo_path_fixed_t *path = closure;
-    cairo_point_t p0, p1, p2;
+    cairo_fixed_t x0, y0;
+    cairo_fixed_t x1, y1;
+    cairo_fixed_t x2, y2;
 
-    p0.x = _cairo_fixed_from_26_6 (control1->x);
-    p0.y = _cairo_fixed_from_26_6 (control1->y);
+    x0 = _cairo_fixed_from_26_6 (control1->x);
+    y0 = _cairo_fixed_from_26_6 (control1->y);
 
-    p1.x = _cairo_fixed_from_26_6 (control2->x);
-    p1.y = _cairo_fixed_from_26_6 (control2->y);
+    x1 = _cairo_fixed_from_26_6 (control2->x);
+    y1 = _cairo_fixed_from_26_6 (control2->y);
 
-    p2.x = _cairo_fixed_from_26_6 (to->x);
-    p2.y = _cairo_fixed_from_26_6 (to->y);
+    x2 = _cairo_fixed_from_26_6 (to->x);
+    y2 = _cairo_fixed_from_26_6 (to->y);
 
-    _cairo_path_fixed_curve_to (path, &p0, &p1, &p2);
+    _cairo_path_fixed_curve_to (path,
+				x0, y0,
+				x1, y1,
+				x2, y2);
 
     return 0;
 }

Index: cairo-gstate-private.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-gstate-private.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- cairo-gstate-private.h	14 Apr 2005 21:42:26 -0000	1.5
+++ cairo-gstate-private.h	26 Apr 2005 19:38:06 -0000	1.6
@@ -36,8 +36,6 @@
 #ifndef CAIRO_GSTATE_PRIVATE_H
 #define CAIRO_GSTATE_PRIVATE_H
 
-#include "cairo-path-fixed-private.h"
-
 struct _cairo_gstate {
     cairo_operator_t operator;
     
@@ -73,8 +71,6 @@
     cairo_matrix_t ctm;
     cairo_matrix_t ctm_inverse;
 
-    cairo_path_fixed_t path;
-
     cairo_pen_t pen_regular;
 
     struct _cairo_gstate *next;

Index: cairo-gstate.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-gstate.c,v
retrieving revision 1.113
retrieving revision 1.114
diff -u -d -r1.113 -r1.114
--- cairo-gstate.c	23 Apr 2005 18:58:18 -0000	1.113
+++ cairo-gstate.c	26 Apr 2005 19:38:06 -0000	1.114
@@ -113,8 +113,6 @@
 
     _cairo_gstate_identity_matrix (gstate);
 
-    _cairo_path_fixed_init (&gstate->path);
-
     _cairo_pen_init_empty (&gstate->pen_regular);
 
     gstate->next = NULL;
@@ -158,19 +156,12 @@
 
     cairo_pattern_reference (gstate->source);
     
-    status = _cairo_path_fixed_init_copy (&gstate->path, &other->path);
-    if (status)
-	goto CLEANUP_FONT;
-
     status = _cairo_pen_init_copy (&gstate->pen_regular, &other->pen_regular);
     if (status)
-	goto CLEANUP_PATH;
+	goto CLEANUP_FONT;
 
     return status;
 
-  CLEANUP_PATH:
-    _cairo_path_fixed_fini (&gstate->path);
-
   CLEANUP_FONT:
     cairo_scaled_font_destroy (gstate->scaled_font);
     gstate->scaled_font = NULL;
@@ -204,8 +195,6 @@
 
     cairo_pattern_destroy (gstate->source);
 
-    _cairo_path_fixed_fini (&gstate->path);
-
     _cairo_pen_fini (&gstate->pen_regular);
 
     if (gstate->dash) {
@@ -680,7 +669,7 @@
     return CAIRO_STATUS_SUCCESS;
 }
 
-static void
+void
 _cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y)
 {
     cairo_matrix_transform_point (&gstate->ctm, x, y);
@@ -690,7 +679,7 @@
     }
 }
 
-static void
+void
 _cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y)
 {
     if (gstate->surface) {
@@ -700,393 +689,9 @@
     cairo_matrix_transform_point (&gstate->ctm_inverse, x, y);
 }
 
-cairo_status_t
-_cairo_gstate_new_path (cairo_gstate_t *gstate)
-{
-    _cairo_path_fixed_fini (&gstate->path);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-_cairo_gstate_move_to (cairo_gstate_t *gstate, double x, double y)
-{
-    cairo_point_t point;
-
-    _cairo_gstate_user_to_backend (gstate, &x, &y);
-
-    point.x = _cairo_fixed_from_double (x);
-    point.y = _cairo_fixed_from_double (y);
-
-    return _cairo_path_fixed_move_to (&gstate->path, &point);
-}
-
-cairo_status_t
-_cairo_gstate_line_to (cairo_gstate_t *gstate, double x, double y)
-{
-    cairo_point_t point;
-
-    _cairo_gstate_user_to_backend (gstate, &x, &y);
-
-    point.x = _cairo_fixed_from_double (x);
-    point.y = _cairo_fixed_from_double (y);
-
-    return _cairo_path_fixed_line_to (&gstate->path, &point);
-}
-
-cairo_status_t
-_cairo_gstate_curve_to (cairo_gstate_t *gstate,
-			double x0, double y0,
-			double x1, double y1,
-			double x2, double y2)
-{
-    cairo_point_t p0, p1, p2;
-
-    _cairo_gstate_user_to_backend (gstate, &x0, &y0);
-    _cairo_gstate_user_to_backend (gstate, &x1, &y1);
-    _cairo_gstate_user_to_backend (gstate, &x2, &y2);
-
-    p0.x = _cairo_fixed_from_double (x0);
-    p0.y = _cairo_fixed_from_double (y0);
-
-    p1.x = _cairo_fixed_from_double (x1);
-    p1.y = _cairo_fixed_from_double (y1);
-
-    p2.x = _cairo_fixed_from_double (x2);
-    p2.y = _cairo_fixed_from_double (y2);
-
-    return _cairo_path_fixed_curve_to (&gstate->path, &p0, &p1, &p2);
-}
-
-/* Spline deviation from the circle in radius would be given by:
-
-	error = sqrt (x**2 + y**2) - 1
-
-   A simpler error function to work with is:
-
-	e = x**2 + y**2 - 1
-
-   From "Good approximation of circles by curvature-continuous Bezier
-   curves", Tor Dokken and Morten Daehlen, Computer Aided Geometric
-   Design 8 (1990) 22-41, we learn:
-
-	abs (max(e)) = 4/27 * sin**6(angle/4) / cos**2(angle/4)
-
-   and
-	abs (error) =~ 1/2 * e
-
-   Of course, this error value applies only for the particular spline
-   approximation that is used in _cairo_gstate_arc_segment.
-*/
-static double
-_arc_error_normalized (double angle)
-{
-    return 2.0/27.0 * pow (sin (angle / 4), 6) / pow (cos (angle / 4), 2);
-}
-
-static double
-_arc_max_angle_for_tolerance_normalized (double tolerance)
-{
-    double angle, error;
-    int i;
-
-    /* Use table lookup to reduce search time in most cases. */
-    struct {
-	double angle;
-	double error;
-    } table[] = {
-	{ M_PI / 1.0,   0.0185185185185185036127 },
-	{ M_PI / 2.0,   0.000272567143730179811158 },
-	{ M_PI / 3.0,   2.38647043651461047433e-05 },
-	{ M_PI / 4.0,   4.2455377443222443279e-06 },
-	{ M_PI / 5.0,   1.11281001494389081528e-06 },
-	{ M_PI / 6.0,   3.72662000942734705475e-07 },
-	{ M_PI / 7.0,   1.47783685574284411325e-07 },
-	{ M_PI / 8.0,   6.63240432022601149057e-08 },
-	{ M_PI / 9.0,   3.2715520137536980553e-08 },
-	{ M_PI / 10.0,  1.73863223499021216974e-08 },
-	{ M_PI / 11.0,  9.81410988043554039085e-09 },
-    };
-    int table_size = (sizeof (table) / sizeof (table[0]));
-
-    for (i = 0; i < table_size; i++)
-	if (table[i].error < tolerance)
-	    return table[i].angle;
-
-    ++i;
-    do {
-	angle = M_PI / i++;
-	error = _arc_error_normalized (angle);
-    } while (error > tolerance);
-
-    return angle;
-}
-
-static int
-_cairo_gstate_arc_segments_needed (cairo_gstate_t *gstate,
-				   double angle,
-				   double radius)
-{
-    double l1, l2, lmax;
-    double max_angle;
-
-    _cairo_matrix_compute_eigen_values (&gstate->ctm, &l1, &l2);
-
-    l1 = fabs (l1);
-    l2 = fabs (l2);
-    if (l1 > l2)
-	lmax = l1;
-    else
-	lmax = l2;
-
-    max_angle = _arc_max_angle_for_tolerance_normalized (gstate->tolerance / (radius * lmax));
-
-    return (int) ceil (angle / max_angle);
-}
-
-/* We want to draw a single spline approximating a circular arc radius
-   R from angle A to angle B. Since we want a symmetric spline that
-   matches the endpoints of the arc in position and slope, we know
-   that the spline control points must be:
-
-	(R * cos(A), R * sin(A))
-	(R * cos(A) - h * sin(A), R * sin(A) + h * cos (A))
-	(R * cos(B) + h * sin(B), R * sin(B) - h * cos (B))
-	(R * cos(B), R * sin(B))
-
-   for some value of h.
-
-   "Approximation of circular arcs by cubic poynomials", Michael
-   Goldapp, Computer Aided Geometric Design 8 (1991) 227-238, provides
-   various values of h along with error analysis for each.
-
-   From that paper, a very practical value of h is:
-
-	h = 4/3 * tan(angle/4)
-
-   This value does not give the spline with minimal error, but it does
-   provide a very good approximation, (6th-order convergence), and the
-   error expression is quite simple, (see the comment for
-   _arc_error_normalized).
-*/
-static cairo_status_t
-_cairo_gstate_arc_segment (cairo_gstate_t *gstate,
-			   double xc, double yc,
-			   double radius,
-			   double angle_A, double angle_B)
-{
-    cairo_status_t status;
-    double r_sin_A, r_cos_A;
-    double r_sin_B, r_cos_B;
-    double h;
-
-    r_sin_A = radius * sin (angle_A);
-    r_cos_A = radius * cos (angle_A);
-    r_sin_B = radius * sin (angle_B);
-    r_cos_B = radius * cos (angle_B);
-
-    h = 4.0/3.0 * tan ((angle_B - angle_A) / 4.0);
-
-    status = _cairo_gstate_curve_to (gstate,
-				     xc + r_cos_A - h * r_sin_A, yc + r_sin_A + h * r_cos_A,
-				     xc + r_cos_B + h * r_sin_B, yc + r_sin_B - h * r_cos_B,
-				     xc + r_cos_B, yc + r_sin_B);
-    if (status)
-	return status;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_gstate_arc_dir (cairo_gstate_t *gstate,
-		       double xc, double yc,
-		       double radius,
-		       double angle_min,
-		       double angle_max,
-		       cairo_direction_t dir)
-{
-    cairo_status_t status;
-
-    while (angle_max - angle_min > 4 * M_PI)
-	angle_max -= 2 * M_PI;
-
-    /* Recurse if drawing arc larger than pi */
-    if (angle_max - angle_min > M_PI) {
-	double angle_mid = angle_min + (angle_max - angle_min) / 2.0;
-	/* XXX: Something tells me this block could be condensed. */
-	if (dir == CAIRO_DIRECTION_FORWARD) {
-	    status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
-					    angle_min, angle_mid, dir);
-	    if (status)
-		return status;
-	    
-	    status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
-					    angle_mid, angle_max, dir);
-	    if (status)
-		return status;
-	} else {
-	    status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
-					    angle_mid, angle_max, dir);
-	    if (status)
-		return status;
-
-	    status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
-					    angle_min, angle_mid, dir);
-	    if (status)
-		return status;
-	}
-    } else {
-	int i, segments;
-	double angle, angle_step;
-
-	segments = _cairo_gstate_arc_segments_needed (gstate,
-						      angle_max - angle_min,
-						      radius);
-	angle_step = (angle_max - angle_min) / (double) segments;
-
-	if (dir == CAIRO_DIRECTION_FORWARD) {
-	    angle = angle_min;
-	} else {
-	    angle = angle_max;
-	    angle_step = - angle_step;
-	}
-
-	for (i = 0; i < segments; i++, angle += angle_step) {
-	    _cairo_gstate_arc_segment (gstate,
-				       xc, yc,
-				       radius,
-				       angle,
-				       angle + angle_step);
-	}
-	
-    }
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-_cairo_gstate_arc (cairo_gstate_t *gstate,
-		   double xc, double yc,
-		   double radius,
-		   double angle1, double angle2)
-{
-    cairo_status_t status;
-
-    if (radius <= 0.0)
-	return CAIRO_STATUS_SUCCESS;
-
-    while (angle2 < angle1)
-	angle2 += 2 * M_PI;
-
-    status = _cairo_gstate_line_to (gstate,
-				    xc + radius * cos (angle1),
-				    yc + radius * sin (angle1));
-    if (status)
-	return status;
-
-    status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
-				    angle1, angle2, CAIRO_DIRECTION_FORWARD);
-    if (status)
-	return status;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-_cairo_gstate_arc_negative (cairo_gstate_t *gstate,
-			    double xc, double yc,
-			    double radius,
-			    double angle1, double angle2)
-{
-    cairo_status_t status;
-
-    if (radius <= 0.0)
-	return CAIRO_STATUS_SUCCESS;
-
-    while (angle2 > angle1)
-	angle2 -= 2 * M_PI;
-
-    status = _cairo_gstate_line_to (gstate,
-				    xc + radius * cos (angle1),
-				    yc + radius * sin (angle1));
-    if (status)
-	return status;
-
-    status = _cairo_gstate_arc_dir (gstate, xc, yc, radius,
-				    angle2, angle1, CAIRO_DIRECTION_REVERSE);
-    if (status)
-	return status;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-/* XXX: NYI
-cairo_status_t
-_cairo_gstate_arc_to (cairo_gstate_t *gstate,
-		      double x1, double y1,
-		      double x2, double y2,
-		      double radius)
-{
-
-}
-*/
-
-cairo_status_t
-_cairo_gstate_rel_move_to (cairo_gstate_t *gstate, double dx, double dy)
-{
-    cairo_distance_t distance;
-
-    cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
-
-    distance.dx = _cairo_fixed_from_double (dx);
-    distance.dy = _cairo_fixed_from_double (dy);
-
-    return _cairo_path_fixed_rel_move_to (&gstate->path, &distance);
-}
-
-cairo_status_t
-_cairo_gstate_rel_line_to (cairo_gstate_t *gstate, double dx, double dy)
-{
-    cairo_distance_t distance;
-
-    cairo_matrix_transform_distance (&gstate->ctm, &dx, &dy);
-
-    distance.dx = _cairo_fixed_from_double (dx);
-    distance.dy = _cairo_fixed_from_double (dy);
-
-    return _cairo_path_fixed_rel_line_to (&gstate->path, &distance);
-}
-
-cairo_status_t
-_cairo_gstate_rel_curve_to (cairo_gstate_t *gstate,
-			    double dx0, double dy0,
-			    double dx1, double dy1,
-			    double dx2, double dy2)
-{
-    cairo_distance_t distance[3];
-
-    cairo_matrix_transform_distance (&gstate->ctm, &dx0, &dy0);
-    cairo_matrix_transform_distance (&gstate->ctm, &dx1, &dy1);
-    cairo_matrix_transform_distance (&gstate->ctm, &dx2, &dy2);
-
-    distance[0].dx = _cairo_fixed_from_double (dx0);
-    distance[0].dy = _cairo_fixed_from_double (dy0);
-
-    distance[1].dx = _cairo_fixed_from_double (dx1);
-    distance[1].dy = _cairo_fixed_from_double (dy1);
-
-    distance[2].dx = _cairo_fixed_from_double (dx2);
-    distance[2].dy = _cairo_fixed_from_double (dy2);
-
-    return _cairo_path_fixed_rel_curve_to (&gstate->path,
-					   &distance[0],
-					   &distance[1],
-					   &distance[2]);
-}
-
 /* XXX: NYI 
 cairo_status_t
-_cairo_gstate_stroke_path (cairo_gstate_t *gstate)
+_cairo_gstate_stroke_to_path (cairo_gstate_t *gstate)
 {
     cairo_status_t status;
 
@@ -1095,194 +700,6 @@
 }
 */
 
-cairo_status_t
-_cairo_gstate_close_path (cairo_gstate_t *gstate)
-{
-    return _cairo_path_fixed_close_path (&gstate->path);
-}
-
-cairo_status_t
-_cairo_gstate_get_current_point (cairo_gstate_t *gstate, double *x_ret, double *y_ret)
-{
-    cairo_status_t status;
-    cairo_point_t point;
-    double x, y;
-
-    status = _cairo_path_fixed_get_current_point (&gstate->path, &point);
-    if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
-	x = 0.0;
-	y = 0.0;
-    } else {
-	x = _cairo_fixed_to_double (point.x);
-	y = _cairo_fixed_to_double (point.y);
-	_cairo_gstate_backend_to_user (gstate, &x, &y);
-    }
-
-    if (x_ret)
-	*x_ret = x;
-    if (y_ret)
-	*y_ret = y;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-typedef struct gstate_path_interpreter {
-    cairo_matrix_t		ctm_inverse;
-    double			tolerance;
-    cairo_point_t		current_point;
-
-    cairo_move_to_func_t	*move_to;
-    cairo_line_to_func_t	*line_to;
-    cairo_curve_to_func_t	*curve_to;
-    cairo_close_path_func_t	*close_path;
-
-    void			*closure;
-} gpi_t;
-
-static cairo_status_t
-_gpi_move_to (void *closure, cairo_point_t *point)
-{
-    gpi_t *gpi = closure;
-    double x, y;
-
-    x = _cairo_fixed_to_double (point->x);
-    y = _cairo_fixed_to_double (point->y);
-
-    cairo_matrix_transform_point (&gpi->ctm_inverse, &x, &y);
-
-    gpi->move_to (gpi->closure, x, y);
-    gpi->current_point = *point;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_gpi_line_to (void *closure, cairo_point_t *point)
-{
-    gpi_t *gpi = closure;
-    double x, y;
-
-    x = _cairo_fixed_to_double (point->x);
-    y = _cairo_fixed_to_double (point->y);
-
-    cairo_matrix_transform_point (&gpi->ctm_inverse, &x, &y);
-
-    gpi->line_to (gpi->closure, x, y);
-    gpi->current_point = *point;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_gpi_curve_to (void *closure,
-	       cairo_point_t *p1,
-	       cairo_point_t *p2,
-	       cairo_point_t *p3)
-{
-    gpi_t *gpi = closure;
-    cairo_status_t status;
-    cairo_spline_t spline;
-    double x1, y1, x2, y2, x3, y3;
-
-    if (gpi->curve_to) {
-	x1 = _cairo_fixed_to_double (p1->x);
-	y1 = _cairo_fixed_to_double (p1->y);
-	cairo_matrix_transform_point (&gpi->ctm_inverse, &x1, &y1);
-
-	x2 = _cairo_fixed_to_double (p2->x);
-	y2 = _cairo_fixed_to_double (p2->y);
-	cairo_matrix_transform_point (&gpi->ctm_inverse, &x2, &y2);
-
-	x3 = _cairo_fixed_to_double (p3->x);
-	y3 = _cairo_fixed_to_double (p3->y);
-	cairo_matrix_transform_point (&gpi->ctm_inverse, &x3, &y3);
-
-	gpi->curve_to (gpi->closure, x1, y1, x2, y2, x3, y3);
-    } else {
-	cairo_point_t *p0 = &gpi->current_point;
-	int i;
-	double x, y;
-
-	status = _cairo_spline_init (&spline, p0, p1, p2, p3);
-	if (status == CAIRO_INT_STATUS_DEGENERATE)
-	    return CAIRO_STATUS_SUCCESS;
-
-	status = _cairo_spline_decompose (&spline, gpi->tolerance);
-	if (status)
-	    return status;
-
-	for (i=1; i < spline.num_points; i++) {
-	    x = _cairo_fixed_to_double (spline.points[i].x);
-	    y = _cairo_fixed_to_double (spline.points[i].y);
-
-	    cairo_matrix_transform_point (&gpi->ctm_inverse, &x, &y);
-
-	    gpi->line_to (gpi->closure, x, y);
-	}
-    }
-
-    gpi->current_point = *p3;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_gpi_close_path (void *closure)
-{
-    gpi_t *gpi = closure;
-
-    gpi->close_path (gpi->closure);
-
-    gpi->current_point.x = 0;
-    gpi->current_point.y = 0;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-/* It's OK for curve_path to be NULL. In that case, all curves in the
-   path will be decomposed into one or more calls to the line_to
-   function, (according to the current tolerance). */
-cairo_status_t
-_cairo_gstate_interpret_path (cairo_gstate_t		*gstate,
-			      cairo_move_to_func_t	*move_to,
-			      cairo_line_to_func_t	*line_to,
-			      cairo_curve_to_func_t	*curve_to,
-			      cairo_close_path_func_t	*close_path,
-			      void			*closure)
-{
-    cairo_path_fixed_t path;
-    gpi_t gpi;
-
-    /* Anything we want from gstate must be copied. We must not retain
-       pointers into gstate. */
-    _cairo_path_fixed_init_copy (&path, &gstate->path);
-
-    gpi.ctm_inverse = gstate->ctm_inverse;
-    if (gstate->surface)
-	cairo_matrix_translate (&gpi.ctm_inverse,
-				- gstate->surface->device_x_offset,
-				- gstate->surface->device_y_offset);
-				
-    gpi.tolerance = gstate->tolerance;
-
-    gpi.move_to = move_to;
-    gpi.line_to = line_to;
-    gpi.curve_to = curve_to;
-    gpi.close_path = close_path;
-    gpi.closure = closure;
-
-    gpi.current_point.x = 0;
-    gpi.current_point.y = 0;
-
-    return _cairo_path_fixed_interpret (&path,
-					CAIRO_DIRECTION_FORWARD,
-					_gpi_move_to,
-					_gpi_line_to,
-					_gpi_curve_to,
-					_gpi_close_path,
-					&gpi);
-}
-
 static void
 _cairo_gstate_pattern_transform (cairo_gstate_t  *gstate,
 				 cairo_pattern_t *pattern)
@@ -1305,7 +722,7 @@
 }
 
 cairo_status_t
-_cairo_gstate_stroke (cairo_gstate_t *gstate)
+_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
 {
     cairo_status_t status;
     cairo_traps_t traps;
@@ -1317,7 +734,7 @@
 
     _cairo_traps_init (&traps);
 
-    status = _cairo_path_fixed_stroke_to_traps (&gstate->path, gstate, &traps);
+    status = _cairo_path_fixed_stroke_to_traps (path, gstate, &traps);
     if (status) {
 	_cairo_traps_fini (&traps);
 	return status;
@@ -1331,16 +748,15 @@
 
     _cairo_traps_fini (&traps);
 
-    _cairo_gstate_new_path (gstate);
-
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_status_t
-_cairo_gstate_in_stroke (cairo_gstate_t	*gstate,
-			 double		x,
-			 double		y,
-			 cairo_bool_t	*inside_ret)
+_cairo_gstate_in_stroke (cairo_gstate_t	    *gstate,
+			 cairo_path_fixed_t *path,
+			 double		     x,
+			 double		     y,
+			 cairo_bool_t	    *inside_ret)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_traps_t traps;
@@ -1351,7 +767,7 @@
 
     _cairo_traps_init (&traps);
 
-    status = _cairo_path_fixed_stroke_to_traps (&gstate->path, gstate, &traps);
+    status = _cairo_path_fixed_stroke_to_traps (path, gstate, &traps);
     if (status)
 	goto BAIL;
 
@@ -1835,14 +1251,14 @@
 }
 
 cairo_status_t
-_cairo_gstate_fill (cairo_gstate_t *gstate)
+_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
 {
     cairo_status_t status;
     cairo_traps_t traps;
 
     _cairo_traps_init (&traps);
 
-    status = _cairo_path_fixed_fill_to_traps (&gstate->path, gstate, &traps);
+    status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
     if (status) {
 	_cairo_traps_fini (&traps);
 	return status;
@@ -1856,16 +1272,15 @@
 
     _cairo_traps_fini (&traps);
 
-    _cairo_gstate_new_path (gstate);
-
     return CAIRO_STATUS_SUCCESS;
 }
 
 cairo_status_t
-_cairo_gstate_in_fill (cairo_gstate_t	*gstate,
-		       double		x,
-		       double		y,
-		       cairo_bool_t	*inside_ret)
+_cairo_gstate_in_fill (cairo_gstate_t	  *gstate,
+		       cairo_path_fixed_t *path,
+		       double		   x,
+		       double		   y,
+		       cairo_bool_t	  *inside_ret)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_traps_t traps;
@@ -1874,7 +1289,7 @@
 
     _cairo_traps_init (&traps);
 
-    status = _cairo_path_fixed_fill_to_traps (&gstate->path, gstate, &traps);
+    status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
     if (status)
 	goto BAIL;
 
@@ -1905,7 +1320,8 @@
 }
 
 cairo_status_t
-_cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
+_cairo_gstate_stroke_extents (cairo_gstate_t	 *gstate,
+			      cairo_path_fixed_t *path,
                               double *x1, double *y1,
 			      double *x2, double *y2)
 {
@@ -1917,7 +1333,7 @@
 
     _cairo_traps_init (&traps);
   
-    status = _cairo_path_fixed_stroke_to_traps (&gstate->path, gstate, &traps);
+    status = _cairo_path_fixed_stroke_to_traps (path, gstate, &traps);
     if (status)
 	goto BAIL;
 
@@ -1938,7 +1354,8 @@
 }
 
 cairo_status_t
-_cairo_gstate_fill_extents (cairo_gstate_t *gstate,
+_cairo_gstate_fill_extents (cairo_gstate_t     *gstate,
+			    cairo_path_fixed_t *path,
                             double *x1, double *y1,
 			    double *x2, double *y2)
 {
@@ -1948,7 +1365,7 @@
   
     _cairo_traps_init (&traps);
   
-    status = _cairo_path_fixed_fill_to_traps (&gstate->path, gstate, &traps);
+    status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
     if (status)
 	goto BAIL;
   
@@ -2008,7 +1425,7 @@
 }
 
 cairo_status_t
-_cairo_gstate_clip (cairo_gstate_t *gstate)
+_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
 {
     cairo_status_t status;
     cairo_pattern_union_t pattern;
@@ -2019,7 +1436,7 @@
     /* Fill the clip region as traps. */
 
     _cairo_traps_init (&traps);
-    status = _cairo_path_fixed_fill_to_traps (&gstate->path, gstate, &traps);
+    status = _cairo_path_fixed_fill_to_traps (path, gstate, &traps);
     if (!CAIRO_OK (status)) {
 	_cairo_traps_fini (&traps);
 	return status;
@@ -2104,8 +1521,10 @@
 cairo_status_t
 _cairo_gstate_show_surface (cairo_gstate_t	*gstate,
 			    cairo_surface_t	*surface,
-			    int			width,
-			    int			height)
+			    double		x,
+			    double		y,
+			    double		width,
+			    double		height)
 {
 
     /* We are dealing with 6 coordinate spaces in this function. this makes
@@ -2199,7 +1618,8 @@
 	image_to_backend = image_to_device;
     }
 
-    _cairo_gstate_get_current_point (gstate, &backend_x, &backend_y);
+    backend_x = x;
+    backend_y = y;
     backend_width = width;
     backend_height = height;
     _cairo_matrix_transform_bounding_box (&image_to_backend,
@@ -2480,30 +1900,18 @@
 cairo_status_t
 _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate, 
 			      const char     *utf8,
+			      double	      x,
+			      double	      y,
 			      cairo_glyph_t **glyphs,
 			      int	     *num_glyphs)
 {
     cairo_status_t status;
-
-    cairo_point_t point; 
-    double origin_x, origin_y;
     int i;
 
     status = _cairo_gstate_ensure_font (gstate);
     if (status)
 	return status;
     
-    status = _cairo_path_fixed_get_current_point (&gstate->path, &point);
-    if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
-	origin_x = 0.0;
-	origin_y = 0.0;
-    } else {
-	origin_x = _cairo_fixed_to_double (point.x);
-	origin_y = _cairo_fixed_to_double (point.y);
-	_cairo_gstate_backend_to_user (gstate,
-				       &origin_x, &origin_y);
-    }
-
     status = _cairo_scaled_font_text_to_glyphs (gstate->scaled_font, 
 						utf8, glyphs, num_glyphs);
 
@@ -2518,8 +1926,8 @@
 	cairo_matrix_transform_point (&gstate->font_matrix, 
 				      &((*glyphs)[i].x),
 				      &((*glyphs)[i].y));
-	(*glyphs)[i].x += origin_x;
-	(*glyphs)[i].y += origin_y;
+	(*glyphs)[i].x += x;
+	(*glyphs)[i].y += y;
     }
     
     return CAIRO_STATUS_SUCCESS;
@@ -2703,9 +2111,10 @@
 }
 
 cairo_status_t
-_cairo_gstate_glyph_path (cairo_gstate_t *gstate,
-			  cairo_glyph_t *glyphs, 
-			  int num_glyphs)
+_cairo_gstate_glyph_path (cairo_gstate_t     *gstate,
+			  cairo_glyph_t	     *glyphs, 
+			  int		      num_glyphs,
+			  cairo_path_fixed_t *path)
 {
     cairo_status_t status;
     int i;
@@ -2725,7 +2134,7 @@
 
     status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
 					    transformed_glyphs, num_glyphs,
-					    &gstate->path);
+					    path);
 
     free (transformed_glyphs);
     return status;

Index: cairo-path-data-private.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-path-data-private.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- cairo-path-data-private.h	23 Mar 2005 21:52:11 -0000	1.3
+++ cairo-path-data-private.h	26 Apr 2005 19:38:06 -0000	1.4
@@ -41,10 +41,14 @@
 extern cairo_path_t _cairo_path_nil;
 
 cairo_path_t *
-_cairo_path_data_create (cairo_gstate_t *gstate);
+_cairo_path_data_create (cairo_path_fixed_t *path,
+			 cairo_matrix_t	    *ctm_inverse,
+			 double		     tolerance);
 
 cairo_path_t *
-_cairo_path_data_create_flat (cairo_gstate_t *gstate);
+_cairo_path_data_create_flat (cairo_path_fixed_t *path,
+			      cairo_matrix_t	 *ctm_inverse,
+			      double		  tolerance);
 
 cairo_status_t
 _cairo_path_data_append_to_context (cairo_path_t *path,

Index: cairo-path-data.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-path-data.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- cairo-path-data.c	18 Mar 2005 22:28:53 -0000	1.2
+++ cairo-path-data.c	26 Apr 2005 19:38:06 -0000	1.3
@@ -34,6 +34,8 @@
  */
 
 #include "cairo-path-data-private.h"
+#include "cairo-path-fixed-private.h"
+#include "cairo-gstate-private.h"
 
 cairo_path_t
 _cairo_path_nil = { NULL, 0 };
@@ -41,56 +43,113 @@
 /* Closure for path interpretation. */
 typedef struct cairo_path_data_count {
     int count;
+    double tolerance;
+    cairo_point_t current_point;
 } cpdc_t;
 
-static void
-_cpdc_move_to (void *closure, double x, double y)
+static cairo_status_t
+_cpdc_move_to (void *closure, cairo_point_t *point)
 {
     cpdc_t *cpdc = closure;
 
     cpdc->count += 2;
+
+    cpdc->current_point = *point;
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static void
-_cpdc_line_to (void *closure, double x, double y)
+static cairo_status_t
+_cpdc_line_to (void *closure, cairo_point_t *point)
 {
     cpdc_t *cpdc = closure;
 
     cpdc->count += 2;
+
+    cpdc->current_point = *point;
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static void
-_cpdc_curve_to (void *closure,
-		double x1, double y1,
-		double x2, double y2,
-		double x3, double y3)
+static cairo_status_t
+_cpdc_curve_to (void	      *closure,
+		cairo_point_t *p1,
+		cairo_point_t *p2,
+		cairo_point_t *p3)
 {
     cpdc_t *cpdc = closure;
 
     cpdc->count += 4;
+
+    cpdc->current_point = *p3;
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static void
+static cairo_status_t
+_cpdc_curve_to_flatten (void	      *closure,
+			cairo_point_t *p1,
+			cairo_point_t *p2,
+			cairo_point_t *p3)
+{
+    cpdc_t *cpdc = closure;
+    cairo_status_t status;
+    cairo_spline_t spline;
+    int i;
+
+    cairo_point_t *p0 = &cpdc->current_point;
+
+    status = _cairo_spline_init (&spline, p0, p1, p2, p3);
+    if (status == CAIRO_INT_STATUS_DEGENERATE)
+	return CAIRO_STATUS_SUCCESS;
+
+    status = _cairo_spline_decompose (&spline, cpdc->tolerance);
+    if (status)
+	return status;
+
+    for (i=1; i < spline.num_points; i++)
+	_cpdc_line_to (cpdc, &spline.points[i]);
+
+    cpdc->current_point = *p3;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
 _cpdc_close_path (void *closure)
 {
     cpdc_t *cpdc = closure;
 
     cpdc->count += 1;
+
+    cpdc->current_point.x = 0;
+    cpdc->current_point.y = 0;
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static int
-_cairo_path_data_count (cairo_gstate_t *gstate, cairo_bool_t flatten)
+_cairo_path_data_count (cairo_path_t	   *path,
+			cairo_path_fixed_t *path_fixed,
+			double		    tolerance,
+			cairo_bool_t	    flatten)
 {
     cpdc_t cpdc;
 
     cpdc.count = 0;
+    cpdc.tolerance = tolerance;
+    cpdc.current_point.x = 0;
+    cpdc.current_point.y = 0;
 
-    _cairo_gstate_interpret_path (gstate,
-				  _cpdc_move_to,
-				  _cpdc_line_to,
-				  flatten ? NULL : _cpdc_curve_to,
-				  _cpdc_close_path,
-				  &cpdc);
+    _cairo_path_fixed_interpret (path_fixed,
+				 CAIRO_DIRECTION_FORWARD,
+				 _cpdc_move_to,
+				 _cpdc_line_to,
+				 flatten ?
+				 _cpdc_curve_to_flatten :
+				 _cpdc_curve_to,
+				 _cpdc_close_path,
+				 &cpdc);
 
     return cpdc.count;
 }
@@ -98,13 +157,22 @@
 /* Closure for path interpretation. */
 typedef struct cairo_path_data_populate {
     cairo_path_data_t *data;
+    cairo_matrix_t    *ctm_inverse;
+    double	       tolerance;
+    cairo_point_t      current_point;
 } cpdp_t;
 
-static void
-_cpdp_move_to (void *closure, double x, double y)
+static cairo_status_t
+_cpdp_move_to (void *closure, cairo_point_t *point)
 {
     cpdp_t *cpdp = closure;
     cairo_path_data_t *data = cpdp->data;
+    double x, y;
+
+    x = _cairo_fixed_to_double (point->x);
+    y = _cairo_fixed_to_double (point->y);
+
+    cairo_matrix_transform_point (cpdp->ctm_inverse, &x, &y);
 
     data->header.type = CAIRO_PATH_MOVE_TO;
     data->header.length = 2;
@@ -114,13 +182,23 @@
     data[1].point.y = y;
 
     cpdp->data += data->header.length;
+
+    cpdp->current_point = *point;
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static void
-_cpdp_line_to (void *closure, double x, double y)
+static cairo_status_t
+_cpdp_line_to (void *closure, cairo_point_t *point)
 {
     cpdp_t *cpdp = closure;
     cairo_path_data_t *data = cpdp->data;
+    double x, y;
+
+    x = _cairo_fixed_to_double (point->x);
+    y = _cairo_fixed_to_double (point->y);
+
+    cairo_matrix_transform_point (cpdp->ctm_inverse, &x, &y);
 
     data->header.type = CAIRO_PATH_LINE_TO;
     data->header.length = 2;
@@ -130,16 +208,35 @@
     data[1].point.y = y;
 
     cpdp->data += data->header.length;
+
+    cpdp->current_point = *point;
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static void
-_cpdp_curve_to (void *closure,
-		double x1, double y1,
-		double x2, double y2,
-		double x3, double y3)
+static cairo_status_t
+_cpdp_curve_to (void	      *closure,
+		cairo_point_t *p1,
+		cairo_point_t *p2,
+		cairo_point_t *p3)
 {
     cpdp_t *cpdp = closure;
     cairo_path_data_t *data = cpdp->data;
+    double x1, y1;
+    double x2, y2;
+    double x3, y3;
+
+    x1 = _cairo_fixed_to_double (p1->x);
+    y1 = _cairo_fixed_to_double (p1->y);
+    cairo_matrix_transform_point (cpdp->ctm_inverse, &x1, &y1);
+
+    x2 = _cairo_fixed_to_double (p2->x);
+    y2 = _cairo_fixed_to_double (p2->y);
+    cairo_matrix_transform_point (cpdp->ctm_inverse, &x2, &y2);
+
+    x3 = _cairo_fixed_to_double (p3->x);
+    y3 = _cairo_fixed_to_double (p3->y);
+    cairo_matrix_transform_point (cpdp->ctm_inverse, &x3, &y3);
 
     data->header.type = CAIRO_PATH_CURVE_TO;
     data->header.length = 4;
@@ -155,9 +252,42 @@
     data[3].point.y = y3;
 
     cpdp->data += data->header.length;
+
+    cpdp->current_point = *p3;
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static void
+static cairo_status_t
+_cpdp_curve_to_flatten (void	      *closure,
+			cairo_point_t *p1,
+			cairo_point_t *p2,
+			cairo_point_t *p3)
+{
+    cpdp_t *cpdp = closure;
+    cairo_status_t status;
+    cairo_spline_t spline;
+    int i;
+
+    cairo_point_t *p0 = &cpdp->current_point;
+
+    status = _cairo_spline_init (&spline, p0, p1, p2, p3);
+    if (status == CAIRO_INT_STATUS_DEGENERATE)
+	return CAIRO_STATUS_SUCCESS;
+
+    status = _cairo_spline_decompose (&spline, cpdp->tolerance);
+    if (status)
+	return status;
+
+    for (i=1; i < spline.num_points; i++)
+	_cpdp_line_to (cpdp, &spline.points[i]);
+
+    cpdp->current_point = *p3;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
 _cpdp_close_path (void *closure)
 {
     cpdp_t *cpdp = closure;
@@ -167,30 +297,47 @@
     data->header.length = 1;
 
     cpdp->data += data->header.length;
+
+    cpdp->current_point.x = 0;
+    cpdp->current_point.y = 0;
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _cairo_path_data_populate (cairo_path_t   *path,
-			   cairo_gstate_t *gstate,
+			   cairo_path_fixed_t *path_fixed,
+			   cairo_matrix_t *ctm_inverse,
+			   double	   tolerance,
 			   cairo_bool_t	   flatten)
 {
     cpdp_t cpdp;
 
     cpdp.data = path->data;
+    cpdp.ctm_inverse = ctm_inverse;
+    cpdp.tolerance = tolerance;
+    cpdp.current_point.x = 0;
+    cpdp.current_point.y = 0;
 
-    _cairo_gstate_interpret_path (gstate,
-				  _cpdp_move_to,
-				  _cpdp_line_to,
-				  flatten ? NULL : _cpdp_curve_to,
-				  _cpdp_close_path,
-				  &cpdp);
+    _cairo_path_fixed_interpret (path_fixed,
+				 CAIRO_DIRECTION_FORWARD,
+				 _cpdp_move_to,
+				 _cpdp_line_to,
+				 flatten ?
+				 _cpdp_curve_to_flatten :
+				 _cpdp_curve_to,
+				 _cpdp_close_path,
+				 &cpdp);
 
     /* Sanity check the count */
     assert (cpdp.data - path->data == path->num_data);
 }
 
 static cairo_path_t *
-_cairo_path_data_create_real (cairo_gstate_t *gstate, cairo_bool_t flatten)
+_cairo_path_data_create_real (cairo_path_fixed_t *path_fixed,
+			      cairo_matrix_t	 *ctm_inverse,
+			      double		  tolerance,
+			      cairo_bool_t	  flatten)
 {
     cairo_path_t *path;
 
@@ -198,7 +345,8 @@
     if (path == NULL)
 	return &_cairo_path_nil;
 
-    path->num_data = _cairo_path_data_count (gstate, flatten);
+    path->num_data = _cairo_path_data_count (path, path_fixed,
+					     tolerance, flatten);
 
     path->data = malloc (path->num_data * sizeof (cairo_path_data_t));
     if (path->data == NULL) {
@@ -206,7 +354,8 @@
 	return &_cairo_path_nil;
     }
 
-    _cairo_path_data_populate (path, gstate, flatten);
+    _cairo_path_data_populate (path, path_fixed,
+			       ctm_inverse, tolerance, flatten);
 
     return path;
 }
@@ -220,15 +369,19 @@
 }
 
 cairo_path_t *
-_cairo_path_data_create (cairo_gstate_t *gstate)
+_cairo_path_data_create (cairo_path_fixed_t *path,
+			 cairo_matrix_t	    *ctm_inverse,
+			 double		     tolerance)
 {
-    return _cairo_path_data_create_real (gstate, FALSE);
+    return _cairo_path_data_create_real (path, ctm_inverse, tolerance, FALSE);
 }
 
 cairo_path_t *
-_cairo_path_data_create_flat (cairo_gstate_t *gstate)
+_cairo_path_data_create_flat (cairo_path_fixed_t *path,
+			      cairo_matrix_t	 *ctm_inverse,
+			      double		  tolerance)
 {
-    return _cairo_path_data_create_real (gstate, TRUE);
+    return _cairo_path_data_create_real (path, ctm_inverse, tolerance, TRUE);
 }
 
 cairo_status_t

Index: cairo-path.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-path.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -d -r1.24 -r1.25
--- cairo-path.c	23 Mar 2005 22:36:29 -0000	1.24
+++ cairo-path.c	26 Apr 2005 19:38:06 -0000	1.25
@@ -156,16 +156,21 @@
 }
 
 cairo_status_t
-_cairo_path_fixed_move_to (cairo_path_fixed_t *path,
-			   cairo_point_t      *point)
+_cairo_path_fixed_move_to (cairo_path_fixed_t  *path,
+			   cairo_fixed_t	x,
+			   cairo_fixed_t	y)
 {
     cairo_status_t status;
+    cairo_point_t point;
 
-    status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, point, 1);
+    point.x = x;
+    point.y = y;
+
+    status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
     if (status)
 	return status;
 
-    path->current_point = *point;
+    path->current_point = point;
     path->has_current_point = 1;
     path->last_move_point = path->current_point;
 
@@ -174,27 +179,33 @@
 
 cairo_status_t
 _cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
-			       cairo_distance_t	  *distance)
+			       cairo_fixed_t	   dx,
+			       cairo_fixed_t	   dy)
 {
-    cairo_point_t point;
+    cairo_fixed_t x, y;
 
-    point.x = path->current_point.x + distance->dx;
-    point.y = path->current_point.y + distance->dy;
+    x = path->current_point.x + dx;
+    y = path->current_point.y + dy;
 
-    return _cairo_path_fixed_move_to (path, &point);
+    return _cairo_path_fixed_move_to (path, x, y);
 }
 
 cairo_status_t
 _cairo_path_fixed_line_to (cairo_path_fixed_t *path,
-			   cairo_point_t      *point)
+			   cairo_fixed_t	x,
+			   cairo_fixed_t	y)
 {
     cairo_status_t status;
+    cairo_point_t point;
 
-    status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, point, 1);
+    point.x = x;
+    point.y = y;
+
+    status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
     if (status)
 	return status;
 
-    path->current_point = *point;
+    path->current_point = point;
     path->has_current_point = 1;
 
     return CAIRO_STATUS_SUCCESS;
@@ -202,34 +213,35 @@
 
 cairo_status_t
 _cairo_path_fixed_rel_line_to (cairo_path_fixed_t *path,
-			       cairo_distance_t   *distance)
+			       cairo_fixed_t	   dx,
+			       cairo_fixed_t	   dy)
 {
-    cairo_point_t point;
+    cairo_fixed_t x, y;
 
-    point.x = path->current_point.x + distance->dx;
-    point.y = path->current_point.y + distance->dy;
+    x = path->current_point.x + dx;
+    y = path->current_point.y + dy;
 
-    return _cairo_path_fixed_line_to (path, &point);
+    return _cairo_path_fixed_line_to (path, x, y);
 }
 
 cairo_status_t
 _cairo_path_fixed_curve_to (cairo_path_fixed_t	*path,
-			    cairo_point_t	*p0,
-			    cairo_point_t	*p1,
-			    cairo_point_t	*p2)
+			    cairo_fixed_t x0, cairo_fixed_t y0,
+			    cairo_fixed_t x1, cairo_fixed_t y1,
+			    cairo_fixed_t x2, cairo_fixed_t y2)
 {
     cairo_status_t status;
     cairo_point_t point[3];
 
-    point[0] = *p0;
-    point[1] = *p1;
-    point[2] = *p2;
+    point[0].x = x0; point[0].y = y0;
+    point[1].x = x1; point[1].y = y1;
+    point[2].x = x2; point[2].y = y2;
 
     status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3);
     if (status)
 	return status;
 
-    path->current_point = *p2;
+    path->current_point = point[2];
     path->has_current_point = 1;
 
     return CAIRO_STATUS_SUCCESS;
@@ -237,22 +249,27 @@
 
 cairo_status_t
 _cairo_path_fixed_rel_curve_to (cairo_path_fixed_t *path,
-				cairo_distance_t   *d0,
-				cairo_distance_t   *d1,
-				cairo_distance_t   *d2)
+				cairo_fixed_t dx0, cairo_fixed_t dy0,
+				cairo_fixed_t dx1, cairo_fixed_t dy1,
+				cairo_fixed_t dx2, cairo_fixed_t dy2)
 {
-    cairo_point_t p0, p1, p2;
+    cairo_fixed_t x0, y0;
+    cairo_fixed_t x1, y1;
+    cairo_fixed_t x2, y2;
 
-    p0.x = path->current_point.x + d0->dx;
-    p0.y = path->current_point.y + d0->dy;
+    x0 = path->current_point.x + dx0;
+    y0 = path->current_point.y + dy0;
 
-    p1.x = path->current_point.x + d1->dx;
-    p1.y = path->current_point.y + d1->dy;
+    x1 = path->current_point.x + dx0;
+    y1 = path->current_point.y + dy0;
 
-    p2.x = path->current_point.x + d2->dx;
-    p2.y = path->current_point.y + d2->dy;
+    x2 = path->current_point.x + dx0;
+    y2 = path->current_point.y + dy0;
 
-    return _cairo_path_fixed_curve_to (path, &p0, &p1, &p2);
+    return _cairo_path_fixed_curve_to (path,
+				       x0, y0,
+				       x1, y1,
+				       x2, y2);
 }
 
 cairo_status_t
@@ -273,12 +290,14 @@
 
 cairo_status_t
 _cairo_path_fixed_get_current_point (cairo_path_fixed_t *path,
-				     cairo_point_t	*point)
+				     cairo_fixed_t	*x,
+				     cairo_fixed_t	*y)
 {
     if (! path->has_current_point)
 	return CAIRO_STATUS_NO_CURRENT_POINT;
 
-    *point = path->current_point;
+    *x = path->current_point.x;
+    *y = path->current_point.y;
 
     return CAIRO_STATUS_SUCCESS;
 }

Index: cairo-private.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-private.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- cairo-private.h	23 Mar 2005 21:51:26 -0000	1.1
+++ cairo-private.h	26 Apr 2005 19:38:06 -0000	1.2
@@ -37,10 +37,14 @@
 #define CAIRO_PRIVATE_H
 
 #include "cairo-gstate-private.h"
+#include "cairo-path-fixed-private.h"
 
 struct _cairo {
     unsigned int ref_count;
+
     cairo_gstate_t *gstate;
+    cairo_path_fixed_t path;
+
     cairo_status_t status;
 };
 

Index: cairo.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo.c,v
retrieving revision 1.80
retrieving revision 1.81
diff -u -d -r1.80 -r1.81
--- cairo.c	26 Apr 2005 03:42:54 -0000	1.80
+++ cairo.c	26 Apr 2005 19:38:06 -0000	1.81
@@ -36,8 +36,9 @@
  */
 
 #include "cairoint.h"
-
 #include "cairo-private.h"
+
+#include "cairo-arc-private.h"
 #include "cairo-path-data-private.h"
 
 #define CAIRO_TOLERANCE_MINIMUM	0.0002 /* We're limited by 16 bits of sub-pixel precision */
@@ -101,6 +102,8 @@
     if (cr->gstate == NULL)
 	cr->status = CAIRO_STATUS_NO_MEMORY;
 
+    _cairo_path_fixed_init (&cr->path);
+
     CAIRO_CHECK_SANITY (cr);
     return cr;
 }
@@ -147,6 +150,8 @@
 	_cairo_gstate_destroy (tmp);
     }
 
+    _cairo_path_fixed_fini (&cr->path);
+
     free (cr);
 }
 
@@ -1161,18 +1166,27 @@
     if (cr->status)
 	return;
 
-    cr->status = _cairo_gstate_new_path (cr->gstate);
+    _cairo_path_fixed_fini (&cr->path);
+
     CAIRO_CHECK_SANITY (cr);
 }
+slim_hidden_def(cairo_new_path);
 
 void
 cairo_move_to (cairo_t *cr, double x, double y)
 {
+    cairo_fixed_t x_fixed, y_fixed;
+
     CAIRO_CHECK_SANITY (cr);
     if (cr->status)
 	return;
 
-    cr->status = _cairo_gstate_move_to (cr->gstate, x, y);
+    _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
+    x_fixed = _cairo_fixed_from_double (x);
+    y_fixed = _cairo_fixed_from_double (y);
+
+    cr->status = _cairo_path_fixed_move_to (&cr->path, x_fixed, y_fixed);
+    
     CAIRO_CHECK_SANITY (cr);
 }
 slim_hidden_def(cairo_move_to);
@@ -1180,11 +1194,18 @@
 void
 cairo_line_to (cairo_t *cr, double x, double y)
 {
+    cairo_fixed_t x_fixed, y_fixed;
+
     CAIRO_CHECK_SANITY (cr);
     if (cr->status)
 	return;
 
-    cr->status = _cairo_gstate_line_to (cr->gstate, x, y);
+    _cairo_gstate_user_to_backend (cr->gstate, &x, &y);
+    x_fixed = _cairo_fixed_from_double (x);
+    y_fixed = _cairo_fixed_from_double (y);
+
+    cr->status = _cairo_path_fixed_line_to (&cr->path, x_fixed, y_fixed);
+
     CAIRO_CHECK_SANITY (cr);
 }
 
@@ -1194,14 +1215,32 @@
 		double x2, double y2,
 		double x3, double y3)
 {
+    cairo_fixed_t x1_fixed, y1_fixed;
+    cairo_fixed_t x2_fixed, y2_fixed;
+    cairo_fixed_t x3_fixed, y3_fixed;
+	
     CAIRO_CHECK_SANITY (cr);
     if (cr->status)
 	return;
 
-    cr->status = _cairo_gstate_curve_to (cr->gstate,
-					 x1, y1,
-					 x2, y2,
-					 x3, y3);
+    _cairo_gstate_user_to_backend (cr->gstate, &x1, &y1);
+    _cairo_gstate_user_to_backend (cr->gstate, &x2, &y2);
+    _cairo_gstate_user_to_backend (cr->gstate, &x3, &y3);
+
+    x1_fixed = _cairo_fixed_from_double (x1);
+    y1_fixed = _cairo_fixed_from_double (y1);
+
+    x2_fixed = _cairo_fixed_from_double (x2);
+    y2_fixed = _cairo_fixed_from_double (y2);
+
+    x3_fixed = _cairo_fixed_from_double (x3);
+    y3_fixed = _cairo_fixed_from_double (y3);
+
+    cr->status = _cairo_path_fixed_curve_to (&cr->path,
+					     x1_fixed, y1_fixed,
+					     x2_fixed, y2_fixed,
+					     x3_fixed, y3_fixed);
+
     CAIRO_CHECK_SANITY (cr);
 }
 
@@ -1248,10 +1287,20 @@
     if (cr->status)
 	return;
 
-    cr->status = _cairo_gstate_arc (cr->gstate,
-				    xc, yc,
-				    radius,
-				    angle1, angle2);
+    /* Do nothing, successfully, if radius is <= 0 */
+    if (radius <= 0.0)
+	return;
+
+    while (angle2 < angle1)
+	angle2 += 2 * M_PI;
+
+    cairo_line_to (cr,
+		   xc + radius * cos (angle1),
+		   yc + radius * sin (angle1));
+
+    _cairo_arc_path (cr, xc, yc, radius,
+		     angle1, angle2);
+
     CAIRO_CHECK_SANITY (cr);
 }
 
@@ -1279,10 +1328,20 @@
     if (cr->status)
 	return;
 
-    cr->status = _cairo_gstate_arc_negative (cr->gstate,
-					     xc, yc,
-					     radius,
-					     angle1, angle2);
+    /* Do nothing, successfully, if radius is <= 0 */
+    if (radius <= 0.0)
+	return;
+
+    while (angle2 > angle1)
+	angle2 -= 2 * M_PI;
+
+    cairo_line_to (cr,
+		   xc + radius * cos (angle1),
+		   yc + radius * sin (angle1));
+
+     _cairo_arc_path_negative (cr, xc, yc, radius,
+			       angle1, angle2);
+
     CAIRO_CHECK_SANITY (cr);
 }
 
@@ -1306,22 +1365,36 @@
 void
 cairo_rel_move_to (cairo_t *cr, double dx, double dy)
 {
+    cairo_fixed_t dx_fixed, dy_fixed;
+
     CAIRO_CHECK_SANITY (cr);
     if (cr->status)
 	return;
 
-    cr->status = _cairo_gstate_rel_move_to (cr->gstate, dx, dy);
+    _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy);
+    dx_fixed = _cairo_fixed_from_double (dx);
+    dy_fixed = _cairo_fixed_from_double (dy);
+
+    cr->status = _cairo_path_fixed_rel_move_to (&cr->path, dx_fixed, dy_fixed);
+
     CAIRO_CHECK_SANITY (cr);
 }
 
 void
 cairo_rel_line_to (cairo_t *cr, double dx, double dy)
 {
+    cairo_fixed_t dx_fixed, dy_fixed;
+
     CAIRO_CHECK_SANITY (cr);
     if (cr->status)
 	return;
 
-    cr->status = _cairo_gstate_rel_line_to (cr->gstate, dx, dy);
+    _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy);
+    dx_fixed = _cairo_fixed_from_double (dx);
+    dy_fixed = _cairo_fixed_from_double (dy);
+
+    cr->status = _cairo_path_fixed_rel_line_to (&cr->path, dx_fixed, dy_fixed);
+
     CAIRO_CHECK_SANITY (cr);
 }
 slim_hidden_def(cairo_rel_line_to);
@@ -1332,14 +1405,32 @@
 		    double dx2, double dy2,
 		    double dx3, double dy3)
 {
+    cairo_fixed_t dx1_fixed, dy1_fixed;
+    cairo_fixed_t dx2_fixed, dy2_fixed;
+    cairo_fixed_t dx3_fixed, dy3_fixed;
+
     CAIRO_CHECK_SANITY (cr);
     if (cr->status)
 	return;
 
-    cr->status = _cairo_gstate_rel_curve_to (cr->gstate,
-					     dx1, dy1,
-					     dx2, dy2,
-					     dx3, dy3);
+    _cairo_gstate_user_to_device_distance (cr->gstate, &dx1, &dy1);
+    _cairo_gstate_user_to_device_distance (cr->gstate, &dx2, &dy2);
+    _cairo_gstate_user_to_device_distance (cr->gstate, &dx3, &dy3);
+
+    dx1_fixed = _cairo_fixed_from_double (dx1);
+    dy1_fixed = _cairo_fixed_from_double (dy1);
+
+    dx2_fixed = _cairo_fixed_from_double (dx2);
+    dy2_fixed = _cairo_fixed_from_double (dy2);
+
+    dx3_fixed = _cairo_fixed_from_double (dx3);
+    dy3_fixed = _cairo_fixed_from_double (dy3);
+
+    cr->status = _cairo_path_fixed_rel_curve_to (&cr->path,
+						 dx1_fixed, dy1_fixed,
+						 dx2_fixed, dy2_fixed,
+						 dx3_fixed, dy3_fixed);
+
     CAIRO_CHECK_SANITY (cr);
 }
 
@@ -1378,7 +1469,8 @@
     if (cr->status)
 	return;
 
-    cr->status = _cairo_gstate_close_path (cr->gstate);
+    cr->status = _cairo_path_fixed_close_path (&cr->path);
+
     CAIRO_CHECK_SANITY (cr);
 }
 slim_hidden_def(cairo_close_path);
@@ -1412,27 +1504,90 @@
     CAIRO_CHECK_SANITY (cr);
 }
 
+/**
+ * cairo_stroke:
+ * @cr: a cairo context
+ * 
+ * A drawing operator that strokes the current path according to the
+ * current line width, line join, line cap, and dash settings. After
+ * cairo_stroke, the current path will be cleared from the cairo
+ * context. See cairo_set_line_width(), cairo_set_line_join(),
+ * cairo_set_line_cap(), cairo_set_dash(), and
+ * cairo_stroke_preserve().
+ **/
 void
 cairo_stroke (cairo_t *cr)
 {
+    cairo_stroke_preserve (cr);
+
+    cairo_new_path (cr);
+}
+
+/**
+ * cairo_stroke_preserve:
+ * @cr: a cairo context
+ * 
+ * A drawing operator that strokes the current path according to the
+ * current line width, line join, line cap, and dash settings. Unlike
+ * cairo_stroke(), cairo_stroke_preserve preserves the path within the
+ * cairo context.
+ *
+ * See cairo_set_line_width(), cairo_set_line_join(),
+ * cairo_set_line_cap(), cairo_set_dash(), and
+ * cairo_stroke_preserve().
+ **/
+void
+cairo_stroke_preserve (cairo_t *cr)
+{
     CAIRO_CHECK_SANITY (cr);
     if (cr->status)
 	return;
 
-    cr->status = _cairo_gstate_stroke (cr->gstate);
+    cr->status = _cairo_gstate_stroke (cr->gstate, &cr->path);
+
     CAIRO_CHECK_SANITY (cr);
 }
+slim_hidden_def(cairo_stroke_preserve);
 
+/**
+ * cairo_fill:
+ * @cr: a cairo context
+ * 
+ * A drawing operator that fills the current path according to the
+ * current fill rule. After cairo_fill, the current path will be
+ * cleared from the cairo context. See cairo_set_fill_rule() and
+ * cairo_fill_preserve().
+ **/
 void
 cairo_fill (cairo_t *cr)
 {
+    cairo_fill_preserve (cr);
+
+    cairo_new_path (cr);
+}
+
+/**
+ * cairo_fill_preserve:
+ * @cr: a cairo context
+ * 
+ * A drawing operator that fills the current path according to the
+ * current fill rule. Unlike cairo_fill(), cairo_fill_preserve
+ * preserves the path within the cairo context.
+ *
+ * See cairo_set_fill_rule() and cairo_fill().
+ **/
+void
+cairo_fill_preserve (cairo_t *cr)
+{
     CAIRO_CHECK_SANITY (cr);
     if (cr->status)
 	return;
 
-    cr->status = _cairo_gstate_fill (cr->gstate);
+    cr->status = _cairo_gstate_fill (cr->gstate, &cr->path);
+
     CAIRO_CHECK_SANITY (cr);
 }
+slim_hidden_def(cairo_fill_preserve);
 
 void
 cairo_copy_page (cairo_t *cr)
@@ -1465,7 +1620,9 @@
     if (cr->status)
 	return 0;
 
-    cr->status = _cairo_gstate_in_stroke (cr->gstate, x, y, &inside);
+    cr->status = _cairo_gstate_in_stroke (cr->gstate,
+					  &cr->path,
+					  x, y, &inside);
 
     CAIRO_CHECK_SANITY (cr);
 
@@ -1484,7 +1641,9 @@
     if (cr->status)
 	return 0;
 
-    cr->status = _cairo_gstate_in_fill (cr->gstate, x, y, &inside);
+    cr->status = _cairo_gstate_in_fill (cr->gstate,
+					&cr->path,
+					x, y, &inside);
 
     CAIRO_CHECK_SANITY (cr);
 
@@ -1502,7 +1661,9 @@
     if (cr->status)
 	return;
     
-    cr->status = _cairo_gstate_stroke_extents (cr->gstate, x1, y1, x2, y2);
+    cr->status = _cairo_gstate_stroke_extents (cr->gstate,
+					       &cr->path,
+					       x1, y1, x2, y2);
     CAIRO_CHECK_SANITY (cr);
 }
 
@@ -1514,7 +1675,9 @@
     if (cr->status)
 	return;
     
-    cr->status = _cairo_gstate_fill_extents (cr->gstate, x1, y1, x2, y2);
+    cr->status = _cairo_gstate_fill_extents (cr->gstate,
+					     &cr->path,
+					     x1, y1, x2, y2);
     CAIRO_CHECK_SANITY (cr);
 }
 
@@ -1526,6 +1689,9 @@
  * region with the current path as it would be filled by cairo_fill()
  * and according to the current fill rule (see cairo_set_fill_rule()).
  *
+ * After cairo_clip, the current path will be cleared from the cairo
+ * context.
+ *
  * The current clip region affects all drawing operations by
  * effectively masking out any changes to the surface that are outside
  * the current clip region.
@@ -1540,13 +1706,44 @@
 void
 cairo_clip (cairo_t *cr)
 {
+    cairo_clip_preserve (cr);
+
+    cairo_new_path (cr);
+}
+
+/**
+ * cairo_clip_preserve:
+ * @cr: a cairo context
+ * 
+ * Establishes a new clip region by intersecting the current clip
+ * region with the current path as it would be filled by cairo_fill()
+ * and according to the current fill rule (see cairo_set_fill_rule()).
+ *
+ * Unlike cairo_clip(), cairo_clip_preserve preserves the path within
+ * the cairo context.
+ *
+ * The current clip region affects all drawing operations by
+ * effectively masking out any changes to the surface that are outside
+ * the current clip region.
+ *
+ * Calling cairo_clip() can only make the clip region smaller, never
+ * larger. But the current clip is part of the graphics state, so a
+ * tempoarary restriction of the clip region can be achieved by
+ * calling cairo_clip() within a cairo_save()/cairo_restore()
+ * pair. The only other means of increasing the size of the clip
+ * region is cairo_reset_clip().
+ **/
+void
+cairo_clip_preserve (cairo_t *cr)
+{
     CAIRO_CHECK_SANITY (cr);
     if (cr->status)
 	return;
 
-    cr->status = _cairo_gstate_clip (cr->gstate);
+    cr->status = _cairo_gstate_clip (cr->gstate, &cr->path);
     CAIRO_CHECK_SANITY (cr);
 }
+slim_hidden_def(cairo_clip_preserve);
 
 /**
  * cairo_reset_clip:
@@ -1763,6 +1960,7 @@
 {
     cairo_glyph_t *glyphs = NULL;
     int num_glyphs;
+    double x, y;
 
     CAIRO_CHECK_SANITY (cr);
     if (cr->status)
@@ -1778,7 +1976,11 @@
 	return;
     }
 
-    cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8, &glyphs, &num_glyphs);
+    cairo_get_current_point (cr, &x, &y);
+
+    cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8,
+					       x, y,
+					       &glyphs, &num_glyphs);
     CAIRO_CHECK_SANITY (cr);
 
     if (cr->status) {
@@ -1832,6 +2034,7 @@
 {
     cairo_glyph_t *glyphs = NULL;
     int num_glyphs;
+    double x, y;
 
     CAIRO_CHECK_SANITY (cr);
     if (cr->status)
@@ -1840,7 +2043,10 @@
     if (utf8 == NULL)
 	return;
 
+    cairo_get_current_point (cr, &x, &y);
+
     cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8,
+					       x, y,
 					       &glyphs, &num_glyphs);
     CAIRO_CHECK_SANITY (cr);
 
@@ -1873,12 +2079,16 @@
 {
     cairo_glyph_t *glyphs = NULL;
     int num_glyphs;
+    double x, y;
 
     CAIRO_CHECK_SANITY (cr);
     if (cr->status)
 	return;
 
+    cairo_get_current_point (cr, &x, &y);
+
     cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8,
+					       x, y,
 					       &glyphs, &num_glyphs);
     CAIRO_CHECK_SANITY (cr);
 
@@ -1888,7 +2098,9 @@
 	return;
     }
 
-    cr->status = _cairo_gstate_glyph_path (cr->gstate, glyphs, num_glyphs);
+    cr->status = _cairo_gstate_glyph_path (cr->gstate,
+					   glyphs, num_glyphs,
+					   &cr->path);
     CAIRO_CHECK_SANITY (cr);
 
     if (glyphs)
@@ -1902,7 +2114,10 @@
     if (cr->status)
 	return;
 
-    cr->status = _cairo_gstate_glyph_path (cr->gstate, glyphs, num_glyphs);  
+    cr->status = _cairo_gstate_glyph_path (cr->gstate,
+					   glyphs, num_glyphs,
+					   &cr->path);
+    
     CAIRO_CHECK_SANITY (cr);
 }
 
@@ -1912,12 +2127,18 @@
 		    int			width,
 		    int			height)
 {
+    double x, y;
+
     CAIRO_CHECK_SANITY (cr);
     if (cr->status)
 	return;
 
+    cairo_get_current_point (cr, &x, &y);
+
     cr->status = _cairo_gstate_show_surface (cr->gstate,
-					     surface, width, height);
+					     surface,
+					     x, y,
+					     width, height);
     CAIRO_CHECK_SANITY (cr);
 }
 
@@ -2001,12 +2222,32 @@
  * cairo_text_path(), cairo_stroke_to_path()
  **/
 void
-cairo_get_current_point (cairo_t *cr, double *x, double *y)
+cairo_get_current_point (cairo_t *cr, double *x_ret, double *y_ret)
 {
+    cairo_status_t status;
+    cairo_fixed_t x_fixed, y_fixed;
+    double x, y;
+
     CAIRO_CHECK_SANITY (cr);
-    _cairo_gstate_get_current_point (cr->gstate, x, y);
+
+    status = _cairo_path_fixed_get_current_point (&cr->path, &x_fixed, &y_fixed);
+    if (status == CAIRO_STATUS_NO_CURRENT_POINT) {
+	x = 0.0;
+	y = 0.0;
+    } else {
+	x = _cairo_fixed_to_double (x_fixed);
+	y = _cairo_fixed_to_double (y_fixed);
+	_cairo_gstate_backend_to_user (cr->gstate, &x, &y);
+    }
+
+    if (x_ret)
+	*x_ret = x;
+    if (y_ret)
+	*y_ret = y;
+
     CAIRO_CHECK_SANITY (cr);
 }
+slim_hidden_def(cairo_get_current_point);
 DEPRECATE (cairo_current_point, cairo_get_current_point);
 
 /**
@@ -2228,7 +2469,9 @@
     if (cr->status)
 	return &_cairo_path_nil;
 
-    return _cairo_path_data_create (cr->gstate);
+    return _cairo_path_data_create (&cr->path,
+				    &cr->gstate->ctm_inverse,
+				    cr->gstate->tolerance);
 }
 
 /**
@@ -2257,7 +2500,9 @@
     if (cr->status)
 	return &_cairo_path_nil;
 
-    return _cairo_path_data_create_flat (cr->gstate);
+    return _cairo_path_data_create_flat (&cr->path,
+					 &cr->gstate->ctm_inverse,
+					 cr->gstate->tolerance);
 }
 
 /**

Index: cairo.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo.h,v
retrieving revision 1.103
retrieving revision 1.104
diff -u -d -r1.103 -r1.104
--- cairo.h	26 Apr 2005 04:36:39 -0000	1.103
+++ cairo.h	26 Apr 2005 19:38:06 -0000	1.104
@@ -466,9 +466,15 @@
 cairo_stroke (cairo_t *cr);
 
 void
+cairo_stroke_preserve (cairo_t *cr);
+
+void
 cairo_fill (cairo_t *cr);
 
 void
+cairo_fill_preserve (cairo_t *cr);
+
+void
 cairo_copy_page (cairo_t *cr);
 
 void
@@ -496,10 +502,12 @@
 void
 cairo_reset_clip (cairo_t *cr);
 
-/* Note: cairo_clip does not consume the current path */
 void
 cairo_clip (cairo_t *cr);
 
+void
+cairo_clip_preserve (cairo_t *cr);
+
 /* Font/Text functions */
 
 /**

Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.128
retrieving revision 1.129
diff -u -d -r1.128 -r1.129
--- cairoint.h	19 Apr 2005 23:29:05 -0000	1.128
+++ cairoint.h	26 Apr 2005 19:38:06 -0000	1.129
@@ -1042,104 +1042,56 @@
 cairo_private cairo_status_t
 _cairo_gstate_device_to_user_distance (cairo_gstate_t *gstate, double *dx, double *dy);
 
-cairo_private cairo_status_t
-_cairo_gstate_new_path (cairo_gstate_t *gstate);
-
-cairo_private cairo_status_t
-_cairo_gstate_move_to (cairo_gstate_t *gstate, double x, double y);
-
-cairo_private cairo_status_t
-_cairo_gstate_line_to (cairo_gstate_t *gstate, double x, double y);
-
-cairo_private cairo_status_t
-_cairo_gstate_curve_to (cairo_gstate_t *gstate,
-			double x1, double y1,
-			double x2, double y2,
-			double x3, double y3);
-
-cairo_private cairo_status_t
-_cairo_gstate_arc (cairo_gstate_t *gstate,
-		   double xc, double yc,
-		   double radius,
-		   double angle1, double angle2);
-
-cairo_private cairo_status_t
-_cairo_gstate_arc_negative (cairo_gstate_t *gstate,
-			    double xc, double yc,
-			    double radius,
-			    double angle1, double angle2);
-
-cairo_private cairo_status_t
-_cairo_gstate_rel_move_to (cairo_gstate_t *gstate, double dx, double dy);
-
-cairo_private cairo_status_t
-_cairo_gstate_rel_line_to (cairo_gstate_t *gstate, double dx, double dy);
-
-cairo_private cairo_status_t
-_cairo_gstate_rel_curve_to (cairo_gstate_t *gstate,
-			    double dx1, double dy1,
-			    double dx2, double dy2,
-			    double dx3, double dy3);
-
-/* XXX: NYI
-cairo_private cairo_status_t
-_cairo_gstate_stroke_path (cairo_gstate_t *gstate);
-*/
+cairo_private void
+_cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y);
 
-cairo_private cairo_status_t
-_cairo_gstate_close_path (cairo_gstate_t *gstate);
+cairo_private void
+_cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y);
 
 cairo_private cairo_status_t
-_cairo_gstate_get_current_point (cairo_gstate_t *gstate, double *x, double *y);
+_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path);
 
 cairo_private cairo_status_t
-_cairo_gstate_interpret_path (cairo_gstate_t		*gstate,
-			      cairo_move_to_func_t	*move_to,
-			      cairo_line_to_func_t	*line_to,
-			      cairo_curve_to_func_t	*curve_to,
-			      cairo_close_path_func_t	*close_path,
-			      void			*closure);
+_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path);
 
 cairo_private cairo_status_t
 _cairo_gstate_get_clip_extents (cairo_gstate_t    *gstate,
 				cairo_rectangle_t *rectangle);
 
 cairo_private cairo_status_t
-_cairo_gstate_stroke (cairo_gstate_t *gstate);
-
-cairo_private cairo_status_t
-_cairo_gstate_fill (cairo_gstate_t *gstate);
-
-cairo_private cairo_status_t
 _cairo_gstate_copy_page (cairo_gstate_t *gstate);
 
 cairo_private cairo_status_t
 _cairo_gstate_show_page (cairo_gstate_t *gstate);
 
 cairo_private cairo_status_t
-_cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
+_cairo_gstate_stroke_extents (cairo_gstate_t	 *gstate,
+			      cairo_path_fixed_t *path,
                               double *x1, double *y1,
 			      double *x2, double *y2);
 
 cairo_private cairo_status_t
-_cairo_gstate_fill_extents (cairo_gstate_t *gstate,
+_cairo_gstate_fill_extents (cairo_gstate_t     *gstate,
+			    cairo_path_fixed_t *path,
                             double *x1, double *y1,
 			    double *x2, double *y2);
 
 cairo_private cairo_status_t
-_cairo_gstate_in_stroke (cairo_gstate_t	*gstate,
-			 double		x,
-			 double		y,
-			 cairo_bool_t	*inside_ret);
+_cairo_gstate_in_stroke (cairo_gstate_t	    *gstate,
+			 cairo_path_fixed_t *path,
+			 double		     x,
+			 double		     y,
+			 cairo_bool_t	    *inside_ret);
 
 cairo_private cairo_status_t
-_cairo_gstate_in_fill (cairo_gstate_t	*gstate,
-		       double		x,
-		       double		y,
-		       cairo_bool_t	*inside_ret);
+_cairo_gstate_in_fill (cairo_gstate_t	  *gstate,
+		       cairo_path_fixed_t *path,
+		       double		   x,
+		       double		   y,
+		       cairo_bool_t	  *inside_ret);
 
 cairo_private cairo_status_t
-_cairo_gstate_clip (cairo_gstate_t *gstate);
+_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path);
 
 cairo_private cairo_status_t
 _cairo_gstate_reset_clip (cairo_gstate_t *gstate);
@@ -1150,8 +1102,10 @@
 cairo_private cairo_status_t
 _cairo_gstate_show_surface (cairo_gstate_t	*gstate,
 			    cairo_surface_t	*surface,
-			    int			width,
-			    int			height);
+			    double		 x,
+			    double		 y,
+			    double		width,
+			    double		height);
 
 cairo_private cairo_status_t
 _cairo_gstate_select_font_face (cairo_gstate_t *gstate, 
@@ -1185,6 +1139,8 @@
 cairo_private cairo_status_t
 _cairo_gstate_text_to_glyphs (cairo_gstate_t *font,
 			      const char     *utf8, 
+			      double	      x,
+			      double	      y,
 			      cairo_glyph_t **glyphs, 
 			      int	     *num_glyphs);
 
@@ -1200,9 +1156,10 @@
 			   int num_glyphs);
 
 cairo_private cairo_status_t
-_cairo_gstate_glyph_path (cairo_gstate_t *gstate, 
-			  cairo_glyph_t *glyphs, 
-			  int num_glyphs);
+_cairo_gstate_glyph_path (cairo_gstate_t     *gstate, 
+			  cairo_glyph_t	     *glyphs, 
+			  int		      num_glyphs,
+			  cairo_path_fixed_t *path);
 
 
 /* cairo_color.c */
@@ -1331,40 +1288,45 @@
 cairo_private void
 _cairo_path_fixed_fini (cairo_path_fixed_t *path);
 
-cairo_private cairo_status_t
-_cairo_path_fixed_move_to (cairo_path_fixed_t	  *path,
-			   cairo_point_t	  *point);
+cairo_status_t
+_cairo_path_fixed_move_to (cairo_path_fixed_t  *path,
+			   cairo_fixed_t	x,
+			   cairo_fixed_t	y);
 
-cairo_private cairo_status_t
+cairo_status_t
 _cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
-			       cairo_slope_t	  *slope);
+			       cairo_fixed_t	   dx,
+			       cairo_fixed_t	   dy);
 
-cairo_private cairo_status_t
-_cairo_path_fixed_line_to (cairo_path_fixed_t	  *path,
-			   cairo_point_t	  *point);
+cairo_status_t
+_cairo_path_fixed_line_to (cairo_path_fixed_t *path,
+			   cairo_fixed_t	x,
+			   cairo_fixed_t	y);
 
-cairo_private cairo_status_t
+cairo_status_t
 _cairo_path_fixed_rel_line_to (cairo_path_fixed_t *path,
-			       cairo_slope_t	  *slope);
+			       cairo_fixed_t	   dx,
+			       cairo_fixed_t	   dy);
 
-cairo_private cairo_status_t
-_cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
-			    cairo_point_t      *p0,
-			    cairo_point_t      *p1,
-			    cairo_point_t      *p2);
+cairo_status_t
+_cairo_path_fixed_curve_to (cairo_path_fixed_t	*path,
+			    cairo_fixed_t x0, cairo_fixed_t y0,
+			    cairo_fixed_t x1, cairo_fixed_t y1,
+			    cairo_fixed_t x2, cairo_fixed_t y2);
 
-cairo_private cairo_status_t
+cairo_status_t
 _cairo_path_fixed_rel_curve_to (cairo_path_fixed_t *path,
-				cairo_slope_t      *s0,
-				cairo_slope_t      *s1,
-				cairo_slope_t      *s2);
+				cairo_fixed_t dx0, cairo_fixed_t dy0,
+				cairo_fixed_t dx1, cairo_fixed_t dy1,
+				cairo_fixed_t dx2, cairo_fixed_t dy2);
 
 cairo_private cairo_status_t
 _cairo_path_fixed_close_path (cairo_path_fixed_t *path);
 
-cairo_private cairo_status_t
-_cairo_path_fixed_get_current_point (cairo_path_fixed_t	*path,
-				     cairo_point_t	*point);
+cairo_status_t
+_cairo_path_fixed_get_current_point (cairo_path_fixed_t *path,
+				     cairo_fixed_t	*x,
+				     cairo_fixed_t	*y);
 
 typedef cairo_status_t
 (cairo_path_fixed_move_to_func_t) (void		 *closure,
@@ -1805,6 +1767,9 @@
 
 /* Avoid unnecessary PLT entries.  */
 
+slim_hidden_proto(cairo_get_current_point)
+slim_hidden_proto(cairo_fill_preserve)
+slim_hidden_proto(cairo_clip_preserve)
 slim_hidden_proto(cairo_close_path)
 slim_hidden_proto(cairo_matrix_copy)
 slim_hidden_proto(cairo_matrix_invert)
@@ -1818,10 +1783,12 @@
 slim_hidden_proto(cairo_matrix_transform_distance)
 slim_hidden_proto(cairo_matrix_transform_point)
 slim_hidden_proto(cairo_move_to)
+slim_hidden_proto(cairo_new_path)
 slim_hidden_proto(cairo_rel_line_to)
 slim_hidden_proto(cairo_restore)
 slim_hidden_proto(cairo_save)
 slim_hidden_proto(cairo_set_target_surface)
+slim_hidden_proto(cairo_stroke_preserve)
 slim_hidden_proto(cairo_surface_destroy)
 slim_hidden_proto(cairo_surface_get_matrix)
 slim_hidden_proto(cairo_surface_set_matrix)




More information about the cairo-commit mailing list