[cairo-commit] 12 commits - doc/public src/cairo-analysis-surface.c src/cairo.c src/cairo-gstate.c src/cairo.h src/cairoint.h src/cairo-path-bounds.c src/cairo-path.c src/cairo-path-fixed.c test/get-path-extents.c

Carl Worth cworth at kemper.freedesktop.org
Mon Jan 21 15:26:04 PST 2008


 doc/public/cairo-sections.txt    |    1 
 doc/public/tmpl/cairo-paths.sgml |   10 +++
 src/cairo-analysis-surface.c     |    2 
 src/cairo-gstate.c               |   11 +++
 src/cairo-path-bounds.c          |   66 ++++++++++------------
 src/cairo-path-fixed.c           |   99 ++++++++++++++++++++++++++++++++++
 src/cairo-path.c                 |  112 ++++++++++-----------------------------
 src/cairo.c                      |   70 +++++++++++++++++++++---
 src/cairo.h                      |    5 +
 src/cairoint.h                   |   19 ++++++
 test/get-path-extents.c          |   83 ++++++++++++++++++++++------
 11 files changed, 333 insertions(+), 145 deletions(-)

New commits:
commit 326342962daa694d876c03194e8a6c1b13f9a8d2
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jan 21 15:20:07 2008 -0800

    Rename trailing_move_to_point to move_to_point
    
    And prefer TRUE and FALSE literals over 1 and 0.

diff --git a/src/cairo-path-bounds.c b/src/cairo-path-bounds.c
index b945c40..581244b 100644
--- a/src/cairo-path-bounds.c
+++ b/src/cairo-path-bounds.c
@@ -37,9 +37,9 @@
 #include "cairoint.h"
 
 typedef struct cairo_path_bounder {
-    cairo_point_t trailing_move_to_point;
-    int has_trailing_move_to;
-    int has_point;
+    cairo_point_t move_to_point;
+    cairo_bool_t has_move_to_point;
+    cairo_bool_t has_point;
 
     cairo_fixed_t min_x;
     cairo_fixed_t min_y;
@@ -68,13 +68,15 @@ _cairo_path_bounder_close_path (void *closure);
 static void
 _cairo_path_bounder_init (cairo_path_bounder_t *bounder)
 {
-    bounder->has_point = 0;
+    bounder->has_move_to_point = FALSE;
+    bounder->has_point = FALSE;
 }
 
 static void
 _cairo_path_bounder_fini (cairo_path_bounder_t *bounder)
 {
-    bounder->has_point = 0;
+    bounder->has_move_to_point = FALSE;
+    bounder->has_point = FALSE;
 }
 
 static void
@@ -98,7 +100,7 @@ _cairo_path_bounder_add_point (cairo_path_bounder_t *bounder, cairo_point_t *poi
 	bounder->max_x = point->x;
 	bounder->max_y = point->y;
 
-	bounder->has_point = 1;
+	bounder->has_point = TRUE;
     }
 }
 
