Skip to content

Commit

Permalink
Fix memory management in FreeType fonts. Get Cairo to handle the life…
Browse files Browse the repository at this point in the history
…cycle of the FT_Face objects.
  • Loading branch information
mgdm committed Aug 13, 2011
1 parent baba970 commit 8052e8c
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 103 deletions.
21 changes: 2 additions & 19 deletions cairo.c
Expand Up @@ -41,8 +41,8 @@ PHP_GINIT_FUNCTION(cairo)

PHP_GSHUTDOWN_FUNCTION(cairo)
{
if(cairo_globals->ft_lib != NULL) {
FT_Done_FreeType(cairo_globals->ft_lib);
if (cairo_globals->ft_lib != NULL) {
FT_Done_Library(cairo_globals->ft_lib);
}
}

Expand Down Expand Up @@ -1208,23 +1208,6 @@ PHP_MSHUTDOWN_FUNCTION(cairo)
cairo_debug_reset_static_data();
#endif

#if defined(CAIRO_HAS_FT_FONT) && defined(HAVE_FREETYPE)
#ifdef ZTS
ts_allocate_id(&cairo_globals_id,
sizeof(zend_cairo_globals),
(ts_allocate_ctor)php_cairo_globals_ctor,
(ts_allocate_dtor)php_cairo_globals_dtor);
#else
php_cairo_globals_ctor(&cairo_globals TSRMLS_CC);
#endif
#endif

#if defined(CAIRO_HAS_FT_FONT) && defined(HAVE_FREETYPE)
#ifndef ZTS
php_cairo_globals_dtor(&cairo_globals TSRMLS_CC);
#endif
#endif

return SUCCESS;
}

Expand Down
166 changes: 84 additions & 82 deletions cairo_ft_font.c
Expand Up @@ -78,25 +78,82 @@ void php_cairo_ft_close_stream(FT_Stream stream)
efree(stream);
}

static zend_bool php_cairo_create_ft_font_face(cairo_ft_font_face_object *font_face_object, php_stream *stream, zend_bool owned_stream, int load_flags, zend_bool throw_exceptions TSRMLS_DC) {
FT_Library *ft_lib;
FT_Stream ft_stream;
FT_Face face;
stream_closure *closure;
php_stream_statbuf ssbuf;
FT_Open_Args open_args;
int error;

ft_lib = &CAIROG(ft_lib);
font_face_object->ft_face = NULL;
font_face_object->ft_stream = NULL;

closure = ecalloc(1, sizeof(stream_closure));
closure->stream = stream;
closure->owned_stream = owned_stream;
#ifdef ZTS
closure->TSRMLS_C = TSRMLS_C;
#endif

ft_stream = ecalloc(1, sizeof(*ft_stream));
ft_stream->descriptor.pointer = (void *)closure;
ft_stream->pos = php_stream_tell(stream);
ft_stream->size = ssbuf.sb.st_size;
ft_stream->read = php_cairo_ft_read_func;
/* ft_stream->close = php_cairo_ft_close_stream; */
open_args.flags = FT_OPEN_STREAM;
open_args.stream = ft_stream;

error = FT_Open_Face(*ft_lib, &open_args, 0, &face);

if (error) {
if (owned_stream) {
php_stream_close(stream);
}
efree(closure);
efree(ft_stream);

return error;
}

font_face_object->ft_stream = ft_stream;
font_face_object->font_face = (cairo_font_face_t *)cairo_ft_font_face_create_for_ft_face(face, (int)load_flags);

/* Set Cairo to automatically destroy the FT_Face when the cairo_font_face_t is destroyed */
error = cairo_font_face_set_user_data (
font_face_object->font_face,
&font_face_object->key,
face,
(cairo_destroy_func_t) FT_Done_Face);

if (error) {
cairo_font_face_destroy (font_face_object->font_face);
FT_Done_Face(face);
return error;
}

return 0;
}

/* {{{ proto CairoFtFontFace cairo_ft_font_face_create(string face, long load_flags)
Creates a new font face for the FreeType font backend from a pre-opened FreeType face. */

/* FIXME: Adapt this to use streams, to handle open_basedir etc */
PHP_FUNCTION(cairo_ft_font_face_create)
{
FT_Face face = (FT_Face) NULL;
FT_Face *face = NULL;
FT_Library *ft_lib;
long load_flags = 0;
int error = 0;
zval *stream_zval = NULL;
cairo_ft_font_face_object *font_face_object;

php_stream *stream;
stream_closure *closure;
zend_bool owned_stream = 0;
FT_Open_Args open_args;
FT_Stream ft_stream;
php_stream_statbuf ssbuf;
zend_bool owned_stream = 0;

PHP_CAIRO_ERROR_HANDLING(FALSE)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l",
Expand Down Expand Up @@ -138,49 +195,20 @@ PHP_FUNCTION(cairo_ft_font_face_create)
return;
}

closure = ecalloc(1, sizeof(stream_closure));
closure->stream = stream;
closure->owned_stream = owned_stream;
#ifdef ZTS
closure->TSRMLS_C = TSRMLS_C;
#endif

ft_stream = ecalloc(sizeof(*ft_stream), 1);
ft_stream->descriptor.pointer = (void *)closure;
ft_stream->pos = php_stream_tell(stream);
ft_stream->size = ssbuf.sb.st_size;
ft_stream->read = php_cairo_ft_read_func;
// ft_stream->close = php_cairo_ft_close_stream;
open_args.flags = FT_OPEN_STREAM;
open_args.stream = ft_stream;

