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