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
4 * Copyright © 2005 Red Hat, Inc.
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.
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
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/
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.
29 * The Original Code is the cairo graphics library.
31 * The Initial Developer of the Original Code is Red Hat, Inc.
34 * Owen Taylor <otaylor@redhat.com>
35 * Vladimir Vukicevic <vladimir@pobox.com>
36 * Søren Sandmann <sandmann@daimi.au.dk>
41 #include "cairo-error-private.h"
42 #include "cairo-region-private.h"
44 /* XXX need to update pixman headers to be const as appropriate */
45 #define CONST_CAST (pixman_region32_t *)
48 * SECTION:cairo-region
50 * @Short_Description: Representing a pixel-aligned area
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.
57 static const cairo_region_t _cairo_region_nil
= {
58 CAIRO_REFERENCE_COUNT_INVALID
, /* ref_count */
59 CAIRO_STATUS_NO_MEMORY
, /* status */
63 _cairo_region_create_in_error (cairo_status_t status
)
66 case CAIRO_STATUS_NO_MEMORY
:
67 return (cairo_region_t
*) &_cairo_region_nil
;
69 case CAIRO_STATUS_SUCCESS
:
70 case CAIRO_STATUS_LAST_STATUS
:
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
:
107 case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION
:
108 case CAIRO_STATUS_DEVICE_FINISHED
:
109 case CAIRO_STATUS_JBIG2_GLOBAL_MISSING
:
111 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
112 return (cairo_region_t
*) &_cairo_region_nil
;
117 * _cairo_region_set_error:
119 * @status: a status value indicating an error
121 * Atomically sets region->status to @status and calls _cairo_error;
122 * Does nothing if status is %CAIRO_STATUS_SUCCESS or any of the internal
125 * All assignments of an error status to region->status should happen
126 * through _cairo_region_set_error(). Note that due to the nature of
127 * the atomic operation, it is not safe to call this function on the
130 * The purpose of this function is to allow the user to set a
131 * breakpoint in _cairo_error() to generate a stack trace for when the
132 * user causes cairo to detect an error.
134 * Return value: the error status.
136 static cairo_status_t
137 _cairo_region_set_error (cairo_region_t
*region
,
138 cairo_status_t status
)
140 if (status
== CAIRO_STATUS_SUCCESS
)
141 return CAIRO_STATUS_SUCCESS
;
143 /* Don't overwrite an existing error. This preserves the first
144 * error, which is the most significant. */
145 _cairo_status_set_error (®ion
->status
, status
);
147 return _cairo_error (status
);
151 _cairo_region_init (cairo_region_t
*region
)
153 VG (VALGRIND_MAKE_MEM_UNDEFINED (region
, sizeof (cairo_region_t
)));
155 region
->status
= CAIRO_STATUS_SUCCESS
;
156 CAIRO_REFERENCE_COUNT_INIT (®ion
->ref_count
, 0);
157 pixman_region32_init (®ion
->rgn
);
161 _cairo_region_init_rectangle (cairo_region_t
*region
,
162 const cairo_rectangle_int_t
*rectangle
)
164 VG (VALGRIND_MAKE_MEM_UNDEFINED (region
, sizeof (cairo_region_t
)));
166 region
->status
= CAIRO_STATUS_SUCCESS
;
167 CAIRO_REFERENCE_COUNT_INIT (®ion
->ref_count
, 0);
168 pixman_region32_init_rect (®ion
->rgn
,
169 rectangle
->x
, rectangle
->y
,
170 rectangle
->width
, rectangle
->height
);
174 _cairo_region_fini (cairo_region_t
*region
)
176 assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (®ion
->ref_count
));
177 pixman_region32_fini (®ion
->rgn
);
178 VG (VALGRIND_MAKE_MEM_NOACCESS (region
, sizeof (cairo_region_t
)));
182 * cairo_region_create:
184 * Allocates a new empty region object.
186 * Return value: A newly allocated #cairo_region_t. Free with
187 * cairo_region_destroy(). This function always returns a
188 * valid pointer; if memory cannot be allocated, then a special
189 * error object is returned where all operations on the object do nothing.
190 * You can check for this with cairo_region_status().
195 cairo_region_create (void)
197 cairo_region_t
*region
;
199 region
= _cairo_malloc (sizeof (cairo_region_t
));
201 return (cairo_region_t
*) &_cairo_region_nil
;
203 region
->status
= CAIRO_STATUS_SUCCESS
;
204 CAIRO_REFERENCE_COUNT_INIT (®ion
->ref_count
, 1);
206 pixman_region32_init (®ion
->rgn
);
210 slim_hidden_def (cairo_region_create
);
213 * cairo_region_create_rectangles:
214 * @rects: an array of @count rectangles
215 * @count: number of rectangles
217 * Allocates a new region object containing the union of all given @rects.
219 * Return value: A newly allocated #cairo_region_t. Free with
220 * cairo_region_destroy(). This function always returns a
221 * valid pointer; if memory cannot be allocated, then a special
222 * error object is returned where all operations on the object do nothing.
223 * You can check for this with cairo_region_status().
228 cairo_region_create_rectangles (const cairo_rectangle_int_t
*rects
,
231 pixman_box32_t stack_pboxes
[CAIRO_STACK_ARRAY_LENGTH (pixman_box32_t
)];
232 pixman_box32_t
*pboxes
= stack_pboxes
;
233 cairo_region_t
*region
;
236 region
= _cairo_malloc (sizeof (cairo_region_t
));
237 if (unlikely (region
== NULL
))
238 return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
240 CAIRO_REFERENCE_COUNT_INIT (®ion
->ref_count
, 1);
241 region
->status
= CAIRO_STATUS_SUCCESS
;
244 pixman_region32_init_rect (®ion
->rgn
,
246 rects
->width
, rects
->height
);
251 if (count
> ARRAY_LENGTH (stack_pboxes
)) {
252 pboxes
= _cairo_malloc_ab (count
, sizeof (pixman_box32_t
));
253 if (unlikely (pboxes
== NULL
)) {
255 return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
259 for (i
= 0; i
< count
; i
++) {
260 pboxes
[i
].x1
= rects
[i
].x
;
261 pboxes
[i
].y1
= rects
[i
].y
;
262 pboxes
[i
].x2
= rects
[i
].x
+ rects
[i
].width
;
263 pboxes
[i
].y2
= rects
[i
].y
+ rects
[i
].height
;
266 i
= pixman_region32_init_rects (®ion
->rgn
, pboxes
, count
);
268 if (pboxes
!= stack_pboxes
)
271 if (unlikely (i
== 0)) {
273 return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
278 slim_hidden_def (cairo_region_create_rectangles
);
281 _cairo_region_create_from_boxes (const cairo_box_t
*boxes
, int count
)
283 cairo_region_t
*region
;
285 region
= _cairo_malloc (sizeof (cairo_region_t
));
286 if (unlikely (region
== NULL
))
287 return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
289 CAIRO_REFERENCE_COUNT_INIT (®ion
->ref_count
, 1);
290 region
->status
= CAIRO_STATUS_SUCCESS
;
292 if (! pixman_region32_init_rects (®ion
->rgn
,
293 (pixman_box32_t
*)boxes
, count
)) {
295 return _cairo_region_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
302 _cairo_region_get_boxes (const cairo_region_t
*region
, int *nbox
)
304 if (region
->status
) {
309 return (cairo_box_t
*) pixman_region32_rectangles (CONST_CAST
®ion
->rgn
, nbox
);
313 * cairo_region_create_rectangle:
314 * @rectangle: a #cairo_rectangle_int_t
316 * Allocates a new region object containing @rectangle.
318 * Return value: A newly allocated #cairo_region_t. Free with
319 * cairo_region_destroy(). This function always returns a
320 * valid pointer; if memory cannot be allocated, then a special
321 * error object is returned where all operations on the object do nothing.
322 * You can check for this with cairo_region_status().
327 cairo_region_create_rectangle (const cairo_rectangle_int_t
*rectangle
)
329 cairo_region_t
*region
;
331 region
= _cairo_malloc (sizeof (cairo_region_t
));
332 if (unlikely (region
== NULL
))
333 return (cairo_region_t
*) &_cairo_region_nil
;
335 region
->status
= CAIRO_STATUS_SUCCESS
;
336 CAIRO_REFERENCE_COUNT_INIT (®ion
->ref_count
, 1);
338 pixman_region32_init_rect (®ion
->rgn
,
339 rectangle
->x
, rectangle
->y
,
340 rectangle
->width
, rectangle
->height
);
344 slim_hidden_def (cairo_region_create_rectangle
);
348 * @original: a #cairo_region_t
350 * Allocates a new region object copying the area from @original.
352 * Return value: A newly allocated #cairo_region_t. Free with
353 * cairo_region_destroy(). This function always returns a
354 * valid pointer; if memory cannot be allocated, then a special
355 * error object is returned where all operations on the object do nothing.
356 * You can check for this with cairo_region_status().
361 cairo_region_copy (const cairo_region_t
*original
)
363 cairo_region_t
*copy
;
365 if (original
!= NULL
&& original
->status
)
366 return (cairo_region_t
*) &_cairo_region_nil
;
368 copy
= cairo_region_create ();
369 if (unlikely (copy
->status
))
372 if (original
!= NULL
&&
373 ! pixman_region32_copy (©
->rgn
, CONST_CAST
&original
->rgn
))
375 cairo_region_destroy (copy
);
376 return (cairo_region_t
*) &_cairo_region_nil
;
381 slim_hidden_def (cairo_region_copy
);
384 * cairo_region_reference:
385 * @region: a #cairo_region_t
387 * Increases the reference count on @region by one. This prevents
388 * @region from being destroyed until a matching call to
389 * cairo_region_destroy() is made.
391 * Return value: the referenced #cairo_region_t.
396 cairo_region_reference (cairo_region_t
*region
)
398 if (region
== NULL
|| CAIRO_REFERENCE_COUNT_IS_INVALID (®ion
->ref_count
))
401 assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (®ion
->ref_count
));
403 _cairo_reference_count_inc (®ion
->ref_count
);
406 slim_hidden_def (cairo_region_reference
);
409 * cairo_region_destroy:
410 * @region: a #cairo_region_t
412 * Destroys a #cairo_region_t object created with
413 * cairo_region_create(), cairo_region_copy(), or
414 * or cairo_region_create_rectangle().
419 cairo_region_destroy (cairo_region_t
*region
)
421 if (region
== NULL
|| CAIRO_REFERENCE_COUNT_IS_INVALID (®ion
->ref_count
))
424 assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (®ion
->ref_count
));
426 if (! _cairo_reference_count_dec_and_test (®ion
->ref_count
))
429 _cairo_region_fini (region
);
432 slim_hidden_def (cairo_region_destroy
);
435 * cairo_region_num_rectangles:
436 * @region: a #cairo_region_t
438 * Returns the number of rectangles contained in @region.
440 * Return value: The number of rectangles contained in @region.
445 cairo_region_num_rectangles (const cairo_region_t
*region
)
450 return pixman_region32_n_rects (CONST_CAST
®ion
->rgn
);
452 slim_hidden_def (cairo_region_num_rectangles
);
455 * cairo_region_get_rectangle:
456 * @region: a #cairo_region_t
457 * @nth: a number indicating which rectangle should be returned
458 * @rectangle: return location for a #cairo_rectangle_int_t
460 * Stores the @nth rectangle from the region in @rectangle.
465 cairo_region_get_rectangle (const cairo_region_t
*region
,
467 cairo_rectangle_int_t
*rectangle
)
469 pixman_box32_t
*pbox
;
471 if (region
->status
) {
472 rectangle
->x
= rectangle
->y
= 0;
473 rectangle
->width
= rectangle
->height
= 0;
477 pbox
= pixman_region32_rectangles (CONST_CAST
®ion
->rgn
, NULL
) + nth
;
479 rectangle
->x
= pbox
->x1
;
480 rectangle
->y
= pbox
->y1
;
481 rectangle
->width
= pbox
->x2
- pbox
->x1
;
482 rectangle
->height
= pbox
->y2
- pbox
->y1
;
484 slim_hidden_def (cairo_region_get_rectangle
);
487 * cairo_region_get_extents:
488 * @region: a #cairo_region_t
489 * @extents: rectangle into which to store the extents
491 * Gets the bounding rectangle of @region as a #cairo_rectangle_int_t
496 cairo_region_get_extents (const cairo_region_t
*region
,
497 cairo_rectangle_int_t
*extents
)
499 pixman_box32_t
*pextents
;
501 if (region
->status
) {
502 extents
->x
= extents
->y
= 0;
503 extents
->width
= extents
->height
= 0;
507 pextents
= pixman_region32_extents (CONST_CAST
®ion
->rgn
);
509 extents
->x
= pextents
->x1
;
510 extents
->y
= pextents
->y1
;
511 extents
->width
= pextents
->x2
- pextents
->x1
;
512 extents
->height
= pextents
->y2
- pextents
->y1
;
514 slim_hidden_def (cairo_region_get_extents
);
517 * cairo_region_status:
518 * @region: a #cairo_region_t
520 * Checks whether an error has previous occurred for this
523 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
528 cairo_region_status (const cairo_region_t
*region
)
530 return region
->status
;
532 slim_hidden_def (cairo_region_status
);
535 * cairo_region_subtract:
536 * @dst: a #cairo_region_t
537 * @other: another #cairo_region_t
539 * Subtracts @other from @dst and places the result in @dst
541 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
546 cairo_region_subtract (cairo_region_t
*dst
, const cairo_region_t
*other
)
552 return _cairo_region_set_error (dst
, other
->status
);
554 if (! pixman_region32_subtract (&dst
->rgn
,
556 CONST_CAST
&other
->rgn
))
558 return _cairo_region_set_error (dst
, CAIRO_STATUS_NO_MEMORY
);
561 return CAIRO_STATUS_SUCCESS
;
563 slim_hidden_def (cairo_region_subtract
);
566 * cairo_region_subtract_rectangle:
567 * @dst: a #cairo_region_t
568 * @rectangle: a #cairo_rectangle_int_t
570 * Subtracts @rectangle from @dst and places the result in @dst
572 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
577 cairo_region_subtract_rectangle (cairo_region_t
*dst
,
578 const cairo_rectangle_int_t
*rectangle
)
580 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
581 pixman_region32_t region
;
586 pixman_region32_init_rect (®ion
,
587 rectangle
->x
, rectangle
->y
,
588 rectangle
->width
, rectangle
->height
);
590 if (! pixman_region32_subtract (&dst
->rgn
, &dst
->rgn
, ®ion
))
591 status
= _cairo_region_set_error (dst
, CAIRO_STATUS_NO_MEMORY
);
593 pixman_region32_fini (®ion
);
597 slim_hidden_def (cairo_region_subtract_rectangle
);
600 * cairo_region_intersect:
601 * @dst: a #cairo_region_t
602 * @other: another #cairo_region_t
604 * Computes the intersection of @dst with @other and places the result in @dst
606 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
611 cairo_region_intersect (cairo_region_t
*dst
, const cairo_region_t
*other
)
617 return _cairo_region_set_error (dst
, other
->status
);
619 if (! pixman_region32_intersect (&dst
->rgn
, &dst
->rgn
, CONST_CAST
&other
->rgn
))
620 return _cairo_region_set_error (dst
, CAIRO_STATUS_NO_MEMORY
);
622 return CAIRO_STATUS_SUCCESS
;
624 slim_hidden_def (cairo_region_intersect
);
627 * cairo_region_intersect_rectangle:
628 * @dst: a #cairo_region_t
629 * @rectangle: a #cairo_rectangle_int_t
631 * Computes the intersection of @dst with @rectangle and places the
634 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
639 cairo_region_intersect_rectangle (cairo_region_t
*dst
,
640 const cairo_rectangle_int_t
*rectangle
)
642 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
643 pixman_region32_t region
;
648 pixman_region32_init_rect (®ion
,
649 rectangle
->x
, rectangle
->y
,
650 rectangle
->width
, rectangle
->height
);
652 if (! pixman_region32_intersect (&dst
->rgn
, &dst
->rgn
, ®ion
))
653 status
= _cairo_region_set_error (dst
, CAIRO_STATUS_NO_MEMORY
);
655 pixman_region32_fini (®ion
);
659 slim_hidden_def (cairo_region_intersect_rectangle
);
662 * cairo_region_union:
663 * @dst: a #cairo_region_t
664 * @other: another #cairo_region_t
666 * Computes the union of @dst with @other and places the result in @dst
668 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
673 cairo_region_union (cairo_region_t
*dst
,
674 const cairo_region_t
*other
)
680 return _cairo_region_set_error (dst
, other
->status
);
682 if (! pixman_region32_union (&dst
->rgn
, &dst
->rgn
, CONST_CAST
&other
->rgn
))
683 return _cairo_region_set_error (dst
, CAIRO_STATUS_NO_MEMORY
);
685 return CAIRO_STATUS_SUCCESS
;
687 slim_hidden_def (cairo_region_union
);
690 * cairo_region_union_rectangle:
691 * @dst: a #cairo_region_t
692 * @rectangle: a #cairo_rectangle_int_t
694 * Computes the union of @dst with @rectangle and places the result in @dst.
696 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
701 cairo_region_union_rectangle (cairo_region_t
*dst
,
702 const cairo_rectangle_int_t
*rectangle
)
704 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
705 pixman_region32_t region
;
710 pixman_region32_init_rect (®ion
,
711 rectangle
->x
, rectangle
->y
,
712 rectangle
->width
, rectangle
->height
);
714 if (! pixman_region32_union (&dst
->rgn
, &dst
->rgn
, ®ion
))
715 status
= _cairo_region_set_error (dst
, CAIRO_STATUS_NO_MEMORY
);
717 pixman_region32_fini (®ion
);
721 slim_hidden_def (cairo_region_union_rectangle
);
725 * @dst: a #cairo_region_t
726 * @other: another #cairo_region_t
728 * Computes the exclusive difference of @dst with @other and places the
729 * result in @dst. That is, @dst will be set to contain all areas that
730 * are either in @dst or in @other, but not in both.
732 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
737 cairo_region_xor (cairo_region_t
*dst
, const cairo_region_t
*other
)
739 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
740 pixman_region32_t tmp
;
746 return _cairo_region_set_error (dst
, other
->status
);
748 pixman_region32_init (&tmp
);
750 /* XXX: get an xor function into pixman */
751 if (! pixman_region32_subtract (&tmp
, CONST_CAST
&other
->rgn
, &dst
->rgn
) ||
752 ! pixman_region32_subtract (&dst
->rgn
, &dst
->rgn
, CONST_CAST
&other
->rgn
) ||
753 ! pixman_region32_union (&dst
->rgn
, &dst
->rgn
, &tmp
))
754 status
= _cairo_region_set_error (dst
, CAIRO_STATUS_NO_MEMORY
);
756 pixman_region32_fini (&tmp
);
760 slim_hidden_def (cairo_region_xor
);
763 * cairo_region_xor_rectangle:
764 * @dst: a #cairo_region_t
765 * @rectangle: a #cairo_rectangle_int_t
767 * Computes the exclusive difference of @dst with @rectangle and places the
768 * result in @dst. That is, @dst will be set to contain all areas that are
769 * either in @dst or in @rectangle, but not in both.
771 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY
776 cairo_region_xor_rectangle (cairo_region_t
*dst
,
777 const cairo_rectangle_int_t
*rectangle
)
779 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
780 pixman_region32_t region
, tmp
;
785 pixman_region32_init_rect (®ion
,
786 rectangle
->x
, rectangle
->y
,
787 rectangle
->width
, rectangle
->height
);
788 pixman_region32_init (&tmp
);
790 /* XXX: get an xor function into pixman */
791 if (! pixman_region32_subtract (&tmp
, ®ion
, &dst
->rgn
) ||
792 ! pixman_region32_subtract (&dst
->rgn
, &dst
->rgn
, ®ion
) ||
793 ! pixman_region32_union (&dst
->rgn
, &dst
->rgn
, &tmp
))
794 status
= _cairo_region_set_error (dst
, CAIRO_STATUS_NO_MEMORY
);
796 pixman_region32_fini (&tmp
);
797 pixman_region32_fini (®ion
);
801 slim_hidden_def (cairo_region_xor_rectangle
);
804 * cairo_region_is_empty:
805 * @region: a #cairo_region_t
807 * Checks whether @region is empty.
809 * Return value: %TRUE if @region is empty, %FALSE if it isn't.
814 cairo_region_is_empty (const cairo_region_t
*region
)
819 return ! pixman_region32_not_empty (CONST_CAST
®ion
->rgn
);
821 slim_hidden_def (cairo_region_is_empty
);
824 * cairo_region_translate:
825 * @region: a #cairo_region_t
826 * @dx: Amount to translate in the x direction
827 * @dy: Amount to translate in the y direction
829 * Translates @region by (@dx, @dy).
834 cairo_region_translate (cairo_region_t
*region
,
840 pixman_region32_translate (®ion
->rgn
, dx
, dy
);
842 slim_hidden_def (cairo_region_translate
);
845 * cairo_region_contains_rectangle:
846 * @region: a #cairo_region_t
847 * @rectangle: a #cairo_rectangle_int_t
849 * Checks whether @rectangle is inside, outside or partially contained
853 * %CAIRO_REGION_OVERLAP_IN if @rectangle is entirely inside @region,
854 * %CAIRO_REGION_OVERLAP_OUT if @rectangle is entirely outside @region, or
855 * %CAIRO_REGION_OVERLAP_PART if @rectangle is partially inside and partially outside @region.
859 cairo_region_overlap_t
860 cairo_region_contains_rectangle (const cairo_region_t
*region
,
861 const cairo_rectangle_int_t
*rectangle
)
864 pixman_region_overlap_t poverlap
;
867 return CAIRO_REGION_OVERLAP_OUT
;
869 pbox
.x1
= rectangle
->x
;
870 pbox
.y1
= rectangle
->y
;
871 pbox
.x2
= rectangle
->x
+ rectangle
->width
;
872 pbox
.y2
= rectangle
->y
+ rectangle
->height
;
874 poverlap
= pixman_region32_contains_rectangle (CONST_CAST
®ion
->rgn
,
878 case PIXMAN_REGION_OUT
: return CAIRO_REGION_OVERLAP_OUT
;
879 case PIXMAN_REGION_IN
: return CAIRO_REGION_OVERLAP_IN
;
880 case PIXMAN_REGION_PART
: return CAIRO_REGION_OVERLAP_PART
;
883 slim_hidden_def (cairo_region_contains_rectangle
);
886 * cairo_region_contains_point:
887 * @region: a #cairo_region_t
888 * @x: the x coordinate of a point
889 * @y: the y coordinate of a point
891 * Checks whether (@x, @y) is contained in @region.
893 * Return value: %TRUE if (@x, @y) is contained in @region, %FALSE if it is not.
898 cairo_region_contains_point (const cairo_region_t
*region
,
906 return pixman_region32_contains_point (CONST_CAST
®ion
->rgn
, x
, y
, &box
);
908 slim_hidden_def (cairo_region_contains_point
);
911 * cairo_region_equal:
912 * @a: a #cairo_region_t or %NULL
913 * @b: a #cairo_region_t or %NULL
915 * Compares whether region_a is equivalent to region_b. %NULL as an argument
916 * is equal to itself, but not to any non-%NULL region.
918 * Return value: %TRUE if both regions contained the same coverage,
919 * %FALSE if it is not or any region is in an error status.
924 cairo_region_equal (const cairo_region_t
*a
,
925 const cairo_region_t
*b
)
927 /* error objects are never equal */
928 if ((a
!= NULL
&& a
->status
) || (b
!= NULL
&& b
->status
))
934 if (a
== NULL
|| b
== NULL
)
937 return pixman_region32_equal (CONST_CAST
&a
->rgn
, CONST_CAST
&b
->rgn
);
939 slim_hidden_def (cairo_region_equal
);