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 : /* {{{ proto int \Cairo\Surface\Pdf::addOutline(int parent_id, string name, string link_attr, int outline_flag])
179 : Add an item to the document outline hierarchy with a name that links to the location specified by link_attribs.
180 : Link attributes have the same keys and values as the Link Tag, excluding the "rect" attribute.
181 : The item will be a child of the item with id parent_id.
182 : Use CAIRO_PDF_OUTLINE_ROOT as the parent id of top level items.
183 : Returns the id for the added item. */
184 11 : PHP_METHOD(Cairo_Surface_Pdf, addOutline)
185 : {
186 : cairo_surface_object *surface_object;
187 : zend_long parent_id;
188 : zval *outline_flag;
189 : char *name, *linkAttribs;
190 : size_t name_len, linkAttribs_len;
191 :
192 11 : ZEND_PARSE_PARAMETERS_START(4, 4)
193 14 : Z_PARAM_LONG(parent_id);
194 12 : Z_PARAM_STRING(name, name_len)
195 10 : Z_PARAM_STRING(linkAttribs, linkAttribs_len)
196 8 : Z_PARAM_OBJECT_OF_CLASS(outline_flag, ce_cairo_pdf_outlineflag);
197 11 : ZEND_PARSE_PARAMETERS_END();
198 :
199 6 : surface_object = cairo_surface_object_get(getThis());
200 3 : if (!surface_object) {
201 0 : RETURN_THROWS();
202 : }
203 :
204 6 : RETVAL_LONG(cairo_pdf_surface_add_outline(
205 : surface_object->surface,
206 : parent_id,
207 : (const char *)name,
208 : (const char *)linkAttribs,
209 : Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(outline_flag)))
210 : ));
211 :
212 3 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
213 0 : RETURN_THROWS();
214 : }
215 : }
216 : /* }}} */
217 :
218 :
219 : /* {{{ proto void \Cairo\Surface\Pdf::setMetadata(int metadata_constant [, string metadata])
220 : Set document metadata.
221 : 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.
222 : An optional timezone of the form "[+/-]hh:mm" or "Z" for UTC time can be appended.
223 : All other metadata values can be any UTF-8 string. */
224 7 : PHP_METHOD(Cairo_Surface_Pdf, setMetadata)
225 : {
226 : cairo_surface_object *surface_object;
227 : zval *metadata_const;
228 7 : char *metadata = "";
229 : size_t metadata_len;
230 :
231 7 : ZEND_PARSE_PARAMETERS_START(1, 2)
232 10 : Z_PARAM_OBJECT_OF_CLASS(metadata_const, ce_cairo_pdf_metadata);
233 4 : Z_PARAM_OPTIONAL;
234 7 : Z_PARAM_STRING(metadata, metadata_len)
235 7 : ZEND_PARSE_PARAMETERS_END();
236 :
237 6 : surface_object = cairo_surface_object_get(getThis());
238 3 : if (!surface_object) {
239 0 : RETURN_THROWS();
240 : }
241 :
242 6 : cairo_pdf_surface_set_metadata(
243 : surface_object->surface,
244 6 : Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(metadata_const))),
245 : (const char *)metadata
246 : );
247 :
248 3 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
249 0 : RETURN_THROWS();
250 : }
251 : }
252 : /* }}} */
253 :
254 :
255 : /* {{{ proto void \Cairo\Surface\Pdf::setPageLabel(string label)
256 : Set page label for the current page. */
257 4 : PHP_METHOD(Cairo_Surface_Pdf, setPageLabel)
258 : {
259 : char *label;
260 : size_t label_len;
261 : cairo_surface_object *surface_object;
262 :
263 4 : ZEND_PARSE_PARAMETERS_START(1, 1)
264 4 : Z_PARAM_STRING(label, label_len)
265 4 : ZEND_PARSE_PARAMETERS_END();
266 :
267 2 : surface_object = cairo_surface_object_get(getThis());
268 1 : if (!surface_object) {
269 0 : RETURN_THROWS();
270 : }
271 :
272 1 : cairo_pdf_surface_set_page_label(surface_object->surface, (const char *)label);
273 :
274 1 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
275 0 : RETURN_THROWS();
276 : }
277 : }
278 : /* }}} */
279 :
280 :
281 : /* {{{ proto void \Cairo\Surface\Pdf::setThumbnailSize(double width, double height)
282 : Set the thumbnail image size for the current and all subsequent pages.
283 : Setting a width or height of 0 disables thumbnails for the current and subsequent pages. */
284 6 : PHP_METHOD(Cairo_Surface_Pdf, setThumbnailSize)
285 : {
286 6 : long width = 0, height = 0;
287 : cairo_surface_object *surface_object;
288 :
289 6 : ZEND_PARSE_PARAMETERS_START(2, 2)
290 6 : Z_PARAM_LONG(width)
291 4 : Z_PARAM_LONG(height)
292 6 : ZEND_PARSE_PARAMETERS_END();
293 :
294 2 : surface_object = cairo_surface_object_get(getThis());
295 1 : if (!surface_object) {
296 0 : RETURN_THROWS();
297 : }
298 :
299 1 : cairo_pdf_surface_set_thumbnail_size(surface_object->surface, width, height);
300 1 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
301 0 : RETURN_THROWS();
302 : }
303 : }
304 : /* }}} */
305 :
306 :
307 : #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 18, 0)
308 : /* {{{ proto void \Cairo\Surface\Pdf::setCustomMetadata(string field, string value)
309 : Set custom metadata for the PDF document.
310 : field may be any string except for the following names reserved by PDF:
311 : "Title", "Author", "Subject", "Keywords", "Creator", "Producer", "CreationDate", "ModDate", "Trapped" .*/
312 6 : PHP_METHOD(Cairo_Surface_Pdf, setCustomMetadata)
313 : {
314 : char *field, *value;
315 : size_t field_len, value_len;
316 : cairo_surface_object *surface_object;
317 :
318 6 : ZEND_PARSE_PARAMETERS_START(2, 2)
319 8 : Z_PARAM_STRING(field, field_len)
320 6 : Z_PARAM_STRING(value, value_len)
321 7 : ZEND_PARSE_PARAMETERS_END();
322 :
323 4 : surface_object = cairo_surface_object_get(getThis());
324 2 : if (!surface_object) {
325 0 : RETURN_THROWS();
326 : }
327 :
328 2 : if (strcasecmp(field, "Title") == 0
329 1 : || strcasecmp(field, "Author") == 0
330 1 : || strcasecmp(field, "Subject") == 0
331 1 : || strcasecmp(field, "Keywords") == 0
332 1 : || strcasecmp(field, "Creator") == 0
333 1 : || strcasecmp(field, "Producer") == 0
334 1 : || strcasecmp(field, "CreationDate") == 0
335 1 : || strcasecmp(field, "ModDate") == 0
336 1 : || strcasecmp(field, "Trapped") == 0
337 : ) {
338 1 : zend_throw_exception_ex(zend_ce_value_error, 0,
339 : "Cairo\\Surface\\Pdf::setCustomMetadata(): "
340 : "Argument #1 ($field) may be any string except for the following names reserved by PDF: "
341 : "Title, Author, Subject, Keywords, Creator, Producer, CreationDate, ModDate, Trapped."
342 : );
343 1 : RETURN_THROWS();
344 : }
345 :
346 1 : cairo_pdf_surface_set_custom_metadata(
347 : surface_object->surface,
348 : (const char *)field,
349 : (const char *)value
350 : );
351 :
352 1 : if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
353 0 : RETURN_THROWS();
354 : }
355 : }
356 : /* }}} */
357 : #endif
358 :
359 : /* ----------------------------------------------------------------
360 : \Cairo\Surface\Pdf Definition and registration
361 : ------------------------------------------------------------------*/
362 :
363 : /* {{{ PHP_MINIT_FUNCTION */
364 424 : PHP_MINIT_FUNCTION(cairo_pdf_surface)
365 : {
366 424 : ce_cairo_pdfsurface = register_class_Cairo_Surface_Pdf(ce_cairo_surface);
367 :
368 : /* PDF-Versions */
369 424 : ce_cairo_pdfversion = register_class_Cairo_Surface_Pdf_Version();
370 :
371 : #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 16, 0)
372 : /* Outline-Flags */
373 424 : ce_cairo_pdf_outlineflag = register_class_Cairo_Surface_Pdf_OutlineFlags();
374 :
375 : /* Metadata */
376 424 : ce_cairo_pdf_metadata = register_class_Cairo_Surface_Pdf_Metadata();
377 : #endif
378 :
379 424 : return SUCCESS;
380 : }
381 :
382 : #endif
|