LCOV - code coverage report
Current view: top level - src - context.c (source / functions) Coverage Total Hit
Test: PHP Cairo Extension Coverage Lines: 84.7 % 1295 1097
Test Date: 2025-09-10 21:28:33 Functions: 97.3 % 111 108

            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              : /* }}} */
        

Generated by: LCOV version 2.0-1