summaryrefslogtreecommitdiffstats
path: root/gfx/cairo/clip-rects-surface-extents.patch
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/cairo/clip-rects-surface-extents.patch')
-rw-r--r--gfx/cairo/clip-rects-surface-extents.patch163
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 000000000..1a9972aa7
--- /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, &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