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