@@ -107,8 +109,8 @@ _cairo_path_bounder_move_to (void *closure, cairo_point_t *point)
 {
     cairo_path_bounder_t *bounder = closure;
 
-    bounder->trailing_move_to_point = *point;
-    bounder->has_trailing_move_to = 1;
+    bounder->move_to_point = *point;
+    bounder->has_move_to_point = TRUE;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -118,10 +120,10 @@ _cairo_path_bounder_line_to (void *closure, cairo_point_t *point)
 {
     cairo_path_bounder_t *bounder = closure;
 
-    if (bounder->has_trailing_move_to) {
+    if (bounder->has_move_to_point) {
 	_cairo_path_bounder_add_point (bounder,
-				       &bounder->trailing_move_to_point);
-	bounder->has_trailing_move_to = 0;
+				       &bounder->move_to_point);
+	bounder->has_move_to_point = FALSE;
     }
 
     _cairo_path_bounder_add_point (bounder, point);
commit c480eedbb58dd03dd4b9b87b3985758ffbce7113
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jan 21 14:56:21 2008 -0800

    Test and document extents of degenerate "dots"
    
    It's a common idiom to stroke degenerate sub-paths made with
    cairo_move_to(x,y);cairo_rel_line_to(0,0) to draw dots. Test
    that we get the desired extents from cairo_fill_extents,
    cairo_stroke_extents, and cairo_path_extents for these cases.
    
    Also document that the cairo_path_extents result is equivalent
    to the limit of stroking with CAIRO_LINE_CAP_ROUND, (so that
    these "dot" points are included), as the line width
    approaches 0.0 .

diff --git a/src/cairo.c b/src/cairo.c
index f5b92a7..3011125 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -1887,9 +1887,9 @@ slim_hidden_def(cairo_close_path);
  * the corresponding drawing operations.
  *
  * The result of cairo_path_extents() is defined as equivalent to the
- * limit of cairo_stroke_extents() as the line width approaches 0.0,
- * (but never reaching the empty-rectangle returned by
- * cairo_stroke_extents() for a line width of 0.0).
+ * limit of cairo_stroke_extents() with CAIRO_LINE_CAP_ROUND as the
+ * line width approaches 0.0, (but never reaching the empty-rectangle
+ * returned by cairo_stroke_extents() for a line width of 0.0).
  *
  * Specifically, this means that zero-area sub-paths such as
  * cairo_move_to();cairo_line_to() segments, (even degenerate cases
diff --git a/test/get-path-extents.c b/test/get-path-extents.c
index 0be57a7..5e82c1e 100644
--- a/test/get-path-extents.c
+++ b/test/get-path-extents.c
@@ -166,6 +166,34 @@ draw (cairo_t *cr, int width, int height)
     cairo_new_path (cr2);
     cairo_restore (cr2);
 
+    /* Test that with CAIRO_LINE_CAP_ROUND, we get "dots" from
+     * cairo_move_to; cairo_rel_line_to(0,0) */
+    cairo_save (cr2);
+
+    cairo_set_line_cap (cr2, CAIRO_LINE_CAP_ROUND);
+    cairo_set_line_width (cr2, 20);
+
+    cairo_move_to (cr2, 200, 400);
+    cairo_rel_line_to (cr2, 0, 0);
+    phase = "Single 'dot'";
+    if (!check_extents (phase, cr2, FILL, EQUALS, 0, 0, 0, 0) ||
+	!check_extents (phase, cr2, STROKE, EQUALS, 190, 390, 20, 20) ||
+	!check_extents (phase, cr2, PATH, EQUALS, 200, 400, 0, 0))
+	ret = CAIRO_TEST_FAILURE;
+
+    /* Add another dot without starting a new path */
+    cairo_move_to (cr2, 100, 500);
+    cairo_rel_line_to (cr2, 0, 0);
+    phase = "Multiple 'dots'";
+    if (!check_extents (phase, cr2, FILL, EQUALS, 0, 0, 0, 0) ||
+	!check_extents (phase, cr2, STROKE, EQUALS, 90, 390, 120, 120) ||
+	!check_extents (phase, cr2, PATH, EQUALS, 100, 400, 100, 100))
+	ret = CAIRO_TEST_FAILURE;
+
+    cairo_new_path (cr2);
+
+    cairo_restore (cr2);
+
     /* http://bugs.freedesktop.org/show_bug.cgi?id=7965 */
     phase = "A vertical, open path";
     cairo_save (cr2);
commit 55e0dddf0408046ea0ded419ebe45099a4eb563e
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jan 21 14:45:06 2008 -0800

    Add cairo_path_extents testing to several cases missing it
    
    With these degenerate shapes, cairo_path_extents still returns
    a zero-area rectangle, but with a non-zero offset.

diff --git a/test/get-path-extents.c b/test/get-path-extents.c
index 5520b39..0be57a7 100644
--- a/test/get-path-extents.c
+++ b/test/get-path-extents.c
@@ -134,7 +134,8 @@ draw (cairo_t *cr, int width, int height)
     cairo_rel_line_to (cr2, 0., 0.);
     phase = "Degenerate line";
     if (!check_extents (phase, cr2, FILL, EQUALS, 0, 0, 0, 0) ||
-        !check_extents (phase, cr2, STROKE, EQUALS, 0, 0, 0, 0))
+        !check_extents (phase, cr2, STROKE, EQUALS, 0, 0, 0, 0) ||
+	!check_extents (phase, cr2, PATH, EQUALS, 200, 400, 0, 0))
 	ret = CAIRO_TEST_FAILURE;
 
     cairo_new_path (cr2);
@@ -142,21 +143,24 @@ draw (cairo_t *cr, int width, int height)
     cairo_rel_curve_to (cr2, 0., 0., 0., 0., 0., 0.);
     phase = "Degenerate curve";
     if (!check_extents (phase, cr2, FILL, EQUALS, 0, 0, 0, 0) ||
-        !check_extents (phase, cr2, STROKE, EQUALS, 0, 0, 0, 0))
+        !check_extents (phase, cr2, STROKE, EQUALS, 0, 0, 0, 0) ||
+	!check_extents (phase, cr2, PATH, EQUALS, 200, 400, 0, 0))
 	ret = CAIRO_TEST_FAILURE;
 
     cairo_new_path (cr2);
     cairo_arc (cr2, 200, 400, 0., 0, 2 * M_PI);
     phase = "Degenerate arc (R=0)";
     if (!check_extents (phase, cr2, FILL, EQUALS, 0, 0, 0, 0) ||
-        !check_extents (phase, cr2, STROKE, EQUALS, 0, 0, 0, 0))
+        !check_extents (phase, cr2, STROKE, EQUALS, 0, 0, 0, 0) ||
+	!check_extents (phase, cr2, PATH, EQUALS, 200, 400, 0, 0))
 	ret = CAIRO_TEST_FAILURE;
 
     cairo_new_path (cr2);
     cairo_arc (cr2, 200, 400, 10., 0, 0);
     phase = "Degenerate arc (Θ=0)";
     if (!check_extents (phase, cr2, FILL, EQUALS, 0, 0, 0, 0) ||
-        !check_extents (phase, cr2, STROKE, EQUALS, 0, 0, 0, 0))
+        !check_extents (phase, cr2, STROKE, EQUALS, 0, 0, 0, 0) ||
+	!check_extents (phase, cr2, PATH, EQUALS, 200, 400, 0, 0))
 	ret = CAIRO_TEST_FAILURE;
 
     cairo_new_path (cr2);
commit 63df3a82a3a4a035edf89152995a324449616059
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jan 21 13:47:05 2008 -0800

    Fix cairo_path_extents to ignore lone cairo_move_to points.
    
    Update the documentation as well.

