LCOV - code coverage report
Current view: top level - src - ft_font.c (source / functions) Coverage Total Hit
Test: PHP Cairo Extension Coverage Lines: 85.4 % 89 76
Test Date: 2025-09-10 21:28:33 Functions: 100.0 % 5 5

            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          140 : 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          140 :     closure = (stream_closure *)stream->descriptor.pointer;
      46          140 :     php_stream_seek(closure->stream, offset, SEEK_SET);
      47          140 :     return php_stream_read(closure->stream, (char *)buffer, count);
      48              : }
      49              : 
      50            2 : static void cairo_user_data_callback_ft_free(pecl_ft_container *ft_container) {
      51            2 :     if (ft_container->ft_face != NULL) {
      52            2 :         FT_Done_Face(ft_container->ft_face);
      53              :     }
      54              : 
      55            2 :     if (ft_container->ft_stream != NULL) {
      56            2 :         pefree(ft_container->ft_stream, 1);
      57              :     }
      58              : 
      59            2 :     if (ft_container->ft_lib != NULL) {
      60            2 :         FT_Done_FreeType(ft_container->ft_lib);
      61              :     }
      62              : 
      63            2 :     pefree(ft_container, 1);
      64            2 : }
      65              : 
      66            3 : 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            3 :     if (php_stream_stat(stream, &ssbuf) < 0) {
      81            0 :         return 1;
      82              :     }
      83              : 
      84            3 :     ft_container->ft_face = NULL;
      85            3 :     ft_container->ft_stream = NULL;
      86              : 
      87            3 :     font_face_object->closure = NULL;
      88              : 
      89            3 :     closure = ecalloc(1, sizeof(stream_closure));
      90            3 :     closure->stream = stream;
      91            3 :     closure->owned_stream = owned_stream;
      92              : 
      93            3 :     ft_stream = pecalloc(1, sizeof(*ft_stream), 1);
      94            3 :     ft_stream->descriptor.pointer = (void *)closure;
      95            3 :     ft_stream->pos = php_stream_tell(stream);
      96            3 :     ft_stream->size = ssbuf.sb.st_size;
      97            3 :     ft_stream->read = php_cairo_ft_read_func;
      98            3 :     open_args.flags = FT_OPEN_STREAM;
      99            3 :     open_args.stream = ft_stream;
     100              : 
     101            3 :     error = FT_Open_Face(ft_container->ft_lib, &open_args, 0, &ft_container->ft_face);
     102              : 
     103            3 :     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            2 :     font_face_object->closure = closure;
     114              : 
     115            2 :     ft_container->ft_stream = ft_stream;
     116            2 :     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            4 :     error = cairo_font_face_set_user_data (
     120              :         font_face_object->font_face,
     121            2 :         &font_face_object->key,
     122              :         ft_container,
     123              :         (cairo_destroy_func_t) cairo_user_data_callback_ft_free
     124              :     );
     125              : 
     126              : 
     127            2 :     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            2 :     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            6 : PHP_METHOD(Cairo_FontFace_Ft, __construct)
     144              : {
     145            6 :     zend_long load_flags = 0;
     146            6 :     int error = 0;
     147            6 :     zval *stream_zval = NULL;
     148              :     cairo_font_face_object *font_face_object;
     149              :     pecl_ft_container *ft_container;
     150              : 
     151              :     php_stream *stream;
     152            6 :     bool owned_stream = 0;
     153              :     php_stream_statbuf ssbuf;
     154              : 
     155            6 :     ZEND_PARSE_PARAMETERS_START(1, 2)
     156            5 :         Z_PARAM_ZVAL(stream_zval)
     157            5 :         Z_PARAM_OPTIONAL
     158            6 :         Z_PARAM_LONG(load_flags)
     159            6 :     ZEND_PARSE_PARAMETERS_END();
     160              : 
     161           10 :     if (Z_TYPE_P(stream_zval) == IS_STRING) {
     162            4 :         stream = php_stream_open_wrapper(Z_STRVAL_P(stream_zval), "rb", REPORT_ERRORS, NULL);
     163            4 :         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            4 :     if (!stream) {
     175            1 :         RETURN_NULL();
     176              :     }
     177              : 
     178            3 :     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            6 :     font_face_object = Z_CAIRO_FONT_FACE_P(getThis());
     184            3 :     if (!font_face_object) {
     185            0 :         RETURN_NULL();
     186              :     }
     187              : 
     188            3 :     ft_container = pecalloc(1, sizeof(pecl_ft_container), 1);
     189              : 
     190            3 :     error = FT_Init_FreeType(&ft_container->ft_lib);
     191            3 :     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            3 :     error = php_cairo_create_ft_font_face(ft_container, font_face_object, stream, owned_stream, load_flags, 1);
     198              : 
     199            3 :     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            2 :     if (php_cairo_throw_exception(cairo_font_face_status(font_face_object->font_face))) {
     210            0 :         RETURN_THROWS();
     211              :     }
     212              : }
     213              : /* }}} */
     214              : 
     215              : /* ----------------------------------------------------------------
     216              :     \Cairo\FontFace\Ft Definition and registration
     217              : ------------------------------------------------------------------*/
     218              : 
     219              : /* {{{ PHP_MINIT_FUNCTION */
     220          424 : PHP_MINIT_FUNCTION(cairo_ft_font)
     221              : {
     222          424 :     ce_cairo_ftfont = register_class_Cairo_FontFace_Ft(php_cairo_get_fontface_ce());
     223              : 
     224          424 :     return SUCCESS;
     225              : }
     226              : /* }}} */
     227              : 
     228              : #endif
        

Generated by: LCOV version 2.0-1