|             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 "rectangle_arginfo.h"
      26              : 
      27              : zend_class_entry *ce_cairo_rectangle;
      28              : 
      29              : static zend_object_handlers cairo_rectangle_object_handlers;
      30              : 
      31          497 : cairo_rectangle_object *cairo_rectangle_fetch_object(zend_object *object)
      32              : {
      33          497 :     return (cairo_rectangle_object *) ((char*)(object) - XtOffsetOf(cairo_rectangle_object, std));
      34              : }
      35              : 
      36          364 : static inline double cairo_rectangle_get_property_default(zend_class_entry *ce, char * name) {
      37              :     zend_property_info *property_info;
      38          364 :     double value = 0;
      39          364 :     zend_string *key = zend_string_init(name, strlen(name), 0);
      40              : 
      41          364 :     property_info = zend_get_property_info(ce, key, 1);
      42          364 :     if (property_info) {
      43          364 :         zval *val = (zval*)((char*)ce->default_properties_table + property_info->offset - OBJ_PROP_TO_OFFSET(0));
      44          364 :         if (val) {
      45          364 :             value = zval_get_double(val);
      46              :         }
      47              :     }
      48              :     zend_string_release(key);
      49          364 :     return value;
      50              : }
      51              : 
      52          216 : static inline long cairo_rectangle_get_property_value(zend_object *object, char *name) {
      53              :     zval *prop, rv;
      54              : 
      55          216 :     prop = zend_read_property(object->ce, object, name, strlen(name), 1, &rv);
      56          216 :     return zval_get_double(prop);
      57              : }
      58              : 
      59              : #define CAIRO_ALLOC_RECT(rect_value) if (!rect_value) \
      60              :     { rect_value = ecalloc(1, sizeof(cairo_rectangle_t)); }
      61              : 
      62              : #define CAIRO_VALUE_FROM_STRUCT(n) \
      63              :     if (strcmp(member->val, #n) == 0) { \
      64              :         value = rectangle_object->rect->n; \
      65              :         break; \
      66              :     }
      67              : 
      68              : #define CAIRO_VALUE_TO_STRUCT(n) \
      69              :     if (strcmp(member->val, #n) == 0) { \
      70              :         rectangle_object->rect->n = zval_get_double(value); \
      71              :         break; \
      72              :     }
      73              : 
      74              : #define CAIRO_ADD_STRUCT_VALUE(n) \
      75              :     ZVAL_DOUBLE(&tmp, rectangle_object->rect->n); \
      76              :     zend_hash_str_update(props, #n, sizeof(#n)-1, &tmp);
      77              : 
      78              : /* ----------------------------------------------------------------
      79              :     \Cairo\Rectangle C API
      80              : ------------------------------------------------------------------*/
      81              : 
      82              : /* {{{ */
      83           32 : cairo_rectangle_t *cairo_rectangle_object_get_rect(zval *zv)
      84              : {
      85           32 :     cairo_rectangle_object *rect_object = Z_CAIRO_RECTANGLE_P(zv);
      86              : 
      87           32 :     if (rect_object->rect == NULL) {
      88            0 :         zend_throw_exception_ex(ce_cairo_exception, 0,
      89              :             "Internal rectangle object missing in %s, you must call parent::__construct in extended classes.",
      90            0 :             ZSTR_VAL(Z_OBJCE_P(zv)->name));
      91            0 :         return NULL;
      92              :     }
      93              : 
      94           32 :     return rect_object->rect;
      95              : }
      96              : /* }}} */
      97              : 
      98           40 : zend_class_entry* php_cairo_get_rectangle_ce()
      99              : {
     100           40 :     return ce_cairo_rectangle;
     101              : }
     102              : 
     103           45 : void cairo_expand_to_rectangle_int(cairo_rectangle_t *rect_double, cairo_rectangle_int_t *rect_int) {
     104           45 :     if (rect_double == NULL) {
     105            0 :         rect_int = NULL;
     106            0 :         return;
     107              :     }
     108              : 
     109              :     // Expand rectangle to contain all fractional parts
     110           45 :     double x0 = rect_double->x;
     111           45 :     double y0 = rect_double->y;
     112           45 :     double x1 = rect_double->x + rect_double->width;
     113           45 :     double y1 = rect_double->y + rect_double->height;
     114              : 
     115              :     // expand outward
     116           45 :     rect_int->x = (int) floor(x0);
     117           45 :     rect_int->y = (int) floor(y0);
     118              : 
     119              :     // Ceiling for right/bottom, then calculate width/height
     120           45 :     int new_x1 = (int) ceil(x1);
     121           45 :     int new_y1 = (int) ceil(y1);
     122              : 
     123           45 :     rect_int->width = new_x1 - rect_int->x;
     124           45 :     rect_int->height = new_y1 - rect_int->y;
     125              : }
     126              : 
     127           29 : void cairo_rectangle_int_to_double(cairo_rectangle_int_t *rect_int, cairo_rectangle_t *rect_double) {
     128           29 :     if (rect_int == NULL) {
     129            0 :         rect_double = NULL;
     130            0 :         return;
     131              :     }
     132              : 
     133           29 :     rect_double->x = (double) rect_int->x;
     134           29 :     rect_double->y = (double) rect_int->y;
     135           29 :     rect_double->width = (double) rect_int->width;
     136           29 :     rect_double->height = (double) rect_int->height;
     137              : }
     138              : 
     139              : 
     140              : /* ----------------------------------------------------------------
     141              :     \Cairo\Rectangle Class API
     142              : ------------------------------------------------------------------*/
     143              : 
     144              : /* {{{ proto void __construct([int x, int y, int width, int height])
     145              :     Creates a new rectangle with the properties populated */
     146           54 : PHP_METHOD(Cairo_Rectangle, __construct)
     147              : {
     148              :     cairo_rectangle_object *rectangle_object;
     149          108 :     zend_object *object = Z_OBJ_P(getThis());
     150              : 
     151              :     /* read defaults from object */
     152           54 :     double x = cairo_rectangle_get_property_value(object, "x");
     153           54 :     double y = cairo_rectangle_get_property_value(object, "y");
     154           54 :     double width = cairo_rectangle_get_property_value(object, "width");
     155           54 :     double height = cairo_rectangle_get_property_value(object, "height");
     156              : 
     157              :     /* Now allow constructor to overwrite them if desired */
     158           54 :     ZEND_PARSE_PARAMETERS_START(0, 4)
     159           53 :         Z_PARAM_OPTIONAL
     160          103 :         Z_PARAM_DOUBLE(x)
     161           96 :         Z_PARAM_DOUBLE(y)
     162           92 :         Z_PARAM_DOUBLE(width)
     163           90 :         Z_PARAM_DOUBLE(height)
     164           54 :     ZEND_PARSE_PARAMETERS_END();
     165              : 
     166           49 :     rectangle_object = cairo_rectangle_fetch_object(object);
     167              : 
     168           49 :     rectangle_object->rect->x = (int) x;
     169           49 :     rectangle_object->rect->y = (int) y;
     170           49 :     rectangle_object->rect->width = (int) width;
     171           49 :     rectangle_object->rect->height = (int) height;
     172              : }
     173              : /* }}} */
     174              : 
     175              : /* ----------------------------------------------------------------
     176              :     \Cairo\Rectangle Object management
     177              : ------------------------------------------------------------------*/
     178              : 
     179              : /* {{{ */
     180           91 : static void cairo_rectangle_free_obj(zend_object *object)
     181              : {
     182           91 :     cairo_rectangle_object *intern = cairo_rectangle_fetch_object(object);
     183              : 
     184           91 :     if (!intern) {
     185            0 :         return;
     186              :     }
     187              : 
     188           91 :     if (intern->rect) {
     189           91 :         efree(intern->rect);
     190           91 :         intern->rect = NULL;
     191              :     }
     192              : 
     193           91 :     zend_object_std_dtor(&intern->std);
     194              : }
     195              : /* }}} */
     196              : 
     197              : /* {{{ */
     198           91 : static zend_object* cairo_rectangle_obj_ctor(zend_class_entry *ce, cairo_rectangle_object **intern)
     199              : {
     200           91 :     cairo_rectangle_object *object = ecalloc(1, sizeof(cairo_rectangle_object) + zend_object_properties_size(ce));
     201           91 :     CAIRO_ALLOC_RECT(object->rect);
     202              : 
     203           91 :     zend_object_std_init(&object->std, ce);
     204              : 
     205           91 :     object->std.handlers = &cairo_rectangle_object_handlers;
     206           91 :     *intern = object;
     207              : 
     208              :     /* We need to read in any default values and set them if applicable */
     209           91 :     if (ce->default_properties_count) {
     210           91 :         object->rect->x = cairo_rectangle_get_property_default(ce, "x");
     211           91 :         object->rect->y = cairo_rectangle_get_property_default(ce, "y");
     212           91 :         object->rect->width = cairo_rectangle_get_property_default(ce, "width");
     213           91 :         object->rect->height = cairo_rectangle_get_property_default(ce, "height");
     214              :     }
     215              : 
     216           91 :     return &object->std;
     217              : }
     218              : /* }}} */
     219              : 
     220              : /* {{{ */
     221           89 : static zend_object* cairo_rectangle_create_object(zend_class_entry *ce)
     222              : {
     223           89 :     cairo_rectangle_object *intern = NULL;
     224           89 :     zend_object *return_value = cairo_rectangle_obj_ctor(ce, &intern);
     225              : 
     226           89 :     object_properties_init(&intern->std, ce);
     227           89 :     return return_value;
     228              : }
     229              : /* }}} */
     230              : 
     231              : /* {{{ */
     232            2 : static zend_object* cairo_rectangle_clone_obj(zend_object *zobj)
     233              : {
     234              :     cairo_rectangle_object *new_rectangle;
     235            2 :     cairo_rectangle_object *old_rectangle = cairo_rectangle_fetch_object(zobj);
     236            2 :     zend_object *return_value = cairo_rectangle_obj_ctor(zobj->ce, &new_rectangle);
     237            2 :     CAIRO_ALLOC_RECT(new_rectangle->rect);
     238              : 
     239            2 :     *new_rectangle->rect = *old_rectangle->rect;
     240              : 
     241            2 :     zend_objects_clone_members(&new_rectangle->std, &old_rectangle->std);
     242              : 
     243            2 :     return return_value;
     244              : }
     245              : /* }}} */
     246              : 
     247              : /* {{{ */
     248          228 : static zval *cairo_rectangle_object_read_property(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv)
     249              : {
     250              :     zval *retval;
     251              :     double value;
     252          228 :     cairo_rectangle_object *rectangle_object = cairo_rectangle_fetch_object(object);
     253              : 
     254          228 :     if (!rectangle_object) {
     255            0 :         return rv;
     256              :     }
     257              : 
     258              :     do {
     259          228 :         CAIRO_VALUE_FROM_STRUCT(x);
     260          169 :         CAIRO_VALUE_FROM_STRUCT(y);
     261          113 :         CAIRO_VALUE_FROM_STRUCT(width);
     262           57 :         CAIRO_VALUE_FROM_STRUCT(height);
     263              : 
     264              :         /* not a struct member */
     265            1 :         retval = (zend_get_std_object_handlers())->read_property(object, member, type, cache_slot, rv);
     266              : 
     267            1 :         return retval;
     268              :     } while(0);
     269              : 
     270          227 :     retval = rv;
     271          227 :     ZVAL_DOUBLE(retval, value);
     272              : 
     273          227 :     return retval;
     274              : }
     275              : /* }}} */
     276              : 
     277              : /* {{{ */
     278            6 : static zval *cairo_rectangle_object_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot)
     279              : {
     280            6 :     cairo_rectangle_object *rectangle_object = cairo_rectangle_fetch_object(object);
     281            6 :         zval *retval = NULL;
     282              : 
     283            6 :     if (!rectangle_object) {
     284            0 :         return retval;
     285              :     }
     286              : 
     287              :     do {
     288            8 :         CAIRO_VALUE_TO_STRUCT(x);
     289            5 :         CAIRO_VALUE_TO_STRUCT(y);
     290            4 :         CAIRO_VALUE_TO_STRUCT(width);
     291            3 :         CAIRO_VALUE_TO_STRUCT(height);
     292              : 
     293              :     } while(0);
     294              : 
     295              :     /* not a struct member */
     296            6 :     retval = (zend_get_std_object_handlers())->write_property(object, member, value, cache_slot);
     297              : 
     298            6 :         return retval;
     299              : }
     300              : /* }}} */
     301              : 
     302              : /* {{{ */
     303           39 : static HashTable *cairo_rectangle_object_get_properties(zend_object *object)
     304              : {
     305              :     HashTable *props;
     306              :     // used in CAIRO_ADD_STRUCT_VALUE below
     307              :     zval tmp;
     308           39 :     cairo_rectangle_object *rectangle_object = cairo_rectangle_fetch_object(object);
     309              : 
     310           39 :     props = zend_std_get_properties(object);
     311              : 
     312           39 :     if (!rectangle_object->rect) {
     313            0 :         return props;
     314              :     }
     315              : 
     316           39 :     CAIRO_ADD_STRUCT_VALUE(x);
     317           39 :     CAIRO_ADD_STRUCT_VALUE(y);
     318           39 :     CAIRO_ADD_STRUCT_VALUE(width);
     319           39 :     CAIRO_ADD_STRUCT_VALUE(height);
     320              : 
     321           39 :     return props;
     322              : }
     323              : /* }}} */
     324              : 
     325              : /* ----------------------------------------------------------------
     326              :     \Cairo\Rectangle Definition and registration
     327              : ------------------------------------------------------------------*/
     328              : 
     329              : /* {{{ PHP_MINIT_FUNCTION */
     330          433 : PHP_MINIT_FUNCTION(cairo_rectangle)
     331              : {
     332          433 :     memcpy(
     333              :         &cairo_rectangle_object_handlers,
     334              :         zend_get_std_object_handlers(),
     335              :         sizeof(zend_object_handlers)
     336              :     );
     337              : 
     338          433 :     cairo_rectangle_object_handlers.offset = XtOffsetOf(cairo_rectangle_object, std);
     339          433 :     cairo_rectangle_object_handlers.free_obj = cairo_rectangle_free_obj;
     340          433 :     cairo_rectangle_object_handlers.clone_obj = cairo_rectangle_clone_obj;
     341          433 :     cairo_rectangle_object_handlers.read_property = cairo_rectangle_object_read_property;
     342          433 :     cairo_rectangle_object_handlers.write_property = cairo_rectangle_object_write_property;
     343          433 :     cairo_rectangle_object_handlers.get_property_ptr_ptr = NULL;
     344          433 :     cairo_rectangle_object_handlers.get_properties = cairo_rectangle_object_get_properties;
     345              : 
     346          433 :     ce_cairo_rectangle = register_class_Cairo_Rectangle();
     347          433 :     ce_cairo_rectangle->create_object = cairo_rectangle_create_object;
     348              : 
     349          433 :     return SUCCESS;
     350              : }
     351              : /* }}} */
         |