LCOV - code coverage report
Current view: top level - src - surface.c (source / functions) Coverage Total Hit
Test: PHP Cairo Extension Coverage Lines: 86.1 % 373 321
Test Date: 2025-09-10 21:28:33 Functions: 100.0 % 34 34

            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 "surface_arginfo.h"
      26              : 
      27              : zend_class_entry *ce_cairo_surface;
      28              : zend_class_entry *ce_cairo_content;
      29              : zend_class_entry *ce_cairo_surfacetype;
      30              : 
      31              : 
      32              : static zend_object_handlers cairo_surface_object_handlers;
      33              : 
      34          608 : cairo_surface_object *cairo_surface_fetch_object(zend_object *object)
      35              : {
      36          608 :     return (cairo_surface_object *) ((char*)(object) - XtOffsetOf(cairo_surface_object, std));
      37              : }
      38              : 
      39          186 : cairo_surface_object *cairo_surface_object_get(zval *zv)
      40              : {
      41          186 :     cairo_surface_object *object = Z_CAIRO_SURFACE_P(zv);
      42              : 
      43          186 :     if (object->surface == NULL) {
      44            2 :         zend_throw_exception_ex(ce_cairo_exception, 0,
      45              :             "Internal surface object missing in %s, you must call parent::__construct in extended classes.",
      46            2 :             ZSTR_VAL(Z_OBJCE_P(zv)->name));
      47            2 :         return NULL;
      48              :     }
      49              : 
      50          184 :     return object;
      51              : }
      52              : 
      53              : /* ----------------------------------------------------------------
      54              :     Cairo\Pattern Class API
      55              : ------------------------------------------------------------------ */
      56              : 
      57              : /* {{{ proto void contruct()
      58              :        CairoSurface CANNOT be extended in userspace, this will throw an exception on use */
      59            1 : PHP_METHOD(Cairo_Surface, __construct) {
      60            1 :     ZEND_PARSE_PARAMETERS_NONE();
      61            1 :     zend_throw_exception(ce_cairo_exception, "Cairo\\Surface cannot be constructed", 0);
      62              : }
      63              : /* }}} */
      64              : 
      65              : /* {{{ proto CairoSurface object \Cairo\Surface::createSimilar(\Cairo\Content content, double width, double height)
      66              :        Create a new surface that is as compatible as possible with an existing surface. */
      67            8 : PHP_METHOD(Cairo_Surface, createSimilar)
      68              : {
      69              :     cairo_surface_object *surface_object, *new_surface_object;
      70              :     cairo_surface_t *new_surface;
      71              :     zval *content;
      72              :     double width, height;
      73              : 
      74            8 :     ZEND_PARSE_PARAMETERS_START(3, 3)
      75            8 :         Z_PARAM_OBJECT_OF_CLASS(content, ce_cairo_content)
      76            6 :         Z_PARAM_DOUBLE(width)
      77            4 :         Z_PARAM_DOUBLE(height)
      78            8 :     ZEND_PARSE_PARAMETERS_END();
      79              : 
      80            2 :     surface_object = cairo_surface_object_get(getThis());
      81            1 :     if (!surface_object) {
      82            0 :         RETURN_THROWS();
      83              :     }
      84              : 
      85            2 :     new_surface = cairo_surface_create_similar(
      86              :         surface_object->surface,
      87            2 :         Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(content))),
      88              :         width,
      89              :         height
      90              :     );
      91              : 
      92              :     /* we can't always rely on the same type of surface being returned, so we use php_cairo_get_surface_ce */
      93            1 :     object_init_ex(return_value, php_cairo_get_surface_ce(new_surface));
      94            1 :     new_surface_object = Z_CAIRO_SURFACE_P(return_value);
      95            1 :     if (!new_surface_object) {
      96            0 :         RETURN_NULL();
      97              :     }
      98              : 
      99            1 :     new_surface_object->surface = new_surface;
     100              : }
     101              : /* }}} */
     102              : 
     103              : /* {{{ proto CairoSurface object \Cairo\Surface::createSimilarImage(\Cairo\Format format, double width, double height)
     104              :        Create a new image surface that is as compatible as possible for uploading to and the use in conjunction with an existing surface.
     105              :        Unlike cairo_surface_create_similar() the new image surface won't inherit the device scale from other. */
     106            8 : PHP_METHOD(Cairo_Surface, createSimilarImage)
     107              : {
     108              :     cairo_surface_object *surface_object, *new_surface_object;
     109              :     cairo_surface_t *new_surface;
     110              :     double width, height;
     111              :     zval *format;
     112              : 
     113            8 :     ZEND_PARSE_PARAMETERS_START(3, 3)
     114            8 :         Z_PARAM_OBJECT_OF_CLASS(format, ce_cairo_format)
     115            6 :         Z_PARAM_DOUBLE(width)
     116            4 :         Z_PARAM_DOUBLE(height)
     117            8 :     ZEND_PARSE_PARAMETERS_END();
     118              : 
     119            2 :     surface_object = cairo_surface_object_get(getThis());
     120            1 :     if (!surface_object) {
     121            0 :         RETURN_THROWS();
     122              :     }
     123              : 
     124            2 :     new_surface = cairo_surface_create_similar_image(
     125              :         surface_object->surface,
     126            2 :         Z_LVAL_P(zend_enum_fetch_case_value(Z_OBJ_P(format))),
     127              :         width,
     128              :         height
     129              :     );
     130              : 
     131              :     /* --> because of used method php_cairo_get_surface_ce() should always give 'ce_cairo_imagesurface' */
     132            1 :     object_init_ex(return_value, php_cairo_get_surface_ce(new_surface));
     133            1 :     new_surface_object = Z_CAIRO_SURFACE_P(return_value);
     134            1 :     if (!new_surface_object) {
     135            0 :         RETURN_NULL();
     136              :     }
     137              : 
     138            1 :     new_surface_object->surface = new_surface;
     139              : }
     140              : /* }}} */
     141              : 
     142              : /* {{{ proto CairoSurface object \Cairo\Surface::createForRectangle(double x, double y, double width, double height)
     143              :        create a new surface that is a rectangle within the target surface. */
     144           10 : PHP_METHOD(Cairo_Surface, createForRectangle)
     145              : {
     146           10 :     zval *surface_zval = NULL;
     147              :     cairo_surface_object *surface_object, *new_surface_object;
     148              :     cairo_surface_t *new_surface;
     149              :     double x, y, width, height;
     150              : 
     151           10 :     ZEND_PARSE_PARAMETERS_START(4, 4)
     152           10 :         Z_PARAM_DOUBLE(x)
     153            8 :         Z_PARAM_DOUBLE(y)
     154            6 :         Z_PARAM_DOUBLE(width)
     155            4 :         Z_PARAM_DOUBLE(height)
     156           10 :     ZEND_PARSE_PARAMETERS_END();
     157              : 
     158            2 :     surface_zval = getThis();
     159            1 :     surface_object = cairo_surface_object_get(surface_zval);
     160            1 :     if (!surface_object) {
     161            0 :         RETURN_THROWS();
     162              :     }
     163              : 
     164            1 :     new_surface = cairo_surface_create_for_rectangle(surface_object->surface, x, y, width, height);
     165              : 
     166            1 :     object_init_ex(return_value, php_cairo_get_subsurface_ce());
     167            1 :     new_surface_object = Z_CAIRO_SURFACE_P(return_value);
     168              :     // Store reference to the parent object
     169            1 :     ZVAL_COPY(&new_surface_object->parent_zval, surface_zval);
     170            1 :     new_surface_object->surface = new_surface;
     171              : }
     172              : /* }}} */
     173              : 
     174              : 
     175              : /* {{{ proto \Cairo\Status \Cairo\Surface::getStatus()
     176              :        Checks whether an error has previously occurred for this surface. */
     177            2 : PHP_METHOD(Cairo_Surface, getStatus)
     178              : {
     179              :     cairo_surface_object *surface_object;
     180              :     zval status_case;
     181              : 
     182            3 :     ZEND_PARSE_PARAMETERS_NONE();
     183              : 
     184            2 :     surface_object = cairo_surface_object_get(getThis());
     185            1 :     if (!surface_object) {
     186            0 :         RETURN_THROWS();
     187              :     }
     188              : 
     189            1 :     status_case = php_enum_from_cairo_c_enum(
     190              :         ce_cairo_status,
     191            1 :         cairo_surface_status(surface_object->surface)
     192              :     );
     193              : 
     194            1 :     if (Z_TYPE(status_case) == IS_OBJECT) {
     195            2 :         RETURN_ZVAL(&status_case, 1, 1);
     196              :     }
     197              : }
     198              : /* }}} */
     199              : 
     200              : /* {{{ proto void \Cairo\Surface::finish()
     201              :        This function finishes the surface and drops all references to external resources. For example,
     202              :        for the Xlib backend it means that cairo will no longer access the drawable, which can be freed. */
     203            4 : PHP_METHOD(Cairo_Surface, finish)
     204              : {
     205              :     cairo_surface_object *surface_object;
     206              : 
     207            4 :     ZEND_PARSE_PARAMETERS_NONE();
     208              : 
     209            6 :     surface_object = cairo_surface_object_get(getThis());
     210            3 :     if (!surface_object) {
     211            2 :         RETURN_THROWS();
     212              :     }
     213              : 
     214            1 :     cairo_surface_finish(surface_object->surface);
     215              : }
     216              : /* }}} */
     217              : 
     218              : /* {{{ proto void \Cairo\Surface::flush()
     219              :        Do any pending drawing for the surface and also restore any temporary modification's cairo has made
     220              :        to the surface's state. This function must be called before switching from drawing on the surface
     221              :        with cairo to drawing on it directly with native APIs. */
     222            2 : PHP_METHOD(Cairo_Surface, flush)
     223              : {
     224              :     cairo_surface_object *surface_object;
     225              : 
     226            2 :     ZEND_PARSE_PARAMETERS_NONE();
     227              : 
     228            2 :     surface_object = cairo_surface_object_get(getThis());
     229            1 :     if (!surface_object) {
     230            0 :         RETURN_THROWS();
     231              :     }
     232              : 
     233            1 :     cairo_surface_flush(surface_object->surface);
     234              : }
     235              : /* }}} */
     236              : 
     237              : /* {{{ proto CairoFontOptions object \Cairo\Surface::getFontOptions()
     238              :        Retrieves the default font rendering options for the surface. */
     239            2 : PHP_METHOD(Cairo_Surface, getFontOptions)
     240              : {
     241              :     cairo_surface_object *surface_object;
     242              :     cairo_font_options_object *font_object;
     243            2 :     cairo_font_options_t *options = cairo_font_options_create();
     244              : 
     245            2 :     ZEND_PARSE_PARAMETERS_NONE();
     246              : 
     247            2 :     surface_object = cairo_surface_object_get(getThis());
     248            1 :     if (!surface_object) {
     249            0 :         RETURN_THROWS();
     250              :     }
     251              : 
     252            1 :     object_init_ex(return_value, php_cairo_get_fontoptions_ce());
     253            1 :     font_object = Z_CAIRO_FONT_OPTIONS_P(return_value);
     254              : 
     255            1 :     cairo_surface_get_font_options(surface_object->surface, options);
     256            1 :     font_object->font_options = options;
     257              : }
     258              : /* }}} */
     259              : 
     260              : /* {{{ proto \Cairo\Content \Cairo\Surface::getContent()
     261              :        This function returns the content type of surface which indicates whether the surface contains color and/or alpha information. */
     262            2 : PHP_METHOD(Cairo_Surface, getContent)
     263              : {
     264              :     cairo_surface_object *surface_object;
     265              :     zval content_case;
     266              : 
     267            3 :     ZEND_PARSE_PARAMETERS_NONE();
     268              : 
     269            2 :     surface_object = cairo_surface_object_get(getThis());
     270            1 :     if (!surface_object) {
     271            0 :         RETURN_THROWS();
     272              :     }
     273              : 
     274            1 :     content_case = php_enum_from_cairo_c_enum(
     275              :         ce_cairo_content,
     276            1 :         cairo_surface_get_content(surface_object->surface)
     277              :     );
     278              : 
     279            1 :     if (Z_TYPE(content_case) == IS_OBJECT) {
     280            2 :         RETURN_ZVAL(&content_case, 1, 1);
     281              :     }
     282              : }
     283              : /* }}} */
     284              : 
     285              : /* {{{ proto void \Cairo\Surface::markDirty()
     286              :        Tells cairo that drawing has been done to surface using means other than cairo, and that cairo should reread any cached areas. */
     287            2 : PHP_METHOD(Cairo_Surface, markDirty)
     288              : {
     289              :     cairo_surface_object *surface_object;
     290              : 
     291            2 :     ZEND_PARSE_PARAMETERS_NONE();
     292              : 
     293            2 :     surface_object = cairo_surface_object_get(getThis());
     294            1 :     if (!surface_object) {
     295            0 :         RETURN_THROWS();
     296              :     }
     297              : 
     298            1 :     cairo_surface_mark_dirty(surface_object->surface);
     299              : }
     300              : /* }}} */
     301              : 
     302              : /* {{{ proto void \Cairo\Surface::markDirtyRectangle(float x, float y, float width, float height)
     303              :        Drawing has been done only to the specified rectangle, so that cairo can retain cached contents for other parts of the surface.
     304              :        Any cached clip set on the surface will be reset by this function, to make sure that future cairo calls have the clip set that they expect.*/
     305           10 : PHP_METHOD(Cairo_Surface, markDirtyRectangle)
     306              : {
     307              :     cairo_surface_object *surface_object;
     308           10 :     long x = 0, y = 0, width = 0, height = 0;
     309              : 
     310           10 :     ZEND_PARSE_PARAMETERS_START(4, 4)
     311           10 :         Z_PARAM_LONG(x)
     312            8 :         Z_PARAM_LONG(y)
     313            6 :         Z_PARAM_LONG(width)
     314            4 :         Z_PARAM_LONG(height)
     315           10 :     ZEND_PARSE_PARAMETERS_END();
     316              : 
     317            2 :     surface_object = cairo_surface_object_get(getThis());
     318            1 :     if (!surface_object) {
     319            0 :         RETURN_THROWS();
     320              :     }
     321              : 
     322            1 :     cairo_surface_mark_dirty_rectangle(surface_object->surface, x, y, width, height);
     323              : }
     324              : /* }}} */
     325              : 
     326              : /* {{{ proto void \Cairo\Surface::setDeviceOffset(float x, float y)
     327              :        Sets an offset that is added to the device coordinates determined by the CTM when drawing to surface. */
     328            6 : PHP_METHOD(Cairo_Surface, setDeviceOffset)
     329              : {
     330              :     cairo_surface_object *surface_object;
     331            6 :     double x = 0.0, y = 0.0;
     332              : 
     333            6 :     ZEND_PARSE_PARAMETERS_START(2, 2)
     334            6 :         Z_PARAM_DOUBLE(x)
     335            4 :         Z_PARAM_DOUBLE(y)
     336            6 :     ZEND_PARSE_PARAMETERS_END();
     337              : 
     338            2 :     surface_object = cairo_surface_object_get(getThis());
     339            1 :     if (!surface_object) {
     340            0 :         RETURN_THROWS();
     341              :     }
     342              : 
     343            1 :     cairo_surface_set_device_offset(surface_object->surface, x, y);
     344              : }
     345              : /* }}} */
     346              : 
     347              : /* {{{ proto array \Cairo\Surface::getDeviceOffset()
     348              :        This function returns the previous device offset */
     349            2 : PHP_METHOD(Cairo_Surface, getDeviceOffset)
     350              : {
     351              :     cairo_surface_object *surface_object;
     352              :     double x, y;
     353              : 
     354            2 :     ZEND_PARSE_PARAMETERS_NONE();
     355              : 
     356            2 :     surface_object = cairo_surface_object_get(getThis());
     357            1 :     if (!surface_object) {
     358            0 :         RETURN_THROWS();
     359              :     }
     360              : 
     361            1 :     cairo_surface_get_device_offset(surface_object->surface, &x, &y);
     362              : 
     363            1 :     array_init(return_value);
     364            1 :     add_assoc_double(return_value, "x", x);
     365            1 :     add_assoc_double(return_value, "y", y);
     366              : }
     367              : /* }}} */
     368              : 
     369              : /* {{{ proto void \Cairo\Surface::setDeviceScale(float x, float y)
     370              :        Sets a scale that is multiplied to the device coordinates determined by the CTM when drawing to surface.
     371              :        One common use for this is to render to very high resolution display devices at a scale factor,
     372              :        so that code that assumes 1 pixel will be a certain size will still work.
     373              :        Setting a transformation via cairo_translate() isn't sufficient to do this,
     374              :        since functions like cairo_device_to_user() will expose the hidden scale. */
     375            7 : PHP_METHOD(Cairo_Surface, setDeviceScale)
     376              : {
     377              :     cairo_surface_object *surface_object;
     378            7 :     double x = 0.0, y = 0.0;
     379              : 
     380            7 :     ZEND_PARSE_PARAMETERS_START(2, 2)
     381            8 :         Z_PARAM_DOUBLE(x)
     382            6 :         Z_PARAM_DOUBLE(y)
     383            7 :     ZEND_PARSE_PARAMETERS_END();
     384              : 
     385            4 :     surface_object = cairo_surface_object_get(getThis());
     386            2 :     if (!surface_object) {
     387            0 :         RETURN_THROWS();
     388              :     }
     389              : 
     390            2 :     cairo_surface_set_device_scale(surface_object->surface, x, y);
     391              : }
     392              : /* }}} */
     393              : 
     394              : /* {{{ proto array \Cairo\Surface::getDeviceScale()
     395              :        This function returns the previous set device scale. */
     396            3 : PHP_METHOD(Cairo_Surface, getDeviceScale)
     397              : {
     398              :     cairo_surface_object *surface_object;
     399              :     double x, y;
     400              : 
     401            3 :     ZEND_PARSE_PARAMETERS_NONE();
     402              : 
     403            4 :     surface_object = cairo_surface_object_get(getThis());
     404            2 :     if (!surface_object) {
     405            0 :         RETURN_THROWS();
     406              :     }
     407              : 
     408            2 :     cairo_surface_get_device_scale(surface_object->surface, &x, &y);
     409              : 
     410            2 :     array_init(return_value);
     411            2 :     add_assoc_double(return_value, "x", x);
     412            2 :     add_assoc_double(return_value, "y", y);
     413              : }
     414              : /* }}} */
     415              : 
     416              : /* {{{ proto void \Cairo\Surface::setFallbackResolution(float x, float y)
     417              :       Set the horizontal and vertical resolution for image fallbacks.
     418              :       When certain operations aren't supported natively by a backend, cairo will fallback by
     419              :       rendering operations to an image and then overlaying that image onto the output. */
     420            6 : PHP_METHOD(Cairo_Surface, setFallbackResolution)
     421              : {
     422              :     cairo_surface_object *surface_object;
     423            6 :     double x = 0.0, y = 0.0;
     424              : 
     425            6 :     ZEND_PARSE_PARAMETERS_START(2, 2)
     426            6 :         Z_PARAM_DOUBLE(x)
     427            4 :         Z_PARAM_DOUBLE(y)
     428            6 :     ZEND_PARSE_PARAMETERS_END();
     429              : 
     430            2 :     surface_object = cairo_surface_object_get(getThis());
     431            1 :     if (!surface_object) {
     432            0 :         RETURN_THROWS();
     433              :     }
     434              : 
     435            1 :     cairo_surface_set_fallback_resolution(surface_object->surface, x, y);
     436              : }
     437              : /* }}} */
     438              : 
     439              : /* {{{ proto array \Cairo\Surface::getFallbackResolution()
     440              :        This function returns the previous fallback resolution */
     441            2 : PHP_METHOD(Cairo_Surface, getFallbackResolution)
     442              : {
     443              :     cairo_surface_object *surface_object;
     444              :     double x, y;
     445              : 
     446            2 :     ZEND_PARSE_PARAMETERS_NONE();
     447              : 
     448            2 :     surface_object = cairo_surface_object_get(getThis());
     449            1 :     if (!surface_object) {
     450            0 :         RETURN_THROWS();
     451              :     }
     452              : 
     453            1 :     cairo_surface_get_fallback_resolution(surface_object->surface, &x, &y);
     454              : 
     455            1 :     array_init(return_value);
     456            1 :     add_assoc_double(return_value, "x", x);
     457            1 :     add_assoc_double(return_value, "y", y);
     458              : }
     459              : /* }}} */
     460              : 
     461              : /* {{{ proto \Cairo\Surface\Type \Cairo\Surface::getType()
     462              :        This function returns the type of the backend used to create a surface. */
     463            2 : PHP_METHOD(Cairo_Surface, getType)
     464              : {
     465              :     cairo_surface_object *surface_object;
     466              :     zval surface_case;
     467              : 
     468            3 :     ZEND_PARSE_PARAMETERS_NONE();
     469              : 
     470            2 :     surface_object = cairo_surface_object_get(getThis());
     471            1 :     if (!surface_object) {
     472            0 :         RETURN_THROWS();
     473              :     }
     474              : 
     475            1 :     surface_case = php_enum_from_cairo_c_enum(
     476              :         ce_cairo_surfacetype,
     477            1 :         cairo_surface_get_type(surface_object->surface)
     478              :     );
     479              : 
     480            1 :     if (Z_TYPE(surface_case) == IS_OBJECT) {
     481            2 :         RETURN_ZVAL(&surface_case, 1, 1);
     482              :     }
     483              : }
     484              : /* }}} */
     485              : 
     486              : /* {{{ proto void \Cairo\Surface::showPage()
     487              :        Emits and clears the current page for backends that support multiple pages.
     488              :        Same as CairoContext->showPage(); */
     489            2 : PHP_METHOD(Cairo_Surface, showPage)
     490              : {
     491              :     cairo_surface_object *surface_object;
     492              : 
     493            2 :     ZEND_PARSE_PARAMETERS_NONE();
     494              : 
     495            2 :     surface_object = cairo_surface_object_get(getThis());
     496            1 :     if (!surface_object) {
     497            0 :         RETURN_THROWS();
     498              :     }
     499              : 
     500            1 :     cairo_surface_show_page(surface_object->surface);
     501              : }
     502              : /* }}} */
     503              : 
     504              : /* {{{ proto void \Cairo\Surface::copyPage()
     505              :        Emits the current page for backends that support multiple pages,
     506              :        but doesn't clear it, so that the contents of the current page will be retained for the next page.
     507              :        Same as CairoContext->copyPage(); */
     508            2 : PHP_METHOD(Cairo_Surface, copyPage)
     509              : {
     510              :     cairo_surface_object *surface_object;
     511              : 
     512            2 :     ZEND_PARSE_PARAMETERS_NONE();
     513              : 
     514            2 :     surface_object = cairo_surface_object_get(getThis());
     515            1 :     if (!surface_object) {
     516            0 :         RETURN_THROWS();
     517              :     }
     518              : 
     519            1 :     cairo_surface_copy_page(surface_object->surface);
     520              : }
     521              : /* }}} */
     522              : 
     523              : /* {{{ proto bool \Cairo\Surface::hasShowTextGlyphs()
     524              :        Returns whether the surface supports sophisticated cairo_show_text_glyphs() operations
     525              :        Users can use this function to avoid computing UTF-8 text and cluster mapping if the target surface does not use it. */
     526            2 : PHP_METHOD(Cairo_Surface, hasShowTextGlyphs)
     527              : {
     528              :     cairo_surface_object *surface_object;
     529              : 
     530            2 :     ZEND_PARSE_PARAMETERS_NONE();
     531              : 
     532            2 :     surface_object = cairo_surface_object_get(getThis());
     533            1 :     if (!surface_object) {
     534            0 :         RETURN_THROWS();
     535              :     }
     536              : 
     537            1 :     RETURN_BOOL(cairo_surface_has_show_text_glyphs(surface_object->surface));
     538              : }
     539              : /* }}} */
     540              : 
     541              : /* {{{ proto CairoSurface object \Cairo\Surface::mapToImage([\Cairo\Rectangle rectangle])
     542              :        .... */
     543            6 : PHP_METHOD(Cairo_Surface, mapToImage)
     544              : {
     545              :     cairo_surface_object *surface_object, *new_surface_object;
     546              :     cairo_surface_t *new_surface;
     547            6 :     zval *rectangle_zval = NULL;
     548              :     cairo_rectangle_object *rectangle_object;
     549              :     cairo_rectangle_int_t int_rect;
     550              : 
     551            6 :     ZEND_PARSE_PARAMETERS_START(0, 1)
     552            5 :         Z_PARAM_OPTIONAL
     553            9 :         Z_PARAM_OBJECT_OF_CLASS(rectangle_zval, ce_cairo_rectangle)
     554            6 :     ZEND_PARSE_PARAMETERS_END();
     555              : 
     556            8 :     surface_object = cairo_surface_object_get(getThis());
     557            4 :     if (!surface_object) {
     558            0 :         RETURN_THROWS();
     559              :     }
     560              : 
     561            7 :     if (rectangle_zval != NULL && Z_TYPE_P(rectangle_zval) == IS_OBJECT) {
     562            3 :         rectangle_object = Z_CAIRO_RECTANGLE_P(rectangle_zval);
     563            3 :         int_rect = cairo_expand_to_rectangle_int(rectangle_object->rect);
     564            3 :         new_surface = cairo_surface_map_to_image(surface_object->surface, &int_rect);
     565            3 :         cairo_surface_reference(new_surface);
     566              :     } else {
     567            1 :         new_surface = cairo_surface_map_to_image(surface_object->surface, NULL);
     568              :     }
     569              : 
     570            4 :     object_init_ex(return_value, php_cairo_get_imagesurface_ce());
     571            4 :     new_surface_object = Z_CAIRO_SURFACE_P(return_value);
     572            4 :     if (!new_surface_object) {
     573            0 :         RETURN_NULL();
     574              :     }
     575              : 
     576            4 :     new_surface_object->surface = new_surface;
     577            4 :     if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
     578            0 :         RETURN_THROWS();
     579              :     }
     580              : }
     581              : /* }}} */
     582              : 
     583              : /* {{{ proto CairoSurface object \Cairo\Surface::unmapImage([\Cairo\Sourface\Image image_surface])
     584              :        .... */
     585            4 : PHP_METHOD(Cairo_Surface, unmapImage)
     586              : {
     587              :     cairo_surface_object *surface_object, *image_surface_object;
     588              :     zval *image_surface_zval;
     589              : 
     590            4 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     591            4 :         Z_PARAM_OBJECT_OF_CLASS(image_surface_zval, ce_cairo_imagesurface)
     592            4 :     ZEND_PARSE_PARAMETERS_END();
     593              : 
     594            2 :     surface_object = cairo_surface_object_get(getThis());
     595            1 :     if (!surface_object) {
     596            0 :         RETURN_THROWS();
     597              :     }
     598              : 
     599            1 :     image_surface_object = cairo_surface_object_get(image_surface_zval);
     600            1 :     if (!image_surface_object) {
     601            0 :         RETURN_THROWS();
     602              :     }
     603              : 
     604            1 :     cairo_surface_unmap_image(surface_object->surface, image_surface_object->surface);
     605              : 
     606            1 :     if (php_cairo_throw_exception(cairo_surface_status(surface_object->surface))) {
     607            0 :         RETURN_THROWS();
     608              :     }
     609              : }
     610              : /* }}} */
     611              : 
     612              : 
     613              : #ifdef CAIRO_HAS_PNG_FUNCTIONS
     614              : /* {{{ proto void \Cairo\Surface::writeToPng(file|resource file)
     615              :        Writes the contents of surface to a new file filename or PHP stream as a PNG image.
     616              :        Unlike some other stream supporting functions, you may NOT pass a null filename */
     617            6 : PHP_METHOD(Cairo_Surface, writeToPng)
     618              : {
     619              :     cairo_surface_object *surface_object;
     620            6 :     zval *stream_zval = NULL;
     621              :     stream_closure *closure;
     622            6 :     php_stream *stream = NULL;
     623            6 :     bool owned_stream = false;
     624              :     cairo_status_t status;
     625              : 
     626            6 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     627            4 :         Z_PARAM_ZVAL(stream_zval)
     628            8 :     ZEND_PARSE_PARAMETERS_END();
     629              : 
     630            8 :     surface_object = cairo_surface_object_get(getThis());
     631            4 :     if (!surface_object) {
     632            0 :         RETURN_THROWS();
     633              :     }
     634              : 
     635            8 :     if (Z_TYPE_P(stream_zval) == IS_STRING && Z_STRLEN_P(stream_zval) > 0) {
     636            1 :         stream = php_stream_open_wrapper(Z_STRVAL_P(stream_zval), "w+b", REPORT_ERRORS, NULL);
     637            1 :         owned_stream = 1;
     638            6 :     } else if (Z_TYPE_P(stream_zval) == IS_RESOURCE)  {
     639            1 :         php_stream_from_zval(stream, stream_zval);
     640              :     } else {
     641            2 :         zend_throw_exception(ce_cairo_exception, "Cairo\\Surface::writeToPng() expects parameter 1 to be a (not empty) string or a stream resource", 0);
     642            2 :         RETURN_THROWS();
     643              :     }
     644              : 
     645              :     /* Pack stream into struct */
     646            2 :     closure = ecalloc(1, sizeof(stream_closure));
     647            2 :     closure->stream = stream;
     648            2 :     closure->owned_stream = owned_stream;
     649              : 
     650            2 :     status = cairo_surface_write_to_png_stream(surface_object->surface, php_cairo_write_func, (void *)closure);
     651            2 :     if (owned_stream) {
     652            1 :         php_stream_close(stream);
     653              :     }
     654            2 :     efree(closure);
     655              : 
     656            2 :     if (php_cairo_throw_exception(status)) {
     657            0 :         RETURN_THROWS();
     658              :     }
     659              : }
     660              : /* }}} */
     661              : #endif
     662              : 
     663              : 
     664              : #ifdef CAIRO_HAS_JPEG_FUNCTIONS
     665              : /* {{{ proto void \Cairo\Surface::writeToJpeg(file|resource file)
     666              :        Writes the contents of surface to a new file filename or PHP stream as a JPEG image.
     667              :        Unlike some other stream supporting functions, you may NOT pass a null filename */
     668            6 : PHP_METHOD(Cairo_Surface, writeToJpeg)
     669              : {
     670              :     cairo_surface_object *surface_object;
     671            6 :     zval *stream_zval = NULL;
     672              :     stream_closure *closure;
     673            6 :     php_stream *stream = NULL;
     674            6 :     bool owned_stream = false;
     675              :     cairo_status_t status;
     676            6 :     double quality = 90;
     677              : 
     678            6 :     ZEND_PARSE_PARAMETERS_START(1, 2)
     679            4 :         Z_PARAM_ZVAL(stream_zval)
     680            4 :         Z_PARAM_OPTIONAL
     681            4 :         Z_PARAM_DOUBLE(quality)
     682            6 :     ZEND_PARSE_PARAMETERS_END();
     683              : 
     684            8 :     surface_object = cairo_surface_object_get(getThis());
     685            4 :     if (!surface_object) {
     686            0 :         RETURN_THROWS();
     687              :     }
     688              : 
     689            8 :     if (Z_TYPE_P(stream_zval) == IS_STRING && Z_STRLEN_P(stream_zval) > 0) {
     690            1 :         stream = php_stream_open_wrapper(Z_STRVAL_P(stream_zval), "w+b", REPORT_ERRORS, NULL);
     691            1 :         owned_stream = 1;
     692            6 :     } else if (Z_TYPE_P(stream_zval) == IS_RESOURCE)  {
     693            1 :         php_stream_from_zval(stream, stream_zval);
     694              :     } else {
     695            2 :         zend_throw_exception(ce_cairo_exception, "Cairo\\Surface::writeToJpeg() expects parameter 1 to be a (not empty) string or a stream resource", 0);
     696            2 :         RETURN_THROWS();
     697              :     }
     698              : 
     699              :     /* Pack stream into struct */
     700            2 :     closure = ecalloc(1, sizeof(stream_closure));
     701            2 :     closure->stream = stream;
     702            2 :     closure->owned_stream = owned_stream;
     703              : 
     704            2 :     status = cairo_image_surface_write_to_jpeg_stream(
     705              :         surface_object->surface,
     706              :         php_cairo_write_func,
     707              :         (void *)closure,
     708              :         quality
     709              :     );
     710            2 :     if (owned_stream) {
     711            1 :         php_stream_close(stream);
     712              :     }
     713            2 :     efree(closure);
     714              : 
     715            2 :     if (php_cairo_throw_exception(status)) {
     716            0 :         RETURN_THROWS();
     717              :     }
     718              : }
     719              : /* }}} */
     720              : #endif
     721              : 
     722              : 
     723              : /* ----------------------------------------------------------------
     724              :     Cairo\Surface Object management
     725              : ------------------------------------------------------------------*/
     726              : 
     727              : /* {{{ */
     728          227 : static void cairo_surface_free_obj(zend_object *object)
     729              : {
     730          227 :     cairo_surface_object *intern = cairo_surface_fetch_object(object);
     731              : 
     732          227 :     if (!intern) {
     733            0 :         return;
     734              :     }
     735              : 
     736              :     /* buffer for the create_from_data image stuff */
     737          227 :     if (intern->buffer) {
     738            1 :         efree(intern->buffer);
     739            1 :         intern->buffer = NULL;
     740              :     }
     741              : 
     742          227 :     if (intern->surface) {
     743          189 :         cairo_surface_finish(intern->surface);
     744          189 :         cairo_surface_destroy(intern->surface);
     745          189 :         intern->surface = NULL;
     746              :     }
     747              : 
     748              :     /* closure free up time */
     749          227 :     if (intern->closure) {
     750            8 :         if (intern->closure->owned_stream == 1) {
     751            3 :             php_stream_close(intern->closure->stream);
     752              :         }
     753            8 :         efree(intern->closure);
     754            8 :         intern->closure = NULL;
     755              :     }
     756              : 
     757          227 :     zval_ptr_dtor(&intern->parent_zval);
     758              : 
     759          227 :     zend_object_std_dtor(&intern->std);
     760              : }
     761              : /* }}} */
     762              : 
     763              : /* {{{ */
     764          227 : static zend_object* cairo_surface_obj_ctor(zend_class_entry *ce, cairo_surface_object **intern)
     765              : {
     766          227 :     cairo_surface_object *object = ecalloc(1, sizeof(cairo_surface_object) + zend_object_properties_size(ce));
     767              : 
     768          227 :     object->surface = NULL;
     769          227 :     object->buffer = NULL;
     770          227 :     object->closure = NULL;
     771          227 :     ZVAL_UNDEF(&object->parent_zval);
     772              : 
     773          227 :     zend_object_std_init(&object->std, ce);
     774          227 :     object->std.handlers = &cairo_surface_object_handlers;
     775          227 :     *intern = object;
     776              : 
     777          227 :     return &object->std;
     778              : }
     779              : /* }}} */
     780              : 
     781              : /* {{{ */
     782          227 : zend_object* cairo_surface_create_object(zend_class_entry *ce)
     783              : {
     784          227 :     cairo_surface_object *surface = NULL;
     785          227 :     zend_object *return_value = cairo_surface_obj_ctor(ce, &surface);
     786              : 
     787          227 :     object_properties_init(&surface->std, ce);
     788          227 :     return return_value;
     789              : }
     790              : /* }}} */
     791              : 
     792              : 
     793              : /* ----------------------------------------------------------------
     794              :     Cairo\Surface C API
     795              : ------------------------------------------------------------------*/
     796              : 
     797              : /* Helper methods for stream surface read/writes */
     798          260 : cairo_status_t php_cairo_write_func(void *closure, const unsigned char *data, unsigned int length)
     799              : {
     800              :     size_t written;
     801              :     stream_closure *cast_closure;
     802              : 
     803          260 :     cast_closure = (stream_closure *)closure;
     804              : 
     805          260 :     written = php_stream_write(cast_closure->stream, data, length);
     806          260 :     if (written == length) {
     807          260 :         return CAIRO_STATUS_SUCCESS;
     808              :     }
     809              : 
     810            0 :     return CAIRO_STATUS_WRITE_ERROR;
     811              : }
     812              : 
     813          650 : cairo_status_t php_cairo_read_func(void *closure, const unsigned char *data, unsigned int length)
     814              : {
     815              :     unsigned int read;
     816              :     stream_closure *cast_closure;
     817              : 
     818          650 :     cast_closure = (stream_closure *)closure;
     819              : 
     820          650 :     read = php_stream_read(cast_closure->stream, (char *)data, length);
     821          650 :     if (read == length) {
     822          649 :         return CAIRO_STATUS_SUCCESS;
     823              :     }
     824              : 
     825            1 :     return CAIRO_STATUS_READ_ERROR;
     826              : }
     827              : 
     828            3 : zend_class_entry* php_cairo_get_surface_ce(cairo_surface_t *surface)
     829              : {
     830              :     zend_class_entry *type;
     831              : 
     832            3 :     if (surface == NULL) {
     833            0 :         return ce_cairo_surface;
     834              :     }
     835              : 
     836            3 :     switch (cairo_surface_get_type(surface)) {
     837            3 :         case CAIRO_SURFACE_TYPE_IMAGE:
     838            3 :             type = ce_cairo_imagesurface;
     839            3 :             break;
     840              : 
     841              : #ifdef CAIRO_HAS_PDF_SURFACE
     842            0 :         case CAIRO_SURFACE_TYPE_PDF:
     843            0 :             type = ce_cairo_pdfsurface;
     844            0 :             break;
     845              : #endif
     846              : #ifdef CAIRO_HAS_SVG_SURFACE
     847            0 :         case CAIRO_SURFACE_TYPE_SVG:
     848            0 :             type = ce_cairo_svgsurface;
     849            0 :             break;
     850              : #endif
     851              : 
     852              : #ifdef CAIRO_HAS_PS_SURFACE
     853            0 :         case CAIRO_SURFACE_TYPE_PS:
     854            0 :             type = ce_cairo_pssurface;
     855            0 :             break;
     856              : #endif
     857              : 
     858              : #ifdef CAIRO_HAS_RECORDING_SURFACE
     859            0 :         case CAIRO_SURFACE_TYPE_RECORDING:
     860            0 :             type = ce_cairo_recordingsurface;
     861            0 :             break;
     862              : #endif
     863              : /*
     864              : #ifdef CAIRO_HAS_WIN32_SURFACE
     865              :         case CAIRO_SURFACE_TYPE_WIN32:
     866              :             type = get_CairoWin32Surface_ce_ptr();
     867              :             break;
     868              : #endif
     869              : #ifdef CAIRO_HAS_XLIB_SURFACE
     870              :         case CAIRO_SURFACE_TYPE_XLIB:
     871              :             type = get_CairoXlibSurface_ce_ptr();
     872              :             break;
     873              : #endif
     874              : #ifdef CAIRO_HAS_QUARTZ_SURFACE
     875              :         case CAIRO_SURFACE_TYPE_QUARTZ:
     876              :             type = get_CairoQuartzSurface_ce_ptr();
     877              :             break;
     878              : #endif */
     879              : 
     880            0 :         case CAIRO_SURFACE_TYPE_SUBSURFACE:
     881            0 :             type = ce_cairo_subsurface;
     882            0 :             break;
     883              : 
     884            0 :         default:
     885            0 :             php_error(E_WARNING, "Unsupported Cairo Surface Type");
     886            0 :             return NULL;
     887              :     }
     888            3 :     return type;
     889              : }
     890              : 
     891              : /* ----------------------------------------------------------------
     892              :     Cairo\Surface Definition and registration
     893              : ------------------------------------------------------------------*/
     894              : 
     895              : /* {{{ PHP_MINIT_FUNCTION */
     896          424 : PHP_MINIT_FUNCTION(cairo_surface)
     897              : {
     898          424 :     memcpy(
     899              :         &cairo_surface_object_handlers,
     900              :         zend_get_std_object_handlers(),
     901              :         sizeof(cairo_surface_object_handlers)
     902              :     );
     903              : 
     904              :     /* Surface */
     905          424 :     cairo_surface_object_handlers.offset = XtOffsetOf(cairo_surface_object, std);
     906          424 :     cairo_surface_object_handlers.free_obj = cairo_surface_free_obj;
     907              : 
     908          424 :     ce_cairo_surface = register_class_Cairo_Surface();
     909          424 :     ce_cairo_surface->create_object = cairo_surface_create_object;
     910              : 
     911              :     /* CairoContent */
     912          424 :     ce_cairo_content = register_class_Cairo_Surface_Content();
     913              : 
     914              :     /* SurfaceType */
     915          424 :     ce_cairo_surfacetype = register_class_Cairo_Surface_Type();
     916              : 
     917          424 :     return SUCCESS;
     918              : }
        

Generated by: LCOV version 2.0-1