Line data Source code
1 : /*
2 : +----------------------------------------------------------------------+
3 : | For PHP Version 8 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 2022 Swen Zanon |
6 : +----------------------------------------------------------------------+
7 : | http://www.opensource.org/licenses/mit-license.php MIT License |
8 : | Also available in LICENSE |
9 : +----------------------------------------------------------------------+
10 : | Authors: Swen Zanon <swen.zanon@geoglis.de> |
11 : +----------------------------------------------------------------------+
12 : */
13 :
14 : #ifdef HAVE_CONFIG_H
15 : #include "config.h"
16 : #endif
17 :
18 : #include <cairo.h>
19 : #include <php.h>
20 : #include <zend_exceptions.h>
21 :
22 : #include "php_cairo.h"
23 : #include "php_cairo_internal.h"
24 : #include "text_cluster_arginfo.h"
25 :
26 : zend_class_entry *ce_cairo_text_cluster;
27 :
28 : static zend_object_handlers cairo_text_cluster_object_handlers;
29 :
30 105 : cairo_text_cluster_object *cairo_text_cluster_fetch_object(zend_object *object)
31 : {
32 105 : return (cairo_text_cluster_object *) ((char*)(object) - XtOffsetOf(cairo_text_cluster_object, std));
33 : }
34 :
35 90 : static inline long cairo_text_cluster_get_property_default(zend_class_entry *ce, char * name) {
36 : zend_property_info *property_info;
37 90 : long value = 0;
38 90 : zend_string *key = zend_string_init(name, strlen(name), 0);
39 :
40 90 : property_info = zend_get_property_info(ce, key, 1);
41 90 : if (property_info) {
42 90 : zval *val = (zval*)((char*)ce->default_properties_table + property_info->offset - OBJ_PROP_TO_OFFSET(0));
43 90 : if (val) {
44 90 : value = zval_get_long(val);
45 : }
46 : }
47 : zend_string_release(key);
48 90 : return value;
49 : }
50 :
51 : #define CAIRO_ALLOC_TEXT_CLUSTER(text_cluster_value) if (!text_cluster_value) \
52 : { text_cluster_value = ecalloc(1, sizeof(cairo_text_cluster_t)); }
53 :
54 : #define CAIRO_VALUE_FROM_STRUCT(n) \
55 : if (strcmp(member->val, #n) == 0) { \
56 : value = text_cluster_object->text_cluster->n; \
57 : break; \
58 : }
59 :
60 : #define CAIRO_VALUE_TO_STRUCT(n) \
61 : if (strcmp(member->val, #n) == 0) { \
62 : text_cluster_object->text_cluster->n = zval_get_long(value); \
63 : break; \
64 : }
65 :
66 : #define CAIRO_ADD_STRUCT_VALUE(n) \
67 : ZVAL_LONG(&tmp, text_cluster_object->text_cluster->n); \
68 : zend_hash_str_update(props, #n, sizeof(#n)-1, &tmp);
69 :
70 : /* ----------------------------------------------------------------
71 : \Cairo\TextCluster C API
72 : ------------------------------------------------------------------*/
73 :
74 : /* {{{ */
75 6 : cairo_text_cluster_t *cairo_text_cluster_object_get_text_cluster(zval *zv)
76 : {
77 6 : cairo_text_cluster_object *text_cluster_object = Z_CAIRO_TEXT_CLUSTER_P(zv);
78 :
79 6 : return text_cluster_object->text_cluster;
80 : }
81 : /* }}} */
82 :
83 34 : zend_class_entry* php_cairo_get_text_cluster_ce()
84 : {
85 34 : return ce_cairo_text_cluster;
86 : }
87 :
88 : /* ----------------------------------------------------------------
89 : \Cairo\TextCluster Class API
90 : ------------------------------------------------------------------*/
91 :
92 : /* {{{ proto void __construct(int num_bytes, int num_glyphs)
93 : Creates a new text_cluster with the properties populated */
94 10 : PHP_METHOD(Cairo_TextCluster, __construct)
95 : {
96 : cairo_text_cluster_object *text_cluster_object;
97 :
98 : /* read defaults from object */
99 : long num_bytes;
100 : long num_glyphs;
101 :
102 : /* Now allow constructor to overwrite them if desired */
103 10 : ZEND_PARSE_PARAMETERS_START(2, 2)
104 14 : Z_PARAM_LONG(num_bytes)
105 12 : Z_PARAM_LONG(num_glyphs)
106 10 : ZEND_PARSE_PARAMETERS_END();
107 :
108 10 : text_cluster_object = Z_CAIRO_TEXT_CLUSTER_P(getThis());
109 :
110 5 : text_cluster_object->text_cluster->num_bytes = num_bytes;
111 5 : text_cluster_object->text_cluster->num_glyphs = num_glyphs;
112 : }
113 : /* }}} */
114 :
115 : /* ----------------------------------------------------------------
116 : \Cairo\TextCluster Object management
117 : ------------------------------------------------------------------*/
118 :
119 : /* {{{ */
120 45 : static void cairo_text_cluster_free_obj(zend_object *zobj)
121 : {
122 45 : cairo_text_cluster_object *intern = cairo_text_cluster_fetch_object(zobj);
123 :
124 45 : if (!intern) {
125 0 : return;
126 : }
127 :
128 45 : if (intern->text_cluster) {
129 45 : efree(intern->text_cluster);
130 45 : intern->text_cluster = NULL;
131 : }
132 :
133 45 : zend_object_std_dtor(&intern->std);
134 : }
135 : /* }}} */
136 :
137 : /* {{{ */
138 45 : static zend_object* cairo_text_cluster_obj_ctor(zend_class_entry *ce, cairo_text_cluster_object **intern)
139 : {
140 45 : cairo_text_cluster_object *object = ecalloc(1, sizeof(cairo_text_cluster_object) + zend_object_properties_size(ce));
141 45 : CAIRO_ALLOC_TEXT_CLUSTER(object->text_cluster);
142 :
143 45 : zend_object_std_init(&object->std, ce);
144 :
145 45 : object->std.handlers = &cairo_text_cluster_object_handlers;
146 45 : *intern = object;
147 :
148 : /* We need to read in any default values and set them if applicable */
149 45 : if (ce->default_properties_count) {
150 45 : object->text_cluster->num_bytes = cairo_text_cluster_get_property_default(ce, "num_bytes");
151 45 : object->text_cluster->num_glyphs = cairo_text_cluster_get_property_default(ce, "num_glyphs");
152 : }
153 :
154 45 : return &object->std;
155 : }
156 : /* }}} */
157 :
158 : /* {{{ */
159 44 : static zend_object* cairo_text_cluster_create_object(zend_class_entry *ce)
160 : {
161 44 : cairo_text_cluster_object *intern = NULL;
162 44 : zend_object *return_value = cairo_text_cluster_obj_ctor(ce, &intern);
163 :
164 44 : object_properties_init(&intern->std, ce);
165 44 : return return_value;
166 : }
167 : /* }}} */
168 :
169 : /* {{{ */
170 1 : static zend_object* cairo_text_cluster_clone_obj(zend_object *zobj)
171 : {
172 : cairo_text_cluster_object *new_text_cluster;
173 1 : cairo_text_cluster_object *old_text_cluster = cairo_text_cluster_fetch_object(zobj);
174 1 : zend_object *return_value = cairo_text_cluster_obj_ctor(zobj->ce, &new_text_cluster);
175 1 : CAIRO_ALLOC_TEXT_CLUSTER(new_text_cluster->text_cluster);
176 :
177 1 : new_text_cluster->text_cluster->num_bytes = old_text_cluster->text_cluster->num_bytes;
178 1 : new_text_cluster->text_cluster->num_glyphs = old_text_cluster->text_cluster->num_glyphs;
179 :
180 1 : zend_objects_clone_members(&new_text_cluster->std, &old_text_cluster->std);
181 :
182 1 : return return_value;
183 : }
184 : /* }}} */
185 :
186 : /* {{{ */
187 5 : static zval *cairo_text_cluster_object_read_property(zend_object *zobj, zend_string *member, int type, void **cache_slot, zval *rv)
188 : {
189 : zval *retval;
190 : long value;
191 5 : cairo_text_cluster_object *text_cluster_object = cairo_text_cluster_fetch_object(zobj);
192 :
193 5 : if (!text_cluster_object) {
194 0 : return rv;
195 : }
196 :
197 : do {
198 5 : CAIRO_VALUE_FROM_STRUCT(num_bytes);
199 3 : CAIRO_VALUE_FROM_STRUCT(num_glyphs);
200 :
201 : // not a struct member
202 1 : retval = (zend_get_std_object_handlers())->read_property(zobj, member, type, cache_slot, rv);
203 :
204 1 : return retval;
205 : } while(0);
206 :
207 4 : retval = rv;
208 4 : ZVAL_LONG(retval, value);
209 :
210 4 : return retval;
211 : }
212 : /* }}} */
213 :
214 : /* {{{ */
215 5 : static zval *cairo_text_cluster_object_write_property(zend_object *zobj, zend_string *member, zval *value, void **cache_slot)
216 : {
217 5 : cairo_text_cluster_object *text_cluster_object = cairo_text_cluster_fetch_object(zobj);
218 5 : zval *retval = NULL;
219 :
220 5 : if (!text_cluster_object) {
221 0 : return retval;
222 : }
223 :
224 : do {
225 7 : CAIRO_VALUE_TO_STRUCT(num_bytes);
226 5 : CAIRO_VALUE_TO_STRUCT(num_glyphs);
227 : } while(0);
228 :
229 : // not a struct member
230 5 : retval = (zend_get_std_object_handlers())->write_property(zobj, member, value, cache_slot);
231 :
232 5 : return retval;
233 : }
234 : /* }}} */
235 :
236 : /* {{{ */
237 4 : static HashTable *cairo_text_cluster_object_get_properties(zend_object *zobj)
238 : {
239 : HashTable *props;
240 : // used in CAIRO_ADD_STRUCT_VALUE below
241 : zval tmp;
242 4 : cairo_text_cluster_object *text_cluster_object = cairo_text_cluster_fetch_object(zobj);
243 :
244 4 : props = zend_std_get_properties(zobj);
245 :
246 4 : if (!text_cluster_object->text_cluster) {
247 0 : return props;
248 : }
249 :
250 4 : CAIRO_ADD_STRUCT_VALUE(num_bytes);
251 4 : CAIRO_ADD_STRUCT_VALUE(num_glyphs);
252 :
253 4 : return props;
254 : }
255 : /* }}} */
256 :
257 : /* ----------------------------------------------------------------
258 : \Cairo\TextCluster Definition and registration
259 : ------------------------------------------------------------------*/
260 :
261 : /* {{{ PHP_MINIT_FUNCTION */
262 424 : PHP_MINIT_FUNCTION(cairo_text_cluster)
263 : {
264 : zend_class_entry ce;
265 :
266 424 : memcpy(
267 : &cairo_text_cluster_object_handlers,
268 : zend_get_std_object_handlers(),
269 : sizeof(zend_object_handlers)
270 : );
271 :
272 424 : cairo_text_cluster_object_handlers.offset = XtOffsetOf(cairo_text_cluster_object, std);
273 424 : cairo_text_cluster_object_handlers.free_obj = cairo_text_cluster_free_obj;
274 424 : cairo_text_cluster_object_handlers.clone_obj = cairo_text_cluster_clone_obj;
275 424 : cairo_text_cluster_object_handlers.read_property = cairo_text_cluster_object_read_property;
276 424 : cairo_text_cluster_object_handlers.write_property = cairo_text_cluster_object_write_property;
277 424 : cairo_text_cluster_object_handlers.get_property_ptr_ptr = NULL;
278 424 : cairo_text_cluster_object_handlers.get_properties = cairo_text_cluster_object_get_properties;
279 :
280 424 : ce_cairo_text_cluster = register_class_Cairo_TextCluster();
281 424 : ce_cairo_text_cluster->create_object = cairo_text_cluster_create_object;
282 :
283 424 : return SUCCESS;
284 : }
285 : /* }}} */
|