diff --git a/src/cairo-path-bounds.c b/src/cairo-path-bounds.c
index f996977..b945c40 100644
--- a/src/cairo-path-bounds.c
+++ b/src/cairo-path-bounds.c
@@ -37,6 +37,8 @@
 #include "cairoint.h"
 
 typedef struct cairo_path_bounder {
+    cairo_point_t trailing_move_to_point;
+    int has_trailing_move_to;
     int has_point;
 
     cairo_fixed_t min_x;
@@ -105,7 +107,8 @@ _cairo_path_bounder_move_to (void *closure, cairo_point_t *point)
 {
     cairo_path_bounder_t *bounder = closure;
 
-    _cairo_path_bounder_add_point (bounder, point);
+    bounder->trailing_move_to_point = *point;
+    bounder->has_trailing_move_to = 1;
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -115,6 +118,12 @@ _cairo_path_bounder_line_to (void *closure, cairo_point_t *point)
 {
     cairo_path_bounder_t *bounder = closure;
 
+    if (bounder->has_trailing_move_to) {
+	_cairo_path_bounder_add_point (bounder,
+				       &bounder->trailing_move_to_point);
+	bounder->has_trailing_move_to = 0;
+    }
+
     _cairo_path_bounder_add_point (bounder, point);
 
     return CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo.c b/src/cairo.c
index 9e71c81..f5b92a7 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -1877,16 +1877,26 @@ slim_hidden_def(cairo_close_path);
  * @x2: right of the resulting extents
  * @y2: bottom of the resulting extents
  *
- * Computes a bounding box in user coordinates covering the points
- * on the current path. If the current path is empty,
- * returns an empty rectangle (0,0, 0,0).  Stroke parameters,
- * surface dimensions and clipping are not taken into account.
+ * Computes a bounding box in user-space coordinates covering the
+ * points on the current path. If the current path is empty, returns
+ * an empty rectangle ((0,0), (0,0)).  Stroke parameters, surface
+ * dimensions and clipping are not taken into account.
  *
  * Contrast with cairo_fill_extents() and cairo_stroke_extents() which
- * return the extents of the area that would be "inked" by drawing
- * operations.  The results of cairo_path_extent() and
- * cairo_fill_extents() are identical unless there are one or more
- * sub-paths with zero area.
+ * return the extents of only the area that would be "inked" by
+ * the corresponding drawing operations.
+ *
+ * The result of cairo_path_extents() is defined as equivalent to the
+ * limit of cairo_stroke_extents() as the line width approaches 0.0,
+ * (but never reaching the empty-rectangle returned by
+ * cairo_stroke_extents() for a line width of 0.0).
+ *
+ * Specifically, this means that zero-area sub-paths such as
+ * cairo_move_to();cairo_line_to() segments, (even degenerate cases
+ * where the coordinates to both calls are identical), will be
+ * considered as contributing to the extents. However, a lone
+ * cairo_move_to() will not contribute to the results of
+ * cairo_path_extents().
  *
  * Since: 1.6
  **/
@@ -2273,8 +2283,8 @@ cairo_in_fill (cairo_t *cr, double x, double y)
  * would be affected, (the "inked" area), by a cairo_stroke()
  * operation operation given the current path and stroke
  * parameters. If the current path is empty, returns an empty
- * rectangle (0,0, 0,0). Surface dimensions and clipping are not taken
- * into account.
+ * rectangle ((0,0), (0,0)). Surface dimensions and clipping are not
+ * taken into account.
  *
  * Note that if the line width is set to exactly zero, then
  * cairo_stroke_extents will return an empty rectangle. Contrast with
@@ -2312,12 +2322,12 @@ cairo_stroke_extents (cairo_t *cr,
  * Computes a bounding box in user coordinates covering the area that
  * would be affected, (the "inked" area), by a cairo_fill() operation
  * given the current path and fill parameters. If the current path is
- * empty, returns an empty rectangle (0,0, 0,0). Surface dimensions
- * and clipping are not taken into account.
+ * empty, returns an empty rectangle ((0,0), (0,0)). Surface
+ * dimensions and clipping are not taken into account.
  *
- * Contrast with cairo_path_extents(), which is similar, but will
- * return non-zero extents for a path with no inked area, (such as a
- * simple line segment).
+ * Contrast with cairo_path_extents(), which is similar, but returns
+ * non-zero extents for some paths no inked area, (such as a simple
+ * line segment).
  *
  * See cairo_fill(), cairo_set_fill_rule() and cairo_fill_preserve().
  **/
commit c15cab8b6855540436e457465c4766812c6def55
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jan 21 13:34:53 2008 -0800

    Correct near-pangram to be an actual pangram
    
    This wasn't affecting the test quality at all, but it did annoy
    me to see this mistake.

diff --git a/test/get-path-extents.c b/test/get-path-extents.c
index 0ba761c..5520b39 100644
--- a/test/get-path-extents.c
+++ b/test/get-path-extents.c
@@ -106,7 +106,7 @@ draw (cairo_t *cr, int width, int height)
     cairo_surface_t *surface;
     cairo_t         *cr2;
     const char      *phase;
-    const char	     string[] = "The quick brown fox jumped over the lazy dog.";
+    const char	     string[] = "The quick brown fox jumps over the lazy dog.";
     cairo_text_extents_t extents, scaled_font_extents;
     cairo_test_status_t ret = CAIRO_TEST_SUCCESS;
 
commit ed695bdb9b1e4500f796c7f07a7cc2f3832b2a39
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jan 21 13:33:46 2008 -0800

    Define repeated string literal once

diff --git a/test/get-path-extents.c b/test/get-path-extents.c
index a06e301..0ba761c 100644
--- a/test/get-path-extents.c
+++ b/test/get-path-extents.c
@@ -106,6 +106,7 @@ draw (cairo_t *cr, int width, int height)
     cairo_surface_t *surface;
     cairo_t         *cr2;
     const char      *phase;
+    const char	     string[] = "The quick brown fox jumped over the lazy dog.";
     cairo_text_extents_t extents, scaled_font_extents;
     cairo_test_status_t ret = CAIRO_TEST_SUCCESS;
 
@@ -223,15 +224,16 @@ draw (cairo_t *cr, int width, int height)
 
     phase = "Text";
     cairo_save (cr2);
+    cairo_set_tolerance (cr2, 100.0);
     cairo_select_font_face (cr2, "Bitstream Vera Sans",
 			    CAIRO_FONT_SLANT_NORMAL,
 			    CAIRO_FONT_WEIGHT_NORMAL);
     cairo_set_font_size (cr2, 12);
-    cairo_text_extents (cr2, "The quick brown fox jumped over the lazy dog.", &extents);
+    cairo_text_extents (cr2, string, &extents);
     /* double check that the two methods of measuring the text agree... */
     cairo_scaled_font_text_extents (cairo_get_scaled_font (cr2),
-	                     "The quick brown fox jumped over the lazy dog.",
-			     &scaled_font_extents);
+				    string,
+				    &scaled_font_extents);
     if (memcmp (&extents, &scaled_font_extents, sizeof (extents))) {
 	cairo_test_log ("Error: cairo_text_extents() does not match cairo_scaled_font_text_extents() - font extents (%f, %f) x (%f, %f) should be (%f, %f) x (%f, %f)\n",
 		        scaled_font_extents.x_bearing,
@@ -246,7 +248,7 @@ draw (cairo_t *cr, int width, int height)
     }
 
     cairo_move_to (cr2, -extents.x_bearing, -extents.y_bearing);
-    cairo_text_path (cr2, "The quick brown fox jumped over the lazy dog.");
+    cairo_text_path (cr2, string);
     cairo_set_line_width (cr2, 2.0);
     if (!check_extents (phase, cr2, FILL, EQUALS, 0, 0, extents.width, extents.height) ||
 	!check_extents (phase, cr2, STROKE, EQUALS, -1, -1, extents.width+2, extents.height+2) ||
commit 80df194b77a4caac1d58132341f034596e500bda
Author: Carl Worth <cworth at cworth.org>
Date:   Mon Jan 21 12:14:49 2008 -0800

    Clarify documentation of cairo_{fill,stroke,path}_extents
    
    Mostly just adding more cross-references between the documentation
    of these three similar functions.

diff --git a/src/cairo.c b/src/cairo.c
index 42411ce..9e71c81 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -1880,9 +1880,13 @@ slim_hidden_def(cairo_close_path);
  * Computes a bounding box in user coordinates covering the points
  * on the current path. If the current path is empty,
  * returns an empty rectangle (0,0, 0,0).  Stroke parameters,
- * surface dimensions and clipping are not taken into account. This
- * will be the same as the value returned by cairo_fill_extents()
- * unless the area enclosed by the path is empty.
+ * surface dimensions and clipping are not taken into account.
+ *
+ * Contrast with cairo_fill_extents() and cairo_stroke_extents() which
+ * return the extents of the area that would be "inked" by drawing
+ * operations.  The results of cairo_path_extent() and
+ * cairo_fill_extents() are identical unless there are one or more
+ * sub-paths with zero area.
  *
  * Since: 1.6
  **/
@@ -2266,10 +2270,16 @@ cairo_in_fill (cairo_t *cr, double x, double y)
  * @y2: bottom of the resulting extents
  *
  * Computes a bounding box in user coordinates covering the area that
- * would be affected by a cairo_stroke() operation operation given the
- * current path and stroke parameters. If the current path is empty,
- * returns an empty rectangle (0,0, 0,0). Surface dimensions and
- * clipping are not taken into account.
+ * would be affected, (the "inked" area), by a cairo_stroke()
+ * operation operation given the current path and stroke
+ * parameters. If the current path is empty, returns an empty
+ * rectangle (0,0, 0,0). Surface dimensions and clipping are not taken
+ * into account.
+ *
+ * Note that if the line width is set to exactly zero, then
+ * cairo_stroke_extents will return an empty rectangle. Contrast with
+ * cairo_path_extents() which can be used to compute the non-empty
+ * bounds as the line width approaches zero.
  *
  * See cairo_stroke(), cairo_set_line_width(), cairo_set_line_join(),
  * cairo_set_line_cap(), cairo_set_dash(), and
@@ -2300,10 +2310,14 @@ cairo_stroke_extents (cairo_t *cr,
  * @y2: bottom of the resulting extents
  *
  * Computes a bounding box in user coordinates covering the area that
- * would be affected by a cairo_fill() operation given the current path
- * and fill parameters. If the current path is empty, returns an empty
- * rectangle (0,0, 0,0). Surface dimensions and clipping are not taken
- * into account.
+ * would be affected, (the "inked" area), by a cairo_fill() operation
+ * given the current path and fill parameters. If the current path is
+ * empty, returns an empty rectangle (0,0, 0,0). Surface dimensions
+ * and clipping are not taken into account.
+ *
+ * Contrast with cairo_path_extents(), which is similar, but will
+ * return non-zero extents for a path with no inked area, (such as a
+ * simple line segment).
  *
  * See cairo_fill(), cairo_set_fill_rule() and cairo_fill_preserve().
  **/
commit eba04b7fbcc7fdbf075ad1372208908634459178
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Sun Jan 20 03:22:12 2008 +0000

    [path] use new interpret_flat infrastructure for path_populate
    
    refactor to reduce duplication of flattening code.

diff --git a/src/cairo-path.c b/src/cairo-path.c
index 605ba05..96ecbb3 100644
--- a/src/cairo-path.c
+++ b/src/cairo-path.c
@@ -237,40 +237,6 @@ _cpp_curve_to (void		*closure,
 }
 
 static cairo_status_t
-_cpp_curve_to_flatten (void		*closure,
-		       cairo_point_t	*p1,
-		       cairo_point_t	*p2,
-		       cairo_point_t	*p3)
-{
-    cpp_t *cpp = closure;
-    cairo_status_t status;
-    cairo_spline_t spline;
-    int i;
-
-    cairo_point_t *p0 = &cpp->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,
-				      _cairo_gstate_get_tolerance (cpp->gstate));
-    if (status)
-      goto out;
-
-    for (i=1; i < spline.num_points; i++)
-	_cpp_line_to (cpp, &spline.points[i]);
-
-    cpp->current_point = *p3;
-
-    status = CAIRO_STATUS_SUCCESS;
-
- out:
-    _cairo_spline_fini (&spline);
-    return status;
-}
-
-static cairo_status_t
 _cpp_close_path (void *closure)
 {
     cpp_t *cpp = closure;
@@ -298,15 +264,25 @@ _cairo_path_populate (cairo_path_t		*path,
     cpp.current_point.x = 0;
     cpp.current_point.y = 0;
 
-    status = _cairo_path_fixed_interpret (path_fixed,
+    if (flatten) {
+	double tolerance = _cairo_gstate_get_tolerance (gstate);
+	status = _cairo_path_fixed_interpret_flat (path_fixed,
+						   CAIRO_DIRECTION_FORWARD,
+						   _cpp_move_to,
+						   _cpp_line_to,
+						   _cpp_close_path,
+						   &cpp,
+						   tolerance);
+    } else {
+	status = _cairo_path_fixed_interpret (path_fixed,
 				          CAIRO_DIRECTION_FORWARD,
 					  _cpp_move_to,
 					  _cpp_line_to,
-					  flatten ?
-					  _cpp_curve_to_flatten :
 					  _cpp_curve_to,
 					  _cpp_close_path,
 					  &cpp);
+    }
+
     if (status)
 	return status;
 
commit 3270ae6a65105787942da8309fa874ee65bc79fe
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Sun Jan 20 03:21:41 2008 +0000

    [path] Use new interpret_flat infrastructure for path_count.
    
    Refactor to reduce duplication of path flattening code.

diff --git a/src/cairo-path-bounds.c b/src/cairo-path-bounds.c
index 9652934..f996977 100644
--- a/src/cairo-path-bounds.c
+++ b/src/cairo-path-bounds.c
@@ -61,12 +61,6 @@ static cairo_status_t
 _cairo_path_bounder_line_to (void *closure, cairo_point_t *point);
 
 static cairo_status_t
-_cairo_path_bounder_curve_to (void *closure,
-			      cairo_point_t *b,
-			      cairo_point_t *c,
-			      cairo_point_t *d);
-
-static cairo_status_t
 _cairo_path_bounder_close_path (void *closure);
 
 static void
diff --git a/src/cairo-path.c b/src/cairo-path.c
index b9086c4..605ba05 100644
--- a/src/cairo-path.c
+++ b/src/cairo-path.c
@@ -44,7 +44,6 @@ static const cairo_path_t _cairo_path_nil = { CAIRO_STATUS_NO_MEMORY, NULL, 0 };
 /* Closure for path interpretation. */
 typedef struct cairo_path_count {
     int count;
-    double tolerance;
     cairo_point_t current_point;
 } cpc_t;
 
@@ -88,39 +87,6 @@ _cpc_curve_to (void		*closure,
 }
 
 static cairo_status_t
-_cpc_curve_to_flatten (void		*closure,
-		       cairo_point_t	*p1,
-		       cairo_point_t	*p2,
-		       cairo_point_t	*p3)
-{
-    cpc_t *cpc = closure;
-    cairo_status_t status;
-    cairo_spline_t spline;
-    int i;
-
-    cairo_point_t *p0 = &cpc->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, cpc->tolerance);
-    if (status)
-      goto out;
-
-    for (i=1; i < spline.num_points; i++)
-	_cpc_line_to (cpc, &spline.points[i]);
-
-    cpc->current_point = *p3;
-
-    status = CAIRO_STATUS_SUCCESS;
-
- out:
-    _cairo_spline_fini (&spline);
-    return status;
-}
-
-static cairo_status_t
 _cpc_close_path (void *closure)
 {
     cpc_t *cpc = closure;
@@ -140,19 +106,27 @@ _cairo_path_count (cairo_path_t		*path,
     cpc_t cpc;
 
     cpc.count = 0;
-    cpc.tolerance = tolerance;
     cpc.current_point.x = 0;
     cpc.current_point.y = 0;
 
-    status = _cairo_path_fixed_interpret (path_fixed,
-					  CAIRO_DIRECTION_FORWARD,
-					  _cpc_move_to,
-					  _cpc_line_to,
-					  flatten ?
-					  _cpc_curve_to_flatten :
-					  _cpc_curve_to,
-					  _cpc_close_path,
-					  &cpc);
+    if (flatten) {
+	status = _cairo_path_fixed_interpret_flat (path_fixed,
+						   CAIRO_DIRECTION_FORWARD,
+						   _cpc_move_to,
+						   _cpc_line_to,
+						   _cpc_close_path,
+						   &cpc,
+						   tolerance);
+    } else {
+	status = _cairo_path_fixed_interpret (path_fixed,
+					      CAIRO_DIRECTION_FORWARD,
+					      _cpc_move_to,
+					      _cpc_line_to,
+					      _cpc_curve_to,
+					      _cpc_close_path,
+					      &cpc);
+    }
+
     if (status)
 	return -1;
 
commit 4177208be63caa3128eaf07428f3d4617fcd18e0
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Fri Nov 16 22:43:43 2007 +0000

    [cairo] Add cairo_path_extents()
    
    This new function gets the extents of the current path, whether
    or not they would be inked by a 'fill'. It differs from
    cairo_fill_extents() when the area enclosed by the path is 0.
    
    Includes documentation and updated test.

diff --git a/doc/public/cairo-sections.txt b/doc/public/cairo-sections.txt
index 4484271..88e9c8a 100644
--- a/doc/public/cairo-sections.txt
+++ b/doc/public/cairo-sections.txt
@@ -326,6 +326,7 @@ cairo_text_path
 cairo_rel_curve_to
 cairo_rel_line_to
 cairo_rel_move_to
+cairo_path_extents
 </SECTION>
 
 <SECTION>
diff --git a/doc/public/tmpl/cairo-paths.sgml b/doc/public/tmpl/cairo-paths.sgml
index 3be71a4..3d68342 100644
--- a/doc/public/tmpl/cairo-paths.sgml
+++ b/doc/public/tmpl/cairo-paths.sgml
@@ -236,3 +236,13 @@ Creating paths and manipulating path data
 @dy: 
 
 
+<!-- ##### FUNCTION cairo_path_extents ##### -->
+<para>
+
+</para>
+
+ at cr: 
+ at x1: 
+ at y1: 
+ at x2: 
+ at y2: 
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 3577d84..a00a52c 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -818,6 +818,17 @@ _cairo_gstate_stroke_to_path (cairo_gstate_t *gstate)
 }
 */
 
+void
+_cairo_gstate_path_extents (cairo_gstate_t     *gstate,
+			    cairo_path_fixed_t *path,
+			    double *x1, double *y1,
+			    double *x2, double *y2)
+{
+    _cairo_path_fixed_bounds (path, x1, y1, x2, y2, gstate->tolerance);
+    
+    _cairo_gstate_backend_to_user_rectangle (gstate, x1, y1, x2, y2, NULL);
+}
+
 static cairo_status_t
 _cairo_gstate_copy_transformed_pattern (cairo_gstate_t  *gstate,
 					cairo_pattern_t *pattern,
diff --git a/src/cairo.c b/src/cairo.c
index 4a7aec1..42411ce 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -1870,6 +1870,36 @@ cairo_close_path (cairo_t *cr)
 slim_hidden_def(cairo_close_path);
 
 /**
+ * cairo_path_extents:
+ * @cr: a cairo context
+ * @x1: left of the resulting extents
+ * @y1: top of the resulting extents
+ * @x2: right of the resulting extents
+ * @y2: bottom of the resulting extents
+ *
+ * Computes a bounding box in user coordinates covering the points
+ * on the current path. If the current path is empty,
+ * returns an empty rectangle (0,0, 0,0).  Stroke parameters,
+ * surface dimensions and clipping are not taken into account. This
+ * will be the same as the value returned by cairo_fill_extents()
+ * unless the area enclosed by the path is empty.
+ *
+ * Since: 1.6
+ **/
+void
+cairo_path_extents (cairo_t *cr,
+		    double *x1, double *y1, double *x2, double *y2)
+{
+    if (cr->status)
+	return;
+
+    _cairo_gstate_path_extents (cr->gstate,
+				cr->path,
+				x1, y1, x2, y2);
+}
+slim_hidden_def (cairo_path_extents);
+
+/**
  * cairo_paint:
  * @cr: a cairo context
  *
diff --git a/src/cairo.h b/src/cairo.h
index 4c58c14..157b6e1 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -584,6 +584,11 @@ cairo_stroke_to_path (cairo_t *cr);
 cairo_public void
 cairo_close_path (cairo_t *cr);
 
+cairo_public void
+cairo_path_extents (cairo_t *cr,
+		    double *x1, double *y1,
+		    double *x2, double *y2);
+
 /* Painting functions */
 cairo_public void
 cairo_paint (cairo_t *cr);
diff --git a/src/cairoint.h b/src/cairoint.h
index ea3c2b6..7c1d2d5 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1005,6 +1005,12 @@ _cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate,
                                          double *x2, double *y2,
                                          cairo_bool_t *is_tight);
 
+cairo_private void
+_cairo_gstate_path_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_paint (cairo_gstate_t *gstate);
 
@@ -2220,6 +2226,7 @@ slim_hidden_proto (cairo_matrix_translate);
 slim_hidden_proto (cairo_move_to);
 slim_hidden_proto (cairo_new_path);
 slim_hidden_proto (cairo_paint);
+slim_hidden_proto (cairo_path_extents);
 slim_hidden_proto (cairo_pattern_create_for_surface);
 slim_hidden_proto (cairo_pattern_create_rgb);
 slim_hidden_proto (cairo_pattern_create_rgba);
diff --git a/test/get-path-extents.c b/test/get-path-extents.c
index b20b13f..a06e301 100644
--- a/test/get-path-extents.c
+++ b/test/get-path-extents.c
@@ -36,7 +36,7 @@ cairo_test_t test = {
     draw
 };
 
-enum ExtentsType { FILL, STROKE };
+enum ExtentsType { FILL, STROKE, PATH };
 
 enum Relation { EQUALS, APPROX_EQUALS, CONTAINS };
 
@@ -59,6 +59,10 @@ check_extents (const char *message, cairo_t *cr, enum ExtentsType type,
         type_string = "stroke";
         cairo_stroke_extents (cr, &ext_x1, &ext_y1, &ext_x2, &ext_y2);
         break;
+    case PATH:
+        type_string = "path";
+        cairo_path_extents (cr, &ext_x1, &ext_y1, &ext_x2, &ext_y2);
+        break;
     }
 
     /* let empty rects match */
@@ -118,7 +122,8 @@ draw (cairo_t *cr, int width, int height)
 
     phase = "No path";
     if (!check_extents (phase, cr2, FILL, EQUALS, 0, 0, 0, 0) ||
-        !check_extents (phase, cr2, STROKE, EQUALS, 0, 0, 0, 0))
+        !check_extents (phase, cr2, STROKE, EQUALS, 0, 0, 0, 0) ||
+        !check_extents (phase, cr2, PATH, EQUALS, 0, 0, 0, 0))
 	ret = CAIRO_TEST_FAILURE;
 
     cairo_save (cr2);
@@ -164,7 +169,8 @@ draw (cairo_t *cr, int width, int height)
     cairo_move_to (cr2, 0, 180);
     cairo_line_to (cr2, 750, 180);
     if (!check_extents (phase, cr2, FILL, EQUALS, 0, 0, 0, 0) ||
-        !check_extents (phase, cr2, STROKE, EQUALS, -5, 175, 760, 10))
+        !check_extents (phase, cr2, STROKE, EQUALS, -5, 175, 760, 10) ||
+        !check_extents (phase, cr2, PATH, EQUALS, 0, 180, 755, 0))
 	ret = CAIRO_TEST_FAILURE;
     cairo_new_path (cr2);
     cairo_restore (cr2);
@@ -173,7 +179,8 @@ draw (cairo_t *cr, int width, int height)
     cairo_save (cr2);
     cairo_rectangle (cr2, 10, 10, 80, 80);
     if (!check_extents (phase, cr2, FILL, EQUALS, 10, 10, 80, 80) ||
-        !check_extents (phase, cr2, STROKE, EQUALS, 5, 5, 90, 90))
+        !check_extents (phase, cr2, STROKE, EQUALS, 5, 5, 90, 90) ||
+        !check_extents (phase, cr2, PATH, EQUALS, 10, 10, 80, 80))
 	ret = CAIRO_TEST_FAILURE;
     cairo_new_path (cr2);
     cairo_restore (cr2);
@@ -183,7 +190,8 @@ draw (cairo_t *cr, int width, int height)
     cairo_rectangle (cr2, 10, 10, 10, 10);
     cairo_rectangle (cr2, 20, 20, 10, 10);
     if (!check_extents (phase, cr2, FILL, EQUALS, 10, 10, 20, 20) ||
-        !check_extents (phase, cr2, STROKE, EQUALS, 5, 5, 30, 30))
+        !check_extents (phase, cr2, STROKE, EQUALS, 5, 5, 30, 30) ||
+        !check_extents (phase, cr2, PATH, EQUALS, 10, 10, 20, 20))
 	ret = CAIRO_TEST_FAILURE;
     cairo_new_path (cr2);
     cairo_restore (cr2);
@@ -197,7 +205,8 @@ draw (cairo_t *cr, int width, int height)
     /* miter joins protrude 5*(1+sqrt(2)) above the top-left corner and to
        the right of the bottom-right corner */
     if (!check_extents (phase, cr2, FILL, EQUALS, 10, 10, 80, 80) ||
-        !check_extents (phase, cr2, STROKE, CONTAINS, 0, 5, 95, 95))
+        !check_extents (phase, cr2, STROKE, CONTAINS, 0, 5, 95, 95) ||
+        !check_extents (phase, cr2, PATH, CONTAINS, 10, 10, 80, 80))
 	ret = CAIRO_TEST_FAILURE;
     cairo_new_path (cr2);
     cairo_restore (cr2);
@@ -240,7 +249,8 @@ draw (cairo_t *cr, int width, int height)
     cairo_text_path (cr2, "The quick brown fox jumped over the lazy dog.");
     cairo_set_line_width (cr2, 2.0);
     if (!check_extents (phase, cr2, FILL, EQUALS, 0, 0, extents.width, extents.height) ||
-	!check_extents (phase, cr2, STROKE, EQUALS, -1, -1, extents.width+2, extents.height+2))
+	!check_extents (phase, cr2, STROKE, EQUALS, -1, -1, extents.width+2, extents.height+2) ||
+	!check_extents (phase, cr2, PATH, EQUALS, 0, 0, extents.width, extents.height))
 	ret = CAIRO_TEST_FAILURE;
     cairo_new_path (cr2);
     cairo_restore (cr2);
@@ -250,7 +260,8 @@ draw (cairo_t *cr, int width, int height)
     cairo_scale (cr2, 2, 2);
     cairo_rectangle (cr2, 5, 5, 40, 40);
     if (!check_extents (phase, cr2, FILL, EQUALS, 5, 5, 40, 40) ||
-        !check_extents (phase, cr2, STROKE, EQUALS, 0, 0, 50, 50))
+        !check_extents (phase, cr2, STROKE, EQUALS, 0, 0, 50, 50) ||
+        !check_extents (phase, cr2, PATH, EQUALS, 5, 5, 40, 40))
 	ret = CAIRO_TEST_FAILURE;
     cairo_new_path (cr2);
     cairo_restore (cr2);
@@ -262,7 +273,8 @@ draw (cairo_t *cr, int width, int height)
     cairo_rectangle (cr2, 5, 5, 40, 40);
     cairo_restore (cr2);
     if (!check_extents (phase, cr2, FILL, EQUALS, 10, 10, 80, 80) ||
-        !check_extents (phase, cr2, STROKE, EQUALS, 5, 5, 90, 90))
+        !check_extents (phase, cr2, STROKE, EQUALS, 5, 5, 90, 90) ||
+        !check_extents (phase, cr2, PATH, EQUALS, 10, 10, 80, 80))
 	ret = CAIRO_TEST_FAILURE;
     cairo_new_path (cr2);
     cairo_restore (cr2);
