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 :
26 : #if CAIRO_HAS_PDF_SURFACE
27 : #include <cairo-pdf.h>
28 : #include "pdf_surface_arginfo.h"
29 :
30 : zend_class_entry *ce_cairo_pdfsurface;
31 : zend_class_entry *ce_cairo_pdf_metadata;
32 : zend_class_entry *ce_cairo_pdf_outlineflag;
33 : zend_class_entry *ce_cairo_pdfversion;
34 :
35 : /* ----------------------------------------------------------------
36 : \Cairo\Surface\Pdf Class API
37 : ------------------------------------------------------------------*/
38 :
39 : /* {{{ proto void __construct(string|resource file, float width, float height)
40 : Creates a PDF surface of the specified size in points to be written to filename. */
41 17 : PHP_METHOD(Cairo_Surface_Pdf, __construct)
42 : {
43 17 : zval *stream_zval = NULL;
44 : stream_closure *closure;
45 17 : php_stream *stream = NULL;
46 : double width, height;
47 17 : bool owned_stream = false;
48 : cairo_surface_object *surface_object;
49 :
50 17 : ZEND_PARSE_PARAMETERS_START(3, 3)
51 13 : Z_PARAM_ZVAL(stream_zval)
52 26 : Z_PARAM_DOUBLE(width)
53 24 : Z_PARAM_DOUBLE(height)
54 17 : ZEND_PARSE_PARAMETERS_END();
55 :
56 22 : surface_object = Z_CAIRO_SURFACE_P(getThis());
57 11 : if (!surface_object) {
58 0 : RETURN_NULL();
59 : }
60 :
61 : /* special case - a NULL file is like an "in memory" PDF */
62 22 : if (Z_TYPE_P(stream_zval) == IS_NULL) {
63 8 : surface_object->surface = cairo_pdf_surface_create(NULL, width, height);
64 : }
65 : /* Otherwise it can be a filename or a PHP stream */
66 : else {
67 6 : if (Z_TYPE_P(stream_zval) == IS_STRING) {
68 1 : stream = php_stream_open_wrapper(Z_STRVAL_P(stream_zval), "w+b", REPORT_ERRORS, NULL);
69 1 : owned_stream = 1;
70 4 : } else if (Z_TYPE_P(stream_zval) == IS_RESOURCE) {
71 1 : php_stream_from_zval(stream, stream_zval);
72 : } else {
73 1 : zend_throw_exception(zend_ce_type_error, "Cairo\\Surface\\Pdf::__construct() expects parameter 1 to be null, a string, or a stream resource", 0);
74 1 : RETURN_THROWS();
75 : }
76 :
77 : /* Pack stream into struct*/
78 2 : closure = ecalloc(1, sizeof(stream_closure));
79 2 : closure->stream = stream;
80 2 : closure->owned_stream = owned_stream;
81 :
82 2 : surface_object->closure = closure;
83 2 : surface_object->surface = cairo_pdf_surface_create_for_stream(php_cairo_write_func, (void *)closure, width, height);
84 : }
85 :
86 10 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
87 0 : RETURN_THROWS();
88 : }
89 : }
90 : /* }}} */
91 :
92 : /* {{{ proto string \Cairo\Surface\Pdf::versionToString(int version)
93 : Get the string representation of the given version id. This function will return NULL if version isn't valid. */
94 4 : PHP_METHOD(Cairo_Surface_Pdf, versionToString)
95 : {
96 : zval *version;
97 :
98 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
99 4 : Z_PARAM_OBJECT_OF_CLASS(version, ce_cairo_pdfversion)
100 4 : ZEND_PARSE_PARAMETERS_END();
101 :
102 3 : RETURN_STRING(cairo_pdf_version_to_string(Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(version)))));
103 : }
104 : /* }}} */
105 :
106 : /* {{{ proto array \Cairo\Surface\Pdf::getVersions()
107 : Used to retrieve the list of supported versions */
108 2 : PHP_METHOD(Cairo_Surface_Pdf, getVersions)
109 : {
110 2 : const cairo_pdf_version_t *versions = 0;
111 2 : int version_count = 0, i = 0;
112 : zval pdf_version_case;
113 :
114 2 : ZEND_PARSE_PARAMETERS_NONE();
115 :
116 1 : cairo_pdf_get_versions(&versions, &version_count);
117 1 : array_init(return_value);
118 :
119 5 : for (i = 0; i < version_count; i++) {
120 4 : pdf_version_case = php_enum_from_cairo_c_enum(ce_cairo_pdfversion, versions[i]);
121 : add_next_index_zval(return_value, &pdf_version_case);
122 : }
123 : }
124 : /* }}} */
125 :
126 : /* {{{ proto void \Cairo\Surface\Pdf::setSize(double width, double height)
127 : Changes the size of a PDF surface for the current (and subsequent) pages.
128 : This should be called before any drawing takes place on the surface */
129 8 : PHP_METHOD(Cairo_Surface_Pdf, setSize)
130 : {
131 8 : double width = 0.0, height = 0.0;
132 : cairo_surface_object *surface_object;
133 :
134 8 : ZEND_PARSE_PARAMETERS_START(2, 2)
135 10 : Z_PARAM_DOUBLE(width)
136 8 : Z_PARAM_DOUBLE(height)
137 8 : ZEND_PARSE_PARAMETERS_END();
138 :
139 6 : surface_object = cairo_surface_object_get(getThis());
140 3 : if (!surface_object) {
141 0 : RETURN_THROWS();
142 : }
143 :
144 3 : cairo_pdf_surface_set_size(surface_object->surface, width, height);
145 3 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
146 0 : RETURN_THROWS();
147 : }
148 : }
149 : /* }}} */
150 :
151 : /* {{{ proto void \Cairo\Surface\Pdf::restrictToVersion(int version)
152 : Restricts the generated PDF file to version. */
153 4 : PHP_METHOD(Cairo_Surface_Pdf, restrictToVersion)
154 : {
155 : cairo_surface_object *surface_object;
156 : zval *version;
157 :
158 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
159 4 : Z_PARAM_OBJECT_OF_CLASS(version, ce_cairo_pdfversion);
160 4 : ZEND_PARSE_PARAMETERS_END();
161 :
162 2 : surface_object = cairo_surface_object_get(getThis());
163 1 : if (!surface_object) {
164 0 : RETURN_THROWS();
165 : }
166 :
167 1 : cairo_pdf_surface_restrict_to_version(
168 : surface_object->surface,
169 2 : Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(version)))
170 : );
171 1 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
172 0 : RETURN_THROWS();
173 : }
174 : }
175 : /* }}} */
176 :
177 :
178 : #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 16, 0)
179 : /* {{{ proto int \Cairo\Surface\Pdf::addOutline(int parent_id, string name, string link_attr, int outline_flag])
180 : Add an item to the document outline hierarchy with a name that links to the location specified by link_attribs.
181 : Link attributes have the same keys and values as the Link Tag, excluding the "rect" attribute.
182 : The item will be a child of the item with id parent_id.
183 : Use CAIRO_PDF_OUTLINE_ROOT as the parent id of top level items.
184 : Returns the id for the added item. */
185 11 : PHP_METHOD(Cairo_Surface_Pdf, addOutline)
186 : {
187 : cairo_surface_object *surface_object;
188 : zend_long parent_id;
189 : zval *outline_flag;
190 : char *name, *linkAttribs;
191 : size_t name_len, linkAttribs_len;
192 :
193 11 : ZEND_PARSE_PARAMETERS_START(4, 4)
194 14 : Z_PARAM_LONG(parent_id);
195 12 : Z_PARAM_STRING(name, name_len)
196 10 : Z_PARAM_STRING(linkAttribs, linkAttribs_len)
197 8 : Z_PARAM_OBJECT_OF_CLASS(outline_flag, ce_cairo_pdf_outlineflag);
198 11 : ZEND_PARSE_PARAMETERS_END();
199 :
200 6 : surface_object = cairo_surface_object_get(getThis());
201 3 : if (!surface_object) {
202 0 : RETURN_THROWS();
203 : }
204 :
205 6 : RETVAL_LONG(cairo_pdf_surface_add_outline(
206 : surface_object->surface,
207 : parent_id,
208 : (const char *)name,
209 : (const char *)linkAttribs,
210 : Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(outline_flag)))
211 : ));
212 :
213 3 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
214 0 : RETURN_THROWS();
215 : }
216 : }
217 : /* }}} */
218 :
219 :
220 : /* {{{ proto void \Cairo\Surface\Pdf::setMetadata(int metadata_constant [, string metadata])
221 : Set document metadata.
222 : The values for the CAIRO_PDF_METADATA_CREATE_DATE and CAIRO_PDF_METADATA_MOD_DATE fields must be in ISO-8601 format: YYYY-MM-DDThh:mm:ss.
223 : An optional timezone of the form "[+/-]hh:mm" or "Z" for UTC time can be appended.
224 : All other metadata values can be any UTF-8 string. */
225 7 : PHP_METHOD(Cairo_Surface_Pdf, setMetadata)
226 : {
227 : cairo_surface_object *surface_object;
228 : zval *metadata_const;
229 7 : char *metadata = "";
230 : size_t metadata_len;
231 :
232 7 : ZEND_PARSE_PARAMETERS_START(1, 2)
233 10 : Z_PARAM_OBJECT_OF_CLASS(metadata_const, ce_cairo_pdf_metadata);
234 4 : Z_PARAM_OPTIONAL;
235 7 : Z_PARAM_STRING(metadata, metadata_len)
236 7 : ZEND_PARSE_PARAMETERS_END();
237 :
238 6 : surface_object = cairo_surface_object_get(getThis());
239 3 : if (!surface_object) {
240 0 : RETURN_THROWS();
241 : }
242 :
243 6 : cairo_pdf_surface_set_metadata(
244 : surface_object->surface,
245 6 : Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(metadata_const))),
246 : (const char *)metadata
247 : );
248 :
249 3 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
250 0 : RETURN_THROWS();
251 : }
252 : }
253 : /* }}} */
254 :
255 :
256 : /* {{{ proto void \Cairo\Surface\Pdf::setPageLabel(string label)
257 : Set page label for the current page. */
258 4 : PHP_METHOD(Cairo_Surface_Pdf, setPageLabel)
259 : {
260 : char *label;
261 : size_t label_len;
262 : cairo_surface_object *surface_object;
263 :
264 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
265 4 : Z_PARAM_STRING(label, label_len)
266 4 : ZEND_PARSE_PARAMETERS_END();
267 :
268 2 : surface_object = cairo_surface_object_get(getThis());
269 1 : if (!surface_object) {
270 0 : RETURN_THROWS();
271 : }
272 :
273 1 : cairo_pdf_surface_set_page_label(surface_object->surface, (const char *)label);
274 :
275 1 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
276 0 : RETURN_THROWS();
277 : }
278 : }
279 : /* }}} */
280 :
281 :
282 : /* {{{ proto void \Cairo\Surface\Pdf::setThumbnailSize(double width, double height)
283 : Set the thumbnail image size for the current and all subsequent pages.
284 : Setting a width or height of 0 disables thumbnails for the current and subsequent pages. */
285 6 : PHP_METHOD(Cairo_Surface_Pdf, setThumbnailSize)
286 : {
287 6 : zend_long width = 0, height = 0;
288 : cairo_surface_object *surface_object;
289 :
290 6 : ZEND_PARSE_PARAMETERS_START(2, 2)
291 6 : Z_PARAM_LONG(width)
292 4 : Z_PARAM_LONG(height)
293 6 : ZEND_PARSE_PARAMETERS_END();
294 :
295 2 : surface_object = cairo_surface_object_get(getThis());
296 1 : if (!surface_object) {
297 0 : RETURN_THROWS();
298 : }
299 :
300 1 : cairo_pdf_surface_set_thumbnail_size(surface_object->surface, (int) width, (int) height);
301 1 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
302 0 : RETURN_THROWS();
303 : }
304 : }
305 : /* }}} */
306 : #endif
307 :
308 :
309 : #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 18, 0)
310 : /* {{{ proto void \Cairo\Surface\Pdf::setCustomMetadata(string field, string value)
311 : Set custom metadata for the PDF document.
312 : field may be any string except for the following names reserved by PDF:
313 : "Title", "Author", "Subject", "Keywords", "Creator", "Producer", "CreationDate", "ModDate", "Trapped" .*/
314 6 : PHP_METHOD(Cairo_Surface_Pdf, setCustomMetadata)
315 : {
316 : char *field, *value;
317 : size_t field_len, value_len;
318 : cairo_surface_object *surface_object;
319 :
320 6 : ZEND_PARSE_PARAMETERS_START(2, 2)
321 8 : Z_PARAM_STRING(field, field_len)
322 6 : Z_PARAM_STRING(value, value_len)
323 7 : ZEND_PARSE_PARAMETERS_END();
324 :
325 4 : surface_object = cairo_surface_object_get(getThis());
326 2 : if (!surface_object) {
327 0 : RETURN_THROWS();
328 : }
329 :
330 2 : if (strcasecmp(field, "Title") == 0
331 1 : || strcasecmp(field, "Author") == 0
332 1 : || strcasecmp(field, "Subject") == 0
333 1 : || strcasecmp(field, "Keywords") == 0
334 1 : || strcasecmp(field, "Creator") == 0
335 1 : || strcasecmp(field, "Producer") == 0
336 1 : || strcasecmp(field, "CreationDate") == 0
337 1 : || strcasecmp(field, "ModDate") == 0
338 1 : || strcasecmp(field, "Trapped") == 0
339 : ) {
340 1 : zend_throw_exception_ex(zend_ce_value_error, 0,
341 : "Cairo\\Surface\\Pdf::setCustomMetadata(): "
342 : "Argument #1 ($field) may be any string except for the following names reserved by PDF: "
343 : "Title, Author, Subject, Keywords, Creator, Producer, CreationDate, ModDate, Trapped."
344 : );
345 1 : RETURN_THROWS();
346 : }
347 :
348 1 : cairo_pdf_surface_set_custom_metadata(
349 : surface_object->surface,
350 : (const char *)field,
351 : (const char *)value
352 : );
353 :
354 1 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
355 0 : RETURN_THROWS();
356 : }
357 : }
358 : /* }}} */
359 : #endif
360 :
361 : /* ----------------------------------------------------------------
362 : \Cairo\Surface\Pdf Definition and registration
363 : ------------------------------------------------------------------*/
364 :
365 : /* {{{ PHP_MINIT_FUNCTION */
366 433 : PHP_MINIT_FUNCTION(cairo_pdf_surface)
367 : {
368 433 : ce_cairo_pdfsurface = register_class_Cairo_Surface_Pdf(ce_cairo_surface);
369 :
370 : /* PDF-Versions */
371 433 : ce_cairo_pdfversion = register_class_Cairo_Surface_Pdf_Version();
372 :
373 : #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 16, 0)
374 : /* Outline-Flags */
375 433 : ce_cairo_pdf_outlineflag = register_class_Cairo_Surface_Pdf_OutlineFlags();
376 :
377 : /* Metadata */
378 433 : ce_cairo_pdf_metadata = register_class_Cairo_Surface_Pdf_Metadata();
379 : #endif
380 :
381 433 : return SUCCESS;
382 : }
383 :
384 : #endif
|