commit 29b6a8f7b2b587769af92c87e12304644845b668 Author: Karl Tomlinson 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 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, ®ion); - 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, ®ion); + 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);