LCOV - code coverage report
Current view: top level - src - image_surface.c (source / functions) Coverage Total Hit
Test: PHP Cairo Extension Coverage Lines: 85.2 % 149 127
Test Date: 2025-09-10 21:28:33 Functions: 100.0 % 12 12

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

Generated by: LCOV version 2.0-1