LCOV - code coverage report
Current view: top level - src - matrix.c (source / functions) Coverage Total Hit
Test: PHP Pango Extension Coverage Lines: 96.5 % 198 191
Test Date: 2025-10-26 00:52:08 Functions: 100.0 % 21 21

            Line data    Source code
       1              : /*
       2              :   +----------------------------------------------------------------------+
       3              :   | For PHP Version 8.2+                                                 |
       4              :   +----------------------------------------------------------------------+
       5              :   | Copyright (c) 2015 Elizabeth M Smith                                 |
       6              :   +----------------------------------------------------------------------+
       7              :   | http://www.opensource.org/licenses/mit-license.php  MIT License      |
       8              :   +----------------------------------------------------------------------+
       9              :   | Authors: Elizabeth M Smith <auroraeosrose@gmail.com>                 |
      10              :   |          Swen Zanon <swen.zanon@geoglis.de>                          |
      11              :   |          Marcel Bolten <github@marcelbolten.de>                      |
      12              :   +----------------------------------------------------------------------+
      13              : */
      14              : 
      15              : #ifdef HAVE_CONFIG_H
      16              : #include "config.h"
      17              : #endif
      18              : 
      19              : #include "php.h"
      20              : #include <zend_exceptions.h>
      21              : #include <zend_gc.h>
      22              : 
      23              : #include "php_pango.h"
      24              : #include "matrix_arginfo.h"
      25              : 
      26              : zend_class_entry *ce_pango_matrix;
      27              : static zend_object_handlers pango_matrix_object_handlers;
      28              : 
      29          200 : pango_matrix_object *pango_matrix_fetch_object(zend_object *object)
      30              : {
      31          200 :     return (pango_matrix_object *) ((char*)(object) - XtOffsetOf(pango_matrix_object, std));
      32              : }
      33              : 
      34          144 : static inline double pango_matrix_get_property_default(zend_class_entry *ce, char * name) {
      35              :     zend_property_info *property_info;
      36          144 :     double value = 0.0;
      37          144 :     zend_string *key = zend_string_init(name, strlen(name), 0);
      38              : 
      39          144 :     property_info = zend_get_property_info(ce, key, 1);
      40          144 :     if (property_info) {
      41          144 :         zval *val = (zval*)((char*)ce->default_properties_table + property_info->offset - OBJ_PROP_TO_OFFSET(0));
      42          144 :         if (val) {
      43          144 :             value = zval_get_double(val);
      44              :         }
      45              :     }
      46              :     zend_string_release(key);
      47          144 :     return value;
      48              : }
      49              : 
      50          114 : static inline double pango_matrix_get_property_value(zend_object *object, char *name) {
      51              :     zval *prop, rv;
      52              : 
      53          114 :     prop = zend_read_property(object->ce, object, name, strlen(name), 1, &rv);
      54          114 :     return zval_get_double(prop);
      55              : }
      56              : 
      57              : #define PANGO_ALLOC_MATRIX(matrix_value) \
      58              :     if (!matrix_value) { \
      59              :         matrix_value = ecalloc(1, sizeof(PangoMatrix)); \
      60              :     }
      61              : 
      62              : #define PANGO_VALUE_FROM_STRUCT(n) \
      63              :     if (strcmp(member->val, #n) == 0) { \
      64              :         value = matrix_object->matrix->n; \
      65              :         break; \
      66              :     }
      67              : 
      68              : #define PANGO_VALUE_TO_STRUCT(n) \
      69              :     if (strcmp(member->val, #n) == 0) { \
      70              :         matrix_object->matrix->n = zval_get_double(value); \
      71              :         break; \
      72              :     }
      73              : 
      74              : #define PANGO_ADD_STRUCT_VALUE(n) \
      75              :     ZVAL_DOUBLE(&tmp, matrix_object->matrix->n); \
      76              :     zend_hash_str_update(props, #n, sizeof(#n)-1, &tmp);
      77              : 
      78              : /* ----------------------------------------------------------------
      79              :     Pango\Matrix C API
      80              : ------------------------------------------------------------------*/
      81              : 
      82              : /* {{{ */
      83            6 : PangoMatrix *pango_matrix_object_get_matrix(zval *zv)
      84              : {
      85            6 :     pango_matrix_object *matrix_object = Z_PANGO_MATRIX_P(zv);
      86              : 
      87            6 :     return matrix_object->matrix;
      88              : }
      89              : /* }}} */
      90              : 
      91            8 : zend_class_entry* php_pango_get_matrix_ce()
      92              : {
      93            8 :     return ce_pango_matrix;
      94              : }
      95              : 
      96              : /* ----------------------------------------------------------------
      97              :     Pango\Matrix Class API
      98              : ------------------------------------------------------------------*/
      99              : 
     100              : /* {{{ Matrix specifies a transformation between user-space and device coordinates */
     101           19 : PHP_METHOD(Pango_Matrix, __construct)
     102              : {
     103              :     pango_matrix_object *matrix_object;
     104           38 :     zend_object *object = Z_OBJ_P(getThis());
     105              : 
     106              :     /* read defaults from object */
     107           19 :     double xx = pango_matrix_get_property_value(object, "xx");
     108           19 :     double yx = pango_matrix_get_property_value(object, "yx");
     109           19 :     double xy = pango_matrix_get_property_value(object, "xy");
     110           19 :     double yy = pango_matrix_get_property_value(object, "yy");
     111           19 :     double x0 = pango_matrix_get_property_value(object, "x0");
     112           19 :     double y0 = pango_matrix_get_property_value(object, "y0");
     113              : 
     114           19 :     ZEND_PARSE_PARAMETERS_START(0, 6)
     115           18 :         Z_PARAM_OPTIONAL
     116           32 :         Z_PARAM_DOUBLE(xx)
     117           25 :         Z_PARAM_DOUBLE(yx)
     118           21 :         Z_PARAM_DOUBLE(xy)
     119           18 :         Z_PARAM_DOUBLE(yy)
     120           13 :         Z_PARAM_DOUBLE(x0)
     121            8 :         Z_PARAM_DOUBLE(y0)
     122           19 :     ZEND_PARSE_PARAMETERS_END();
     123              : 
     124           12 :     matrix_object = pango_matrix_fetch_object(object);
     125              : 
     126           12 :     matrix_object->matrix->xx = xx;
     127           12 :     matrix_object->matrix->yx = yx;
     128           12 :     matrix_object->matrix->xy = xy;
     129           12 :     matrix_object->matrix->yy = yy;
     130           12 :     matrix_object->matrix->x0 = x0;
     131           12 :     matrix_object->matrix->y0 = y0;
     132              : }
     133              : /* }}} */
     134              : 
     135              : /* {{{ Changes the transformation represented by matrix to be the transformation
     136              :        given by first translating by (tx, ty) then applying the original transformation. */
     137            6 : PHP_METHOD(Pango_Matrix, translate)
     138              : {
     139            6 :     double tx = 0.0, ty = 0.0;
     140              :     pango_matrix_object *matrix_object;
     141              : 
     142            6 :     ZEND_PARSE_PARAMETERS_START(2, 2)
     143            6 :         Z_PARAM_DOUBLE(tx)
     144            4 :         Z_PARAM_DOUBLE(ty)
     145            6 :     ZEND_PARSE_PARAMETERS_END();
     146              : 
     147            2 :     matrix_object = Z_PANGO_MATRIX_P(getThis());
     148              : 
     149            1 :     pango_matrix_translate(matrix_object->matrix, tx, ty);
     150              : }
     151              : /* }}} */
     152              : 
     153              : /* {{{ Changes the transformation represented by matrix to be the transformation
     154              :        given by first scaling by sx in the X direction and sy in the Y direction
     155              :        then applying the original transformation. */
     156            3 : PHP_METHOD(Pango_Matrix, scale)
     157              : {
     158            3 :     double sx = 0.0, sy = 0.0;
     159              :     pango_matrix_object *matrix_object;
     160              : 
     161            3 :     ZEND_PARSE_PARAMETERS_START(2, 2)
     162            6 :         Z_PARAM_DOUBLE(sx)
     163            6 :         Z_PARAM_DOUBLE(sy)
     164            3 :     ZEND_PARSE_PARAMETERS_END();
     165              : 
     166            6 :     matrix_object = Z_PANGO_MATRIX_P(getThis());
     167              : 
     168            3 :     pango_matrix_scale(matrix_object->matrix, sx, sy);
     169              : }
     170              : /* }}} */
     171              : 
     172              : /* {{{ Changes the transformation represented by matrix to be the transformation
     173              :        given by first rotating by degrees degrees counter-clockwise
     174              :        then applying the original transformation. */
     175            5 : PHP_METHOD(Pango_Matrix, rotate)
     176              : {
     177            5 :     double degrees = 0.0;
     178              :     pango_matrix_object *matrix_object;
     179              : 
     180            5 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     181            6 :         Z_PARAM_DOUBLE(degrees)
     182            5 :     ZEND_PARSE_PARAMETERS_END();
     183              : 
     184            4 :     matrix_object = Z_PANGO_MATRIX_P(getThis());
     185              : 
     186            2 :     pango_matrix_rotate(matrix_object->matrix, degrees);
     187              : }
     188              : /* }}} */
     189              : 
     190              : 
     191              : /* {{{ Transforms the distance vector (dx,dy) by matrix.
     192              :        This is similar to pango_matrix_transform_point(), except that
     193              :        the translation components of the transformation are ignored. */
     194            6 : PHP_METHOD(Pango_Matrix, transformDistance)
     195              : {
     196            6 :     double dx = 0.0, dy = 0.0;
     197              :     pango_matrix_object *matrix_object;
     198              : 
     199            6 :     ZEND_PARSE_PARAMETERS_START(2, 2)
     200            6 :         Z_PARAM_DOUBLE(dx)
     201            4 :         Z_PARAM_DOUBLE(dy)
     202            6 :     ZEND_PARSE_PARAMETERS_END();
     203              : 
     204            2 :     matrix_object = Z_PANGO_MATRIX_P(getThis());
     205              : 
     206            1 :     pango_matrix_transform_distance(matrix_object->matrix, &dx, &dy);
     207              : 
     208            1 :     array_init(return_value);
     209            1 :     add_assoc_double(return_value, "x", dx);
     210            1 :     add_assoc_double(return_value, "y", dy);
     211              : }
     212              : /* }}} */
     213              : 
     214              : /* {{{ */
     215            4 : PHP_METHOD(Pango_Matrix, transformPixelRectangle)
     216              : {
     217              :     zval *rectangle_zv;
     218              :     PangoRectangle rect;
     219              : 
     220            4 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     221            4 :         Z_PARAM_OBJECT_OF_CLASS(rectangle_zv, php_pango_get_rectangle_ce())
     222            4 :     ZEND_PARSE_PARAMETERS_END();
     223              : 
     224            1 :     rect = *pango_rectangle_object_get_rectangle(rectangle_zv);
     225              : 
     226            1 :     pango_matrix_transform_pixel_rectangle(
     227            2 :         pango_matrix_object_get_matrix(getThis()),
     228              :         &rect
     229              :     );
     230              : 
     231            1 :     object_init_ex(return_value, php_pango_get_rectangle_ce());
     232            1 :     *pango_rectangle_object_get_rectangle(return_value) = rect;
     233              : }
     234              : /* }}} */
     235              : 
     236              : /* {{{ Transforms the point (x, y) by matrix. */
     237            6 : PHP_METHOD(Pango_Matrix, transformPoint)
     238              : {
     239            6 :     double x = 0.0, y = 0.0;
     240              :     pango_matrix_object *matrix_object;
     241              : 
     242            6 :     ZEND_PARSE_PARAMETERS_START(2, 2)
     243            6 :         Z_PARAM_DOUBLE(x)
     244            4 :         Z_PARAM_DOUBLE(y)
     245            6 :     ZEND_PARSE_PARAMETERS_END();
     246              : 
     247            2 :     matrix_object = Z_PANGO_MATRIX_P(getThis());
     248              : 
     249            1 :     pango_matrix_transform_point(matrix_object->matrix, &x, &y);
     250              : 
     251            1 :     array_init(return_value);
     252            1 :     add_assoc_double(return_value, "x", x);
     253            1 :     add_assoc_double(return_value, "y", y);
     254              : }
     255              : /* }}} */
     256              : 
     257              : /* {{{ */
     258            5 : PHP_METHOD(Pango_Matrix, transformRectangle)
     259              : {
     260              :     zval *rectangle_zv;
     261              :     PangoRectangle rect;
     262              : 
     263            5 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     264            6 :         Z_PARAM_OBJECT_OF_CLASS(rectangle_zv, php_pango_get_rectangle_ce())
     265            5 :     ZEND_PARSE_PARAMETERS_END();
     266              : 
     267            2 :     rect = *pango_rectangle_object_get_rectangle(rectangle_zv);
     268              : 
     269            2 :     pango_matrix_transform_rectangle(
     270            4 :         pango_matrix_object_get_matrix(getThis()),
     271              :         &rect
     272              :     );
     273              : 
     274            2 :     object_init_ex(return_value, php_pango_get_rectangle_ce());
     275            2 :     *pango_rectangle_object_get_rectangle(return_value) = rect;
     276              : }
     277              : /* }}} */
     278              : 
     279              : /* ----------------------------------------------------------------
     280              :     Pango\Matrix Object management
     281              : ------------------------------------------------------------------*/
     282              : 
     283              : /* {{{ */
     284           24 : static void pango_matrix_free_obj(zend_object *object)
     285              : {
     286           24 :     pango_matrix_object *intern = pango_matrix_fetch_object(object);
     287              : 
     288           24 :     if (!intern) {
     289            0 :         return;
     290              :     }
     291              : 
     292           24 :     if (intern->matrix) {
     293           24 :         efree(intern->matrix);
     294           24 :         intern->matrix = NULL;
     295              :     }
     296              : 
     297           24 :     zend_object_std_dtor(&intern->std);
     298              : }
     299              : /* }}} */
     300              : 
     301              : /* {{{ */
     302           24 : static zend_object* pango_matrix_obj_ctor(zend_class_entry *ce, pango_matrix_object **intern)
     303              : {
     304           24 :     pango_matrix_object *object = ecalloc(1, sizeof(pango_matrix_object) + zend_object_properties_size(ce));
     305           24 :     PANGO_ALLOC_MATRIX(object->matrix);
     306              : 
     307           24 :     zend_object_std_init(&object->std, ce);
     308           24 :     object->std.handlers = &pango_matrix_object_handlers;
     309           24 :     *intern = object;
     310              : 
     311              :     /* We need to read in any default values and set them if applicable
     312              :        xx, yx, xy, yy, x0, y0
     313              :      */
     314           24 :     if (ce->default_properties_count) {
     315           24 :         object->matrix->xx = pango_matrix_get_property_default(ce, "xx");
     316           24 :         object->matrix->yx = pango_matrix_get_property_default(ce, "yx");
     317           24 :         object->matrix->xy = pango_matrix_get_property_default(ce, "xy");
     318           24 :         object->matrix->yy = pango_matrix_get_property_default(ce, "yy");
     319           24 :         object->matrix->x0 = pango_matrix_get_property_default(ce, "x0");
     320           24 :         object->matrix->y0 = pango_matrix_get_property_default(ce, "y0");
     321              :     }
     322              : 
     323           24 :     return &object->std;
     324              : }
     325              : /* }}} */
     326              : 
     327              : /* {{{ */
     328           23 : static zend_object* pango_matrix_create_object(zend_class_entry *ce)
     329              : {
     330           23 :     pango_matrix_object *intern = NULL;
     331           23 :     zend_object *return_value = pango_matrix_obj_ctor(ce, &intern);
     332              : 
     333           23 :     object_properties_init(&intern->std, ce);
     334           23 :     return return_value;
     335              : }
     336              : /* }}} */
     337              : 
     338              : /* {{{ */
     339            1 : static zend_object* pango_matrix_clone_obj(zend_object *zobj)
     340              : {
     341              :     pango_matrix_object *new_matrix;
     342            1 :     pango_matrix_object *old_matrix = pango_matrix_fetch_object(zobj);
     343            1 :     zend_object *return_value = pango_matrix_obj_ctor(zobj->ce, &new_matrix);
     344            1 :     PANGO_ALLOC_MATRIX(new_matrix->matrix);
     345              : 
     346              :     // init new matrix values from old matrix
     347            1 :     new_matrix->matrix->xx = old_matrix->matrix->xx;
     348            1 :     new_matrix->matrix->yx = old_matrix->matrix->yx;
     349            1 :     new_matrix->matrix->xy = old_matrix->matrix->xy;
     350            1 :     new_matrix->matrix->yy = old_matrix->matrix->yy;
     351            1 :     new_matrix->matrix->x0 = old_matrix->matrix->x0;
     352            1 :     new_matrix->matrix->y0 = old_matrix->matrix->y0;
     353              : 
     354            1 :     zend_objects_clone_members(&new_matrix->std, &old_matrix->std);
     355              : 
     356            1 :     return return_value;
     357              : }
     358              : /* }}} */
     359              : 
     360              : /* {{{ */
     361          128 : static zval *pango_matrix_object_read_property(zend_object *object, zend_string *member, int type, void **cache_slot, zval *rv)
     362              : {
     363              :     zval *retval;
     364              :     double value;
     365          128 :     pango_matrix_object *matrix_object = pango_matrix_fetch_object(object);
     366              : 
     367          128 :     if (!matrix_object) {
     368            0 :         return rv;
     369              :     }
     370              : 
     371              :     do {
     372          128 :         PANGO_VALUE_FROM_STRUCT(xx);
     373          105 :         PANGO_VALUE_FROM_STRUCT(yx);
     374           84 :         PANGO_VALUE_FROM_STRUCT(xy);
     375           63 :         PANGO_VALUE_FROM_STRUCT(yy);
     376           42 :         PANGO_VALUE_FROM_STRUCT(x0);
     377           21 :         PANGO_VALUE_FROM_STRUCT(y0);
     378              : 
     379              :         /* not a struct member */
     380            0 :         retval = (zend_get_std_object_handlers())->read_property(object, member, type, cache_slot, rv);
     381              : 
     382            0 :         return retval;
     383              :     } while(0);
     384              : 
     385          128 :     retval = rv;
     386          128 :     ZVAL_DOUBLE(retval, value);
     387              : 
     388          128 :     return retval;
     389              : }
     390              : /* }}} */
     391              : 
     392              : /* {{{ */
     393            7 : static zval *pango_matrix_object_write_property(zend_object *object, zend_string *member, zval *value, void **cache_slot)
     394              : {
     395            7 :     pango_matrix_object *matrix_object = pango_matrix_fetch_object(object);
     396            7 :     zval *retval = NULL;
     397              : 
     398            7 :     if (!matrix_object) {
     399            0 :         return retval;
     400              :     }
     401              : 
     402              :     do {
     403            9 :         PANGO_VALUE_TO_STRUCT(xx);
     404            6 :         PANGO_VALUE_TO_STRUCT(yx);
     405            5 :         PANGO_VALUE_TO_STRUCT(xy);
     406            4 :         PANGO_VALUE_TO_STRUCT(yy);
     407            3 :         PANGO_VALUE_TO_STRUCT(x0);
     408            2 :         PANGO_VALUE_TO_STRUCT(y0);
     409              : 
     410              :         /* not a struct member */
     411            0 :         retval = (zend_get_std_object_handlers())->write_property(object, member, value, cache_slot);
     412              :     } while(0);
     413              : 
     414            7 :     return retval;
     415              : }
     416              : /* }}} */
     417              : 
     418              : /* {{{ */
     419           14 : static HashTable *pango_matrix_object_get_properties(zend_object *object)
     420              : {
     421              :     HashTable *props;
     422              :     // used in PANGO_ADD_STRUCT_VALUE below
     423              :     zval tmp;
     424           14 :     pango_matrix_object *matrix_object = pango_matrix_fetch_object(object);
     425              : 
     426           14 :     props = zend_std_get_properties(object);
     427              : 
     428           14 :     if (!matrix_object->matrix) {
     429            0 :         return props;
     430              :     }
     431              : 
     432              :     /* Don't add struct values when destructor calls get_properties handler */
     433           28 :     if (props && GC_REFCOUNT(props) > 0) {
     434           14 :         PANGO_ADD_STRUCT_VALUE(xx);
     435           14 :         PANGO_ADD_STRUCT_VALUE(yx);
     436           14 :         PANGO_ADD_STRUCT_VALUE(xy);
     437           14 :         PANGO_ADD_STRUCT_VALUE(yy);
     438           14 :         PANGO_ADD_STRUCT_VALUE(x0);
     439           14 :         PANGO_ADD_STRUCT_VALUE(y0);
     440              :     }
     441              : 
     442           14 :     return props;
     443              : }
     444              : /* }}} */
     445              : 
     446              : /* ----------------------------------------------------------------
     447              :     Pango\Matrix Definition and registration
     448              : ------------------------------------------------------------------*/
     449              : 
     450              : /* {{{ PHP_MINIT_FUNCTION */
     451          194 : PHP_MINIT_FUNCTION(pango_matrix)
     452              : {
     453          194 :     memcpy(
     454              :         &pango_matrix_object_handlers,
     455              :         zend_get_std_object_handlers(),
     456              :         sizeof(zend_object_handlers)
     457              :     );
     458              : 
     459          194 :     pango_matrix_object_handlers.offset = XtOffsetOf(pango_matrix_object, std);
     460          194 :     pango_matrix_object_handlers.free_obj = pango_matrix_free_obj;
     461          194 :     pango_matrix_object_handlers.clone_obj = pango_matrix_clone_obj;
     462          194 :     pango_matrix_object_handlers.read_property = pango_matrix_object_read_property;
     463          194 :     pango_matrix_object_handlers.write_property = pango_matrix_object_write_property;
     464          194 :     pango_matrix_object_handlers.get_property_ptr_ptr = NULL;
     465          194 :     pango_matrix_object_handlers.get_properties = pango_matrix_object_get_properties;
     466              : 
     467          194 :     ce_pango_matrix = register_class_Pango_Matrix();
     468          194 :     ce_pango_matrix->create_object = pango_matrix_create_object;
     469              : 
     470          194 :     return SUCCESS;
     471              : }
     472              : /* }}} */
        

Generated by: LCOV version 2.0-1