[cairo-commit] src/cairo-analysis-surface.c src/cairo-clip.c src/cairoint.h src/cairo-path-bounds.c src/cairo-rectangle.c src/cairo-surface-fallback.c

Chris Wilson ickle at kemper.freedesktop.org
Thu Dec 18 07:08:06 PST 2008


 src/cairo-analysis-surface.c |   32 +++++--------
 src/cairo-clip.c             |   14 ++---
 src/cairo-path-bounds.c      |  101 ++++++++++++++++++++++++++++++++++++++++---
 src/cairo-rectangle.c        |   10 ----
 src/cairo-surface-fallback.c |   10 ++--
 src/cairoint.h               |   19 +++++---
 6 files changed, 134 insertions(+), 52 deletions(-)

New commits:
commit 813cbf13ddbd3d4b708b3b362dd6c108966f44d5
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 18 14:52:03 2008 +0000

    [path] Separate the approx. bounds into 3 distinct functions
    
    Based on feedback from Jeff Muizelaar, there is a case for a very quick
    and dirty extents approximation based solely on the curve control points
    (for example when computing the clip intersect rectangle of a path) and
    by moving the stroke extension into a core function we can clean up the
    interface for all users, and centralise the logic of approximating the
    stroke extents.

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index b8f2ab4..b3eab41 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -290,12 +290,12 @@ _cairo_analysis_surface_intersect_clip_path (void		*abstract_surface,
 	surface->current_clip.width  = surface->width;
 	surface->current_clip.height = surface->height;
     } else {
-	cairo_box_t extents;
+	cairo_rectangle_int_t extents;
 	cairo_bool_t is_empty;
 
-	_cairo_path_fixed_approximate_extents (path, tolerance, &extents);
-	is_empty = _cairo_rectangle_intersect_box (&surface->current_clip,
-						   &extents);
+	_cairo_path_fixed_approximate_extents (path, &extents);
+	is_empty = _cairo_rectangle_intersect (&surface->current_clip,
+					       &extents);
     }
 
     return CAIRO_STATUS_SUCCESS;
