[cairo-commit] 5 commits - src/cairo-clip.c src/cairo-gstate.c test/get-clip.c

Chris Wilson ickle at kemper.freedesktop.org
Sat Jul 17 03:32:21 PDT 2010


 src/cairo-clip.c   |   78 ++++++++++++++++++++++-------------------------------
 src/cairo-gstate.c |   14 ++++++++-
 test/get-clip.c    |   34 ++++++++++++++++++++---
 3 files changed, 76 insertions(+), 50 deletions(-)

New commits:
commit 108b1c7825116ed3f93aa57384bbd3290cdc9181
Author: Karl Tomlinson <karlt+ at karlt.net>
Date:   Sat Jul 17 13:08:53 2010 +1200

    clip: consider gstate target extents in _cairo_gstate_copy_clip_rectangle_list
    
    Fixes https://bugs.freedesktop.org/show_bug.cgi?id=29125
    
    To be consistent with _cairo_gstate_clip_extents, the context's clip
    should be intersected with the target surface extents (instead of only
    using them when there is no clip).
    
    Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 77d8214..d5a2fab 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -1495,7 +1495,7 @@ _cairo_rectangle_list_create_in_error (cairo_status_t status)
 cairo_rectangle_list_t *
 _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
 {
-#define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S));
+#define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S))
 
     cairo_rectangle_list_t *list;
     cairo_rectangle_t *rectangles = NULL;
@@ -1507,57 +1507,37 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
     if (clip->all_clipped)
 	goto DONE;
 
-    if (clip->path != NULL) {
-	status = _cairo_clip_get_region (clip, &region);
-	if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
-	    goto DONE;
-	} else if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
-	    return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE)
-	} else if (unlikely (status)) {
-	    return ERROR_LIST (status);
-	}
-    }
-
-    if (region != NULL) {
-	n_rects = cairo_region_num_rectangles (region);
-	if (n_rects) {
-	    rectangles = _cairo_malloc_ab (n_rects, sizeof (cairo_rectangle_t));
-	    if (unlikely (rectangles == NULL)) {
-		return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
-	    }
+    if (!clip->path)
+	return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
 
-	    for (i = 0; i < n_rects; ++i) {
-		cairo_rectangle_int_t clip_rect;
-
-		cairo_region_get_rectangle (region, i, &clip_rect);
+    status = _cairo_clip_get_region (clip, &region);
+    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
+	goto DONE;
+    } else if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+	return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
+    } else if (unlikely (status)) {
+	return ERROR_LIST (status);
+    }
 
-		if (! _cairo_clip_int_rect_to_user (gstate,
-						    &clip_rect,
-						    &rectangles[i]))
-		{
-		    free (rectangles);
-		    return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
-		}
-	    }
+    n_rects = cairo_region_num_rectangles (region);
+    if (n_rects) {
+	rectangles = _cairo_malloc_ab (n_rects, sizeof (cairo_rectangle_t));
+	if (unlikely (rectangles == NULL)) {
+	    return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
 	}
-    } else {
-        cairo_rectangle_int_t extents;
 
-	if (! _cairo_surface_get_extents (_cairo_gstate_get_target (gstate),
-					  &extents))
-	{
-	    /* unbounded surface -> unclipped */
-	    goto DONE;
-	}
+	for (i = 0; i < n_rects; ++i) {
+	    cairo_rectangle_int_t clip_rect;
 
-	n_rects = 1;
-	rectangles = malloc(sizeof (cairo_rectangle_t));
-	if (unlikely (rectangles == NULL))
-	    return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
+	    cairo_region_get_rectangle (region, i, &clip_rect);
 
-	if (! _cairo_clip_int_rect_to_user (gstate, &extents, rectangles)) {
-	    free (rectangles);
-	    return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
+	    if (! _cairo_clip_int_rect_to_user (gstate,
+						&clip_rect,
+						&rectangles[i]))
+	    {
+		free (rectangles);
+		return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
+	    }
 	}
     }
 
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index baf6145..7caf624 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -1555,7 +1555,19 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate,
 cairo_rectangle_list_t*
 _cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate)
 {
-    return _cairo_clip_copy_rectangle_list (&gstate->clip, gstate);
+    cairo_clip_t clip;
+    cairo_rectangle_int_t extents;
+    cairo_rectangle_list_t *list;
+
+    _cairo_clip_init_copy (&clip, &gstate->clip);
+
+    if (_cairo_surface_get_extents (gstate->target, &extents))
+        _cairo_clip_rectangle (&clip, &extents);
+
+    list = _cairo_clip_copy_rectangle_list (&clip, gstate);
+    _cairo_clip_fini (&clip);
+
+    return list;
 }
 
 static void
