Line data Source code
1 : /*
2 : +----------------------------------------------------------------------+
3 : | For PHP Version 8 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 2015 Elizabeth M Smith |
6 : +----------------------------------------------------------------------+
7 : | http://www.opensource.org/licenses/mit-license.php MIT License |
8 : | Also available in LICENSE |
9 : +----------------------------------------------------------------------+
10 : | Authors: Elizabeth M Smith <auroraeosrose@gmail.com> |
11 : | Swen Zanon <swen.zanon@geoglis.de> |
12 : +----------------------------------------------------------------------+
13 : */
14 :
15 : #ifdef HAVE_CONFIG_H
16 : #include "config.h"
17 : #endif
18 :
19 : #include <cairo.h>
20 : #include <php.h>
21 : #include <zend_exceptions.h>
22 :
23 : #include "php_cairo.h"
24 : #include "php_cairo_internal.h"
25 : #include "region_arginfo.h"
26 :
27 : zend_class_entry *ce_cairo_region;
28 : zend_class_entry *ce_cairo_region_overlap;
29 :
30 : static zend_object_handlers cairo_region_object_handlers;
31 :
32 : typedef struct _cairo_region_object {
33 : cairo_region_t *region;
34 : zend_object std;
35 : } cairo_region_object;
36 :
37 197 : static inline cairo_region_object *cairo_region_fetch_object(zend_object *object)
38 : {
39 197 : return (cairo_region_object *) ((char*)(object) - XtOffsetOf(cairo_region_object, std));
40 : }
41 :
42 : #define Z_CAIRO_REGION_P(zv) cairo_region_fetch_object(Z_OBJ_P(zv))
43 :
44 92 : cairo_region_object *cairo_region_object_get(zval *zv)
45 : {
46 92 : cairo_region_object *object = Z_CAIRO_REGION_P(zv);
47 92 : if (object->region == NULL) {
48 0 : zend_throw_exception_ex(ce_cairo_exception, 0,
49 : "Internal region object missing in %s, you must call parent::__construct in extended classes.",
50 0 : ZSTR_VAL(Z_OBJCE_P(zv)->name));
51 0 : return NULL;
52 : }
53 92 : return object;
54 : }
55 :
56 : /* ----------------------------------------------------------------
57 : \Cairo\Region Object management
58 : ------------------------------------------------------------------*/
59 :
60 : /* {{{ */
61 47 : static void cairo_region_free_obj(zend_object *object)
62 : {
63 47 : cairo_region_object *intern = cairo_region_fetch_object(object);
64 :
65 47 : if (!intern) {
66 0 : return;
67 : }
68 :
69 47 : if (intern->region) {
70 44 : cairo_region_destroy(intern->region);
71 44 : intern->region = NULL;
72 : }
73 :
74 47 : zend_object_std_dtor(&intern->std);
75 : }
76 :
77 : /* {{{ */
78 47 : static zend_object* cairo_region_obj_ctor(zend_class_entry *ce, cairo_region_object **intern)
79 : {
80 47 : cairo_region_object *object = ecalloc(1, sizeof(cairo_region_object) + zend_object_properties_size(ce));
81 :
82 47 : object->region = NULL;
83 :
84 47 : zend_object_std_init(&object->std, ce);
85 47 : object->std.handlers = &cairo_region_object_handlers;
86 47 : *intern = object;
87 :
88 47 : return &object->std;
89 : }
90 : /* }}} */
91 :
92 : /* {{{ */
93 45 : static zend_object* cairo_region_create_object(zend_class_entry *ce)
94 : {
95 45 : cairo_region_object *region_obj = NULL;
96 45 : zend_object *return_value = cairo_region_obj_ctor(ce, ®ion_obj);
97 :
98 45 : object_properties_init(®ion_obj->std, ce);
99 45 : return return_value;
100 : }
101 : /* }}} */
102 :
103 : /* {{{ */
104 2 : static zend_object* cairo_region_clone_obj(zend_object *old_object)
105 : {
106 : cairo_region_object *new_region;
107 2 : cairo_region_object *old_region = cairo_region_fetch_object(old_object);
108 2 : zend_object *return_value = cairo_region_obj_ctor(old_object->ce, &new_region);
109 :
110 2 : new_region->region = old_region->region;
111 2 : cairo_region_reference(old_region->region);
112 :
113 2 : zend_objects_clone_members(&new_region->std, &old_region->std);
114 :
115 2 : return return_value;
116 : }
117 : /* }}} */
118 :
119 :
120 : /* ----------------------------------------------------------------
121 : \Cairo\Region Class API
122 : ------------------------------------------------------------------ */
123 :
124 : /* {{{ proto void __contruct([void | Cairo\Rectangle $rect | array Cairo\Rectangle $rects])
125 : Creates a new region - optionally with a single or union of multiple rectangles inside */
126 45 : PHP_METHOD(Cairo_Region, __construct)
127 : {
128 : cairo_region_object *region_object;
129 45 : zval *rectangles_zval = NULL;
130 45 : long num_rectangles = 0;
131 : HashTable *rectangles_hash;
132 : cairo_rectangle_t *rectangle;
133 : cairo_rectangle_int_t *rectangles_array;
134 : cairo_rectangle_int_t int_rect;
135 45 : int i = 0;
136 : zval *pzval;
137 :
138 45 : ZEND_PARSE_PARAMETERS_START(0, 1)
139 44 : Z_PARAM_OPTIONAL
140 44 : Z_PARAM_ZVAL(rectangles_zval)
141 47 : ZEND_PARSE_PARAMETERS_END();
142 :
143 88 : region_object = Z_CAIRO_REGION_P(getThis());
144 44 : if (!region_object) {
145 0 : RETURN_NULL();
146 : }
147 :
148 44 : if (rectangles_zval == NULL) {
149 17 : region_object->region = cairo_region_create();
150 54 : } else if (Z_TYPE_P(rectangles_zval) == IS_OBJECT) {
151 19 : rectangle = cairo_rectangle_object_get_rect(rectangles_zval);
152 19 : cairo_expand_to_rectangle_int(rectangle, &int_rect);
153 19 : region_object->region = cairo_region_create_rectangle(&int_rect);
154 16 : } else if (Z_TYPE_P(rectangles_zval) == IS_ARRAY) {
155 :
156 : /* Grab the zend hash and see how big our array will be */
157 7 : rectangles_hash = Z_ARRVAL_P(rectangles_zval);
158 7 : num_rectangles = zend_hash_num_elements(rectangles_hash);
159 7 : rectangles_array = ecalloc(num_rectangles, sizeof(cairo_rectangle_int_t));
160 :
161 : /* iterate over the array*/
162 34 : ZEND_HASH_FOREACH_VAL(rectangles_hash, pzval) {
163 14 : if (Z_TYPE_P(pzval) != IS_OBJECT || Z_OBJCE_P(pzval) != ce_cairo_rectangle) {
164 1 : zend_throw_exception(zend_ce_type_error, "Cairo\\Region::__construct(): Argument #1 ($rectangle) must be empty, a Cairo\\Rectangle object, or an array of Cairo\\Rectangle objects.", 0);
165 1 : efree(rectangles_array);
166 1 : RETURN_THROWS();
167 : }
168 13 : cairo_expand_to_rectangle_int(cairo_rectangle_object_get_rect(pzval), &int_rect);
169 13 : rectangles_array[i++] = int_rect;
170 : } ZEND_HASH_FOREACH_END();
171 :
172 6 : region_object->region = cairo_region_create_rectangles(rectangles_array, i);
173 6 : efree(rectangles_array);
174 :
175 : } else {
176 1 : zend_throw_exception(zend_ce_type_error, "Cairo\\Region::__construct(): Argument #1 ($rectangle) must be empty, a Cairo\\Rectangle object, or an array of Cairo\\Rectangle objects.", 0);
177 1 : RETURN_THROWS();
178 : }
179 :
180 42 : if (php_cairo_throw_exception(cairo_region_status(region_object->region))) {
181 0 : RETURN_THROWS();
182 : }
183 : }
184 : /* }}} */
185 :
186 : /* {{{ proto \Cairo\Status \Cairo\Region::getStatus()
187 : Checks whether an error has previous occurred for this region object. Returns CAIRO_STATUS_SUCCESS or CAIRO_STATUS_NO_MEMORY */
188 2 : PHP_METHOD(Cairo_Region, getStatus)
189 : {
190 : cairo_region_object *region_object;
191 : zval status_case;
192 :
193 3 : ZEND_PARSE_PARAMETERS_NONE();
194 :
195 2 : region_object = cairo_region_object_get(getThis());
196 1 : if (!region_object) {
197 0 : RETURN_THROWS();
198 : }
199 :
200 1 : status_case = php_enum_from_cairo_c_enum(
201 : ce_cairo_status,
202 1 : cairo_region_status(region_object->region)
203 : );
204 :
205 1 : if (Z_TYPE(status_case) == IS_OBJECT) {
206 2 : RETURN_ZVAL(&status_case, 1, 1);
207 : }
208 : }
209 : /* }}} */
210 :
211 : /* {{{ proto long \Cairo\Region::getExtents()
212 : Gets the bounding rectangle of a region. Returns a \Cairo\Rectangle. */
213 27 : PHP_METHOD(Cairo_Region, getExtents)
214 : {
215 : cairo_region_object *region_object;
216 : cairo_rectangle_object *rectangle_object;
217 : cairo_rectangle_int_t int_rect;
218 :
219 27 : ZEND_PARSE_PARAMETERS_NONE();
220 :
221 52 : region_object = cairo_region_object_get(getThis());
222 26 : if (!region_object) {
223 0 : RETURN_THROWS();
224 : }
225 :
226 26 : cairo_region_get_extents(region_object->region, &int_rect);
227 :
228 26 : object_init_ex(return_value, php_cairo_get_rectangle_ce());
229 26 : rectangle_object = Z_CAIRO_RECTANGLE_P(return_value);
230 26 : cairo_rectangle_int_to_double(&int_rect, rectangle_object->rect);
231 : }
232 : /* }}} */
233 :
234 : /* {{{ proto long \Cairo\Region::getNumRectangles()
235 : Returns the number of rectangles contained in region. */
236 27 : PHP_METHOD(Cairo_Region, getNumRectangles)
237 : {
238 : cairo_region_object *region_object;
239 :
240 27 : ZEND_PARSE_PARAMETERS_NONE();
241 :
242 52 : region_object = cairo_region_object_get(getThis());
243 26 : if (!region_object) {
244 0 : RETURN_THROWS();
245 : }
246 :
247 26 : RETVAL_LONG(cairo_region_num_rectangles(region_object->region));
248 : }
249 : /* }}} */
250 :
251 : /* {{{ proto long \Cairo\Region::getRectangle(int number).
252 : Returns the nth rectangle in region or false if rectangle does not exist. */
253 5 : PHP_METHOD(Cairo_Region, getRectangle)
254 : {
255 : zend_long rect_id;
256 : cairo_region_object *region_object;
257 : cairo_rectangle_object *rectangle_object;
258 : cairo_rectangle_int_t int_rect;
259 :
260 5 : ZEND_PARSE_PARAMETERS_START(1, 1)
261 10 : Z_PARAM_LONG(rect_id)
262 5 : ZEND_PARSE_PARAMETERS_END();
263 :
264 8 : region_object = cairo_region_object_get(getThis());
265 4 : if (!region_object) {
266 0 : RETURN_THROWS();
267 : }
268 :
269 4 : if ((int) rect_id > cairo_region_num_rectangles(region_object->region) - 1) {
270 1 : RETURN_FALSE;
271 : }
272 :
273 3 : cairo_region_get_rectangle(region_object->region, (int) rect_id, &int_rect);
274 :
275 3 : object_init_ex(return_value, php_cairo_get_rectangle_ce());
276 3 : rectangle_object = Z_CAIRO_RECTANGLE_P(return_value);
277 3 : cairo_rectangle_int_to_double(&int_rect, rectangle_object->rect);
278 : }
279 : /* }}} */
280 :
281 : /* {{{ proto bool \Cairo\Region::isEmpty()
282 : Checks whether region is empty. Returns TRUE if region is empty, FALSE if it isn't. */
283 2 : PHP_METHOD(Cairo_Region, isEmpty)
284 : {
285 : cairo_region_object *region_object;
286 :
287 2 : ZEND_PARSE_PARAMETERS_NONE();
288 :
289 2 : region_object = cairo_region_object_get(getThis());
290 1 : if (!region_object) {
291 0 : RETURN_THROWS();
292 : }
293 :
294 1 : RETVAL_BOOL(cairo_region_is_empty(region_object->region));
295 : }
296 : /* }}} */
297 :
298 : /* {{{ proto long \Cairo\Region::containsPoint(long x, long y)
299 : Checks whether (x, y) is contained in region. Returns TRUE if (x, y) is contained in region, FALSE if it is not. */
300 11 : PHP_METHOD(Cairo_Region, containsPoint)
301 : {
302 : zend_long x, y;
303 : cairo_region_object *region_object;
304 :
305 11 : ZEND_PARSE_PARAMETERS_START(2, 2)
306 18 : Z_PARAM_LONG(x)
307 18 : Z_PARAM_LONG(y)
308 11 : ZEND_PARSE_PARAMETERS_END();
309 :
310 18 : region_object = cairo_region_object_get(getThis());
311 9 : if (!region_object) {
312 0 : RETURN_THROWS();
313 : }
314 :
315 9 : RETVAL_BOOL(cairo_region_contains_point(region_object->region, (int) x, (int) y));
316 : }
317 : /* }}} */
318 :
319 : /* {{{ proto \Cairo\Region\Overlap \Cairo\Region::containsRectangle(Cairo\Rectangle $rect)
320 : Checks whether rectangle is inside, outside or partially contained in region.
321 : Returns OVERLAP::IN if rectangle is entirely inside region,
322 : OVERLAP::OUT if rectangle is entirely outside region, or
323 : OVERLAP::PART if rectangle is partially inside and partially outside region. */
324 7 : PHP_METHOD(Cairo_Region, containsRectangle)
325 : {
326 : cairo_rectangle_object *rectangle_object;
327 : cairo_region_object *region_object;
328 : zval *rectangle_zval;
329 : zval region_overlap_case;
330 : cairo_rectangle_int_t int_rect;
331 :
332 7 : ZEND_PARSE_PARAMETERS_START(1, 1)
333 10 : Z_PARAM_OBJECT_OF_CLASS(rectangle_zval, ce_cairo_rectangle)
334 11 : ZEND_PARSE_PARAMETERS_END();
335 :
336 8 : region_object = cairo_region_object_get(getThis());
337 4 : if (!region_object) {
338 0 : RETURN_THROWS();
339 : }
340 :
341 4 : rectangle_object = Z_CAIRO_RECTANGLE_P(rectangle_zval);
342 4 : if (!rectangle_object) {
343 0 : RETURN_NULL();
344 : }
345 :
346 4 : cairo_expand_to_rectangle_int(rectangle_object->rect, &int_rect);
347 :
348 4 : region_overlap_case = php_enum_from_cairo_c_enum(
349 : ce_cairo_region_overlap,
350 4 : cairo_region_contains_rectangle(region_object->region, &int_rect)
351 : );
352 :
353 4 : if (Z_TYPE(region_overlap_case) == IS_OBJECT) {
354 8 : RETURN_ZVAL(®ion_overlap_case, 1, 1);
355 : }
356 : }
357 : /* }}} */
358 :
359 : /* {{{ proto long \Cairo\Region::equal(\Cairo\Region region)
360 : Compares whether region_a is equivalent to region_b. NULL as an argument is equal to itself, but not to any non-NULL region. */
361 7 : PHP_METHOD(Cairo_Region, equal)
362 : {
363 7 : zval *other_region = NULL;
364 : cairo_region_object *region_obj, *other_region_obj;
365 :
366 7 : ZEND_PARSE_PARAMETERS_START(1, 1)
367 12 : Z_PARAM_OBJECT_OF_CLASS_OR_NULL(other_region, ce_cairo_region)
368 8 : ZEND_PARSE_PARAMETERS_END();
369 :
370 10 : region_obj = cairo_region_object_get(getThis());
371 5 : if (!region_obj) {
372 0 : RETURN_THROWS();
373 : }
374 :
375 5 : if (other_region == NULL) {
376 1 : RETURN_TRUE;
377 : }
378 :
379 4 : other_region_obj = Z_CAIRO_REGION_P(other_region);
380 4 : RETVAL_BOOL(cairo_region_equal(region_obj->region, other_region_obj->region));
381 : }
382 : /* }}} */
383 :
384 : /* {{{ proto long \Cairo\Region::translate(long dx, long dy)
385 : Translates region by (dx, dy). */
386 5 : PHP_METHOD(Cairo_Region, translate)
387 : {
388 : zend_long dx, dy;
389 : cairo_region_object *region_object;
390 :
391 5 : ZEND_PARSE_PARAMETERS_START(2, 2)
392 4 : Z_PARAM_LONG(dx)
393 4 : Z_PARAM_LONG(dy)
394 5 : ZEND_PARSE_PARAMETERS_END();
395 :
396 4 : region_object = cairo_region_object_get(getThis());
397 2 : if (!region_object) {
398 0 : RETURN_THROWS();
399 : }
400 :
401 2 : cairo_region_translate(region_object->region, (int) dx, (int) dy);
402 2 : if (php_cairo_throw_exception(cairo_region_status(region_object->region))) {
403 0 : RETURN_THROWS();
404 : }
405 : }
406 : /* }}} */
407 :
408 : /* {{{ proto \Cairo\Status \Cairo\Region::intersect(\Cairo\Region other_region)
409 : Computes the intersection with other_region and stores the result. */
410 4 : PHP_METHOD(Cairo_Region, intersect)
411 : {
412 : cairo_region_object *region_obj, *other_region_obj;
413 : zval *other_region;
414 : zval status_case;
415 :
416 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
417 6 : Z_PARAM_OBJECT_OF_CLASS(other_region, ce_cairo_region)
418 6 : ZEND_PARSE_PARAMETERS_END();
419 :
420 4 : region_obj = cairo_region_object_get(getThis());
421 2 : if (!region_obj) {
422 0 : RETURN_THROWS();
423 : }
424 :
425 2 : other_region_obj = Z_CAIRO_REGION_P(other_region);
426 :
427 2 : status_case = php_enum_from_cairo_c_enum(
428 : ce_cairo_status,
429 2 : cairo_region_intersect(region_obj->region, other_region_obj->region)
430 : );
431 :
432 2 : if (Z_TYPE(status_case) == IS_OBJECT) {
433 4 : RETURN_ZVAL(&status_case, 1, 1);
434 : }
435 : }
436 : /* }}} */
437 :
438 : /* {{{ proto \Cairo\Status \Cairo\Region::intersectRectangle(Cairo\Rectangle $rect)
439 : Computes the intersection with rectangle and stores the result. */
440 3 : PHP_METHOD(Cairo_Region, intersectRectangle)
441 : {
442 : cairo_rectangle_object *rectangle_object;
443 : cairo_region_object *region_object;
444 : zval *rectangle_zval;
445 : zval status_case;
446 : cairo_rectangle_int_t int_rect;
447 :
448 3 : ZEND_PARSE_PARAMETERS_START(1, 1)
449 4 : Z_PARAM_OBJECT_OF_CLASS(rectangle_zval, ce_cairo_rectangle)
450 4 : ZEND_PARSE_PARAMETERS_END();
451 :
452 2 : region_object = cairo_region_object_get(getThis());
453 1 : if (!region_object) {
454 0 : RETURN_THROWS();
455 : }
456 :
457 1 : rectangle_object = Z_CAIRO_RECTANGLE_P(rectangle_zval);
458 1 : if (!rectangle_object) {
459 0 : RETURN_NULL();
460 : }
461 :
462 1 : cairo_expand_to_rectangle_int(rectangle_object->rect, &int_rect);
463 :
464 1 : status_case = php_enum_from_cairo_c_enum(
465 : ce_cairo_status,
466 1 : cairo_region_intersect_rectangle(region_object->region, &int_rect)
467 : );
468 :
469 1 : if (Z_TYPE(status_case) == IS_OBJECT) {
470 2 : RETURN_ZVAL(&status_case, 1, 1);
471 : }
472 : }
473 : /* }}} */
474 :
475 : /* {{{ proto \Cairo\Status \Cairo\Region::subtract(\Cairo\Region other_region)
476 : Subtracts other_region and stores the result. */
477 4 : PHP_METHOD(Cairo_Region, subtract)
478 : {
479 : zval *other_region;
480 : cairo_region_object *region_obj, *other_region_obj;
481 : zval status_case;
482 :
483 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
484 6 : Z_PARAM_OBJECT_OF_CLASS(other_region, ce_cairo_region)
485 6 : ZEND_PARSE_PARAMETERS_END();
486 :
487 4 : region_obj = cairo_region_object_get(getThis());
488 2 : if (!region_obj) {
489 0 : RETURN_THROWS();
490 : }
491 :
492 2 : other_region_obj = Z_CAIRO_REGION_P(other_region);
493 :
494 2 : status_case = php_enum_from_cairo_c_enum(
495 : ce_cairo_status,
496 2 : cairo_region_subtract(region_obj->region, other_region_obj->region)
497 : );
498 :
499 2 : if (Z_TYPE(status_case) == IS_OBJECT) {
500 4 : RETURN_ZVAL(&status_case, 1, 1);
501 : }
502 : }
503 : /* }}} */
504 :
505 : /* {{{ proto \Cairo\Status \Cairo\Region::subtractRectangle(Cairo\Rectangle $rect)
506 : Subtracts rectangle from region and stores the result. */
507 3 : PHP_METHOD(Cairo_Region, subtractRectangle)
508 : {
509 : zval *rectangle_zval;
510 : cairo_rectangle_object *rectangle_object;
511 : cairo_region_object *region_object;
512 : zval status_case;
513 : cairo_rectangle_int_t int_rect;
514 :
515 3 : ZEND_PARSE_PARAMETERS_START(1, 1)
516 4 : Z_PARAM_OBJECT_OF_CLASS(rectangle_zval, ce_cairo_rectangle)
517 4 : ZEND_PARSE_PARAMETERS_END();
518 :
519 2 : region_object = cairo_region_object_get(getThis());
520 1 : if (!region_object) {
521 0 : RETURN_THROWS();
522 : }
523 :
524 1 : rectangle_object = Z_CAIRO_RECTANGLE_P(rectangle_zval);
525 1 : if (!rectangle_object) {
526 0 : RETURN_NULL();
527 : }
528 :
529 1 : cairo_expand_to_rectangle_int(rectangle_object->rect, &int_rect);
530 :
531 1 : status_case = php_enum_from_cairo_c_enum(
532 : ce_cairo_status,
533 1 : cairo_region_subtract_rectangle(region_object->region, &int_rect)
534 : );
535 :
536 1 : if (Z_TYPE(status_case) == IS_OBJECT) {
537 2 : RETURN_ZVAL(&status_case, 1, 1);
538 : }
539 : }
540 : /* }}} */
541 :
542 : /* {{{ proto \Cairo\Status \Cairo\Region::union(\Cairo\Region other_region)
543 : Computes the union with other_region and stores the result. */
544 4 : PHP_METHOD(Cairo_Region, union)
545 : {
546 : zval *other_region;
547 : cairo_region_object *region_obj, *other_region_obj;
548 : zval status_case;
549 :
550 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
551 6 : Z_PARAM_OBJECT_OF_CLASS(other_region, ce_cairo_region)
552 6 : ZEND_PARSE_PARAMETERS_END();
553 :
554 4 : region_obj = cairo_region_object_get(getThis());
555 2 : if (!region_obj) {
556 0 : RETURN_THROWS();
557 : }
558 :
559 2 : other_region_obj = Z_CAIRO_REGION_P(other_region);
560 :
561 2 : status_case = php_enum_from_cairo_c_enum(
562 : ce_cairo_status,
563 2 : cairo_region_union(region_obj->region, other_region_obj->region)
564 : );
565 :
566 2 : if (Z_TYPE(status_case) == IS_OBJECT) {
567 4 : RETURN_ZVAL(&status_case, 1, 1);
568 : }
569 : }
570 : /* }}} */
571 :
572 : /* {{{ proto \Cairo\Status \Cairo\Region::unionRectangle(Cairo\Rectangle $rect)
573 : Computes the union of region with rectangle and stores the result. */
574 4 : PHP_METHOD(Cairo_Region, unionRectangle)
575 : {
576 : zval *rectangle_zval;
577 : cairo_rectangle_object *rectangle_object;
578 : cairo_region_object *region_object;
579 : zval status_case;
580 : cairo_rectangle_int_t int_rect;
581 :
582 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
583 6 : Z_PARAM_OBJECT_OF_CLASS(rectangle_zval, ce_cairo_rectangle)
584 6 : ZEND_PARSE_PARAMETERS_END();
585 :
586 4 : region_object = cairo_region_object_get(getThis());
587 2 : if (!region_object) {
588 0 : RETURN_THROWS();
589 : }
590 :
591 2 : rectangle_object = Z_CAIRO_RECTANGLE_P(rectangle_zval);
592 2 : if (!rectangle_object) {
593 0 : RETURN_NULL();
594 : }
595 :
596 2 : cairo_expand_to_rectangle_int(rectangle_object->rect, &int_rect);
597 :
598 2 : status_case = php_enum_from_cairo_c_enum(
599 : ce_cairo_status,
600 2 : cairo_region_union_rectangle(region_object->region, &int_rect)
601 : );
602 :
603 2 : if (Z_TYPE(status_case) == IS_OBJECT) {
604 4 : RETURN_ZVAL(&status_case, 1, 1);
605 : }
606 : }
607 : /* }}} */
608 :
609 : /* {{{ proto \Cairo\Status \Cairo\Region::xor(\Cairo\Region other_region)
610 : Computes the exclusive difference with other_region and stores the result.
611 : That is, region will be set to contain all areas that are either in region or in other_region, but not in both. */
612 4 : PHP_METHOD(Cairo_Region, xor)
613 : {
614 : zval *other_region;
615 : cairo_region_object *region_obj, *other_region_obj;
616 : zval status_case;
617 :
618 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
619 6 : Z_PARAM_OBJECT_OF_CLASS(other_region, ce_cairo_region)
620 6 : ZEND_PARSE_PARAMETERS_END();
621 :
622 4 : region_obj = cairo_region_object_get(getThis());
623 2 : if (!region_obj) {
624 0 : RETURN_THROWS();
625 : }
626 :
627 2 : other_region_obj = Z_CAIRO_REGION_P(other_region);
628 :
629 2 : status_case = php_enum_from_cairo_c_enum(
630 : ce_cairo_status,
631 2 : cairo_region_xor(region_obj->region, other_region_obj->region)
632 : );
633 :
634 2 : if (Z_TYPE(status_case) == IS_OBJECT) {
635 4 : RETURN_ZVAL(&status_case, 1, 1);
636 : }
637 : }
638 : /* }}} */
639 :
640 : /* {{{ proto \Cairo\Status \Cairo\Region::xorRectangle(Cairo\Rectangle $rect)
641 : Computes the exclusive difference of region with rectangle and stores the result.
642 : That is, region will be set to contain all areas that are either in region or in rectangle, but not in both. */
643 4 : PHP_METHOD(Cairo_Region, xorRectangle)
644 : {
645 : zval *rectangle_zval;
646 : cairo_rectangle_object *rectangle_object;
647 : cairo_region_object *region_object;
648 : zval status_case;
649 : cairo_rectangle_int_t int_rect;
650 :
651 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
652 6 : Z_PARAM_OBJECT_OF_CLASS(rectangle_zval, ce_cairo_rectangle)
653 6 : ZEND_PARSE_PARAMETERS_END();
654 :
655 4 : region_object = cairo_region_object_get(getThis());
656 2 : if (!region_object) {
657 0 : RETURN_THROWS();
658 : }
659 :
660 2 : rectangle_object = Z_CAIRO_RECTANGLE_P(rectangle_zval);
661 2 : if (!rectangle_object) {
662 0 : RETURN_NULL();
663 : }
664 :
665 2 : cairo_expand_to_rectangle_int(rectangle_object->rect, &int_rect);
666 :
667 2 : status_case = php_enum_from_cairo_c_enum(
668 : ce_cairo_status,
669 2 : cairo_region_xor_rectangle(region_object->region, &int_rect)
670 : );
671 :
672 2 : if (Z_TYPE(status_case) == IS_OBJECT) {
673 4 : RETURN_ZVAL(&status_case, 1, 1);
674 : }
675 : }
676 : /* }}} */
677 :
678 :
679 : /* ----------------------------------------------------------------
680 : \Cairo\Region Definition and registration
681 : ------------------------------------------------------------------*/
682 :
683 :
684 : /* {{{ PHP_MINIT_FUNCTION */
685 433 : PHP_MINIT_FUNCTION(cairo_region)
686 : {
687 433 : memcpy(
688 : &cairo_region_object_handlers,
689 : zend_get_std_object_handlers(),
690 : sizeof(zend_object_handlers)
691 : );
692 :
693 433 : cairo_region_object_handlers.offset = XtOffsetOf(cairo_region_object, std);
694 433 : cairo_region_object_handlers.free_obj = cairo_region_free_obj;
695 433 : cairo_region_object_handlers.clone_obj = cairo_region_clone_obj;
696 :
697 433 : ce_cairo_region = register_class_Cairo_Region();
698 433 : ce_cairo_region->create_object = cairo_region_create_object;
699 :
700 : /* Region\Overlap */
701 433 : ce_cairo_region_overlap = register_class_Cairo_Region_Overlap();
702 :
703 433 : return SUCCESS;
704 : }
|