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-10-09 18:11:12 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              : #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
        

Generated by: LCOV version 2.0-1