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((char *)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 5 : stream_closure *closure = NULL;
269 5 : php_stream *stream = NULL;
270 5 : cairo_surface_t *surface = 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 6 : if (Z_TYPE_P(stream_zval) == IS_STRING) {
277 1 : surface = cairo_image_surface_create_from_png(Z_STRVAL_P(stream_zval));
278 4 : } else if (Z_TYPE_P(stream_zval) == IS_RESOURCE) {
279 1 : php_stream_from_zval(stream, stream_zval);
280 :
281 1 : if (!stream) {
282 0 : RETURN_NULL();
283 : }
284 :
285 : // Pack stream into struct
286 1 : closure = ecalloc(1, sizeof(stream_closure));
287 1 : closure->stream = stream;
288 1 : closure->owned_stream = false;
289 :
290 1 : surface = cairo_image_surface_create_from_png_stream(
291 : (cairo_read_func_t) php_cairo_read_func,
292 : (void *)closure
293 : );
294 : } else {
295 1 : zend_throw_exception(ce_cairo_exception, "Cairo\\Surface\\Image::createFromPng() Argument #1 ($file) must be of type string or a stream resource", 0);
296 1 : RETURN_THROWS();
297 : }
298 :
299 2 : if (php_cairo_throw_exception(cairo_surface_status(surface))) {
300 0 : if (closure) {
301 0 : efree(closure);
302 : }
303 0 : RETURN_THROWS();
304 : }
305 :
306 2 : object_init_ex(return_value, ce_cairo_imagesurface);
307 2 : surface_object = Z_CAIRO_SURFACE_P(return_value);
308 2 : surface_object->surface = surface;
309 2 : surface_object->closure = closure;
310 : }
311 : /* }}} */
312 : #endif
313 :
314 :
315 : #ifdef CAIRO_HAS_JPEG_FUNCTIONS
316 : /* {{{ proto \Cairo\Surface\Image object \Cairo\Surface\Image::createFromJpeg(file|resource file)
317 : Creates a new image surface and initializes the contents to the given JPEG file. */
318 5 : PHP_METHOD(Cairo_Surface_Image, createFromJpeg)
319 : {
320 : cairo_surface_object *surface_object;
321 5 : zval *stream_zval = NULL;
322 5 : cairo_surface_t *surface = NULL;
323 5 : stream_closure *closure = NULL;
324 5 : php_stream *stream = NULL;
325 :
326 5 : ZEND_PARSE_PARAMETERS_START(1, 1)
327 3 : Z_PARAM_ZVAL(stream_zval)
328 6 : ZEND_PARSE_PARAMETERS_END();
329 :
330 6 : if (Z_TYPE_P(stream_zval) == IS_STRING) {
331 1 : surface = cairo_image_surface_create_from_jpeg(Z_STRVAL_P(stream_zval));
332 4 : } else if (Z_TYPE_P(stream_zval) == IS_RESOURCE) {
333 1 : php_stream_from_zval(stream, stream_zval);
334 :
335 1 : if (!stream) {
336 0 : RETURN_NULL();
337 : }
338 :
339 : // Pack stream into struct
340 1 : closure = ecalloc(1, sizeof(stream_closure));
341 1 : closure->stream = stream;
342 1 : closure->owned_stream = false;
343 :
344 1 : surface = cairo_image_surface_create_from_jpeg_stream(
345 : (cairo_read_func_t) php_cairo_read_func,
346 : (void *)closure
347 : );
348 : } else {
349 1 : zend_throw_exception(ce_cairo_exception, "Cairo\\Surface\\Image::createFromJpeg() Argument #1 ($file) must be of type string or a stream resource", 0);
350 1 : RETURN_THROWS();
351 : }
352 :
353 :
354 2 : if (php_cairo_throw_exception(cairo_surface_status(surface))) {
355 0 : if (closure) {
356 0 : efree(closure);
357 : }
358 0 : RETURN_THROWS();
359 : }
360 :
361 2 : object_init_ex(return_value, ce_cairo_imagesurface);
362 2 : surface_object = Z_CAIRO_SURFACE_P(return_value);
363 2 : surface_object->closure = closure;
364 2 : surface_object->surface = surface;
365 : }
366 : /* }}} */
367 : #endif
368 :
369 : /* {{{ proto int CairoFormat::strideForWidth(long format, long width)
370 : This function provides a stride value that will respect all alignment
371 : requirements of the accelerated image-rendering code within cairo. */
372 6 : PHP_METHOD(Cairo_Surface_ImageFormat, strideForWidth)
373 : {
374 : zend_long width;
375 : zval *format;
376 :
377 6 : ZEND_PARSE_PARAMETERS_START(2, 2)
378 6 : Z_PARAM_OBJECT_OF_CLASS(format, ce_cairo_format)
379 4 : Z_PARAM_LONG(width)
380 6 : ZEND_PARSE_PARAMETERS_END();
381 :
382 2 : RETURN_LONG(cairo_format_stride_for_width(
383 : Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(format))),
384 : (int) width
385 : ));
386 : }
387 : /* }}} */
388 :
389 :
390 : /* ----------------------------------------------------------------
391 : Cairo\FontOptions Definition and registration
392 : ------------------------------------------------------------------*/
393 :
394 : /* {{{ PHP_MINIT_FUNCTION */
395 433 : PHP_MINIT_FUNCTION(cairo_image_surface)
396 : {
397 433 : ce_cairo_imagesurface = register_class_Cairo_Surface_Image(ce_cairo_surface);
398 :
399 433 : ce_cairo_format = register_class_Cairo_Surface_ImageFormat();
400 :
401 433 : return SUCCESS;
402 : }
403 : /* }}} */
|