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