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