Rev 1892 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1892 | Rev 3959 | ||
---|---|---|---|
Line 38... | Line 38... | ||
38 | * Kristian Høgsberg |
38 | * Kristian Høgsberg |
39 | * Chris Wilson |
39 | * Chris Wilson |
40 | */ |
40 | */ |
Line 41... | Line 41... | ||
41 | 41 | ||
- | 42 | #include "cairoint.h" |
|
42 | #include "cairoint.h" |
43 | #include "cairo-clip-inline.h" |
43 | #include "cairo-clip-private.h" |
44 | #include "cairo-clip-private.h" |
44 | #include "cairo-error-private.h" |
45 | #include "cairo-error-private.h" |
45 | #include "cairo-freed-pool-private.h" |
46 | #include "cairo-freed-pool-private.h" |
46 | #include "cairo-gstate-private.h" |
47 | #include "cairo-gstate-private.h" |
- | 48 | #include "cairo-path-fixed-private.h" |
|
47 | #include "cairo-path-fixed-private.h" |
49 | #include "cairo-pattern-private.h" |
48 | #include "cairo-composite-rectangles-private.h" |
50 | #include "cairo-composite-rectangles-private.h" |
Line 49... | Line -... | ||
49 | #include "cairo-region-private.h" |
- | |
50 | 51 | #include "cairo-region-private.h" |
|
- | 52 | ||
51 | #if HAS_FREED_POOL |
53 | static freed_pool_t clip_path_pool; |
- | 54 | static freed_pool_t clip_pool; |
|
Line 52... | Line 55... | ||
52 | static freed_pool_t clip_path_pool; |
55 | |
53 | #endif |
56 | const cairo_clip_t __cairo_clip_all; |
54 | 57 | ||
55 | static cairo_clip_path_t * |
58 | static cairo_clip_path_t * |
Line 64... | Line 67... | ||
64 | return NULL; |
67 | return NULL; |
65 | } |
68 | } |
Line 66... | Line 69... | ||
66 | 69 | ||
Line 67... | Line -... | ||
67 | CAIRO_REFERENCE_COUNT_INIT (&clip_path->ref_count, 1); |
- | |
68 | - | ||
69 | clip_path->flags = 0; |
- | |
70 | clip_path->region = NULL; |
- | |
71 | clip_path->surface = NULL; |
70 | CAIRO_REFERENCE_COUNT_INIT (&clip_path->ref_count, 1); |
72 | 71 | ||
Line 73... | Line 72... | ||
73 | clip_path->prev = clip->path; |
72 | clip_path->prev = clip->path; |
74 | clip->path = clip_path; |
73 | clip->path = clip_path; |
Line 75... | Line 74... | ||
75 | 74 | ||
76 | return clip_path; |
75 | return clip_path; |
77 | } |
76 | } |
78 | 77 | ||
Line 79... | Line 78... | ||
79 | static cairo_clip_path_t * |
78 | cairo_clip_path_t * |
Line 80... | Line 79... | ||
80 | _cairo_clip_path_reference (cairo_clip_path_t *clip_path) |
79 | _cairo_clip_path_reference (cairo_clip_path_t *clip_path) |
81 | { |
80 | { |
Line 82... | Line 81... | ||
82 | assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count)); |
81 | assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count)); |
83 | 82 | ||
84 | _cairo_reference_count_inc (&clip_path->ref_count); |
83 | _cairo_reference_count_inc (&clip_path->ref_count); |
85 | 84 | ||
Line 86... | Line 85... | ||
86 | return clip_path; |
85 | return clip_path; |
87 | } |
86 | } |
Line 88... | Line 87... | ||
88 | 87 | ||
89 | static void |
- | |
90 | _cairo_clip_path_destroy (cairo_clip_path_t *clip_path) |
- | |
91 | { |
- | |
92 | assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count)); |
- | |
Line 93... | Line 88... | ||
93 | 88 | void |
|
94 | if (! _cairo_reference_count_dec_and_test (&clip_path->ref_count)) |
89 | _cairo_clip_path_destroy (cairo_clip_path_t *clip_path) |
Line 95... | Line 90... | ||
95 | return; |
90 | { |
96 | 91 | assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count)); |
|
Line 97... | Line 92... | ||
97 | _cairo_path_fixed_fini (&clip_path->path); |
92 | |
98 | if (clip_path->region != NULL) |
93 | if (! _cairo_reference_count_dec_and_test (&clip_path->ref_count)) |
99 | cairo_region_destroy (clip_path->region); |
94 | return; |
100 | if (clip_path->surface != NULL) |
95 | |
- | 96 | _cairo_path_fixed_fini (&clip_path->path); |
|
- | 97 | ||
- | 98 | if (clip_path->prev != NULL) |
|
- | 99 | _cairo_clip_path_destroy (clip_path->prev); |
|
- | 100 | ||
- | 101 | _freed_pool_put (&clip_path_pool, clip_path); |
|
- | 102 | } |
|
- | 103 | ||
- | 104 | cairo_clip_t * |
|
- | 105 | _cairo_clip_create (void) |
|
101 | cairo_surface_destroy (clip_path->surface); |
106 | { |
- | 107 | cairo_clip_t *clip; |
|
- | 108 | ||
- | 109 | clip = _freed_pool_get (&clip_pool); |
|
- | 110 | if (unlikely (clip == NULL)) { |
|
- | 111 | clip = malloc (sizeof (cairo_clip_t)); |
|
- | 112 | if (unlikely (clip == NULL)) |
|
102 | 113 | return NULL; |
|
Line 103... | Line 114... | ||
103 | if (clip_path->prev != NULL) |
114 | } |
104 | _cairo_clip_path_destroy (clip_path->prev); |
115 | |
105 | 116 | clip->extents = _cairo_unbounded_rectangle; |
|
106 | _freed_pool_put (&clip_path_pool, clip_path); |
117 | |
- | 118 | clip->path = NULL; |
|
- | 119 | clip->boxes = NULL; |
|
107 | } |
120 | clip->num_boxes = 0; |
108 | 121 | clip->region = NULL; |
|
- | 122 | clip->is_region = FALSE; |
|
- | 123 | ||
109 | void |
124 | return clip; |
- | 125 | } |
|
110 | _cairo_clip_init (cairo_clip_t *clip) |
126 | |
- | 127 | void |
|
111 | { |
128 | _cairo_clip_destroy (cairo_clip_t *clip) |
Line 112... | Line 129... | ||
112 | clip->all_clipped = FALSE; |
129 | { |
113 | clip->path = NULL; |
130 | if (clip == NULL || _cairo_clip_is_all_clipped (clip)) |
114 | } |
- | |
115 | 131 | return; |
|
116 | static void |
132 | |
117 | _cairo_clip_set_all_clipped (cairo_clip_t *clip) |
- | |
Line 118... | Line -... | ||
118 | { |
- | |
119 | clip->all_clipped = TRUE; |
- | |
120 | if (clip->path != NULL) { |
133 | if (clip->path != NULL) |
121 | _cairo_clip_path_destroy (clip->path); |
- | |
122 | clip->path = NULL; |
- | |
123 | } |
- | |
124 | } |
134 | _cairo_clip_path_destroy (clip->path); |
125 | - | ||
126 | static cairo_status_t |
- | |
Line 127... | Line 135... | ||
127 | _cairo_clip_intersect_rectangle (cairo_clip_t *clip, |
135 | |
128 | const cairo_rectangle_int_t *rect) |
- | |
129 | { |
- | |
Line -... | Line 136... | ||
- | 136 | if (clip->boxes != &clip->embedded_box) |
|
130 | cairo_clip_path_t *clip_path; |
137 | free (clip->boxes); |
Line 131... | Line -... | ||
131 | cairo_status_t status; |
- | |
132 | - | ||
133 | if (clip->path != NULL) { |
- | |
134 | if (rect->x <= clip->path->extents.x && |
- | |
135 | rect->y <= clip->path->extents.y && |
- | |
136 | rect->x + rect->width >= clip->path->extents.x + clip->path->extents.width && |
- | |
137 | rect->y + rect->height >= clip->path->extents.y + clip->path->extents.height) |
138 | cairo_region_destroy (clip->region); |
138 | { |
- | |
139 | return CAIRO_STATUS_SUCCESS; |
- | |
140 | } |
139 | |
141 | } |
140 | _freed_pool_put (&clip_pool, clip); |
142 | - | ||
143 | clip_path = _cairo_clip_path_create (clip); |
- | |
144 | if (unlikely (clip_path == NULL)) |
- | |
145 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
141 | } |
146 | - | ||
147 | _cairo_path_fixed_init (&clip_path->path); |
142 | |
148 | - | ||
149 | status = _cairo_path_fixed_move_to (&clip_path->path, |
- | |
150 | _cairo_fixed_from_int (rect->x), |
- | |
151 | _cairo_fixed_from_int (rect->y)); |
- | |
152 | assert (status == CAIRO_STATUS_SUCCESS); |
- | |
153 | status = _cairo_path_fixed_rel_line_to (&clip_path->path, |
- | |
154 | _cairo_fixed_from_int (rect->width), |
- | |
155 | _cairo_fixed_from_int (0)); |
- | |
156 | assert (status == CAIRO_STATUS_SUCCESS); |
143 | cairo_clip_t * |
157 | status = _cairo_path_fixed_rel_line_to (&clip_path->path, |
- | |
158 | _cairo_fixed_from_int (0), |
- | |
159 | _cairo_fixed_from_int (rect->height)); |
- | |
160 | assert (status == CAIRO_STATUS_SUCCESS); |
144 | _cairo_clip_copy (const cairo_clip_t *clip) |
161 | status = _cairo_path_fixed_rel_line_to (&clip_path->path, |
145 | { |
- | 146 | cairo_clip_t *copy; |
|
- | 147 | ||
- | 148 | if (clip == NULL || _cairo_clip_is_all_clipped (clip)) |
|
- | 149 | return (cairo_clip_t *) clip; |
|
162 | _cairo_fixed_from_int (-rect->width), |
150 | |
Line -... | Line 151... | ||
- | 151 | copy = _cairo_clip_create (); |
|
163 | _cairo_fixed_from_int (0)); |
152 | |
- | 153 | if (clip->path) |
|
Line 164... | Line 154... | ||
164 | assert (status == CAIRO_STATUS_SUCCESS); |
154 | copy->path = _cairo_clip_path_reference (clip->path); |
165 | status = _cairo_path_fixed_close_path (&clip_path->path); |
155 | |
Line 166... | Line 156... | ||
166 | assert (status == CAIRO_STATUS_SUCCESS); |
156 | if (clip->num_boxes) { |
167 | 157 | if (clip->num_boxes == 1) { |
|
168 | clip_path->fill_rule = CAIRO_FILL_RULE_WINDING; |
158 | copy->boxes = ©->embedded_box; |
169 | clip_path->tolerance = 1; |
159 | } else { |
- | 160 | copy->boxes = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_box_t)); |
|
170 | clip_path->antialias = CAIRO_ANTIALIAS_DEFAULT; |
161 | if (unlikely (copy->boxes == NULL)) |
171 | clip_path->flags |= CAIRO_CLIP_PATH_IS_BOX; |
162 | return _cairo_clip_set_all_clipped (copy); |
- | 163 | } |
|
172 | 164 | ||
- | 165 | memcpy (copy->boxes, clip->boxes, |
|
173 | clip_path->extents = *rect; |
166 | clip->num_boxes * sizeof (cairo_box_t)); |
174 | if (clip_path->prev != NULL) { |
167 | copy->num_boxes = clip->num_boxes; |
175 | if (! _cairo_rectangle_intersect (&clip_path->extents, |
168 | } |
176 | &clip_path->prev->extents)) |
169 | |
- | 170 | copy->extents = clip->extents; |
|
- | 171 | copy->region = cairo_region_reference (clip->region); |
|
177 | { |
172 | copy->is_region = clip->is_region; |
- | 173 | ||
- | 174 | return copy; |
|
- | 175 | } |
|
- | 176 | ||
- | 177 | cairo_clip_t * |
|
- | 178 | _cairo_clip_copy_path (const cairo_clip_t *clip) |
|
- | 179 | { |
|
- | 180 | cairo_clip_t *copy; |
|
- | 181 | ||
- | 182 | if (clip == NULL || _cairo_clip_is_all_clipped (clip)) |
|
- | 183 | return (cairo_clip_t *) clip; |
|
- | 184 | ||
- | 185 | assert (clip->num_boxes); |
|
- | 186 | ||
- | 187 | copy = _cairo_clip_create (); |
|
- | 188 | copy->extents = clip->extents; |
|
- | 189 | if (clip->path) |
|
178 | _cairo_clip_set_all_clipped (clip); |
190 | copy->path = _cairo_clip_path_reference (clip->path); |
179 | } |
191 | |
180 | } |
192 | return copy; |
- | 193 | } |
|
181 | 194 | ||
Line 182... | Line 195... | ||
182 | /* could preallocate the region if it proves worthwhile */ |
195 | cairo_clip_t * |
- | 196 | _cairo_clip_copy_region (const cairo_clip_t *clip) |
|
- | 197 | { |
|
- | 198 | cairo_clip_t *copy; |
|
- | 199 | int i; |
|
183 | 200 | ||
- | 201 | if (clip == NULL || _cairo_clip_is_all_clipped (clip)) |
|
Line 184... | Line -... | ||
184 | return CAIRO_STATUS_SUCCESS; |
- | |
185 | } |
202 | return (cairo_clip_t *) clip; |
- | 203 | ||
186 | 204 | assert (clip->num_boxes); |
|
187 | cairo_clip_t * |
- | |
188 | _cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other) |
- | |
189 | { |
- | |
190 | if (other != NULL) { |
205 | |
191 | clip->all_clipped = other->all_clipped; |
- | |
192 | if (other->path == NULL) { |
206 | copy = _cairo_clip_create (); |
Line 193... | Line 207... | ||
193 | clip->path = NULL; |
207 | copy->extents = clip->extents; |
194 | if (! clip->all_clipped) |
208 | |
195 | clip = NULL; |
209 | if (clip->num_boxes == 1) { |
196 | } else { |
210 | copy->boxes = ©->embedded_box; |
197 | clip->path = _cairo_clip_path_reference (other->path); |
211 | } else { |
198 | } |
212 | copy->boxes = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_box_t)); |
199 | } else { |
213 | if (unlikely (copy->boxes == NULL)) |
200 | _cairo_clip_init (clip); |
214 | return _cairo_clip_set_all_clipped (copy); |
201 | clip = NULL; |
215 | } |
202 | } |
216 | |
203 | 217 | for (i = 0; i < clip->num_boxes; i++) { |
|
204 | return clip; |
- | |
Line 205... | Line -... | ||
205 | } |
- | |
206 | - | ||
207 | void |
- | |
208 | _cairo_clip_reset (cairo_clip_t *clip) |
- | |
209 | { |
218 | copy->boxes[i].p1.x = _cairo_fixed_floor (clip->boxes[i].p1.x); |
210 | clip->all_clipped = FALSE; |
- | |
211 | if (clip->path != NULL) { |
219 | copy->boxes[i].p1.y = _cairo_fixed_floor (clip->boxes[i].p1.y); |
212 | _cairo_clip_path_destroy (clip->path); |
- | |
213 | clip->path = NULL; |
- | |
Line 214... | Line 220... | ||
214 | } |
220 | copy->boxes[i].p2.x = _cairo_fixed_ceil (clip->boxes[i].p2.x); |
215 | } |
221 | copy->boxes[i].p2.y = _cairo_fixed_ceil (clip->boxes[i].p2.y); |
216 | 222 | } |
|
217 | static cairo_status_t |
- | |
218 | _cairo_clip_intersect_path (cairo_clip_t *clip, |
- | |
Line 219... | Line 223... | ||
219 | const cairo_path_fixed_t *path, |
223 | copy->num_boxes = clip->num_boxes; |
220 | cairo_fill_rule_t fill_rule, |
224 | |
221 | double tolerance, |
225 | copy->region = cairo_region_reference (clip->region); |
222 | cairo_antialias_t antialias) |
226 | copy->is_region = TRUE; |
223 | { |
227 | |
- | 228 | return copy; |
|
224 | cairo_clip_path_t *clip_path; |
229 | } |
- | 230 | ||
- | 231 | cairo_clip_t * |
|
- | 232 | _cairo_clip_intersect_path (cairo_clip_t *clip, |
|
- | 233 | const cairo_path_fixed_t *path, |
|
- | 234 | cairo_fill_rule_t fill_rule, |
|
- | 235 | double tolerance, |
|
Line 225... | Line -... | ||
225 | cairo_status_t status; |
- | |
226 | cairo_rectangle_int_t extents; |
- | |
227 | cairo_box_t box; |
236 | cairo_antialias_t antialias) |
228 | cairo_bool_t is_box = FALSE; |
237 | { |
229 | 238 | cairo_clip_path_t *clip_path; |
|
230 | if (clip->path != NULL) { |
- | |
231 | if (clip->path->fill_rule == fill_rule && |
239 | cairo_status_t status; |
- | 240 | cairo_rectangle_int_t extents; |
|
232 | (path->is_rectilinear || tolerance == clip->path->tolerance) && |
241 | cairo_box_t box; |
233 | antialias == clip->path->antialias && |
- | |
234 | _cairo_path_fixed_equal (&clip->path->path, path)) |
242 | |
Line 235... | Line 243... | ||
235 | { |
243 | if (_cairo_clip_is_all_clipped (clip)) |
236 | return CAIRO_STATUS_SUCCESS; |
244 | return clip; |
237 | } |
245 | |
Line 238... | Line 246... | ||
238 | } |
246 | /* catch the empty clip path */ |
239 | 247 | if (_cairo_path_fixed_fill_is_empty (path)) |
|
240 | _cairo_path_fixed_approximate_clip_extents (path, &extents); |
- | |
241 | if (extents.width == 0 || extents.height == 0) { |
248 | return _cairo_clip_set_all_clipped (clip); |
242 | _cairo_clip_set_all_clipped (clip); |
- | |
243 | return CAIRO_STATUS_SUCCESS; |
- | |
Line 244... | Line -... | ||
244 | } |
- | |
245 | 249 | ||
246 | is_box = _cairo_path_fixed_is_box (path, &box); |
250 | if (_cairo_path_fixed_is_box (path, &box)) { |
247 | if (clip->path != NULL) { |
251 | if (antialias == CAIRO_ANTIALIAS_NONE) { |
248 | if (! _cairo_rectangle_intersect (&extents, &clip->path->extents)) { |
- | |
249 | _cairo_clip_set_all_clipped (clip); |
- | |
Line -... | Line 252... | ||
- | 252 | box.p1.x = _cairo_fixed_round_down (box.p1.x); |
|
250 | return CAIRO_STATUS_SUCCESS; |
253 | box.p1.y = _cairo_fixed_round_down (box.p1.y); |
- | 254 | box.p2.x = _cairo_fixed_round_down (box.p2.x); |
|
251 | } |
255 | box.p2.y = _cairo_fixed_round_down (box.p2.y); |
Line -... | Line 256... | ||
- | 256 | } |
|
- | 257 | ||
- | 258 | return _cairo_clip_intersect_box (clip, &box); |
|
- | 259 | } |
|
252 | 260 | if (_cairo_path_fixed_fill_is_rectilinear (path)) |
|
253 | /* does this clip wholly subsume the others? */ |
261 | return _cairo_clip_intersect_rectilinear_path (clip, path, |
254 | if (is_box && |
262 | fill_rule, antialias); |
255 | box.p1.x <= _cairo_fixed_from_int (clip->path->extents.x) && |
263 | |
- | 264 | _cairo_path_fixed_approximate_clip_extents (path, &extents); |
|
256 | box.p2.x >= _cairo_fixed_from_int (clip->path->extents.x + clip->path->extents.width) && |
265 | if (extents.width == 0 || extents.height == 0) |
Line -... | Line 266... | ||
- | 266 | return _cairo_clip_set_all_clipped (clip); |
|
257 | box.p1.y <= _cairo_fixed_from_int (clip->path->extents.y) && |
267 | |
- | 268 | clip = _cairo_clip_intersect_rectangle (clip, &extents); |
|
- | 269 | if (_cairo_clip_is_all_clipped (clip)) |
|
258 | box.p2.y >= _cairo_fixed_from_int (clip->path->extents.y + clip->path->extents.height)) |
270 | return clip; |
- | 271 | ||
Line -... | Line 272... | ||
- | 272 | clip_path = _cairo_clip_path_create (clip); |
|
259 | { |
273 | if (unlikely (clip_path == NULL)) |
260 | return CAIRO_STATUS_SUCCESS; |
274 | return _cairo_clip_set_all_clipped (clip); |
- | 275 | ||
- | 276 | status = _cairo_path_fixed_init_copy (&clip_path->path, path); |
|
261 | } |
277 | if (unlikely (status)) |
Line 262... | Line 278... | ||
262 | } |
278 | return _cairo_clip_set_all_clipped (clip); |
263 | 279 | ||
Line 264... | Line 280... | ||
264 | clip_path = _cairo_clip_path_create (clip); |
280 | clip_path->fill_rule = fill_rule; |
265 | if (unlikely (clip_path == NULL)) |
281 | clip_path->tolerance = tolerance; |
Line 266... | Line 282... | ||
266 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
282 | clip_path->antialias = antialias; |
267 | 283 | ||
Line 268... | Line 284... | ||
268 | status = _cairo_path_fixed_init_copy (&clip_path->path, path); |
284 | if (clip->region) { |
269 | if (unlikely (status)) { |
285 | cairo_region_destroy (clip->region); |
Line 270... | Line 286... | ||
270 | clip->path = clip->path->prev; |
286 | clip->region = NULL; |
271 | _cairo_clip_path_destroy (clip_path); |
287 | } |
272 | return status; |
- | |
Line -... | Line 288... | ||
- | 288 | ||
273 | } |
289 | clip->is_region = FALSE; |
274 | 290 | return clip; |
|
Line 275... | Line -... | ||
275 | clip_path->extents = extents; |
- | |
276 | clip_path->fill_rule = fill_rule; |
291 | } |
277 | clip_path->tolerance = tolerance; |
292 | |
278 | clip_path->antialias = antialias; |
293 | static cairo_clip_t * |
279 | if (is_box) |
294 | _cairo_clip_intersect_clip_path (cairo_clip_t *clip, |
- | 295 | const cairo_clip_path_t *clip_path) |
|
280 | clip_path->flags |= CAIRO_CLIP_PATH_IS_BOX; |
296 | { |
281 | 297 | if (clip_path->prev) |
|
282 | return CAIRO_STATUS_SUCCESS; |
298 | clip = _cairo_clip_intersect_clip_path (clip, clip_path->prev); |
283 | } |
- | |
Line 284... | Line 299... | ||
284 | 299 | ||
285 | cairo_bool_t |
- | |
286 | _cairo_clip_equal (const cairo_clip_t *clip_a, |
300 | return _cairo_clip_intersect_path (clip, |
287 | const cairo_clip_t *clip_b) |
301 | &clip_path->path, |
288 | { |
302 | clip_path->fill_rule, |
- | 303 | clip_path->tolerance, |
|
Line 289... | Line -... | ||
289 | const cairo_clip_path_t *clip_path_a, *clip_path_b; |
- | |
290 | - | ||
291 | clip_path_a = clip_a->path; |
304 | clip_path->antialias); |
292 | clip_path_b = clip_b->path; |
305 | } |
Line 293... | Line 306... | ||
293 | 306 | ||
294 | while (clip_path_a && clip_path_b) { |
307 | cairo_clip_t * |
295 | if (clip_path_a == clip_path_b) |
308 | _cairo_clip_intersect_clip (cairo_clip_t *clip, |
296 | return TRUE; |
309 | const cairo_clip_t *other) |
297 | 310 | { |
|
298 | if (clip_path_a->fill_rule != clip_path_b->fill_rule) |
- | |
Line 299... | Line 311... | ||
299 | return FALSE; |
311 | if (_cairo_clip_is_all_clipped (clip)) |
300 | 312 | return clip; |
|
301 | if (clip_path_a->tolerance != clip_path_b->tolerance) |
313 | |
302 | return FALSE; |
- | |
Line 303... | Line 314... | ||
303 | 314 | if (other == NULL) |
|
304 | if (clip_path_a->antialias != clip_path_b->antialias) |
315 | return clip; |
305 | return FALSE; |
316 | |
306 | 317 | if (clip == NULL) |
|
307 | if (! _cairo_path_fixed_equal (&clip_path_a->path, &clip_path_b->path)) |
- | |
308 | return FALSE; |
- | |
309 | 318 | return _cairo_clip_copy (other); |
|
310 | clip_path_a = clip_path_a->prev; |
319 | |
311 | clip_path_b = clip_path_b->prev; |
- | |
312 | } |
320 | if (_cairo_clip_is_all_clipped (other)) |
Line 313... | Line 321... | ||
313 | 321 | return _cairo_clip_set_all_clipped (clip); |
|
314 | return clip_path_a == clip_path_b; /* ie both NULL */ |
- | |
Line 315... | Line -... | ||
315 | } |
- | |
316 | - | ||
317 | cairo_status_t |
- | |
318 | _cairo_clip_clip (cairo_clip_t *clip, |
- | |
319 | const cairo_path_fixed_t *path, |
- | |
320 | cairo_fill_rule_t fill_rule, |
- | |
321 | double tolerance, |
322 | |
322 | cairo_antialias_t antialias) |
323 | if (! _cairo_rectangle_intersect (&clip->extents, &other->extents)) |
Line 323... | Line 324... | ||
323 | { |
324 | return _cairo_clip_set_all_clipped (clip); |
324 | if (clip->all_clipped) |
325 | |
325 | return CAIRO_STATUS_SUCCESS; |
- | |
326 | - | ||
327 | /* catch the empty clip path */ |
- | |
328 | if (_cairo_path_fixed_fill_is_empty (path)) { |
326 | if (other->num_boxes) { |
329 | _cairo_clip_set_all_clipped (clip); |
- | |
Line 330... | Line 327... | ||
330 | return CAIRO_STATUS_SUCCESS; |
327 | cairo_boxes_t boxes; |
- | 328 | ||
331 | } |
329 | _cairo_boxes_init_for_array (&boxes, other->boxes, other->num_boxes); |
- | 330 | clip = _cairo_clip_intersect_boxes (clip, &boxes); |
|
332 | 331 | } |
|
Line 333... | Line -... | ||
333 | return _cairo_clip_intersect_path (clip, |
- | |
334 | path, fill_rule, tolerance, |
- | |
335 | antialias); |
- | |
336 | } |
- | |
337 | 332 | ||
338 | cairo_status_t |
- | |
339 | _cairo_clip_rectangle (cairo_clip_t *clip, |
- | |
Line 340... | Line 333... | ||
340 | const cairo_rectangle_int_t *rectangle) |
333 | if (! _cairo_clip_is_all_clipped (clip)) { |
341 | { |
- | |
342 | if (clip->all_clipped) |
- | |
343 | return CAIRO_STATUS_SUCCESS; |
334 | if (other->path) { |
344 | - | ||
345 | if (rectangle->width == 0 || rectangle->height == 0) { |
- | |
346 | _cairo_clip_set_all_clipped (clip); |
- | |
Line 347... | Line -... | ||
347 | return CAIRO_STATUS_SUCCESS; |
- | |
348 | } |
335 | if (clip->path == NULL) |
349 | 336 | clip->path = _cairo_clip_path_reference (other->path); |
|
Line -... | Line 337... | ||
- | 337 | else |
|
- | 338 | clip = _cairo_clip_intersect_clip_path (clip, other->path); |
|
- | 339 | } |
|
- | 340 | } |
|
- | 341 | ||
350 | /* if a smaller clip has already been set, ignore the new path */ |
342 | if (clip->region) { |
- | 343 | cairo_region_destroy (clip->region); |
|
- | 344 | clip->region = NULL; |
|
- | 345 | } |
|
351 | if (clip->path != NULL) { |
346 | clip->is_region = FALSE; |
Line -... | Line 347... | ||
- | 347 | ||
- | 348 | return clip; |
|
- | 349 | } |
|
352 | if (rectangle->x <= clip->path->extents.x && |
350 | |
353 | rectangle->y <= clip->path->extents.y && |
351 | cairo_bool_t |
354 | rectangle->x + rectangle->width >= clip->path->extents.x + clip->path->extents.width && |
352 | _cairo_clip_equal (const cairo_clip_t *clip_a, |
355 | rectangle->y + rectangle->height >= clip->path->extents.y + clip->path->extents.height) |
353 | const cairo_clip_t *clip_b) |
356 | { |
354 | { |
357 | return CAIRO_STATUS_SUCCESS; |
355 | const cairo_clip_path_t *cp_a, *cp_b; |
358 | } |
356 | |
Line 359... | Line 357... | ||
359 | } |
357 | /* are both all-clipped or no-clip? */ |
360 | 358 | if (clip_a == clip_b) |
|
361 | return _cairo_clip_intersect_rectangle (clip, rectangle); |
- | |
362 | } |
359 | return TRUE; |
363 | 360 | ||
364 | static cairo_status_t |
361 | /* or just one of them? */ |
365 | _cairo_clip_path_reapply_clip_path_transform (cairo_clip_t *clip, |
- | |
Line 366... | Line 362... | ||
366 | cairo_clip_path_t *other_path, |
362 | if (clip_a == NULL || clip_b == NULL || |
367 | const cairo_matrix_t *matrix) |
363 | _cairo_clip_is_all_clipped (clip_a) || |
368 | { |
364 | _cairo_clip_is_all_clipped (clip_b)) |
Line 369... | Line 365... | ||
369 | cairo_status_t status; |
365 | { |
370 | cairo_clip_path_t *clip_path; |
366 | return FALSE; |
371 | cairo_bool_t is_empty; |
367 | } |
372 | - | ||
373 | if (other_path->prev != NULL) { |
368 | |
374 | status = _cairo_clip_path_reapply_clip_path_transform (clip, |
- | |
375 | other_path->prev, |
- | |
Line 376... | Line 369... | ||
376 | matrix); |
369 | /* We have a pair of normal clips, check their contents */ |
377 | if (unlikely (status)) |
- | |
378 | return status; |
- | |
Line 379... | Line 370... | ||
379 | } |
370 | |
380 | 371 | if (clip_a->num_boxes != clip_b->num_boxes) |
|
381 | clip_path = _cairo_clip_path_create (clip); |
372 | return FALSE; |
Line 382... | Line -... | ||
382 | if (unlikely (clip_path == NULL)) |
- | |
383 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
384 | - | ||
385 | status = _cairo_path_fixed_init_copy (&clip_path->path, |
- | |
386 | &other_path->path); |
- | |
387 | if (unlikely (status)) { |
- | |
388 | clip->path = clip->path->prev; |
- | |
389 | _cairo_clip_path_destroy (clip_path); |
- | |
390 | return status; |
- | |
391 | } |
- | |
392 | - | ||
393 | _cairo_path_fixed_transform (&clip_path->path, matrix); |
- | |
394 | _cairo_path_fixed_approximate_clip_extents (&clip_path->path, |
- | |
395 | &clip_path->extents); |
- | |
396 | if (clip_path->prev != NULL) { |
- | |
397 | is_empty = _cairo_rectangle_intersect (&clip_path->extents, |
- | |
398 | &clip_path->prev->extents); |
- | |
399 | } |
- | |
400 | - | ||
401 | clip_path->fill_rule = other_path->fill_rule; |
- | |
402 | clip_path->tolerance = other_path->tolerance; |
- | |
403 | clip_path->antialias = other_path->antialias; |
- | |
404 | - | ||
405 | return CAIRO_STATUS_SUCCESS; |
- | |
406 | } |
- | |
407 | - | ||
408 | static cairo_status_t |
- | |
409 | _cairo_clip_path_reapply_clip_path_translate (cairo_clip_t *clip, |
- | |
410 | cairo_clip_path_t *other_path, |
- | |
411 | int tx, int ty) |
- | |
412 | { |
- | |
413 | cairo_status_t status; |
- | |
414 | cairo_clip_path_t *clip_path; |
- | |
415 | - | ||
416 | if (other_path->prev != NULL) { |
- | |
417 | status = _cairo_clip_path_reapply_clip_path_translate (clip, |
- | |
418 | other_path->prev, |
- | |
419 | tx, ty); |
- | |
420 | if (unlikely (status)) |
- | |
421 | return status; |
- | |
422 | } |
- | |
423 | - | ||
424 | clip_path = _cairo_clip_path_create (clip); |
- | |
425 | if (unlikely (clip_path == NULL)) |
- | |
426 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
427 | - | ||
428 | status = _cairo_path_fixed_init_copy (&clip_path->path, |
- | |
429 | &other_path->path); |
- | |
430 | if (unlikely (status)) { |
- | |
431 | clip->path = clip->path->prev; |
- | |
432 | _cairo_clip_path_destroy (clip_path); |
- | |
433 | return status; |
- | |
434 | } |
- | |
435 | - | ||
436 | _cairo_path_fixed_translate (&clip_path->path, |
- | |
437 | _cairo_fixed_from_int (tx), |
- | |
438 | _cairo_fixed_from_int (ty)); |
- | |
439 | - | ||
440 | clip_path->fill_rule = other_path->fill_rule; |
- | |
441 | clip_path->tolerance = other_path->tolerance; |
- | |
442 | clip_path->antialias = other_path->antialias; |
- | |
443 | - | ||
444 | clip_path->flags = other_path->flags; |
- | |
445 | if (other_path->region != NULL) { |
- | |
446 | clip_path->region = cairo_region_copy (other_path->region); |
- | |
447 | status = clip_path->region->status; |
- | |
448 | if (unlikely (status)) { |
- | |
449 | clip->path = clip->path->prev; |
- | |
450 | _cairo_clip_path_destroy (clip_path); |
373 | |
451 | return status; |
374 | if (memcmp (clip_a->boxes, clip_b->boxes, |
Line 452... | Line 375... | ||
452 | } |
375 | sizeof (cairo_box_t) * clip_a->num_boxes)) |
453 | 376 | return FALSE; |
|
454 | cairo_region_translate (clip_path->region, tx, ty); |
- | |
455 | } |
377 | |
456 | clip_path->surface = cairo_surface_reference (other_path->surface); |
378 | cp_a = clip_a->path; |
457 | - | ||
458 | clip_path->extents = other_path->extents; |
- | |
459 | clip_path->extents.x += tx; |
379 | cp_b = clip_b->path; |
Line 460... | Line 380... | ||
460 | clip_path->extents.y += ty; |
380 | while (cp_a && cp_b) { |
461 | - | ||
462 | return CAIRO_STATUS_SUCCESS; |
- | |
463 | } |
- | |
464 | 381 | if (cp_a == cp_b) |
|
465 | cairo_status_t |
- | |
Line 466... | Line -... | ||
466 | _cairo_clip_init_copy_transformed (cairo_clip_t *clip, |
- | |
467 | cairo_clip_t *other, |
- | |
468 | const cairo_matrix_t *matrix) |
382 | return TRUE; |
469 | { |
- | |
470 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
383 | |
Line 471... | Line 384... | ||
471 | int tx, ty; |
384 | /* XXX compare reduced polygons? */ |
472 | 385 | ||
Line 473... | Line 386... | ||
473 | if (other == NULL) { |
386 | if (cp_a->antialias != cp_b->antialias) |
- | 387 | return FALSE; |
|
- | 388 | ||
474 | _cairo_clip_init (clip); |
389 | if (cp_a->tolerance != cp_b->tolerance) |
475 | return CAIRO_STATUS_SUCCESS; |
390 | return FALSE; |
476 | } |
391 | |
Line 477... | Line -... | ||
477 | - | ||
478 | if (other->all_clipped) { |
392 | if (cp_a->fill_rule != cp_b->fill_rule) |
479 | _cairo_clip_init (clip); |
- | |
480 | clip->all_clipped = TRUE; |
- | |
481 | return CAIRO_STATUS_SUCCESS; |
393 | return FALSE; |
482 | } |
- | |
Line 483... | Line -... | ||
483 | - | ||
484 | if (_cairo_matrix_is_identity (matrix)) { |
- | |
485 | _cairo_clip_init_copy (clip, other); |
- | |
486 | return CAIRO_STATUS_SUCCESS; |
394 | |
487 | } |
- | |
488 | 395 | if (! _cairo_path_fixed_equal (&cp_a->path, |
|
Line 489... | Line 396... | ||
489 | if (other->path != NULL) { |
396 | &cp_b->path)) |
490 | _cairo_clip_init (clip); |
397 | return FALSE; |
- | 398 | ||
- | 399 | cp_a = cp_a->prev; |
|
Line 491... | Line 400... | ||
491 | 400 | cp_b = cp_b->prev; |
|
492 | /* if we only need to translate, so we can reuse the caches... */ |
401 | } |
Line 493... | Line 402... | ||
493 | /* XXX we still loose the benefit of constructs when the copy is |
402 | |
494 | * deleted though. Indirect clip_paths? |
403 | return cp_a == NULL && cp_b == NULL; |
- | 404 | } |
|
495 | */ |
405 | |
496 | if (_cairo_matrix_is_integer_translation (matrix, &tx, &ty)) { |
- | |
497 | status = _cairo_clip_path_reapply_clip_path_translate (clip, |
- | |
498 | other->path, |
- | |
499 | tx, ty); |
406 | static cairo_clip_t * |
500 | } else { |
- | |
501 | status = _cairo_clip_path_reapply_clip_path_transform (clip, |
- | |
502 | other->path, |
- | |
503 | matrix); |
- | |
504 | if (clip->path->extents.width == 0 && |
- | |
505 | clip->path->extents.height == 0) |
- | |
506 | { |
- | |
507 | _cairo_clip_set_all_clipped (clip); |
- | |
508 | } |
- | |
509 | } |
- | |
510 | } |
- | |
511 | - | ||
512 | return status; |
- | |
513 | } |
- | |
514 | - | ||
515 | static cairo_status_t |
- | |
516 | _cairo_clip_apply_clip_path (cairo_clip_t *clip, |
- | |
517 | const cairo_clip_path_t *path) |
- | |
518 | { |
- | |
519 | cairo_status_t status; |
- | |
520 | - | ||
521 | if (path->prev != NULL) |
- | |
522 | status = _cairo_clip_apply_clip_path (clip, path->prev); |
- | |
523 | - | ||
524 | return _cairo_clip_intersect_path (clip, |
- | |
525 | &path->path, |
- | |
526 | path->fill_rule, |
- | |
527 | path->tolerance, |
- | |
528 | path->antialias); |
- | |
529 | } |
- | |
530 | - | ||
531 | cairo_status_t |
- | |
532 | _cairo_clip_apply_clip (cairo_clip_t *clip, |
- | |
533 | const cairo_clip_t *other) |
- | |
534 | { |
- | |
535 | cairo_status_t status; |
- | |
536 | - | ||
537 | if (clip->all_clipped) |
- | |
538 | return CAIRO_STATUS_SUCCESS; |
- | |
539 | - | ||
540 | if (other->all_clipped) { |
- | |
541 | _cairo_clip_set_all_clipped (clip); |
- | |
542 | return CAIRO_STATUS_SUCCESS; |
- | |
543 | } |
- | |
544 | - | ||
545 | status = CAIRO_STATUS_SUCCESS; |
- | |
546 | if (other->path != NULL) |
- | |
Line -... | Line 407... | ||
- | 407 | _cairo_clip_path_copy_with_translation (cairo_clip_t *clip, |
|
547 | status = _cairo_clip_apply_clip_path (clip, other->path); |
408 | cairo_clip_path_t *other_path, |
548 | 409 | int fx, int fy) |
|
Line 549... | Line 410... | ||
549 | return status; |
410 | { |
550 | } |
- | |
551 | - | ||
552 | static inline cairo_bool_t |
- | |
553 | _clip_paths_are_rectilinear (cairo_clip_path_t *clip_path) |
- | |
554 | { |
411 | cairo_status_t status; |
555 | while (clip_path != NULL) { |
412 | cairo_clip_path_t *clip_path; |
Line 556... | Line -... | ||
556 | if (! clip_path->path.is_rectilinear) |
- | |
557 | return FALSE; |
- | |
558 | - | ||
559 | clip_path = clip_path->prev; |
- | |
560 | } |
- | |
561 | - | ||
562 | return TRUE; |
- | |
563 | } |
- | |
564 | - | ||
565 | static cairo_int_status_t |
- | |
566 | _cairo_clip_path_to_region_geometric (cairo_clip_path_t *clip_path) |
- | |
567 | { |
- | |
568 | cairo_traps_t traps; |
- | |
569 | cairo_box_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (cairo_box_t)]; |
- | |
570 | cairo_box_t *boxes = stack_boxes; |
- | |
571 | cairo_status_t status; |
- | |
572 | int n; |
- | |
573 | - | ||
574 | /* If we have nothing to intersect with this path, then it cannot |
- | |
575 | * magically be reduced into a region. |
- | |
576 | */ |
- | |
577 | if (clip_path->prev == NULL) |
- | |
578 | goto UNSUPPORTED; |
- | |
579 | - | ||
580 | /* Start simple... Intersect some boxes with an arbitrary path. */ |
- | |
581 | if (! clip_path->path.is_rectilinear) |
- | |
582 | goto UNSUPPORTED; |
- | |
583 | if (clip_path->prev->prev != NULL) |
- | |
584 | goto UNSUPPORTED; |
413 | |
585 | - | ||
586 | _cairo_traps_init (&traps); |
- | |
587 | _cairo_box_from_rectangle (&boxes[0], &clip_path->extents); |
- | |
588 | _cairo_traps_limit (&traps, boxes, 1); |
- | |
589 | - | ||
590 | status = _cairo_path_fixed_fill_rectilinear_to_traps (&clip_path->path, |
- | |
591 | clip_path->fill_rule, |
- | |
592 | &traps); |
- | |
593 | if (unlikely (_cairo_status_is_error (status))) |
- | |
594 | return status; |
- | |
595 | if (status == CAIRO_INT_STATUS_UNSUPPORTED) |
- | |
596 | goto UNSUPPORTED; |
- | |
597 | - | ||
598 | if (traps.num_traps > ARRAY_LENGTH (stack_boxes)) { |
- | |
599 | boxes = _cairo_malloc_ab (traps.num_traps, sizeof (cairo_box_t)); |
- | |
600 | if (unlikely (boxes == NULL)) |
- | |
601 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
602 | } |
- | |
603 | 414 | if (other_path->prev != NULL) |
|
604 | for (n = 0; n < traps.num_traps; n++) { |
415 | clip = _cairo_clip_path_copy_with_translation (clip, other_path->prev, |
Line 605... | Line -... | ||
605 | boxes[n].p1.x = traps.traps[n].left.p1.x; |
- | |
606 | boxes[n].p1.y = traps.traps[n].top; |
416 | fx, fy); |
607 | boxes[n].p2.x = traps.traps[n].right.p1.x; |
417 | if (_cairo_clip_is_all_clipped (clip)) |
608 | boxes[n].p2.y = traps.traps[n].bottom; |
418 | return clip; |
609 | } |
- | |
610 | - | ||
611 | _cairo_traps_clear (&traps); |
- | |
612 | _cairo_traps_limit (&traps, boxes, n); |
- | |
613 | status = _cairo_path_fixed_fill_to_traps (&clip_path->prev->path, |
- | |
614 | clip_path->prev->fill_rule, |
- | |
615 | clip_path->prev->tolerance, |
- | |
616 | &traps); |
- | |
617 | if (boxes != stack_boxes) |
- | |
618 | free (boxes); |
- | |
619 | - | ||
620 | if (unlikely (status)) |
- | |
621 | return status; |
- | |
622 | - | ||
623 | status = _cairo_traps_extract_region (&traps, &clip_path->region); |
- | |
624 | _cairo_traps_fini (&traps); |
- | |
625 | - | ||
626 | if (status == CAIRO_INT_STATUS_UNSUPPORTED) |
- | |
627 | goto UNSUPPORTED; |
- | |
628 | if (unlikely (status)) |
- | |
629 | return status; |
- | |
630 | - | ||
631 | clip_path->flags |= CAIRO_CLIP_PATH_HAS_REGION; |
- | |
632 | return CAIRO_STATUS_SUCCESS; |
- | |
633 | - | ||
634 | UNSUPPORTED: |
- | |
635 | clip_path->flags |= CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED; |
- | |
636 | return CAIRO_INT_STATUS_UNSUPPORTED; |
- | |
637 | } |
- | |
638 | - | ||
639 | static cairo_int_status_t |
- | |
640 | _cairo_clip_path_to_region (cairo_clip_path_t *clip_path) |
- | |
641 | { |
- | |
642 | cairo_int_status_t status; |
- | |
643 | cairo_region_t *prev = NULL; |
- | |
644 | - | ||
645 | if (clip_path->flags & |
- | |
646 | (CAIRO_CLIP_PATH_HAS_REGION | |
- | |
647 | CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED)) |
- | |
648 | { |
- | |
649 | return clip_path->flags & CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED ? |
- | |
650 | CAIRO_INT_STATUS_UNSUPPORTED : |
- | |
651 | CAIRO_STATUS_SUCCESS; |
- | |
652 | } |
- | |
653 | - | ||
654 | if (! clip_path->path.maybe_fill_region) |
- | |
655 | return _cairo_clip_path_to_region_geometric (clip_path); |
- | |
656 | - | ||
657 | /* first retrieve the region for our antecedents */ |
- | |
658 | if (clip_path->prev != NULL) { |
- | |
659 | status = _cairo_clip_path_to_region (clip_path->prev); |
- | |
660 | if (status) { |
- | |
661 | if (status == CAIRO_INT_STATUS_UNSUPPORTED) |
- | |
662 | return _cairo_clip_path_to_region_geometric (clip_path); |
- | |
663 | - | ||
664 | return status; |
- | |
665 | } |
- | |
666 | - | ||
667 | prev = clip_path->prev->region; |
- | |
668 | } |
- | |
669 | - | ||
670 | /* now extract the region for ourselves */ |
- | |
671 | clip_path->region = |
- | |
672 | _cairo_path_fixed_fill_rectilinear_to_region (&clip_path->path, |
- | |
673 | clip_path->fill_rule, |
- | |
674 | &clip_path->extents); |
- | |
675 | assert (clip_path->region != NULL); |
- | |
676 | - | ||
677 | status = clip_path->region->status; |
- | |
678 | if (unlikely (status)) |
- | |
679 | return status; |
- | |
680 | - | ||
681 | if (prev != NULL) { |
- | |
682 | status = cairo_region_intersect (clip_path->region, prev); |
- | |
683 | if (unlikely (status)) |
- | |
684 | return status; |
- | |
685 | } |
- | |
686 | - | ||
687 | clip_path->flags |= CAIRO_CLIP_PATH_HAS_REGION; |
- | |
688 | return CAIRO_STATUS_SUCCESS; |
- | |
689 | } |
- | |
690 | - | ||
691 | static inline int |
- | |
692 | pot (int v) |
- | |
693 | { |
- | |
694 | v--; |
- | |
Line 695... | Line 419... | ||
695 | v |= v >> 1; |
419 | |
696 | v |= v >> 2; |
420 | clip_path = _cairo_clip_path_create (clip); |
Line 697... | Line 421... | ||
697 | v |= v >> 4; |
421 | if (unlikely (clip_path == NULL)) |
698 | v |= v >> 8; |
422 | return _cairo_clip_set_all_clipped (clip); |
699 | v |= v >> 16; |
- | |
700 | v++; |
423 | |
701 | return v; |
- | |
702 | } |
- | |
703 | 424 | status = _cairo_path_fixed_init_copy (&clip_path->path, |
|
704 | /* XXX there is likely a faster method! ;-) */ |
- | |
705 | static cairo_status_t |
- | |
706 | _region_clip_to_boxes (const cairo_region_t *region, |
425 | &other_path->path); |
707 | cairo_box_t **boxes, |
- | |
708 | int *num_boxes, |
- | |
709 | int *size_boxes) |
- | |
710 | { |
- | |
711 | cairo_traps_t traps; |
- | |
712 | cairo_status_t status; |
- | |
713 | int n, num_rects; |
- | |
714 | - | ||
715 | _cairo_traps_init (&traps); |
- | |
716 | _cairo_traps_limit (&traps, *boxes, *num_boxes); |
- | |
717 | traps.is_rectilinear = TRUE; |
426 | if (unlikely (status)) |
718 | traps.is_rectangular = TRUE; |
- | |
719 | - | ||
720 | num_rects = cairo_region_num_rectangles (region); |
- | |
721 | for (n = 0; n < num_rects; n++) { |
- | |
722 | cairo_rectangle_int_t rect; |
- | |
723 | cairo_point_t p1, p2; |
- | |
724 | - | ||
725 | cairo_region_get_rectangle (region, n, &rect); |
- | |
726 | - | ||
727 | p1.x = _cairo_fixed_from_int (rect.x); |
- | |
728 | p1.y = _cairo_fixed_from_int (rect.y); |
- | |
729 | p2.x = _cairo_fixed_from_int (rect.x + rect.width); |
- | |
730 | p2.y = _cairo_fixed_from_int (rect.y + rect.height); |
- | |
731 | - | ||
732 | status = _cairo_traps_tessellate_rectangle (&traps, &p1, &p2); |
- | |
733 | if (unlikely (status)) |
- | |
734 | goto CLEANUP; |
427 | return _cairo_clip_set_all_clipped (clip); |
Line 735... | Line -... | ||
735 | } |
- | |
736 | 428 | ||
737 | status = _cairo_bentley_ottmann_tessellate_rectangular_traps (&traps, CAIRO_FILL_RULE_WINDING); |
- | |
738 | if (unlikely (status)) |
- | |
739 | goto CLEANUP; |
- | |
740 | 429 | _cairo_path_fixed_translate (&clip_path->path, fx, fy); |
|
741 | n = *size_boxes; |
- | |
742 | if (n < 0) |
- | |
743 | n = -n; |
- | |
744 | - | ||
745 | if (traps.num_traps > n) { |
- | |
746 | cairo_box_t *new_boxes; |
- | |
747 | 430 | ||
748 | new_boxes = _cairo_malloc_ab (traps.num_traps, sizeof (cairo_box_t)); |
- | |
749 | if (unlikely (new_boxes == NULL)) { |
- | |
750 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
751 | goto CLEANUP; |
- | |
752 | } |
- | |
753 | - | ||
754 | if (*size_boxes > 0) |
- | |
755 | free (*boxes); |
- | |
756 | - | ||
Line -... | Line 431... | ||
- | 431 | clip_path->fill_rule = other_path->fill_rule; |
|
757 | *boxes = new_boxes; |
432 | clip_path->tolerance = other_path->tolerance; |
758 | *size_boxes = traps.num_traps; |
433 | clip_path->antialias = other_path->antialias; |
759 | } |
434 | |
760 | 435 | return clip; |
|
761 | for (n = 0; n < traps.num_traps; n++) { |
436 | } |
762 | (*boxes)[n].p1.x = traps.traps[n].left.p1.x; |
437 | |
763 | (*boxes)[n].p1.y = traps.traps[n].top; |
- | |
764 | (*boxes)[n].p2.x = traps.traps[n].right.p1.x; |
438 | cairo_clip_t * |
765 | (*boxes)[n].p2.y = traps.traps[n].bottom; |
439 | _cairo_clip_translate (cairo_clip_t *clip, int tx, int ty) |
Line 766... | Line -... | ||
766 | } |
- | |
767 | *num_boxes = n; |
- | |
768 | - | ||
769 | CLEANUP: |
- | |
770 | _cairo_traps_fini (&traps); |
440 | { |
771 | 441 | int fx, fy, i; |
|
Line 772... | Line 442... | ||
772 | return status; |
442 | cairo_clip_path_t *clip_path; |
773 | } |
443 | |
774 | 444 | if (clip == NULL || _cairo_clip_is_all_clipped (clip)) |
|
775 | static cairo_status_t |
445 | return clip; |
776 | _rectilinear_clip_to_boxes (const cairo_path_fixed_t *path, |
446 | |
777 | cairo_fill_rule_t fill_rule, |
- | |
778 | cairo_box_t **boxes, |
- | |
779 | int *num_boxes, |
447 | if (tx == 0 && ty == 0) |
780 | int *size_boxes) |
- | |
781 | { |
- | |
782 | cairo_polygon_t polygon; |
- | |
783 | cairo_traps_t traps; |
- | |
784 | cairo_status_t status; |
- | |
785 | - | ||
786 | _cairo_traps_init (&traps); |
- | |
787 | _cairo_traps_limit (&traps, *boxes, *num_boxes); |
- | |
788 | - | ||
789 | _cairo_polygon_init (&polygon); |
- | |
790 | _cairo_polygon_limit (&polygon, *boxes, *num_boxes); |
- | |
Line 791... | Line 448... | ||
791 | 448 | return clip; |
|
792 | status = _cairo_path_fixed_fill_rectilinear_to_traps (path, |
- | |
793 | fill_rule, |
- | |
794 | &traps); |
449 | |
795 | if (unlikely (_cairo_status_is_error (status))) |
450 | fx = _cairo_fixed_from_int (tx); |
- | 451 | fy = _cairo_fixed_from_int (ty); |
|
Line 796... | Line 452... | ||
796 | goto CLEANUP; |
452 | |
797 | if (status == CAIRO_STATUS_SUCCESS) |
453 | for (i = 0; i < clip->num_boxes; i++) { |
798 | goto BOXES; |
- | |
799 | - | ||
800 | /* tolerance will be ignored as the path is rectilinear */ |
- | |
801 | status = _cairo_path_fixed_fill_to_polygon (path, 0., &polygon); |
- | |
Line 802... | Line -... | ||
802 | if (unlikely (status)) |
- | |
803 | goto CLEANUP; |
454 | clip->boxes[i].p1.x += fx; |
804 | - | ||
Line 805... | Line -... | ||
805 | if (polygon.num_edges == 0) { |
- | |
806 | *num_boxes = 0; |
455 | clip->boxes[i].p2.x += fx; |
807 | } else { |
- | |
808 | status = _cairo_bentley_ottmann_tessellate_rectilinear_polygon (&traps, |
- | |
809 | &polygon, |
- | |
810 | fill_rule); |
- | |
811 | if (likely (status == CAIRO_STATUS_SUCCESS)) { |
- | |
812 | int i; |
456 | clip->boxes[i].p1.y += fy; |
813 | - | ||
814 | BOXES: |
457 | clip->boxes[i].p2.y += fy; |
815 | i = *size_boxes; |
458 | } |
816 | if (i < 0) |
- | |
817 | i = -i; |
- | |
818 | - | ||
819 | if (traps.num_traps > i) { |
- | |
820 | cairo_box_t *new_boxes; |
- | |
821 | int new_size; |
- | |
822 | - | ||
823 | new_size = pot (traps.num_traps); |
- | |
824 | new_boxes = _cairo_malloc_ab (new_size, sizeof (cairo_box_t)); |
- | |
825 | if (unlikely (new_boxes == NULL)) { |
459 | |
826 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
827 | goto CLEANUP; |
- | |
828 | } |
- | |
829 | - | ||
830 | if (*size_boxes > 0) |
460 | clip->extents.x += tx; |
831 | free (*boxes); |
- | |
Line 832... | Line -... | ||
832 | - | ||
833 | *boxes = new_boxes; |
461 | clip->extents.y += ty; |
834 | *size_boxes = new_size; |
- | |
- | 462 | ||
Line 835... | Line 463... | ||
835 | } |
463 | if (clip->path == NULL) |
836 | - | ||
837 | for (i = 0; i < traps.num_traps; i++) { |
464 | return clip; |
- | 465 | ||
838 | (*boxes)[i].p1.x = traps.traps[i].left.p1.x; |
466 | clip_path = clip->path; |
Line 839... | Line 467... | ||
839 | (*boxes)[i].p1.y = traps.traps[i].top; |
467 | clip->path = NULL; |
840 | (*boxes)[i].p2.x = traps.traps[i].right.p1.x; |
468 | clip = _cairo_clip_path_copy_with_translation (clip, clip_path, fx, fy); |
841 | (*boxes)[i].p2.y = traps.traps[i].bottom; |
- | |
842 | } |
- | |
Line 843... | Line 469... | ||
843 | *num_boxes = i; |
469 | _cairo_clip_path_destroy (clip_path); |
844 | } |
470 | |
845 | } |
- | |
Line 846... | Line -... | ||
846 | - | ||
847 | CLEANUP: |
- | |
848 | _cairo_polygon_fini (&polygon); |
- | |
849 | _cairo_traps_fini (&traps); |
- | |
850 | - | ||
851 | return status; |
471 | return clip; |
852 | } |
- | |
853 | - | ||
854 | static cairo_int_status_t |
- | |
Line 855... | Line 472... | ||
855 | _cairo_clip_path_to_boxes (cairo_clip_path_t *clip_path, |
472 | } |
856 | cairo_box_t **boxes, |
473 | |
857 | int *count) |
- | |
- | 474 | static cairo_status_t |
|
Line 858... | Line -... | ||
858 | { |
- | |
859 | int size = -*count; |
475 | _cairo_path_fixed_add_box (cairo_path_fixed_t *path, |
860 | int num_boxes = 0; |
- | |
861 | cairo_status_t status; |
- | |
862 | - | ||
863 | if (clip_path->region != NULL) { |
476 | const cairo_box_t *box) |
864 | int num_rects, n; |
477 | { |
865 | - | ||
866 | num_rects = cairo_region_num_rectangles (clip_path->region); |
- | |
867 | if (num_rects > -size) { |
- | |
Line 868... | Line -... | ||
868 | cairo_box_t *new_boxes; |
- | |
869 | - | ||
870 | new_boxes = _cairo_malloc_ab (num_rects, sizeof (cairo_box_t)); |
- | |
871 | if (unlikely (new_boxes == NULL)) |
- | |
872 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
873 | - | ||
874 | *boxes = new_boxes; |
- | |
875 | } |
- | |
876 | - | ||
877 | for (n = 0; n < num_rects; n++) { |
- | |
878 | cairo_rectangle_int_t rect; |
- | |
879 | - | ||
880 | cairo_region_get_rectangle (clip_path->region, n, &rect); |
- | |
881 | (*boxes)[n].p1.x = _cairo_fixed_from_int (rect.x); |
- | |
882 | (*boxes)[n].p1.y = _cairo_fixed_from_int (rect.y); |
- | |
883 | (*boxes)[n].p2.x = _cairo_fixed_from_int (rect.x + rect.width); |
- | |
884 | (*boxes)[n].p2.y = _cairo_fixed_from_int (rect.y + rect.height); |
- | |
885 | } |
- | |
886 | - | ||
887 | *count = num_rects; |
- | |
888 | return CAIRO_STATUS_SUCCESS; |
- | |
889 | } |
- | |
890 | - | ||
891 | /* keep it simple at first */ |
- | |
892 | if (! _clip_paths_are_rectilinear (clip_path)) |
- | |
893 | return CAIRO_INT_STATUS_UNSUPPORTED; |
- | |
894 | - | ||
895 | assert (-size >= 1); |
- | |
896 | if (_cairo_path_fixed_is_box (&clip_path->path, *boxes)) { |
- | |
897 | num_boxes = 1; |
- | |
898 | } else { |
- | |
899 | status = _rectilinear_clip_to_boxes (&clip_path->path, |
- | |
900 | clip_path->fill_rule, |
478 | cairo_status_t status; |
901 | boxes, &num_boxes, &size); |
479 | |
902 | if (unlikely (status)) |
- | |
903 | return status; |
480 | status = _cairo_path_fixed_move_to (path, box->p1.x, box->p1.y); |
904 | } |
- | |
905 | - | ||
906 | while (num_boxes > 0 && (clip_path = clip_path->prev) != NULL) { |
- | |
907 | cairo_box_t box; |
- | |
908 | - | ||
909 | if (clip_path->region != NULL) { |
- | |
910 | status = _region_clip_to_boxes (clip_path->region, |
481 | if (unlikely (status)) |
911 | boxes, &num_boxes, &size); |
- | |
912 | if (unlikely (status)) |
- | |
913 | return status; |
- | |
914 | - | ||
Line 915... | Line -... | ||
915 | break; |
- | |
916 | } else if (_cairo_path_fixed_is_box (&clip_path->path, &box)) { |
482 | return status; |
917 | int i, j; |
- | |
918 | - | ||
919 | for (i = j = 0; i < num_boxes; i++) { |
- | |
920 | if (j != i) |
- | |
921 | (*boxes)[j] = (*boxes)[i]; |
- | |
922 | - | ||
923 | if (box.p1.x > (*boxes)[j].p1.x) |
- | |
924 | (*boxes)[j].p1.x = box.p1.x; |
- | |
925 | if (box.p2.x < (*boxes)[j].p2.x) |
- | |
926 | (*boxes)[j].p2.x = box.p2.x; |
- | |
927 | - | ||
928 | if (box.p1.y > (*boxes)[j].p1.y) |
- | |
929 | (*boxes)[j].p1.y = box.p1.y; |
- | |
930 | if (box.p2.y < (*boxes)[j].p2.y) |
- | |
931 | (*boxes)[j].p2.y = box.p2.y; |
- | |
932 | 483 | ||
Line 933... | Line 484... | ||
933 | j += (*boxes)[j].p2.x > (*boxes)[j].p1.x && |
484 | status = _cairo_path_fixed_line_to (path, box->p2.x, box->p1.y); |
934 | (*boxes)[j].p2.y > (*boxes)[j].p1.y; |
485 | if (unlikely (status)) |
935 | } |
- | |
Line 936... | Line 486... | ||
936 | 486 | return status; |
|
937 | num_boxes = j; |
- | |
938 | } else { |
- | |
939 | status = _rectilinear_clip_to_boxes (&clip_path->path, |
- | |
940 | clip_path->fill_rule, |
- | |
941 | boxes, &num_boxes, &size); |
- | |
942 | if (unlikely (status)) |
- | |
943 | return status; |
- | |
944 | } |
- | |
945 | } |
- | |
946 | - | ||
947 | *count = num_boxes; |
487 | |
948 | return CAIRO_STATUS_SUCCESS; |
- | |
949 | } |
- | |
950 | - | ||
951 | static cairo_surface_t * |
- | |
952 | _cairo_clip_path_get_surface (cairo_clip_path_t *clip_path, |
- | |
953 | cairo_surface_t *target, |
- | |
954 | int *tx, int *ty) |
- | |
955 | { |
- | |
956 | const cairo_rectangle_int_t *clip_extents = &clip_path->extents; |
- | |
957 | cairo_bool_t need_translate; |
- | |
958 | cairo_surface_t *surface; |
- | |
959 | cairo_clip_path_t *prev; |
- | |
960 | cairo_status_t status; |
- | |
961 | - | ||
962 | while (clip_path->prev != NULL && |
- | |
963 | clip_path->flags & CAIRO_CLIP_PATH_IS_BOX && |
- | |
964 | clip_path->path.maybe_fill_region) |
488 | status = _cairo_path_fixed_line_to (path, box->p2.x, box->p2.y); |
Line 965... | Line -... | ||
965 | { |
- | |
966 | clip_path = clip_path->prev; |
489 | if (unlikely (status)) |
967 | } |
- | |
968 | - | ||
- | 490 | return status; |
|
969 | clip_extents = &clip_path->extents; |
491 | |
970 | if (clip_path->surface != NULL && |
- | |
971 | clip_path->surface->backend == target->backend) |
492 | status = _cairo_path_fixed_line_to (path, box->p1.x, box->p2.y); |
972 | { |
493 | if (unlikely (status)) |
Line 973... | Line 494... | ||
973 | *tx = clip_extents->x; |
494 | return status; |
974 | *ty = clip_extents->y; |
- | |
975 | return clip_path->surface; |
495 | |
976 | } |
- | |
Line 977... | Line -... | ||
977 | - | ||
978 | surface = _cairo_surface_create_similar_scratch (target, |
- | |
979 | CAIRO_CONTENT_ALPHA, |
- | |
980 | clip_extents->width, |
- | |
981 | clip_extents->height); |
496 | return _cairo_path_fixed_close_path (path); |
982 | if (surface == NULL) { |
497 | } |
983 | surface = cairo_image_surface_create (CAIRO_FORMAT_A8, |
- | |
984 | clip_extents->width, |
- | |
985 | clip_extents->height); |
- | |
986 | } |
- | |
Line 987... | Line 498... | ||
987 | if (unlikely (surface->status)) |
498 | |
988 | return surface; |
499 | static cairo_status_t |
- | 500 | _cairo_path_fixed_init_from_boxes (cairo_path_fixed_t *path, |
|
Line 989... | Line 501... | ||
989 | 501 | const cairo_boxes_t *boxes) |
|
990 | need_translate = clip_extents->x | clip_extents->y; |
- | |
- | 502 | { |
|
Line -... | Line 503... | ||
- | 503 | cairo_status_t status; |
|
- | 504 | const struct _cairo_boxes_chunk *chunk; |
|
991 | if (clip_path->flags & CAIRO_CLIP_PATH_IS_BOX && |
505 | int i; |
- | 506 | ||
- | 507 | _cairo_path_fixed_init (path); |
|
- | 508 | if (boxes->num_boxes == 0) |
|
- | 509 | return CAIRO_STATUS_SUCCESS; |
|
992 | clip_path->path.maybe_fill_region) |
510 | |
Line 993... | Line -... | ||
993 | { |
- | |
994 | status = _cairo_surface_paint (surface, |
511 | for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { |
995 | CAIRO_OPERATOR_SOURCE, |
512 | for (i = 0; i < chunk->count; i++) { |
996 | &_cairo_pattern_white.base, |
513 | status = _cairo_path_fixed_add_box (path, &chunk->base[i]); |
997 | NULL); |
- | |
998 | if (unlikely (status)) |
- | |
999 | goto BAIL; |
514 | if (unlikely (status)) { |
1000 | } |
515 | _cairo_path_fixed_fini (path); |
1001 | else |
516 | return status; |
1002 | { |
- | |
1003 | status = _cairo_surface_paint (surface, |
- | |
1004 | CAIRO_OPERATOR_CLEAR, |
- | |
1005 | &_cairo_pattern_clear.base, |
- | |
1006 | NULL); |
- | |
1007 | if (unlikely (status)) |
- | |
1008 | goto BAIL; |
- | |
1009 | - | ||
1010 | if (need_translate) { |
- | |
1011 | _cairo_path_fixed_translate (&clip_path->path, |
- | |
1012 | _cairo_fixed_from_int (-clip_extents->x), |
517 | } |
1013 | _cairo_fixed_from_int (-clip_extents->y)); |
- | |
1014 | } |
- | |
1015 | status = _cairo_surface_fill (surface, |
- | |
1016 | CAIRO_OPERATOR_ADD, |
- | |
1017 | &_cairo_pattern_white.base, |
- | |
1018 | &clip_path->path, |
- | |
1019 | clip_path->fill_rule, |
518 | } |
Line 1020... | Line -... | ||
1020 | clip_path->tolerance, |
- | |
1021 | clip_path->antialias, |
519 | } |
1022 | NULL); |
- | |
1023 | if (need_translate) { |
- | |
1024 | _cairo_path_fixed_translate (&clip_path->path, |
520 | |
1025 | _cairo_fixed_from_int (clip_extents->x), |
- | |
1026 | _cairo_fixed_from_int (clip_extents->y)); |
- | |
1027 | } |
521 | return CAIRO_STATUS_SUCCESS; |
Line 1028... | Line -... | ||
1028 | - | ||
1029 | if (unlikely (status)) |
522 | } |
1030 | goto BAIL; |
- | |
1031 | } |
- | |
1032 | - | ||
1033 | prev = clip_path->prev; |
523 | |
1034 | while (prev != NULL) { |
- | |
1035 | if (prev->flags & CAIRO_CLIP_PATH_IS_BOX && |
- | |
Line 1036... | Line 524... | ||
1036 | prev->path.maybe_fill_region) |
524 | static cairo_clip_t * |
1037 | { |
525 | _cairo_clip_intersect_clip_path_transformed (cairo_clip_t *clip, |
Line 1038... | Line 526... | ||
1038 | /* a simple box only affects the extents */ |
526 | const cairo_clip_path_t *clip_path, |
1039 | } |
527 | const cairo_matrix_t *m) |
1040 | else if (prev->path.is_rectilinear || |
528 | { |
1041 | prev->surface == NULL || |
529 | cairo_path_fixed_t path; |
1042 | prev->surface->backend != target->backend) |
530 | |
Line 1043... | Line -... | ||
1043 | { |
- | |
1044 | if (need_translate) { |
- | |
1045 | _cairo_path_fixed_translate (&prev->path, |
- | |
1046 | _cairo_fixed_from_int (-clip_extents->x), |
531 | if (clip_path->prev) |
1047 | _cairo_fixed_from_int (-clip_extents->y)); |
532 | clip = _cairo_clip_intersect_clip_path_transformed (clip, |
1048 | } |
533 | clip_path->prev, |
Line 1049... | Line 534... | ||
1049 | status = _cairo_surface_fill (surface, |
534 | m); |
1050 | CAIRO_OPERATOR_IN, |
535 | |
1051 | &_cairo_pattern_white.base, |
536 | if (_cairo_path_fixed_init_copy (&path, &clip_path->path)) |
1052 | &prev->path, |
537 | return _cairo_clip_set_all_clipped (clip); |
Line 1053... | Line 538... | ||
1053 | prev->fill_rule, |
538 | |
1054 | prev->tolerance, |
539 | _cairo_path_fixed_transform (&path, m); |
1055 | prev->antialias, |
540 | |
1056 | NULL); |
541 | clip = _cairo_clip_intersect_path (clip, |
Line 1057... | Line 542... | ||
1057 | if (need_translate) { |
542 | &path, |
1058 | _cairo_path_fixed_translate (&prev->path, |
543 | clip_path->fill_rule, |
1059 | _cairo_fixed_from_int (clip_extents->x), |
544 | clip_path->tolerance, |
1060 | _cairo_fixed_from_int (clip_extents->y)); |
545 | clip_path->antialias); |
Line 1061... | Line -... | ||
1061 | } |
- | |
1062 | - | ||
1063 | if (unlikely (status)) |
- | |
1064 | goto BAIL; |
- | |
1065 | } |
- | |
1066 | else |
546 | _cairo_path_fixed_fini (&path); |
- | 547 | ||
- | 548 | return clip; |
|
- | 549 | } |
|
- | 550 | ||
- | 551 | cairo_clip_t * |
|
- | 552 | _cairo_clip_transform (cairo_clip_t *clip, const cairo_matrix_t *m) |
|
- | 553 | { |
|
- | 554 | cairo_clip_t *copy; |
|
- | 555 | ||
- | 556 | if (clip == NULL || _cairo_clip_is_all_clipped (clip)) |
|
- | 557 | return clip; |
|
- | 558 | ||
- | 559 | if (_cairo_matrix_is_translation (m)) |
|
Line 1067... | Line 560... | ||
1067 | { |
560 | return _cairo_clip_translate (clip, m->x0, m->y0); |
- | 561 | ||
1068 | cairo_surface_pattern_t pattern; |
562 | copy = _cairo_clip_create (); |
1069 | cairo_surface_t *prev_surface; |
563 | |
1070 | int prev_tx, prev_ty; |
- | |
1071 | - | ||
1072 | prev_surface = _cairo_clip_path_get_surface (prev, target, &prev_tx, &prev_ty); |
564 | if (clip->num_boxes) { |
1073 | status = prev_surface->status; |
565 | cairo_path_fixed_t path; |
1074 | if (unlikely (status)) |
566 | cairo_boxes_t boxes; |
1075 | goto BAIL; |
567 | |
1076 | 568 | _cairo_boxes_init_for_array (&boxes, clip->boxes, clip->num_boxes); |
|
1077 | _cairo_pattern_init_for_surface (&pattern, prev_surface); |
569 | _cairo_path_fixed_init_from_boxes (&path, &boxes); |
1078 | pattern.base.filter = CAIRO_FILTER_NEAREST; |
570 | _cairo_path_fixed_transform (&path, m); |
1079 | cairo_matrix_init_translate (&pattern.base.matrix, |
- | |
1080 | clip_extents->x - prev_tx, |
- | |
1081 | clip_extents->y - prev_ty); |
- | |
1082 | status = _cairo_surface_paint (surface, |
- | |
1083 | CAIRO_OPERATOR_IN, |
- | |
1084 | &pattern.base, |
- | |
1085 | NULL); |
- | |
1086 | _cairo_pattern_fini (&pattern.base); |
- | |
1087 | - | ||
1088 | if (unlikely (status)) |
- | |
1089 | goto BAIL; |
- | |
1090 | - | ||
1091 | break; |
- | |
1092 | } |
- | |
1093 | - | ||
1094 | prev = prev->prev; |
- | |
1095 | } |
- | |
1096 | - | ||
1097 | *tx = clip_extents->x; |
- | |
1098 | *ty = clip_extents->y; |
- | |
1099 | cairo_surface_destroy (clip_path->surface); |
- | |
1100 | return clip_path->surface = surface; |
- | |
1101 | - | ||
1102 | BAIL: |
- | |
1103 | cairo_surface_destroy (surface); |
- | |
1104 | return _cairo_surface_create_in_error (status); |
- | |
1105 | } |
- | |
1106 | - | ||
1107 | cairo_bool_t |
- | |
1108 | _cairo_clip_contains_rectangle (cairo_clip_t *clip, |
- | |
1109 | const cairo_rectangle_int_t *rect) |
- | |
1110 | { |
- | |
1111 | cairo_clip_path_t *clip_path; |
- | |
1112 | - | ||
1113 | if (clip == NULL) |
- | |
1114 | return FALSE; |
- | |
1115 | - | ||
1116 | clip_path = clip->path; |
- | |
1117 | if (clip_path->extents.x > rect->x || |
- | |
1118 | clip_path->extents.y > rect->y || |
- | |
1119 | clip_path->extents.x + clip_path->extents.width < rect->x + rect->width || |
- | |
1120 | clip_path->extents.y + clip_path->extents.height < rect->y + rect->height) |
- | |
1121 | { |
- | |
1122 | return FALSE; |
- | |
1123 | } |
- | |
1124 | - | ||
1125 | do { |
- | |
1126 | cairo_box_t box; |
- | |
1127 | - | ||
1128 | if ((clip_path->flags & CAIRO_CLIP_PATH_IS_BOX) == 0) |
- | |
1129 | return FALSE; |
- | |
1130 | - | ||
1131 | if (! _cairo_path_fixed_is_box (&clip_path->path, &box)) |
- | |
1132 | return FALSE; |
- | |
1133 | - | ||
1134 | if (box.p1.x > _cairo_fixed_from_int (rect->x) || |
- | |
1135 | box.p1.y > _cairo_fixed_from_int (rect->y) || |
- | |
1136 | box.p2.x < _cairo_fixed_from_int (rect->x + rect->width) || |
- | |
1137 | box.p2.y < _cairo_fixed_from_int (rect->y + rect->height)) |
- | |
1138 | { |
- | |
1139 | return FALSE; |
- | |
1140 | } |
- | |
1141 | } while ((clip_path = clip_path->prev) != NULL); |
- | |
1142 | - | ||
1143 | return TRUE; |
- | |
1144 | } |
- | |
1145 | - | ||
1146 | cairo_bool_t |
- | |
1147 | _cairo_clip_contains_extents (cairo_clip_t *clip, |
- | |
1148 | const cairo_composite_rectangles_t *extents) |
- | |
1149 | { |
- | |
1150 | const cairo_rectangle_int_t *rect; |
- | |
1151 | 571 | ||
Line 1152... | Line -... | ||
1152 | if (clip == NULL) |
- | |
1153 | return FALSE; |
- | |
1154 | 572 | copy = _cairo_clip_intersect_path (copy, &path, |
|
1155 | rect = extents->is_bounded ? &extents->bounded : &extents->unbounded; |
573 | CAIRO_FILL_RULE_WINDING, |
1156 | return _cairo_clip_contains_rectangle (clip, rect); |
574 | 0.1, |
1157 | } |
575 | CAIRO_ANTIALIAS_DEFAULT); |
1158 | 576 | ||
1159 | void |
- | |
1160 | _cairo_debug_print_clip (FILE *stream, cairo_clip_t *clip) |
- | |
1161 | { |
- | |
1162 | cairo_clip_path_t *clip_path; |
- | |
1163 | - | ||
1164 | if (clip == NULL) { |
- | |
1165 | fprintf (stream, "no clip\n"); |
- | |
1166 | return; |
- | |
1167 | } |
- | |
1168 | - | ||
1169 | if (clip->all_clipped) { |
- | |
1170 | fprintf (stream, "clip: all-clipped\n"); |
- | |
1171 | return; |
- | |
1172 | } |
- | |
Line 1173... | Line -... | ||
1173 | - | ||
1174 | if (clip->path == NULL) { |
- | |
1175 | fprintf (stream, "clip: empty\n"); |
- | |
1176 | return; |
577 | _cairo_path_fixed_fini (&path); |
1177 | } |
578 | } |
1178 | - | ||
Line 1179... | Line -... | ||
1179 | fprintf (stream, "clip:\n"); |
- | |
1180 | - | ||
1181 | clip_path = clip->path; |
579 | |
1182 | do { |
- | |
1183 | fprintf (stream, "path: has region? %s, has surface? %s, aa=%d, tolerance=%f, rule=%d: ", |
- | |
1184 | clip_path->region == NULL ? "no" : "yes", |
- | |
1185 | clip_path->surface == NULL ? "no" : "yes", |
- | |
1186 | clip_path->antialias, |
580 | if (clip->path) |
Line 1187... | Line 581... | ||
1187 | clip_path->tolerance, |
581 | copy = _cairo_clip_intersect_clip_path_transformed (copy, clip->path,m); |
1188 | clip_path->fill_rule); |
582 | |
1189 | _cairo_debug_print_path (stream, &clip_path->path); |
583 | _cairo_clip_destroy (clip); |
Line 1329... | Line 723... | ||
1329 | user_rect->height = y2 - y1; |
723 | user_rect->height = y2 - y1; |
Line 1330... | Line 724... | ||
1330 | 724 | ||
1331 | return is_tight; |
725 | return is_tight; |
Line 1332... | Line -... | ||
1332 | } |
- | |
1333 | - | ||
1334 | cairo_int_status_t |
- | |
1335 | _cairo_clip_get_region (cairo_clip_t *clip, |
- | |
1336 | cairo_region_t **region) |
- | |
1337 | { |
- | |
1338 | cairo_int_status_t status; |
- | |
1339 | - | ||
1340 | if (clip->all_clipped) |
- | |
1341 | goto CLIPPED; |
- | |
1342 | - | ||
1343 | assert (clip->path != NULL); |
- | |
1344 | - | ||
1345 | status = _cairo_clip_path_to_region (clip->path); |
- | |
1346 | if (status) |
- | |
1347 | return status; |
- | |
1348 | - | ||
1349 | if (cairo_region_is_empty (clip->path->region)) { |
- | |
1350 | _cairo_clip_set_all_clipped (clip); |
- | |
1351 | goto CLIPPED; |
- | |
1352 | } |
- | |
1353 | - | ||
1354 | if (region) |
- | |
1355 | *region = clip->path->region; |
- | |
1356 | return CAIRO_STATUS_SUCCESS; |
- | |
1357 | - | ||
1358 | CLIPPED: |
- | |
1359 | if (region) |
- | |
1360 | *region = NULL; |
- | |
1361 | return CAIRO_INT_STATUS_NOTHING_TO_DO; |
- | |
1362 | } |
- | |
1363 | - | ||
1364 | cairo_int_status_t |
- | |
1365 | _cairo_clip_get_boxes (cairo_clip_t *clip, |
- | |
1366 | cairo_box_t **boxes, |
- | |
1367 | int *count) |
- | |
1368 | { |
- | |
1369 | cairo_int_status_t status; |
- | |
1370 | - | ||
1371 | if (clip->all_clipped) |
- | |
1372 | return CAIRO_INT_STATUS_NOTHING_TO_DO; |
- | |
1373 | - | ||
1374 | assert (clip->path != NULL); |
- | |
1375 | - | ||
1376 | status = _cairo_clip_path_to_boxes (clip->path, boxes, count); |
- | |
1377 | if (status) |
- | |
1378 | return status; |
- | |
1379 | - | ||
1380 | if (*count == 0) { |
- | |
1381 | _cairo_clip_set_all_clipped (clip); |
- | |
1382 | return CAIRO_INT_STATUS_NOTHING_TO_DO; |
- | |
1383 | } |
- | |
1384 | - | ||
1385 | return CAIRO_STATUS_SUCCESS; |
- | |
1386 | } |
- | |
1387 | - | ||
1388 | static cairo_bool_t |
- | |
1389 | box_is_aligned (const cairo_box_t *box) |
- | |
1390 | { |
- | |
1391 | return |
- | |
1392 | _cairo_fixed_is_integer (box->p1.x) && |
- | |
1393 | _cairo_fixed_is_integer (box->p1.y) && |
- | |
1394 | _cairo_fixed_is_integer (box->p2.x) && |
- | |
1395 | _cairo_fixed_is_integer (box->p2.y); |
- | |
1396 | } |
- | |
1397 | - | ||
1398 | static void |
- | |
1399 | intersect_with_boxes (cairo_composite_rectangles_t *extents, |
- | |
1400 | cairo_box_t *boxes, |
- | |
1401 | int num_boxes) |
- | |
1402 | { |
- | |
1403 | cairo_rectangle_int_t rect; |
- | |
1404 | cairo_box_t box; |
- | |
1405 | cairo_bool_t is_empty; |
- | |
1406 | - | ||
1407 | box.p1.x = box.p1.y = INT_MIN; |
- | |
1408 | box.p2.x = box.p2.y = INT_MAX; |
- | |
1409 | while (num_boxes--) { |
- | |
1410 | if (boxes->p1.x < box.p1.x) |
- | |
1411 | box.p1.x = boxes->p1.x; |
- | |
1412 | if (boxes->p1.y < box.p1.y) |
- | |
1413 | box.p1.y = boxes->p1.y; |
- | |
1414 | - | ||
1415 | if (boxes->p2.x > box.p2.x) |
- | |
1416 | box.p2.x = boxes->p2.x; |
- | |
1417 | if (boxes->p2.y > box.p2.y) |
- | |
1418 | box.p2.y = boxes->p2.y; |
- | |
1419 | } |
- | |
1420 | - | ||
1421 | _cairo_box_round_to_rectangle (&box, &rect); |
- | |
1422 | is_empty = _cairo_rectangle_intersect (&extents->bounded, &rect); |
- | |
1423 | is_empty = _cairo_rectangle_intersect (&extents->unbounded, &rect); |
- | |
1424 | } |
- | |
1425 | - | ||
1426 | cairo_status_t |
- | |
1427 | _cairo_clip_to_boxes (cairo_clip_t **clip, |
- | |
1428 | cairo_composite_rectangles_t *extents, |
- | |
1429 | cairo_box_t **boxes, |
- | |
1430 | int *num_boxes) |
- | |
1431 | { |
- | |
1432 | cairo_status_t status; |
- | |
1433 | const cairo_rectangle_int_t *rect; |
- | |
1434 | - | ||
1435 | rect = extents->is_bounded ? &extents->bounded : &extents->unbounded; |
- | |
1436 | - | ||
1437 | if (*clip == NULL) |
- | |
1438 | goto EXTENTS; |
- | |
1439 | - | ||
1440 | status = _cairo_clip_rectangle (*clip, rect); |
- | |
1441 | if (unlikely (status)) |
- | |
1442 | return status; |
- | |
1443 | - | ||
1444 | status = _cairo_clip_get_boxes (*clip, boxes, num_boxes); |
- | |
1445 | switch ((int) status) { |
- | |
1446 | case CAIRO_STATUS_SUCCESS: |
- | |
1447 | intersect_with_boxes (extents, *boxes, *num_boxes); |
- | |
1448 | if (rect->width == 0 || rect->height == 0 || |
- | |
1449 | extents->is_bounded || |
- | |
1450 | (*num_boxes == 1 && box_is_aligned (*boxes))) |
- | |
1451 | { |
- | |
1452 | *clip = NULL; |
- | |
1453 | } |
- | |
1454 | goto DONE; |
- | |
1455 | - | ||
1456 | case CAIRO_INT_STATUS_UNSUPPORTED: |
- | |
1457 | goto EXTENTS; |
- | |
1458 | - | ||
1459 | default: |
- | |
1460 | return status; |
- | |
1461 | } |
- | |
1462 | - | ||
1463 | EXTENTS: |
- | |
1464 | status = CAIRO_STATUS_SUCCESS; |
- | |
1465 | _cairo_box_from_rectangle (&(*boxes)[0], rect); |
- | |
1466 | *num_boxes = 1; |
- | |
1467 | DONE: |
- | |
1468 | return status; |
- | |
1469 | } |
- | |
1470 | 726 | } |
|
1471 | 727 | ||
1472 | static cairo_rectangle_list_t * |
728 | cairo_rectangle_list_t * |
1473 | _cairo_rectangle_list_create_in_error (cairo_status_t status) |
729 | _cairo_rectangle_list_create_in_error (cairo_status_t status) |
Line 1474... | Line 730... | ||
1474 | { |
730 | { |
Line 1479... | Line 735... | ||
1479 | if (status == CAIRO_STATUS_CLIP_NOT_REPRESENTABLE) |
735 | if (status == CAIRO_STATUS_CLIP_NOT_REPRESENTABLE) |
1480 | return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable; |
736 | return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable; |
Line 1481... | Line 737... | ||
1481 | 737 | ||
1482 | list = malloc (sizeof (*list)); |
738 | list = malloc (sizeof (*list)); |
1483 | if (unlikely (list == NULL)) { |
739 | if (unlikely (list == NULL)) { |
1484 | _cairo_error_throw (status); |
740 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1485 | return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; |
741 | return (cairo_rectangle_list_t*) &_cairo_rectangles_nil; |
Line 1486... | Line 742... | ||
1486 | } |
742 | } |
1487 | 743 | ||
Line 1498... | Line 754... | ||
1498 | #define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S)) |
754 | #define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S)) |
Line 1499... | Line 755... | ||
1499 | 755 | ||
1500 | cairo_rectangle_list_t *list; |
756 | cairo_rectangle_list_t *list; |
1501 | cairo_rectangle_t *rectangles = NULL; |
757 | cairo_rectangle_t *rectangles = NULL; |
1502 | cairo_region_t *region = NULL; |
- | |
1503 | cairo_int_status_t status; |
758 | cairo_region_t *region = NULL; |
1504 | int n_rects = 0; |
759 | int n_rects = 0; |
Line 1505... | Line -... | ||
1505 | int i; |
- | |
1506 | - | ||
1507 | if (clip->all_clipped) |
- | |
1508 | goto DONE; |
760 | int i; |
1509 | 761 | ||
Line 1510... | Line 762... | ||
1510 | if (!clip->path) |
762 | if (clip == NULL) |
1511 | return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); |
- | |
1512 | 763 | return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); |
|
- | 764 | ||
1513 | status = _cairo_clip_get_region (clip, ®ion); |
765 | if (_cairo_clip_is_all_clipped (clip)) |
1514 | if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) { |
766 | goto DONE; |
- | 767 | ||
- | 768 | if (! _cairo_clip_is_region (clip)) |
|
1515 | goto DONE; |
769 | return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); |
1516 | } else if (status == CAIRO_INT_STATUS_UNSUPPORTED) { |
770 | |
1517 | return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE); |
- | |
Line 1518... | Line 771... | ||
1518 | } else if (unlikely (status)) { |
771 | region = _cairo_clip_get_region (clip); |
1519 | return ERROR_LIST (status); |
772 | if (region == NULL) |
1520 | } |
773 | return ERROR_LIST (CAIRO_STATUS_NO_MEMORY); |
1521 | 774 | ||
Line 1556... | Line 809... | ||
1556 | #undef ERROR_LIST |
809 | #undef ERROR_LIST |
1557 | } |
810 | } |
Line 1558... | Line 811... | ||
1558 | 811 | ||
1559 | /** |
812 | /** |
1560 | * cairo_rectangle_list_destroy: |
813 | * cairo_rectangle_list_destroy: |
1561 | * @rectangle_list: a rectangle list, as obtained from cairo_copy_clip_rectangles() |
814 | * @rectangle_list: a rectangle list, as obtained from cairo_copy_clip_rectangle_list() |
1562 | * |
815 | * |
1563 | * Unconditionally frees @rectangle_list and all associated |
816 | * Unconditionally frees @rectangle_list and all associated |
1564 | * references. After this call, the @rectangle_list pointer must not |
817 | * references. After this call, the @rectangle_list pointer must not |
1565 | * be dereferenced. |
818 | * be dereferenced. |
Line 1579... | Line 832... | ||
1579 | 832 | ||
1580 | void |
833 | void |
1581 | _cairo_clip_reset_static_data (void) |
834 | _cairo_clip_reset_static_data (void) |
1582 | { |
835 | { |
- | 836 | _freed_pool_reset (&clip_path_pool); |
|
1583 | _freed_pool_reset (&clip_path_pool); |
837 | _freed_pool_reset (&clip_pool); |