diff --git a/test/get-clip.c b/test/get-clip.c
index f0477a1..f97db3f 100644
--- a/test/get-clip.c
+++ b/test/get-clip.c
@@ -120,6 +120,22 @@ preamble (cairo_test_context_t *ctx)
     }
     cairo_rectangle_list_destroy (rectangle_list);
 
+    /* We should get the same results after applying a clip that contains the
+       existing clip. */
+    phase = "Clip beyond surface extents";
+    cairo_save (cr);
+    cairo_rectangle (cr, -10, -10, SIZE + 20 , SIZE + 20);
+    cairo_clip (cr);
+    rectangle_list = cairo_copy_clip_rectangle_list (cr);
+    if (! check_count (ctx, phase, rectangle_list, 1) ||
+        ! check_clip_extents (ctx, phase, cr, 0, 0, SIZE, SIZE) ||
+        ! check_rectangles_contain (ctx, phase, rectangle_list, 0, 0, SIZE, SIZE))
+    {
+	goto FAIL;
+    }
+    cairo_rectangle_list_destroy (rectangle_list);
+    cairo_restore (cr);
+
     /* Test simple clip rect. */
     phase = "Simple clip rect";
     cairo_save (cr);
commit b79ea8a6cab8bd28aebecf6e1e8229d5ac017264
Author: Karl Tomlinson <karlt+ at karlt.net>
Date:   Sat Jul 17 11:46:25 2010 +1200

    clip: consider all_clipped in _cairo_clip_get_extents
    
    If the gstate clip in _cairo_gstate_int_clip_extents() has all_clipped
    set (and path NULL), then it returns the gstate target extents instead of
    an empty rectangle.  If the target is infinite, then it says the clip is
    unbounded.
    
    Fixes https://bugs.freedesktop.org/show_bug.cgi?id=29124
    Tested-by test/get-clip
    
    Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index f6173c6..77d8214 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -1264,9 +1264,14 @@ _cairo_clip_combine_with_surface (cairo_clip_t *clip,
     return CAIRO_STATUS_SUCCESS;
 }
 
