Line data Source code
1 : /*
2 : +----------------------------------------------------------------------+
3 : | For PHP Version 8 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 2015 Elizabeth M Smith, 2022 Swen Zanon |
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 "context_arginfo.h"
26 :
27 : zend_class_entry *ce_cairo_context;
28 : zend_class_entry *ce_cairo_fillrule;
29 : zend_class_entry *ce_cairo_linecap;
30 : zend_class_entry *ce_cairo_linejoin;
31 : zend_class_entry *ce_cairo_operator;
32 :
33 :
34 : static zend_object_handlers cairo_context_object_handlers;
35 :
36 421 : cairo_context_object *cairo_context_fetch_object(zend_object *object) {
37 421 : return (cairo_context_object *) ((char*) (object) - XtOffsetOf(cairo_context_object, std));
38 : }
39 :
40 208 : cairo_context_object *cairo_context_object_get(zval *zv) {
41 :
42 208 : cairo_context_object *object = Z_CAIRO_CONTEXT_P(zv);
43 :
44 208 : if (object->context == NULL) {
45 0 : zend_throw_exception_ex(ce_cairo_exception, 0,
46 : "Internal context object missing in %s, you must call parent::__construct in extended classes.",
47 0 : ZSTR_VAL(Z_OBJCE_P(zv)->name));
48 0 : return NULL;
49 : }
50 :
51 208 : return object;
52 : }
53 :
54 :
55 : /* ----------------------------------------------------------------
56 : Cairo\Context C API
57 : ------------------------------------------------------------------*/
58 :
59 : /* {{{ */
60 0 : cairo_t *cairo_context_object_get_context(zval *zv) {
61 0 : cairo_context_object *context_object = cairo_context_object_get(zv);
62 0 : return context_object->context;
63 : }
64 : /* }}} */
65 :
66 0 : zend_class_entry* php_cairo_get_context_ce() {
67 0 : return ce_cairo_context;
68 : }
69 :
70 0 : extern cairo_t * php_cairo_context_reference(cairo_t *context) {
71 0 : return cairo_reference(context);
72 : }
73 :
74 :
75 : /* ----------------------------------------------------------------
76 : Cairo\Context Object management
77 : ------------------------------------------------------------------*/
78 :
79 : /* {{{ */
80 108 : static void cairo_context_free_obj(zend_object *object)
81 : {
82 108 : cairo_context_object *intern = cairo_context_fetch_object(object);
83 :
84 108 : if (!intern) {
85 0 : return;
86 : }
87 :
88 108 : zval_ptr_dtor(&intern->surface);
89 108 : zval_ptr_dtor(&intern->matrix);
90 108 : zval_ptr_dtor(&intern->pattern);
91 108 : zval_ptr_dtor(&intern->font_face);
92 108 : zval_ptr_dtor(&intern->font_matrix);
93 108 : zval_ptr_dtor(&intern->font_options);
94 108 : zval_ptr_dtor(&intern->scaled_font);
95 :
96 108 : if (intern->context) {
97 105 : cairo_destroy(intern->context);
98 : }
99 :
100 108 : zend_object_std_dtor(&intern->std);
101 : }
102 : /* }}} */
103 :
104 : /* {{{ */
105 108 : static zend_object* cairo_context_obj_ctor(zend_class_entry *ce, cairo_context_object **intern)
106 : {
107 108 : cairo_context_object *object = ecalloc(1, sizeof(cairo_context_object) + zend_object_properties_size(ce));
108 :
109 108 : ZVAL_UNDEF(&object->surface);
110 108 : ZVAL_UNDEF(&object->matrix);
111 108 : ZVAL_UNDEF(&object->pattern);
112 108 : ZVAL_UNDEF(&object->font_face);
113 108 : ZVAL_UNDEF(&object->font_matrix);
114 108 : ZVAL_UNDEF(&object->scaled_font);
115 :
116 108 : zend_object_std_init(&object->std, ce);
117 108 : object->std.handlers = &cairo_context_object_handlers;
118 108 : *intern = object;
119 :
120 108 : return &object->std;
121 : }
122 : /* }}} */
123 :
124 : /* {{{ */
125 108 : zend_object* cairo_context_create_object(zend_class_entry *ce)
126 : {
127 108 : cairo_context_object *context = NULL;
128 108 : zend_object *return_value = cairo_context_obj_ctor(ce, &context);
129 :
130 108 : object_properties_init(&context->std, ce);
131 108 : return return_value;
132 : }
133 : /* }}} */
134 :
135 :
136 : /* ----------------------------------------------------------------
137 : Cairo\Context Class API
138 : ------------------------------------------------------------------*/
139 :
140 : /* Basic Context */
141 :
142 : /* {{{ proto void __construct(object surface)
143 : Returns new CairoContext object on the requested surface */
144 108 : PHP_METHOD(Cairo_Context, __construct)
145 : {
146 : zval *surface_zval;
147 : cairo_context_object *context_object;
148 : cairo_surface_object *surface_object;
149 :
150 108 : ZEND_PARSE_PARAMETERS_START(1, 1)
151 212 : Z_PARAM_OBJECT_OF_CLASS(surface_zval, ce_cairo_surface)
152 108 : ZEND_PARSE_PARAMETERS_END();
153 :
154 210 : context_object = Z_CAIRO_CONTEXT_P(getThis());
155 105 : if (!context_object) {
156 0 : RETURN_NULL();
157 : }
158 :
159 105 : surface_object = cairo_surface_object_get(surface_zval);
160 105 : if (!surface_object) {
161 0 : RETURN_THROWS();
162 : }
163 :
164 105 : context_object->context = cairo_create(surface_object->surface);
165 105 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
166 0 : RETURN_THROWS();
167 : }
168 :
169 105 : ZVAL_COPY(&context_object->surface, surface_zval);
170 : }
171 : /* }}} */
172 :
173 : /* {{{ proto \Cairo\Status \Cairo\Context::getStatus()
174 : Returns the current integer status of the CairoContext */
175 4 : PHP_METHOD(Cairo_Context, getStatus)
176 : {
177 : cairo_context_object *context_object;
178 : zval status_case;
179 :
180 7 : ZEND_PARSE_PARAMETERS_NONE();
181 :
182 6 : context_object = cairo_context_object_get(getThis());
183 3 : if (!context_object) {
184 0 : RETURN_THROWS();
185 : }
186 :
187 3 : status_case = php_enum_from_cairo_c_enum(
188 : ce_cairo_status,
189 3 : cairo_status(context_object->context)
190 : );
191 :
192 3 : if (Z_TYPE(status_case) == IS_OBJECT) {
193 6 : RETURN_ZVAL(&status_case, 1, 1);
194 : }
195 : }
196 : /* }}} */
197 :
198 : /* {{{ proto void \Cairo\Context::save()
199 : Makes a copy of the current state of the context and saves it on an internal stack of saved states */
200 3 : PHP_METHOD(Cairo_Context, save)
201 : {
202 : cairo_context_object *context_object;
203 :
204 3 : ZEND_PARSE_PARAMETERS_NONE();
205 :
206 4 : context_object = cairo_context_object_get(getThis());
207 2 : if (!context_object) {
208 0 : RETURN_THROWS();
209 : }
210 :
211 2 : cairo_save(context_object->context);
212 2 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
213 0 : RETURN_THROWS();
214 : }
215 : }
216 : /* }}} */
217 :
218 : /* {{{ proto void \Cairo\Context::restore()
219 : Restores the context to the state saved and removes that state from the stack of saved states */
220 3 : PHP_METHOD(Cairo_Context, restore)
221 : {
222 : cairo_context_object *context_object;
223 :
224 3 : ZEND_PARSE_PARAMETERS_NONE();
225 :
226 4 : context_object = cairo_context_object_get(getThis());
227 2 : if (!context_object) {
228 0 : RETURN_THROWS();
229 : }
230 :
231 2 : cairo_restore(context_object->context);
232 2 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
233 1 : RETURN_THROWS();
234 : }
235 : }
236 : /* }}} */
237 :
238 : /* {{{ proto void \Cairo\Context::pushGroup()
239 : Temporarily redirects drawing to an intermediate surface known as a group. */
240 4 : PHP_METHOD(Cairo_Context, pushGroup)
241 : {
242 : cairo_context_object *context_object;
243 :
244 4 : ZEND_PARSE_PARAMETERS_NONE();
245 :
246 6 : context_object = cairo_context_object_get(getThis());
247 3 : if (!context_object) {
248 0 : RETURN_THROWS();
249 : }
250 :
251 3 : cairo_push_group(context_object->context);
252 3 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
253 0 : RETURN_THROWS();
254 : }
255 : }
256 : /* }}} */
257 :
258 : /* {{{ proto void \Cairo\Context::pushGroupWithContent(\Cairo\Surface\Content content)
259 : Temporarily redirects drawing to an intermediate surface known as a group. */
260 4 : PHP_METHOD(Cairo_Context, pushGroupWithContent)
261 : {
262 : cairo_context_object *context_object;
263 : zval *content;
264 :
265 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
266 4 : Z_PARAM_OBJECT_OF_CLASS(content, ce_cairo_content)
267 4 : ZEND_PARSE_PARAMETERS_END();
268 :
269 2 : context_object = cairo_context_object_get(getThis());
270 1 : if (!context_object) {
271 0 : RETURN_THROWS();
272 : }
273 :
274 1 : cairo_push_group_with_content(
275 : context_object->context,
276 2 : Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(content)))
277 : );
278 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
279 0 : RETURN_THROWS();
280 : }
281 : }
282 : /* }}} */
283 :
284 : /* {{{ proto Cairo\Pattern object \Cairo\Context::popGroup()
285 : Terminates the redirection and returns a new pattern containing the results of all drawing operations performed to the group. */
286 2 : PHP_METHOD(Cairo_Context, popGroup)
287 : {
288 : cairo_pattern_t *pattern;
289 : cairo_context_object *context_object;
290 : cairo_pattern_object *pattern_object;
291 :
292 2 : ZEND_PARSE_PARAMETERS_NONE();
293 :
294 2 : context_object = cairo_context_object_get(getThis());
295 1 : if (!context_object) {
296 0 : RETURN_THROWS();
297 : }
298 :
299 1 : pattern = cairo_pop_group(context_object->context);
300 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
301 0 : RETURN_THROWS();
302 : }
303 :
304 1 : object_init_ex(return_value, php_cairo_get_pattern_ce(pattern));
305 1 : pattern_object = Z_CAIRO_PATTERN_P(return_value);
306 1 : pattern_object->pattern = pattern;
307 1 : cairo_pattern_reference(pattern_object->pattern);
308 : }
309 : /* }}} */
310 :
311 : /* {{{ proto void \Cairo\Context::popGroupToSource()
312 : Terminates the redirection and installs the resulting pattern as the source pattern in the given cairo context. */
313 2 : PHP_METHOD(Cairo_Context, popGroupToSource)
314 : {
315 : cairo_context_object *context_object;
316 :
317 2 : ZEND_PARSE_PARAMETERS_NONE();
318 :
319 2 : context_object = cairo_context_object_get(getThis());
320 1 : if (!context_object) {
321 0 : RETURN_THROWS();
322 : }
323 :
324 1 : cairo_pop_group_to_source(context_object->context);
325 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
326 0 : RETURN_THROWS();
327 : }
328 : }
329 : /* }}} */
330 :
331 : /* {{{ proto Cairo\Surface object \Cairo\Context::getGroupSurface()
332 : previous method-name was getGroupTarget()
333 : Gets the current destination surface for the context. */
334 2 : PHP_METHOD(Cairo_Context, getGroupSurface)
335 : {
336 : cairo_context_object *context_object;
337 : cairo_surface_object *surface_object;
338 :
339 2 : ZEND_PARSE_PARAMETERS_NONE();
340 :
341 2 : context_object = cairo_context_object_get(getThis());
342 1 : if (!context_object) {
343 0 : RETURN_THROWS();
344 : }
345 :
346 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
347 0 : RETURN_THROWS();
348 : }
349 :
350 1 : object_init_ex(
351 : return_value,
352 : php_cairo_get_surface_ce(cairo_get_group_target(context_object->context))
353 : );
354 1 : surface_object = Z_CAIRO_SURFACE_P(return_value);
355 1 : surface_object->surface = cairo_get_group_target(context_object->context);
356 1 : cairo_surface_reference(surface_object->surface);
357 : }
358 : /* }}} */
359 :
360 : // /* {{{ proto void \Cairo\Context::setSourceRGB(float red, float green, float blue)
361 : // Sets the source pattern within context to an opaque color.
362 : // This opaque color will then be used for any subsequent drawing operation
363 : // until a new source pattern is set. */
364 : // PHP_METHOD(Cairo_Context, setSourceRGB)
365 : // {
366 : // double red = 0.0, green = 0.0, blue = 0.0;
367 : // cairo_context_object *context_object;
368 :
369 : // ZEND_PARSE_PARAMETERS_START(3, 3)
370 : // Z_PARAM_DOUBLE(red)
371 : // Z_PARAM_DOUBLE(green)
372 : // Z_PARAM_DOUBLE(blue)
373 : // ZEND_PARSE_PARAMETERS_END();
374 :
375 : // context_object = cairo_context_object_get(getThis());
376 : // if (!context_object) {
377 : // RETURN_THROWS();
378 : // }
379 :
380 : // cairo_set_source_rgb(context_object->context, red, green, blue);
381 : // if (php_cairo_throw_exception(cairo_status(context_object->context))) {
382 : // RETURN_THROWS();
383 : // }
384 : // }
385 : // /* }}} */
386 :
387 : /* {{{ proto void \Cairo\Context::setSourceRgba(float red, float green, float blue, float alpha)
388 : Sets the source pattern within context to an translucent color. This opaque color will then be used for any subsequent drawing operation until a new source pattern is set. */
389 13 : PHP_METHOD(Cairo_Context, setSourceRgba)
390 : {
391 13 : double red = 0.0, green = 0.0, blue = 0.0, alpha = 1.0;
392 13 : bool alpha_is_null = true;
393 :
394 : cairo_context_object *context_object;
395 :
396 13 : ZEND_PARSE_PARAMETERS_START(3, 4)
397 18 : Z_PARAM_DOUBLE(red)
398 16 : Z_PARAM_DOUBLE(green)
399 14 : Z_PARAM_DOUBLE(blue)
400 6 : Z_PARAM_OPTIONAL
401 11 : Z_PARAM_DOUBLE_OR_NULL(alpha, alpha_is_null)
402 13 : ZEND_PARSE_PARAMETERS_END();
403 :
404 10 : context_object = cairo_context_object_get(getThis());
405 5 : if (!context_object) {
406 0 : RETURN_THROWS();
407 : }
408 :
409 5 : if (alpha_is_null) {
410 2 : cairo_set_source_rgb(context_object->context, red, green, blue);
411 : } else {
412 3 : cairo_set_source_rgba(context_object->context, red, green, blue, alpha);
413 : }
414 :
415 5 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
416 0 : RETURN_THROWS();
417 : }
418 : }
419 : /* }}} */
420 :
421 : /* {{{ proto void \Cairo\Context::setSurface(object surface [, float x, float y])
422 : previous method-name was setSourceSurface()
423 : This is a convenience function for creating a pattern from surface and setting it as the source. */
424 7 : PHP_METHOD(Cairo_Context, setSurface)
425 : {
426 : zval *surface_zval;
427 : cairo_context_object *context_object;
428 : cairo_surface_object *surface_object;
429 7 : double x = 0.0, y = 0.0;
430 :
431 7 : ZEND_PARSE_PARAMETERS_START(1, 3)
432 10 : Z_PARAM_OBJECT_OF_CLASS(surface_zval, ce_cairo_surface)
433 4 : Z_PARAM_OPTIONAL
434 7 : Z_PARAM_DOUBLE(x)
435 4 : Z_PARAM_DOUBLE(y)
436 7 : ZEND_PARSE_PARAMETERS_END();
437 :
438 4 : context_object = cairo_context_object_get(getThis());
439 2 : if (!context_object) {
440 0 : RETURN_THROWS();
441 : }
442 :
443 2 : surface_object = cairo_surface_object_get(surface_zval);
444 2 : if (!surface_object) {
445 0 : RETURN_THROWS();
446 : }
447 :
448 2 : if (context_object->context == NULL) {
449 0 : context_object->context = cairo_create(surface_object->surface);
450 0 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
451 0 : RETURN_THROWS();
452 : }
453 : }
454 :
455 2 : cairo_set_source_surface(context_object->context, surface_object->surface, x, y);
456 2 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
457 0 : RETURN_THROWS();
458 : }
459 :
460 : /* If there's already a pattern, then we deref and remove it because we just overwrote it */
461 7 : CAIRO_UNREF_AND_UNDEF(context_object->pattern)
462 :
463 : /* If there's already a surface, then we deref and remove it */
464 8 : CAIRO_UNREF_AND_UNDEF(context_object->surface)
465 :
466 : /* we need to be able to get this zval out later, so ref and store */
467 2 : ZVAL_COPY(&context_object->surface, surface_zval);
468 : }
469 : /* }}} */
470 :
471 : /* {{{ proto CairoSurface object \Cairo\Context::getSurface
472 : previous method-name was getTarget()
473 : Gets the target surface for the cairo context that was set on creation */
474 5 : PHP_METHOD(Cairo_Context, getSurface)
475 : {
476 : cairo_surface_t *surface;
477 : cairo_context_object *context_object;
478 : cairo_surface_object *surface_object;
479 :
480 5 : ZEND_PARSE_PARAMETERS_NONE();
481 :
482 8 : context_object = cairo_context_object_get(getThis());
483 4 : if (!context_object) {
484 0 : RETURN_THROWS();
485 : }
486 :
487 : /* If we have a surface stored, grab that zval to use */
488 20 : CAIRO_RETURN_IF_REF(context_object->surface);
489 :
490 : /* Otherwise we spawn a new object */
491 0 : surface = cairo_get_target(context_object->context);
492 0 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
493 0 : RETURN_THROWS();
494 : }
495 :
496 0 : object_init_ex(return_value, php_cairo_get_surface_ce(surface));
497 0 : surface_object = Z_CAIRO_SURFACE_P(return_value);
498 0 : surface_object->surface = surface;
499 0 : cairo_surface_reference(surface_object->surface);
500 : }
501 : /* }}} */
502 :
503 : /* {{{ proto void \Cairo\Context::setPattern(CairoPattern object)
504 : previous method-name was setSource()
505 : Sets the source pattern within context to source.
506 : This pattern will then be used for any subsequent drawing operation until a new source pattern is set. */
507 7 : PHP_METHOD(Cairo_Context, setPattern)
508 : {
509 7 : zval *pattern_zval = NULL;
510 : cairo_context_object *context_object;
511 : cairo_pattern_object *pattern_object;
512 :
513 7 : ZEND_PARSE_PARAMETERS_START(1, 1)
514 10 : Z_PARAM_OBJECT_OF_CLASS(pattern_zval, ce_cairo_pattern)
515 7 : ZEND_PARSE_PARAMETERS_END();
516 :
517 6 : context_object = cairo_context_object_get(getThis());
518 3 : if (!context_object) {
519 0 : RETURN_THROWS();
520 : }
521 :
522 3 : pattern_object = Z_CAIRO_PATTERN_P(pattern_zval);
523 3 : cairo_set_source(context_object->context, pattern_object->pattern);
524 3 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
525 0 : RETURN_THROWS();
526 : }
527 :
528 : /* If there's already a pattern, then we deref and remove it */
529 10 : CAIRO_UNREF_AND_UNDEF(context_object->pattern)
530 :
531 : /* we need to be able to get this zval out later, so ref and store */
532 3 : ZVAL_COPY(&context_object->pattern, pattern_zval);
533 : }
534 : /* }}} */
535 :
536 : /* {{{ proto CairoPattern object \Cairo\Context::getPattern()
537 : previous method-name was getSource()
538 : Gets the current source pattern for the context. */
539 8 : PHP_METHOD(Cairo_Context, getPattern)
540 : {
541 : cairo_pattern_t *pattern;
542 : cairo_context_object *context_object;
543 : cairo_pattern_object *pattern_object;
544 :
545 8 : ZEND_PARSE_PARAMETERS_NONE();
546 :
547 14 : context_object = cairo_context_object_get(getThis());
548 7 : if (!context_object) {
549 0 : RETURN_THROWS();
550 : }
551 :
552 : /* If we have a patter/source object stored, grab that zval to use */
553 25 : CAIRO_RETURN_IF_REF(context_object->pattern);
554 :
555 : /* Otherwise we spawn a new object */
556 5 : pattern = cairo_get_source(context_object->context);
557 5 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
558 0 : RETURN_THROWS();
559 : }
560 :
561 5 : object_init_ex(return_value, php_cairo_get_pattern_ce(pattern));
562 5 : pattern_object = Z_CAIRO_PATTERN_P(return_value);
563 5 : pattern_object->pattern = pattern;
564 5 : cairo_pattern_reference(pattern_object->pattern);
565 : }
566 : /* }}} */
567 :
568 : /* {{{ proto void \Cairo\Context::setAntialias(\Cairo\Antialias antialias)
569 : Set the antialiasing mode of the rasterizer used for drawing shapes. */
570 4 : PHP_METHOD(Cairo_Context, setAntialias)
571 : {
572 : cairo_context_object *context_object;
573 : cairo_antialias_t antialias;
574 : zval *antialias_case;
575 :
576 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
577 4 : Z_PARAM_OBJECT_OF_CLASS(antialias_case, ce_cairo_antialias)
578 4 : ZEND_PARSE_PARAMETERS_END();
579 :
580 2 : context_object = cairo_context_object_get(getThis());
581 1 : if (!context_object) {
582 0 : RETURN_THROWS();
583 : }
584 :
585 1 : antialias = Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(antialias_case)));
586 :
587 1 : cairo_set_antialias(context_object->context, antialias);
588 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
589 0 : RETURN_THROWS();
590 : }
591 : }
592 : /* }}} */
593 :
594 : /* {{{ proto int \Cairo\Context::getAntialias()
595 : Gets the current shape antialiasing mode */
596 3 : PHP_METHOD(Cairo_Context, getAntialias)
597 : {
598 : cairo_context_object *context_object;
599 : cairo_antialias_t antialias;
600 : zval antialias_case;
601 :
602 5 : ZEND_PARSE_PARAMETERS_NONE();
603 :
604 4 : context_object = cairo_context_object_get(getThis());
605 2 : if (!context_object) {
606 0 : RETURN_THROWS();
607 : }
608 :
609 2 : antialias = cairo_get_antialias(context_object->context);
610 :
611 2 : antialias_case = php_enum_from_cairo_c_enum(ce_cairo_antialias, antialias);
612 :
613 2 : if (Z_TYPE(antialias_case) == IS_OBJECT) {
614 4 : RETURN_ZVAL(&antialias_case, 1, 1);
615 : }
616 : }
617 : /* }}} */
618 :
619 : /* {{{ proto void \Cairo\Context::setDash(array dashes [, float offset])
620 : Sets the dash pattern to be used by cairo_stroke() */
621 6 : PHP_METHOD(Cairo_Context, setDash)
622 : {
623 : cairo_context_object *context_object;
624 6 : double offset = 0.0;
625 6 : long num_dashes = 0;
626 : double *dashes_array;
627 6 : zval * dashes = NULL, *pzval;
628 6 : HashTable *dashes_hash = NULL;
629 6 : int i = 0;
630 :
631 6 : ZEND_PARSE_PARAMETERS_START(1, 2)
632 8 : Z_PARAM_ARRAY(dashes)
633 3 : Z_PARAM_OPTIONAL
634 4 : Z_PARAM_DOUBLE(offset)
635 6 : ZEND_PARSE_PARAMETERS_END();
636 :
637 : /* Grab the zend hash and see how big our array will be */
638 2 : dashes_hash = Z_ARRVAL_P(dashes);
639 2 : num_dashes = zend_hash_num_elements(dashes_hash);
640 2 : dashes_array = emalloc(num_dashes * sizeof(double));
641 :
642 : /* iterate the array, make sure we JUGGLE the value to a double */
643 10 : ZEND_HASH_FOREACH_VAL(dashes_hash, pzval) {
644 4 : if (Z_TYPE_P(pzval) != IS_DOUBLE) {
645 4 : convert_to_double(pzval);
646 : }
647 4 : dashes_array[i++] = Z_DVAL_P(pzval);
648 : }
649 : ZEND_HASH_FOREACH_END();
650 :
651 4 : context_object = cairo_context_object_get(getThis());
652 2 : if (!context_object) {
653 0 : RETURN_THROWS();
654 : }
655 :
656 : /* we use i in case we had a bad issue while iterating the array */
657 2 : cairo_set_dash(context_object->context, dashes_array, i, offset);
658 2 : efree(dashes_array);
659 2 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
660 1 : RETURN_THROWS();
661 : }
662 : }
663 : /* }}} */
664 :
665 : /* {{{ proto int \Cairo\Context::getDashCount()
666 : This function returns the length of the dash array or 0 */
667 2 : PHP_METHOD(Cairo_Context, getDashCount)
668 : {
669 : cairo_context_object *context_object;
670 :
671 2 : ZEND_PARSE_PARAMETERS_NONE();
672 :
673 2 : context_object = cairo_context_object_get(getThis());
674 1 : if (!context_object) {
675 0 : RETURN_THROWS();
676 : }
677 :
678 1 : RETURN_LONG(cairo_get_dash_count(context_object->context));
679 : }
680 : /* }}} */
681 :
682 : /* {{{ proto array \Cairo\Context::getDash()
683 : Gets the current dash array and offset */
684 3 : PHP_METHOD(Cairo_Context, getDash)
685 : {
686 : zval sub_array;
687 : cairo_context_object *context_object;
688 3 : double *dashes = NULL;
689 3 : double offset = 0;
690 : int num_dashes, i;
691 :
692 3 : ZEND_PARSE_PARAMETERS_NONE();
693 :
694 4 : context_object = cairo_context_object_get(getThis());
695 2 : if (!context_object) {
696 0 : RETURN_THROWS();
697 : }
698 :
699 : /* Setup container for dashes */
700 2 : num_dashes = cairo_get_dash_count(context_object->context);
701 2 : dashes = emalloc(num_dashes * sizeof(double));
702 :
703 : /* Get dashes and push into PHP array */
704 2 : cairo_get_dash(context_object->context, dashes, &offset);
705 :
706 2 : array_init(&sub_array);
707 5 : for (i = 0; i < num_dashes; i++) {
708 3 : add_next_index_double(&sub_array, dashes[i]);
709 : }
710 2 : efree(dashes);
711 :
712 : /* Put dashes and offset into return */
713 2 : array_init(return_value);
714 : add_assoc_zval(return_value, "dashes", &sub_array);
715 2 : add_assoc_double(return_value, "offset", offset);
716 : }
717 : /* }}} */
718 :
719 : /* {{{ proto void \Cairo\Context::setFillRule(int setting)
720 : Set the current fill rule within the cairo context. The fill rule is used
721 : to determine which regions are inside or outside a complex path */
722 4 : PHP_METHOD(Cairo_Context, setFillRule)
723 : {
724 : cairo_context_object *context_object;
725 : cairo_fill_rule_t fillrule;
726 : zval *fillrule_case;
727 :
728 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
729 4 : Z_PARAM_OBJECT_OF_CLASS(fillrule_case, ce_cairo_fillrule)
730 4 : ZEND_PARSE_PARAMETERS_END();
731 :
732 2 : context_object = cairo_context_object_get(getThis());
733 1 : if (!context_object) {
734 0 : RETURN_THROWS();
735 : }
736 :
737 1 : fillrule = Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(fillrule_case)));
738 :
739 1 : cairo_set_fill_rule(context_object->context, fillrule);
740 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
741 0 : RETURN_THROWS();
742 : }
743 : }
744 : /* }}} */
745 :
746 : /* {{{ proto int \Cairo\Context::getFillRule()
747 : Gets the current fill rule */
748 3 : PHP_METHOD(Cairo_Context, getFillRule)
749 : {
750 : cairo_context_object *context_object;
751 : cairo_fill_rule_t fillrule;
752 : zval fillrule_case;
753 :
754 5 : ZEND_PARSE_PARAMETERS_NONE();
755 :
756 4 : context_object = cairo_context_object_get(getThis());
757 2 : if (!context_object) {
758 0 : RETURN_THROWS();
759 : }
760 :
761 2 : fillrule = cairo_get_fill_rule(context_object->context);
762 :
763 2 : fillrule_case = php_enum_from_cairo_c_enum(ce_cairo_fillrule, fillrule);
764 :
765 2 : if (Z_TYPE(fillrule_case) == IS_OBJECT) {
766 4 : RETURN_ZVAL(&fillrule_case, 1, 1);
767 : }
768 : }
769 : /* }}} */
770 :
771 : /* {{{ proto void \Cairo\Context::setLineCap(\Cairo\LineCap::Butt)
772 : Sets the current line cap style within the cairo context. */
773 4 : PHP_METHOD(Cairo_Context, setLineCap)
774 : {
775 : cairo_context_object *context_object;
776 : zval *linecap_case;
777 :
778 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
779 4 : Z_PARAM_OBJECT_OF_CLASS(linecap_case, ce_cairo_linecap)
780 4 : ZEND_PARSE_PARAMETERS_END();
781 :
782 2 : context_object = cairo_context_object_get(getThis());
783 1 : if (!context_object) {
784 0 : RETURN_THROWS();
785 : }
786 :
787 1 : cairo_set_line_cap(
788 : context_object->context,
789 2 : Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(linecap_case)))
790 : );
791 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
792 0 : RETURN_THROWS();
793 : }
794 : }
795 : /* }}} */
796 :
797 : /* {{{ proto int \Cairo\Context::getLineCap()
798 : Gets the current line cap style */
799 3 : PHP_METHOD(Cairo_Context, getLineCap)
800 : {
801 : cairo_context_object *context_object;
802 : zval linecap_case;
803 :
804 5 : ZEND_PARSE_PARAMETERS_NONE();
805 :
806 4 : context_object = cairo_context_object_get(getThis());
807 2 : if (!context_object) {
808 0 : RETURN_THROWS();
809 : }
810 :
811 2 : linecap_case = php_enum_from_cairo_c_enum(
812 : ce_cairo_linecap,
813 2 : cairo_get_line_cap(context_object->context)
814 : );
815 :
816 2 : if (Z_TYPE(linecap_case) == IS_OBJECT) {
817 4 : RETURN_ZVAL(&linecap_case, 1, 1);
818 : }
819 : }
820 : /* }}} */
821 :
822 : /* {{{ proto void \Cairo\Context::setLineJoin(\Cairo\LineJoin::Miter)
823 : Sets the current line join style within the cairo context. */
824 4 : PHP_METHOD(Cairo_Context, setLineJoin)
825 : {
826 : cairo_context_object *context_object;
827 : cairo_line_join_t linejoin;
828 : zval *linejoin_case;
829 :
830 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
831 4 : Z_PARAM_OBJECT_OF_CLASS(linejoin_case, ce_cairo_linejoin)
832 4 : ZEND_PARSE_PARAMETERS_END();
833 :
834 2 : context_object = cairo_context_object_get(getThis());
835 1 : if (!context_object) {
836 0 : RETURN_THROWS();
837 : }
838 :
839 1 : linejoin = Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(linejoin_case)));
840 :
841 1 : cairo_set_line_join(context_object->context, linejoin);
842 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
843 0 : RETURN_THROWS();
844 : }
845 : }
846 : /* }}} */
847 :
848 : /* {{{ proto int \Cairo\Context::getLineJoin()
849 : Gets the current line join style */
850 3 : PHP_METHOD(Cairo_Context, getLineJoin)
851 : {
852 : cairo_context_object *context_object;
853 : cairo_line_join_t linejoin;
854 : zval linejoin_case;
855 :
856 5 : ZEND_PARSE_PARAMETERS_NONE();
857 :
858 4 : context_object = cairo_context_object_get(getThis());
859 2 : if (!context_object) {
860 0 : RETURN_THROWS();
861 : }
862 :
863 2 : linejoin = cairo_get_line_join(context_object->context);
864 :
865 2 : linejoin_case = php_enum_from_cairo_c_enum(ce_cairo_linejoin, linejoin);
866 :
867 2 : if (Z_TYPE(linejoin_case) == IS_OBJECT) {
868 4 : RETURN_ZVAL(&linejoin_case, 1, 1);
869 : }
870 : }
871 : /* }}} */
872 :
873 : /* {{{ proto void \Cairo\Context::setLineWidth(float width)
874 : Sets the current line width within the cairo context. The line width value
875 : specifies the diameter of a pen that is circular in user space */
876 5 : PHP_METHOD(Cairo_Context, setLineWidth)
877 : {
878 : cairo_context_object *context_object;
879 5 : double width = 0.0;
880 :
881 5 : ZEND_PARSE_PARAMETERS_START(1, 1)
882 6 : Z_PARAM_DOUBLE(width)
883 5 : ZEND_PARSE_PARAMETERS_END();
884 :
885 4 : context_object = cairo_context_object_get(getThis());
886 2 : if (!context_object) {
887 0 : RETURN_THROWS();
888 : }
889 :
890 2 : cairo_set_line_width(context_object->context, width);
891 2 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
892 0 : RETURN_THROWS();
893 : }
894 : }
895 : /* }}} */
896 :
897 : /* {{{ proto double \Cairo\Context::getLineWidth()
898 : This function returns the current line width value exactly as set by cairo_set_line_width() */
899 3 : PHP_METHOD(Cairo_Context, getLineWidth)
900 : {
901 : cairo_context_object *context_object;
902 :
903 3 : ZEND_PARSE_PARAMETERS_NONE();
904 :
905 4 : context_object = cairo_context_object_get(getThis());
906 2 : if (!context_object) {
907 0 : RETURN_THROWS();
908 : }
909 :
910 2 : RETURN_DOUBLE(cairo_get_line_width(context_object->context));
911 : }
912 : /* }}} */
913 :
914 : /* {{{ proto void \Cairo\Context::setMiterLimit(float limit)
915 : Sets the current miter limit within the cairo context. */
916 5 : PHP_METHOD(Cairo_Context, setMiterLimit)
917 : {
918 : cairo_context_object *context_object;
919 5 : double limit = 0.0;
920 :
921 5 : ZEND_PARSE_PARAMETERS_START(1, 1)
922 6 : Z_PARAM_DOUBLE(limit)
923 5 : ZEND_PARSE_PARAMETERS_END();
924 :
925 4 : context_object = cairo_context_object_get(getThis());
926 2 : if (!context_object) {
927 0 : RETURN_THROWS();
928 : }
929 :
930 2 : cairo_set_miter_limit(context_object->context, limit);
931 2 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
932 0 : RETURN_THROWS();
933 : }
934 : }
935 : /* }}} */
936 :
937 : /* {{{ proto double \Cairo\Context::getMiterLimit()
938 : Gets the current miter limit */
939 3 : PHP_METHOD(Cairo_Context, getMiterLimit)
940 : {
941 : cairo_context_object *context_object;
942 :
943 3 : ZEND_PARSE_PARAMETERS_NONE();
944 :
945 4 : context_object = cairo_context_object_get(getThis());
946 2 : if (!context_object) {
947 0 : RETURN_THROWS();
948 : }
949 :
950 2 : RETURN_DOUBLE(cairo_get_miter_limit(context_object->context));
951 : }
952 : /* }}} */
953 :
954 : /* {{{ proto void \Cairo\Context::setOperator(\Cairo\Operator::Over)
955 : Sets the compositing operator to be used for all drawing operations. */
956 5 : PHP_METHOD(Cairo_Context, setOperator)
957 : {
958 : cairo_context_object *context_object;
959 : cairo_operator_t operator;
960 : zval *operator_case;
961 :
962 5 : ZEND_PARSE_PARAMETERS_START(1, 1)
963 6 : Z_PARAM_OBJECT_OF_CLASS(operator_case, ce_cairo_operator)
964 5 : ZEND_PARSE_PARAMETERS_END();
965 :
966 4 : context_object = cairo_context_object_get(getThis());
967 2 : if (!context_object) {
968 0 : RETURN_THROWS();
969 : }
970 :
971 2 : operator = Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(operator_case)));
972 :
973 2 : cairo_set_operator(context_object->context, operator);
974 2 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
975 0 : RETURN_THROWS();
976 : }
977 : }
978 : /* }}} */
979 :
980 : /* {{{ proto int \Cairo\Context::getOperator()
981 : Gets the current compositing operator for a cairo context. */
982 3 : PHP_METHOD(Cairo_Context, getOperator)
983 : {
984 : cairo_context_object *context_object;
985 : cairo_operator_t operator;
986 : zval operator_case;
987 :
988 5 : ZEND_PARSE_PARAMETERS_NONE();
989 :
990 4 : context_object = cairo_context_object_get(getThis());
991 2 : if (!context_object) {
992 0 : RETURN_THROWS();
993 : }
994 :
995 2 : operator = cairo_get_operator(context_object->context);
996 :
997 2 : operator_case = php_enum_from_cairo_c_enum(ce_cairo_operator, operator);
998 :
999 2 : if (Z_TYPE(operator_case) == IS_OBJECT) {
1000 4 : RETURN_ZVAL(&operator_case, 1, 1);
1001 : }
1002 : }
1003 : /* }}} */
1004 :
1005 : /* {{{ proto void \Cairo\Context::setTolerance(float tolerance)
1006 : Sets the tolerance used when converting paths into trapezoids.
1007 : The default value is 0.1. A larger value will give better performance, a smaller value, better appearance. */
1008 5 : PHP_METHOD(Cairo_Context, setTolerance)
1009 : {
1010 : cairo_context_object *context_object;
1011 5 : double tolerance = 0.1;
1012 :
1013 5 : ZEND_PARSE_PARAMETERS_START(1, 1)
1014 6 : Z_PARAM_DOUBLE(tolerance)
1015 5 : ZEND_PARSE_PARAMETERS_END();
1016 :
1017 4 : context_object = cairo_context_object_get(getThis());
1018 2 : if (!context_object) {
1019 0 : RETURN_THROWS();
1020 : }
1021 :
1022 2 : cairo_set_tolerance(context_object->context, tolerance);
1023 2 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1024 0 : RETURN_THROWS();
1025 : }
1026 : }
1027 : /* }}} */
1028 :
1029 : /* {{{ proto double \Cairo\Context::getTolerance()
1030 : Gets the current tolerance value */
1031 3 : PHP_METHOD(Cairo_Context, getTolerance)
1032 : {
1033 : cairo_context_object *context_object;
1034 :
1035 3 : ZEND_PARSE_PARAMETERS_NONE();
1036 :
1037 4 : context_object = cairo_context_object_get(getThis());
1038 2 : if (!context_object) {
1039 0 : RETURN_THROWS();
1040 : }
1041 :
1042 2 : RETURN_DOUBLE(cairo_get_tolerance(context_object->context));
1043 : }
1044 : /* }}} */
1045 :
1046 : /* {{{ proto void \Cairo\Context::clip()
1047 : Establishes a new clip region by intersecting the current clip region with the current path as it
1048 : would be filled by cairo_fill() and according to the current fill rule */
1049 3 : PHP_METHOD(Cairo_Context, clip)
1050 : {
1051 : cairo_context_object *context_object;
1052 :
1053 3 : ZEND_PARSE_PARAMETERS_NONE();
1054 :
1055 4 : context_object = cairo_context_object_get(getThis());
1056 2 : if (!context_object) {
1057 0 : RETURN_THROWS();
1058 : }
1059 :
1060 2 : cairo_clip(context_object->context);
1061 2 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1062 0 : RETURN_THROWS();
1063 : }
1064 : }
1065 : /* }}} */
1066 :
1067 : /* {{{ proto boolean \Cairo\Context::inClip(double x, double y)
1068 : Tests whether the given point is inside the area that would be visible
1069 : through the current clip
1070 : */
1071 17 : PHP_METHOD(Cairo_Context, inClip)
1072 : {
1073 : cairo_context_object *context_object;
1074 17 : double x = 0.0, y = 0.0;
1075 :
1076 17 : ZEND_PARSE_PARAMETERS_START(2, 2)
1077 28 : Z_PARAM_DOUBLE(x)
1078 26 : Z_PARAM_DOUBLE(y)
1079 17 : ZEND_PARSE_PARAMETERS_END();
1080 :
1081 24 : context_object = cairo_context_object_get(getThis());
1082 12 : if (!context_object) {
1083 0 : RETURN_THROWS();
1084 : }
1085 :
1086 12 : RETURN_BOOL(cairo_in_clip(context_object->context, x, y));
1087 : }
1088 : /* }}} */
1089 :
1090 : /* {{{ proto void \Cairo\Context::clipPreserve()
1091 : Establishes a new clip region by intersecting the current clip region with the current path as it
1092 : would be filled by cairo_fill() and according to the current fill rule
1093 : Unlike cairo_clip(), cairo_clip_preserve() preserves the path within the cairo context. */
1094 2 : PHP_METHOD(Cairo_Context, clipPreserve)
1095 : {
1096 : cairo_context_object *context_object;
1097 :
1098 2 : ZEND_PARSE_PARAMETERS_NONE();
1099 :
1100 2 : context_object = cairo_context_object_get(getThis());
1101 1 : if (!context_object) {
1102 0 : RETURN_THROWS();
1103 : }
1104 :
1105 1 : cairo_clip_preserve(context_object->context);
1106 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1107 0 : RETURN_THROWS();
1108 : }
1109 : }
1110 : /* }}} */
1111 :
1112 : /* {{{ proto void \Cairo\Context::resetClip()
1113 : Reset the current clip region to its original, unrestricted state. */
1114 2 : PHP_METHOD(Cairo_Context, resetClip)
1115 : {
1116 : cairo_context_object *context_object;
1117 :
1118 2 : ZEND_PARSE_PARAMETERS_NONE();
1119 :
1120 2 : context_object = cairo_context_object_get(getThis());
1121 1 : if (!context_object) {
1122 0 : RETURN_THROWS();
1123 : }
1124 :
1125 1 : cairo_reset_clip(context_object->context);
1126 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1127 0 : RETURN_THROWS();
1128 : }
1129 : }
1130 : /* }}} */
1131 :
1132 : /* {{{ proto array \Cairo\Context::getClipExtents()
1133 : previous method-name was clipExtents()
1134 : Computes a bounding box in user coordinates covering the area inside the current clip. */
1135 3 : PHP_METHOD(Cairo_Context, getClipExtents)
1136 : {
1137 : cairo_context_object *context_object;
1138 : double x1, y1, x2, y2;
1139 :
1140 3 : ZEND_PARSE_PARAMETERS_NONE();
1141 :
1142 4 : context_object = cairo_context_object_get(getThis());
1143 2 : if (!context_object) {
1144 0 : RETURN_THROWS();
1145 : }
1146 :
1147 2 : cairo_clip_extents(context_object->context, &x1, &y1, &x2, &y2);
1148 2 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1149 0 : RETURN_THROWS();
1150 : }
1151 :
1152 2 : array_init(return_value);
1153 2 : add_assoc_double(return_value, "x1", x1);
1154 2 : add_assoc_double(return_value, "y1", y1);
1155 2 : add_assoc_double(return_value, "x2", x2);
1156 2 : add_assoc_double(return_value, "y2", y2);}
1157 : /* }}} */
1158 :
1159 : /* {{{ proto array \Cairo\Context::clipRectangleList()
1160 : Gets the current stroke region as a list of rectangles in user coordinates. */
1161 2 : PHP_METHOD(Cairo_Context, getClipRectangleList)
1162 : {
1163 : cairo_context_object *context_object;
1164 : cairo_rectangle_list_t *rectangles;
1165 : cairo_rectangle_t rectangle;
1166 : zval rectangle_zv;
1167 : cairo_rectangle_object *rectangle_object;
1168 : int i;
1169 :
1170 2 : ZEND_PARSE_PARAMETERS_NONE();
1171 :
1172 2 : context_object = cairo_context_object_get(getThis());
1173 1 : if (!context_object) {
1174 0 : RETURN_THROWS();
1175 : }
1176 :
1177 1 : rectangles = cairo_copy_clip_rectangle_list(context_object->context);
1178 1 : if (php_cairo_throw_exception(rectangles->status)) {
1179 0 : RETURN_THROWS();
1180 : }
1181 :
1182 1 : array_init(return_value);
1183 :
1184 2 : for (i = 0; i < rectangles->num_rectangles; i++) {
1185 1 : rectangle = rectangles->rectangles[i];
1186 :
1187 1 : object_init_ex(&rectangle_zv, php_cairo_get_rectangle_ce());
1188 1 : rectangle_object = Z_CAIRO_RECTANGLE_P(&rectangle_zv);
1189 1 : *rectangle_object->rect = rectangle;
1190 :
1191 : add_next_index_zval(return_value, &rectangle_zv);
1192 : }
1193 :
1194 1 : cairo_rectangle_list_destroy(rectangles);
1195 : }
1196 : /* }}} */
1197 :
1198 : /* {{{ proto void \Cairo\Context::fill()
1199 : A drawing operator that fills the current path according to the current fill rule,
1200 : (each sub-path is implicitly closed before being filled). */
1201 2 : PHP_METHOD(Cairo_Context, fill)
1202 : {
1203 : cairo_context_object *context_object;
1204 :
1205 2 : ZEND_PARSE_PARAMETERS_NONE();
1206 :
1207 2 : context_object = cairo_context_object_get(getThis());
1208 1 : if (!context_object) {
1209 0 : RETURN_THROWS();
1210 : }
1211 :
1212 1 : cairo_fill(context_object->context);
1213 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1214 0 : RETURN_THROWS();
1215 : }
1216 : }
1217 : /* }}} */
1218 :
1219 : /* {{{ proto void \Cairo\Context::fillPreserve()
1220 : A drawing operator that fills the current path according to the current fill rule,
1221 : (each sub-path is implicitly closed before being filled). Unlike cairo_fill(),
1222 : cairo_fill_preserve() preserves the path within the cairo context. */
1223 2 : PHP_METHOD(Cairo_Context, fillPreserve)
1224 : {
1225 : cairo_context_object *context_object;
1226 :
1227 2 : ZEND_PARSE_PARAMETERS_NONE();
1228 :
1229 2 : context_object = cairo_context_object_get(getThis());
1230 1 : if (!context_object) {
1231 0 : RETURN_THROWS();
1232 : }
1233 :
1234 1 : cairo_fill_preserve(context_object->context);
1235 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1236 0 : RETURN_THROWS();
1237 : }
1238 : }
1239 : /* }}} */
1240 :
1241 : /* {{{ proto array \Cairo\Context::getFillExtents()
1242 : previous method-name was fillExtents()
1243 : Computes a bounding box in user coordinates covering the area that would be affected,
1244 : (the "inked" area), by a cairo_fill() operation given the current path and fill parameters. */
1245 2 : PHP_METHOD(Cairo_Context, getFillExtents)
1246 : {
1247 : cairo_context_object *context_object;
1248 : double x1, y1, x2, y2;
1249 :
1250 2 : ZEND_PARSE_PARAMETERS_NONE();
1251 :
1252 2 : context_object = cairo_context_object_get(getThis());
1253 1 : if (!context_object) {
1254 0 : RETURN_THROWS();
1255 : }
1256 :
1257 1 : cairo_fill_extents(context_object->context, &x1, &y1, &x2, &y2);
1258 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1259 0 : RETURN_THROWS();
1260 : }
1261 :
1262 1 : array_init(return_value);
1263 1 : add_assoc_double(return_value, "x1", x1);
1264 1 : add_assoc_double(return_value, "y1", y1);
1265 1 : add_assoc_double(return_value, "x2", x2);
1266 1 : add_assoc_double(return_value, "y2", y2);}
1267 : /* }}} */
1268 :
1269 : /* {{{ proto bool \Cairo\Context::inFill(int x, int y)
1270 : Tests whether the given point is inside the area that would be affected by a cairo_fill()
1271 : operation given the current path and filling parameters. */
1272 6 : PHP_METHOD(Cairo_Context, inFill)
1273 : {
1274 : cairo_context_object *context_object;
1275 6 : double x = 0.0, y = 0.0;
1276 :
1277 6 : ZEND_PARSE_PARAMETERS_START(2, 2)
1278 6 : Z_PARAM_DOUBLE(x)
1279 4 : Z_PARAM_DOUBLE(y)
1280 6 : ZEND_PARSE_PARAMETERS_END();
1281 :
1282 2 : context_object = cairo_context_object_get(getThis());
1283 1 : if (!context_object) {
1284 0 : RETURN_THROWS();
1285 : }
1286 :
1287 1 : RETURN_BOOL(cairo_in_fill(context_object->context, x, y));
1288 : }
1289 : /* }}} */
1290 :
1291 : /* {{{ proto void \Cairo\Context::mask(CairoPattern object)
1292 : A drawing operator that paints the current source using the alpha channel of pattern as a mask. */
1293 4 : PHP_METHOD(Cairo_Context, mask)
1294 : {
1295 4 : zval *pattern_zval = NULL;
1296 : cairo_context_object *context_object;
1297 : cairo_pattern_object *pattern_object;
1298 :
1299 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
1300 4 : Z_PARAM_OBJECT_OF_CLASS(pattern_zval, ce_cairo_pattern)
1301 4 : ZEND_PARSE_PARAMETERS_END();
1302 :
1303 2 : context_object = cairo_context_object_get(getThis());
1304 1 : if (!context_object) {
1305 0 : RETURN_THROWS();
1306 : }
1307 :
1308 1 : pattern_object = Z_CAIRO_PATTERN_P(pattern_zval);
1309 1 : cairo_mask(context_object->context, pattern_object->pattern);
1310 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1311 0 : RETURN_THROWS();
1312 : }
1313 : }
1314 : /* }}} */
1315 :
1316 : /* {{{ proto void \Cairo\Context::maskSurface(object surface [, float x, float y])
1317 : A drawing operator that paints the current source using the alpha channel of surface as a mask.
1318 : */
1319 7 : PHP_METHOD(Cairo_Context, maskSurface)
1320 : {
1321 7 : zval *surface_zval = NULL;
1322 : cairo_context_object *context_object;
1323 : cairo_surface_object *surface_object;
1324 7 : double x = 0.0, y = 0.0;
1325 :
1326 7 : ZEND_PARSE_PARAMETERS_START(1, 3)
1327 10 : Z_PARAM_OBJECT_OF_CLASS(surface_zval, ce_cairo_surface)
1328 3 : Z_PARAM_OPTIONAL
1329 6 : Z_PARAM_DOUBLE(x)
1330 4 : Z_PARAM_DOUBLE(y)
1331 7 : ZEND_PARSE_PARAMETERS_END();
1332 :
1333 2 : context_object = cairo_context_object_get(getThis());
1334 1 : if (!context_object) {
1335 0 : RETURN_THROWS();
1336 : }
1337 :
1338 1 : surface_object = Z_CAIRO_SURFACE_P(surface_zval);
1339 1 : cairo_mask_surface(context_object->context, surface_object->surface, x, y);
1340 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1341 0 : RETURN_THROWS();
1342 : }
1343 : }
1344 : /* }}} */
1345 :
1346 : /* {{{ proto void \Cairo\Context::paint()
1347 : A drawing operator that paints the current source everywhere within the current clip region. */
1348 2 : PHP_METHOD(Cairo_Context, paint)
1349 : {
1350 : cairo_context_object *context_object;
1351 :
1352 2 : ZEND_PARSE_PARAMETERS_NONE();
1353 :
1354 2 : context_object = cairo_context_object_get(getThis());
1355 1 : if (!context_object) {
1356 0 : RETURN_THROWS();
1357 : }
1358 :
1359 1 : cairo_paint(context_object->context);
1360 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1361 0 : RETURN_THROWS();
1362 : }
1363 : }
1364 : /* }}} */
1365 :
1366 : /* {{{ proto void \Cairo\Context::paintWithAlpha(float alpha)
1367 : A drawing operator that paints the current source everywhere within the current clip region using a mask of constant alpha value alpha. */
1368 4 : PHP_METHOD(Cairo_Context, paintWithAlpha)
1369 : {
1370 : cairo_context_object *context_object;
1371 4 : double alpha = 0.0;
1372 :
1373 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
1374 4 : Z_PARAM_DOUBLE(alpha)
1375 4 : ZEND_PARSE_PARAMETERS_END();
1376 :
1377 2 : context_object = cairo_context_object_get(getThis());
1378 1 : if (!context_object) {
1379 0 : RETURN_THROWS();
1380 : }
1381 :
1382 1 : cairo_paint_with_alpha(context_object->context, alpha);
1383 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1384 0 : RETURN_THROWS();
1385 : }
1386 : }
1387 : /* }}} */
1388 :
1389 : /* {{{ proto void \Cairo\Context::stroke()
1390 : A drawing operator that strokes the current path according to the current line width, line join, line cap, and dash settings. */
1391 2 : PHP_METHOD(Cairo_Context, stroke)
1392 : {
1393 : cairo_context_object *context_object;
1394 :
1395 2 : ZEND_PARSE_PARAMETERS_NONE();
1396 :
1397 2 : context_object = cairo_context_object_get(getThis());
1398 1 : if (!context_object) {
1399 0 : RETURN_THROWS();
1400 : }
1401 :
1402 1 : cairo_stroke(context_object->context);
1403 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1404 0 : RETURN_THROWS();
1405 : }
1406 : }
1407 : /* }}} */
1408 :
1409 : /* {{{ proto void \Cairo\Context::strokePreserve()
1410 : A drawing operator that strokes the current path according to the current line width, line join, line cap, and dash settings.
1411 : Unlike cairo_stroke(), cairo_stroke_preserve() preserves the path within the cairo context. */
1412 2 : PHP_METHOD(Cairo_Context, strokePreserve)
1413 : {
1414 : cairo_context_object *context_object;
1415 :
1416 2 : ZEND_PARSE_PARAMETERS_NONE();
1417 :
1418 2 : context_object = cairo_context_object_get(getThis());
1419 1 : if (!context_object) {
1420 0 : RETURN_THROWS();
1421 : }
1422 :
1423 1 : cairo_stroke_preserve(context_object->context);
1424 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1425 0 : RETURN_THROWS();
1426 : }
1427 : }
1428 : /* }}} */
1429 :
1430 : /* {{{ proto array \Cairo\Context::strokeExtents()
1431 : Computes a bounding box in user coordinates covering the area that would be affected, (the "inked" area), by a cairo_stroke()
1432 : operation operation given the current path and stroke parameters. */
1433 2 : PHP_METHOD(Cairo_Context, getStrokeExtents)
1434 : {
1435 : cairo_context_object *context_object;
1436 : double x1, y1, x2, y2;
1437 :
1438 2 : ZEND_PARSE_PARAMETERS_NONE();
1439 :
1440 2 : context_object = cairo_context_object_get(getThis());
1441 1 : if (!context_object) {
1442 0 : RETURN_THROWS();
1443 : }
1444 :
1445 1 : cairo_stroke_extents(context_object->context, &x1, &y1, &x2, &y2);
1446 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1447 0 : RETURN_THROWS();
1448 : }
1449 :
1450 1 : array_init(return_value);
1451 1 : add_assoc_double(return_value, "x1", x1);
1452 1 : add_assoc_double(return_value, "y1", y1);
1453 1 : add_assoc_double(return_value, "x2", x2);
1454 1 : add_assoc_double(return_value, "y2", y2);}
1455 : /* }}} */
1456 :
1457 : /* {{{ proto bool \Cairo\Context::inStroke(int x, int y)
1458 : Tests whether the given point is inside the area that would be affected by a cairo_stroke()
1459 : operation given the current path and stroking parameters. */
1460 6 : PHP_METHOD(Cairo_Context, inStroke)
1461 : {
1462 : cairo_context_object *context_object;
1463 6 : double x = 0.0, y = 0.0;
1464 :
1465 6 : ZEND_PARSE_PARAMETERS_START(2, 2)
1466 6 : Z_PARAM_DOUBLE(x)
1467 4 : Z_PARAM_DOUBLE(y)
1468 6 : ZEND_PARSE_PARAMETERS_END();
1469 :
1470 2 : context_object = cairo_context_object_get(getThis());
1471 1 : if (!context_object) {
1472 0 : RETURN_THROWS();
1473 : }
1474 :
1475 1 : RETURN_BOOL(cairo_in_stroke(context_object->context, x, y));
1476 : }
1477 : /* }}} */
1478 :
1479 : /* {{{ proto void \Cairo\Context::copyPage()
1480 : Emits the current page for backends that support multiple pages, but doesn't clear it,
1481 : so, the contents of the current page will be retained for the next page too.*/
1482 2 : PHP_METHOD(Cairo_Context, copyPage)
1483 : {
1484 : cairo_context_object *context_object;
1485 :
1486 2 : ZEND_PARSE_PARAMETERS_NONE();
1487 :
1488 2 : context_object = cairo_context_object_get(getThis());
1489 1 : if (!context_object) {
1490 0 : RETURN_THROWS();
1491 : }
1492 :
1493 1 : cairo_copy_page(context_object->context);
1494 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1495 0 : RETURN_THROWS();
1496 : }
1497 : }
1498 : /* }}} */
1499 :
1500 : /* {{{ proto void \Cairo\Context::showPage()
1501 : Emits and clears the current page for backends that support multiple pages.
1502 : Use cairo_copy_page() if you don't want to clear the page. */
1503 2 : PHP_METHOD(Cairo_Context, showPage)
1504 : {
1505 : cairo_context_object *context_object;
1506 :
1507 2 : ZEND_PARSE_PARAMETERS_NONE();
1508 :
1509 2 : context_object = cairo_context_object_get(getThis());
1510 1 : if (!context_object) {
1511 0 : RETURN_THROWS();
1512 : }
1513 :
1514 1 : cairo_show_page(context_object->context);
1515 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1516 0 : RETURN_THROWS();
1517 : }
1518 : }
1519 : /* }}} */
1520 :
1521 : #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 18, 0)
1522 : /* {{{ proto void \Cairo\Context::setHairline(bool hairline)
1523 : Sets whether to use hairline mode for stroking.
1524 : Hairline mode is disabled by default. */
1525 4 : PHP_METHOD(Cairo_Context, setHairline)
1526 : {
1527 : cairo_context_object *context_object;
1528 4 : bool hairline = false;
1529 :
1530 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
1531 4 : Z_PARAM_BOOL(hairline)
1532 4 : ZEND_PARSE_PARAMETERS_END();
1533 :
1534 2 : context_object = cairo_context_object_get(getThis());
1535 1 : if (!context_object) {
1536 0 : RETURN_THROWS();
1537 : }
1538 :
1539 1 : cairo_set_hairline(context_object->context, hairline);
1540 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1541 0 : RETURN_THROWS();
1542 : }
1543 : }
1544 : /* }}} */
1545 :
1546 : /* {{{ proto bool \Cairo\Context::getHairline()
1547 : Gets whether hairline mode is enabled for stroking. */
1548 3 : PHP_METHOD(Cairo_Context, getHairline)
1549 : {
1550 : cairo_context_object *context_object;
1551 :
1552 3 : ZEND_PARSE_PARAMETERS_NONE();
1553 :
1554 4 : context_object = cairo_context_object_get(getThis());
1555 2 : if (!context_object) {
1556 0 : RETURN_THROWS();
1557 : }
1558 :
1559 2 : RETURN_BOOL(cairo_get_hairline(context_object->context));
1560 : }
1561 : /* }}} */
1562 : #endif
1563 :
1564 : /*
1565 : * Transformations
1566 : */
1567 :
1568 : /* {{{ proto void \Cairo\Context::translate(float x, float y)
1569 : Modifies the current transformation matrix by translating the user-space origin by (x, y) */
1570 6 : PHP_METHOD(Cairo_Context, translate)
1571 : {
1572 6 : double x = 0.0, y = 0.0;
1573 : cairo_context_object *context_object;
1574 :
1575 6 : ZEND_PARSE_PARAMETERS_START(2, 2)
1576 6 : Z_PARAM_DOUBLE(x)
1577 4 : Z_PARAM_DOUBLE(y)
1578 6 : ZEND_PARSE_PARAMETERS_END();
1579 :
1580 2 : context_object = cairo_context_object_get(getThis());
1581 1 : if (!context_object) {
1582 0 : RETURN_THROWS();
1583 : }
1584 :
1585 1 : cairo_translate(context_object->context, x, y);
1586 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1587 0 : RETURN_THROWS();
1588 : }
1589 : }
1590 : /* }}} */
1591 :
1592 : /* {{{ proto void \Cairo\Context::scale(float x, float y)
1593 : Modifies the current transformation matrix by scaling the X and Y user-space axes by x and y respectively */
1594 6 : PHP_METHOD(Cairo_Context, scale)
1595 : {
1596 6 : double x = 0.0, y = 0.0;
1597 : cairo_context_object *context_object;
1598 :
1599 6 : ZEND_PARSE_PARAMETERS_START(2, 2)
1600 6 : Z_PARAM_DOUBLE(x)
1601 4 : Z_PARAM_DOUBLE(y)
1602 6 : ZEND_PARSE_PARAMETERS_END();
1603 :
1604 2 : context_object = cairo_context_object_get(getThis());
1605 1 : if (!context_object) {
1606 0 : RETURN_THROWS();
1607 : }
1608 :
1609 1 : cairo_scale(context_object->context, x, y);
1610 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1611 0 : RETURN_THROWS();
1612 : }
1613 : }
1614 : /* }}} */
1615 :
1616 : /* {{{ proto void \Cairo\Context::rotate(float angle)
1617 : Modifies the current transformation matrix by rotating the user-space axes by angle radians */
1618 4 : PHP_METHOD(Cairo_Context, rotate)
1619 : {
1620 4 : double angle = 0.0;
1621 : cairo_context_object *context_object;
1622 :
1623 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
1624 4 : Z_PARAM_DOUBLE(angle)
1625 4 : ZEND_PARSE_PARAMETERS_END();
1626 :
1627 2 : context_object = cairo_context_object_get(getThis());
1628 1 : if (!context_object) {
1629 0 : RETURN_THROWS();
1630 : }
1631 1 : cairo_rotate(context_object->context, angle);
1632 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1633 0 : RETURN_THROWS();
1634 : }
1635 : }
1636 : /* }}} */
1637 :
1638 : /* {{{ proto void \Cairo\Context::transform(\Cairo\Matrix matrix)
1639 : Modifies the current transformation matrix by applying a matrix as an additional transformation */
1640 4 : PHP_METHOD(Cairo_Context, transform)
1641 : {
1642 4 : zval *matrix_zval = NULL;
1643 : cairo_context_object *context_object;
1644 : cairo_matrix_object *matrix_object;
1645 :
1646 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
1647 4 : Z_PARAM_OBJECT_OF_CLASS(matrix_zval, ce_cairo_matrix)
1648 4 : ZEND_PARSE_PARAMETERS_END();
1649 :
1650 2 : context_object = cairo_context_object_get(getThis());
1651 1 : if (!context_object) {
1652 0 : RETURN_THROWS();
1653 : }
1654 :
1655 1 : matrix_object = Z_CAIRO_MATRIX_P(matrix_zval);
1656 1 : cairo_transform(context_object->context, matrix_object->matrix);
1657 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1658 0 : RETURN_THROWS();
1659 : }
1660 : }
1661 : /* }}} */
1662 :
1663 : /* {{{ proto void \Cairo\Context::setMatrix(\Cairo\Matrix matrix)
1664 : Sets the current transformation matrix */
1665 6 : PHP_METHOD(Cairo_Context, setMatrix)
1666 : {
1667 6 : zval *matrix_zval = NULL;
1668 : cairo_context_object *context_object;
1669 : cairo_matrix_object *matrix_object;
1670 :
1671 6 : ZEND_PARSE_PARAMETERS_START(1, 1)
1672 8 : Z_PARAM_OBJECT_OF_CLASS(matrix_zval, ce_cairo_matrix)
1673 6 : ZEND_PARSE_PARAMETERS_END();
1674 :
1675 6 : context_object = cairo_context_object_get(getThis());
1676 3 : if (!context_object) {
1677 0 : RETURN_THROWS();
1678 : }
1679 :
1680 3 : matrix_object = Z_CAIRO_MATRIX_P(matrix_zval);
1681 3 : cairo_set_matrix(context_object->context, matrix_object->matrix);
1682 3 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1683 0 : RETURN_THROWS();
1684 : }
1685 :
1686 : /* If there's already a matrix, then we deref and remove it */
1687 10 : CAIRO_UNREF_AND_UNDEF(context_object->matrix)
1688 :
1689 : /* we need to be able to get this zval out later, so ref and store */
1690 3 : ZVAL_COPY(&context_object->matrix, matrix_zval);
1691 : }
1692 : /* }}} */
1693 :
1694 : /* {{{ proto \Cairo\Matrix matrix \Cairo\Context::getMatrix()
1695 : Returns the current transformation matrix */
1696 5 : PHP_METHOD(Cairo_Context, getMatrix)
1697 : {
1698 : cairo_context_object *context_object;
1699 : cairo_matrix_object *matrix_object;
1700 :
1701 5 : ZEND_PARSE_PARAMETERS_NONE();
1702 :
1703 8 : context_object = cairo_context_object_get(getThis());
1704 4 : if (!context_object) {
1705 0 : RETURN_THROWS();
1706 : }
1707 :
1708 : /* If we have a matrix object stored, grab that zval to use */
1709 18 : CAIRO_RETURN_IF_REF(context_object->matrix);
1710 :
1711 : /* Otherwise we spawn a new object */
1712 1 : object_init_ex(return_value, php_cairo_get_matrix_ce());
1713 1 : matrix_object = Z_CAIRO_MATRIX_P(return_value);
1714 1 : cairo_get_matrix(context_object->context, matrix_object->matrix);
1715 : }
1716 : /* }}} */
1717 :
1718 : /* {{{ proto void \Cairo\Context::identityMatrix()
1719 : Resets the current transformation matrix by setting it equal to the identity matrix */
1720 2 : PHP_METHOD(Cairo_Context, identityMatrix)
1721 : {
1722 : cairo_context_object *context_object;
1723 :
1724 2 : ZEND_PARSE_PARAMETERS_NONE();
1725 :
1726 2 : context_object = cairo_context_object_get(getThis());
1727 1 : if (!context_object) {
1728 0 : RETURN_THROWS();
1729 : }
1730 :
1731 1 : cairo_identity_matrix(context_object->context);
1732 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1733 0 : RETURN_THROWS();
1734 : }
1735 : }
1736 : /* }}} */
1737 :
1738 : /* {{{ proto array cairo_user_to_device(CairoContext object, int x, int y)
1739 : proto array \Cairo\Context::userToDevice(int x, int y)
1740 : Transform a coordinate from user space to device space by multiplying the given point by the current transformation matrix */
1741 6 : PHP_METHOD(Cairo_Context, userToDevice)
1742 : {
1743 6 : double x = 0.0, y = 0.0;
1744 : cairo_context_object *context_object;
1745 :
1746 6 : ZEND_PARSE_PARAMETERS_START(2, 2)
1747 6 : Z_PARAM_DOUBLE(x)
1748 4 : Z_PARAM_DOUBLE(y)
1749 6 : ZEND_PARSE_PARAMETERS_END();
1750 :
1751 2 : context_object = cairo_context_object_get(getThis());
1752 1 : if (!context_object) {
1753 0 : RETURN_THROWS();
1754 : }
1755 :
1756 1 : cairo_user_to_device(context_object->context, &x, &y);
1757 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1758 0 : RETURN_THROWS();
1759 : }
1760 :
1761 1 : array_init(return_value);
1762 1 : add_assoc_double(return_value, "x", x);
1763 1 : add_assoc_double(return_value, "y", y);
1764 : }
1765 : /* }}} */
1766 :
1767 : /* {{{ proto array \Cairo\Context::userToDeviceDistance(int x, int y)
1768 : Transform a coordinate from user space to device space by multiplying the
1769 : given point by the current transformation matrix except that the translation components
1770 : are ignored */
1771 6 : PHP_METHOD(Cairo_Context, userToDeviceDistance)
1772 : {
1773 6 : double x = 0.0, y = 0.0;
1774 : cairo_context_object *context_object;
1775 :
1776 6 : ZEND_PARSE_PARAMETERS_START(2, 2)
1777 6 : Z_PARAM_DOUBLE(x)
1778 4 : Z_PARAM_DOUBLE(y)
1779 6 : ZEND_PARSE_PARAMETERS_END();
1780 :
1781 2 : context_object = cairo_context_object_get(getThis());
1782 1 : if (!context_object) {
1783 0 : RETURN_THROWS();
1784 : }
1785 :
1786 1 : cairo_user_to_device_distance(context_object->context, &x, &y);
1787 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1788 0 : RETURN_THROWS();
1789 : }
1790 :
1791 1 : array_init(return_value);
1792 1 : add_assoc_double(return_value, "x", x);
1793 1 : add_assoc_double(return_value, "y", y);
1794 : }
1795 : /* }}} */
1796 :
1797 : /* {{{ proto array \Cairo\Context::deviceToUser(int x, int y)
1798 : Transform a coordinate from device space to user space by multiplying the given
1799 : point by the inverse of the current transformation matrix */
1800 6 : PHP_METHOD(Cairo_Context, deviceToUser)
1801 : {
1802 6 : double x = 0.0, y = 0.0;
1803 : cairo_context_object *context_object;
1804 :
1805 6 : ZEND_PARSE_PARAMETERS_START(2, 2)
1806 6 : Z_PARAM_DOUBLE(x)
1807 4 : Z_PARAM_DOUBLE(y)
1808 6 : ZEND_PARSE_PARAMETERS_END();
1809 :
1810 2 : context_object = cairo_context_object_get(getThis());
1811 1 : if (!context_object) {
1812 0 : RETURN_THROWS();
1813 : }
1814 :
1815 1 : cairo_device_to_user(context_object->context, &x, &y);
1816 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1817 0 : RETURN_THROWS();
1818 : }
1819 :
1820 1 : array_init(return_value);
1821 1 : add_assoc_double(return_value, "x", x);
1822 1 : add_assoc_double(return_value, "y", y);
1823 : }
1824 : /* }}} */
1825 :
1826 : /* {{{ proto void \Cairo\Context::deviceToUserDistance(int x, int y)
1827 : Transform a distance vector from device space to user space. */
1828 6 : PHP_METHOD(Cairo_Context, deviceToUserDistance)
1829 : {
1830 6 : double x = 0.0, y = 0.0;
1831 : cairo_context_object *context_object;
1832 :
1833 6 : ZEND_PARSE_PARAMETERS_START(2, 2)
1834 6 : Z_PARAM_DOUBLE(x)
1835 4 : Z_PARAM_DOUBLE(y)
1836 6 : ZEND_PARSE_PARAMETERS_END();
1837 :
1838 2 : context_object = cairo_context_object_get(getThis());
1839 1 : if (!context_object) {
1840 0 : RETURN_THROWS();
1841 : }
1842 :
1843 1 : cairo_device_to_user_distance(context_object->context, &x, &y);
1844 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1845 0 : RETURN_THROWS();
1846 : }
1847 :
1848 1 : array_init(return_value);
1849 1 : add_assoc_double(return_value, "x", x);
1850 1 : add_assoc_double(return_value, "y", y);
1851 : }
1852 : /* }}} */
1853 :
1854 : /*
1855 : * Paths
1856 : */
1857 :
1858 : /* {{{ proto CairoPath object \Cairo\Context::copyPath()
1859 : Creates a copy of the current path and returns it to the user as a CairoPath object */
1860 3 : PHP_METHOD(Cairo_Context, copyPath)
1861 : {
1862 : cairo_path_object *path_object;
1863 : cairo_context_object *context_object;
1864 :
1865 3 : ZEND_PARSE_PARAMETERS_NONE();
1866 :
1867 4 : context_object = cairo_context_object_get(getThis());
1868 2 : if (!context_object) {
1869 0 : RETURN_THROWS();
1870 : }
1871 :
1872 2 : object_init_ex(return_value, php_cairo_get_path_ce());
1873 2 : path_object = Z_CAIRO_PATH_P(return_value);
1874 2 : path_object->path = cairo_copy_path(context_object->context);
1875 2 : if (php_cairo_throw_exception(path_object->path->status)) {
1876 0 : RETURN_THROWS();
1877 : }
1878 : }
1879 : /* }}} */
1880 :
1881 : /* {{{ proto CairoPath object \Cairo\Context::copyPathFlat()
1882 : Creates a copy of the current path and returns it to the user as a CairoPath object
1883 : any curves in the path will be approximated with piecewise-linear approximations*/
1884 2 : PHP_METHOD(Cairo_Context, copyPathFlat)
1885 : {
1886 : cairo_path_object *path_object;
1887 : cairo_context_object *context_object;
1888 :
1889 2 : ZEND_PARSE_PARAMETERS_NONE();
1890 :
1891 2 : context_object = cairo_context_object_get(getThis());
1892 1 : if (!context_object) {
1893 0 : RETURN_THROWS();
1894 : }
1895 :
1896 1 : object_init_ex(return_value, php_cairo_get_path_ce());
1897 1 : path_object = Z_CAIRO_PATH_P(return_value);
1898 1 : path_object->path = cairo_copy_path_flat(context_object->context);
1899 1 : if (php_cairo_throw_exception(path_object->path->status)) {
1900 0 : RETURN_THROWS();
1901 : }
1902 : }
1903 : /* }}} */
1904 :
1905 : /* {{{ proto void \Cairo\Context::appendPath(CairoPath object)
1906 : Append the path onto the current path. */
1907 4 : PHP_METHOD(Cairo_Context, appendPath)
1908 : {
1909 4 : zval *path_zval = NULL;
1910 : const cairo_path_t *path;
1911 : cairo_path_object *path_object;
1912 : cairo_context_object *context_object;
1913 :
1914 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
1915 4 : Z_PARAM_OBJECT_OF_CLASS(path_zval, ce_cairo_path)
1916 4 : ZEND_PARSE_PARAMETERS_END();
1917 :
1918 2 : context_object = cairo_context_object_get(getThis());
1919 1 : if (!context_object) {
1920 0 : RETURN_THROWS();
1921 : }
1922 :
1923 1 : path_object = Z_CAIRO_PATH_P(path_zval);
1924 1 : path = path_object->path;
1925 1 : cairo_append_path(context_object->context, path);
1926 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1927 0 : RETURN_THROWS();
1928 : }
1929 : }
1930 : /* }}} */
1931 :
1932 : /* {{{ proto bool \Cairo\Context::hasCurrentPoint()
1933 : Returns whether a current point is defined on the current path. */
1934 2 : PHP_METHOD(Cairo_Context, hasCurrentPoint)
1935 : {
1936 : cairo_context_object *context_object;
1937 :
1938 2 : ZEND_PARSE_PARAMETERS_NONE();
1939 :
1940 2 : context_object = cairo_context_object_get(getThis());
1941 1 : if (!context_object) {
1942 0 : RETURN_THROWS();
1943 : }
1944 :
1945 1 : RETURN_BOOL(cairo_has_current_point(context_object->context));
1946 : }
1947 : /* }}} */
1948 :
1949 : /* {{{ proto array \Cairo\Context::getCurrentPoint()
1950 : Gets the current point of the current path, which is conceptually the final point reached by the path so far. */
1951 8 : PHP_METHOD(Cairo_Context, getCurrentPoint)
1952 : {
1953 : double x, y;
1954 : cairo_context_object *context_object;
1955 :
1956 8 : ZEND_PARSE_PARAMETERS_NONE();
1957 :
1958 14 : context_object = cairo_context_object_get(getThis());
1959 7 : if (!context_object) {
1960 0 : RETURN_THROWS();
1961 : }
1962 :
1963 7 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1964 0 : RETURN_THROWS();
1965 : }
1966 :
1967 7 : cairo_get_current_point(context_object->context, &x, &y);
1968 7 : array_init(return_value);
1969 7 : add_assoc_double(return_value, "x", x);
1970 7 : add_assoc_double(return_value, "y", y);
1971 : }
1972 : /* }}} */
1973 :
1974 : /* {{{ proto void \Cairo\Context::newPath()
1975 : Clears the current path. After this call there will be no path and no current point. */
1976 2 : PHP_METHOD(Cairo_Context, newPath)
1977 : {
1978 : cairo_context_object *context_object;
1979 :
1980 2 : ZEND_PARSE_PARAMETERS_NONE();
1981 :
1982 2 : context_object = cairo_context_object_get(getThis());
1983 1 : if (!context_object) {
1984 0 : RETURN_THROWS();
1985 : }
1986 :
1987 1 : cairo_new_path(context_object->context);
1988 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
1989 0 : RETURN_THROWS();
1990 : }
1991 : }
1992 : /* }}} */
1993 :
1994 : /* {{{ proto void \Cairo\Context::newSubPath()
1995 : Begin a new sub-path. Note that the existing path is not affected. After this call there will be no current point. */
1996 2 : PHP_METHOD(Cairo_Context, newSubPath)
1997 : {
1998 : cairo_context_object *context_object;
1999 :
2000 2 : ZEND_PARSE_PARAMETERS_NONE();
2001 :
2002 2 : context_object = cairo_context_object_get(getThis());
2003 1 : if (!context_object) {
2004 0 : RETURN_THROWS();
2005 : }
2006 :
2007 1 : cairo_new_sub_path(context_object->context);
2008 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2009 0 : RETURN_THROWS();
2010 : }
2011 : }
2012 : /* }}} */
2013 :
2014 : /* {{{ proto void \Cairo\Context::closePath()
2015 : Adds a line segment to the path from the current point to the beginning of the current sub-path,
2016 : and closes this sub-path. After this call the current point will be at the joined endpoint of the sub-path. */
2017 2 : PHP_METHOD(Cairo_Context, closePath)
2018 : {
2019 : cairo_context_object *context_object;
2020 :
2021 2 : ZEND_PARSE_PARAMETERS_NONE();
2022 :
2023 2 : context_object = cairo_context_object_get(getThis());
2024 1 : if (!context_object) {
2025 0 : RETURN_THROWS();
2026 : }
2027 :
2028 1 : cairo_close_path(context_object->context);
2029 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2030 0 : RETURN_THROWS();
2031 : }
2032 : }
2033 : /* }}} */
2034 :
2035 : /* {{{ proto void \Cairo\Context::arc(float x, float y, float radius, float angle1, float angle2)
2036 : Adds a circular arc of the given radius to the current path.
2037 : The arc is centered at (x, y), begins at angle1 and proceeds in the direction of increasing angles to end at angle2*/
2038 12 : PHP_METHOD(Cairo_Context, arc)
2039 : {
2040 12 : double x = 0.0, y = 0.0, radius = 0.0, angle1 = 0.0, angle2 = 0.0;
2041 : cairo_context_object *context_object;
2042 :
2043 12 : ZEND_PARSE_PARAMETERS_START(5, 5)
2044 12 : Z_PARAM_DOUBLE(x)
2045 10 : Z_PARAM_DOUBLE(y)
2046 8 : Z_PARAM_DOUBLE(radius)
2047 6 : Z_PARAM_DOUBLE(angle1)
2048 4 : Z_PARAM_DOUBLE(angle2)
2049 12 : ZEND_PARSE_PARAMETERS_END();
2050 :
2051 2 : context_object = cairo_context_object_get(getThis());
2052 1 : if (!context_object) {
2053 0 : RETURN_THROWS();
2054 : }
2055 :
2056 1 : cairo_arc(context_object->context, x, y, radius, angle1, angle2);
2057 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2058 0 : RETURN_THROWS();
2059 : }
2060 : }
2061 : /* }}} */
2062 :
2063 : /* {{{ proto void \Cairo\Context::arcNegative(float x, float y, float radius, float angle1, float angle2)
2064 : Adds a circular arc of the given radius to the current path.
2065 : The arc is centered at (x, y), begins at angle1 and proceeds in the direction of decreasing angles to end at angle2.*/
2066 12 : PHP_METHOD(Cairo_Context, arcNegative)
2067 : {
2068 12 : double x = 0.0, y = 0.0, radius = 0.0, angle1 = 0.0, angle2 = 0.0;
2069 : cairo_context_object *context_object;
2070 :
2071 12 : ZEND_PARSE_PARAMETERS_START(5, 5)
2072 12 : Z_PARAM_DOUBLE(x)
2073 10 : Z_PARAM_DOUBLE(y)
2074 8 : Z_PARAM_DOUBLE(radius)
2075 6 : Z_PARAM_DOUBLE(angle1)
2076 4 : Z_PARAM_DOUBLE(angle2)
2077 12 : ZEND_PARSE_PARAMETERS_END();
2078 :
2079 2 : context_object = cairo_context_object_get(getThis());
2080 1 : if (!context_object) {
2081 0 : RETURN_THROWS();
2082 : }
2083 :
2084 1 : cairo_arc_negative(context_object->context, x, y, radius, angle1, angle2);
2085 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2086 0 : RETURN_THROWS();
2087 : }
2088 : }
2089 : /* }}} */
2090 :
2091 : /* {{{ proto void cairo_curve_to(CairoContext object, float x1, float y1, float x2, float y2, float x3, float y3)
2092 : proto void \Cairo\Context::curveTo(float x1, float y1, float x2, float y2, float x3, float y3)
2093 : Adds a cubic Bézier spline to the path from the current point to position (x3, y3) in user-space coordinates, using (x1, y1) and (x2, y2) as the control points.
2094 : After this call the current point will be (x3, y3). */
2095 15 : PHP_METHOD(Cairo_Context, curveTo)
2096 : {
2097 15 : double x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0, x3 = 0.0, y3 = 0.0;
2098 : cairo_context_object *context_object;
2099 :
2100 15 : ZEND_PARSE_PARAMETERS_START(6, 6)
2101 16 : Z_PARAM_DOUBLE(x1)
2102 14 : Z_PARAM_DOUBLE(y1)
2103 12 : Z_PARAM_DOUBLE(x2)
2104 10 : Z_PARAM_DOUBLE(y2)
2105 8 : Z_PARAM_DOUBLE(x3)
2106 6 : Z_PARAM_DOUBLE(y3)
2107 15 : ZEND_PARSE_PARAMETERS_END();
2108 :
2109 4 : context_object = cairo_context_object_get(getThis());
2110 2 : if (!context_object) {
2111 0 : RETURN_THROWS();
2112 : }
2113 :
2114 2 : cairo_curve_to(context_object->context, x1, y1, x2, y2, x3, y3);
2115 2 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2116 0 : RETURN_THROWS();
2117 : }
2118 : }
2119 : /* }}} */
2120 :
2121 : /* {{{ proto void cairo_line_to(CairoContext object, float x, float y)
2122 : proto void \Cairo\Context::lineTo(float x, float y)
2123 : Adds a line to the path from the current point to position (x, y) in user-space coordinates. After this call the current point will be (x, y). */
2124 9 : PHP_METHOD(Cairo_Context, lineTo)
2125 : {
2126 9 : double x = 0.0, y = 0.0;
2127 : cairo_context_object *context_object;
2128 :
2129 9 : ZEND_PARSE_PARAMETERS_START(2, 2)
2130 12 : Z_PARAM_DOUBLE(x)
2131 10 : Z_PARAM_DOUBLE(y)
2132 9 : ZEND_PARSE_PARAMETERS_END();
2133 :
2134 8 : context_object = cairo_context_object_get(getThis());
2135 4 : if (!context_object) {
2136 0 : RETURN_THROWS();
2137 : }
2138 4 : cairo_line_to(context_object->context, x, y);
2139 4 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2140 0 : RETURN_THROWS();
2141 : }
2142 : }
2143 : /* }}} */
2144 :
2145 : /* {{{ proto void cairo_move_to(CairoContext object, float x, float y)
2146 : proto void \Cairo\Context::moveTo(float x, float y)
2147 : Begin a new sub-path. After this call the current point will be (x, y) */
2148 7 : PHP_METHOD(Cairo_Context, moveTo)
2149 : {
2150 7 : double x = 0.0, y = 0.0;
2151 : cairo_context_object *context_object;
2152 :
2153 7 : ZEND_PARSE_PARAMETERS_START(2, 2)
2154 8 : Z_PARAM_DOUBLE(x)
2155 6 : Z_PARAM_DOUBLE(y)
2156 7 : ZEND_PARSE_PARAMETERS_END();
2157 :
2158 4 : context_object = cairo_context_object_get(getThis());
2159 2 : if (!context_object) {
2160 0 : RETURN_THROWS();
2161 : }
2162 :
2163 2 : cairo_move_to(context_object->context, x, y);
2164 2 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2165 0 : RETURN_THROWS();
2166 : }
2167 : }
2168 : /* }}} */
2169 :
2170 : /* {{{ proto void \Cairo\Context::rectangle(float x, float y, float width, float height)
2171 : Adds a closed sub-path rectangle of the given size to the current path at position (x, y) in user-space coordinates. */
2172 11 : PHP_METHOD(Cairo_Context, rectangle)
2173 : {
2174 11 : double x = 0.0, y = 0.0, width = 0.0, height = 0.0;
2175 : cairo_context_object *context_object;
2176 :
2177 11 : ZEND_PARSE_PARAMETERS_START(4, 4)
2178 12 : Z_PARAM_DOUBLE(x)
2179 10 : Z_PARAM_DOUBLE(y)
2180 8 : Z_PARAM_DOUBLE(width)
2181 6 : Z_PARAM_DOUBLE(height)
2182 11 : ZEND_PARSE_PARAMETERS_END();
2183 :
2184 4 : context_object = cairo_context_object_get(getThis());
2185 2 : if (!context_object) {
2186 0 : RETURN_THROWS();
2187 : }
2188 :
2189 2 : cairo_rectangle(context_object->context, x, y, width, height);
2190 2 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2191 0 : RETURN_THROWS();
2192 : }
2193 : }
2194 : /* }}} */
2195 :
2196 : /* {{{ proto void \Cairo\Context::glyphPath(array glyphs)
2197 : Adds closed paths for the glyphs to the current path. */
2198 5 : PHP_METHOD(Cairo_Context, glyphPath)
2199 : {
2200 : cairo_context_object *context_object;
2201 : cairo_glyph_t *glyphs_array;
2202 5 : int num_glyphs = 0;
2203 5 : zval *php_glyphs = NULL, *pzval;
2204 5 : HashTable *glyphs_hash = NULL;
2205 5 : int i = 0;
2206 :
2207 5 : ZEND_PARSE_PARAMETERS_START(1, 1)
2208 6 : Z_PARAM_ARRAY(php_glyphs)
2209 6 : ZEND_PARSE_PARAMETERS_END();
2210 :
2211 4 : context_object = cairo_context_object_get(getThis());
2212 2 : if (!context_object) {
2213 0 : RETURN_THROWS();
2214 : }
2215 :
2216 : /* Grab the zend hash */
2217 2 : glyphs_hash = Z_ARRVAL_P(php_glyphs);
2218 2 : num_glyphs = zend_hash_num_elements(glyphs_hash);
2219 2 : glyphs_array = ecalloc(num_glyphs, sizeof(cairo_glyph_t));
2220 :
2221 : /* iterate over the array, each value inside MUST be an instance of CairoGlyph */
2222 17 : ZEND_HASH_FOREACH_VAL(glyphs_hash, pzval) {
2223 8 : if (Z_TYPE_P(pzval) != IS_OBJECT || Z_OBJCE_P(pzval) != ce_cairo_glyph) {
2224 1 : zend_throw_exception(zend_ce_type_error, "Cairo\\Context::glyphPath(): Argument #1 ($glyphs) must be an array of Cairo\\Glyph objects.", 0);
2225 1 : efree(glyphs_array);
2226 1 : RETURN_THROWS();
2227 : }
2228 7 : glyphs_array[i++] = *(cairo_glyph_object_get_glyph(pzval));
2229 : }
2230 : ZEND_HASH_FOREACH_END();
2231 :
2232 1 : cairo_glyph_path(context_object->context, glyphs_array, num_glyphs);
2233 1 : efree(glyphs_array);
2234 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2235 0 : RETURN_THROWS();
2236 : }
2237 : }
2238 : /* }}} */
2239 :
2240 : /* {{{ proto void \Cairo\Context::textPath(string text)
2241 : Adds closed paths for text to the current path
2242 : NOTE: text must be UTF-8 charset or results will be unexpected */
2243 4 : PHP_METHOD(Cairo_Context, textPath)
2244 : {
2245 : char *text;
2246 : size_t text_len;
2247 : cairo_context_object *context_object;
2248 :
2249 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
2250 4 : Z_PARAM_STRING(text, text_len)
2251 4 : ZEND_PARSE_PARAMETERS_END();
2252 :
2253 2 : context_object = cairo_context_object_get(getThis());
2254 1 : if (!context_object) {
2255 0 : RETURN_THROWS();
2256 : }
2257 :
2258 1 : cairo_text_path(context_object->context, (const char *)text);
2259 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2260 0 : RETURN_THROWS();
2261 : }
2262 : }
2263 : /* }}} */
2264 :
2265 : /* {{{ proto void \Cairo\Context::relCurveTo(float x1, float y1, float x2, float y2, float x3, float y3)
2266 : Adds a cubic Bézier spline to the path from the current point to a point offset from the current point by (x3, y3),
2267 : using points offset by (x1, y1) and (x2, y2) as the control points. */
2268 14 : PHP_METHOD(Cairo_Context, relCurveTo)
2269 : {
2270 14 : double x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0, x3 = 0.0, y3 = 0.0;
2271 : cairo_context_object *context_object;
2272 :
2273 14 : ZEND_PARSE_PARAMETERS_START(6, 6)
2274 14 : Z_PARAM_DOUBLE(x1)
2275 12 : Z_PARAM_DOUBLE(y1)
2276 10 : Z_PARAM_DOUBLE(x2)
2277 8 : Z_PARAM_DOUBLE(y2)
2278 6 : Z_PARAM_DOUBLE(x3)
2279 4 : Z_PARAM_DOUBLE(y3)
2280 14 : ZEND_PARSE_PARAMETERS_END();
2281 :
2282 2 : context_object = cairo_context_object_get(getThis());
2283 1 : if (!context_object) {
2284 0 : RETURN_THROWS();
2285 : }
2286 :
2287 1 : cairo_rel_curve_to(context_object->context, x1, y1, x2, y2, x3, y3);
2288 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2289 0 : RETURN_THROWS();
2290 : }
2291 : }
2292 : /* }}} */
2293 :
2294 : /* {{{ proto void \Cairo\Context::relLineTo(float x, float y)
2295 : Adds a line to the path from the current point to a point that is offset from the current point by (x, y) in user space */
2296 6 : PHP_METHOD(Cairo_Context, relLineTo)
2297 : {
2298 6 : double x = 0.0, y = 0.0;
2299 : cairo_context_object *context_object;
2300 :
2301 6 : ZEND_PARSE_PARAMETERS_START(2, 2)
2302 6 : Z_PARAM_DOUBLE(x)
2303 4 : Z_PARAM_DOUBLE(y)
2304 6 : ZEND_PARSE_PARAMETERS_END();
2305 :
2306 2 : context_object = cairo_context_object_get(getThis());
2307 1 : if (!context_object) {
2308 0 : RETURN_THROWS();
2309 : }
2310 :
2311 1 : cairo_rel_line_to(context_object->context, x, y);
2312 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2313 0 : RETURN_THROWS();
2314 : }
2315 : }
2316 : /* }}} */
2317 :
2318 : /* {{{ proto void \Cairo\Context::relMoveTo(float x, float y)
2319 : Begin a new sub-path. After this call the current point will offset by (x, y). */
2320 6 : PHP_METHOD(Cairo_Context, relMoveTo)
2321 : {
2322 6 : double x = 0.0, y = 0.0;
2323 : cairo_context_object *context_object;
2324 :
2325 6 : ZEND_PARSE_PARAMETERS_START(2, 2)
2326 6 : Z_PARAM_DOUBLE(x)
2327 4 : Z_PARAM_DOUBLE(y)
2328 6 : ZEND_PARSE_PARAMETERS_END();
2329 :
2330 2 : context_object = cairo_context_object_get(getThis());
2331 1 : if (!context_object) {
2332 0 : RETURN_THROWS();
2333 : }
2334 :
2335 1 : cairo_rel_move_to(context_object->context, x, y);
2336 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2337 0 : RETURN_THROWS();
2338 : }
2339 : }
2340 : /* }}} */
2341 :
2342 : /* {{{ proto array \Cairo\Context::getPathExtents()
2343 : previous name was pathExtents()
2344 : Computes a bounding box in user-space coordinates covering the points on the current path */
2345 3 : PHP_METHOD(Cairo_Context, getPathExtents)
2346 : {
2347 : double x1, y1, x2, y2;
2348 : cairo_context_object *context_object;
2349 :
2350 3 : ZEND_PARSE_PARAMETERS_NONE();
2351 :
2352 4 : context_object = cairo_context_object_get(getThis());
2353 2 : if (!context_object) {
2354 0 : RETURN_THROWS();
2355 : }
2356 :
2357 2 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2358 0 : RETURN_THROWS();
2359 : }
2360 :
2361 2 : cairo_path_extents(context_object->context, &x1, &y1, &x2, &y2);
2362 2 : array_init(return_value);
2363 2 : add_assoc_double(return_value, "x1", x1);
2364 2 : add_assoc_double(return_value, "y1", y1);
2365 2 : add_assoc_double(return_value, "x2", x2);
2366 2 : add_assoc_double(return_value, "y2", y2);
2367 : }
2368 : /* }}} */
2369 :
2370 : /*
2371 : * Text items
2372 : */
2373 :
2374 : /* {{{ proto void \Cairo\Context::selectFontFace(string family, CairoFontSlant slant, CairoFontWeight weight)
2375 : Selects a family and style of font from a simplified description as a family name, slant and weight. */
2376 7 : PHP_METHOD(Cairo_Context, selectFontFace)
2377 : {
2378 7 : zval *slant = NULL;
2379 7 : zval *weight = NULL;
2380 : size_t family_len;
2381 : char *family, *cairo_family;
2382 : cairo_context_object *context_object;
2383 :
2384 7 : ZEND_PARSE_PARAMETERS_START(1, 3)
2385 10 : Z_PARAM_STRING(family, family_len)
2386 4 : Z_PARAM_OPTIONAL
2387 7 : Z_PARAM_OBJECT_OF_CLASS(slant, ce_cairo_fontslant)
2388 4 : Z_PARAM_OBJECT_OF_CLASS(weight, ce_cairo_fontweight)
2389 7 : ZEND_PARSE_PARAMETERS_END();
2390 :
2391 4 : context_object = cairo_context_object_get(getThis());
2392 2 : if (!context_object) {
2393 0 : RETURN_THROWS();
2394 : }
2395 :
2396 2 : cairo_family = estrdup(family);
2397 3 : cairo_select_font_face(
2398 : context_object->context,
2399 : family,
2400 : slant
2401 3 : ? Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(slant)))
2402 : : CAIRO_FONT_SLANT_NORMAL,
2403 : weight
2404 3 : ? Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(weight)))
2405 : : CAIRO_FONT_WEIGHT_NORMAL
2406 : );
2407 2 : efree(cairo_family);
2408 : }
2409 : /* }}} */
2410 :
2411 : /* {{{ proto void \Cairo\Context::setFontSize(double size)
2412 : Sets the current font matrix to a scale by a factor of size, replacing any font matrix previously
2413 : set with cairo_set_font_size() or cairo_set_font_matrix() */
2414 5 : PHP_METHOD(Cairo_Context, setFontSize)
2415 : {
2416 : double size;
2417 : cairo_context_object *context_object;
2418 :
2419 5 : ZEND_PARSE_PARAMETERS_START(1, 1)
2420 6 : Z_PARAM_DOUBLE(size)
2421 5 : ZEND_PARSE_PARAMETERS_END();
2422 :
2423 4 : context_object = cairo_context_object_get(getThis());
2424 2 : if (!context_object) {
2425 0 : RETURN_THROWS();
2426 : }
2427 :
2428 2 : cairo_set_font_size(context_object->context, size);
2429 :
2430 : /* If there's a font matrix stored, we've just reset it */
2431 7 : CAIRO_UNREF_AND_UNDEF(context_object->font_matrix)
2432 : }
2433 : /* }}} */
2434 :
2435 : /* {{{ proto void \Cairo\Context::setFontMatrix(\Cairo\Matrix matrix)
2436 : Sets the current transformation matrix for fonts */
2437 8 : PHP_METHOD(Cairo_Context, setFontMatrix)
2438 : {
2439 8 : zval *matrix_zval = NULL;
2440 : cairo_context_object *context_object;
2441 : cairo_matrix_object *matrix_object;
2442 :
2443 8 : ZEND_PARSE_PARAMETERS_START(1, 1)
2444 12 : Z_PARAM_OBJECT_OF_CLASS(matrix_zval, ce_cairo_matrix)
2445 8 : ZEND_PARSE_PARAMETERS_END();
2446 :
2447 10 : context_object = cairo_context_object_get(getThis());
2448 5 : if (!context_object) {
2449 0 : RETURN_THROWS();
2450 : }
2451 :
2452 5 : matrix_object = Z_CAIRO_MATRIX_P(matrix_zval);
2453 5 : cairo_set_font_matrix(context_object->context, matrix_object->matrix);
2454 5 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2455 0 : RETURN_THROWS();
2456 : }
2457 :
2458 : /* If there's already a matrix, then we deref and remove it */
2459 16 : CAIRO_UNREF_AND_UNDEF(context_object->font_matrix)
2460 :
2461 : /* we need to be able to get this zval out later, so ref and store */
2462 5 : ZVAL_COPY(&context_object->font_matrix, matrix_zval);
2463 : }
2464 : /* }}} */
2465 :
2466 : /* {{{ proto \Cairo\Matrix matrix \Cairo\Context::getFontMatrix()
2467 : Returns the current transformation matrix fot the font*/
2468 6 : PHP_METHOD(Cairo_Context, getFontMatrix)
2469 : {
2470 : cairo_context_object *context_object;
2471 : cairo_matrix_object *matrix_object;
2472 :
2473 6 : ZEND_PARSE_PARAMETERS_NONE();
2474 :
2475 10 : context_object = cairo_context_object_get(getThis());
2476 5 : if (!context_object) {
2477 0 : RETURN_THROWS();
2478 : }
2479 :
2480 : /* If we have a matrix object stored, grab that zval to use */
2481 23 : CAIRO_RETURN_IF_REF(context_object->font_matrix);
2482 :
2483 : /* Otherwise we spawn a new object */
2484 1 : object_init_ex(return_value, php_cairo_get_matrix_ce());
2485 1 : matrix_object = Z_CAIRO_MATRIX_P(return_value);
2486 1 : cairo_get_font_matrix(context_object->context, matrix_object->matrix);
2487 : }
2488 : /* }}} */
2489 :
2490 : /* {{{ proto void \Cairo\Context::setFontOptions(CairoFontOptions object)
2491 : Sets the font options to be used with the context */
2492 7 : PHP_METHOD(Cairo_Context, setFontOptions)
2493 : {
2494 7 : zval *font_options_zval = NULL;
2495 : cairo_context_object *context_object;
2496 : cairo_font_options_object *font_options_object;
2497 :
2498 7 : ZEND_PARSE_PARAMETERS_START(1, 1)
2499 10 : Z_PARAM_OBJECT_OF_CLASS(font_options_zval, ce_cairo_fontoptions)
2500 7 : ZEND_PARSE_PARAMETERS_END();
2501 :
2502 8 : context_object = cairo_context_object_get(getThis());
2503 4 : if (!context_object) {
2504 0 : RETURN_THROWS();
2505 : }
2506 :
2507 4 : font_options_object = Z_CAIRO_FONT_OPTIONS_P(font_options_zval);
2508 4 : cairo_set_font_options(context_object->context, font_options_object->font_options);
2509 4 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2510 0 : RETURN_THROWS();
2511 : }
2512 :
2513 : /* If there's already a font options, then we deref and remove it */
2514 13 : CAIRO_UNREF_AND_UNDEF(context_object->font_options)
2515 :
2516 : /* we need to be able to get this zval out later, so ref and store */
2517 4 : ZVAL_COPY(&context_object->font_options, font_options_zval);
2518 : }
2519 : /* }}} */
2520 :
2521 : /* {{{ proto CairoFontOptions object \Cairo\Context::getFontOptions()
2522 : Retrieves the font options selected by the context.
2523 : If no font options have been selected or set then the default options will be returned. */
2524 6 : PHP_METHOD(Cairo_Context, getFontOptions)
2525 : {
2526 : cairo_context_object *context_object;
2527 : cairo_font_options_object *font_options_object;
2528 6 : cairo_font_options_t *font_options = NULL;
2529 :
2530 6 : ZEND_PARSE_PARAMETERS_NONE();
2531 :
2532 10 : context_object = cairo_context_object_get(getThis());
2533 5 : if (!context_object) {
2534 0 : RETURN_THROWS();
2535 : }
2536 :
2537 : /* Grab the font options properly */
2538 5 : cairo_get_font_options(context_object->context, font_options);
2539 5 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2540 0 : RETURN_THROWS();
2541 : }
2542 :
2543 : /* If we have a font face object stored, grab that zval to use */
2544 23 : CAIRO_RETURN_IF_REF(context_object->font_options);
2545 :
2546 : /* Otherwise we spawn a new object */
2547 1 : object_init_ex(return_value, php_cairo_get_fontoptions_ce());
2548 1 : font_options_object = Z_CAIRO_FONT_OPTIONS_P(return_value);
2549 1 : font_options_object->font_options = font_options;
2550 : }
2551 : /* }}} */
2552 :
2553 : /* {{{ proto void \Cairo\Context::setFontFace(CairoFontFace object)
2554 : Sets the font face to be used with the context */
2555 7 : PHP_METHOD(Cairo_Context, setFontFace)
2556 : {
2557 7 : zval *font_face_zval = NULL;
2558 : cairo_context_object *context_object;
2559 : cairo_font_face_object *font_face_object;
2560 :
2561 7 : ZEND_PARSE_PARAMETERS_START(1, 1)
2562 10 : Z_PARAM_OBJECT_OF_CLASS(font_face_zval, ce_cairo_fontface)
2563 7 : ZEND_PARSE_PARAMETERS_END();
2564 :
2565 8 : context_object = cairo_context_object_get(getThis());
2566 4 : if (!context_object) {
2567 0 : RETURN_THROWS();
2568 : }
2569 :
2570 4 : font_face_object = Z_CAIRO_FONT_FACE_P(font_face_zval);
2571 4 : cairo_set_font_face(context_object->context, font_face_object->font_face);
2572 4 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2573 0 : RETURN_THROWS();
2574 : }
2575 :
2576 : /* If there's already a font face, then we deref and remove it */
2577 13 : CAIRO_UNREF_AND_UNDEF(context_object->font_face)
2578 :
2579 : /* we need to be able to get this zval out later, so ref and store */
2580 4 : ZVAL_COPY(&context_object->font_face, font_face_zval);
2581 : }
2582 : /* }}} */
2583 :
2584 : /* {{{ proto CairoFontFace object \Cairo\Context::getFontFace()
2585 : Retrieves the font face selected by the context. If no font face has been selected or set then the default face
2586 : will be returned. */
2587 7 : PHP_METHOD(Cairo_Context, getFontFace)
2588 : {
2589 : cairo_context_object *context_object;
2590 : cairo_font_face_object *font_face_object;
2591 :
2592 7 : ZEND_PARSE_PARAMETERS_NONE();
2593 :
2594 12 : context_object = cairo_context_object_get(getThis());
2595 6 : if (!context_object) {
2596 0 : RETURN_THROWS();
2597 : }
2598 :
2599 : /* If we have a font face object stored, grab that zval to use */
2600 26 : CAIRO_RETURN_IF_REF(context_object->font_face);
2601 :
2602 : /* Otherwise we spawn a new object */
2603 2 : object_init_ex(return_value, php_cairo_get_toyfontface_ce());
2604 2 : font_face_object = Z_CAIRO_FONT_FACE_P(return_value);
2605 2 : font_face_object->font_face = cairo_get_font_face(context_object->context);
2606 2 : cairo_font_face_reference(font_face_object->font_face);
2607 : }
2608 : /* }}} */
2609 :
2610 : /* {{{ proto void \Cairo\Context::setScaledFont(CairoScaledFont object)
2611 : Replaces the current font face, font matrix, and font options in the context with those of the scaled font. */
2612 6 : PHP_METHOD(Cairo_Context, setScaledFont)
2613 : {
2614 6 : zval *scaled_font_zval = NULL;
2615 : cairo_context_object *context_object;
2616 : cairo_scaled_font_object *scaled_font_object;
2617 :
2618 6 : ZEND_PARSE_PARAMETERS_START(1, 1)
2619 8 : Z_PARAM_OBJECT_OF_CLASS(scaled_font_zval, ce_cairo_scaled_font)
2620 6 : ZEND_PARSE_PARAMETERS_END();
2621 :
2622 6 : context_object = cairo_context_object_get(getThis());
2623 3 : if (!context_object) {
2624 0 : RETURN_THROWS();
2625 : }
2626 :
2627 3 : scaled_font_object = Z_CAIRO_SCALED_FONT_P(scaled_font_zval);
2628 3 : cairo_set_scaled_font(context_object->context, scaled_font_object->scaled_font);
2629 3 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2630 0 : RETURN_THROWS();
2631 : }
2632 :
2633 : /* If there's already a font face, font matrix, scaled font, and or font options stored, then we deref and remove them */
2634 11 : CAIRO_UNREF_AND_UNDEF(context_object->font_face)
2635 11 : CAIRO_UNREF_AND_UNDEF(context_object->font_matrix)
2636 11 : CAIRO_UNREF_AND_UNDEF(context_object->font_options)
2637 10 : CAIRO_UNREF_AND_UNDEF(context_object->scaled_font)
2638 :
2639 : /* if the scaled font has a font_face, matrix, or option zvals stored, move them to context as well and ref again */
2640 9 : CAIRO_ZVAL_COPY(context_object->font_face, scaled_font_object->font_face);
2641 9 : CAIRO_ZVAL_COPY(context_object->font_matrix, scaled_font_object->matrix);
2642 9 : CAIRO_ZVAL_COPY(context_object->font_options, scaled_font_object->font_options);
2643 :
2644 : /* we need to be able to get this zval out later, so ref and store */
2645 3 : ZVAL_COPY(&context_object->scaled_font, scaled_font_zval);
2646 : }
2647 : /* }}} */
2648 :
2649 : /* {{{ proto CairoScaledFont object \Cairo\Context::getScaledFont()
2650 : Retrieves the scaled font face selected by the context.
2651 : If no scaled font has been selected or set then the default face will be returned. */
2652 8 : PHP_METHOD(Cairo_Context, getScaledFont)
2653 : {
2654 : cairo_context_object *context_object;
2655 : cairo_scaled_font_object *scaled_font_object;
2656 :
2657 8 : ZEND_PARSE_PARAMETERS_NONE();
2658 :
2659 14 : context_object = cairo_context_object_get(getThis());
2660 7 : if (!context_object) {
2661 0 : RETURN_THROWS();
2662 : }
2663 :
2664 : /* If we have a scaled font object stored, grab that zval to use */
2665 25 : CAIRO_RETURN_IF_REF(context_object->scaled_font);
2666 :
2667 : /* Otherwise we spawn a new object */
2668 5 : object_init_ex(return_value, php_cairo_get_scaled_font_ce());
2669 5 : scaled_font_object = Z_CAIRO_SCALED_FONT_P(return_value);
2670 5 : scaled_font_object->scaled_font = cairo_get_scaled_font(context_object->context);
2671 5 : cairo_scaled_font_reference(scaled_font_object->scaled_font);
2672 : }
2673 : /* }}} */
2674 :
2675 : /* {{{ proto array \Cairo\Context::showText(string text)
2676 : A drawing operator that generates the shape from a string of UTF-8 characters,
2677 : rendered according to the current font_face, font_size (font_matrix), and font_options. */
2678 4 : PHP_METHOD(Cairo_Context, showText)
2679 : {
2680 : char *text, *cairo_text;
2681 : size_t text_len;
2682 : cairo_context_object *context_object;
2683 :
2684 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
2685 4 : Z_PARAM_STRING(text, text_len)
2686 4 : ZEND_PARSE_PARAMETERS_END();
2687 :
2688 2 : context_object = cairo_context_object_get(getThis());
2689 1 : if (!context_object) {
2690 0 : RETURN_THROWS();
2691 : }
2692 :
2693 1 : cairo_text = estrdup(text);
2694 1 : cairo_show_text(context_object->context, text);
2695 1 : efree(cairo_text);
2696 : }
2697 : /* }}} */
2698 :
2699 : /* {{{ proto void \Cairo\Context::showGlyphs(array glyphs)
2700 : A drawing operator that generates the shape from an array of glyphs,
2701 : rendered according to the current font face, font size (font matrix),
2702 : and font options. */
2703 5 : PHP_METHOD(Cairo_Context, showGlyphs)
2704 : {
2705 : cairo_context_object *context_object;
2706 : cairo_glyph_t *glyphs_array;
2707 5 : int num_glyphs = 0;
2708 5 : zval *php_glyphs = NULL, *pzval;
2709 5 : HashTable *glyphs_hash = NULL;
2710 5 : int i = 0;
2711 :
2712 5 : ZEND_PARSE_PARAMETERS_START(1, 1)
2713 6 : Z_PARAM_ARRAY(php_glyphs)
2714 6 : ZEND_PARSE_PARAMETERS_END();
2715 :
2716 4 : context_object = cairo_context_object_get(getThis());
2717 2 : if (!context_object) {
2718 0 : RETURN_THROWS();
2719 : }
2720 :
2721 : /* Grab the zend hash */
2722 2 : glyphs_hash = Z_ARRVAL_P(php_glyphs);
2723 2 : num_glyphs = zend_hash_num_elements(glyphs_hash);
2724 2 : glyphs_array = ecalloc(num_glyphs, sizeof(cairo_glyph_t));
2725 :
2726 : /* iterate over the array, each value inside MUST be an instance of CairoGlyph */
2727 15 : ZEND_HASH_FOREACH_VAL(glyphs_hash, pzval) {
2728 7 : if (Z_TYPE_P(pzval) != IS_OBJECT || Z_OBJCE_P(pzval) != ce_cairo_glyph) {
2729 1 : zend_throw_exception(zend_ce_type_error, "Cairo\\Context::showGlyphs(): Argument #1 ($glyphs) must be an array of Cairo\\Glyph objects.", 0);
2730 1 : efree(glyphs_array);
2731 1 : RETURN_THROWS();
2732 : }
2733 6 : glyphs_array[i++] = *(cairo_glyph_object_get_glyph(pzval));
2734 : }
2735 : ZEND_HASH_FOREACH_END();
2736 :
2737 1 : cairo_show_glyphs(context_object->context, glyphs_array, num_glyphs);
2738 1 : efree(glyphs_array);
2739 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2740 0 : RETURN_THROWS();
2741 : }
2742 : }
2743 : /* }}} */
2744 :
2745 : /* {{{ proto void \Cairo\Context::showTextGlyphs(string text, array glyphs, array clusters)
2746 : This operation has rendering effects similar to cairo_show_glyphs() but, if
2747 : the target surface supports it, uses the provided text and cluster mapping to
2748 : embed the text for the glyphs shown in the output. If the target does not
2749 : support the extended attributes, this function acts like the basic
2750 : cairo_show_glyphs() as if it had been passed glyphs and num_glyphs. */
2751 12 : PHP_METHOD(Cairo_Context, showTextGlyphs)
2752 : {
2753 : cairo_context_object *context_object;
2754 : char *utf8Str;
2755 12 : size_t utf8Str_len = 0;
2756 : cairo_glyph_t *glyphs_array;
2757 12 : int num_glyphs = 0;
2758 : cairo_text_cluster_t *clusters_array;
2759 12 : int num_clusters = 0;
2760 12 : zval *php_glyphs = NULL, *pzval;
2761 12 : zval *php_clusters = NULL;
2762 : long cluster_flags;
2763 12 : HashTable *glyphs_hash = NULL;
2764 12 : HashTable *clusters_hash = NULL;
2765 12 : int i = 0;
2766 :
2767 12 : ZEND_PARSE_PARAMETERS_START(4, 4)
2768 14 : Z_PARAM_STRING(utf8Str, utf8Str_len)
2769 12 : Z_PARAM_ARRAY(php_glyphs)
2770 10 : Z_PARAM_ARRAY(php_clusters)
2771 8 : Z_PARAM_LONG(cluster_flags)
2772 12 : ZEND_PARSE_PARAMETERS_END();
2773 :
2774 6 : context_object = cairo_context_object_get(getThis());
2775 3 : if (!context_object) {
2776 0 : RETURN_THROWS();
2777 : }
2778 :
2779 : /* Glyphs */
2780 3 : glyphs_hash = Z_ARRVAL_P(php_glyphs);
2781 3 : num_glyphs = zend_hash_num_elements(glyphs_hash);
2782 3 : glyphs_array = ecalloc(num_glyphs, sizeof(cairo_glyph_t));
2783 :
2784 : /* iterate over the array, each value inside MUST be an instance of CairoGlyph */
2785 16 : ZEND_HASH_FOREACH_VAL(glyphs_hash, pzval) {
2786 7 : if (Z_TYPE_P(pzval) != IS_OBJECT || Z_OBJCE_P(pzval) != ce_cairo_glyph) {
2787 1 : zend_throw_exception(zend_ce_type_error, "Cairo\\Context::showTextGlyphs(): Argument #2 ($glyphs) must be an array of Cairo\\Glyph objects.", 0);
2788 1 : efree(glyphs_array);
2789 1 : RETURN_THROWS();
2790 : }
2791 6 : glyphs_array[i++] = *(cairo_glyph_object_get_glyph(pzval));
2792 : }
2793 : ZEND_HASH_FOREACH_END();
2794 :
2795 : /* Clusters */
2796 2 : i = 0;
2797 2 : clusters_hash = Z_ARRVAL_P(php_clusters);
2798 2 : num_clusters = zend_hash_num_elements(clusters_hash);
2799 2 : clusters_array = ecalloc(num_clusters, sizeof(cairo_text_cluster_t));
2800 :
2801 : /* iterate over the array, each value inside MUST be an instance of Cairo\\TextCluster */
2802 15 : ZEND_HASH_FOREACH_VAL(clusters_hash, pzval) {
2803 7 : if (Z_TYPE_P(pzval) != IS_OBJECT || Z_OBJCE_P(pzval) != ce_cairo_text_cluster) {
2804 1 : zend_throw_exception(zend_ce_type_error, "Cairo\\Context::showTextGlyphs(): Argument #3 ($clusters) must be an array of Cairo\\TextCluster objects.", 0);
2805 1 : efree(glyphs_array);
2806 1 : efree(clusters_array);
2807 1 : RETURN_THROWS();
2808 : }
2809 6 : clusters_array[i++] = *(cairo_text_cluster_object_get_text_cluster(pzval));
2810 : }
2811 : ZEND_HASH_FOREACH_END();
2812 :
2813 1 : cairo_show_text_glyphs(context_object->context, utf8Str, utf8Str_len, glyphs_array, num_glyphs, clusters_array, num_clusters, (cairo_text_cluster_flags_t) cluster_flags);
2814 1 : efree(glyphs_array);
2815 1 : efree(clusters_array);
2816 :
2817 1 : if (php_cairo_throw_exception(cairo_status(context_object->context))) {
2818 0 : RETURN_THROWS();
2819 : }
2820 : }
2821 : /* }}} */
2822 :
2823 : /* {{{ proto array \Cairo\Context::getFontExtents()
2824 : previous name was fontExtents
2825 : Gets the metrics for a font in an assoc array. */
2826 2 : PHP_METHOD(Cairo_Context, getFontExtents)
2827 : {
2828 : cairo_context_object *context_object;
2829 : cairo_font_extents_t extents;
2830 :
2831 2 : ZEND_PARSE_PARAMETERS_NONE();
2832 :
2833 2 : context_object = cairo_context_object_get(getThis());
2834 1 : if (!context_object) {
2835 0 : RETURN_THROWS();
2836 : }
2837 :
2838 1 : cairo_font_extents(context_object->context, &extents);
2839 :
2840 1 : array_init(return_value);
2841 1 : add_assoc_double(return_value, "ascent", extents.ascent);
2842 1 : add_assoc_double(return_value, "descent", extents.descent);
2843 1 : add_assoc_double(return_value, "height", extents.height);
2844 1 : add_assoc_double(return_value, "max_x_advance", extents.max_x_advance);
2845 1 : add_assoc_double(return_value, "max_y_advance", extents.max_y_advance);
2846 : }
2847 : /* }}} */
2848 :
2849 : /* {{{ proto array \Cairo\Context::getTextExtents(string text)
2850 : previous name was textExtents
2851 : Gets the extents for a string of text. */
2852 4 : PHP_METHOD(Cairo_Context, getTextExtents)
2853 : {
2854 : char *text, *cairo_text;
2855 : size_t text_len;
2856 : cairo_context_object *context_object;
2857 : cairo_text_extents_t extents;
2858 :
2859 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
2860 4 : Z_PARAM_STRING(text, text_len)
2861 4 : ZEND_PARSE_PARAMETERS_END();
2862 :
2863 2 : context_object = cairo_context_object_get(getThis());
2864 1 : if (!context_object) {
2865 0 : RETURN_THROWS();
2866 : }
2867 :
2868 1 : cairo_text = estrdup(text);
2869 1 : cairo_text_extents(context_object->context, cairo_text, &extents);
2870 1 : efree(cairo_text);
2871 :
2872 1 : array_init(return_value);
2873 1 : add_assoc_double(return_value, "x_bearing", extents.x_bearing);
2874 1 : add_assoc_double(return_value, "y_bearing", extents.y_bearing);
2875 1 : add_assoc_double(return_value, "width", extents.width);
2876 1 : add_assoc_double(return_value, "height", extents.height);
2877 1 : add_assoc_double(return_value, "x_advance", extents.x_advance);
2878 1 : add_assoc_double(return_value, "y_advance", extents.y_advance);
2879 : }
2880 : /* }}} */
2881 :
2882 : /* {{{ proto array \Cairo\Context::getGlyphExtents(array glyphs)
2883 : previous name was glyphExtents
2884 : Gets the extents for an array of glyphs. */
2885 5 : PHP_METHOD(Cairo_Context, getGlyphExtents)
2886 : {
2887 : cairo_context_object *context_object;
2888 : cairo_glyph_t *glyphs_array;
2889 5 : int num_glyphs = 0;
2890 5 : zval *php_glyphs = NULL, *pzval;
2891 5 : HashTable *glyphs_hash = NULL;
2892 5 : int i = 0;
2893 : cairo_text_extents_t extents;
2894 :
2895 5 : ZEND_PARSE_PARAMETERS_START(1, 1)
2896 6 : Z_PARAM_ARRAY(php_glyphs)
2897 6 : ZEND_PARSE_PARAMETERS_END();
2898 :
2899 4 : context_object = cairo_context_object_get(getThis());
2900 2 : if (!context_object) {
2901 0 : RETURN_THROWS();
2902 : }
2903 :
2904 : /* Grab the zend hash */
2905 2 : glyphs_hash = Z_ARRVAL_P(php_glyphs);
2906 2 : num_glyphs = zend_hash_num_elements(glyphs_hash);
2907 2 : glyphs_array = ecalloc(num_glyphs, sizeof(cairo_glyph_t));
2908 :
2909 : /* iterate over the array, each value inside MUST be an instance of CairoGlyph */
2910 15 : ZEND_HASH_FOREACH_VAL(glyphs_hash, pzval) {
2911 7 : if (Z_TYPE_P(pzval) != IS_OBJECT || Z_OBJCE_P(pzval) != ce_cairo_glyph) {
2912 1 : zend_throw_exception(zend_ce_type_error, "Cairo\\Context::getGlyphExtents(): Argument #1 ($glyphs) must be an array of Cairo\\Glyph objects.", 0);
2913 1 : efree(glyphs_array);
2914 1 : RETURN_THROWS();
2915 : }
2916 6 : glyphs_array[i++] = *(cairo_glyph_object_get_glyph(pzval));
2917 : }
2918 : ZEND_HASH_FOREACH_END();
2919 :
2920 1 : cairo_glyph_extents(context_object->context, glyphs_array, num_glyphs, &extents);
2921 1 : efree(glyphs_array);
2922 :
2923 1 : array_init(return_value);
2924 1 : add_assoc_double(return_value, "x_bearing", extents.x_bearing);
2925 1 : add_assoc_double(return_value, "y_bearing", extents.y_bearing);
2926 1 : add_assoc_double(return_value, "width", extents.width);
2927 1 : add_assoc_double(return_value, "height", extents.height);
2928 1 : add_assoc_double(return_value, "x_advance", extents.x_advance);
2929 1 : add_assoc_double(return_value, "y_advance", extents.y_advance);
2930 : }
2931 : /* }}} */
2932 :
2933 :
2934 : /* ----------------------------------------------------------------
2935 : Cairo\Context Definition and registration
2936 : ------------------------------------------------------------------*/
2937 :
2938 : /* {{{ PHP_MINIT_FUNCTION */
2939 424 : PHP_MINIT_FUNCTION(cairo_context)
2940 : {
2941 424 : memcpy(
2942 : &cairo_context_object_handlers,
2943 : zend_get_std_object_handlers(),
2944 : sizeof(cairo_context_object_handlers)
2945 : );
2946 :
2947 : /* Context */
2948 424 : cairo_context_object_handlers.offset = XtOffsetOf(cairo_context_object, std);
2949 424 : cairo_context_object_handlers.free_obj = cairo_context_free_obj;
2950 :
2951 424 : ce_cairo_context = register_class_Cairo_Context();
2952 424 : ce_cairo_context->create_object = cairo_context_create_object;
2953 :
2954 : /* FillRule */
2955 424 : ce_cairo_fillrule = register_class_Cairo_FillRule();
2956 :
2957 : /* LineCap */
2958 424 : ce_cairo_linecap = register_class_Cairo_LineCap();
2959 :
2960 : /* LineJoin */
2961 424 : ce_cairo_linejoin = register_class_Cairo_LineJoin();
2962 :
2963 : /* Operator */
2964 424 : ce_cairo_operator = register_class_Cairo_Operator();
2965 :
2966 424 : return SUCCESS;
2967 : }
2968 : /* }}} */
|