[cairo-commit] 2 commits - src/cairo-clip.c src/cairo-clip-private.h src/cairo-image-surface.c src/cairo-surface-fallback.c src/cairo-xcb-surface-render.c src/drm test/clip-twice-rectangle.c test/clip-twice-rectangle.ref.png test/Makefile.am test/Makefile.sources

Chris Wilson ickle at kemper.freedesktop.org
Fri Feb 12 04:24:42 PST 2010


 src/cairo-clip-private.h          |    6 ++
 src/cairo-clip.c                  |   84 ++++++++++++++++++++++++++++++++++++++
 src/cairo-image-surface.c         |   74 ++++++++-------------------------
 src/cairo-surface-fallback.c      |   71 +-------------------------------
 src/cairo-xcb-surface-render.c    |   78 +++++++++--------------------------
 src/drm/cairo-drm-i915-surface.c  |   47 +--------------------
 src/drm/cairo-drm-i965-surface.c  |   47 +--------------------
 test/Makefile.am                  |    1 
 test/Makefile.sources             |    1 
 test/clip-twice-rectangle.c       |   70 +++++++++++++++++++++++++++++++
 test/clip-twice-rectangle.ref.png |binary
 11 files changed, 209 insertions(+), 270 deletions(-)

New commits:
commit 5390df961f6dff8e25e5aac21062026a81710d88
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Feb 12 12:20:35 2010 +0000

    clip: Restrict composite extents to clip extents
    
    Fixes test/clip-rectangle-twice.

diff --git a/src/cairo-clip-private.h b/src/cairo-clip-private.h
index a3303fe..b9a39ae 100644
--- a/src/cairo-clip-private.h
+++ b/src/cairo-clip-private.h
@@ -128,6 +128,12 @@ _cairo_clip_get_boxes (cairo_clip_t *clip,
 		       cairo_box_t **boxes,
 		       int *count);
 
+cairo_private cairo_status_t
+_cairo_clip_to_boxes (cairo_clip_t **clip,
+		      cairo_composite_rectangles_t *extents,
+		      cairo_box_t **boxes,
+		      int *num_boxes);
+
 cairo_private cairo_bool_t
 _cairo_clip_contains_rectangle (cairo_clip_t *clip,
 				const cairo_composite_rectangles_t *extents);
diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index abcf659..fdb9470 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -1335,6 +1335,90 @@ _cairo_clip_get_boxes (cairo_clip_t *clip,
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_bool_t
+box_is_aligned (const cairo_box_t *box)
+{
+    return
+	_cairo_fixed_is_integer (box->p1.x) &&
+	_cairo_fixed_is_integer (box->p1.y) &&
+	_cairo_fixed_is_integer (box->p2.x) &&
+	_cairo_fixed_is_integer (box->p2.y);
+}
+
+static void
+intersect_with_boxes (cairo_composite_rectangles_t *extents,
+		      cairo_box_t *boxes,
+		      int num_boxes)
+{
+    cairo_rectangle_int_t rect;
+    cairo_box_t box;
+    cairo_bool_t is_empty;
+
+    box.p1.x = box.p1.y = INT_MIN;
+    box.p2.x = box.p2.y = INT_MAX;
+    while (num_boxes--) {
+	if (boxes->p1.x < box.p1.x)
+	    box.p1.x = boxes->p1.x;
+	if (boxes->p1.y < box.p1.y)
+	    box.p1.y = boxes->p1.y;
+
+	if (boxes->p2.x > box.p2.x)
+	    box.p2.x = boxes->p2.x;
+	if (boxes->p2.y > box.p2.y)
+	    box.p2.y = boxes->p2.y;
+    }
+
+    _cairo_box_round_to_rectangle (&box, &rect);
+    is_empty = _cairo_rectangle_intersect (&extents->bounded, &rect);
+    is_empty = _cairo_rectangle_intersect (&extents->unbounded, &rect);
+}
+
+cairo_status_t
+_cairo_clip_to_boxes (cairo_clip_t **clip,
+		      cairo_composite_rectangles_t *extents,
+		      cairo_box_t **boxes,
+		      int *num_boxes)
+{
+    cairo_status_t status;
+    const cairo_rectangle_int_t *rect;
+
+    rect = extents->is_bounded ? &extents->bounded : &extents->unbounded;
+
+    if (*clip == NULL)
+	goto EXTENTS;
+
+    status = _cairo_clip_rectangle (*clip, rect);
+    if (unlikely (status))
+	return status;
+
+    status = _cairo_clip_get_boxes (*clip, boxes, num_boxes);
+    switch ((int) status) {
+    case CAIRO_STATUS_SUCCESS:
+	intersect_with_boxes (extents, *boxes, *num_boxes);
+	if (rect->width == 0 || rect->height == 0 ||
+	    extents->is_bounded ||
+	    (*num_boxes == 1 && box_is_aligned (*boxes)))
+	{
+	    *clip = NULL;
+	}
+	goto DONE;
+
+    case CAIRO_INT_STATUS_UNSUPPORTED:
+	goto EXTENTS;
+
+    default:
+	return status;
+    }
+
+  EXTENTS:
+    status = CAIRO_STATUS_SUCCESS;
+    _cairo_box_from_rectangle (&(*boxes)[0], rect);
+    *num_boxes = 1;
+  DONE:
+    return status;
+}
+
+
 static cairo_rectangle_list_t *
 _cairo_rectangle_list_create_in_error (cairo_status_t status)
 {
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index d4bff51..76f50f7 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -2017,7 +2017,7 @@ _clip_and_composite (cairo_image_surface_t	*dst,
 		     const cairo_pattern_t	*src,
 		     image_draw_func_t		 draw_func,
 		     void			*draw_closure,
-		     const cairo_composite_rectangles_t*extents,
+		     cairo_composite_rectangles_t*extents,
 		     cairo_clip_t		*clip)
 {
     cairo_status_t status;
@@ -2025,6 +2025,9 @@ _clip_and_composite (cairo_image_surface_t	*dst,
     cairo_bool_t need_clip_surface = FALSE;
 
     if (clip != NULL) {
+	cairo_rectangle_int_t rect;
+	cairo_bool_t is_empty;
+
 	status = _cairo_clip_get_region (clip, &clip_region);
 	if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
 	    return CAIRO_STATUS_SUCCESS;
@@ -2032,6 +2035,15 @@ _clip_and_composite (cairo_image_surface_t	*dst,
 	assert (! _cairo_status_is_error (status));
 	need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
 
+	cairo_region_get_extents (clip_region, &rect);
+	is_empty = ! _cairo_rectangle_intersect (&extents->unbounded, &rect);
+	if (unlikely (is_empty))
+	    return CAIRO_STATUS_SUCCESS;
+
+	is_empty = ! _cairo_rectangle_intersect (&extents->bounded, &rect);
+	if (unlikely (is_empty && extents->is_bounded))
+	    return CAIRO_STATUS_SUCCESS;
+
 	if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
 	    clip_region = NULL;
     }
@@ -2781,7 +2793,7 @@ _clip_and_composite_boxes (cairo_image_surface_t *dst,
 			   const cairo_pattern_t *src,
 			   cairo_boxes_t *boxes,
 			   cairo_antialias_t antialias,
-			   const cairo_composite_rectangles_t *extents,
+			   cairo_composite_rectangles_t *extents,
 			   cairo_clip_t *clip)
 {
     cairo_traps_t traps;
@@ -2886,7 +2898,7 @@ _clip_and_composite_trapezoids (cairo_image_surface_t *dst,
 				const cairo_pattern_t *src,
 				cairo_traps_t *traps,
 				cairo_antialias_t antialias,
-				const cairo_composite_rectangles_t *extents,
+				cairo_composite_rectangles_t *extents,
 				cairo_clip_t *clip)
 {
     composite_traps_info_t info;
@@ -2942,56 +2954,6 @@ _clip_and_composite_trapezoids (cairo_image_surface_t *dst,
 				extents, clip);
 }
 
-static cairo_bool_t
-box_is_aligned (const cairo_box_t *box)
-{
-    return
-	_cairo_fixed_is_integer (box->p1.x) &&
-	_cairo_fixed_is_integer (box->p1.y) &&
-	_cairo_fixed_is_integer (box->p2.x) &&
-	_cairo_fixed_is_integer (box->p2.y);
-}
-
-static inline cairo_status_t
-_clip_to_boxes (cairo_clip_t **clip,
-		const cairo_composite_rectangles_t *extents,
-		cairo_box_t **boxes,
-		int *num_boxes)
-{
-    cairo_status_t status;
-    const cairo_rectangle_int_t *rect;
-
-    rect = extents->is_bounded ? &extents->bounded : &extents->unbounded;
-
-    if (*clip == NULL)
-	goto EXTENTS;
-
-    status = _cairo_clip_rectangle (*clip, rect);
-    if (unlikely (status))
-	return status;
-
-    status = _cairo_clip_get_boxes (*clip, boxes, num_boxes);
-    switch ((int) status) {
-    case CAIRO_STATUS_SUCCESS:
-	if (extents->is_bounded || (*num_boxes == 1 && box_is_aligned (*boxes)))
-	    *clip = NULL;
-	goto DONE;
-
-    case CAIRO_INT_STATUS_UNSUPPORTED:
-	goto EXTENTS;
-
-    default:
-	return status;
-    }
-
-  EXTENTS:
-    status = CAIRO_STATUS_SUCCESS;
-    _cairo_box_from_rectangle (&(*boxes)[0], rect);
-    *num_boxes = 1;
-  DONE:
-    return status;
-}
-
 static cairo_clip_path_t *
 _clip_get_single_path (cairo_clip_t *clip)
 {
@@ -3044,7 +3006,7 @@ _cairo_image_surface_paint (void			*abstract_surface,
 	have_clip = TRUE;
     }
 
-    status = _clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
+    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
     if (unlikely (status)) {
 	if (have_clip)
 	    _cairo_clip_fini (&local_clip);
@@ -3396,7 +3358,7 @@ _cairo_image_surface_stroke (void			*abstract_surface,
 	have_clip = TRUE;
     }
 
-    status = _clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
+    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
     if (unlikely (status)) {
 	if (have_clip)
 	    _cairo_clip_fini (&local_clip);
@@ -3497,7 +3459,7 @@ _cairo_image_surface_fill (void				*abstract_surface,
 	have_clip = TRUE;
     }
 
-    status = _clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
+    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
     if (unlikely (status)) {
 	if (have_clip)
 	    _cairo_clip_fini (&local_clip);
diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 9047787..232e15e 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -139,9 +139,6 @@ _create_composite_mask_pattern (cairo_surface_pattern_t       *mask_pattern,
 	assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
 
 	clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
-
-	if (clip_region && cairo_region_num_rectangles (clip_region) == 1)
-	    clip_region = NULL;
     }
 
     /* We need to use solid here, because to use CAIRO_OPERATOR_SOURCE with
@@ -337,10 +334,6 @@ _clip_and_composite_source (cairo_clip_t                  *clip,
 	assert (! _cairo_status_is_error (status));
 	if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
 	    return CAIRO_STATUS_SUCCESS;
-
-	/* a solitary clip rectangle is already accommodated by extents */
-	if (clip_region && cairo_region_num_rectangles (clip_region) == 1)
-	    clip_region = NULL;
     }
 
 
@@ -456,10 +449,6 @@ _clip_and_composite (cairo_clip_t                  *clip,
 						      dst, extents);
 	    }
 	} else {
-	    /* a solitary clip rectangle is already accommodated by extents */
-	    if (clip_region && cairo_region_num_rectangles (clip_region) == 1)
-		clip_region = NULL;
-
 	    status = draw_func (draw_closure, op,
 				src, dst,
 				0, 0,
@@ -506,10 +495,6 @@ _composite_trap_region (cairo_clip_t            *clip,
 	mask = &mask_pattern.base;
     }
 
-    /* reduce a solitary clipping region to the extents */
-    if (cairo_region_num_rectangles (trap_region) == 1)
-	trap_region = NULL;
-
     status = _cairo_surface_composite (op, src, mask, dst,
 				       extents->x, extents->y,
 				       mask_x, mask_y,
@@ -892,56 +877,6 @@ _composite_spans_draw_func (void                          *closure,
 					     clip_region);
 }
 
-static cairo_bool_t
-box_is_aligned (const cairo_box_t *box)
-{
-    return
-	_cairo_fixed_is_integer (box->p1.x) &&
-	_cairo_fixed_is_integer (box->p1.y) &&
-	_cairo_fixed_is_integer (box->p2.x) &&
-	_cairo_fixed_is_integer (box->p2.y);
-}
-
-static inline cairo_status_t
-_clip_to_boxes (cairo_clip_t **clip,
-		const cairo_composite_rectangles_t *extents,
-		cairo_box_t **boxes,
-		int *num_boxes)
-{
-    cairo_status_t status;
-    const cairo_rectangle_int_t *rect;
-
-    rect = extents->is_bounded ? &extents->bounded : &extents->unbounded;
-
-    if (*clip == NULL)
-	goto EXTENTS;
-
-    status = _cairo_clip_rectangle (*clip, rect);
-    if (unlikely (status))
-	return status;
-
-    status = _cairo_clip_get_boxes (*clip, boxes, num_boxes);
-    switch ((int) status) {
-    case CAIRO_STATUS_SUCCESS:
-	if (extents->is_bounded || (*num_boxes == 1 && box_is_aligned (*boxes)))
-	    *clip = NULL;
-	goto DONE;
-
-    case CAIRO_INT_STATUS_UNSUPPORTED:
-	goto EXTENTS;
-
-    default:
-	return status;
-    }
-
-  EXTENTS:
-    status = CAIRO_STATUS_SUCCESS;
-    _cairo_box_from_rectangle (&(*boxes)[0], rect);
-    *num_boxes = 1;
-  DONE:
-    return status;
-}
-
 cairo_status_t
 _cairo_surface_fallback_paint (cairo_surface_t		*surface,
 			       cairo_operator_t		 op,
@@ -971,7 +906,7 @@ _cairo_surface_fallback_paint (cairo_surface_t		*surface,
     if (_cairo_clip_contains_rectangle (clip, &extents))
 	clip = NULL;
 
-    status = _clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
+    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
     if (unlikely (status))
 	return status;
 
@@ -1110,7 +1045,7 @@ _cairo_surface_fallback_stroke (cairo_surface_t		*surface,
     if (_cairo_clip_contains_rectangle (clip, &extents))
 	clip = NULL;
 
-    status = _clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
+    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
     if (unlikely (status))
 	return status;
 
@@ -1215,7 +1150,7 @@ _cairo_surface_fallback_fill (cairo_surface_t		*surface,
     if (_cairo_clip_contains_rectangle (clip, &extents))
 	clip = NULL;
 
-    status = _clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
+    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
     if (unlikely (status))
 	return status;
 
diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index 5d19792..9122d64 100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -2344,7 +2344,7 @@ _clip_and_composite (cairo_xcb_surface_t	*dst,
 		     const cairo_pattern_t	*src,
 		     xcb_draw_func_t		 draw_func,
 		     void			*draw_closure,
-		     const cairo_composite_rectangles_t*extents,
+		     cairo_composite_rectangles_t*extents,
 		     cairo_clip_t		*clip)
 {
     cairo_status_t status;
@@ -2352,6 +2352,9 @@ _clip_and_composite (cairo_xcb_surface_t	*dst,
     cairo_bool_t need_clip_surface = FALSE;
 
     if (clip != NULL) {
+	cairo_rectangle_int_t rect;
+	cairo_bool_t is_empty;
+
 	status = _cairo_clip_get_region (clip, &clip_region);
 	if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
 	    return CAIRO_STATUS_SUCCESS;
@@ -2359,6 +2362,15 @@ _clip_and_composite (cairo_xcb_surface_t	*dst,
 	assert (! _cairo_status_is_error (status));
 	need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
 
+	cairo_region_get_extents (clip_region, &rect);
+	is_empty = ! _cairo_rectangle_intersect (&extents->unbounded, &rect);
+	if (unlikely (is_empty))
+	    return CAIRO_STATUS_SUCCESS;
+
+	is_empty = ! _cairo_rectangle_intersect (&extents->bounded, &rect);
+	if (unlikely (is_empty && extents->is_bounded))
+	    return CAIRO_STATUS_SUCCESS;
+
 	if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
 	    clip_region = NULL;
     }
@@ -2574,7 +2586,7 @@ _clip_and_composite_boxes (cairo_xcb_surface_t *dst,
 			   const cairo_pattern_t *src,
 			   cairo_boxes_t *boxes,
 			   cairo_antialias_t antialias,
-			   const cairo_composite_rectangles_t *extents,
+			   cairo_composite_rectangles_t *extents,
 			   cairo_clip_t *clip)
 {
     composite_traps_info_t info;
@@ -2855,56 +2867,6 @@ _composite_mask (void				*closure,
 
 /* high level rasteriser -> compositor */
 
-static cairo_bool_t
-box_is_aligned (const cairo_box_t *box)
-{
-    return
-	_cairo_fixed_is_integer (box->p1.x) &&
-	_cairo_fixed_is_integer (box->p1.y) &&
-	_cairo_fixed_is_integer (box->p2.x) &&
-	_cairo_fixed_is_integer (box->p2.y);
-}
-
-static inline cairo_status_t
-_clip_to_boxes (cairo_clip_t **clip,
-		const cairo_composite_rectangles_t *extents,
-		cairo_box_t **boxes,
-		int *num_boxes)
-{
-    cairo_status_t status;
-    const cairo_rectangle_int_t *rect;
-
-    rect = extents->is_bounded ? &extents->bounded: &extents->unbounded;
-
-    if (*clip == NULL)
-	goto EXTENTS;
-
-    status = _cairo_clip_rectangle (*clip, rect);
-    if (unlikely (status))
-	return status;
-
-    status = _cairo_clip_get_boxes (*clip, boxes, num_boxes);
-    switch ((int) status) {
-    case CAIRO_STATUS_SUCCESS:
-	if (extents->is_bounded || (*num_boxes == 1 && box_is_aligned (*boxes)))
-	    *clip = NULL;
-	goto DONE;
-
-    case  CAIRO_INT_STATUS_UNSUPPORTED:
-	goto EXTENTS;
-
-    default:
-	return status;
-    }
-
-  EXTENTS:
-    status = CAIRO_STATUS_SUCCESS;
-    _cairo_box_from_rectangle (&(*boxes)[0], rect);
-    *num_boxes = 1;
-  DONE:
-    return status;
-}
-
 static cairo_clip_path_t *
 _clip_get_single_path (cairo_clip_t *clip)
 {
@@ -2965,7 +2927,7 @@ _cairo_xcb_surface_render_paint (cairo_xcb_surface_t	*surface,
 	have_clip = TRUE;
     }
 
-    status = _clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
+    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
     if (unlikely (status)) {
 	if (have_clip)
 	    _cairo_clip_fini (&local_clip);
@@ -3231,7 +3193,7 @@ _cairo_xcb_surface_render_stroke_via_mask (cairo_xcb_surface_t		*dst,
 					   double			 tolerance,
 					   cairo_antialias_t		 antialias,
 					   cairo_clip_t			*clip,
-					   const cairo_composite_rectangles_t *extents)
+					   cairo_composite_rectangles_t *extents)
 {
     cairo_surface_t *image;
     cairo_status_t status;
@@ -3319,7 +3281,7 @@ _cairo_xcb_surface_render_stroke (cairo_xcb_surface_t	*surface,
 	have_clip = TRUE;
     }
 
-    status = _clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
+    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
     if (unlikely (status)) {
 	if (have_clip)
 	    _cairo_clip_fini (&local_clip);
@@ -3417,7 +3379,7 @@ _cairo_xcb_surface_render_fill_via_mask (cairo_xcb_surface_t	*dst,
 					 double			 tolerance,
 					 cairo_antialias_t	 antialias,
 					 cairo_clip_t		*clip,
-					 const cairo_composite_rectangles_t *extents)
+					 cairo_composite_rectangles_t *extents)
 {
     cairo_surface_t *image;
     cairo_status_t status;
@@ -3502,7 +3464,7 @@ _cairo_xcb_surface_render_fill (cairo_xcb_surface_t	*surface,
 	have_clip = TRUE;
     }
 
-    status = _clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
+    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
     if (unlikely (status)) {
 	if (have_clip)
 	    _cairo_clip_fini (&local_clip);
@@ -3562,7 +3524,7 @@ _cairo_xcb_surface_render_glyphs_via_mask (cairo_xcb_surface_t		*dst,
 					   cairo_glyph_t		*glyphs,
 					   int				 num_glyphs,
 					   cairo_clip_t			*clip,
-					   const cairo_composite_rectangles_t *extents)
+					   cairo_composite_rectangles_t *extents)
 {
     cairo_surface_t *image;
     cairo_content_t content;
diff --git a/src/drm/cairo-drm-i915-surface.c b/src/drm/cairo-drm-i915-surface.c
index d3c3940..3872832 100644
--- a/src/drm/cairo-drm-i915-surface.c
+++ b/src/drm/cairo-drm-i915-surface.c
@@ -910,47 +910,6 @@ _clip_and_composite_boxes (i915_surface_t *dst,
 					  extents, clip);
 }
 
-static cairo_bool_t
-box_is_aligned (const cairo_box_t *box)
-{
-    return
-	_cairo_fixed_is_integer (box->p1.x) &&
-	_cairo_fixed_is_integer (box->p1.y) &&
-	_cairo_fixed_is_integer (box->p2.x) &&
-	_cairo_fixed_is_integer (box->p2.y);
-}
-
-static inline cairo_status_t
-_clip_to_boxes (cairo_clip_t **clip,
-		const cairo_composite_rectangles_t *extents,
-		cairo_box_t **boxes,
-		int *num_boxes)
-{
-    cairo_status_t status;
-    const cairo_rectangle_int_t *rect;
-
-    rect = extents->is_bounded ? &extents->bounded: &extents->unbounded;
-
-    if (*clip == NULL)
-	goto EXTENTS;
-
-    status = _cairo_clip_rectangle (*clip, rect);
-    if (unlikely (status))
-	return status;
-
-    status = _cairo_clip_get_boxes (*clip, boxes, num_boxes);
-    if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
-	if (extents->is_bounded || (*num_boxes == 1 && box_is_aligned (*boxes)))
-	    *clip = NULL;
-	return status;
-    }
-
-  EXTENTS:
-    _cairo_box_from_rectangle (&(*boxes)[0], rect);
-    *num_boxes = 1;
-    return CAIRO_STATUS_SUCCESS;
-}
-
 static cairo_clip_path_t *
 _clip_get_solitary_path (cairo_clip_t *clip)
 {
@@ -1004,7 +963,7 @@ i915_surface_paint (void			*abstract_dst,
 	have_clip = TRUE;
     }
 
-    status = _clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
+    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
     if (unlikely (status)) {
 	if (have_clip)
 	    _cairo_clip_fini (&local_clip);
@@ -1211,7 +1170,7 @@ i915_surface_stroke (void			*abstract_dst,
 	have_clip = TRUE;
     }
 
-    status = _clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
+    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
     if (unlikely (status)) {
 	if (have_clip)
 	    _cairo_clip_fini (&local_clip);
@@ -1320,7 +1279,7 @@ i915_surface_fill (void			*abstract_dst,
 	have_clip = TRUE;
     }
 
-    status = _clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
+    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
     if (unlikely (status)) {
 	if (have_clip)
 	    _cairo_clip_fini (&local_clip);
diff --git a/src/drm/cairo-drm-i965-surface.c b/src/drm/cairo-drm-i965-surface.c
index e1bdf5f..10331dd 100644
--- a/src/drm/cairo-drm-i965-surface.c
+++ b/src/drm/cairo-drm-i965-surface.c
@@ -1071,47 +1071,6 @@ _clip_and_composite_boxes (i965_surface_t *dst,
 					  extents, clip);
 }
 
-static cairo_bool_t
-box_is_aligned (const cairo_box_t *box)
-{
-    return
-	_cairo_fixed_is_integer (box->p1.x) &&
-	_cairo_fixed_is_integer (box->p1.y) &&
-	_cairo_fixed_is_integer (box->p2.x) &&
-	_cairo_fixed_is_integer (box->p2.y);
-}
-
-static inline cairo_status_t
-_clip_to_boxes (cairo_clip_t **clip,
-		const cairo_composite_rectangles_t *extents,
-		cairo_box_t **boxes,
-		int *num_boxes)
-{
-    cairo_status_t status;
-    const cairo_rectangle_int_t *rect;
-
-    rect = extents->is_bounded ? &extents->bounded: &extents->unbounded;
-
-    if (*clip == NULL)
-	goto EXTENTS;
-
-    status = _cairo_clip_rectangle (*clip, rect);
-    if (unlikely (status))
-	return status;
-
-    status = _cairo_clip_get_boxes (*clip, boxes, num_boxes);
-    if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
-	if (extents->is_bounded || (*num_boxes == 1 && box_is_aligned (*boxes)))
-	    *clip = NULL;
-	return status;
-    }
-
-  EXTENTS:
-    _cairo_box_from_rectangle (&(*boxes)[0], rect);
-    *num_boxes = 1;
-    return CAIRO_STATUS_SUCCESS;
-}
-
 static cairo_int_status_t
 i965_surface_paint (void			*abstract_dst,
 		    cairo_operator_t		 op,
@@ -1145,7 +1104,7 @@ i965_surface_paint (void			*abstract_dst,
 	have_clip = TRUE;
     }
 
-    status = _clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
+    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
     if (unlikely (status)) {
 	if (have_clip)
 	    _cairo_clip_fini (&local_clip);
@@ -1333,7 +1292,7 @@ i965_surface_stroke (void			*abstract_dst,
 	have_clip = TRUE;
     }
 
-    status = _clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
+    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
     if (unlikely (status)) {
 	if (have_clip)
 	    _cairo_clip_fini (&local_clip);
@@ -1440,7 +1399,7 @@ i965_surface_fill (void			*abstract_dst,
 	have_clip = TRUE;
     }
 
-    status = _clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
+    status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
     if (unlikely (status)) {
 	if (have_clip)
 	    _cairo_clip_fini (&local_clip);
commit 51047483f462a905567b42275ae061ead4df0a07
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Feb 12 12:18:30 2010 +0000

    test: Add clip-twice-rectangle
    
    Jeff Muizeelar found another bug with clipping whereby the clip was
    been incorrectly discarded.

diff --git a/test/Makefile.am b/test/Makefile.am
index 10e322a..a2cfb7d 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -265,6 +265,7 @@ REFERENCE_IMAGES = \
 	clip-twice.test-paginated.rgb24.ref.png \
 	clip-twice.xlib.ref.png \
 	clip-twice.xlib.rgb24.ref.png \
+	clip-twice-rectangle.ref.png \
 	clipped-group.pdf.ref.png \
 	clipped-group.ps2.ref.png \
 	clipped-group.ps3.ref.png \
diff --git a/test/Makefile.sources b/test/Makefile.sources
index a8aa0e9..87c25a0 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -33,6 +33,7 @@ test_sources = \
 	clip-stroke-unbounded.c				\
 	clip-text.c					\
 	clip-twice.c					\
+	clip-twice-rectangle.c				\
 	clip-unbounded.c				\
 	clip-zero.c					\
 	clipped-group.c					\
diff --git a/test/clip-twice-rectangle.c b/test/clip-twice-rectangle.c
new file mode 100644
index 0000000..28f16ec
--- /dev/null
+++ b/test/clip-twice-rectangle.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright © 2010 Mozilla Corporation
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Author: Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test.h"
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    cairo_surface_t *mask;
+    cairo_t *cr2;
+
+    cairo_set_source_rgb (cr, 0, 1, 0);
+    cairo_paint (cr);
+
+    /* clip twice, note that the intersection is smaller then the extents */
+    cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+    cairo_rectangle (cr, 10, 10, 80, 80);
+    cairo_rectangle (cr, 20, 20, 60, 60);
+    cairo_clip (cr);
+
+    cairo_rectangle (cr, 0, 40, 40, 30);
+    cairo_clip (cr);
+
+    /* and exercise the bug found by Jeff Muizelaar */
+    mask = cairo_surface_create_similar (cairo_get_target (cr),
+					 CAIRO_CONTENT_ALPHA,
+					 width-20, height-20);
+    cr2 = cairo_create (mask);
+    cairo_surface_destroy (mask);
+
+    cairo_set_source_rgba (cr2, 1, 1, 1, 1);
+    cairo_paint (cr2);
+
+    cairo_set_source_rgb (cr, 1, 0, 0);
+    cairo_mask_surface (cr, cairo_get_target (cr2), 0, 0);
+    cairo_destroy (cr2);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+CAIRO_TEST (clip_twice_rectangle,
+	    "Tests clipping twice using rectangles",
+	    "clip", /* keywords */
+	    NULL, /* requirements */
+	    100, 100,
+	    NULL, draw)
diff --git a/test/clip-twice-rectangle.ref.png b/test/clip-twice-rectangle.ref.png
new file mode 100644
index 0000000..d0e65ea
Binary files /dev/null and b/test/clip-twice-rectangle.ref.png differ


More information about the cairo-commit mailing list