+static const cairo_rectangle_int_t _cairo_empty_rectangle_int = { 0, 0, 0, 0 };
+
 const cairo_rectangle_int_t *
 _cairo_clip_get_extents (const cairo_clip_t *clip)
 {
+    if (clip->all_clipped)
+	return &_cairo_empty_rectangle_int;
+
     if (clip->path == NULL)
 	return NULL;
 
diff --git a/test/get-clip.c b/test/get-clip.c
index 9d6e796..f0477a1 100644
--- a/test/get-clip.c
+++ b/test/get-clip.c
@@ -83,6 +83,8 @@ check_clip_extents (const cairo_test_context_t *ctx,
     cairo_clip_extents (cr, &ext_x1, &ext_y1, &ext_x2, &ext_y2);
     if (ext_x1 == x && ext_y1 == y && ext_x2 == x + width && ext_y2 == y + height)
         return 1;
+    if (width == 0.0 && height == 0.0 && ext_x1 == ext_x2 && ext_y1 == ext_y2)
+        return 1;
     cairo_test_log (ctx, "Error: %s; clip extents %f,%f,%f,%f should be %f,%f,%f,%f\n",
                     message, ext_x1, ext_y1, ext_x2 - ext_x1, ext_y2 - ext_y1,
                     x, y, width, height);
@@ -138,7 +140,8 @@ preamble (cairo_test_context_t *ctx)
     cairo_save (cr);
     cairo_clip (cr);
     rectangle_list = cairo_copy_clip_rectangle_list (cr);
-    if (! check_count (ctx, phase, rectangle_list, 0))
+    if (! check_count (ctx, phase, rectangle_list, 0) ||
+        ! check_clip_extents (ctx, phase, cr, 0, 0, 0, 0))
     {
 	goto FAIL;
     }
commit 6a5115901381fe9c81a8a311e267c2a00e2a1d04
Author: Karl Tomlinson <karlt+ at karlt.net>
Date:   Sat Jul 17 10:47:42 2010 +1200

    test: return CAIRO_TEST_FAILURE from get-clip preamble on failure
    
    https://bugs.freedesktop.org/show_bug.cgi?id=29120

diff --git a/test/get-clip.c b/test/get-clip.c
index 1847229..9d6e796 100644
--- a/test/get-clip.c
+++ b/test/get-clip.c
@@ -98,6 +98,7 @@ preamble (cairo_test_context_t *ctx)
     cairo_t                *cr;
     cairo_rectangle_list_t *rectangle_list;
     const char             *phase;
+    cairo_bool_t            completed = 0;
     cairo_status_t          status;
 
     surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, SIZE, SIZE);
@@ -224,11 +225,15 @@ preamble (cairo_test_context_t *ctx)
     if (! check_unrepresentable (ctx, phase, rectangle_list))
 	goto FAIL;
 
+    completed = 1;
 FAIL:
     cairo_rectangle_list_destroy (rectangle_list);
     status = cairo_status (cr);
     cairo_destroy (cr);
 
+    if (!completed)
+        return CAIRO_TEST_FAILURE;
+
     return cairo_test_status_from_status (ctx, status);
 }
 
commit f2fa15680ec3ac95cb68d4957557f06561a7dc55
Author: Karl Tomlinson <karlt+ at karlt.net>
Date:   Sat Jul 17 10:39:50 2010 +1200

    clip: return empty clip from _cairo_clip_copy_rectangle_list when all_clipped
    
    Fixes https://bugs.freedesktop.org/show_bug.cgi?id=29122
    Tested by test/get-clip
    
    Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 12dc04d..f6173c6 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -1499,7 +1499,10 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate)
     int n_rects = 0;
     int i;
 
-    if (clip != NULL && clip->path != NULL) {
+    if (clip->all_clipped)
+	goto DONE;
+
+    if (clip->path != NULL) {
 	status = _cairo_clip_get_region (clip, &region);
 	if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
 	    goto DONE;
commit 33ac2035876aeb9215ca0bdaaeea5265fcee61f8
Author: Karl Tomlinson <karlt+ at karlt.net>
Date:   Sat Jul 17 10:13:22 2010 +1200

    test: use the surface size expected in get-clip phase "No clip set"
    
    https://bugs.freedesktop.org/show_bug.cgi?id=29121

diff --git a/test/get-clip.c b/test/get-clip.c
index d254495..1847229 100644
--- a/test/get-clip.c
+++ b/test/get-clip.c
@@ -89,6 +89,8 @@ check_clip_extents (const cairo_test_context_t *ctx,
     return 0;
 }
 
+#define SIZE 100
+
 static cairo_test_status_t
 preamble (cairo_test_context_t *ctx)
 {
@@ -98,7 +100,7 @@ preamble (cairo_test_context_t *ctx)
     const char             *phase;
     cairo_status_t          status;
 
-    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
+    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, SIZE, SIZE);
     cr = cairo_create (surface);
     cairo_surface_destroy (surface);
 
@@ -108,8 +110,8 @@ preamble (cairo_test_context_t *ctx)
     phase = "No clip set";
     rectangle_list = cairo_copy_clip_rectangle_list (cr);
     if (! check_count (ctx, phase, rectangle_list, 1) ||
-        ! check_clip_extents (ctx, phase, cr, 0, 0, 100, 100) ||
-        ! check_rectangles_contain (ctx, phase, rectangle_list, 0, 0, 100, 100))
+        ! check_clip_extents (ctx, phase, cr, 0, 0, SIZE, SIZE) ||
+        ! check_rectangles_contain (ctx, phase, rectangle_list, 0, 0, SIZE, SIZE))
     {
 	goto FAIL;
     }


More information about the cairo-commit mailing list