/work/workdir/UnpackedTarball/cairo/src/cairo-clip-boxes.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ |
2 | | /* cairo - a vector graphics library with display and print output |
3 | | * |
4 | | * Copyright © 2002 University of Southern California |
5 | | * Copyright © 2005 Red Hat, Inc. |
6 | | * Copyright © 2009 Chris Wilson |
7 | | * |
8 | | * This library is free software; you can redistribute it and/or |
9 | | * modify it either under the terms of the GNU Lesser General Public |
10 | | * License version 2.1 as published by the Free Software Foundation |
11 | | * (the "LGPL") or, at your option, under the terms of the Mozilla |
12 | | * Public License Version 1.1 (the "MPL"). If you do not alter this |
13 | | * notice, a recipient may use your version of this file under either |
14 | | * the MPL or the LGPL. |
15 | | * |
16 | | * You should have received a copy of the LGPL along with this library |
17 | | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
19 | | * You should have received a copy of the MPL along with this library |
20 | | * in the file COPYING-MPL-1.1 |
21 | | * |
22 | | * The contents of this file are subject to the Mozilla Public License |
23 | | * Version 1.1 (the "License"); you may not use this file except in |
24 | | * compliance with the License. You may obtain a copy of the License at |
25 | | * http://www.mozilla.org/MPL/ |
26 | | * |
27 | | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
28 | | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
29 | | * the specific language governing rights and limitations. |
30 | | * |
31 | | * The Original Code is the cairo graphics library. |
32 | | * |
33 | | * The Initial Developer of the Original Code is University of Southern |
34 | | * California. |
35 | | * |
36 | | * Contributor(s): |
37 | | * Carl D. Worth <cworth@cworth.org> |
38 | | * Kristian Høgsberg <krh@redhat.com> |
39 | | * Chris Wilson <chris@chris-wilson.co.uk> |
40 | | */ |
41 | | |
42 | | #include "cairoint.h" |
43 | | |
44 | | #include "cairo-box-inline.h" |
45 | | #include "cairo-clip-inline.h" |
46 | | #include "cairo-clip-private.h" |
47 | | #include "cairo-error-private.h" |
48 | | #include "cairo-freed-pool-private.h" |
49 | | #include "cairo-gstate-private.h" |
50 | | #include "cairo-path-fixed-private.h" |
51 | | #include "cairo-pattern-private.h" |
52 | | #include "cairo-composite-rectangles-private.h" |
53 | | #include "cairo-region-private.h" |
54 | | |
55 | | static inline int |
56 | | pot (int v) |
57 | 0 | { |
58 | 0 | v--; |
59 | 0 | v |= v >> 1; |
60 | 0 | v |= v >> 2; |
61 | 0 | v |= v >> 4; |
62 | 0 | v |= v >> 8; |
63 | 0 | v |= v >> 16; |
64 | 0 | v++; |
65 | 0 | return v; |
66 | 0 | } |
67 | | |
68 | | static cairo_bool_t |
69 | | _cairo_clip_contains_rectangle_box (const cairo_clip_t *clip, |
70 | | const cairo_rectangle_int_t *rect, |
71 | | const cairo_box_t *box) |
72 | 1.81M | { |
73 | 1.81M | int i; |
74 | | |
75 | | /* clip == NULL means no clip, so the clip contains everything */ |
76 | 1.81M | if (clip == NULL) |
77 | 1.24M | return TRUE; |
78 | | |
79 | 563k | if (_cairo_clip_is_all_clipped (clip)) |
80 | 0 | return FALSE; |
81 | | |
82 | | /* If we have a non-trivial path, just say no */ |
83 | 563k | if (clip->path) |
84 | 0 | return FALSE; |
85 | | |
86 | 563k | if (! _cairo_rectangle_contains_rectangle (&clip->extents, rect)) |
87 | 20.5k | return FALSE; |
88 | | |
89 | 542k | if (clip->num_boxes == 0) |
90 | 0 | return TRUE; |
91 | | |
92 | | /* Check for a clip-box that wholly contains the rectangle */ |
93 | 542k | for (i = 0; i < clip->num_boxes; i++) { |
94 | 542k | if (box->p1.x >= clip->boxes[i].p1.x && |
95 | 542k | box->p1.y >= clip->boxes[i].p1.y && |
96 | 542k | box->p2.x <= clip->boxes[i].p2.x && |
97 | 542k | box->p2.y <= clip->boxes[i].p2.y) |
98 | 542k | { |
99 | 542k | return TRUE; |
100 | 542k | } |
101 | 542k | } |
102 | | |
103 | 0 | return FALSE; |
104 | 542k | } |
105 | | |
106 | | cairo_bool_t |
107 | | _cairo_clip_contains_box (const cairo_clip_t *clip, |
108 | | const cairo_box_t *box) |
109 | 547 | { |
110 | 547 | cairo_rectangle_int_t rect; |
111 | | |
112 | 547 | _cairo_box_round_to_rectangle (box, &rect); |
113 | 547 | return _cairo_clip_contains_rectangle_box(clip, &rect, box); |
114 | 547 | } |
115 | | |
116 | | cairo_bool_t |
117 | | _cairo_clip_contains_rectangle (const cairo_clip_t *clip, |
118 | | const cairo_rectangle_int_t *rect) |
119 | 1.81M | { |
120 | 1.81M | cairo_box_t box; |
121 | | |
122 | 1.81M | _cairo_box_from_rectangle_int (&box, rect); |
123 | 1.81M | return _cairo_clip_contains_rectangle_box (clip, rect, &box); |
124 | 1.81M | } |
125 | | |
126 | | cairo_clip_t * |
127 | | _cairo_clip_intersect_rectilinear_path (cairo_clip_t *clip, |
128 | | const cairo_path_fixed_t *path, |
129 | | cairo_fill_rule_t fill_rule, |
130 | | cairo_antialias_t antialias) |
131 | 1.37k | { |
132 | 1.37k | cairo_status_t status; |
133 | 1.37k | cairo_boxes_t boxes; |
134 | | |
135 | 1.37k | _cairo_boxes_init (&boxes); |
136 | 1.37k | status = _cairo_path_fixed_fill_rectilinear_to_boxes (path, |
137 | 1.37k | fill_rule, |
138 | 1.37k | antialias, |
139 | 1.37k | &boxes); |
140 | 1.37k | if (likely (status == CAIRO_STATUS_SUCCESS && boxes.num_boxes)) |
141 | 1.26k | clip = _cairo_clip_intersect_boxes (clip, &boxes); |
142 | 108 | else |
143 | 108 | clip = _cairo_clip_set_all_clipped (clip); |
144 | 1.37k | _cairo_boxes_fini (&boxes); |
145 | | |
146 | 1.37k | return clip; |
147 | 1.37k | } |
148 | | |
149 | | static cairo_clip_t * |
150 | | _cairo_clip_intersect_rectangle_box (cairo_clip_t *clip, |
151 | | const cairo_rectangle_int_t *r, |
152 | | const cairo_box_t *box) |
153 | 1.56M | { |
154 | 1.56M | cairo_box_t extents_box; |
155 | 1.56M | cairo_bool_t changed = FALSE; |
156 | 1.56M | int i, j; |
157 | | |
158 | 1.56M | if (clip == NULL) { |
159 | 1.54M | clip = _cairo_clip_create (); |
160 | 1.54M | if (clip == NULL) |
161 | 0 | return _cairo_clip_set_all_clipped (clip); |
162 | 1.54M | } |
163 | | |
164 | 1.56M | if (clip->num_boxes == 0) { |
165 | 1.56M | clip->boxes = &clip->embedded_box; |
166 | 1.56M | clip->boxes[0] = *box; |
167 | 1.56M | clip->num_boxes = 1; |
168 | 1.56M | if (clip->path == NULL) { |
169 | 1.56M | clip->extents = *r; |
170 | 1.56M | } else { |
171 | 0 | if (! _cairo_rectangle_intersect (&clip->extents, r)) |
172 | 0 | return _cairo_clip_set_all_clipped (clip); |
173 | 0 | } |
174 | 1.56M | if (clip->path == NULL) |
175 | 1.56M | clip->is_region = _cairo_box_is_pixel_aligned (box); |
176 | 1.56M | return clip; |
177 | 1.56M | } |
178 | | |
179 | | /* Does the new box wholly subsume the clip? Perform a cheap check |
180 | | * for the common condition of a single clip rectangle. |
181 | | */ |
182 | 923 | if (clip->num_boxes == 1 && |
183 | 923 | clip->boxes[0].p1.x >= box->p1.x && |
184 | 923 | clip->boxes[0].p1.y >= box->p1.y && |
185 | 923 | clip->boxes[0].p2.x <= box->p2.x && |
186 | 923 | clip->boxes[0].p2.y <= box->p2.y) |
187 | 335 | { |
188 | 335 | return clip; |
189 | 335 | } |
190 | | |
191 | 1.33k | for (i = j = 0; i < clip->num_boxes; i++) { |
192 | 747 | cairo_box_t *b = &clip->boxes[j]; |
193 | | |
194 | 747 | if (j != i) |
195 | 65 | *b = clip->boxes[i]; |
196 | | |
197 | 747 | if (box->p1.x > b->p1.x) |
198 | 247 | b->p1.x = box->p1.x, changed = TRUE; |
199 | 747 | if (box->p2.x < b->p2.x) |
200 | 81 | b->p2.x = box->p2.x, changed = TRUE; |
201 | | |
202 | 747 | if (box->p1.y > b->p1.y) |
203 | 111 | b->p1.y = box->p1.y, changed = TRUE; |
204 | 747 | if (box->p2.y < b->p2.y) |
205 | 285 | b->p2.y = box->p2.y, changed = TRUE; |
206 | | |
207 | 747 | j += b->p2.x > b->p1.x && b->p2.y > b->p1.y; |
208 | 747 | } |
209 | 588 | clip->num_boxes = j; |
210 | | |
211 | 588 | if (clip->num_boxes == 0) |
212 | 397 | return _cairo_clip_set_all_clipped (clip); |
213 | | |
214 | 191 | if (! changed) |
215 | 2 | return clip; |
216 | | |
217 | 189 | extents_box = clip->boxes[0]; |
218 | 189 | for (i = 1; i < clip->num_boxes; i++) { |
219 | 0 | if (clip->boxes[i].p1.x < extents_box.p1.x) |
220 | 0 | extents_box.p1.x = clip->boxes[i].p1.x; |
221 | |
|
222 | 0 | if (clip->boxes[i].p1.y < extents_box.p1.y) |
223 | 0 | extents_box.p1.y = clip->boxes[i].p1.y; |
224 | |
|
225 | 0 | if (clip->boxes[i].p2.x > extents_box.p2.x) |
226 | 0 | extents_box.p2.x = clip->boxes[i].p2.x; |
227 | |
|
228 | 0 | if (clip->boxes[i].p2.y > extents_box.p2.y) |
229 | 0 | extents_box.p2.y = clip->boxes[i].p2.y; |
230 | 0 | } |
231 | | |
232 | 189 | if (clip->path == NULL) { |
233 | 189 | _cairo_box_round_to_rectangle (&extents_box, &clip->extents); |
234 | 189 | } else { |
235 | 0 | cairo_rectangle_int_t extents_rect; |
236 | |
|
237 | 0 | _cairo_box_round_to_rectangle (&extents_box, &extents_rect); |
238 | 0 | if (! _cairo_rectangle_intersect (&clip->extents, &extents_rect)) |
239 | 0 | return _cairo_clip_set_all_clipped (clip); |
240 | 0 | } |
241 | | |
242 | 189 | if (clip->region) { |
243 | 0 | cairo_region_destroy (clip->region); |
244 | 0 | clip->region = NULL; |
245 | 0 | } |
246 | | |
247 | 189 | clip->is_region = FALSE; |
248 | 189 | return clip; |
249 | 189 | } |
250 | | |
251 | | cairo_clip_t * |
252 | | _cairo_clip_intersect_box (cairo_clip_t *clip, |
253 | | const cairo_box_t *box) |
254 | 306k | { |
255 | 306k | cairo_rectangle_int_t r; |
256 | | |
257 | 306k | if (_cairo_clip_is_all_clipped (clip)) |
258 | 0 | return clip; |
259 | | |
260 | 306k | _cairo_box_round_to_rectangle (box, &r); |
261 | 306k | if (r.width == 0 || r.height == 0) |
262 | 19.4k | return _cairo_clip_set_all_clipped (clip); |
263 | | |
264 | 287k | return _cairo_clip_intersect_rectangle_box (clip, &r, box); |
265 | 306k | } |
266 | | |
267 | | /* Copy a box set to a clip |
268 | | * |
269 | | * @param boxes The box set to copy from. |
270 | | * @param clip The clip to copy to (return buffer). |
271 | | * @returns Zero if the allocation failed (the clip will be set to |
272 | | * all-clipped), otherwise non-zero. |
273 | | */ |
274 | | static cairo_bool_t |
275 | | _cairo_boxes_copy_to_clip (const cairo_boxes_t *boxes, cairo_clip_t *clip) |
276 | 1.26k | { |
277 | | /* XXX cow-boxes? */ |
278 | 1.26k | if (boxes->num_boxes == 1) { |
279 | 0 | clip->boxes = &clip->embedded_box; |
280 | 0 | clip->boxes[0] = boxes->chunks.base[0]; |
281 | 0 | clip->num_boxes = 1; |
282 | 0 | return TRUE; |
283 | 0 | } |
284 | | |
285 | 1.26k | clip->boxes = _cairo_boxes_to_array (boxes, &clip->num_boxes); |
286 | 1.26k | if (unlikely (clip->boxes == NULL)) |
287 | 0 | { |
288 | 0 | _cairo_clip_set_all_clipped (clip); |
289 | 0 | return FALSE; |
290 | 0 | } |
291 | | |
292 | 1.26k | return TRUE; |
293 | 1.26k | } |
294 | | |
295 | | cairo_clip_t * |
296 | | _cairo_clip_intersect_boxes (cairo_clip_t *clip, |
297 | | const cairo_boxes_t *boxes) |
298 | 1.26k | { |
299 | 1.26k | cairo_boxes_t clip_boxes; |
300 | 1.26k | cairo_box_t limits; |
301 | 1.26k | cairo_rectangle_int_t extents; |
302 | | |
303 | 1.26k | if (_cairo_clip_is_all_clipped (clip)) |
304 | 0 | return clip; |
305 | | |
306 | 1.26k | if (boxes->num_boxes == 0) |
307 | 0 | return _cairo_clip_set_all_clipped (clip); |
308 | | |
309 | 1.26k | if (boxes->num_boxes == 1) |
310 | 0 | return _cairo_clip_intersect_box (clip, boxes->chunks.base); |
311 | | |
312 | 1.26k | if (clip == NULL) |
313 | 1.26k | clip = _cairo_clip_create (); |
314 | | |
315 | 1.26k | if (clip->num_boxes) { |
316 | 0 | _cairo_boxes_init_for_array (&clip_boxes, clip->boxes, clip->num_boxes); |
317 | 0 | if (unlikely (_cairo_boxes_intersect (&clip_boxes, boxes, &clip_boxes))) { |
318 | 0 | clip = _cairo_clip_set_all_clipped (clip); |
319 | 0 | goto out; |
320 | 0 | } |
321 | | |
322 | 0 | if (clip->boxes != &clip->embedded_box) |
323 | 0 | free (clip->boxes); |
324 | |
|
325 | 0 | clip->boxes = NULL; |
326 | 0 | boxes = &clip_boxes; |
327 | 0 | } |
328 | | |
329 | 1.26k | if (boxes->num_boxes == 0) { |
330 | 0 | clip = _cairo_clip_set_all_clipped (clip); |
331 | 0 | goto out; |
332 | 0 | } |
333 | | |
334 | 1.26k | _cairo_boxes_copy_to_clip (boxes, clip); |
335 | | |
336 | 1.26k | _cairo_boxes_extents (boxes, &limits); |
337 | | |
338 | 1.26k | _cairo_box_round_to_rectangle (&limits, &extents); |
339 | 1.26k | if (clip->path == NULL) { |
340 | 1.26k | clip->extents = extents; |
341 | 1.26k | } else if (! _cairo_rectangle_intersect (&clip->extents, &extents)) { |
342 | 0 | clip = _cairo_clip_set_all_clipped (clip); |
343 | 0 | goto out; |
344 | 0 | } |
345 | | |
346 | 1.26k | if (clip->region) { |
347 | 0 | cairo_region_destroy (clip->region); |
348 | 0 | clip->region = NULL; |
349 | 0 | } |
350 | 1.26k | clip->is_region = FALSE; |
351 | | |
352 | 1.26k | out: |
353 | 1.26k | if (boxes == &clip_boxes) |
354 | 0 | _cairo_boxes_fini (&clip_boxes); |
355 | | |
356 | 1.26k | return clip; |
357 | 1.26k | } |
358 | | |
359 | | cairo_clip_t * |
360 | | _cairo_clip_intersect_rectangle (cairo_clip_t *clip, |
361 | | const cairo_rectangle_int_t *r) |
362 | 1.27M | { |
363 | 1.27M | cairo_box_t box; |
364 | | |
365 | 1.27M | if (_cairo_clip_is_all_clipped (clip)) |
366 | 0 | return clip; |
367 | | |
368 | 1.27M | if (r->width == 0 || r->height == 0) |
369 | 16 | return _cairo_clip_set_all_clipped (clip); |
370 | | |
371 | 1.27M | _cairo_box_from_rectangle_int (&box, r); |
372 | | |
373 | 1.27M | return _cairo_clip_intersect_rectangle_box (clip, r, &box); |
374 | 1.27M | } |
375 | | |
376 | | struct reduce { |
377 | | cairo_clip_t *clip; |
378 | | cairo_box_t limit; |
379 | | cairo_box_t extents; |
380 | | cairo_bool_t inside; |
381 | | |
382 | | cairo_point_t current_point; |
383 | | cairo_point_t last_move_to; |
384 | | }; |
385 | | |
386 | | static void |
387 | | _add_clipped_edge (struct reduce *r, |
388 | | const cairo_point_t *p1, |
389 | | const cairo_point_t *p2, |
390 | | int y1, int y2) |
391 | 0 | { |
392 | 0 | cairo_fixed_t x; |
393 | 0 |
|
394 | 0 | x = _cairo_edge_compute_intersection_x_for_y (p1, p2, y1); |
395 | 0 | if (x < r->extents.p1.x) |
396 | 0 | r->extents.p1.x = x; |
397 | 0 |
|
398 | 0 | x = _cairo_edge_compute_intersection_x_for_y (p1, p2, y2); |
399 | 0 | if (x > r->extents.p2.x) |
400 | 0 | r->extents.p2.x = x; |
401 | 0 |
|
402 | 0 | if (y1 < r->extents.p1.y) |
403 | 0 | r->extents.p1.y = y1; |
404 | 0 |
|
405 | 0 | if (y2 > r->extents.p2.y) |
406 | 0 | r->extents.p2.y = y2; |
407 | 0 |
|
408 | 0 | r->inside = TRUE; |
409 | 0 | } |
410 | | |
411 | | static void |
412 | | _add_edge (struct reduce *r, |
413 | | const cairo_point_t *p1, |
414 | | const cairo_point_t *p2) |
415 | 0 | { |
416 | 0 | int top, bottom; |
417 | 0 | int top_y, bot_y; |
418 | 0 | int n; |
419 | 0 |
|
420 | 0 | if (p1->y < p2->y) { |
421 | 0 | top = p1->y; |
422 | 0 | bottom = p2->y; |
423 | 0 | } else { |
424 | 0 | top = p2->y; |
425 | 0 | bottom = p1->y; |
426 | 0 | } |
427 | 0 |
|
428 | 0 | if (bottom < r->limit.p1.y || top > r->limit.p2.y) |
429 | 0 | return; |
430 | 0 |
|
431 | 0 | if (p1->x > p2->x) { |
432 | 0 | const cairo_point_t *t = p1; |
433 | 0 | p1 = p2; |
434 | 0 | p2 = t; |
435 | 0 | } |
436 | 0 |
|
437 | 0 | if (p2->x <= r->limit.p1.x || p1->x >= r->limit.p2.x) |
438 | 0 | return; |
439 | 0 |
|
440 | 0 | for (n = 0; n < r->clip->num_boxes; n++) { |
441 | 0 | const cairo_box_t *limits = &r->clip->boxes[n]; |
442 | 0 |
|
443 | 0 | if (bottom < limits->p1.y || top > limits->p2.y) |
444 | 0 | continue; |
445 | 0 |
|
446 | 0 | if (p2->x <= limits->p1.x || p1->x >= limits->p2.x) |
447 | 0 | continue; |
448 | 0 |
|
449 | 0 | if (p1->x >= limits->p1.x && p2->x <= limits->p1.x) { |
450 | 0 | top_y = top; |
451 | 0 | bot_y = bottom; |
452 | 0 | } else { |
453 | 0 | int p1_y, p2_y; |
454 | 0 |
|
455 | 0 | p1_y = _cairo_edge_compute_intersection_y_for_x (p1, p2, |
456 | 0 | limits->p1.x); |
457 | 0 | p2_y = _cairo_edge_compute_intersection_y_for_x (p1, p2, |
458 | 0 | limits->p2.x); |
459 | 0 | if (p1_y < p2_y) { |
460 | 0 | top_y = p1_y; |
461 | 0 | bot_y = p2_y; |
462 | 0 | } else { |
463 | 0 | top_y = p2_y; |
464 | 0 | bot_y = p1_y; |
465 | 0 | } |
466 | 0 |
|
467 | 0 | if (top_y < top) |
468 | 0 | top_y = top; |
469 | 0 | if (bot_y > bottom) |
470 | 0 | bot_y = bottom; |
471 | 0 | } |
472 | 0 |
|
473 | 0 | if (top_y < limits->p1.y) |
474 | 0 | top_y = limits->p1.y; |
475 | 0 |
|
476 | 0 | if (bot_y > limits->p2.y) |
477 | 0 | bot_y = limits->p2.y; |
478 | 0 | if (bot_y > top_y) |
479 | 0 | _add_clipped_edge (r, p1, p2, top_y, bot_y); |
480 | 0 | } |
481 | 0 | } |
482 | | |
483 | | static cairo_status_t |
484 | | _reduce_line_to (void *closure, |
485 | | const cairo_point_t *point) |
486 | 0 | { |
487 | 0 | struct reduce *r = closure; |
488 | 0 |
|
489 | 0 | _add_edge (r, &r->current_point, point); |
490 | 0 | r->current_point = *point; |
491 | 0 |
|
492 | 0 | return CAIRO_STATUS_SUCCESS; |
493 | 0 | } |
494 | | |
495 | | static cairo_status_t |
496 | | _reduce_close (void *closure) |
497 | 0 | { |
498 | 0 | struct reduce *r = closure; |
499 | 0 |
|
500 | 0 | return _reduce_line_to (r, &r->last_move_to); |
501 | 0 | } |
502 | | |
503 | | static cairo_status_t |
504 | | _reduce_move_to (void *closure, |
505 | | const cairo_point_t *point) |
506 | 0 | { |
507 | 0 | struct reduce *r = closure; |
508 | 0 | cairo_status_t status; |
509 | 0 |
|
510 | 0 | /* close current subpath */ |
511 | 0 | status = _reduce_close (closure); |
512 | 0 |
|
513 | 0 | /* make sure that the closure represents a degenerate path */ |
514 | 0 | r->current_point = *point; |
515 | 0 | r->last_move_to = *point; |
516 | 0 |
|
517 | 0 | return status; |
518 | 0 | } |
519 | | |
520 | | static cairo_clip_t * |
521 | | _cairo_clip_reduce_to_boxes (cairo_clip_t *clip) |
522 | 0 | { |
523 | 0 | struct reduce r; |
524 | 0 | cairo_clip_path_t *clip_path; |
525 | 0 | cairo_status_t status; |
526 | |
|
527 | 0 | return clip; |
528 | 0 | if (clip->path == NULL) |
529 | 0 | return clip; |
530 | | |
531 | 0 | r.clip = clip; |
532 | 0 | r.extents.p1.x = r.extents.p1.y = INT_MAX; |
533 | 0 | r.extents.p2.x = r.extents.p2.y = INT_MIN; |
534 | 0 | r.inside = FALSE; |
535 | |
|
536 | 0 | r.limit.p1.x = _cairo_fixed_from_int (clip->extents.x); |
537 | 0 | r.limit.p1.y = _cairo_fixed_from_int (clip->extents.y); |
538 | 0 | r.limit.p2.x = _cairo_fixed_from_int (clip->extents.x + clip->extents.width); |
539 | 0 | r.limit.p2.y = _cairo_fixed_from_int (clip->extents.y + clip->extents.height); |
540 | |
|
541 | 0 | clip_path = clip->path; |
542 | 0 | do { |
543 | 0 | r.current_point.x = 0; |
544 | 0 | r.current_point.y = 0; |
545 | 0 | r.last_move_to = r.current_point; |
546 | |
|
547 | 0 | status = _cairo_path_fixed_interpret_flat (&clip_path->path, |
548 | 0 | _reduce_move_to, |
549 | 0 | _reduce_line_to, |
550 | 0 | _reduce_close, |
551 | 0 | &r, |
552 | 0 | clip_path->tolerance); |
553 | 0 | assert (status == CAIRO_STATUS_SUCCESS); |
554 | 0 | _reduce_close (&r); |
555 | 0 | } while ((clip_path = clip_path->prev)); |
556 | | |
557 | 0 | if (! r.inside) { |
558 | 0 | _cairo_clip_path_destroy (clip->path); |
559 | 0 | clip->path = NULL; |
560 | 0 | } |
561 | |
|
562 | 0 | return _cairo_clip_intersect_box (clip, &r.extents); |
563 | 0 | } |
564 | | |
565 | | cairo_clip_t * |
566 | | _cairo_clip_reduce_to_rectangle (const cairo_clip_t *clip, |
567 | | const cairo_rectangle_int_t *r) |
568 | 1.27M | { |
569 | 1.27M | cairo_clip_t *copy; |
570 | | |
571 | 1.27M | if (_cairo_clip_is_all_clipped (clip)) |
572 | 0 | return (cairo_clip_t *) clip; |
573 | | |
574 | 1.27M | if (_cairo_clip_contains_rectangle (clip, r)) |
575 | 1.27M | return _cairo_clip_intersect_rectangle (NULL, r); |
576 | | |
577 | 0 | copy = _cairo_clip_copy_intersect_rectangle (clip, r); |
578 | 0 | if (_cairo_clip_is_all_clipped (copy)) |
579 | 0 | return copy; |
580 | | |
581 | 0 | return _cairo_clip_reduce_to_boxes (copy); |
582 | 0 | } |
583 | | |
584 | | cairo_clip_t * |
585 | | _cairo_clip_reduce_for_composite (const cairo_clip_t *clip, |
586 | | cairo_composite_rectangles_t *extents) |
587 | 1.27M | { |
588 | 1.27M | const cairo_rectangle_int_t *r; |
589 | | |
590 | 1.27M | r = extents->is_bounded ? &extents->bounded : &extents->unbounded; |
591 | 1.27M | return _cairo_clip_reduce_to_rectangle (clip, r); |
592 | 1.27M | } |
593 | | |
594 | | cairo_clip_t * |
595 | | _cairo_clip_from_boxes (const cairo_boxes_t *boxes) |
596 | 0 | { |
597 | 0 | cairo_box_t extents; |
598 | 0 | cairo_clip_t *clip = _cairo_clip_create (); |
599 | 0 | if (clip == NULL) |
600 | 0 | return _cairo_clip_set_all_clipped (clip); |
601 | | |
602 | 0 | if (unlikely (! _cairo_boxes_copy_to_clip (boxes, clip))) |
603 | 0 | return clip; |
604 | | |
605 | 0 | _cairo_boxes_extents (boxes, &extents); |
606 | 0 | _cairo_box_round_to_rectangle (&extents, &clip->extents); |
607 | |
|
608 | 0 | return clip; |
609 | 0 | } |