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