pjs/gfx/cairo/clip-rects-surface-extents....

164 строки
5.3 KiB
Diff

From 108b1c7825116ed3f93aa57384bbd3290cdc9181 Mon Sep 17 00:00:00 2001
From: Karl Tomlinson <karlt+@karlt.net>
Date: Sat, 17 Jul 2010 01:08:53 +0000
Subject: 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@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);
--
cgit v0.8.3-6-g21f6