diff options
Diffstat (limited to 'gfx/cairo/clip-rects-surface-extents.patch')
-rw-r--r-- | gfx/cairo/clip-rects-surface-extents.patch | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/gfx/cairo/clip-rects-surface-extents.patch b/gfx/cairo/clip-rects-surface-extents.patch new file mode 100644 index 0000000000..1a9972aa75 --- /dev/null +++ b/gfx/cairo/clip-rects-surface-extents.patch @@ -0,0 +1,163 @@ +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, ®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); +-- +cgit v0.8.3-6-g21f6 |