LCOV - code coverage report
Current view: top level - src - pattern.c (source / functions) Coverage Total Hit
Test: PHP Cairo Extension Coverage Lines: 83.7 % 539 451
Test Date: 2025-09-10 21:28:33 Functions: 100.0 % 44 44

            Line data    Source code
       1              : /*
       2              :   +----------------------------------------------------------------------+
       3              :   | For PHP Version 8                                                    |
       4              :   +----------------------------------------------------------------------+
       5              :   | Copyright (c) 2015 Elizabeth M Smith                                 |
       6              :   +----------------------------------------------------------------------+
       7              :   | http://www.opensource.org/licenses/mit-license.php  MIT License      |
       8              :   | Also available in LICENSE                                            |
       9              :   +----------------------------------------------------------------------+
      10              :   | Authors: Elizabeth M Smith <auroraeosrose@gmail.com>                 |
      11              :   |          Swen Zanon <swen.zanon@geoglis.de>                          |
      12              :   +----------------------------------------------------------------------+
      13              : */
      14              : 
      15              : #ifdef HAVE_CONFIG_H
      16              : #include "config.h"
      17              : #endif
      18              : 
      19              : #include <cairo.h>
      20              : #include <php.h>
      21              : #include <zend_exceptions.h>
      22              : 
      23              : #include "php_cairo.h"
      24              : #include "php_cairo_internal.h"
      25              : #include "pattern_arginfo.h"
      26              : 
      27              : zend_class_entry *ce_cairo_pattern;
      28              : zend_class_entry *ce_cairo_pattern_solid;
      29              : zend_class_entry *ce_cairo_pattern_gradient;
      30              : zend_class_entry *ce_cairo_pattern_gradient_linear;
      31              : zend_class_entry *ce_cairo_pattern_gradient_radial;
      32              : zend_class_entry *ce_cairo_pattern_surface;
      33              : zend_class_entry *ce_cairo_pattern_mesh;
      34              : zend_class_entry *ce_cairo_pattern_raster;
      35              : 
      36              : zend_class_entry *ce_cairo_pattern_type;
      37              : zend_class_entry *ce_cairo_extend;
      38              : zend_class_entry *ce_cairo_filter;
      39              : zend_class_entry *ce_cairo_dither;
      40              : 
      41              : static zend_object_handlers cairo_pattern_object_handlers;
      42              : 
      43              : static cairo_user_data_key_t matrix_key;
      44              : 
      45            4 : void cairo_pattern_destroy_func (void *data)
      46              : {
      47              :     Z_DELREF_P(data);
      48            4 :     efree(data);
      49            4 : }
      50              : 
      51          284 : cairo_pattern_object *cairo_pattern_fetch_object(zend_object *object)
      52              : {
      53          284 :     return (cairo_pattern_object *) ((char*)(object) - XtOffsetOf(cairo_pattern_object, std));
      54              : }
      55              : 
      56          139 : static inline cairo_pattern_object *cairo_pattern_object_get(zval *zv)
      57              : {
      58          139 :     cairo_pattern_object *object = Z_CAIRO_PATTERN_P(zv);
      59          139 :     if (object->pattern == NULL) {
      60            3 :         zend_throw_exception_ex(ce_cairo_exception, 0,
      61              :             "Internal pattern object missing in %s, you must call parent::__construct in extended classes.",
      62            3 :             ZSTR_VAL(Z_OBJCE_P(zv)->name));
      63            3 :         return NULL;
      64              :     }
      65          136 :     return object;
      66              : }
      67              : 
      68              : 
      69              : /* ----------------------------------------------------------------
      70              :     Cairo\Pattern C API
      71              : ------------------------------------------------------------------*/
      72              : 
      73            6 : zend_class_entry* php_cairo_get_pattern_ce(cairo_pattern_t *pattern)
      74              : {
      75              :     zend_class_entry *type;
      76            6 :     if (pattern == NULL) {
      77            0 :         return ce_cairo_pattern;
      78              :     }
      79              : 
      80            6 :     switch(cairo_pattern_get_type(pattern)) {
      81            4 :         case CAIRO_PATTERN_TYPE_SOLID:
      82            4 :             type = ce_cairo_pattern_solid;
      83            4 :             break;
      84            2 :         case CAIRO_PATTERN_TYPE_SURFACE:
      85            2 :             type = ce_cairo_pattern_surface;
      86            2 :             break;
      87            0 :         case CAIRO_PATTERN_TYPE_LINEAR:
      88            0 :             type = ce_cairo_pattern_gradient_linear;
      89            0 :             break;
      90            0 :         case CAIRO_PATTERN_TYPE_RADIAL:
      91            0 :             type = ce_cairo_pattern_gradient_radial;
      92            0 :             break;
      93            0 :         case CAIRO_PATTERN_TYPE_MESH:
      94            0 :             type = ce_cairo_pattern_mesh;
      95            0 :             break;
      96            0 :         case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
      97            0 :             type = ce_cairo_pattern_raster;
      98            0 :             break;
      99            0 :         default:
     100            0 :             php_error(E_WARNING, "Unsupported Cairo Surface Type");
     101            0 :             return NULL;
     102              :     }
     103            6 :     return type;
     104              : }
     105              : 
     106              : 
     107              : /* ----------------------------------------------------------------
     108              :     Cairo\Pattern Class API
     109              : ------------------------------------------------------------------ */
     110              : 
     111              : /* {{{ proto void contruct()
     112              :    \Cairo\Pattern CANNOT be extended in userspace, this will throw an exception on use */
     113            2 : PHP_METHOD(Cairo_Pattern, __construct)
     114              : {
     115            2 :     ZEND_PARSE_PARAMETERS_NONE();
     116            2 :     zend_throw_exception(ce_cairo_exception, "Cairo\\Pattern cannot be constructed", 0);
     117              : }
     118              : /* }}} */
     119              : 
     120              : /* {{{ proto \Cairo\Status \Cairo\Pattern::getStatus()
     121              :    Returns the current integer status of the CairoPattern */
     122            5 : PHP_METHOD(Cairo_Pattern, getStatus)
     123              : {
     124              :     cairo_pattern_object *pattern_object;
     125              :     zval status_case;
     126              : 
     127            9 :     ZEND_PARSE_PARAMETERS_NONE();
     128              : 
     129            8 :     pattern_object = cairo_pattern_object_get(getThis());
     130            4 :     if (!pattern_object) {
     131            3 :         RETURN_THROWS();
     132              :     }
     133              : 
     134            1 :     status_case = php_enum_from_cairo_c_enum(
     135              :         ce_cairo_status,
     136            1 :         cairo_pattern_status(pattern_object->pattern)
     137              :     );
     138              : 
     139            1 :     if (Z_TYPE(status_case) == IS_OBJECT) {
     140            2 :         RETURN_ZVAL(&status_case, 1, 1);
     141              :     }
     142              : }
     143              : /* }}} */
     144              : 
     145              : /* {{{ proto void \Cairo\Pattern::getType()
     146              :    This function returns the Cairo\Pattern\Type of a pattern */
     147            2 : PHP_METHOD(Cairo_Pattern, getType)
     148              : {
     149              :     cairo_pattern_object *pattern_object;
     150              :     zval pattern_case;
     151              : 
     152            3 :     ZEND_PARSE_PARAMETERS_NONE();
     153              : 
     154            2 :     pattern_object = cairo_pattern_object_get(getThis());
     155            1 :     if (!pattern_object) {
     156            0 :         RETURN_THROWS();
     157              :     }
     158              : 
     159            1 :     pattern_case = php_enum_from_cairo_c_enum(
     160              :         ce_cairo_pattern_type,
     161            1 :         cairo_pattern_get_type(pattern_object->pattern)
     162              :     );
     163              : 
     164            1 :     if (Z_TYPE(pattern_case) == IS_OBJECT) {
     165            2 :         RETURN_ZVAL(&pattern_case, 1, 1);
     166              :     }
     167              : }
     168              : 
     169              : /* }}} */
     170              : 
     171              : /* {{{ proto int \Cairo\Pattern::getExtend()
     172              :        Gets the current extend mode for a pattern */
     173            6 : PHP_METHOD(Cairo_Pattern, getExtend)
     174              : {
     175              :     cairo_pattern_object *pattern_object;
     176              :     zval extend_case;
     177              : 
     178           10 :     ZEND_PARSE_PARAMETERS_NONE();
     179              : 
     180            8 :     pattern_object = cairo_pattern_object_get(getThis());
     181            4 :     if (!pattern_object) {
     182            0 :         RETURN_THROWS();
     183              :     }
     184              : 
     185            4 :     extend_case = php_enum_from_cairo_c_enum(
     186              :         ce_cairo_extend,
     187            4 :         cairo_pattern_get_extend(pattern_object->pattern)
     188              :     );
     189              : 
     190            4 :     if (Z_TYPE(extend_case) == IS_OBJECT) {
     191            8 :         RETURN_ZVAL(&extend_case, 1, 1);
     192              :     }
     193              : }
     194              : /* }}} */
     195              : 
     196              : /* {{{ proto void \Cairo\Pattern::setExtend(object)
     197              :        Sets the mode to be used for drawing outside the area of a pattern */
     198            9 : PHP_METHOD(Cairo_Pattern, setExtend)
     199              : {
     200              :     cairo_pattern_object *pattern_object;
     201              :     zval *extend_case;
     202              : 
     203            9 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     204           10 :         Z_PARAM_OBJECT_OF_CLASS(extend_case, ce_cairo_extend)
     205            9 :     ZEND_PARSE_PARAMETERS_END();
     206              : 
     207            4 :     pattern_object = cairo_pattern_object_get(getThis());
     208            2 :     if (!pattern_object) {
     209            0 :         RETURN_THROWS();
     210              :     }
     211              : 
     212            2 :     cairo_pattern_set_extend(
     213              :         pattern_object->pattern,
     214            4 :         Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(extend_case)))
     215              :     );
     216              : 
     217            2 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
     218            0 :         RETURN_THROWS();
     219              :     }
     220              : }
     221              : /* }}} */
     222              : 
     223              : /* {{{ proto int \Cairo\Pattern::getFilter()
     224              :        Gets the current filter mode for a pattern */
     225            6 : PHP_METHOD(Cairo_Pattern, getFilter)
     226              : {
     227              :     cairo_pattern_object *pattern_object;
     228              :     zval filter_case;
     229              : 
     230           10 :     ZEND_PARSE_PARAMETERS_NONE();
     231              : 
     232            8 :     pattern_object = cairo_pattern_object_get(getThis());
     233            4 :     if (!pattern_object) {
     234            0 :         RETURN_THROWS();
     235              :     }
     236              : 
     237            4 :     filter_case = php_enum_from_cairo_c_enum(
     238              :         ce_cairo_filter,
     239            4 :         cairo_pattern_get_filter(pattern_object->pattern)
     240              :     );
     241              : 
     242            4 :     if (Z_TYPE(filter_case) == IS_OBJECT) {
     243            8 :         RETURN_ZVAL(&filter_case, 1, 1);
     244              :     }
     245              : }
     246              : /* }}} */
     247              : 
     248              : /* {{{ proto void \Cairo\Pattern::setFilter(Cairo\Filter filter)
     249              :        Sets the filter to be used for resizing when using this pattern */
     250           10 : PHP_METHOD(Cairo_Pattern, setFilter)
     251              : {
     252              :     cairo_pattern_object *pattern_object;
     253              :     zval *filter_case;
     254              : 
     255           10 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     256           12 :         Z_PARAM_OBJECT_OF_CLASS(filter_case, ce_cairo_filter)
     257           10 :     ZEND_PARSE_PARAMETERS_END();
     258              : 
     259            6 :     pattern_object = cairo_pattern_object_get(getThis());
     260            3 :     if (!pattern_object) {
     261            0 :         RETURN_THROWS();
     262              :     }
     263              : 
     264            3 :     cairo_pattern_set_filter(
     265              :         pattern_object->pattern,
     266            6 :         Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(filter_case)))
     267              :     );
     268            3 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
     269            0 :         RETURN_THROWS();
     270              :     }
     271              : }
     272              : 
     273              : /* }}} */
     274              : 
     275              : /* {{{ proto object \Cairo\Pattern::getMatrix()
     276              :    Returns the pattern's transformation matrix */
     277            5 : PHP_METHOD(Cairo_Pattern, getMatrix)
     278              : {
     279              :     cairo_pattern_object *pattern_object;
     280            5 :     zval *matrix = NULL;
     281              : 
     282            5 :     ZEND_PARSE_PARAMETERS_NONE();
     283              : 
     284            8 :     pattern_object = cairo_pattern_object_get(getThis());
     285            4 :     if (!pattern_object) {
     286            0 :         RETURN_THROWS();
     287              :     }
     288              : 
     289            4 :     matrix = cairo_pattern_get_user_data(pattern_object->pattern, &matrix_key);
     290            4 :     if (matrix) {
     291            6 :         RETURN_COPY(matrix);
     292              :     }
     293              : 
     294            1 :     zval *matrix_store = emalloc(sizeof(zval));
     295              :     cairo_status_t status;
     296              : 
     297            1 :     object_init_ex(return_value, php_cairo_get_matrix_ce());
     298            1 :     cairo_pattern_get_matrix(pattern_object->pattern, cairo_matrix_object_get_matrix(return_value));
     299            1 :     ZVAL_COPY(matrix_store, return_value);
     300            1 :     status = cairo_pattern_set_user_data(
     301              :         pattern_object->pattern,
     302              :         &matrix_key,
     303              :         (void *)matrix_store, cairo_pattern_destroy_func
     304              :     );
     305              : 
     306            1 :     if (php_cairo_throw_exception(status)) {
     307            0 :         RETURN_THROWS();
     308              :     }
     309              : }
     310              : /* }}} */
     311              : 
     312              : /* {{{ proto void \Cairo\Pattern::setMatrix(\Cairo\Matrix object)
     313              :    Sets the pattern's transformation matrix using the created matrix object.
     314              :    This matrix is a transformation from user space to pattern space. */
     315            6 : PHP_METHOD(Cairo_Pattern, setMatrix)
     316              : {
     317              :     zval *matrix_zval;
     318              :     cairo_pattern_object *pattern_object;
     319              : 
     320            6 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     321            8 :         Z_PARAM_OBJECT_OF_CLASS(matrix_zval, ce_cairo_matrix)
     322            6 :     ZEND_PARSE_PARAMETERS_END();
     323              : 
     324            6 :     pattern_object = cairo_pattern_object_get(getThis());
     325            3 :     if (!pattern_object) {
     326            0 :         RETURN_THROWS();
     327              :     }
     328              : 
     329            3 :     cairo_pattern_set_matrix(pattern_object->pattern, cairo_matrix_object_get_matrix(matrix_zval));
     330              : 
     331            3 :     zval *matrix_store = emalloc(sizeof(zval));
     332              :     cairo_status_t status;
     333              : 
     334            3 :     ZVAL_COPY(matrix_store, matrix_zval);
     335              : 
     336            3 :     status = cairo_pattern_set_user_data(pattern_object->pattern, &matrix_key,
     337              :         (void *)matrix_store, cairo_pattern_destroy_func
     338              :     );
     339              : 
     340            3 :     if (php_cairo_throw_exception(status)) {
     341            0 :         RETURN_THROWS();
     342              :     }
     343              : }
     344              : /* }}} */
     345              : 
     346              : #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 18, 0)
     347              : /* {{{ proto object \Cairo\Pattern::getDither()
     348              :        Returns the pattern's dithering mode */
     349            3 : PHP_METHOD(Cairo_Pattern, getDither)
     350              : {
     351              :     cairo_pattern_object *pattern_object;
     352              :     zval dither_case;
     353              : 
     354            5 :     ZEND_PARSE_PARAMETERS_NONE();
     355              : 
     356            4 :     pattern_object = cairo_pattern_object_get(getThis());
     357            2 :     if (!pattern_object) {
     358            0 :         RETURN_THROWS();
     359              :     }
     360              : 
     361            2 :     dither_case = php_enum_from_cairo_c_enum(
     362              :         ce_cairo_dither,
     363            2 :         cairo_pattern_get_dither(pattern_object->pattern)
     364              :     );
     365              : 
     366            2 :     if (Z_TYPE(dither_case) == IS_OBJECT) {
     367            4 :         RETURN_ZVAL(&dither_case, 1, 1);
     368              :     }
     369              : }
     370              : /* }}} */
     371              : 
     372              : /* {{{ proto void \Cairo\Pattern::setDither(Cairo\Dither dither)
     373              :        Sets the dithering mode to be used for this pattern */
     374            4 : PHP_METHOD(Cairo_Pattern, setDither)
     375              : {
     376              :     cairo_pattern_object *pattern_object;
     377              :     zval *dither_case;
     378              : 
     379            4 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     380            4 :         Z_PARAM_OBJECT_OF_CLASS(dither_case, ce_cairo_dither)
     381            4 :     ZEND_PARSE_PARAMETERS_END();
     382              : 
     383            2 :     pattern_object = cairo_pattern_object_get(getThis());
     384            1 :     if (!pattern_object) {
     385            0 :         RETURN_THROWS();
     386              :     }
     387              : 
     388            1 :     cairo_pattern_set_dither(
     389              :         pattern_object->pattern,
     390            2 :         Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(dither_case)))
     391              :     );
     392              : 
     393            1 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
     394            0 :         RETURN_THROWS();
     395              :     }
     396              : }
     397              : /* }}} */
     398              : #endif
     399              : 
     400              : 
     401              : /* ----------------------------------------------------------------
     402              :     \Cairo\Pattern\Solid Class API
     403              : ------------------------------------------------------------------ */
     404              : 
     405              : /* {{{ proto void contruct(float red, float green, float blue[, float alpha])
     406              :     Returns new \Cairo\Pattern\Solid using rgb and optionally alpha */
     407           25 : PHP_METHOD(Cairo_Pattern_Solid, __construct)
     408              : {
     409           25 :     double red = 0.0, green = 0.0, blue = 0.0;
     410              :     double alpha;
     411           25 :     bool alpha_is_null = true;
     412              :     cairo_pattern_object *pattern_object;
     413              : 
     414           25 :     ZEND_PARSE_PARAMETERS_START(3, 4)
     415           42 :         Z_PARAM_DOUBLE(red)
     416           40 :         Z_PARAM_DOUBLE(green)
     417           38 :         Z_PARAM_DOUBLE(blue)
     418           18 :         Z_PARAM_OPTIONAL
     419           21 :         Z_PARAM_DOUBLE_OR_NULL(alpha, alpha_is_null)
     420           25 :     ZEND_PARSE_PARAMETERS_END();
     421              : 
     422           34 :     pattern_object = Z_CAIRO_PATTERN_P(getThis());
     423           17 :     if (!pattern_object) {
     424            0 :         RETURN_NULL();
     425              :     }
     426              : 
     427           17 :     if (alpha_is_null) {
     428           15 :         pattern_object->pattern = cairo_pattern_create_rgb(red, green, blue);
     429              :     } else {
     430            2 :         pattern_object->pattern = cairo_pattern_create_rgba(red, green, blue, alpha);
     431              :     }
     432              : 
     433           17 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
     434            0 :         RETURN_THROWS();
     435              :     }
     436              : }
     437              : /* }}} */
     438              : 
     439              : /* {{{ proto array \Cairo\Pattern\Solid::getRgba()
     440              :    This function returns an array with four elements,
     441              :    the float values of red, green, blue, and alpha from the solid pattern */
     442            9 : PHP_METHOD(Cairo_Pattern_Solid, getRgba)
     443              : {
     444              :     cairo_pattern_object *pattern_object;
     445              :     double red, green, blue, alpha;
     446              :         cairo_status_t status;
     447              : 
     448            9 :     ZEND_PARSE_PARAMETERS_NONE();
     449              : 
     450           16 :     pattern_object = cairo_pattern_object_get(getThis());
     451            8 :     if (!pattern_object) {
     452            0 :         RETURN_THROWS();
     453              :     }
     454              : 
     455            8 :     status = cairo_pattern_get_rgba(pattern_object->pattern, &red, &green, &blue, &alpha);
     456            8 :     if (php_cairo_throw_exception(status)) {
     457            0 :         RETURN_THROWS();
     458              :     }
     459              : 
     460            8 :     array_init(return_value);
     461            8 :     add_assoc_double(return_value, "red", red);
     462            8 :     add_assoc_double(return_value, "green", green);
     463            8 :     add_assoc_double(return_value, "blue", blue);
     464            8 :     add_assoc_double(return_value, "alpha", alpha);
     465              : }
     466              : /* }}} */
     467              : 
     468              : 
     469              : /* ----------------------------------------------------------------
     470              :     \Cairo\Pattern\Gradient Class API
     471              : ------------------------------------------------------------------ */
     472              : 
     473              : /* {{{ proto void \Cairo\Pattern\Gradient::addColorStopRgb(float offset, float red, float green, float blue)
     474              :    Adds an opaque color stop to a gradient pattern.
     475              :    The offset specifies the location along the gradient's control vector. */
     476           10 : PHP_METHOD(Cairo_Pattern_Gradient, addColorStopRgb)
     477              : {
     478           10 :     double offset = 0.0, red = 0.0, green = 0.0, blue = 0.0;
     479              :     cairo_pattern_object *pattern_object;
     480              : 
     481           10 :     ZEND_PARSE_PARAMETERS_START(4, 4)
     482           10 :         Z_PARAM_DOUBLE(offset)
     483            8 :         Z_PARAM_DOUBLE(red)
     484            6 :         Z_PARAM_DOUBLE(green)
     485            4 :         Z_PARAM_DOUBLE(blue)
     486           10 :     ZEND_PARSE_PARAMETERS_END();
     487              : 
     488            2 :     pattern_object = cairo_pattern_object_get(getThis());
     489            1 :     if (!pattern_object) {
     490            0 :         RETURN_THROWS();
     491              :     }
     492              : 
     493            1 :     cairo_pattern_add_color_stop_rgb(pattern_object->pattern, offset, red, green, blue);
     494              : 
     495            1 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
     496            0 :         RETURN_THROWS();
     497              :     }
     498              : }
     499              : /* }}} */
     500              : 
     501              : /* {{{ proto void \Cairo\Pattern\Gradient::addColorStopRgba(float offset, float red, float green, float blue, float alpha)
     502              :    Adds a transparent color stop to a gradient pattern.
     503              :    The offset specifies the location along the gradient's control vector. */
     504           16 : PHP_METHOD(Cairo_Pattern_Gradient, addColorStopRgba)
     505              : {
     506           16 :     double offset = 0.0, red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
     507              :     cairo_pattern_object *pattern_object;
     508              : 
     509           16 :     ZEND_PARSE_PARAMETERS_START(5, 5)
     510           20 :         Z_PARAM_DOUBLE(offset)
     511           18 :         Z_PARAM_DOUBLE(red)
     512           16 :         Z_PARAM_DOUBLE(green)
     513           14 :         Z_PARAM_DOUBLE(blue)
     514           12 :         Z_PARAM_DOUBLE(alpha)
     515           16 :     ZEND_PARSE_PARAMETERS_END();
     516              : 
     517           10 :     pattern_object = cairo_pattern_object_get(getThis());
     518            5 :     if (!pattern_object) {
     519            0 :         RETURN_THROWS();
     520              :     }
     521              : 
     522            5 :     cairo_pattern_add_color_stop_rgba(pattern_object->pattern, offset, red, green, blue, alpha);
     523              : 
     524            5 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
     525            0 :         RETURN_THROWS();
     526              :     }
     527              : }
     528              : /* }}} */
     529              : 
     530              : /* {{{ proto array \Cairo\Pattern\Gradient::getColorStopRgba()
     531              :    Gets the color and offset information at the given index for a gradient pattern */
     532            6 : PHP_METHOD(Cairo_Pattern_Gradient, getColorStopRgba)
     533              : {
     534              :     zend_long index;
     535              :     double offset, red, green, blue, alpha;
     536              :     cairo_pattern_object *pattern_object;
     537              :     cairo_status_t status;
     538              : 
     539            6 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     540            8 :         Z_PARAM_LONG(index)
     541            6 :     ZEND_PARSE_PARAMETERS_END();
     542              : 
     543            6 :     pattern_object = cairo_pattern_object_get(getThis());
     544            3 :     if (!pattern_object) {
     545            0 :         RETURN_THROWS();
     546              :     }
     547              : 
     548            3 :     status = cairo_pattern_get_color_stop_rgba(pattern_object->pattern, index, &offset, &red, &green, &blue, &alpha);
     549            3 :     if (php_cairo_throw_exception(status)) {
     550            0 :         RETURN_THROWS();
     551              :     }
     552              : 
     553            3 :     array_init(return_value);
     554            3 :     add_assoc_double(return_value, "offset", offset);
     555            3 :     add_assoc_double(return_value, "red", red);
     556            3 :     add_assoc_double(return_value, "green", green);
     557            3 :     add_assoc_double(return_value, "blue", blue);
     558            3 :     add_assoc_double(return_value, "alpha", alpha);
     559              : }
     560              : /* }}} */
     561              : 
     562              : /* {{{ proto int \Cairo\Pattern\Gradient::getColorStopCount()
     563              :    Gets the number of color stops specified in the given gradient pattern */
     564            3 : PHP_METHOD(Cairo_Pattern_Gradient, getColorStopCount)
     565              : {
     566              :     int count;
     567              :     cairo_pattern_object *pattern_object;
     568              :     cairo_status_t status;
     569              : 
     570            3 :     ZEND_PARSE_PARAMETERS_NONE();
     571              : 
     572            4 :     pattern_object = cairo_pattern_object_get(getThis());
     573            2 :     if (!pattern_object) {
     574            0 :         RETURN_THROWS();
     575              :     }
     576              : 
     577            2 :     status = cairo_pattern_get_color_stop_count(pattern_object->pattern, &count);
     578            2 :     if (php_cairo_throw_exception(status)) {
     579            0 :         RETURN_THROWS();
     580              :     }
     581              : 
     582            2 :     RETURN_LONG(count);
     583              : }
     584              : /* }}} */
     585              : 
     586              : 
     587              : /* ----------------------------------------------------------------
     588              :     \Cairo\Pattern\Gradient\Radial Class API
     589              : ------------------------------------------------------------------ */
     590              : 
     591              : /* {{{ proto void construct(float x0, float y0, float r0, float x1, float y1, float r1)
     592              :   Create a new Gradient along the line defined by (x0, y0) and (x1, y1).
     593              :   Before using the gradient pattern, a number of color stops should be defined. */
     594           19 : PHP_METHOD(Cairo_Pattern_Gradient_Radial, __construct)
     595              : {
     596              :     cairo_pattern_object *pattern_object;
     597           19 :     double x0 = 0.0, y0 = 0.0, r0 = 0.0, x1 = 0.0, y1 = 0.0, r1 = 0.0;
     598              : 
     599           19 :     ZEND_PARSE_PARAMETERS_START(6, 6)
     600           24 :         Z_PARAM_DOUBLE(x0)
     601           22 :         Z_PARAM_DOUBLE(y0)
     602           20 :         Z_PARAM_DOUBLE(r0)
     603           18 :         Z_PARAM_DOUBLE(x1)
     604           16 :         Z_PARAM_DOUBLE(y1)
     605           14 :         Z_PARAM_DOUBLE(r1)
     606           19 :     ZEND_PARSE_PARAMETERS_END();
     607              : 
     608           12 :     pattern_object = Z_CAIRO_PATTERN_P(getThis());
     609            6 :     if (!pattern_object) {
     610            0 :         RETURN_NULL();
     611              :     }
     612            6 :     pattern_object->pattern = cairo_pattern_create_radial(x0, y0, r0, x1, y1, r1);
     613            6 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
     614            0 :         RETURN_THROWS();
     615              :     }
     616              : }
     617              : /* }}} */
     618              : 
     619              : /* {{{ proto array \Cairo\Pattern\Gradient\Radial::getCircles()
     620              :    Gets the gradient endpoint circles for a radial gradient
     621              :    each specified as a center coordinate and a radius.*/
     622            2 : PHP_METHOD(Cairo_Pattern_Gradient_Radial, getCircles)
     623              : {
     624              :     cairo_pattern_object *pattern_object;
     625            2 :     double x0 = 0.0, y0 = 0.0, r0 = 0.0, x1 = 0.0, y1 = 0.0, r1 = 0.0;
     626              :     cairo_status_t status;
     627              : 
     628            2 :     ZEND_PARSE_PARAMETERS_NONE();
     629              : 
     630            2 :     pattern_object = cairo_pattern_object_get(getThis());
     631            1 :     if (!pattern_object) {
     632            0 :         RETURN_THROWS();
     633              :     }
     634              : 
     635            1 :     status = cairo_pattern_get_radial_circles(pattern_object->pattern, &x0, &y0, &r0, &x1, &y1, &r1);
     636              : 
     637            1 :     if (php_cairo_throw_exception(status)) {
     638            0 :         RETURN_THROWS();
     639              :     }
     640              : 
     641            1 :     array_init(return_value);
     642            1 :     add_assoc_double(return_value, "x0", x0);
     643            1 :     add_assoc_double(return_value, "y0", y0);
     644            1 :     add_assoc_double(return_value, "r0", r0);
     645            1 :     add_assoc_double(return_value, "x1", x1);
     646            1 :     add_assoc_double(return_value, "y1", y1);
     647            1 :     add_assoc_double(return_value, "r1", r1);
     648              : }
     649              : /* }}} */
     650              : 
     651              : 
     652              : /* ----------------------------------------------------------------
     653              :     \Cairo\Pattern\Gradient\Linear Class API
     654              : ------------------------------------------------------------------ */
     655              : 
     656              : /* {{{ proto void construct(float x0, float y0, float x1, float y1)
     657              :   Create a new CairoLinearGradient along the line defined by (x0, y0) and (x1, y1).
     658              :   Before using the gradient pattern, a number of color stops should be defined. */
     659           11 : PHP_METHOD(Cairo_Pattern_Gradient_Linear, __construct)
     660              : {
     661              :     cairo_pattern_object *pattern_object;
     662           11 :     double x0 = 0.0, y0 = 0.0, x1 = 0.0, y1 = 0.0;
     663              : 
     664           11 :     ZEND_PARSE_PARAMETERS_START(4, 4)
     665           12 :         Z_PARAM_DOUBLE(x0)
     666           10 :         Z_PARAM_DOUBLE(y0)
     667            8 :         Z_PARAM_DOUBLE(x1)
     668            6 :         Z_PARAM_DOUBLE(y1)
     669           11 :     ZEND_PARSE_PARAMETERS_END();
     670              : 
     671            4 :     pattern_object = Z_CAIRO_PATTERN_P(getThis());
     672            2 :     if (!pattern_object) {
     673            0 :         RETURN_NULL();
     674              :     }
     675              : 
     676            2 :     pattern_object->pattern = cairo_pattern_create_linear(x0, y0, x1, y1);
     677              : 
     678            2 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
     679            0 :         RETURN_THROWS();
     680              :     }
     681              : }
     682              : /* }}} */
     683              : 
     684              : /* {{{ proto void cairo_pattern_get_linear_points(CairoLinearGradient object)
     685              :    proto void \Cairo\Pattern\Gradient\Linear::getPoints()
     686              :    Gets the gradient endpoints for a linear gradient. */
     687            2 : PHP_METHOD(Cairo_Pattern_Gradient_Linear, getPoints)
     688              : {
     689              :     cairo_pattern_object *pattern_object;
     690              :     double x0, y0, x1, y1;
     691              :     cairo_status_t status;
     692              : 
     693            2 :     ZEND_PARSE_PARAMETERS_NONE();
     694              : 
     695            2 :     pattern_object = cairo_pattern_object_get(getThis());
     696            1 :     if (!pattern_object) {
     697            0 :         RETURN_THROWS();
     698              :     }
     699              : 
     700            1 :     status = cairo_pattern_get_linear_points(pattern_object->pattern, &x0, &y0, &x1, &y1);
     701              : 
     702            1 :     if (php_cairo_throw_exception(status)) {
     703            0 :         RETURN_THROWS();
     704              :     }
     705              : 
     706            1 :     array_init(return_value);
     707            1 :     add_assoc_double(return_value, "x0", x0);
     708            1 :     add_assoc_double(return_value, "y0", y0);
     709            1 :     add_assoc_double(return_value, "x1", x1);
     710            1 :     add_assoc_double(return_value, "y1", y1);
     711              : }
     712              : /* }}} */
     713              : 
     714              : 
     715              : /* ----------------------------------------------------------------
     716              :     \Cairo\Pattern\Surface Class API
     717              : ------------------------------------------------------------------ */
     718              : 
     719              : /* {{{ proto void contruct([object surface])
     720              :     Returns new \Cairo\Pattern\Surface using supplied surface */
     721            9 : PHP_METHOD(Cairo_Pattern_Surface, __construct)
     722              : {
     723              :     cairo_pattern_object *pattern_object;
     724              :     cairo_surface_object *surface_object;
     725              :     zval *surface_zval;
     726              : 
     727            9 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     728           14 :         Z_PARAM_OBJECT_OF_CLASS(surface_zval, ce_cairo_surface)
     729            9 :     ZEND_PARSE_PARAMETERS_END();
     730              : 
     731           12 :     pattern_object = Z_CAIRO_PATTERN_P(getThis());
     732            6 :     if (!pattern_object) {
     733            0 :         RETURN_NULL();
     734              :     }
     735              : 
     736            6 :     surface_object = cairo_surface_object_get(surface_zval);
     737            6 :     if (!surface_object) {
     738            0 :         RETURN_THROWS();
     739              :     }
     740              : 
     741            6 :     pattern_object->pattern = cairo_pattern_create_for_surface(surface_object->surface);
     742            6 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
     743            0 :         RETURN_THROWS();
     744              :     }
     745              : 
     746              :     /* we need to be able to get these zvals out later, so store it*/
     747            6 :     ZVAL_COPY(&pattern_object->surface, surface_zval);
     748              : }
     749              : /* }}} */
     750              : 
     751              : /* {{{ proto CairoSurface object \Cairo\Pattern\Surface::getSurface()
     752              :    This function returns the surface object */
     753            2 : PHP_METHOD(Cairo_Pattern_Surface, getSurface)
     754              : {
     755              :     cairo_pattern_object *pattern_object;
     756              :     cairo_surface_object *surface_object;
     757              :     cairo_surface_t *surface;
     758              : 
     759            3 :     ZEND_PARSE_PARAMETERS_NONE();
     760              : 
     761            2 :     pattern_object = cairo_pattern_object_get(getThis());
     762            1 :     if (!pattern_object) {
     763            0 :         RETURN_THROWS();
     764              :     }
     765              : 
     766            1 :     if (php_cairo_throw_exception(cairo_pattern_get_surface(pattern_object->pattern, &surface))) {
     767            0 :         RETURN_THROWS();
     768              :     }
     769              : 
     770              :     /* If we have a surface, grab that zval to use */
     771            5 :     CAIRO_RETURN_IF_REF(pattern_object->surface);
     772              : 
     773              :     /* Otherwise we spawn a new object */
     774              :     /* we can't always rely on the same type of surface being returned, so we use php_cairo_get_surface_ce */
     775            0 :     object_init_ex(return_value, php_cairo_get_surface_ce(surface));
     776              : 
     777              :     // cairo_surface_create_object(php_cairo_get_surface_ce(surface));
     778            0 :     surface_object = Z_CAIRO_SURFACE_P(return_value);
     779              : 
     780              :     /* if there IS a value in surface, destroy it cause we're getting a new one */
     781            0 :     if (surface_object->surface != NULL) {
     782            0 :         cairo_surface_destroy(surface_object->surface);
     783              :     }
     784              : 
     785            0 :     surface_object->surface = surface;
     786            0 :     cairo_surface_reference(surface_object->surface);
     787              : }
     788              : /* }}} */
     789              : 
     790              : 
     791              : /* ----------------------------------------------------------------
     792              :     \Cairo\Pattern\Mesh Class API
     793              : ------------------------------------------------------------------ */
     794              : 
     795              : /* {{{ proto void contruct()
     796              :     Returns new \Cairo\Pattern\Mesh */
     797           15 : PHP_METHOD(Cairo_Pattern_Mesh, __construct)
     798              : {
     799              :     cairo_pattern_object *pattern_object;
     800              : 
     801           15 :     ZEND_PARSE_PARAMETERS_NONE();
     802              : 
     803           28 :     pattern_object = Z_CAIRO_PATTERN_P(getThis());
     804           14 :     if (!pattern_object) {
     805            0 :         RETURN_NULL();
     806              :     }
     807              : 
     808           14 :     pattern_object->pattern = cairo_pattern_create_mesh();
     809              : 
     810           14 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
     811            0 :         RETURN_THROWS();
     812              :     }
     813              : }
     814              : /* }}} */
     815              : 
     816              : /* {{{  proto void \Cairo\Pattern\Mesh::beginPatch()
     817              :   begin a patch in a mesh pattern */
     818           15 : PHP_METHOD(Cairo_Pattern_Mesh, beginPatch)
     819              : {
     820              :     cairo_pattern_object *pattern_object;
     821              : 
     822           15 :     ZEND_PARSE_PARAMETERS_NONE();
     823              : 
     824           28 :     pattern_object = cairo_pattern_object_get(getThis());
     825           14 :     if (!pattern_object) {
     826            0 :         RETURN_THROWS();
     827              :     }
     828              : 
     829           14 :     cairo_mesh_pattern_begin_patch(pattern_object->pattern);
     830              : 
     831           14 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
     832            1 :         RETURN_THROWS();
     833              :     }
     834              : }
     835              : /* }}} */
     836              : 
     837              : /* {{{  proto void \Cairo\Pattern\Mesh::endPatch()
     838              :   end a patch in a mesh pattern*/
     839           14 : PHP_METHOD(Cairo_Pattern_Mesh, endPatch)
     840              : {
     841              :     cairo_pattern_object *pattern_object;
     842              : 
     843           14 :     ZEND_PARSE_PARAMETERS_NONE();
     844              : 
     845           26 :     pattern_object = cairo_pattern_object_get(getThis());
     846           13 :     if (!pattern_object) {
     847            0 :         RETURN_THROWS();
     848              :     }
     849              : 
     850           13 :     cairo_mesh_pattern_end_patch(pattern_object->pattern);
     851              : 
     852           13 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
     853            1 :         RETURN_THROWS();
     854              :     }
     855              : }
     856              : /* }}} */
     857              : 
     858              : /* {{{  proto void \Cairo\Pattern\Mesh::moveTo(float x, float y)
     859              :   move to a new starting point position in the patch */
     860           12 : PHP_METHOD(Cairo_Pattern_Mesh, moveTo)
     861              : {
     862              :     cairo_pattern_object *pattern_object;
     863              :     double x, y;
     864              : 
     865           12 :     ZEND_PARSE_PARAMETERS_START(2, 2)
     866           18 :         Z_PARAM_DOUBLE(x)
     867           16 :         Z_PARAM_DOUBLE(y)
     868           12 :     ZEND_PARSE_PARAMETERS_END();
     869              : 
     870           14 :     pattern_object = cairo_pattern_object_get(getThis());
     871            7 :     if (!pattern_object) {
     872            0 :         RETURN_THROWS();
     873              :     }
     874              : 
     875            7 :     cairo_mesh_pattern_move_to(pattern_object->pattern, x, y);
     876              : 
     877            7 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
     878            0 :         RETURN_THROWS();
     879              :     }
     880              : }
     881              : /* }}} */
     882              : 
     883              : /* {{{  proto void \Cairo\Pattern\Mesh::lineTo(float x, float y)
     884              :    add a line from the current point to position in the patch */
     885           15 : PHP_METHOD(Cairo_Pattern_Mesh, lineTo)
     886              : {
     887              :     cairo_pattern_object *pattern_object;
     888              :     double x, y;
     889              : 
     890           15 :     ZEND_PARSE_PARAMETERS_START(2, 2)
     891           24 :         Z_PARAM_DOUBLE(x)
     892           22 :         Z_PARAM_DOUBLE(y)
     893           15 :     ZEND_PARSE_PARAMETERS_END();
     894              : 
     895           20 :     pattern_object = cairo_pattern_object_get(getThis());
     896           10 :     if (!pattern_object) {
     897            0 :         RETURN_THROWS();
     898              :     }
     899              : 
     900           10 :     cairo_mesh_pattern_line_to(pattern_object->pattern, x, y);
     901              : 
     902           10 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
     903            0 :         RETURN_THROWS();
     904              :     }
     905              : }
     906              : /* }}} */
     907              : 
     908              : /* {{{  proto void \Cairo\Pattern\Mesh::curveTo(float x1, float y1, float x2,
     909              :  *           float y2, float x3, float y3)
     910              :    cubic bezier spline added to current path */
     911           10 : PHP_METHOD(Cairo_Pattern_Mesh, curveTo)
     912              : {
     913              :     cairo_pattern_object *pattern_object;
     914              :     double x1, y1, x2, y2, x3, y3;
     915              : 
     916           10 :     ZEND_PARSE_PARAMETERS_START(6, 6)
     917           14 :         Z_PARAM_DOUBLE(x1)
     918           12 :         Z_PARAM_DOUBLE(y1)
     919           10 :         Z_PARAM_DOUBLE(x2)
     920            8 :         Z_PARAM_DOUBLE(y2)
     921            6 :         Z_PARAM_DOUBLE(x3)
     922            4 :         Z_PARAM_DOUBLE(y3)
     923           10 :     ZEND_PARSE_PARAMETERS_END();
     924              : 
     925            2 :     pattern_object = cairo_pattern_object_get(getThis());
     926            1 :     if (!pattern_object) {
     927            0 :         RETURN_THROWS();
     928              :     }
     929              : 
     930            1 :     cairo_mesh_pattern_curve_to(pattern_object->pattern, x1, y1, x2, y2, x3, y3);
     931              : 
     932            1 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
     933            0 :         RETURN_THROWS();
     934              :     }
     935              : }
     936              : /* }}} */
     937              : 
     938              : /* {{{  proto void \Cairo\Pattern\Mesh::setControlPoint(int point_num,
     939              :             float x, float y)
     940              :         Set an internal control point of the current patch. */
     941           11 : PHP_METHOD(Cairo_Pattern_Mesh, setControlPoint)
     942              : {
     943              :     cairo_pattern_object *pattern_object;
     944              :     zend_long point_num;
     945              :     double x, y;
     946              : 
     947           11 :     ZEND_PARSE_PARAMETERS_START(3, 3)
     948           16 :         Z_PARAM_LONG(point_num)
     949           14 :         Z_PARAM_DOUBLE(x)
     950           12 :         Z_PARAM_DOUBLE(y)
     951           11 :     ZEND_PARSE_PARAMETERS_END();
     952              : 
     953           10 :     pattern_object = cairo_pattern_object_get(getThis());
     954            5 :     if (!pattern_object) {
     955            0 :         RETURN_THROWS();
     956              :     }
     957              : 
     958            5 :     if (point_num < 0 || point_num > 3) {
     959            2 :         zend_throw_error(ce_cairo_exception, "Invalid $point_num. Expected 0, 1, 2, or 3.");
     960            2 :         RETURN_THROWS();
     961              :     }
     962              : 
     963            3 :     cairo_mesh_pattern_set_control_point(pattern_object->pattern, point_num, x, y);
     964              : 
     965            3 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
     966            0 :         RETURN_THROWS();
     967              :     }
     968              : }
     969              : /* }}} */
     970              : 
     971              : // TODO: combine setCornerColorRgb and setCornerColorRgba to setCornerColor
     972              : // default value for alpha = 1.0
     973              : 
     974              : /* {{{  proto void \Cairo\Pattern\Mesh::setCornerColorRgb(int corner_num,
     975              :             float red, float blue, float green)
     976              :         Sets the color of a corner of the current patch in a mesh pattern. */
     977           12 : PHP_METHOD(Cairo_Pattern_Mesh, setCornerColorRgb)
     978              : {
     979              :     cairo_pattern_object *pattern_object;
     980              :     zend_long corner_num;
     981              :     double red, green, blue;
     982              : 
     983           12 :     ZEND_PARSE_PARAMETERS_START(4, 4)
     984           14 :         Z_PARAM_LONG(corner_num)
     985           12 :         Z_PARAM_DOUBLE(red)
     986           10 :         Z_PARAM_DOUBLE(green)
     987            8 :         Z_PARAM_DOUBLE(blue)
     988           12 :     ZEND_PARSE_PARAMETERS_END();
     989              : 
     990            6 :     pattern_object = cairo_pattern_object_get(getThis());
     991            3 :     if (!pattern_object) {
     992            0 :         RETURN_THROWS();
     993              :     }
     994              : 
     995            3 :     if (corner_num < 0 || corner_num > 3) {
     996            2 :         zend_throw_error(ce_cairo_exception, "Invalid $corner_num. Expected 0, 1, 2, or 3.");
     997            2 :         RETURN_THROWS();
     998              :     }
     999              : 
    1000            1 :     cairo_mesh_pattern_set_corner_color_rgb(pattern_object->pattern, corner_num, red, green, blue);
    1001              : 
    1002            1 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
    1003            0 :         RETURN_THROWS();
    1004              :     }
    1005              : }
    1006              : /* }}} */
    1007              : 
    1008              : /* {{{  proto void \Cairo\Pattern\Mesh::setCornerColorRgba(int corner_num,
    1009              :             float red, float blue, float green, float alpha)
    1010              :         Sets the color of a corner of the current patch in a mesh pattern. */
    1011           18 : PHP_METHOD(Cairo_Pattern_Mesh, setCornerColorRgba)
    1012              : {
    1013              :     cairo_pattern_object *pattern_object;
    1014              :     zend_long corner_num;
    1015              :     double red, green, blue, alpha;
    1016              : 
    1017           18 :     ZEND_PARSE_PARAMETERS_START(5, 5)
    1018           24 :         Z_PARAM_LONG(corner_num)
    1019           22 :         Z_PARAM_DOUBLE(red)
    1020           20 :         Z_PARAM_DOUBLE(green)
    1021           18 :         Z_PARAM_DOUBLE(blue)
    1022           16 :         Z_PARAM_DOUBLE(alpha)
    1023           18 :     ZEND_PARSE_PARAMETERS_END();
    1024              : 
    1025           14 :     pattern_object = cairo_pattern_object_get(getThis());
    1026            7 :     if (!pattern_object) {
    1027            0 :         RETURN_THROWS();
    1028              :     }
    1029              : 
    1030            7 :     if (corner_num < 0 || corner_num > 3) {
    1031            2 :         zend_throw_error(ce_cairo_exception, "Invalid $corner_num. Expected 0, 1, 2, or 3.");
    1032            2 :         RETURN_THROWS();
    1033              :     }
    1034              : 
    1035            5 :     cairo_mesh_pattern_set_corner_color_rgba(pattern_object->pattern, corner_num, red, green, blue, alpha);
    1036              : 
    1037            5 :     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
    1038            0 :         RETURN_THROWS();
    1039              :     }
    1040              : }
    1041              : /* }}} */
    1042              : 
    1043              : /* {{{  proto void \Cairo\Pattern\Mesh::getPatchCount()
    1044              :         Gets the number of patches specified in the given mesh pattern. */
    1045           12 : PHP_METHOD(Cairo_Pattern_Mesh, getPatchCount)
    1046              : {
    1047              :     cairo_pattern_object *pattern_object;
    1048              :     unsigned int count;
    1049              : 
    1050           12 :     ZEND_PARSE_PARAMETERS_NONE();
    1051              : 
    1052           24 :     pattern_object = cairo_pattern_object_get(getThis());
    1053           12 :     if (!pattern_object) {
    1054            0 :         RETURN_THROWS();
    1055              :     }
    1056              : 
    1057           12 :     if (php_cairo_throw_exception(cairo_mesh_pattern_get_patch_count(pattern_object->pattern, &count))) {
    1058            0 :         RETURN_THROWS();
    1059              :     }
    1060              : 
    1061           12 :     RETURN_LONG(count);
    1062              : }
    1063              : /* }}} */
    1064              : 
    1065              : /* {{{  proto void \Cairo\Pattern\Mesh::getPath()
    1066              :         Gets path defining the patch patch_num for a mesh pattern. */
    1067            4 : PHP_METHOD(Cairo_Pattern_Mesh, getPath)
    1068              : {
    1069              :     cairo_pattern_object *pattern_object;
    1070              :     cairo_path_object *path_object;
    1071              :     cairo_path_t *path;
    1072              :     zend_long patch_num;
    1073              : 
    1074            4 :     ZEND_PARSE_PARAMETERS_START(1, 1)
    1075            4 :         Z_PARAM_LONG(patch_num)
    1076            4 :     ZEND_PARSE_PARAMETERS_END();
    1077              : 
    1078            2 :     pattern_object = cairo_pattern_object_get(getThis());
    1079            1 :     if (!pattern_object) {
    1080            0 :         RETURN_THROWS();
    1081              :     }
    1082              : 
    1083            1 :     path = cairo_mesh_pattern_get_path(pattern_object->pattern, patch_num);
    1084              : 
    1085            1 :     object_init_ex(return_value, php_cairo_get_path_ce());
    1086              : 
    1087            1 :     path_object = Z_CAIRO_PATH_P(return_value);
    1088            1 :     if (!path_object) {
    1089            0 :         RETURN_NULL();
    1090              :     }
    1091              : 
    1092            1 :     path_object->path = path;
    1093              : }
    1094              : /* }}} */
    1095              : 
    1096              : /* {{{  proto array \Cairo\Pattern\Mesh::getControlPoint()
    1097              :         Gets the control point point_num of patch patch_num for a mesh pattern. */
    1098           13 : PHP_METHOD(Cairo_Pattern_Mesh, getControlPoint)
    1099              : {
    1100              :     cairo_pattern_object *pattern_object;
    1101              :     zend_long patch_num, point_num;
    1102              :     double x, y;
    1103              :     unsigned int count, max_patch_id;
    1104              : 
    1105           13 :     ZEND_PARSE_PARAMETERS_START(2, 2)
    1106           20 :         Z_PARAM_LONG(patch_num)
    1107           18 :         Z_PARAM_LONG(point_num)
    1108           13 :     ZEND_PARSE_PARAMETERS_END();
    1109              : 
    1110           16 :     pattern_object = cairo_pattern_object_get(getThis());
    1111            8 :     if (!pattern_object) {
    1112            0 :         RETURN_THROWS();
    1113              :     }
    1114              : 
    1115            8 :     cairo_mesh_pattern_get_patch_count(pattern_object->pattern, &count);
    1116            8 :     max_patch_id = count - 1;
    1117            8 :     if (count == 0) {
    1118            2 :         zend_throw_error(ce_cairo_exception, "No patches found or first patch not finished with endPatch().");
    1119            2 :         RETURN_THROWS();
    1120            6 :     } else if (patch_num < 0 || (unsigned int)patch_num > max_patch_id) {
    1121            2 :         zend_throw_error(ce_cairo_exception, "Invalid $patch_num. Expected 0 to %d.", max_patch_id);
    1122            2 :         RETURN_THROWS();
    1123              :     }
    1124              : 
    1125            4 :     if (point_num < 0 || point_num > 3) {
    1126            2 :         zend_throw_error(ce_cairo_exception, "Invalid $point_num. Expected 0, 1, 2, or 3.");
    1127            2 :         RETURN_THROWS();
    1128              :     }
    1129              : 
    1130            2 :     if (php_cairo_throw_exception(cairo_mesh_pattern_get_control_point(
    1131              :         pattern_object->pattern, patch_num, point_num, &x, &y))) {
    1132            0 :         RETURN_THROWS();
    1133              :     }
    1134              : 
    1135            2 :     array_init(return_value);
    1136            2 :     add_assoc_double(return_value, "x", x);
    1137            2 :     add_assoc_double(return_value, "y", y);
    1138              : }
    1139              : /* }}} */
    1140              : 
    1141              : /* {{{  proto void \Cairo\Pattern\Mesh::getCornerColorRgba()
    1142              :         Gets the color information in corner of path for a mesh pattern */
    1143           13 : PHP_METHOD(Cairo_Pattern_Mesh, getCornerColorRgba)
    1144              : {
    1145              :     cairo_pattern_object *pattern_object;
    1146              :     zend_long patch_num, corner_num;
    1147              :     double red, green, blue, alpha;
    1148              :     unsigned int count, max_patch_id;
    1149              : 
    1150           13 :     ZEND_PARSE_PARAMETERS_START(2, 2)
    1151           20 :         Z_PARAM_LONG(patch_num)
    1152           18 :         Z_PARAM_LONG(corner_num)
    1153           13 :     ZEND_PARSE_PARAMETERS_END();
    1154              : 
    1155           16 :     pattern_object = cairo_pattern_object_get(getThis());
    1156            8 :     if (!pattern_object) {
    1157            0 :         RETURN_THROWS();
    1158              :     }
    1159              : 
    1160            8 :     cairo_mesh_pattern_get_patch_count(pattern_object->pattern, &count);
    1161            8 :     max_patch_id = count - 1;
    1162            8 :     if (count == 0) {
    1163            0 :         zend_throw_error(ce_cairo_exception, "No patches found or first patch not finished with endPatch().");
    1164            0 :         RETURN_THROWS();
    1165            8 :     } else if (patch_num < 0 || (unsigned int)patch_num > max_patch_id) {
    1166            2 :         zend_throw_error(ce_cairo_exception, "Invalid $patch_num. Expected 0 to %d.", max_patch_id);
    1167            2 :         RETURN_THROWS();
    1168              :     }
    1169              : 
    1170            6 :     if (corner_num < 0 || corner_num > 3) {
    1171            2 :         zend_throw_error(ce_cairo_exception, "Invalid $corner_num. Expected 0, 1, 2, or 3.");
    1172            2 :         RETURN_THROWS();
    1173              :     }
    1174              : 
    1175            4 :     if (php_cairo_throw_exception(cairo_mesh_pattern_get_corner_color_rgba(
    1176              :         pattern_object->pattern, patch_num, corner_num, &red, &green, &blue, &alpha))) {
    1177            0 :         RETURN_THROWS();
    1178              :     }
    1179              : 
    1180            4 :     array_init(return_value);
    1181            4 :     add_assoc_double(return_value, "red", red);
    1182            4 :     add_assoc_double(return_value, "green", green);
    1183            4 :     add_assoc_double(return_value, "blue", blue);
    1184            4 :     add_assoc_double(return_value, "alpha", alpha);
    1185              : }
    1186              : /* }}} */
    1187              : 
    1188              : 
    1189              : /* ----------------------------------------------------------------
    1190              :     \Cairo\Pattern\RasterSource Class API
    1191              : ------------------------------------------------------------------ */
    1192              : 
    1193              : /* {{{ proto void construct(enum \Cairo\Surface\Content, int width, int height)
    1194              :        Returns new \Cairo\Pattern\RasterSource using supplied surface */
    1195              : // PHP_METHOD(CairoPatternRasterSource, __construct)
    1196              : // {
    1197              : //     cairo_pattern_object *pattern_object;
    1198              : //     zend_long width, height;
    1199              : //     zval *content;
    1200              : 
    1201              : //     ZEND_PARSE_PARAMETERS_START(3, 3)
    1202              : //         Z_PARAM_OBJECT_OF_CLASS(content, ce_cairo_content)
    1203              : //         Z_PARAM_LONG(width)
    1204              : //         Z_PARAM_LONG(height)
    1205              : //     ZEND_PARSE_PARAMETERS_END();
    1206              : 
    1207              : //     pattern_object = Z_CAIRO_PATTERN_P(getThis());
    1208              : //     if (!pattern_object) {
    1209              : //         RETURN_NULL();
    1210              : //     }
    1211              : 
    1212              : //     // TODO: create callbacks in C that feed to php methods as callbacks
    1213              : //     // register them all, and do the create
    1214              : //     // also figure out callback data - varargs?
    1215              : //     if (php_cairo_throw_exception(cairo_pattern_status(pattern_object->pattern))) {
    1216              : //         RETURN_THROWS();
    1217              : //     }
    1218              : // }
    1219              : /* }}} */
    1220              : 
    1221              : 
    1222              : /* ----------------------------------------------------------------
    1223              :     \Cairo\Pattern Object management
    1224              : ------------------------------------------------------------------*/
    1225              : 
    1226              : /* {{{ */
    1227           90 : static void cairo_pattern_free_obj(zend_object *object)
    1228              : {
    1229           90 :     cairo_pattern_object *intern = cairo_pattern_fetch_object(object);
    1230              : 
    1231           90 :     if (!intern) {
    1232            0 :         return;
    1233              :     }
    1234              : 
    1235           90 :     zval_ptr_dtor(&intern->surface);
    1236              : 
    1237           90 :     if (intern->pattern) {
    1238           51 :         cairo_pattern_destroy(intern->pattern);
    1239           51 :         intern->pattern = NULL;
    1240              :     }
    1241              : 
    1242           90 :     zend_object_std_dtor(&intern->std);
    1243              : }
    1244              : /* }}} */
    1245              : 
    1246              : /* {{{ */
    1247           90 : static zend_object* cairo_pattern_obj_ctor(zend_class_entry *ce, cairo_pattern_object **intern)
    1248              : {
    1249           90 :     cairo_pattern_object *object = ecalloc(1, sizeof(cairo_pattern_object) + zend_object_properties_size(ce));
    1250              : 
    1251           90 :     ZVAL_UNDEF(&object->surface);
    1252           90 :     object->pattern = NULL;
    1253              : 
    1254           90 :     zend_object_std_init(&object->std, ce);
    1255           90 :     object->std.handlers = &cairo_pattern_object_handlers;
    1256           90 :     *intern = object;
    1257              : 
    1258           90 :     return &object->std;
    1259              : }
    1260              : /* }}} */
    1261              : 
    1262              : /* {{{ */
    1263           90 : static zend_object* cairo_pattern_create_object(zend_class_entry *ce)
    1264              : {
    1265           90 :     cairo_pattern_object *pattern = NULL;
    1266           90 :     zend_object *return_value = cairo_pattern_obj_ctor(ce, &pattern);
    1267              : 
    1268           90 :     object_properties_init(&pattern->std, ce);
    1269           90 :     return return_value;
    1270              : }
    1271              : /* }}} */
    1272              : 
    1273              : 
    1274              : /* ----------------------------------------------------------------
    1275              :     \Cairo\Pattern Definition and registration
    1276              : ------------------------------------------------------------------*/
    1277              : 
    1278              : /* {{{ PHP_MINIT_FUNCTION */
    1279          424 : PHP_MINIT_FUNCTION(cairo_pattern)
    1280              : {
    1281          424 :     memcpy(
    1282              :         &cairo_pattern_object_handlers,
    1283              :         zend_get_std_object_handlers(),
    1284              :         sizeof(zend_object_handlers)
    1285              :     );
    1286              : 
    1287              :     // Pattern
    1288          424 :     cairo_pattern_object_handlers.offset = XtOffsetOf(cairo_pattern_object, std);
    1289          424 :     cairo_pattern_object_handlers.free_obj = cairo_pattern_free_obj;
    1290              : 
    1291          424 :     ce_cairo_pattern = register_class_Cairo_Pattern();
    1292          424 :     ce_cairo_pattern->create_object = cairo_pattern_create_object;
    1293              : 
    1294              :     // Pattern\Solid
    1295          424 :     ce_cairo_pattern_solid = register_class_Cairo_Pattern_Solid(ce_cairo_pattern);
    1296              : 
    1297              :     // Pattern\Gradient
    1298          424 :     ce_cairo_pattern_gradient = register_class_Cairo_Pattern_Gradient(ce_cairo_pattern);
    1299              : 
    1300              :     // Pattern\Gradient\Radial
    1301          424 :     ce_cairo_pattern_gradient_radial = register_class_Cairo_Pattern_Gradient_Radial(ce_cairo_pattern_gradient);
    1302              : 
    1303              :     // Pattern\Gradient\Linear
    1304          424 :     ce_cairo_pattern_gradient_linear = register_class_Cairo_Pattern_Gradient_Linear(ce_cairo_pattern_gradient);
    1305              : 
    1306              :     // Pattern\Surface
    1307          424 :     ce_cairo_pattern_surface = register_class_Cairo_Pattern_Surface(ce_cairo_pattern);
    1308              : 
    1309              :     // Pattern\Mesh
    1310          424 :     ce_cairo_pattern_mesh = register_class_Cairo_Pattern_Mesh(ce_cairo_pattern);
    1311              : 
    1312              :     // Pattern\RasterSource
    1313              :     // not implemented yet
    1314              :     // ce_cairo_pattern_raster = register_class_Cairo_Pattern_RasterSource(ce_cairo_pattern);
    1315              : 
    1316              :     // Pattern\Type
    1317          424 :     ce_cairo_pattern_type = register_class_Cairo_Pattern_Type();
    1318              : 
    1319              :     // Extend
    1320          424 :     ce_cairo_extend = register_class_Cairo_Extend();
    1321              : 
    1322              :     // Filter
    1323          424 :     ce_cairo_filter = register_class_Cairo_Filter();
    1324              : 
    1325              :     // Dither
    1326          424 :     ce_cairo_dither = register_class_Cairo_Dither();
    1327              : 
    1328          424 :     return SUCCESS;
    1329              : }
        

Generated by: LCOV version 2.0-1