/work/workdir/UnpackedTarball/cairo/src/cairo-region.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 © 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 | 17.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 | default: |
116 | 0 | _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); |
117 | 0 | return (cairo_region_t *) &_cairo_region_nil; |
118 | 0 | } |
119 | 0 | } |
120 | | |
121 | | /** |
122 | | * _cairo_region_set_error: |
123 | | * @region: a region |
124 | | * @status: a status value indicating an error |
125 | | * |
126 | | * Atomically sets region->status to @status and calls _cairo_error; |
127 | | * Does nothing if status is %CAIRO_STATUS_SUCCESS or any of the internal |
128 | | * status values. |
129 | | * |
130 | | * All assignments of an error status to region->status should happen |
131 | | * through _cairo_region_set_error(). Note that due to the nature of |
132 | | * the atomic operation, it is not safe to call this function on the |
133 | | * nil objects. |
134 | | * |
135 | | * The purpose of this function is to allow the user to set a |
136 | | * breakpoint in _cairo_error() to generate a stack trace for when the |
137 | | * user causes cairo to detect an error. |
138 | | * |
139 | | * Return value: the error status. |
140 | | **/ |
141 | | static cairo_status_t |
142 | | _cairo_region_set_error (cairo_region_t *region, |
143 | | cairo_status_t status) |
144 | 0 | { |
145 | 0 | if (status == CAIRO_STATUS_SUCCESS) |
146 | 0 | return CAIRO_STATUS_SUCCESS; |
147 | | |
148 | | /* Don't overwrite an existing error. This preserves the first |
149 | | * error, which is the most significant. */ |
150 | 0 | _cairo_status_set_error (®ion->status, status); |
151 | | |
152 | 0 | return _cairo_error (status); |
153 | 0 | } |
154 | | |
155 | | void |
156 | | _cairo_region_init (cairo_region_t *region) |
157 | 4 | { |
158 | 4 | VG (VALGRIND_MAKE_MEM_UNDEFINED (region, sizeof (cairo_region_t))); |
159 | | |
160 | 4 | region->status = CAIRO_STATUS_SUCCESS; |
161 | 4 | CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 0); |
162 | 4 | pixman_region32_init (®ion->rgn); |
163 | 4 | } |
164 | | |
165 | | void |
166 | | _cairo_region_init_rectangle (cairo_region_t *region, |
167 | | const cairo_rectangle_int_t *rectangle) |
168 | 0 | { |
169 | 0 | VG (VALGRIND_MAKE_MEM_UNDEFINED (region, sizeof (cairo_region_t))); |
170 | |
|
171 | 0 | region->status = CAIRO_STATUS_SUCCESS; |
172 | 0 | CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 0); |
173 | 0 | pixman_region32_init_rect (®ion->rgn, |
174 | 0 | rectangle->x, rectangle->y, |
175 | 0 | rectangle->width, rectangle->height); |
176 | 0 | } |
177 | | |
178 | | void |
179 | | _cairo_region_fini (cairo_region_t *region) |
180 | 17.7k | { |
181 | 17.7k | assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (®ion->ref_count)); |
182 | 17.7k | pixman_region32_fini (®ion->rgn); |
183 | 17.7k | VG (VALGRIND_MAKE_MEM_UNDEFINED (region, sizeof (cairo_region_t))); |
184 | 17.7k | } |
185 | | |
186 | | /** |
187 | | * cairo_region_create: |
188 | | * |
189 | | * Allocates a new empty region object. |
190 | | * |
191 | | * Return value: A newly allocated #cairo_region_t. Free with |
192 | | * cairo_region_destroy(). This function always returns a |
193 | | * valid pointer; if memory cannot be allocated, then a special |
194 | | * error object is returned where all operations on the object do nothing. |
195 | | * You can check for this with cairo_region_status(). |
196 | | * |
197 | | * Since: 1.10 |
198 | | **/ |
199 | | cairo_region_t * |
200 | | cairo_region_create (void) |
201 | 0 | { |
202 | 0 | cairo_region_t *region; |
203 | |
|
204 | 0 | region = _cairo_malloc (sizeof (cairo_region_t)); |
205 | 0 | if (region == NULL) |
206 | 0 | return (cairo_region_t *) &_cairo_region_nil; |
207 | | |
208 | 0 | region->status = CAIRO_STATUS_SUCCESS; |
209 | 0 | CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 1); |
210 | |
|
211 | 0 | pixman_region32_init (®ion->rgn); |
212 | |
|
213 | 0 | return region; |
214 | 0 | } |
215 | | slim_hidden_def (cairo_region_create); |
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 | 17.7k | { |
236 | 17.7k | pixman_box32_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box32_t)]; |
237 | 17.7k | pixman_box32_t *pboxes = stack_pboxes; |
238 | 17.7k | cairo_region_t *region; |
239 | 17.7k | int i; |
240 | | |
241 | 17.7k | region = _cairo_malloc (sizeof (cairo_region_t)); |
242 | 17.7k | if (unlikely (region == NULL)) |
243 | 0 | return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
244 | | |
245 | 17.7k | CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 1); |
246 | 17.7k | region->status = CAIRO_STATUS_SUCCESS; |
247 | | |
248 | 17.7k | if (count == 1) { |
249 | 17.7k | pixman_region32_init_rect (®ion->rgn, |
250 | 17.7k | rects->x, rects->y, |
251 | 17.7k | rects->width, rects->height); |
252 | | |
253 | 17.7k | return region; |
254 | 17.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 | | slim_hidden_def (cairo_region_create_rectangles); |
284 | | |
285 | | cairo_region_t * |
286 | | _cairo_region_create_from_boxes (const cairo_box_t *boxes, int count) |
287 | 0 | { |
288 | 0 | cairo_region_t *region; |
289 | |
|
290 | 0 | region = _cairo_malloc (sizeof (cairo_region_t)); |
291 | 0 | if (unlikely (region == NULL)) |
292 | 0 | return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
293 | | |
294 | 0 | CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 1); |
295 | 0 | region->status = CAIRO_STATUS_SUCCESS; |
296 | |
|
297 | 0 | if (! pixman_region32_init_rects (®ion->rgn, |
298 | 0 | (pixman_box32_t *)boxes, count)) { |
299 | 0 | free (region); |
300 | 0 | return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
301 | 0 | } |
302 | | |
303 | 0 | return region; |
304 | 0 | } |
305 | | |
306 | | cairo_box_t * |
307 | | _cairo_region_get_boxes (const cairo_region_t *region, int *nbox) |
308 | 0 | { |
309 | 0 | if (region->status) { |
310 | 0 | nbox = 0; |
311 | 0 | return NULL; |
312 | 0 | } |
313 | | |
314 | 0 | return (cairo_box_t *) pixman_region32_rectangles (CONST_CAST ®ion->rgn, nbox); |
315 | 0 | } |
316 | | |
317 | | /** |
318 | | * cairo_region_create_rectangle: |
319 | | * @rectangle: a #cairo_rectangle_int_t |
320 | | * |
321 | | * Allocates a new region object containing @rectangle. |
322 | | * |
323 | | * Return value: A newly allocated #cairo_region_t. Free with |
324 | | * cairo_region_destroy(). This function always returns a |
325 | | * valid pointer; if memory cannot be allocated, then a special |
326 | | * error object is returned where all operations on the object do nothing. |
327 | | * You can check for this with cairo_region_status(). |
328 | | * |
329 | | * Since: 1.10 |
330 | | **/ |
331 | | cairo_region_t * |
332 | | cairo_region_create_rectangle (const cairo_rectangle_int_t *rectangle) |
333 | 0 | { |
334 | 0 | cairo_region_t *region; |
335 | |
|
336 | 0 | region = _cairo_malloc (sizeof (cairo_region_t)); |
337 | 0 | if (unlikely (region == NULL)) |
338 | 0 | return (cairo_region_t *) &_cairo_region_nil; |
339 | | |
340 | 0 | region->status = CAIRO_STATUS_SUCCESS; |
341 | 0 | CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 1); |
342 | |
|
343 | 0 | pixman_region32_init_rect (®ion->rgn, |
344 | 0 | rectangle->x, rectangle->y, |
345 | 0 | rectangle->width, rectangle->height); |
346 | |
|
347 | 0 | return region; |
348 | 0 | } |
349 | | slim_hidden_def (cairo_region_create_rectangle); |
350 | | |
351 | | /** |
352 | | * cairo_region_copy: |
353 | | * @original: a #cairo_region_t |
354 | | * |
355 | | * Allocates a new region object copying the area from @original. |
356 | | * |
357 | | * Return value: A newly allocated #cairo_region_t. Free with |
358 | | * cairo_region_destroy(). This function always returns a |
359 | | * valid pointer; if memory cannot be allocated, then a special |
360 | | * error object is returned where all operations on the object do nothing. |
361 | | * You can check for this with cairo_region_status(). |
362 | | * |
363 | | * Since: 1.10 |
364 | | **/ |
365 | | cairo_region_t * |
366 | | cairo_region_copy (const cairo_region_t *original) |
367 | 0 | { |
368 | 0 | cairo_region_t *copy; |
369 | |
|
370 | 0 | if (original != NULL && original->status) |
371 | 0 | return (cairo_region_t *) &_cairo_region_nil; |
372 | | |
373 | 0 | copy = cairo_region_create (); |
374 | 0 | if (unlikely (copy->status)) |
375 | 0 | return copy; |
376 | | |
377 | 0 | if (original != NULL && |
378 | 0 | ! pixman_region32_copy (©->rgn, CONST_CAST &original->rgn)) |
379 | 0 | { |
380 | 0 | cairo_region_destroy (copy); |
381 | 0 | return (cairo_region_t *) &_cairo_region_nil; |
382 | 0 | } |
383 | | |
384 | 0 | return copy; |
385 | 0 | } |
386 | | slim_hidden_def (cairo_region_copy); |
387 | | |
388 | | /** |
389 | | * cairo_region_reference: |
390 | | * @region: a #cairo_region_t |
391 | | * |
392 | | * Increases the reference count on @region by one. This prevents |
393 | | * @region from being destroyed until a matching call to |
394 | | * cairo_region_destroy() is made. |
395 | | * |
396 | | * Return value: the referenced #cairo_region_t. |
397 | | * |
398 | | * Since: 1.10 |
399 | | **/ |
400 | | cairo_region_t * |
401 | | cairo_region_reference (cairo_region_t *region) |
402 | 18.3k | { |
403 | 18.3k | if (region == NULL || CAIRO_REFERENCE_COUNT_IS_INVALID (®ion->ref_count)) |
404 | 18.3k | return NULL; |
405 | | |
406 | 0 | assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (®ion->ref_count)); |
407 | | |
408 | 0 | _cairo_reference_count_inc (®ion->ref_count); |
409 | 0 | return region; |
410 | 0 | } |
411 | | slim_hidden_def (cairo_region_reference); |
412 | | |
413 | | /** |
414 | | * cairo_region_destroy: |
415 | | * @region: a #cairo_region_t |
416 | | * |
417 | | * Destroys a #cairo_region_t object created with |
418 | | * cairo_region_create(), cairo_region_copy(), or |
419 | | * or cairo_region_create_rectangle(). |
420 | | * |
421 | | * Since: 1.10 |
422 | | **/ |
423 | | void |
424 | | cairo_region_destroy (cairo_region_t *region) |
425 | 1.60M | { |
426 | 1.60M | if (region == NULL || CAIRO_REFERENCE_COUNT_IS_INVALID (®ion->ref_count)) |
427 | 1.58M | return; |
428 | | |
429 | 17.7k | assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (®ion->ref_count)); |
430 | | |
431 | 17.7k | if (! _cairo_reference_count_dec_and_test (®ion->ref_count)) |
432 | 0 | return; |
433 | | |
434 | 17.7k | _cairo_region_fini (region); |
435 | 17.7k | free (region); |
436 | 17.7k | } |
437 | | slim_hidden_def (cairo_region_destroy); |
438 | | |
439 | | /** |
440 | | * cairo_region_num_rectangles: |
441 | | * @region: a #cairo_region_t |
442 | | * |
443 | | * Returns the number of rectangles contained in @region. |
444 | | * |
445 | | * Return value: The number of rectangles contained in @region. |
446 | | * |
447 | | * Since: 1.10 |
448 | | **/ |
449 | | int |
450 | | cairo_region_num_rectangles (const cairo_region_t *region) |
451 | 0 | { |
452 | 0 | if (region->status) |
453 | 0 | return 0; |
454 | | |
455 | 0 | return pixman_region32_n_rects (CONST_CAST ®ion->rgn); |
456 | 0 | } |
457 | | slim_hidden_def (cairo_region_num_rectangles); |
458 | | |
459 | | /** |
460 | | * cairo_region_get_rectangle: |
461 | | * @region: a #cairo_region_t |
462 | | * @nth: a number indicating which rectangle should be returned |
463 | | * @rectangle: return location for a #cairo_rectangle_int_t |
464 | | * |
465 | | * Stores the @nth rectangle from the region in @rectangle. |
466 | | * |
467 | | * Since: 1.10 |
468 | | **/ |
469 | | void |
470 | | cairo_region_get_rectangle (const cairo_region_t *region, |
471 | | int nth, |
472 | | cairo_rectangle_int_t *rectangle) |
473 | 0 | { |
474 | 0 | pixman_box32_t *pbox; |
475 | |
|
476 | 0 | if (region->status) { |
477 | 0 | rectangle->x = rectangle->y = 0; |
478 | 0 | rectangle->width = rectangle->height = 0; |
479 | 0 | return; |
480 | 0 | } |
481 | | |
482 | 0 | pbox = pixman_region32_rectangles (CONST_CAST ®ion->rgn, NULL) + nth; |
483 | |
|
484 | 0 | rectangle->x = pbox->x1; |
485 | 0 | rectangle->y = pbox->y1; |
486 | 0 | rectangle->width = pbox->x2 - pbox->x1; |
487 | 0 | rectangle->height = pbox->y2 - pbox->y1; |
488 | 0 | } |
489 | | slim_hidden_def (cairo_region_get_rectangle); |
490 | | |
491 | | /** |
492 | | * cairo_region_get_extents: |
493 | | * @region: a #cairo_region_t |
494 | | * @extents: rectangle into which to store the extents |
495 | | * |
496 | | * Gets the bounding rectangle of @region as a #cairo_rectangle_int_t |
497 | | * |
498 | | * Since: 1.10 |
499 | | **/ |
500 | | void |
501 | | cairo_region_get_extents (const cairo_region_t *region, |
502 | | cairo_rectangle_int_t *extents) |
503 | 0 | { |
504 | 0 | pixman_box32_t *pextents; |
505 | |
|
506 | 0 | if (region->status) { |
507 | 0 | extents->x = extents->y = 0; |
508 | 0 | extents->width = extents->height = 0; |
509 | 0 | return; |
510 | 0 | } |
511 | | |
512 | 0 | pextents = pixman_region32_extents (CONST_CAST ®ion->rgn); |
513 | |
|
514 | 0 | extents->x = pextents->x1; |
515 | 0 | extents->y = pextents->y1; |
516 | 0 | extents->width = pextents->x2 - pextents->x1; |
517 | 0 | extents->height = pextents->y2 - pextents->y1; |
518 | 0 | } |
519 | | slim_hidden_def (cairo_region_get_extents); |
520 | | |
521 | | /** |
522 | | * cairo_region_status: |
523 | | * @region: a #cairo_region_t |
524 | | * |
525 | | * Checks whether an error has previous occurred for this |
526 | | * region object. |
527 | | * |
528 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
529 | | * |
530 | | * Since: 1.10 |
531 | | **/ |
532 | | cairo_status_t |
533 | | cairo_region_status (const cairo_region_t *region) |
534 | 0 | { |
535 | 0 | return region->status; |
536 | 0 | } |
537 | | slim_hidden_def (cairo_region_status); |
538 | | |
539 | | /** |
540 | | * cairo_region_subtract: |
541 | | * @dst: a #cairo_region_t |
542 | | * @other: another #cairo_region_t |
543 | | * |
544 | | * Subtracts @other from @dst and places the result in @dst |
545 | | * |
546 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
547 | | * |
548 | | * Since: 1.10 |
549 | | **/ |
550 | | cairo_status_t |
551 | | cairo_region_subtract (cairo_region_t *dst, const cairo_region_t *other) |
552 | 0 | { |
553 | 0 | if (dst->status) |
554 | 0 | return dst->status; |
555 | | |
556 | 0 | if (other->status) |
557 | 0 | return _cairo_region_set_error (dst, other->status); |
558 | | |
559 | 0 | if (! pixman_region32_subtract (&dst->rgn, |
560 | 0 | &dst->rgn, |
561 | 0 | CONST_CAST &other->rgn)) |
562 | 0 | { |
563 | 0 | return _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); |
564 | 0 | } |
565 | | |
566 | 0 | return CAIRO_STATUS_SUCCESS; |
567 | 0 | } |
568 | | slim_hidden_def (cairo_region_subtract); |
569 | | |
570 | | /** |
571 | | * cairo_region_subtract_rectangle: |
572 | | * @dst: a #cairo_region_t |
573 | | * @rectangle: a #cairo_rectangle_int_t |
574 | | * |
575 | | * Subtracts @rectangle from @dst and places the result in @dst |
576 | | * |
577 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
578 | | * |
579 | | * Since: 1.10 |
580 | | **/ |
581 | | cairo_status_t |
582 | | cairo_region_subtract_rectangle (cairo_region_t *dst, |
583 | | const cairo_rectangle_int_t *rectangle) |
584 | 0 | { |
585 | 0 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
586 | 0 | pixman_region32_t region; |
587 | |
|
588 | 0 | if (dst->status) |
589 | 0 | return dst->status; |
590 | | |
591 | 0 | pixman_region32_init_rect (®ion, |
592 | 0 | rectangle->x, rectangle->y, |
593 | 0 | rectangle->width, rectangle->height); |
594 | |
|
595 | 0 | if (! pixman_region32_subtract (&dst->rgn, &dst->rgn, ®ion)) |
596 | 0 | status = _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); |
597 | |
|
598 | 0 | pixman_region32_fini (®ion); |
599 | |
|
600 | 0 | return status; |
601 | 0 | } |
602 | | slim_hidden_def (cairo_region_subtract_rectangle); |
603 | | |
604 | | /** |
605 | | * cairo_region_intersect: |
606 | | * @dst: a #cairo_region_t |
607 | | * @other: another #cairo_region_t |
608 | | * |
609 | | * Computes the intersection of @dst with @other and places the result in @dst |
610 | | * |
611 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
612 | | * |
613 | | * Since: 1.10 |
614 | | **/ |
615 | | cairo_status_t |
616 | | cairo_region_intersect (cairo_region_t *dst, const cairo_region_t *other) |
617 | 0 | { |
618 | 0 | if (dst->status) |
619 | 0 | return dst->status; |
620 | | |
621 | 0 | if (other->status) |
622 | 0 | return _cairo_region_set_error (dst, other->status); |
623 | | |
624 | 0 | if (! pixman_region32_intersect (&dst->rgn, &dst->rgn, CONST_CAST &other->rgn)) |
625 | 0 | return _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); |
626 | | |
627 | 0 | return CAIRO_STATUS_SUCCESS; |
628 | 0 | } |
629 | | slim_hidden_def (cairo_region_intersect); |
630 | | |
631 | | /** |
632 | | * cairo_region_intersect_rectangle: |
633 | | * @dst: a #cairo_region_t |
634 | | * @rectangle: a #cairo_rectangle_int_t |
635 | | * |
636 | | * Computes the intersection of @dst with @rectangle and places the |
637 | | * result in @dst |
638 | | * |
639 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
640 | | * |
641 | | * Since: 1.10 |
642 | | **/ |
643 | | cairo_status_t |
644 | | cairo_region_intersect_rectangle (cairo_region_t *dst, |
645 | | const cairo_rectangle_int_t *rectangle) |
646 | 0 | { |
647 | 0 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
648 | 0 | pixman_region32_t region; |
649 | |
|
650 | 0 | if (dst->status) |
651 | 0 | return dst->status; |
652 | | |
653 | 0 | pixman_region32_init_rect (®ion, |
654 | 0 | rectangle->x, rectangle->y, |
655 | 0 | rectangle->width, rectangle->height); |
656 | |
|
657 | 0 | if (! pixman_region32_intersect (&dst->rgn, &dst->rgn, ®ion)) |
658 | 0 | status = _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); |
659 | |
|
660 | 0 | pixman_region32_fini (®ion); |
661 | |
|
662 | 0 | return status; |
663 | 0 | } |
664 | | slim_hidden_def (cairo_region_intersect_rectangle); |
665 | | |
666 | | /** |
667 | | * cairo_region_union: |
668 | | * @dst: a #cairo_region_t |
669 | | * @other: another #cairo_region_t |
670 | | * |
671 | | * Computes the union of @dst with @other and places the result in @dst |
672 | | * |
673 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
674 | | * |
675 | | * Since: 1.10 |
676 | | **/ |
677 | | cairo_status_t |
678 | | cairo_region_union (cairo_region_t *dst, |
679 | | const cairo_region_t *other) |
680 | 0 | { |
681 | 0 | if (dst->status) |
682 | 0 | return dst->status; |
683 | | |
684 | 0 | if (other->status) |
685 | 0 | return _cairo_region_set_error (dst, other->status); |
686 | | |
687 | 0 | if (! pixman_region32_union (&dst->rgn, &dst->rgn, CONST_CAST &other->rgn)) |
688 | 0 | return _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); |
689 | | |
690 | 0 | return CAIRO_STATUS_SUCCESS; |
691 | 0 | } |
692 | | slim_hidden_def (cairo_region_union); |
693 | | |
694 | | /** |
695 | | * cairo_region_union_rectangle: |
696 | | * @dst: a #cairo_region_t |
697 | | * @rectangle: a #cairo_rectangle_int_t |
698 | | * |
699 | | * Computes the union of @dst with @rectangle and places the result in @dst. |
700 | | * |
701 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
702 | | * |
703 | | * Since: 1.10 |
704 | | **/ |
705 | | cairo_status_t |
706 | | cairo_region_union_rectangle (cairo_region_t *dst, |
707 | | const cairo_rectangle_int_t *rectangle) |
708 | 0 | { |
709 | 0 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
710 | 0 | pixman_region32_t region; |
711 | |
|
712 | 0 | if (dst->status) |
713 | 0 | return dst->status; |
714 | | |
715 | 0 | pixman_region32_init_rect (®ion, |
716 | 0 | rectangle->x, rectangle->y, |
717 | 0 | rectangle->width, rectangle->height); |
718 | |
|
719 | 0 | if (! pixman_region32_union (&dst->rgn, &dst->rgn, ®ion)) |
720 | 0 | status = _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); |
721 | |
|
722 | 0 | pixman_region32_fini (®ion); |
723 | |
|
724 | 0 | return status; |
725 | 0 | } |
726 | | slim_hidden_def (cairo_region_union_rectangle); |
727 | | |
728 | | /** |
729 | | * cairo_region_xor: |
730 | | * @dst: a #cairo_region_t |
731 | | * @other: another #cairo_region_t |
732 | | * |
733 | | * Computes the exclusive difference of @dst with @other and places the |
734 | | * result in @dst. That is, @dst will be set to contain all areas that |
735 | | * are either in @dst or in @other, but not in both. |
736 | | * |
737 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
738 | | * |
739 | | * Since: 1.10 |
740 | | **/ |
741 | | cairo_status_t |
742 | | cairo_region_xor (cairo_region_t *dst, const cairo_region_t *other) |
743 | 0 | { |
744 | 0 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
745 | 0 | pixman_region32_t tmp; |
746 | |
|
747 | 0 | if (dst->status) |
748 | 0 | return dst->status; |
749 | | |
750 | 0 | if (other->status) |
751 | 0 | return _cairo_region_set_error (dst, other->status); |
752 | | |
753 | 0 | pixman_region32_init (&tmp); |
754 | | |
755 | | /* XXX: get an xor function into pixman */ |
756 | 0 | if (! pixman_region32_subtract (&tmp, CONST_CAST &other->rgn, &dst->rgn) || |
757 | 0 | ! pixman_region32_subtract (&dst->rgn, &dst->rgn, CONST_CAST &other->rgn) || |
758 | 0 | ! pixman_region32_union (&dst->rgn, &dst->rgn, &tmp)) |
759 | 0 | status = _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); |
760 | |
|
761 | 0 | pixman_region32_fini (&tmp); |
762 | |
|
763 | 0 | return status; |
764 | 0 | } |
765 | | slim_hidden_def (cairo_region_xor); |
766 | | |
767 | | /** |
768 | | * cairo_region_xor_rectangle: |
769 | | * @dst: a #cairo_region_t |
770 | | * @rectangle: a #cairo_rectangle_int_t |
771 | | * |
772 | | * Computes the exclusive difference of @dst with @rectangle and places the |
773 | | * result in @dst. That is, @dst will be set to contain all areas that are |
774 | | * either in @dst or in @rectangle, but not in both. |
775 | | * |
776 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY |
777 | | * |
778 | | * Since: 1.10 |
779 | | **/ |
780 | | cairo_status_t |
781 | | cairo_region_xor_rectangle (cairo_region_t *dst, |
782 | | const cairo_rectangle_int_t *rectangle) |
783 | 0 | { |
784 | 0 | cairo_status_t status = CAIRO_STATUS_SUCCESS; |
785 | 0 | pixman_region32_t region, tmp; |
786 | |
|
787 | 0 | if (dst->status) |
788 | 0 | return dst->status; |
789 | | |
790 | 0 | pixman_region32_init_rect (®ion, |
791 | 0 | rectangle->x, rectangle->y, |
792 | 0 | rectangle->width, rectangle->height); |
793 | 0 | pixman_region32_init (&tmp); |
794 | | |
795 | | /* XXX: get an xor function into pixman */ |
796 | 0 | if (! pixman_region32_subtract (&tmp, ®ion, &dst->rgn) || |
797 | 0 | ! pixman_region32_subtract (&dst->rgn, &dst->rgn, ®ion) || |
798 | 0 | ! pixman_region32_union (&dst->rgn, &dst->rgn, &tmp)) |
799 | 0 | status = _cairo_region_set_error (dst, CAIRO_STATUS_NO_MEMORY); |
800 | |
|
801 | 0 | pixman_region32_fini (&tmp); |
802 | 0 | pixman_region32_fini (®ion); |
803 | |
|
804 | 0 | return status; |
805 | 0 | } |
806 | | slim_hidden_def (cairo_region_xor_rectangle); |
807 | | |
808 | | /** |
809 | | * cairo_region_is_empty: |
810 | | * @region: a #cairo_region_t |
811 | | * |
812 | | * Checks whether @region is empty. |
813 | | * |
814 | | * Return value: %TRUE if @region is empty, %FALSE if it isn't. |
815 | | * |
816 | | * Since: 1.10 |
817 | | **/ |
818 | | cairo_bool_t |
819 | | cairo_region_is_empty (const cairo_region_t *region) |
820 | 0 | { |
821 | 0 | if (region->status) |
822 | 0 | return TRUE; |
823 | | |
824 | 0 | return ! pixman_region32_not_empty (CONST_CAST ®ion->rgn); |
825 | 0 | } |
826 | | slim_hidden_def (cairo_region_is_empty); |
827 | | |
828 | | /** |
829 | | * cairo_region_translate: |
830 | | * @region: a #cairo_region_t |
831 | | * @dx: Amount to translate in the x direction |
832 | | * @dy: Amount to translate in the y direction |
833 | | * |
834 | | * Translates @region by (@dx, @dy). |
835 | | * |
836 | | * Since: 1.10 |
837 | | **/ |
838 | | void |
839 | | cairo_region_translate (cairo_region_t *region, |
840 | | int dx, int dy) |
841 | 0 | { |
842 | 0 | if (region->status) |
843 | 0 | return; |
844 | | |
845 | 0 | pixman_region32_translate (®ion->rgn, dx, dy); |
846 | 0 | } |
847 | | slim_hidden_def (cairo_region_translate); |
848 | | |
849 | | /** |
850 | | * cairo_region_contains_rectangle: |
851 | | * @region: a #cairo_region_t |
852 | | * @rectangle: a #cairo_rectangle_int_t |
853 | | * |
854 | | * Checks whether @rectangle is inside, outside or partially contained |
855 | | * in @region |
856 | | * |
857 | | * Return value: |
858 | | * %CAIRO_REGION_OVERLAP_IN if @rectangle is entirely inside @region, |
859 | | * %CAIRO_REGION_OVERLAP_OUT if @rectangle is entirely outside @region, or |
860 | | * %CAIRO_REGION_OVERLAP_PART if @rectangle is partially inside and partially outside @region. |
861 | | * |
862 | | * Since: 1.10 |
863 | | **/ |
864 | | cairo_region_overlap_t |
865 | | cairo_region_contains_rectangle (const cairo_region_t *region, |
866 | | const cairo_rectangle_int_t *rectangle) |
867 | 17.7k | { |
868 | 17.7k | pixman_box32_t pbox; |
869 | 17.7k | pixman_region_overlap_t poverlap; |
870 | | |
871 | 17.7k | if (region->status) |
872 | 0 | return CAIRO_REGION_OVERLAP_OUT; |
873 | | |
874 | 17.7k | pbox.x1 = rectangle->x; |
875 | 17.7k | pbox.y1 = rectangle->y; |
876 | 17.7k | pbox.x2 = rectangle->x + rectangle->width; |
877 | 17.7k | pbox.y2 = rectangle->y + rectangle->height; |
878 | | |
879 | 17.7k | poverlap = pixman_region32_contains_rectangle (CONST_CAST ®ion->rgn, |
880 | 17.7k | &pbox); |
881 | 17.7k | switch (poverlap) { |
882 | 0 | default: |
883 | 0 | case PIXMAN_REGION_OUT: return CAIRO_REGION_OVERLAP_OUT; |
884 | 17.7k | case PIXMAN_REGION_IN: return CAIRO_REGION_OVERLAP_IN; |
885 | 0 | case PIXMAN_REGION_PART: return CAIRO_REGION_OVERLAP_PART; |
886 | 17.7k | } |
887 | 17.7k | } |
888 | | slim_hidden_def (cairo_region_contains_rectangle); |
889 | | |
890 | | /** |
891 | | * cairo_region_contains_point: |
892 | | * @region: a #cairo_region_t |
893 | | * @x: the x coordinate of a point |
894 | | * @y: the y coordinate of a point |
895 | | * |
896 | | * Checks whether (@x, @y) is contained in @region. |
897 | | * |
898 | | * Return value: %TRUE if (@x, @y) is contained in @region, %FALSE if it is not. |
899 | | * |
900 | | * Since: 1.10 |
901 | | **/ |
902 | | cairo_bool_t |
903 | | cairo_region_contains_point (const cairo_region_t *region, |
904 | | int x, int y) |
905 | 0 | { |
906 | 0 | pixman_box32_t box; |
907 | |
|
908 | 0 | if (region->status) |
909 | 0 | return FALSE; |
910 | | |
911 | 0 | return pixman_region32_contains_point (CONST_CAST ®ion->rgn, x, y, &box); |
912 | 0 | } |
913 | | slim_hidden_def (cairo_region_contains_point); |
914 | | |
915 | | /** |
916 | | * cairo_region_equal: |
917 | | * @a: a #cairo_region_t or %NULL |
918 | | * @b: a #cairo_region_t or %NULL |
919 | | * |
920 | | * Compares whether region_a is equivalent to region_b. %NULL as an argument |
921 | | * is equal to itself, but not to any non-%NULL region. |
922 | | * |
923 | | * Return value: %TRUE if both regions contained the same coverage, |
924 | | * %FALSE if it is not or any region is in an error status. |
925 | | * |
926 | | * Since: 1.10 |
927 | | **/ |
928 | | cairo_bool_t |
929 | | cairo_region_equal (const cairo_region_t *a, |
930 | | const cairo_region_t *b) |
931 | 0 | { |
932 | | /* error objects are never equal */ |
933 | 0 | if ((a != NULL && a->status) || (b != NULL && b->status)) |
934 | 0 | return FALSE; |
935 | | |
936 | 0 | if (a == b) |
937 | 0 | return TRUE; |
938 | | |
939 | 0 | if (a == NULL || b == NULL) |
940 | 0 | return FALSE; |
941 | | |
942 | 0 | return pixman_region32_equal (CONST_CAST &a->rgn, CONST_CAST &b->rgn); |
943 | 0 | } |
944 | | slim_hidden_def (cairo_region_equal); |