/work/workdir/UnpackedTarball/cairo/src/cairo-region.c
Line | Count | Source |
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 © 2005 Red Hat, Inc. |
5 | | * |
6 | | * This library is free software; you can redistribute it and/or |
7 | | * modify it either under the terms of the GNU Lesser General Public |
8 | | * License version 2.1 as published by the Free Software Foundation |
9 | | * (the "LGPL") or, at your option, under the terms of the Mozilla |
10 | | * Public License Version 1.1 (the "MPL"). If you do not alter this |
11 | | * notice, a recipient may use your version of this file under either |
12 | | * the MPL or the LGPL. |
13 | | * |
14 | | * You should have received a copy of the LGPL along with this library |
15 | | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
16 | | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
17 | | * You should have received a copy of the MPL along with this library |
18 | | * in the file COPYING-MPL-1.1 |
19 | | * |
20 | | * The contents of this file are subject to the Mozilla Public License |
21 | | * Version 1.1 (the "License"); you may not use this file except in |
22 | | * compliance with the License. You may obtain a copy of the License at |
23 | | * http://www.mozilla.org/MPL/ |
24 | | * |
25 | | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
26 | | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
27 | | * the specific language governing rights and limitations. |
28 | | * |
29 | | * The Original Code is the cairo graphics library. |
30 | | * |
31 | | * The Initial Developer of the Original Code is Red Hat, Inc. |
32 | | * |
33 | | * Contributor(s): |
34 | | * Owen Taylor <otaylor@redhat.com> |
35 | | * Vladimir Vukicevic <vladimir@pobox.com> |
36 | | * Søren Sandmann <sandmann@daimi.au.dk> |
37 | | */ |
38 | | |
39 | | #include "cairoint.h" |
40 | | |
41 | | #include "cairo-error-private.h" |
42 | | #include "cairo-region-private.h" |
43 | | |
44 | | /* XXX need to update pixman headers to be const as appropriate */ |
45 | 25.7k | #define CONST_CAST (pixman_region32_t *) |
46 | | |
47 | | /** |
48 | | * SECTION:cairo-region |
49 | | * @Title: Regions |
50 | | * @Short_Description: Representing a pixel-aligned area |
51 | | * |
52 | | * Regions are a simple graphical data type representing an area of |
53 | | * integer-aligned rectangles. They are often used on raster surfaces |
54 | | * to track areas of interest, such as change or clip areas. |
55 | | **/ |
56 | | |
57 | | static const cairo_region_t _cairo_region_nil = { |
58 | | CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ |
59 | | CAIRO_STATUS_NO_MEMORY, /* status */ |
60 | | }; |
61 | | |
62 | | cairo_region_t * |
63 | | _cairo_region_create_in_error (cairo_status_t status) |
64 | 0 | { |
65 | 0 | switch (status) { |
66 | 0 | case CAIRO_STATUS_NO_MEMORY: |
67 | 0 | return (cairo_region_t *) &_cairo_region_nil; |
68 | | |
69 | 0 | case CAIRO_STATUS_SUCCESS: |
70 | 0 | case CAIRO_STATUS_LAST_STATUS: |
71 | 0 | ASSERT_NOT_REACHED; |
72 | | /* fall-through */ |
73 | 0 | case CAIRO_STATUS_SURFACE_TYPE_MISMATCH: |
74 | 0 | case CAIRO_STATUS_INVALID_STATUS: |
75 | 0 | case CAIRO_STATUS_INVALID_CONTENT: |
76 | 0 | case CAIRO_STATUS_INVALID_FORMAT: |
77 | 0 | case CAIRO_STATUS_INVALID_VISUAL: |
78 | 0 | case CAIRO_STATUS_READ_ERROR: |
79 | 0 | case CAIRO_STATUS_WRITE_ERROR: |
80 | 0 | case CAIRO_STATUS_FILE_NOT_FOUND: |
81 | 0 | case CAIRO_STATUS_TEMP_FILE_ERROR: |
82 | 0 | case CAIRO_STATUS_INVALID_STRIDE: |
83 | 0 | case CAIRO_STATUS_INVALID_SIZE: |
84 | 0 | case CAIRO_STATUS_DEVICE_TYPE_MISMATCH: |
85 | 0 | case CAIRO_STATUS_DEVICE_ERROR: |
86 | 0 | case CAIRO_STATUS_INVALID_RESTORE: |
87 | 0 | case CAIRO_STATUS_INVALID_POP_GROUP: |
88 | 0 | case CAIRO_STATUS_NO_CURRENT_POINT: |
89 | 0 | case CAIRO_STATUS_INVALID_MATRIX: |
90 | 0 | case CAIRO_STATUS_NULL_POINTER: |
91 | 0 | case CAIRO_STATUS_INVALID_STRING: |
92 | 0 | case CAIRO_STATUS_INVALID_PATH_DATA: |
93 | 0 | case CAIRO_STATUS_SURFACE_FINISHED: |
94 | 0 | case CAIRO_STATUS_PATTERN_TYPE_MISMATCH: |
95 | 0 | case CAIRO_STATUS_INVALID_DASH: |
96 | 0 | case CAIRO_STATUS_INVALID_DSC_COMMENT: |
97 | 0 | case CAIRO_STATUS_INVALID_INDEX: |
98 | 0 | case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE: |
99 | 0 | case CAIRO_STATUS_FONT_TYPE_MISMATCH: |
100 | 0 | case CAIRO_STATUS_USER_FONT_IMMUTABLE: |
101 | 0 | case CAIRO_STATUS_USER_FONT_ERROR: |
102 | 0 | case CAIRO_STATUS_NEGATIVE_COUNT: |
103 | 0 | case CAIRO_STATUS_INVALID_CLUSTERS: |
104 | 0 | case CAIRO_STATUS_INVALID_SLANT: |
105 | 0 | case CAIRO_STATUS_INVALID_WEIGHT: |
106 | 0 | case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED: |
107 | 0 | case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION: |
108 | 0 | case CAIRO_STATUS_DEVICE_FINISHED: |
109 | 0 | case CAIRO_STATUS_JBIG2_GLOBAL_MISSING: |
110 | 0 | case CAIRO_STATUS_PNG_ERROR: |
111 | 0 | case CAIRO_STATUS_FREETYPE_ERROR: |
112 | 0 | case CAIRO_STATUS_WIN32_GDI_ERROR: |
113 | 0 | case CAIRO_STATUS_TAG_ERROR: |
114 | 0 | case CAIRO_STATUS_DWRITE_ERROR: |
115 | 0 | case CAIRO_STATUS_SVG_FONT_ERROR: |
116 | 0 | default: |
117 | 0 | _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); |
118 | 0 | return (cairo_region_t *) &_cairo_region_nil; |
119 | 0 | } |
120 | 0 | } |
121 | | |
122 | | /** |
123 | | * _cairo_region_set_error: |
124 | | * @region: a region |
125 | | * @status: a status value indicating an error |
126 | | * |
127 | | * Atomically sets region->status to @status and calls _cairo_error; |
128 | | * Does nothing if status is %CAIRO_STATUS_SUCCESS or any of the internal |
129 | | * status values. |
130 | | * |
131 | | * All assignments of an error status to region->status should happen |
132 | | * through _cairo_region_set_error(). Note that due to the nature of |
133 | | * the atomic operation, it is not safe to call this function on the |
134 | | * nil objects. |
135 | | * |
136 | | * The purpose of this function is to allow the user to set a |
137 | | * breakpoint in _cairo_error() to generate a stack trace for when the |
138 | | * user causes cairo to detect an error. |
139 | | * |
140 | | * Return value: the error status. |
141 | | **/ |
142 | | static cairo_status_t |
143 | | _cairo_region_set_error (cairo_region_t *region, |
144 | | cairo_status_t status) |
145 | 0 | { |
146 | 0 | if (status == CAIRO_STATUS_SUCCESS) |
147 | 0 | return CAIRO_STATUS_SUCCESS; |
148 | | |
149 | | /* Don't overwrite an existing error. This preserves the first |
150 | | * error, which is the most significant. */ |
151 | 0 | _cairo_status_set_error (®ion->status, status); |
152 | |
|
153 | 0 | return _cairo_error (status); |
154 | 0 | } |
155 | | |
156 | | void |
157 | | _cairo_region_init (cairo_region_t *region) |
158 | 4 | { |
159 | 4 | VG (VALGRIND_MAKE_MEM_UNDEFINED (region, sizeof (cairo_region_t))); |
160 | | |
161 | 4 | region->status = CAIRO_STATUS_SUCCESS; |
162 | 4 | CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 0); |
163 | 4 | pixman_region32_init (®ion->rgn); |
164 | 4 | } |
165 | | |
166 | | void |
167 | | _cairo_region_init_rectangle (cairo_region_t *region, |
168 | | const cairo_rectangle_int_t *rectangle) |
169 | 0 | { |
170 | 0 | VG (VALGRIND_MAKE_MEM_UNDEFINED (region, sizeof (cairo_region_t))); |
171 | |
|
172 | 0 | region->status = CAIRO_STATUS_SUCCESS; |
173 | 0 | CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 0); |
174 | 0 | pixman_region32_init_rect (®ion->rgn, |
175 | 0 | rectangle->x, rectangle->y, |
176 | 0 | rectangle->width, rectangle->height); |
177 | 0 | } |
178 | | |
179 | | void |
180 | | _cairo_region_fini (cairo_region_t *region) |
181 | 25.7k | { |
182 | 25.7k | assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (®ion->ref_count)); |
183 | 25.7k | pixman_region32_fini (®ion->rgn); |
184 | 25.7k | VG (VALGRIND_MAKE_MEM_UNDEFINED (region, sizeof (cairo_region_t))); |
185 | 25.7k | } |
186 | | |
187 | | /** |
188 | | * cairo_region_create: |
189 | | * |
190 | | * Allocates a new empty region object. |
191 | | * |
192 | | * Return value: A newly allocated #cairo_region_t. Free with |
193 | | * cairo_region_destroy(). This function always returns a |
194 | | * valid pointer; if memory cannot be allocated, then a special |
195 | | * error object is returned where all operations on the object do nothing. |
196 | | * You can check for this with cairo_region_status(). |
197 | | * |
198 | | * Since: 1.10 |
199 | | **/ |
200 | | cairo_region_t * |
201 | | cairo_region_create (void) |
202 | 0 | { |
203 | 0 | cairo_region_t *region; |
204 | |
|
205 | 0 | region = _cairo_calloc (sizeof (cairo_region_t)); |
206 | 0 | if (region == NULL) |
207 | 0 | return (cairo_region_t *) &_cairo_region_nil; |
208 | | |
209 | 0 | region->status = CAIRO_STATUS_SUCCESS; |
210 | 0 | CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 1); |
211 | |
|
212 | 0 | pixman_region32_init (®ion->rgn); |
213 | |
|
214 | 0 | return region; |
215 | 0 | } |
216 | | |
217 | | /** |
218 | | * cairo_region_create_rectangles: |
219 | | * @rects: an array of @count rectangles |
220 | | * @count: number of rectangles |
221 | | * |
222 | | * Allocates a new region object containing the union of all given @rects. |
223 | | * |
224 | | * Return value: A newly allocated #cairo_region_t. Free with |
225 | | * cairo_region_destroy(). This function always returns a |
226 | | * valid pointer; if memory cannot be allocated, then a special |
227 | | * error object is returned where all operations on the object do nothing. |
228 | | * You can check for this with cairo_region_status(). |
229 | | * |
230 | | * Since: 1.10 |
231 | | **/ |
232 | | cairo_region_t * |
233 | | cairo_region_create_rectangles (const cairo_rectangle_int_t *rects, |
234 | | int count) |
235 | 25.7k | { |
236 | 25.7k | pixman_box32_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box32_t)]; |
237 | 25.7k | pixman_box32_t *pboxes = stack_pboxes; |
238 | 25.7k | cairo_region_t *region; |
239 | 25.7k | int i; |
240 | | |
241 | 25.7k | region = _cairo_calloc (sizeof (cairo_region_t)); |
242 | 25.7k | if (unlikely (region == NULL)) |
243 | 0 | return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
244 | | |
245 | 25.7k | CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 1); |
246 | 25.7k | region->status = CAIRO_STATUS_SUCCESS; |
247 | | |
248 | 25.7k | if (count == 1) { |
249 | 25.7k | pixman_region32_init_rect (®ion->rgn, |
250 | 25.7k | rects->x, rects->y, |
251 | 25.7k | rects->width, rects->height); |
252 | | |
253 | 25.7k | return region; |
254 | 25.7k | } |
255 | | |
256 | 0 | if (count > ARRAY_LENGTH (stack_pboxes)) { |
257 | 0 | pboxes = _cairo_malloc_ab (count, sizeof (pixman_box32_t)); |
258 | 0 | if (unlikely (pboxes == NULL)) { |
259 | 0 | free (region); |
260 | 0 | return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
261 | 0 | } |
262 | 0 | } |
263 | | |
264 | 0 | for (i = 0; i < count; i++) { |
265 | 0 | pboxes[i].x1 = rects[i].x; |
266 | 0 | pboxes[i].y1 = rects[i].y; |
267 | 0 | pboxes[i].x2 = rects[i].x + rects[i].width; |
268 | 0 | pboxes[i].y2 = rects[i].y + rects[i].height; |
269 | 0 | } |
270 | |
|
271 | 0 | i = pixman_region32_init_rects (®ion->rgn, pboxes, count); |
272 | |
|
273 | 0 | if (pboxes != stack_pboxes) |
274 | 0 | free (pboxes); |
275 | |
|
276 | 0 | if (unlikely (i == 0)) { |
277 | 0 | free (region); |
278 | 0 | return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
279 | 0 | } |
280 | | |
281 | 0 | return region; |
282 | 0 | } |
283 | | |
284 | | cairo_region_t * |
285 | | _cairo_region_create_from_boxes (const cairo_box_t *boxes, int count) |
286 | 0 | { |
287 | 0 | cairo_region_t *region; |
288 | |
|
289 | 0 | region = _cairo_calloc (sizeof (cairo_region_t)); |
290 | 0 | if (unlikely (region == NULL)) |
291 | 0 | return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
292 | | |
293 | 0 | CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 1); |
294 | 0 | region->status = CAIRO_STATUS_SUCCESS; |
295 | |
|
296 | 0 | if (! pixman_region32_init_rects (®ion->rgn, |
297 | 0 | (pixman_box32_t *)boxes, count)) { |
298 | 0 | free (region); |
299 | 0 | return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
300 | 0 | } |
301 | | |
302 | 0 | return region; |
303 | 0 | } |
304 | | |
305 | | cairo_box_t * |
306 | | _cairo_region_get_boxes (const cairo_region_t *region, int *nbox) |
307 | 0 | { |
308 | 0 | if (region->status) { |
309 | 0 | nbox = 0; |
310 | 0 | return NULL; |
311 | 0 | } |
312 | | |
313 | 0 | return (cairo_box_t *) pixman_region32_rectangles (CONST_CAST ®ion->rgn, nbox); |
314 | 0 | } |
315 | | |
316 | | /** |
317 | | * cairo_region_create_rectangle: |
318 | | * @rectangle: a #cairo_rectangle_int_t |
319 | | * |
320 | | * Allocates a new region object containing @rectangle. |
321 | | * |
322 | | * Return value: A newly allocated #cairo_region_t. Free with |
323 | | * cairo_region_destroy(). This function always returns a |
324 | | * valid pointer; if memory cannot be allocated, then a special |
325 | | * error object is returned where all operations on the object do nothing. |
326 | | * You can check for this with cairo_region_status(). |
327 | | * |
328 | | * Since: 1.10 |
329 | | **/ |
330 | | cairo_region_t * |
331 | | cairo_region_create_rectangle (const cairo_rectangle_int_t *rectangle) |
332 | 0 | { |
333 | 0 | cairo_region_t *region; |
334 | |
|
335 | 0 | region = _cairo_calloc (sizeof (cairo_region_t)); |
336 | 0 | if (unlikely (region == NULL)) |
337 | 0 | return (cairo_region_t *) &_cairo_region_nil; |
338 | | |
339 | 0 | region->status = CAIRO_STATUS_SUCCESS; |
340 | 0 | CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 1); |
341 | |
|
342 | 0 | pixman_region32_init_rect (®ion->rgn, |
343 | 0 | rectangle->x, rectangle->y, |
344 | 0 | rectangle->width, rectangle->height); |
345 | |
|
346 | 0 | return region; |
347 | 0 | } |
348 | | |
349 | | /** |
350 | | * cairo_region_copy: |
351 | | * @original: a #cairo_region_t |
352 | | * |
353 | | * Allocates a new region object copying the area from @original. |
354 | | * |
355 | | * Return value: A newly allocated #cairo_region_t. Free with |
356 | | * cairo_region_destroy(). This function always returns a |
357 | | * valid pointer; if memory cannot be allocated, then a special |
358 | | * error object is returned where all operations on the object do nothing. |
359 | | * You can check for this with cairo_region_status(). |
360 | | * |
361 | | * Since: 1.10 |
362 | | **/ |
363 | | cairo_region_t * |
364 | | cairo_region_copy (const cairo_region_t *original) |
365 | 0 | { |
366 | 0 | cairo_region_t *copy; |
367 | |
|
368 | 0 | if (original != NULL && original->status) |
369 | 0 | return (cairo_region_t *) &_cairo_region_nil; |
370 | | |
371 | 0 | copy = cairo_region_create (); |
372 | 0 | if (unlikely (copy->status)) |
373 | 0 | return copy; |
374 | | |
375 | 0 | if (original != NULL && |
376 | 0 | ! pixman_region32_copy (©->rgn, CONST_CAST &original->rgn)) |
377 | 0 | { |
378 | 0 | cairo_region_destroy (copy); |
379 | 0 | return (cairo_region_t *) &_cairo_region_nil; |
380 | 0 | } |
381 | | |
382 | 0 | return copy; |
383 | 0 | } |
384 | | |
385 | | /** |
386 | | * cairo_region_reference: |
387 | | * @region: a #cairo_region_t |
388 | | * |
389 | | * Increases the reference count on @region by one. This prevents |
390 | | * @region from being destroyed until a matching call to |
391 | | * cairo_region_destroy() is made. |
392 | | * |
393 | | * Return value: the referenced #cairo_region_t. |
394 | | * |
395 | | * Since: 1.10 |
396 | | **/ |
397 | | cairo_region_t * |
398 | | cairo_region_reference (cairo_region_t *region) |
399 | 17.3k | { |
400 | 17.3k | if (region == NULL || CAIRO_REFERENCE_COUNT_IS_INVALID (®ion->ref_count)) |
401 | 17.3k | return NULL; |
402 | | |
403 | 17.3k | assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (®ion->ref_count)); |
404 | |
|
405 | 0 | _cairo_reference_count_inc (®ion->ref_count); |
406 | 0 | return region; |
407 | 0 | } |
408 | | |
409 | | /** |
410 | | * cairo_region_destroy: |
411 | | * @region: a #cairo_region_t |
412 | | * |
413 | | * Destroys a #cairo_region_t object created with |
414 | | * cairo_region_create(), cairo_region_copy(), or |
415 | | * or cairo_region_create_rectangle(). |
416 | | * |
417 | | * Since: 1.10 |
418 | | **/ |
419 | | void |
420 | | cairo_region_destroy (cairo_region_t *region) |
421 | 4.64M | { |
422 | 4.64M | if (region == NULL || CAIRO_REFERENCE_COUNT_IS_INVALID (®ion->ref_count)) |
423 | 4.62M | return; |
424 | | |
425 | 4.64M | assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (®ion->ref_count)); |
426 | | |
427 | 25.7k | if (! _cairo_reference_count_dec_and_test (®ion->ref_count)) |
428 | 0 | return; |
429 | | |
430 | 25.7k | _cairo_region_fini (region); |
431 | 25.7k | free (region); |
432 | 25.7k | } |
433 | | |
434 | | /** |
435 | | * cairo_region_num_rectangles: |
436 | | * @region: a #cairo_region_t |
437 | | * |
438 | | * Returns the number of rectangles contained in @region. |
439 | | * |
440 | | * Return value: The number of rectangles contained in @region. |
441 | | * |
442 | | * Since: 1.10 |
443 | | **/ |
444 | | int |
445 | | cairo_region_num_rectangles (const cairo_region_t *region) |
446 | 0 | { |
447 | 0 | if (region->status) |
448 | 0 | return 0; |
449 | | |
450 | 0 | return pixman_region32_n_rects (CONST_CAST ®ion->rgn); |
451 | 0 | } |
452 | | |
453 | | /** |
454 | | * cairo_region_get_rectangle: |
455 | | * @region: a #cairo_region_t |
456 | | * @nth: a number indicating which rectangle should be returned |
457 | | * @rectangle: return location for a #cairo_rectangle_int_t |
458 | | * |
459 | | * Stores the @nth rectangle from the region in @rectangle. |
460 | | * |
461 | | * Since: 1.10 |
462 | | **/ |
463 | | void |
464 | | cairo_region_get_rectangle (const cairo_region_t *region, |
465 | | int nth, |
466 | | cairo_rectangle_int_t *rectangle) |
467 | 0 | { |
468 | 0 | pixman_box32_t *pbox; |
469 | |
|
470 | 0 | if (region->status) { |
471 | 0 | rectangle->x = rectangle->y = 0; |
472 | 0 | rectangle->width = rectangle->height = 0; |
473 | 0 | return; |
474 | 0 | } |
475 | | |
476 | 0 | pbox = pixman_region32_rectangles (CONST_CAST ®ion->rgn, NULL) + nth; |
477 | |
|
478 | 0 | rectangle->x = pbox->x1; |
479 | 0 | rectangle->y = pbox->y1; |
480 | 0 | rectangle->width = pbox->x2 - pbox->x1; |
481 | 0 | rectangle->height = pbox->y2 - pbox->y1; |
482 | 0 | } |
483 | | |
484 | | /** |
485 | | * cairo_region_get_extents: |
486 | | * @region: a #cairo_region_t |
487 | | * @extents: rectangle into which to store the extents |
488 | | * |
489 | | * Gets the bounding rectangle of @region as a #cairo_rectangle_int_t |
490 | | * |
491 | | * Since: 1.10 |
492 | | **/ |
493 | | void |
494 | | cairo_region_get_extents (const cairo_region_t *region, |
495 | | cairo_rectangle_int_t *extents) |
496 | 0 | { |
497 | 0 | pixman_box32_t *pextents; |
498 | |
|
499 | 0 | if (region->status) { |
500 | 0 | extents->x = extents->y = 0; |
501 | 0 | extents->width = extents->height = 0; |
502 | 0 | return; |
503 | 0 | } |
504 | | |
505 | 0 | pextents = pixman_region32_extents (CONST_CAST ®ion->rgn); |
506 | |
|
507 | 0 | extents->x = pextents->x1; |
508 | 0 | extents->y = pextents->y1; |
509 | 0 | extents->width = pextents->x2 - pextents->x1; |
510 | 0 | extents->height = pextents->y2 - pextents->y1; |
511 | 0 | } |
512 | | |
513 | | /** |
514 | | * cairo_region_status: |
515 | | * @region: a #cairo_region_t |
516 | | * |
517 | | * Checks whether an error has previous occurred for this |
518 | | * region object. |
519 | | * |
520 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
521 | | * |
522 | | * Since: 1.10 |
523 | | **/ |
524 | | cairo_status_t |
525 | | cairo_region_status (const cairo_region_t *region) |
526 | 0 | { |
527 | 0 | return region->status; |
528 | 0 | } |
529 | | |
530 | | /** |
531 | | * cairo_region_subtract: |
532 | | * @dst: a #cairo_region_t |
533 | | * @other: another #cairo_region_t |
534 | | * |
535 | | * Subtracts @other from @dst and places the result in @dst |
536 | | * |
537 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
538 | | * |
539 | | * Since: 1.10 |
540 | | **/ |
541 | | cairo_status_t |
542 | | cairo_region_subtract (cairo_region_t *dst, const cairo_region_t *other) |
543 | 0 | { |
544 | 0 | if (dst->status) |
545 | 0 | return dst->status; |
546 | | |
547 | 0 | if (other->status) |
548 | 0 | return _cairo_region_set_error (dst, other->status); |
549 | | |
550 | 0 | if (! pixman_region32_subtract (&dst->rgn, |
551 | 0 | &dst->rgn, |
552 | 0 | CONST_CAST &other->rgn)) |
553 | 0 | { |
554 | 0 | return _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); |
555 | 0 | } |
556 | | |
557 | 0 | return CAIRO_STATUS_SUCCESS; |
558 | 0 | } |
559 | | |
560 | | /** |
561 | | * cairo_region_subtract_rectangle: |
562 | | * @dst: a #cairo_region_t |
563 | | * @rectangle: a #cairo_rectangle_int_t |
564 | | * |
565 | | * Subtracts @rectangle from @dst and places the result in @dst |
566 | | * |
567 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
568 | | * |
569 | | * Since: 1.10 |
570 | | **/ |
571 | | cairo_status_t |
572 | | cairo_region_subtract_rectangle (cairo_region_t *dst, |
573 | | const cairo_rectangle_int_t *rectangle) |
574 | 0 | { |
575 | 0 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
576 | 0 | pixman_region32_t region; |
577 | |
|
578 | 0 | if (dst->status) |
579 | 0 | return dst->status; |
580 | | |
581 | 0 | pixman_region32_init_rect (®ion, |
582 | 0 | rectangle->x, rectangle->y, |
583 | 0 | rectangle->width, rectangle->height); |
584 | |
|
585 | 0 | if (! pixman_region32_subtract (&dst->rgn, &dst->rgn, ®ion)) |
586 | 0 | status = _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); |
587 | |
|
588 | 0 | pixman_region32_fini (®ion); |
589 | |
|
590 | 0 | return status; |
591 | 0 | } |
592 | | |
593 | | /** |
594 | | * cairo_region_intersect: |
595 | | * @dst: a #cairo_region_t |
596 | | * @other: another #cairo_region_t |
597 | | * |
598 | | * Computes the intersection of @dst with @other and places the result in @dst |
599 | | * |
600 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
601 | | * |
602 | | * Since: 1.10 |
603 | | **/ |
604 | | cairo_status_t |
605 | | cairo_region_intersect (cairo_region_t *dst, const cairo_region_t *other) |
606 | 0 | { |
607 | 0 | if (dst->status) |
608 | 0 | return dst->status; |
609 | | |
610 | 0 | if (other->status) |
611 | 0 | return _cairo_region_set_error (dst, other->status); |
612 | | |
613 | 0 | if (! pixman_region32_intersect (&dst->rgn, &dst->rgn, CONST_CAST &other->rgn)) |
614 | 0 | return _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); |
615 | | |
616 | 0 | return CAIRO_STATUS_SUCCESS; |
617 | 0 | } |
618 | | |
619 | | /** |
620 | | * cairo_region_intersect_rectangle: |
621 | | * @dst: a #cairo_region_t |
622 | | * @rectangle: a #cairo_rectangle_int_t |
623 | | * |
624 | | * Computes the intersection of @dst with @rectangle and places the |
625 | | * result in @dst |
626 | | * |
627 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
628 | | * |
629 | | * Since: 1.10 |
630 | | **/ |
631 | | cairo_status_t |
632 | | cairo_region_intersect_rectangle (cairo_region_t *dst, |
633 | | const cairo_rectangle_int_t *rectangle) |
634 | 0 | { |
635 | 0 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
636 | 0 | pixman_region32_t region; |
637 | |
|
638 | 0 | if (dst->status) |
639 | 0 | return dst->status; |
640 | | |
641 | 0 | pixman_region32_init_rect (®ion, |
642 | 0 | rectangle->x, rectangle->y, |
643 | 0 | rectangle->width, rectangle->height); |
644 | |
|
645 | 0 | if (! pixman_region32_intersect (&dst->rgn, &dst->rgn, ®ion)) |
646 | 0 | status = _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); |
647 | |
|
648 | 0 | pixman_region32_fini (®ion); |
649 | |
|
650 | 0 | return status; |
651 | 0 | } |
652 | | |
653 | | /** |
654 | | * cairo_region_union: |
655 | | * @dst: a #cairo_region_t |
656 | | * @other: another #cairo_region_t |
657 | | * |
658 | | * Computes the union of @dst with @other and places the result in @dst |
659 | | * |
660 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
661 | | * |
662 | | * Since: 1.10 |
663 | | **/ |
664 | | cairo_status_t |
665 | | cairo_region_union (cairo_region_t *dst, |
666 | | const cairo_region_t *other) |
667 | 0 | { |
668 | 0 | if (dst->status) |
669 | 0 | return dst->status; |
670 | | |
671 | 0 | if (other->status) |
672 | 0 | return _cairo_region_set_error (dst, other->status); |
673 | | |
674 | 0 | if (! pixman_region32_union (&dst->rgn, &dst->rgn, CONST_CAST &other->rgn)) |
675 | 0 | return _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); |
676 | | |
677 | 0 | return CAIRO_STATUS_SUCCESS; |
678 | 0 | } |
679 | | |
680 | | /** |
681 | | * cairo_region_union_rectangle: |
682 | | * @dst: a #cairo_region_t |
683 | | * @rectangle: a #cairo_rectangle_int_t |
684 | | * |
685 | | * Computes the union of @dst with @rectangle and places the result in @dst. |
686 | | * |
687 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
688 | | * |
689 | | * Since: 1.10 |
690 | | **/ |
691 | | cairo_status_t |
692 | | cairo_region_union_rectangle (cairo_region_t *dst, |
693 | | const cairo_rectangle_int_t *rectangle) |
694 | 0 | { |
695 | 0 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
696 | 0 | pixman_region32_t region; |
697 | |
|
698 | 0 | if (dst->status) |
699 | 0 | return dst->status; |
700 | | |
701 | 0 | pixman_region32_init_rect (®ion, |
702 | 0 | rectangle->x, rectangle->y, |
703 | 0 | rectangle->width, rectangle->height); |
704 | |
|
705 | 0 | if (! pixman_region32_union (&dst->rgn, &dst->rgn, ®ion)) |
706 | 0 | status = _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); |
707 | |
|
708 | 0 | pixman_region32_fini (®ion); |
709 | |
|
710 | 0 | return status; |
711 | 0 | } |
712 | | |
713 | | /** |
714 | | * cairo_region_xor: |
715 | | * @dst: a #cairo_region_t |
716 | | * @other: another #cairo_region_t |
717 | | * |
718 | | * Computes the exclusive difference of @dst with @other and places the |
719 | | * result in @dst. That is, @dst will be set to contain all areas that |
720 | | * are either in @dst or in @other, but not in both. |
721 | | * |
722 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
723 | | * |
724 | | * Since: 1.10 |
725 | | **/ |
726 | | cairo_status_t |
727 | | cairo_region_xor (cairo_region_t *dst, const cairo_region_t *other) |
728 | 0 | { |
729 | 0 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
730 | 0 | pixman_region32_t tmp; |
731 | |
|
732 | 0 | if (dst->status) |
733 | 0 | return dst->status; |
734 | | |
735 | 0 | if (other->status) |
736 | 0 | return _cairo_region_set_error (dst, other->status); |
737 | | |
738 | 0 | pixman_region32_init (&tmp); |
739 | | |
740 | | /* XXX: get an xor function into pixman */ |
741 | 0 | if (! pixman_region32_subtract (&tmp, CONST_CAST &other->rgn, &dst->rgn) || |
742 | 0 | ! pixman_region32_subtract (&dst->rgn, &dst->rgn, CONST_CAST &other->rgn) || |
743 | 0 | ! pixman_region32_union (&dst->rgn, &dst->rgn, &tmp)) |
744 | 0 | status = _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); |
745 | |
|
746 | 0 | pixman_region32_fini (&tmp); |
747 | |
|
748 | 0 | return status; |
749 | 0 | } |
750 | | |
751 | | /** |
752 | | * cairo_region_xor_rectangle: |
753 | | * @dst: a #cairo_region_t |
754 | | * @rectangle: a #cairo_rectangle_int_t |
755 | | * |
756 | | * Computes the exclusive difference of @dst with @rectangle and places the |
757 | | * result in @dst. That is, @dst will be set to contain all areas that are |
758 | | * either in @dst or in @rectangle, but not in both. |
759 | | * |
760 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
761 | | * |
762 | | * Since: 1.10 |
763 | | **/ |
764 | | cairo_status_t |
765 | | cairo_region_xor_rectangle (cairo_region_t *dst, |
766 | | const cairo_rectangle_int_t *rectangle) |
767 | 0 | { |
768 | 0 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
769 | 0 | pixman_region32_t region, tmp; |
770 | |
|
771 | 0 | if (dst->status) |
772 | 0 | return dst->status; |
773 | | |
774 | 0 | pixman_region32_init_rect (®ion, |
775 | 0 | rectangle->x, rectangle->y, |
776 | 0 | rectangle->width, rectangle->height); |
777 | 0 | pixman_region32_init (&tmp); |
778 | | |
779 | | /* XXX: get an xor function into pixman */ |
780 | 0 | if (! pixman_region32_subtract (&tmp, ®ion, &dst->rgn) || |
781 | 0 | ! pixman_region32_subtract (&dst->rgn, &dst->rgn, ®ion) || |
782 | 0 | ! pixman_region32_union (&dst->rgn, &dst->rgn, &tmp)) |
783 | 0 | status = _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); |
784 | |
|
785 | 0 | pixman_region32_fini (&tmp); |
786 | 0 | pixman_region32_fini (®ion); |
787 | |
|
788 | 0 | return status; |
789 | 0 | } |
790 | | |
791 | | /** |
792 | | * cairo_region_is_empty: |
793 | | * @region: a #cairo_region_t |
794 | | * |
795 | | * Checks whether @region is empty. |
796 | | * |
797 | | * Return value: %TRUE if @region is empty, %FALSE if it isn't. |
798 | | * |
799 | | * Since: 1.10 |
800 | | **/ |
801 | | cairo_bool_t |
802 | | cairo_region_is_empty (const cairo_region_t *region) |
803 | 0 | { |
804 | 0 | if (region->status) |
805 | 0 | return TRUE; |
806 | | |
807 | 0 | return ! pixman_region32_not_empty (CONST_CAST ®ion->rgn); |
808 | 0 | } |
809 | | |
810 | | /** |
811 | | * cairo_region_translate: |
812 | | * @region: a #cairo_region_t |
813 | | * @dx: Amount to translate in the x direction |
814 | | * @dy: Amount to translate in the y direction |
815 | | * |
816 | | * Translates @region by (@dx, @dy). |
817 | | * |
818 | | * Since: 1.10 |
819 | | **/ |
820 | | void |
821 | | cairo_region_translate (cairo_region_t *region, |
822 | | int dx, int dy) |
823 | 0 | { |
824 | 0 | if (region->status) |
825 | 0 | return; |
826 | | |
827 | 0 | pixman_region32_translate (®ion->rgn, dx, dy); |
828 | 0 | } |
829 | | |
830 | | /** |
831 | | * cairo_region_contains_rectangle: |
832 | | * @region: a #cairo_region_t |
833 | | * @rectangle: a #cairo_rectangle_int_t |
834 | | * |
835 | | * Checks whether @rectangle is inside, outside or partially contained |
836 | | * in @region |
837 | | * |
838 | | * Return value: |
839 | | * %CAIRO_REGION_OVERLAP_IN if @rectangle is entirely inside @region, |
840 | | * %CAIRO_REGION_OVERLAP_OUT if @rectangle is entirely outside @region, or |
841 | | * %CAIRO_REGION_OVERLAP_PART if @rectangle is partially inside and partially outside @region. |
842 | | * |
843 | | * Since: 1.10 |
844 | | **/ |
845 | | cairo_region_overlap_t |
846 | | cairo_region_contains_rectangle (const cairo_region_t *region, |
847 | | const cairo_rectangle_int_t *rectangle) |
848 | 25.7k | { |
849 | 25.7k | pixman_box32_t pbox; |
850 | 25.7k | pixman_region_overlap_t poverlap; |
851 | | |
852 | 25.7k | if (region->status) |
853 | 0 | return CAIRO_REGION_OVERLAP_OUT; |
854 | | |
855 | 25.7k | pbox.x1 = rectangle->x; |
856 | 25.7k | pbox.y1 = rectangle->y; |
857 | 25.7k | pbox.x2 = rectangle->x + rectangle->width; |
858 | 25.7k | pbox.y2 = rectangle->y + rectangle->height; |
859 | | |
860 | 25.7k | poverlap = pixman_region32_contains_rectangle (CONST_CAST ®ion->rgn, |
861 | 25.7k | &pbox); |
862 | 25.7k | switch (poverlap) { |
863 | 0 | default: |
864 | 0 | case PIXMAN_REGION_OUT: return CAIRO_REGION_OVERLAP_OUT; |
865 | 25.7k | case PIXMAN_REGION_IN: return CAIRO_REGION_OVERLAP_IN; |
866 | 0 | case PIXMAN_REGION_PART: return CAIRO_REGION_OVERLAP_PART; |
867 | 25.7k | } |
868 | 25.7k | } |
869 | | |
870 | | /** |
871 | | * cairo_region_contains_point: |
872 | | * @region: a #cairo_region_t |
873 | | * @x: the x coordinate of a point |
874 | | * @y: the y coordinate of a point |
875 | | * |
876 | | * Checks whether (@x, @y) is contained in @region. |
877 | | * |
878 | | * Return value: %TRUE if (@x, @y) is contained in @region, %FALSE if it is not. |
879 | | * |
880 | | * Since: 1.10 |
881 | | **/ |
882 | | cairo_bool_t |
883 | | cairo_region_contains_point (const cairo_region_t *region, |
884 | | int x, int y) |
885 | 0 | { |
886 | 0 | pixman_box32_t box; |
887 | |
|
888 | 0 | if (region->status) |
889 | 0 | return FALSE; |
890 | | |
891 | 0 | return pixman_region32_contains_point (CONST_CAST ®ion->rgn, x, y, &box); |
892 | 0 | } |
893 | | |
894 | | /** |
895 | | * cairo_region_equal: |
896 | | * @a: a #cairo_region_t or %NULL |
897 | | * @b: a #cairo_region_t or %NULL |
898 | | * |
899 | | * Compares whether region_a is equivalent to region_b. %NULL as an argument |
900 | | * is equal to itself, but not to any non-%NULL region. |
901 | | * |
902 | | * Return value: %TRUE if both regions contained the same coverage, |
903 | | * %FALSE if it is not or any region is in an error status. |
904 | | * |
905 | | * Since: 1.10 |
906 | | **/ |
907 | | cairo_bool_t |
908 | | cairo_region_equal (const cairo_region_t *a, |
909 | | const cairo_region_t *b) |
910 | 0 | { |
911 | | /* error objects are never equal */ |
912 | 0 | if ((a != NULL && a->status) || (b != NULL && b->status)) |
913 | 0 | return FALSE; |
914 | | |
915 | 0 | if (a == b) |
916 | 0 | return TRUE; |
917 | | |
918 | 0 | if (a == NULL || b == NULL) |
919 | 0 | return FALSE; |
920 | | |
921 | 0 | return pixman_region32_equal (CONST_CAST &a->rgn, CONST_CAST &b->rgn); |
922 | 0 | } |