Subversion Repositories Kolibri OS

Rev

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);