|
1 From 108b1c7825116ed3f93aa57384bbd3290cdc9181 Mon Sep 17 00:00:00 2001 |
|
2 From: Karl Tomlinson <karlt+@karlt.net> |
|
3 Date: Sat, 17 Jul 2010 01:08:53 +0000 |
|
4 Subject: clip: consider gstate target extents in _cairo_gstate_copy_clip_rectangle_list |
|
5 |
|
6 Fixes https://bugs.freedesktop.org/show_bug.cgi?id=29125 |
|
7 |
|
8 To be consistent with _cairo_gstate_clip_extents, the context's clip |
|
9 should be intersected with the target surface extents (instead of only |
|
10 using them when there is no clip). |
|
11 |
|
12 Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> |
|
13 --- |
|
14 diff --git a/src/cairo-clip.c b/src/cairo-clip.c |
|
15 index 77d8214..d5a2fab 100644 |
|
16 --- a/src/cairo-clip.c |
|
17 +++ b/src/cairo-clip.c |
|
18 @@ -1495,7 +1495,7 @@ _cairo_rectangle_list_create_in_error (cairo_status_t status) |
|
19 cairo_rectangle_list_t * |
|
20 _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate) |
|
21 { |
|
22 -#define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S)); |
|
23 +#define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S)) |
|
24 |
|
25 cairo_rectangle_list_t *list; |
|
26 cairo_rectangle_t *rectangles = NULL; |
|
27 @@ -1507,57 +1507,37 @@ _cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate) |
|
28 if (clip->all_clipped) |
|
29 goto DONE; |
|
30 |
|
31 - if (clip->path != NULL) { |
|
32 - status = _cairo_clip_get_region (clip, ®ion); |
|
33 - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) { |
|
34 - goto DONE; |
|
35 - } else if (status == CAIRO_INT_STATUS_UNSUPPORTED) { |
|
36 - return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE) |
|
37 - } else if (unlikely (status)) { |
|
38 - return ERROR_LIST (status); |
|
39 - } |
|
40 - } |
|
41 - |
|
42 - if (region != NULL) { |
|
43 - n_rects = cairo_region_num_rectangles (region); |
|
44 - if (n_rects) { |
|
45 - rectangles = _cairo_malloc_ab (n_rects, sizeof (cairo_rectangle_t)); |
|
46 - if (unlikely (rectangles == NULL)) { |
|
47 - return ERROR_LIST (CAIRO_STATUS_NO_MEMORY); |
|
48 - } |
|
49 + if (!clip->path) |
|
50 + return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); |
|
51 |
|
52 - for (i = 0; i < n_rects; ++i) { |
|
53 - cairo_rectangle_int_t clip_rect; |
|
54 - |
|
55 - cairo_region_get_rectangle (region, i, &clip_rect); |
|
56 + status = _cairo_clip_get_region (clip, ®ion); |
|
57 + if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) { |
|
58 + goto DONE; |
|
59 + } else if (status == CAIRO_INT_STATUS_UNSUPPORTED) { |
|
60 + return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); |
|
61 + } else if (unlikely (status)) { |
|
62 + return ERROR_LIST (status); |
|
63 + } |
|
64 |
|
65 - if (! _cairo_clip_int_rect_to_user (gstate, |
|
66 - &clip_rect, |
|
67 - &rectangles[i])) |
|
68 - { |
|
69 - free (rectangles); |
|
70 - return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); |
|
71 - } |
|
72 - } |
|
73 + n_rects = cairo_region_num_rectangles (region); |
|
74 + if (n_rects) { |
|
75 + rectangles = _cairo_malloc_ab (n_rects, sizeof (cairo_rectangle_t)); |
|
76 + if (unlikely (rectangles == NULL)) { |
|
77 + return ERROR_LIST (CAIRO_STATUS_NO_MEMORY); |
|
78 } |
|
79 - } else { |
|
80 - cairo_rectangle_int_t extents; |
|
81 |
|
82 - if (! _cairo_surface_get_extents (_cairo_gstate_get_target (gstate), |
|
83 - &extents)) |
|
84 - { |
|
85 - /* unbounded surface -> unclipped */ |
|
86 - goto DONE; |
|
87 - } |
|
88 + for (i = 0; i < n_rects; ++i) { |
|
89 + cairo_rectangle_int_t clip_rect; |
|
90 |
|
91 - n_rects = 1; |
|
92 - rectangles = malloc(sizeof (cairo_rectangle_t)); |
|
93 - if (unlikely (rectangles == NULL)) |
|
94 - return ERROR_LIST (CAIRO_STATUS_NO_MEMORY); |
|
95 + cairo_region_get_rectangle (region, i, &clip_rect); |
|
96 |
|
97 - if (! _cairo_clip_int_rect_to_user (gstate, &extents, rectangles)) { |
|
98 - free (rectangles); |
|
99 - return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); |
|
100 + if (! _cairo_clip_int_rect_to_user (gstate, |
|
101 + &clip_rect, |
|
102 + &rectangles[i])) |
|
103 + { |
|
104 + free (rectangles); |
|
105 + return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); |
|
106 + } |
|
107 } |
|
108 } |
|
109 |
|
110 diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c |
|
111 index baf6145..7caf624 100644 |
|
112 --- a/src/cairo-gstate.c |
|
113 +++ b/src/cairo-gstate.c |
|
114 @@ -1555,7 +1555,19 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate, |
|
115 cairo_rectangle_list_t* |
|
116 _cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate) |
|
117 { |
|
118 - return _cairo_clip_copy_rectangle_list (&gstate->clip, gstate); |
|
119 + cairo_clip_t clip; |
|
120 + cairo_rectangle_int_t extents; |
|
121 + cairo_rectangle_list_t *list; |
|
122 + |
|
123 + _cairo_clip_init_copy (&clip, &gstate->clip); |
|
124 + |
|
125 + if (_cairo_surface_get_extents (gstate->target, &extents)) |
|
126 + _cairo_clip_rectangle (&clip, &extents); |
|
127 + |
|
128 + list = _cairo_clip_copy_rectangle_list (&clip, gstate); |
|
129 + _cairo_clip_fini (&clip); |
|
130 + |
|
131 + return list; |
|
132 } |
|
133 |
|
134 static void |
|
135 diff --git a/test/get-clip.c b/test/get-clip.c |
|
136 index f0477a1..f97db3f 100644 |
|
137 --- a/test/get-clip.c |
|
138 +++ b/test/get-clip.c |
|
139 @@ -120,6 +120,22 @@ preamble (cairo_test_context_t *ctx) |
|
140 } |
|
141 cairo_rectangle_list_destroy (rectangle_list); |
|
142 |
|
143 + /* We should get the same results after applying a clip that contains the |
|
144 + existing clip. */ |
|
145 + phase = "Clip beyond surface extents"; |
|
146 + cairo_save (cr); |
|
147 + cairo_rectangle (cr, -10, -10, SIZE + 20 , SIZE + 20); |
|
148 + cairo_clip (cr); |
|
149 + rectangle_list = cairo_copy_clip_rectangle_list (cr); |
|
150 + if (! check_count (ctx, phase, rectangle_list, 1) || |
|
151 + ! check_clip_extents (ctx, phase, cr, 0, 0, SIZE, SIZE) || |
|
152 + ! check_rectangles_contain (ctx, phase, rectangle_list, 0, 0, SIZE, SIZE)) |
|
153 + { |
|
154 + goto FAIL; |
|
155 + } |
|
156 + cairo_rectangle_list_destroy (rectangle_list); |
|
157 + cairo_restore (cr); |
|
158 + |
|
159 /* Test simple clip rect. */ |
|
160 phase = "Simple clip rect"; |
|
161 cairo_save (cr); |
|
162 -- |
|
163 cgit v0.8.3-6-g21f6 |