michael@0: From 108b1c7825116ed3f93aa57384bbd3290cdc9181 Mon Sep 17 00:00:00 2001 michael@0: From: Karl Tomlinson michael@0: Date: Sat, 17 Jul 2010 01:08:53 +0000 michael@0: Subject: clip: consider gstate target extents in _cairo_gstate_copy_clip_rectangle_list michael@0: michael@0: Fixes https://bugs.freedesktop.org/show_bug.cgi?id=29125 michael@0: michael@0: To be consistent with _cairo_gstate_clip_extents, the context's clip michael@0: should be intersected with the target surface extents (instead of only michael@0: using them when there is no clip). michael@0: michael@0: Reviewed-by: Chris Wilson michael@0: --- michael@0: diff --git a/src/cairo-clip.c b/src/cairo-clip.c michael@0: index 77d8214..d5a2fab 100644 michael@0: --- a/src/cairo-clip.c michael@0: +++ b/src/cairo-clip.c michael@0: @@ -1495,7 +1495,7 @@ _cairo_rectangle_list_create_in_error (cairo_status_t status) michael@0: cairo_rectangle_list_t * michael@0: _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate) michael@0: { michael@0: -#define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S)); michael@0: +#define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S)) michael@0: michael@0: cairo_rectangle_list_t *list; michael@0: cairo_rectangle_t *rectangles = NULL; michael@0: @@ -1507,57 +1507,37 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate) michael@0: if (clip->all_clipped) michael@0: goto DONE; michael@0: michael@0: - if (clip->path != NULL) { michael@0: - status = _cairo_clip_get_region (clip, ®ion); michael@0: - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) { michael@0: - goto DONE; michael@0: - } else if (status == CAIRO_INT_STATUS_UNSUPPORTED) { michael@0: - return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE) michael@0: - } else if (unlikely (status)) { michael@0: - return ERROR_LIST (status); michael@0: - } michael@0: - } michael@0: - michael@0: - if (region != NULL) { michael@0: - n_rects = cairo_region_num_rectangles (region); michael@0: - if (n_rects) { michael@0: - rectangles = _cairo_malloc_ab (n_rects, sizeof (cairo_rectangle_t)); michael@0: - if (unlikely (rectangles == NULL)) { michael@0: - return ERROR_LIST (CAIRO_STATUS_NO_MEMORY); michael@0: - } michael@0: + if (!clip->path) michael@0: + return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); michael@0: michael@0: - for (i = 0; i < n_rects; ++i) { michael@0: - cairo_rectangle_int_t clip_rect; michael@0: - michael@0: - cairo_region_get_rectangle (region, i, &clip_rect); michael@0: + status = _cairo_clip_get_region (clip, ®ion); michael@0: + if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) { michael@0: + goto DONE; michael@0: + } else if (status == CAIRO_INT_STATUS_UNSUPPORTED) { michael@0: + return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); michael@0: + } else if (unlikely (status)) { michael@0: + return ERROR_LIST (status); michael@0: + } michael@0: michael@0: - if (! _cairo_clip_int_rect_to_user (gstate, michael@0: - &clip_rect, michael@0: - &rectangles[i])) michael@0: - { michael@0: - free (rectangles); michael@0: - return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); michael@0: - } michael@0: - } michael@0: + n_rects = cairo_region_num_rectangles (region); michael@0: + if (n_rects) { michael@0: + rectangles = _cairo_malloc_ab (n_rects, sizeof (cairo_rectangle_t)); michael@0: + if (unlikely (rectangles == NULL)) { michael@0: + return ERROR_LIST (CAIRO_STATUS_NO_MEMORY); michael@0: } michael@0: - } else { michael@0: - cairo_rectangle_int_t extents; michael@0: michael@0: - if (! _cairo_surface_get_extents (_cairo_gstate_get_target (gstate), michael@0: - &extents)) michael@0: - { michael@0: - /* unbounded surface -> unclipped */ michael@0: - goto DONE; michael@0: - } michael@0: + for (i = 0; i < n_rects; ++i) { michael@0: + cairo_rectangle_int_t clip_rect; michael@0: michael@0: - n_rects = 1; michael@0: - rectangles = malloc(sizeof (cairo_rectangle_t)); michael@0: - if (unlikely (rectangles == NULL)) michael@0: - return ERROR_LIST (CAIRO_STATUS_NO_MEMORY); michael@0: + cairo_region_get_rectangle (region, i, &clip_rect); michael@0: michael@0: - if (! _cairo_clip_int_rect_to_user (gstate, &extents, rectangles)) { michael@0: - free (rectangles); michael@0: - return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); michael@0: + if (! _cairo_clip_int_rect_to_user (gstate, michael@0: + &clip_rect, michael@0: + &rectangles[i])) michael@0: + { michael@0: + free (rectangles); michael@0: + return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); michael@0: + } michael@0: } michael@0: } michael@0: michael@0: diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c michael@0: index baf6145..7caf624 100644 michael@0: --- a/src/cairo-gstate.c michael@0: +++ b/src/cairo-gstate.c michael@0: @@ -1555,7 +1555,19 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate, michael@0: cairo_rectangle_list_t* michael@0: _cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate) michael@0: { michael@0: - return _cairo_clip_copy_rectangle_list (&gstate->clip, gstate); michael@0: + cairo_clip_t clip; michael@0: + cairo_rectangle_int_t extents; michael@0: + cairo_rectangle_list_t *list; michael@0: + michael@0: + _cairo_clip_init_copy (&clip, &gstate->clip); michael@0: + michael@0: + if (_cairo_surface_get_extents (gstate->target, &extents)) michael@0: + _cairo_clip_rectangle (&clip, &extents); michael@0: + michael@0: + list = _cairo_clip_copy_rectangle_list (&clip, gstate); michael@0: + _cairo_clip_fini (&clip); michael@0: + michael@0: + return list; michael@0: } michael@0: michael@0: static void michael@0: diff --git a/test/get-clip.c b/test/get-clip.c michael@0: index f0477a1..f97db3f 100644 michael@0: --- a/test/get-clip.c michael@0: +++ b/test/get-clip.c michael@0: @@ -120,6 +120,22 @@ preamble (cairo_test_context_t *ctx) michael@0: } michael@0: cairo_rectangle_list_destroy (rectangle_list); michael@0: michael@0: + /* We should get the same results after applying a clip that contains the michael@0: + existing clip. */ michael@0: + phase = "Clip beyond surface extents"; michael@0: + cairo_save (cr); michael@0: + cairo_rectangle (cr, -10, -10, SIZE + 20 , SIZE + 20); michael@0: + cairo_clip (cr); michael@0: + rectangle_list = cairo_copy_clip_rectangle_list (cr); michael@0: + if (! check_count (ctx, phase, rectangle_list, 1) || michael@0: + ! check_clip_extents (ctx, phase, cr, 0, 0, SIZE, SIZE) || michael@0: + ! check_rectangles_contain (ctx, phase, rectangle_list, 0, 0, SIZE, SIZE)) michael@0: + { michael@0: + goto FAIL; michael@0: + } michael@0: + cairo_rectangle_list_destroy (rectangle_list); michael@0: + cairo_restore (cr); michael@0: + michael@0: /* Test simple clip rect. */ michael@0: phase = "Simple clip rect"; michael@0: cairo_save (cr); michael@0: -- michael@0: cgit v0.8.3-6-g21f6