/* FIXME: hard coding open first face, will change to allow it to be selected */
error = FT_Open_Face(*ft_lib, &open_args, 0, &face);
if(error == FT_Err_Unknown_File_Format) {
if(owned_stream) {
php_stream_close(stream);
}
efree(closure);
efree(ft_stream);

zend_error(E_WARNING, "cairo_ft_font_face_create(): unknown file format");
return;
} else if (error) {
if(owned_stream) {
php_stream_close(stream);
}
efree(closure);
efree(ft_stream);
object_init_ex(return_value, cairo_ce_cairoftfont);
font_face_object = (cairo_ft_font_face_object *)zend_object_store_get_object(return_value TSRMLS_CC);
error = php_cairo_create_ft_font_face(font_face_object, stream, owned_stream, load_flags, 0 TSRMLS_CC);

zend_error(E_WARNING, "cairo_ft_font_face_create(): An error occurred opening the file");
return;
}
if (error) {
if (error == FT_Err_Unknown_File_Format) {
zend_error(E_WARNING, "Unknown file format");
} else {
zend_error(E_WARNING, "Error %d occurred opening the file", error);
}

RETURN_NULL();
}

object_init_ex(return_value, cairo_ce_cairoftfont);
font_face_object = (cairo_ft_font_face_object *)zend_object_store_get_object(return_value TSRMLS_CC);
font_face_object->font_face = (cairo_font_face_t *)cairo_ft_font_face_create_for_ft_face(face, (int)load_flags);
font_face_object->ft_stream = ft_stream;
PHP_CAIRO_ERROR(cairo_font_face_status(font_face_object->font_face));
}

Expand Down Expand Up @@ -232,7 +260,6 @@ PHP_METHOD(CairoFtFontFace, __construct)
php_stream_from_zval(stream, &stream_zval);
} else {
PHP_CAIRO_RESTORE_ERRORS(TRUE)

zend_throw_exception(cairo_ce_cairoexception, "CairoFtFontFace::__construct() expects parameter 1 to be a string or a stream resource", 0 TSRMLS_CC);
return;
}
Expand All @@ -250,43 +277,18 @@ PHP_METHOD(CairoFtFontFace, __construct)
return;
}

closure = ecalloc(1, sizeof(stream_closure));
closure->stream = stream;
closure->owned_stream = owned_stream;
#ifdef ZTS
closure->TSRMLS_C = TSRMLS_C;
#endif

ft_stream = ecalloc(sizeof(*ft_stream), 1);
ft_stream->descriptor.pointer = (void *)closure;
ft_stream->pos = php_stream_tell(stream);
ft_stream->size = ssbuf.sb.st_size;
ft_stream->read = php_cairo_ft_read_func;
ft_stream->close = php_cairo_ft_close_stream;
open_args.flags = FT_OPEN_STREAM;
open_args.stream = ft_stream;

/* FIXME: hard coding open first face, will change to allow it to be selected */
error = FT_Open_Face(*ft_lib, &open_args, 0, &face);
if(error == FT_Err_Unknown_File_Format) {
if(owned_stream) {
php_stream_close(stream);
}

zend_throw_exception(cairo_ce_cairoexception, "CairoFtFontFace::__construct(): unknown file format", 0 TSRMLS_CC);
return;
} else if (error) {
if(owned_stream) {
php_stream_close(stream);
}

zend_throw_exception(cairo_ce_cairoexception, "CairoFtFontFace::__construct(): An error occurred opening the file", 0 TSRMLS_CC);
return;
}

font_face_object = (cairo_ft_font_face_object *)zend_object_store_get_object(getThis() TSRMLS_CC);
font_face_object->ft_stream = ft_stream;
font_face_object->font_face = (cairo_font_face_t *)cairo_ft_font_face_create_for_ft_face(face, (int)load_flags);
error = php_cairo_create_ft_font_face(font_face_object, stream, owned_stream, load_flags, 1 TSRMLS_CC);

if (error) {
if (error == FT_Err_Unknown_File_Format) {
zend_throw_exception(cairo_ce_cairoexception, "CairoFtFontFace::__construct(): unknown file format", error TSRMLS_CC);
return;
} else {
zend_throw_exception(cairo_ce_cairoexception, "CairoFtFontFace::__construct(): An error occurred opening the file", error TSRMLS_CC);
return;
}
}

php_cairo_throw_exception(cairo_font_face_status(font_face_object->font_face) TSRMLS_CC);
}
Expand Down
4 changes: 3 additions & 1 deletion php_cairo.h
Expand Up @@ -23,7 +23,7 @@
#ifndef PHP_CAIRO_H
#define PHP_CAIRO_H

#define PHP_CAIRO_VERSION "0.2.0-beta"
#define PHP_CAIRO_VERSION "0.2.1-beta"

extern zend_module_entry cairo_module_entry;
#define phpext_cairo_ptr &cairo_module_entry
Expand Down Expand Up @@ -140,6 +140,8 @@ typedef struct _cairo_ft_font_face_object {
zend_object std;
cairo_font_face_t *font_face;
FT_Stream ft_stream;
FT_Face ft_face;
cairo_user_data_key_t key;
} cairo_ft_font_face_object;
#endif

Expand Down
2 changes: 1 addition & 1 deletion tests/CairoFontFace/CairoFtFontFace/__construct.phpt
@@ -1,5 +1,5 @@
--TEST--
cairo_ft_font_face_create() function
CairoFtFontFace::__construct()
--SKIPIF--
<?php
if(!extension_loaded('cairo')) die('skip - Cairo extension not available');
Expand Down

0 comments on commit 8052e8c

Please sign in to comment.