LCOV - code coverage report
Current view: top level - src - ft_font.c (source / functions) Coverage Total Hit
Test: PHP Cairo Extension Coverage Lines: 84.5 % 116 98
Test Date: 2025-10-09 18:11:12 Functions: 100.0 % 8 8

            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 "ft_font_arginfo.h"
      26              : 
      27              : #if defined(CAIRO_HAS_FT_FONT) && defined(HAVE_FREETYPE)
      28              : 
      29              : php_cairo_ft_error php_cairo_ft_errors[] =
      30              : #include FT_ERRORS_H
      31              : 
      32              : #include <fontconfig/fontconfig.h>
      33              : 
      34              : 
      35              : zend_class_entry *ce_cairo_ftfont;
      36              : 
      37              : /* Functions for stream handling */
      38          347 : static unsigned long php_cairo_ft_read_func(
      39              :     FT_Stream stream,
      40              :     unsigned long offset,
      41              :     unsigned char* buffer,
      42              :     unsigned long count
      43              : ) {
      44              :     stream_closure *closure;
      45          347 :     closure = (stream_closure *)stream->descriptor.pointer;
      46          347 :     php_stream_seek(closure->stream, offset, SEEK_SET);
      47          347 :     return php_stream_read(closure->stream, (char *)buffer, count);
      48              : }
      49              : 
      50            5 : static void cairo_user_data_callback_ft_free(pecl_ft_container *ft_container) {
      51            5 :     if (ft_container->ft_face != NULL) {
      52            5 :         FT_Done_Face(ft_container->ft_face);
      53              :     }
      54              : 
      55            5 :     if (ft_container->ft_stream != NULL) {
      56            5 :         pefree(ft_container->ft_stream, 1);
      57              :     }
      58              : 
      59            5 :     if (ft_container->ft_lib != NULL) {
      60            5 :         FT_Done_FreeType(ft_container->ft_lib);
      61              :     }
      62              : 
      63            5 :     pefree(ft_container, 1);
      64            5 : }
      65              : 
      66            6 : static bool php_cairo_create_ft_font_face(
      67              :     pecl_ft_container *ft_container,
      68              :     cairo_font_face_object *font_face_object,
      69              :     php_stream *stream,
      70              :     bool owned_stream,
      71              :     int load_flags,
      72              :     bool throw_exceptions
      73              : ) {
      74              :     FT_Stream ft_stream;
      75              :     stream_closure *closure;
      76              :     php_stream_statbuf ssbuf;
      77              :     FT_Open_Args open_args;
      78              :     int error;
      79              : 
      80            6 :     if (php_stream_stat(stream, &ssbuf) < 0) {
      81            0 :         return 1;
      82              :     }
      83              : 
      84            6 :     ft_container->ft_face = NULL;
      85            6 :     ft_container->ft_stream = NULL;
      86              : 
      87            6 :     font_face_object->closure = NULL;
      88              : 
      89            6 :     closure = ecalloc(1, sizeof(stream_closure));
      90            6 :     closure->stream = stream;
      91            6 :     closure->owned_stream = owned_stream;
      92              : 
      93            6 :     ft_stream = pecalloc(1, sizeof(*ft_stream), 1);
      94            6 :     ft_stream->descriptor.pointer = (void *)closure;
      95            6 :     ft_stream->pos = php_stream_tell(stream);
      96            6 :     ft_stream->size = ssbuf.sb.st_size;
      97            6 :     ft_stream->read = php_cairo_ft_read_func;
      98            6 :     open_args.flags = FT_OPEN_STREAM;
      99            6 :     open_args.stream = ft_stream;
     100              : 
     101            6 :     error = FT_Open_Face(ft_container->ft_lib, &open_args, 0, &ft_container->ft_face);
     102              : 
     103            6 :     if (error) {
     104            1 :         if (owned_stream) {
     105            1 :             php_stream_close(stream);
     106              :         }
     107            1 :         efree(closure);
     108            1 :         pefree(ft_stream, 1);
     109              : 
     110            1 :         return error;
     111              :     }
     112              : 
     113            5 :     font_face_object->closure = closure;
     114              : 
     115            5 :     ft_container->ft_stream = ft_stream;
     116            5 :     font_face_object->font_face = (cairo_font_face_t *)cairo_ft_font_face_create_for_ft_face(ft_container->ft_face, (int)load_flags);
     117              : 
     118              :     /* Set Cairo to automatically destroy the FT_Face when the cairo_font_face_t is destroyed */
     119           10 :     error = cairo_font_face_set_user_data(
     120              :         font_face_object->font_face,
     121            5 :         &font_face_object->key,
     122              :         ft_container,
     123              :         (cairo_destroy_func_t) cairo_user_data_callback_ft_free
     124              :     );
     125              : 
     126              : 
     127            5 :     if (error) {
     128            0 :         cairo_font_face_destroy (font_face_object->font_face);
     129            0 :         FT_Done_Face(ft_container->ft_face);
     130            0 :         pefree(ft_stream, 1);
     131            0 :         return error;
     132              :     }
     133              : 
     134            5 :     return 0;
     135              : }
     136              : 
     137              : /* ----------------------------------------------------------------
     138              :     \Cairo\FontFace\Ft Class API
     139              : ------------------------------------------------------------------*/
     140              : 
     141              : /* {{{ proto \Cairo\FontFace\Ft::__construct(string fontFilename, long load_flags)
     142              :        Creates a new font face for the FreeType font backend from a pre-opened FreeType face. */
     143            9 : PHP_METHOD(Cairo_FontFace_Ft, __construct)
     144              : {
     145            9 :     zend_long load_flags = 0;
     146            9 :     int error = 0;
     147            9 :     zval *stream_zval = NULL;
     148              :     cairo_font_face_object *font_face_object;
     149              :     pecl_ft_container *ft_container;
     150              : 
     151              :     php_stream *stream;
     152            9 :     bool owned_stream = 0;
     153              :     php_stream_statbuf ssbuf;
     154              : 
     155            9 :     ZEND_PARSE_PARAMETERS_START(1, 2)
     156            8 :         Z_PARAM_ZVAL(stream_zval)
     157            8 :         Z_PARAM_OPTIONAL
     158            9 :         Z_PARAM_LONG(load_flags)
     159            9 :     ZEND_PARSE_PARAMETERS_END();
     160              : 
     161           16 :     if (Z_TYPE_P(stream_zval) == IS_STRING) {
     162            7 :         stream = php_stream_open_wrapper(Z_STRVAL_P(stream_zval), "rb", REPORT_ERRORS, NULL);
     163            7 :         owned_stream = 1;
     164            2 :     } else if (Z_TYPE_P(stream_zval) == IS_RESOURCE)  {
     165            0 :         php_stream_from_zval(stream, stream_zval);
     166              :     } else {
     167            1 :         zend_throw_exception(ce_cairo_exception,
     168              :             "Cairo\\FontFace\\Ft::__construct() expects parameter 1 to be a string or a stream resource",
     169              :             0
     170              :         );
     171            1 :         RETURN_THROWS();
     172              :     }
     173              : 
     174            7 :     if (!stream) {
     175            1 :         RETURN_NULL();
     176              :     }
     177              : 
     178            6 :     if (php_stream_stat(stream, &ssbuf) != 0) {
     179            0 :         zend_throw_exception(ce_cairo_exception, "Cannot determine size of stream", 0);
     180            0 :         RETURN_THROWS();
     181              :     }
     182              : 
     183           12 :     font_face_object = Z_CAIRO_FONT_FACE_P(getThis());
     184            6 :     if (!font_face_object) {
     185            0 :         RETURN_NULL();
     186              :     }
     187              : 
     188            6 :     ft_container = pecalloc(1, sizeof(pecl_ft_container), 1);
     189              : 
     190            6 :     error = FT_Init_FreeType(&ft_container->ft_lib);
     191            6 :     if (error) {
     192            0 :         pefree(ft_container, 1);
     193            0 :         zend_throw_exception(ce_cairo_exception, "Failed to initalise FreeType library", 0);
     194            0 :         RETURN_THROWS();
     195              :     }
     196              : 
     197            6 :     error = php_cairo_create_ft_font_face(ft_container, font_face_object, stream, owned_stream, load_flags, 1);
     198              : 
     199            6 :     if (error) {
     200            1 :         const char *err_string = php_cairo_get_ft_error(error);
     201            1 :         zend_throw_exception_ex(ce_cairo_exception, error,
     202              :             "Cairo\\FontFace\\Ft::__construct(): An error occurred opening the file %s",
     203              :             err_string
     204              :         );
     205            1 :         pefree(ft_container, 1);
     206            1 :         RETURN_THROWS();
     207              :     }
     208              : 
     209            5 :     if (php_cairo_throw_exception(cairo_font_face_status(font_face_object->font_face))) {
     210            0 :         RETURN_THROWS();
     211              :     }
     212              : }
     213              : /* }}} */
     214              : 
     215            7 : PHP_METHOD(Cairo_FontFace_Ft, getSynthesize)
     216              : {
     217              :     cairo_font_face_object *font_face_object;
     218              :     zend_long synth_flags;
     219              : 
     220            7 :     ZEND_PARSE_PARAMETERS_NONE();
     221              : 
     222           12 :     font_face_object = Z_CAIRO_FONT_FACE_P(getThis());
     223            6 :     if (!font_face_object) {
     224            0 :         RETURN_NULL();
     225              :     }
     226              : 
     227            6 :     synth_flags = cairo_ft_font_face_get_synthesize(font_face_object->font_face);
     228              : 
     229            6 :     RETURN_LONG(synth_flags);
     230              : }
     231              : 
     232            6 : PHP_METHOD(Cairo_FontFace_Ft, setSynthesize)
     233              : {
     234              :     cairo_font_face_object *font_face_object;
     235              :     zend_long synth_flags;
     236              : 
     237            6 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     238            8 :         Z_PARAM_LONG(synth_flags);
     239            6 :     ZEND_PARSE_PARAMETERS_END();
     240              : 
     241            6 :     font_face_object = Z_CAIRO_FONT_FACE_P(getThis());
     242            3 :     if (!font_face_object) {
     243            0 :         RETURN_NULL();
     244              :     }
     245              : 
     246            3 :     cairo_ft_font_face_set_synthesize(
     247              :         font_face_object->font_face,
     248              :         synth_flags
     249              :     );
     250              : 
     251            3 :     if (php_cairo_throw_exception(cairo_font_face_status(font_face_object->font_face))) {
     252            0 :         RETURN_THROWS();
     253              :     }
     254              : }
     255              : 
     256            5 : PHP_METHOD(Cairo_FontFace_Ft, unsetSynthesize)
     257              : {
     258              :     cairo_font_face_object *font_face_object;
     259              :     zend_long synth_flags;
     260              : 
     261            5 :     ZEND_PARSE_PARAMETERS_START(1, 1)
     262            6 :         Z_PARAM_LONG(synth_flags);
     263            5 :     ZEND_PARSE_PARAMETERS_END();
     264              : 
     265            4 :     font_face_object = Z_CAIRO_FONT_FACE_P(getThis());
     266            2 :     if (!font_face_object) {
     267            0 :         RETURN_NULL();
     268              :     }
     269              : 
     270            2 :     cairo_ft_font_face_unset_synthesize(
     271              :         font_face_object->font_face,
     272              :         synth_flags
     273              :     );
     274              : 
     275            2 :     if (php_cairo_throw_exception(cairo_font_face_status(font_face_object->font_face))) {
     276            0 :         RETURN_THROWS();
     277              :     }
     278              : }
     279              : 
     280              : /* ----------------------------------------------------------------
     281              :     \Cairo\FontFace\Ft Definition and registration
     282              : ------------------------------------------------------------------*/
     283              : 
     284              : /* {{{ PHP_MINIT_FUNCTION */
     285          433 : PHP_MINIT_FUNCTION(cairo_ft_font)
     286              : {
     287          433 :     ce_cairo_ftfont = register_class_Cairo_FontFace_Ft(php_cairo_get_fontface_ce());
     288              : 
     289          433 :     return SUCCESS;
     290              : }
     291              : /* }}} */
     292              : 
     293              : #endif
        

Generated by: LCOV version 2.0-1