@@ -281,7 +293,8 @@ draw (cairo_t *cr, int width, int height)
        the largest axis-aligned square is a bit over 38 on either side of
        the axes. */
     if (!check_extents (phase, cr2, FILL, CONTAINS, -35, -35, 35, 35) ||
-        !check_extents (phase, cr2, STROKE, CONTAINS, -38, -38, 38, 38))
+        !check_extents (phase, cr2, STROKE, CONTAINS, -38, -38, 38, 38) ||
+        !check_extents (phase, cr2, PATH, CONTAINS, -35, -35, 35, 35))
 	ret = CAIRO_TEST_FAILURE;
     cairo_new_path (cr2);
     cairo_restore (cr2);
commit d923457c0f40c9b34ee75d4d47b9bd0c3edfe669
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Sat Jan 19 22:31:49 2008 +0000

    [path-fixed] make _cairo_path_fixed_bounds use _cairo_path_fixed_interpret_flat
    
    _cairo_path_fixed_bounds can use the new _interpret_flat mechanism; this
    results in tighter bounds; previously the bounds followed the control
    points of the beziers, whereas now they are the bounds of the curve.

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index 509b5f2..a223086 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -228,7 +228,7 @@ _cairo_analysis_surface_intersect_clip_path (void		*abstract_surface,
 	surface->current_clip.width  = surface->width;
 	surface->current_clip.height = surface->height;
     } else {
-	_cairo_path_fixed_bounds (path, &x1, &y1, &x2, &y2);
+	_cairo_path_fixed_bounds (path, &x1, &y1, &x2, &y2, tolerance);
 
 	extent.x = floor (x1);
 	extent.y = floor (y1);
diff --git a/src/cairo-path-bounds.c b/src/cairo-path-bounds.c
index 55a64e5..9652934 100644
--- a/src/cairo-path-bounds.c
+++ b/src/cairo-path-bounds.c
@@ -127,21 +127,6 @@ _cairo_path_bounder_line_to (void *closure, cairo_point_t *point)
 }
 
 static cairo_status_t
