LCOV - code coverage report
Current view: top level - src - pdf_surface.c (source / functions) Coverage Total Hit
Test: PHP Cairo Extension Coverage Lines: 88.7 % 141 125
Test Date: 2025-09-10 21:28:33 Functions: 100.0 % 11 11

            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
        

Generated by: LCOV version 2.0-1