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 "image_surface_arginfo.h"
26 :
27 : zend_class_entry *ce_cairo_imagesurface;
28 : zend_class_entry *ce_cairo_format;
29 :
30 : /* ----------------------------------------------------------------
31 : \Cairo\TextCluster C API
32 : ------------------------------------------------------------------*/
33 :
34 4 : zend_class_entry* php_cairo_get_imagesurface_ce()
35 : {
36 4 : return ce_cairo_imagesurface;
37 : }
38 :
39 :
40 : /* ----------------------------------------------------------------
41 : Cairo\ImageSurface Class API
42 : ------------------------------------------------------------------*/
43 :
44 : /* {{{ proto void __construct(int format, int width, int height)
45 : Creates an image surface of the specified format and dimensions.
46 : Initially the surface contents are set to 0. */
47 151 : PHP_METHOD(Cairo_Surface_Image, __construct)
48 : {
49 : zend_long width, height;
50 : cairo_surface_object *surface_object;
51 : zval *format_case;
52 :
53 151 : ZEND_PARSE_PARAMETERS_START(3, 3)
54 294 : Z_PARAM_OBJECT_OF_CLASS(format_case, ce_cairo_format)
55 292 : Z_PARAM_LONG(width)
56 290 : Z_PARAM_LONG(height)
57 151 : ZEND_PARSE_PARAMETERS_END();
58 :
59 288 : surface_object = Z_CAIRO_SURFACE_P(getThis());
60 144 : if (!surface_object) {
61 0 : RETURN_NULL();
62 : }
63 :
64 432 : surface_object->surface = cairo_image_surface_create(
65 288 : Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(format_case))),
66 : width,
67 : height
68 : );
69 144 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
70 0 : RETURN_THROWS();
71 : }
72 : }
73 : /* }}} */
74 :
75 : /* {{{ proto \Cairo\Surface\Image Object \Cairo\Surface\Image::createForData(string data, Cairo\Surface\ImageFormat format, int width, int height, int stride)
76 : Creates an image surface for the provided pixel data. */
77 12 : PHP_METHOD(Cairo_Surface_Image, createForData)
78 : {
79 : /* NOTE: we have to keep the data buffer around, so we put it in the cairo_surface_object */
80 : char *data;
81 : size_t data_len;
82 12 : zend_long format, width, height, stride = -1;
83 : cairo_surface_object *surface_object;
84 : zval *format_case;
85 :
86 12 : ZEND_PARSE_PARAMETERS_START(4, 4)
87 14 : Z_PARAM_STRING(data, data_len)
88 12 : Z_PARAM_OBJECT_OF_CLASS(format_case, ce_cairo_format)
89 10 : Z_PARAM_LONG(width)
90 8 : Z_PARAM_LONG(height)
91 12 : ZEND_PARSE_PARAMETERS_END();
92 :
93 3 : format = Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(format_case)));
94 :
95 3 : if (width < 1 || height < 1) {
96 2 : zend_throw_exception(ce_cairo_exception, "Cairo\\Surface\\Image::createForData(): invalid surface dimensions. Arguments #3 ($width) and #4 ($height) must be positive integers.", 0);
97 2 : RETURN_THROWS();
98 : }
99 :
100 : /* Figure out our stride */
101 : /* This is the way the stride SHOULD be done */
102 1 : stride = cairo_format_stride_for_width(format, width);
103 :
104 1 : if (stride <= 0) {
105 0 : zend_throw_exception(ce_cairo_exception, "Could not calculate stride for surface in Cairo\\Surface\\Image::createForData().Argument #3 ($width) might be too large.", 0);
106 0 : RETURN_THROWS();
107 : }
108 :
109 : /* Create the object, stick in the buffer and surface, check our status */
110 1 : object_init_ex(return_value, ce_cairo_imagesurface);
111 1 : surface_object = Z_CAIRO_SURFACE_P(return_value);
112 1 : if (!surface_object) {
113 0 : RETURN_NULL();
114 : }
115 :
116 : /* allocate our internal surface object buffer - has to be left lying around until we destroy the image */
117 1 : surface_object->buffer = safe_emalloc(stride * height, sizeof(char), 0);
118 :
119 1 : if (surface_object->buffer == NULL) {
120 0 : zend_throw_exception(ce_cairo_exception, "Cairo\\Surface\\Image::createForData(): Could not allocate memory for buffer", 0);
121 0 : RETURN_THROWS();
122 : }
123 :
124 : /* copy our data into the buffer */
125 1 : memcpy(
126 1 : surface_object->buffer,
127 : data,
128 : data_len
129 : );
130 :
131 : /* create our surface and check for errors */
132 2 : surface_object->surface = cairo_image_surface_create_for_data(
133 1 : (unsigned char*)surface_object->buffer,
134 : format, width, height, stride
135 : );
136 1 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
137 0 : RETURN_THROWS();
138 : }
139 : }
140 : /* }}} */
141 :
142 : /* {{{ proto string \Cairo\Surface\Image->getData()
143 : Get the string data of the image surface, for direct inspection or modification */
144 2 : PHP_METHOD(Cairo_Surface_Image, getData)
145 : {
146 : cairo_surface_object *surface_object;
147 : unsigned char *data;
148 : zend_long height, stride;
149 :
150 2 : ZEND_PARSE_PARAMETERS_NONE();
151 :
152 2 : surface_object = cairo_surface_object_get(getThis());
153 1 : if (!surface_object) {
154 0 : RETURN_THROWS();
155 : }
156 :
157 1 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
158 0 : RETURN_THROWS();
159 : }
160 :
161 1 : data = cairo_image_surface_get_data(surface_object->surface);
162 1 : height = cairo_image_surface_get_height(surface_object->surface);
163 1 : stride = cairo_image_surface_get_stride(surface_object->surface);
164 :
165 2 : RETURN_STRINGL(data, height * stride);
166 : }
167 : /* }}} */
168 :
169 : /* {{{ proto int \Cairo\Surface\Image->getFormat()
170 : Get the format of the surface */
171 2 : PHP_METHOD(Cairo_Surface_Image, getFormat)
172 : {
173 : cairo_surface_object *surface_object;
174 : zval format_case;
175 :
176 3 : ZEND_PARSE_PARAMETERS_NONE();
177 :
178 2 : surface_object = cairo_surface_object_get(getThis());
179 1 : if (!surface_object) {
180 0 : RETURN_THROWS();
181 : }
182 :
183 1 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
184 0 : RETURN_THROWS();
185 : }
186 :
187 1 : format_case = php_enum_from_cairo_c_enum(
188 : ce_cairo_format,
189 1 : cairo_image_surface_get_format(surface_object->surface)
190 : );
191 :
192 1 : if (Z_TYPE(format_case) == IS_OBJECT) {
193 2 : RETURN_ZVAL(&format_case, 1, 1);
194 : }
195 : }
196 : /* }}} */
197 :
198 : /* {{{ proto int \Cairo\Surface\Image->getWidth()
199 : Get the width of the image surface in pixels. */
200 2 : PHP_METHOD(Cairo_Surface_Image, getWidth)
201 : {
202 : cairo_surface_object *surface_object;
203 :
204 2 : ZEND_PARSE_PARAMETERS_NONE();
205 :
206 2 : surface_object = cairo_surface_object_get(getThis());
207 1 : if (!surface_object) {
208 0 : RETURN_THROWS();
209 : }
210 :
211 1 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
212 0 : RETURN_THROWS();
213 : }
214 :
215 1 : RETURN_LONG(cairo_image_surface_get_width(surface_object->surface));
216 : }
217 : /* }}} */
218 :
219 : /* {{{ proto int \Cairo\Surface\Image->getHeight()
220 : Get the height of the image surface in pixels. */
221 2 : PHP_METHOD(Cairo_Surface_Image, getHeight)
222 : {
223 : cairo_surface_object *surface_object;
224 :
225 2 : ZEND_PARSE_PARAMETERS_NONE();
226 :
227 2 : surface_object = cairo_surface_object_get(getThis());
228 1 : if (!surface_object) {
229 0 : RETURN_THROWS();
230 : }
231 :
232 1 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
233 0 : RETURN_THROWS();
234 : }
235 :
236 1 : RETURN_LONG(cairo_image_surface_get_height(surface_object->surface));
237 : }
238 : /* }}} */
239 :
240 : /* {{{ proto int \Cairo\Surface\Image->getStride()
241 : Get the stride of the image surface in bytes */
242 2 : PHP_METHOD(Cairo_Surface_Image, getStride)
243 : {
244 : cairo_surface_object *surface_object;
245 :
246 2 : ZEND_PARSE_PARAMETERS_NONE();
247 :
248 2 : surface_object = cairo_surface_object_get(getThis());
249 1 : if (!surface_object) {
250 0 : RETURN_THROWS();
251 : }
252 :
253 1 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
254 0 : RETURN_THROWS();
255 : }
256 :
257 1 : RETURN_LONG(cairo_image_surface_get_stride(surface_object->surface));
258 : }
259 : /* }}} */
260 :
261 : #ifdef CAIRO_HAS_PNG_FUNCTIONS
262 : /* {{{ proto \Cairo\Surface\Image object \Cairo\Surface\Image::createFromPng(file|resource file)
263 : Creates a new image surface and initializes the contents to the given PNG file. */
264 5 : PHP_METHOD(Cairo_Surface_Image, createFromPng)
265 : {
266 : cairo_surface_object *surface_object;
267 5 : zval *stream_zval = NULL;
268 : stream_closure *closure;
269 5 : bool owned_stream = false;
270 5 : php_stream *stream = NULL;
271 :
272 5 : ZEND_PARSE_PARAMETERS_START(1, 1)
273 3 : Z_PARAM_ZVAL(stream_zval)
274 6 : ZEND_PARSE_PARAMETERS_END();
275 :
276 3 : object_init_ex(return_value, ce_cairo_imagesurface);
277 3 : surface_object = Z_CAIRO_SURFACE_P(return_value);
278 :
279 6 : if (Z_TYPE_P(stream_zval) == IS_STRING) {
280 1 : surface_object->surface = cairo_image_surface_create_from_png(Z_STRVAL_P(stream_zval));
281 4 : } else if (Z_TYPE_P(stream_zval) == IS_RESOURCE) {
282 1 : php_stream_from_zval(stream, stream_zval);
283 :
284 1 : if (!stream) {
285 0 : RETURN_NULL();
286 : }
287 :
288 : // Pack stream into struct
289 1 : closure = ecalloc(1, sizeof(stream_closure));
290 1 : closure->stream = stream;
291 1 : closure->owned_stream = owned_stream;
292 :
293 1 : surface_object->closure = closure;
294 1 : surface_object->surface = cairo_image_surface_create_from_png_stream((cairo_read_func_t) php_cairo_read_func, (void *)closure);
295 : } else {
296 1 : zend_throw_exception(ce_cairo_exception, "Cairo\\Surface\\Image::createFromPng() expects parameter 1 to be a string or a stream resource", 0);
297 1 : RETURN_THROWS();
298 : }
299 :
300 2 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
301 0 : RETURN_THROWS();
302 : }
303 : }
304 : /* }}} */
305 : #endif
306 :
307 :
308 : #ifdef CAIRO_HAS_JPEG_FUNCTIONS
309 : /* {{{ proto \Cairo\Surface\Image object \Cairo\Surface\Image::createFromJpeg(file|resource file)
310 : Creates a new image surface and initializes the contents to the given JPEG file. */
311 5 : PHP_METHOD(Cairo_Surface_Image, createFromJpeg)
312 : {
313 : cairo_surface_object *surface_object;
314 5 : zval *stream_zval = NULL;
315 : stream_closure *closure;
316 5 : bool owned_stream = false;
317 5 : php_stream *stream = NULL;
318 :
319 5 : ZEND_PARSE_PARAMETERS_START(1, 1)
320 3 : Z_PARAM_ZVAL(stream_zval)
321 6 : ZEND_PARSE_PARAMETERS_END();
322 :
323 3 : object_init_ex(return_value, ce_cairo_imagesurface);
324 3 : surface_object = Z_CAIRO_SURFACE_P(return_value);
325 :
326 6 : if (Z_TYPE_P(stream_zval) == IS_STRING) {
327 1 : surface_object->surface = cairo_image_surface_create_from_jpeg(Z_STRVAL_P(stream_zval));
328 4 : } else if (Z_TYPE_P(stream_zval) == IS_RESOURCE) {
329 1 : php_stream_from_zval(stream, stream_zval);
330 :
331 1 : if (!stream) {
332 0 : RETURN_NULL();
333 : }
334 :
335 : // Pack stream into struct
336 1 : closure = ecalloc(1, sizeof(stream_closure));
337 1 : closure->stream = stream;
338 1 : closure->owned_stream = owned_stream;
339 :
340 1 : surface_object->closure = closure;
341 1 : surface_object->surface = cairo_image_surface_create_from_jpeg_stream(
342 : (cairo_read_func_t) php_cairo_read_func,
343 : (void *)closure
344 : );
345 : } else {
346 1 : zend_throw_exception(ce_cairo_exception, "Cairo\\Surface\\Image::createFromJpeg() Argument #1 ($file) must be of type string or a stream resource", 0);
347 1 : RETURN_THROWS();
348 : }
349 :
350 2 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
351 0 : RETURN_THROWS();
352 : }
353 : }
354 : /* }}} */
355 : #endif
356 :
357 : /* {{{ proto int CairoFormat::strideForWidth(long format, long width)
358 : This function provides a stride value that will respect all alignment
359 : requirements of the accelerated image-rendering code within cairo. */
360 6 : PHP_METHOD(Cairo_Surface_ImageFormat, strideForWidth)
361 : {
362 : long width;
363 : zval *format;
364 :
365 6 : ZEND_PARSE_PARAMETERS_START(2, 2)
366 6 : Z_PARAM_OBJECT_OF_CLASS(format, ce_cairo_format)
367 4 : Z_PARAM_LONG(width)
368 6 : ZEND_PARSE_PARAMETERS_END();
369 :
370 2 : RETURN_LONG(cairo_format_stride_for_width(
371 : Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(format))),
372 : width
373 : ));
374 : }
375 : /* }}} */
376 :
377 :
378 : /* ----------------------------------------------------------------
379 : Cairo\FontOptions Definition and registration
380 : ------------------------------------------------------------------*/
381 :
382 : /* {{{ PHP_MINIT_FUNCTION */
383 424 : PHP_MINIT_FUNCTION(cairo_image_surface)
384 : {
385 424 : ce_cairo_imagesurface = register_class_Cairo_Surface_Image(ce_cairo_surface);
386 :
387 424 : ce_cairo_format = register_class_Cairo_Surface_ImageFormat();
388 :
389 424 : return SUCCESS;
390 : }
391 : /* }}} */
|