-_cairo_path_bounder_curve_to (void *closure,
-			      cairo_point_t *b,
-			      cairo_point_t *c,
-			      cairo_point_t *d)
-{
-    cairo_path_bounder_t *bounder = closure;
-
-    _cairo_path_bounder_add_point (bounder, b);
-    _cairo_path_bounder_add_point (bounder, c);
-    _cairo_path_bounder_add_point (bounder, d);
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
 _cairo_path_bounder_close_path (void *closure)
 {
     return CAIRO_STATUS_SUCCESS;
@@ -151,7 +136,8 @@ _cairo_path_bounder_close_path (void *closure)
 void
 _cairo_path_fixed_bounds (cairo_path_fixed_t *path,
 			  double *x1, double *y1,
-			  double *x2, double *y2)
+			  double *x2, double *y2,
+			  double tolerance)
 {
     cairo_status_t status;
 
@@ -159,21 +145,24 @@ _cairo_path_fixed_bounds (cairo_path_fixed_t *path,
 
     _cairo_path_bounder_init (&bounder);
 
-    status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD,
-					  _cairo_path_bounder_move_to,
-					  _cairo_path_bounder_line_to,
-					  _cairo_path_bounder_curve_to,
-					  _cairo_path_bounder_close_path,
-					  &bounder);
+    status = _cairo_path_fixed_interpret_flat (path, CAIRO_DIRECTION_FORWARD,
+					       _cairo_path_bounder_move_to,
+					       _cairo_path_bounder_line_to,
+					       _cairo_path_bounder_close_path,
+					       &bounder,
+					       tolerance);
     assert (status == CAIRO_STATUS_SUCCESS);
 
-    if (! bounder.has_point) {
-	*x1 = *y1 = *x2 = *y2 = 0.;
-    } else {
+    if (bounder.has_point) {
 	*x1 = _cairo_fixed_to_double (bounder.min_x);
 	*y1 = _cairo_fixed_to_double (bounder.min_y);
 	*x2 = _cairo_fixed_to_double (bounder.max_x);
 	*y2 = _cairo_fixed_to_double (bounder.max_y);
+    } else {
+	*x1 = 0.0;
+	*y1 = 0.0;
+	*x2 = 0.0;
+	*y2 = 0.0;
     }
 
     _cairo_path_bounder_fini (&bounder);
diff --git a/src/cairoint.h b/src/cairoint.h
index fe23259..ea3c2b6 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1359,7 +1359,8 @@ _cairo_path_fixed_interpret_flat (cairo_path_fixed_t	  *path,
 cairo_private void
 _cairo_path_fixed_bounds (cairo_path_fixed_t *path,
 			  double *x1, double *y1,
-			  double *x2, double *y2);
+			  double *x2, double *y2,
+			  double tolerance);
 
 cairo_private void
 _cairo_path_fixed_device_transform (cairo_path_fixed_t	*path,
commit 1471b3f00acddecdfc2617a62ab0e584f319dc1c
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Sat Jan 19 22:31:10 2008 +0000

    [path-fixed] add _cairo_path_fixed_interpret_flat
    
    _cairo_path_fixed_interpret_flat flattens the path as it
    interprets it, meaning that a curve_to callback is not
    required.

diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index e18ecc3..91b8c0e 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -622,3 +622,102 @@ _cairo_path_fixed_is_equal (cairo_path_fixed_t *path,
     }
     return TRUE;
 }
+
+/* Closure for path flattening */
+typedef struct cairo_path_flattener {
+    double tolerance;
+    cairo_point_t current_point;
+    cairo_path_fixed_move_to_func_t	*move_to;
+    cairo_path_fixed_line_to_func_t	*line_to;
+    cairo_path_fixed_close_path_func_t	*close_path;
+    void *closure;
+} cpf_t;
+
+static cairo_status_t
+_cpf_move_to (void *closure, cairo_point_t *point)
+{
+    cpf_t *cpf = closure;
+
+    cpf->current_point = *point;
+
+    return cpf->move_to (cpf->closure, point);
+}
+
+static cairo_status_t
+_cpf_line_to (void *closure, cairo_point_t *point)
+{
+    cpf_t *cpf = closure;
+
+    cpf->current_point = *point;
+
+    return cpf->line_to (cpf->closure, point);
+}
+
+static cairo_status_t
+_cpf_curve_to (void		*closure,
+	       cairo_point_t	*p1,
+	       cairo_point_t	*p2,
+	       cairo_point_t	*p3)
+{
+    cpf_t *cpf = closure;
+    cairo_status_t status;
+    cairo_spline_t spline;
+    int i;
+
+    cairo_point_t *p0 = &cpf->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, cpf->tolerance);
+    if (status)
+      goto out;
+
+    for (i=1; i < spline.num_points; i++) {
+	status = cpf->line_to (cpf->closure, &spline.points[i]);
+	if (status)
+	    goto out;
+    }
+
+    cpf->current_point = *p3;
+
+    status = CAIRO_STATUS_SUCCESS;
+
+ out:
+    _cairo_spline_fini (&spline);
+    return status;
+}
+
+static cairo_status_t
+_cpf_close_path (void *closure)
+{
+    cpf_t *cpf = closure;
+
+    return cpf->close_path (cpf->closure);
+}
+
+
+cairo_status_t
+_cairo_path_fixed_interpret_flat (cairo_path_fixed_t			*path,
+				  cairo_direction_t			dir,
+				  cairo_path_fixed_move_to_func_t	*move_to,
+				  cairo_path_fixed_line_to_func_t	*line_to,
+				  cairo_path_fixed_close_path_func_t	*close_path,
+				  void					*closure,
+				  double				tolerance)
+{
+    cpf_t flattener;
+
+    flattener.tolerance = tolerance;
+    flattener.move_to = move_to;
+    flattener.line_to = line_to;
+    flattener.close_path = close_path;
+    flattener.closure = closure;
+    return _cairo_path_fixed_interpret (path, dir,
+					_cpf_move_to,
+					_cpf_line_to,
+					_cpf_curve_to,
+					_cpf_close_path,
+					&flattener);
+}
diff --git a/src/cairoint.h b/src/cairoint.h
index d8a31b5..fe23259 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1347,6 +1347,15 @@ _cairo_path_fixed_interpret (cairo_path_fixed_t		  *path,
 		       cairo_path_fixed_close_path_func_t *close_path,
 		       void				  *closure);
 
+cairo_private cairo_status_t
+_cairo_path_fixed_interpret_flat (cairo_path_fixed_t	  *path,
+		       cairo_direction_t		   dir,
+		       cairo_path_fixed_move_to_func_t	  *move_to,
+		       cairo_path_fixed_line_to_func_t	  *line_to,
+		       cairo_path_fixed_close_path_func_t *close_path,
+		       void				  *closure,
+		       double				  tolerance);
+
 cairo_private void
 _cairo_path_fixed_bounds (cairo_path_fixed_t *path,
 			  double *x1, double *y1,


More information about the cairo-commit mailing list