@@ -478,19 +478,13 @@ _cairo_analysis_surface_stroke (void			*abstract_surface,
     is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
-	cairo_box_t mask_extents;
-	double dx, dy;
-
-	_cairo_path_fixed_approximate_extents (path, tolerance, &mask_extents);
-
-	_cairo_stroke_style_max_distance_from_path (style, ctm, &dx, &dy);
+	cairo_rectangle_int_t mask_extents;
 
-	mask_extents.p1.x -= _cairo_fixed_from_double (dx);
-	mask_extents.p2.x += _cairo_fixed_from_double (dx);
-	mask_extents.p1.y -= _cairo_fixed_from_double (dy);
-	mask_extents.p2.y += _cairo_fixed_from_double (dy);
+	_cairo_path_fixed_approximate_stroke_extents (path,
+						      style, ctm, tolerance,
+						      &mask_extents);
 
-	is_empty = _cairo_rectangle_intersect_box (&extents, &mask_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
     }
     if (stroke_extents)
 	*stroke_extents = extents;
@@ -542,11 +536,13 @@ _cairo_analysis_surface_fill (void			*abstract_surface,
     is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
 
     if (_cairo_operator_bounded_by_mask (op)) {
-	cairo_box_t mask_extents;
+	cairo_rectangle_int_t mask_extents;
 
-	_cairo_path_fixed_approximate_extents (path, tolerance, &mask_extents);
+	_cairo_path_fixed_approximate_fill_extents (path,
+						    tolerance,
+						    &mask_extents);
 
-	is_empty = _cairo_rectangle_intersect_box (&extents, &mask_extents);
+	is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
     }
     if (fill_extents)
 	*fill_extents = extents;
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index cd36924..f0f68a3 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -143,13 +143,11 @@ _cairo_clip_path_intersect_to_rectangle (cairo_clip_path_t       *clip_path,
 				         cairo_rectangle_int_t   *rectangle)
 {
     while (clip_path) {
-        cairo_box_t extents;
+        cairo_rectangle_int_t extents;
 
-	_cairo_path_fixed_approximate_extents (&clip_path->path,
-					       clip_path->tolerance,
-					       &extents);
+	_cairo_path_fixed_approximate_extents (&clip_path->path, &extents);
 
-        if (! _cairo_rectangle_intersect_box (rectangle, &extents))
+        if (! _cairo_rectangle_intersect (rectangle, &extents))
 	    return CAIRO_STATUS_SUCCESS;
 
         clip_path = clip_path->prev;
@@ -577,10 +575,10 @@ _cairo_clip_intersect_mask_using_spans (cairo_clip_t       *clip,
     /* We'll create a new surface the size of the intersection of the
      * old mask surface and the extents of the new clip path. */
     {
-	cairo_box_t extents;
+	cairo_rectangle_int_t extents;
 
-	_cairo_path_fixed_approximate_extents (path, tolerance, &extents);
-	if (! _cairo_rectangle_intersect_box (&surface_rect, &extents))
+	_cairo_path_fixed_approximate_extents (path, &extents);
+	if (! _cairo_rectangle_intersect (&surface_rect, &extents))
 	    goto SUCCESS;
 
 	if (clip->surface != NULL &&
diff --git a/src/cairo-path-bounds.c b/src/cairo-path-bounds.c
index 25737e8..ec5bb21 100644
--- a/src/cairo-path-bounds.c
+++ b/src/cairo-path-bounds.c
@@ -141,6 +141,27 @@ _cairo_path_bounder_curve_to (void *closure,
 }
 
 static cairo_status_t
+_cairo_path_bounder_curve_to_cp (void *closure,
+				 const cairo_point_t *b,
+				 const cairo_point_t *c,
+				 const cairo_point_t *d)
+{
+    cairo_path_bounder_t *bounder = closure;
+
+    if (bounder->has_move_to_point) {
+	_cairo_path_bounder_add_point (bounder,
+				       &bounder->move_to_point);
+	bounder->has_move_to_point = FALSE;
+    }
+
+    _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;
@@ -152,8 +173,69 @@ _cairo_path_bounder_close_path (void *closure)
  */
 void
 _cairo_path_fixed_approximate_extents (cairo_path_fixed_t *path,
-				       double tolerance,
-				       cairo_box_t *extents)
+				       cairo_rectangle_int_t *extents)
+{
+    cairo_path_bounder_t bounder;
+    cairo_status_t status;
+
+    _cairo_path_bounder_init (&bounder, 0.);
+
+    status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD,
+					  _cairo_path_bounder_move_to,
+					  _cairo_path_bounder_line_to,
+					  _cairo_path_bounder_curve_to_cp,
+					  _cairo_path_bounder_close_path,
+					  &bounder);
+    assert (status == CAIRO_STATUS_SUCCESS);
+
+    if (bounder.has_point) {
+	_cairo_box_round_to_rectangle (&bounder.extents, extents);
+    } else {
+	extents->x = extents->y = 0;
+	extents->width = extents->width = 0;
+    }
+
+    _cairo_path_bounder_fini (&bounder);
+}
+
+/* A slightly better approximation than above - we actually decompose the
+ * Bezier, but we continue to ignore winding.
+ */
+void
+_cairo_path_fixed_approximate_fill_extents (cairo_path_fixed_t *path,
+					    double tolerance,
+					    cairo_rectangle_int_t *extents)
+{
+    cairo_path_bounder_t bounder;
+    cairo_status_t status;
+
+    _cairo_path_bounder_init (&bounder, tolerance);
+
+    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);
+    assert (status == CAIRO_STATUS_SUCCESS);
+
+    if (bounder.has_point) {
+	_cairo_box_round_to_rectangle (&bounder.extents, extents);
+    } else {
+	extents->x = extents->y = 0;
+	extents->width = extents->width = 0;
+    }
+
+    _cairo_path_bounder_fini (&bounder);
+}
+
+/* Adjusts the fill extents (above) by the device-space pen.  */
+void
+_cairo_path_fixed_approximate_stroke_extents (cairo_path_fixed_t *path,
+					      cairo_stroke_style_t *style,
+					      const cairo_matrix_t *ctm,
+					      double tolerance,
+					      cairo_rectangle_int_t *extents)
 {
     cairo_path_bounder_t bounder;
     cairo_status_t status;
@@ -169,10 +251,19 @@ _cairo_path_fixed_approximate_extents (cairo_path_fixed_t *path,
     assert (status == CAIRO_STATUS_SUCCESS);
 
     if (bounder.has_point) {
-	*extents = bounder.extents;
+	double dx, dy;
+
+	_cairo_stroke_style_max_distance_from_path (style, ctm, &dx, &dy);
+
+	bounder.extents.p1.x -= _cairo_fixed_from_double (dx);
+	bounder.extents.p2.x += _cairo_fixed_from_double (dx);
+	bounder.extents.p1.y -= _cairo_fixed_from_double (dy);
+	bounder.extents.p2.y += _cairo_fixed_from_double (dy);
+
+	_cairo_box_round_to_rectangle (&bounder.extents, extents);
     } else {
-	extents->p1.x = extents->p1.y = 0;
-	extents->p2.x = extents->p2.y = 0;
+	extents->x = extents->y = 0;
+	extents->width = extents->width = 0;
     }
 
     _cairo_path_bounder_fini (&bounder);
diff --git a/src/cairo-rectangle.c b/src/cairo-rectangle.c
index 31a530e..b139624 100644
--- a/src/cairo-rectangle.c
+++ b/src/cairo-rectangle.c
@@ -126,16 +126,6 @@ _cairo_rectangle_intersect (cairo_rectangle_int_t *dst,
     }
 }
 
-cairo_bool_t
-_cairo_rectangle_intersect_box (cairo_rectangle_int_t *dst,
-				const cairo_box_t *src)
-{
-    cairo_rectangle_int_t rect;
-
-    _cairo_box_round_to_rectangle (src, &rect);
-    return _cairo_rectangle_intersect (dst, &rect);
-}
-
 #define P1x (line->p1.x)
 #define P1y (line->p1.y)
 #define P2x (line->p2.x)
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 0fd1dee..9cd59d4 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -955,12 +955,12 @@ _cairo_surface_fallback_fill (cairo_surface_t		*surface,
 	info.antialias = antialias;
 
 	if (_cairo_operator_bounded_by_mask (op)) {
-	    cairo_box_t path_extents;
+	    cairo_rectangle_int_t path_extents;
 
-	    _cairo_path_fixed_approximate_extents (path,
-						   tolerance,
-						   &path_extents);
-	    if (! _cairo_rectangle_intersect_box (&extents, &path_extents))
+	    _cairo_path_fixed_approximate_fill_extents (path,
+							tolerance,
+							&path_extents);
+	    if (! _cairo_rectangle_intersect (&extents, &path_extents))
 		return CAIRO_STATUS_SUCCESS;
 	}
 
diff --git a/src/cairoint.h b/src/cairoint.h
index 88945a3..e98bac0 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -259,10 +259,6 @@ _cairo_rectangle_intersect (cairo_rectangle_int_t *dst,
 			    const cairo_rectangle_int_t *src);
 
 cairo_private cairo_bool_t
-_cairo_rectangle_intersect_box (cairo_rectangle_int_t *dst,
-				const cairo_box_t *src);
-
-cairo_private cairo_bool_t
 _cairo_box_intersects_line_segment (cairo_box_t *box, cairo_line_t *line);
 
 cairo_private cairo_bool_t
@@ -1545,8 +1541,19 @@ _cairo_path_fixed_append (cairo_path_fixed_t		  *path,
 
 cairo_private void
 _cairo_path_fixed_approximate_extents (cairo_path_fixed_t	*path,
-				       double			 tolerance,
-				       cairo_box_t		*extents);
+				       cairo_rectangle_int_t	*extents);
+
+cairo_private void
+_cairo_path_fixed_approximate_fill_extents (cairo_path_fixed_t *path,
+					    double tolerance,
+					    cairo_rectangle_int_t *extents);
+
+cairo_private void
+_cairo_path_fixed_approximate_stroke_extents (cairo_path_fixed_t *path,
+					      cairo_stroke_style_t *style,
+					      const cairo_matrix_t *ctm,
+					      double tolerance,
+					      cairo_rectangle_int_t *extents);
 
 cairo_private void
 _cairo_path_fixed_bounds (cairo_path_fixed_t *path,


More information about the cairo-commit mailing list