LCOV - code coverage report
Current view: top level - src - rectangle.c (source / functions) Coverage Total Hit
Test: PHP Cairo Extension Coverage Lines: 94.9 % 137 130
Test Date: 2025-09-10 21:28:33 Functions: 100.0 % 16 16

            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 : cairo_rectangle_int_t cairo_expand_to_rectangle_int(cairo_rectangle_t *rect) {
     104              :     cairo_rectangle_int_t result;
     105              : 
     106              :     // Expand rectangle to contain all fractional parts
     107           45 :     double x0 = rect->x;
     108           45 :     double y0 = rect->y;
     109           45 :     double x1 = rect->x + rect->width;
     110           45 :     double y1 = rect->y + rect->height;
     111              : 
     112              :     // expand outward
     113           45 :     result.x = (int) floor(x0);
     114           45 :     result.y = (int) floor(y0);
     115              : 
     116              :     // Ceiling for right/bottom, then calculate width/height
     117           45 :     int new_x1 = (int) ceil(x1);
     118           45 :     int new_y1 = (int) ceil(y1);
     119              : 
     120           45 :     result.width = new_x1 - result.x;
     121           45 :     result.height = new_y1 - result.y;
     122              : 
     123           45 :     return result;
     124              : }
     125              : 
     126           29 : void cairo_rectangle_int_to_double(cairo_rectangle_int_t *rect_int, cairo_rectangle_t *rect_double) {
     127           29 :     rect_double->x = (double) rect_int->x;
     128           29 :     rect_double->y = (double) rect_int->y;
     129           29 :     rect_double->width = (double) rect_int->width;
     130           29 :     rect_double->height = (double) rect_int->height;
     131           29 : }
     132              : 
     133              : 
     134              : /* ----------------------------------------------------------------
     135              :     \Cairo\Rectangle Class API
     136              : ------------------------------------------------------------------*/
     137              : 
     138              : /* {{{ proto void __construct([int x, int y, int width, int height])
     139              :     Creates a new rectangle with the properties populated */
     140           54 : PHP_METHOD(Cairo_Rectangle, __construct)
     141              : {
     142              :     cairo_rectangle_object *rectangle_object;
     143          108 :     zend_object *object = Z_OBJ_P(getThis());
     144              : 
     145              :     /* read defaults from object */
     146           54 :     double x = cairo_rectangle_get_property_value(object, "x");
     147           54 :     double y = cairo_rectangle_get_property_value(object, "y");
     148           54 :     double width = cairo_rectangle_get_property_value(object, "width");
     149           54 :     double height = cairo_rectangle_get_property_value(object, "height");
     150              : 
     151              :     /* Now allow constructor to overwrite them if desired */
     152           54 :     ZEND_PARSE_PARAMETERS_START(0, 4)
     153           53 :         Z_PARAM_OPTIONAL
     154          103 :         Z_PARAM_DOUBLE(x)
     155           96 :         Z_PARAM_DOUBLE(y)
     156           92 :         Z_PARAM_DOUBLE(width)
     157           90 :         Z_PARAM_DOUBLE(height)
     158           54 :     ZEND_PARSE_PARAMETERS_END();
     159              : 
     160           49 :     rectangle_object = cairo_rectangle_fetch_object(object);
     161              : 
     162           49 :     rectangle_object->rect->x = x;
     163           49 :     rectangle_object->rect->y = y;
     164           49 :     rectangle_object->rect->width = width;
     165           49 :     rectangle_object->rect->height = height;
     166              : }
     167              : /* }}} */
     168              : 
     169              : /* ----------------------------------------------------------------
     170              :     \Cairo\Rectangle Object management
     171              : ------------------------------------------------------------------*/
     172              : 
     173              : /* {{{ */
     174           91 : static void cairo_rectangle_free_obj(zend_object *object)
     175              : {
     176           91 :     cairo_rectangle_object *intern = cairo_rectangle_fetch_object(object);
     177              : 
     178           91 :     if (!intern) {
     179            0 :         return;
     180              :     }
     181              : 
     182           91 :     if (intern->rect) {
     183           91 :         efree(intern->rect);
     184           91 :         intern->rect = NULL;
     185              :     }
     186              : 
     187           91 :     zend_object_std_dtor(&intern->std);
     188              : }
     189              : /* }}} */
     190              : 
     191              : /* {{{ */
     192           91 : static zend_object* cairo_rectangle_obj_ctor(zend_class_entry *ce, cairo_rectangle_object **intern)
     193              : {
     194           91 :     cairo_rectangle_object *object = ecalloc(1, sizeof(cairo_rectangle_object) + zend_object_properties_size(ce));
     195           91 :     CAIRO_ALLOC_RECT(object->rect);
     196              : 
     197           91 :     zend_object_std_init(&object->std, ce);
     198              : 
     199           91 :     object->std.handlers = &cairo_rectangle_object_handlers;
     200           91 :     *intern = object;
     201              : 
     202              :     /* We need to read in any default values and set them if applicable */
     203           91 :     if (ce->default_properties_count) {
     204           91 :         object->rect->x = cairo_rectangle_get_property_default(ce, "x");
     205           91 :         object->rect->y = cairo_rectangle_get_property_default(ce, "y");
     206           91 :         object->rect->width = cairo_rectangle_get_property_default(ce, "width");
     207           91 :         object->rect->height = cairo_rectangle_get_property_default(ce, "height");
     208              :     }
     209              : 
     210           91 :     return &object->std;
     211              : }
     212              : /* }}} */
     213              : 
     214              : /* {{{ */
     215           89 : static zend_object* cairo_rectangle_create_object(zend_class_entry *ce)
     216              : {
     217           89 :     cairo_rectangle_object *intern = NULL;
     218           89 :     zend_object *return_value = cairo_rectangle_obj_ctor(ce, &intern);
     219              : 
     220           89 :     object_properties_init(&intern->std, ce);
     221           89 :     return return_value;
     222              : }
     223              : /* }}} */
     224              : 
     225              : /* {{{ */
     226            2 : static zend_object* cairo_rectangle_clone_obj(zend_object *zobj)
     227              : {
     228              :     cairo_rectangle_object *new_rectangle;
     229            2 :     cairo_rectangle_object *old_rectangle = cairo_rectangle_fetch_object(zobj);
     230            2 :     zend_object *return_value = cairo_rectangle_obj_ctor(zobj->ce, &new_rectangle);
     231            2 :     CAIRO_ALLOC_RECT(new_rectangle->rect);
     232              : 
     233            2 :     *new_rectangle->rect = *old_rectangle->rect;
     234              : 
     235            2 :     zend_objects_clone_members(&new_rectangle->std, &old_rectangle->std);
     236              : 
     237            2 :     return return_value;
     238              : }
     239              : /* }}} */
     240              : 
     241              : /* {{{ */
     242          228 : static zval *cairo_rectangle_object_read_property(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv)
     243              : {
     244              :     zval *retval;
     245              :     double value;
     246          228 :     cairo_rectangle_object *rectangle_object = cairo_rectangle_fetch_object(object);
     247              : 
     248          228 :     if (!rectangle_object) {
     249            0 :         return rv;
     250              :     }
     251              : 
     252              :     do {
     253          228 :         CAIRO_VALUE_FROM_STRUCT(x);
     254          169 :         CAIRO_VALUE_FROM_STRUCT(y);
     255          113 :         CAIRO_VALUE_FROM_STRUCT(width);
     256           57 :         CAIRO_VALUE_FROM_STRUCT(height);
     257              : 
     258              :         /* not a struct member */
     259            1 :         retval = (zend_get_std_object_handlers())->read_property(object, member, type, cache_slot, rv);
     260              : 
     261            1 :         return retval;
     262              :     } while(0);
     263              : 
     264          227 :     retval = rv;
     265          227 :     ZVAL_DOUBLE(retval, value);
     266              : 
     267          227 :     return retval;
     268              : }
     269              : /* }}} */
     270              : 
     271              : /* {{{ */
     272            6 : static zval *cairo_rectangle_object_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot)
     273              : {
     274            6 :     cairo_rectangle_object *rectangle_object = cairo_rectangle_fetch_object(object);
     275            6 :         zval *retval = NULL;
     276              : 
     277            6 :     if (!rectangle_object) {
     278            0 :         return retval;
     279              :     }
     280              : 
     281              :     do {
     282            8 :         CAIRO_VALUE_TO_STRUCT(x);
     283            5 :         CAIRO_VALUE_TO_STRUCT(y);
     284            4 :         CAIRO_VALUE_TO_STRUCT(width);
     285            3 :         CAIRO_VALUE_TO_STRUCT(height);
     286              : 
     287              :     } while(0);
     288              : 
     289              :     /* not a struct member */
     290            6 :     retval = (zend_get_std_object_handlers())->write_property(object, member, value, cache_slot);
     291              : 
     292            6 :         return retval;
     293              : }
     294              : /* }}} */
     295              : 
     296              : /* {{{ */
     297           39 : static HashTable *cairo_rectangle_object_get_properties(zend_object *object)
     298              : {
     299              :     HashTable *props;
     300              :     // used in CAIRO_ADD_STRUCT_VALUE below
     301              :     zval tmp;
     302           39 :     cairo_rectangle_object *rectangle_object = cairo_rectangle_fetch_object(object);
     303              : 
     304           39 :     props = zend_std_get_properties(object);
     305              : 
     306           39 :     if (!rectangle_object->rect) {
     307            0 :         return props;
     308              :     }
     309              : 
     310           39 :     CAIRO_ADD_STRUCT_VALUE(x);
     311           39 :     CAIRO_ADD_STRUCT_VALUE(y);
     312           39 :     CAIRO_ADD_STRUCT_VALUE(width);
     313           39 :     CAIRO_ADD_STRUCT_VALUE(height);
     314              : 
     315           39 :     return props;
     316              : }
     317              : /* }}} */
     318              : 
     319              : /* ----------------------------------------------------------------
     320              :     \Cairo\Rectangle Definition and registration
     321              : ------------------------------------------------------------------*/
     322              : 
     323              : /* {{{ PHP_MINIT_FUNCTION */
     324          424 : PHP_MINIT_FUNCTION(cairo_rectangle)
     325              : {
     326          424 :     memcpy(
     327              :         &cairo_rectangle_object_handlers,
     328              :         zend_get_std_object_handlers(),
     329              :         sizeof(zend_object_handlers)
     330              :     );
     331              : 
     332          424 :     cairo_rectangle_object_handlers.offset = XtOffsetOf(cairo_rectangle_object, std);
     333          424 :     cairo_rectangle_object_handlers.free_obj = cairo_rectangle_free_obj;
     334          424 :     cairo_rectangle_object_handlers.clone_obj = cairo_rectangle_clone_obj;
     335          424 :     cairo_rectangle_object_handlers.read_property = cairo_rectangle_object_read_property;
     336          424 :     cairo_rectangle_object_handlers.write_property = cairo_rectangle_object_write_property;
     337          424 :     cairo_rectangle_object_handlers.get_property_ptr_ptr = NULL;
     338          424 :     cairo_rectangle_object_handlers.get_properties = cairo_rectangle_object_get_properties;
     339              : 
     340          424 :     ce_cairo_rectangle = register_class_Cairo_Rectangle();
     341          424 :     ce_cairo_rectangle->create_object = cairo_rectangle_create_object;
     342              : 
     343          424 :     return SUCCESS;
     344              : }
     345              : /* }}} */
        

Generated by: LCOV version 2.0-1