Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Convert gdFont from resource to object
  • Loading branch information
sgolemon committed Oct 21, 2020
1 parent b4503fb commit bc40bce
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 81 deletions.
164 changes: 98 additions & 66 deletions ext/gd/gd.c
Expand Up @@ -57,8 +57,6 @@

#include "gd_compat.h"

static int le_gd_font;

#include <gd.h>
#include <gd_errors.h>
#include <gdfontt.h> /* 1 Tiny font */
Expand Down Expand Up @@ -235,6 +233,75 @@ static void php_gd_object_minit_helper()
php_gd_image_object_handlers.offset = XtOffsetOf(php_gd_image_object, std);
}

static zend_class_entry *gd_font_ce = NULL;
static zend_object_handlers php_gd_font_object_handlers;

typedef struct _php_gd_font_object {
gdFontPtr font;
zend_object std;
} php_gd_font_object;

static php_gd_font_object *php_gd_font_object_from_zend_object(zend_object *zobj)
{
return ((php_gd_font_object*)(zobj + 1)) - 1;
}

static zend_object *php_gd_font_object_to_zend_object(php_gd_font_object *obj)
{
return ((zend_object*)(obj + 1)) - 1;

This comment has been minimized.

Copy link
@remicollet

remicollet Oct 26, 2020

Contributor

While I found this +1 / -1 very elegant, can't it raise issue with memory alignment?

BTW, for the second, a return obj->std; seems simpler ;)

}

static zend_object *php_gd_font_object_create(zend_class_entry *ce)
{
php_gd_font_object *obj = zend_object_alloc(sizeof(php_gd_font_object), ce);
zend_object *zobj = php_gd_font_object_to_zend_object(obj);

obj->font = NULL;
zend_object_std_init(zobj, ce);
object_properties_init(zobj, ce);
zobj->handlers = &php_gd_font_object_handlers;

return zobj;
}

static void php_gd_font_object_free(zend_object *zobj)
{
php_gd_font_object *obj = php_gd_font_object_from_zend_object(zobj);

if (obj->font) {
if (obj->font->data) {
efree(obj->font->data);
}
efree(obj->font);
obj->font = NULL;
}

zend_object_std_dtor(zobj);
}

static zend_function *php_gd_font_object_get_constructor(zend_object *object)
{
zend_throw_error(NULL, "You cannot initialize a GdImage object except through helper functions");
return NULL;
}

static void php_gd_font_minit_helper()
{
zend_class_entry ce;
INIT_CLASS_ENTRY(ce, "GdFont", class_GdFont_methods);
gd_font_ce = zend_register_internal_class(&ce);
gd_font_ce->ce_flags |= ZEND_ACC_FINAL;
gd_font_ce->create_object = php_gd_font_object_create;
gd_font_ce->serialize = zend_class_serialize_deny;
gd_font_ce->unserialize = zend_class_unserialize_deny;

/* setting up the object handlers for the GdFont class */
memcpy(&php_gd_font_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
php_gd_font_object_handlers.clone_obj = NULL;
php_gd_font_object_handlers.free_obj = php_gd_font_object_free;
php_gd_font_object_handlers.get_constructor = php_gd_font_object_get_constructor;
php_gd_font_object_handlers.offset = XtOffsetOf(php_gd_font_object, std);
}

/*********************************************************
*
Expand Down Expand Up @@ -265,19 +332,6 @@ PHP_INI_BEGIN()
PHP_INI_END()
/* }}} */

/* {{{ php_free_gd_font */
static void php_free_gd_font(zend_resource *rsrc)
{
gdFontPtr fp = (gdFontPtr) rsrc->ptr;

if (fp->data) {
efree(fp->data);
}

efree(fp);
}
/* }}} */

/* {{{ php_gd_error_method */
void php_gd_error_method(int type, const char *format, va_list args)
{
Expand All @@ -302,8 +356,8 @@ void php_gd_error_method(int type, const char *format, va_list args)
/* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(gd)
{
le_gd_font = zend_register_list_destructors_ex(php_free_gd_font, NULL, "gd font", module_number);
php_gd_object_minit_helper();
php_gd_font_minit_helper();

#if defined(HAVE_GD_FREETYPE) && defined(HAVE_GD_BUNDLED)
gdFontCacheMutexSetup();
Expand Down Expand Up @@ -614,7 +668,6 @@ PHP_FUNCTION(gd_info)
/* {{{ Load a new font */
PHP_FUNCTION(imageloadfont)
{
zval *ind;
zend_string *file;
int hdr_size = sizeof(gdFont) - sizeof(char *);
int body_size, n = 0, b, i, body_size_check;
Expand Down Expand Up @@ -704,13 +757,8 @@ PHP_FUNCTION(imageloadfont)
}
php_stream_close(stream);

ind = zend_list_insert(font, le_gd_font);

/* Adding 5 to the font index so we will never have font indices
* that overlap with the old fonts (with indices 1-5). The first
* list index given out is always 1.
*/
RETURN_LONG(Z_RES_HANDLE_P(ind) + 5);
object_init_ex(return_value, gd_font_ce);
php_gd_font_object_from_zend_object(Z_OBJ_P(return_value))->font = font;
}
/* }}} */

Expand Down Expand Up @@ -2695,42 +2743,26 @@ PHP_FUNCTION(imagefilledpolygon)
/* }}} */

/* {{{ php_find_gd_font */
static gdFontPtr php_find_gd_font(int size)
static gdFontPtr php_find_gd_font(zval *zfont)
{
gdFontPtr font;
if ((Z_TYPE_P(zfont) == IS_OBJECT) && instanceof_function(Z_OBJCE_P(zfont), gd_font_ce)) {
return php_gd_font_object_from_zend_object(Z_OBJ_P(zfont))->font;
}

switch (size) {
case 1:
font = gdFontTiny;
break;
case 2:
font = gdFontSmall;
break;
case 3:
font = gdFontMediumBold;
break;
case 4:
font = gdFontLarge;
break;
case 5:
font = gdFontGiant;
break;
default: {
zval *zv = zend_hash_index_find(&EG(regular_list), size - 5);
if (!zv || (Z_RES_P(zv))->type != le_gd_font) {
if (size < 1) {
font = gdFontTiny;
} else {
font = gdFontGiant;
}
} else {
font = (gdFontPtr)Z_RES_P(zv)->ptr;
}
}
break;
}

return font;
if (Z_TYPE_P(zfont) != IS_LONG) {
/* In practice, type checks should prevent us from reaching here. */
return gdFontTiny;
}

switch (Z_LVAL_P(zfont)) {
case 1: return gdFontTiny;
case 2: return gdFontSmall;
case 3: return gdFontMediumBold;
case 4: return gdFontLarge;
case 5: return gdFontGiant;
}

return (Z_LVAL_P(zfont) < 1) ? gdFontTiny : gdFontGiant;
}
/* }}} */

Expand All @@ -2740,14 +2772,14 @@ static gdFontPtr php_find_gd_font(int size)
*/
static void php_imagefontsize(INTERNAL_FUNCTION_PARAMETERS, int arg)
{
zend_long SIZE;
zval *zfont;
gdFontPtr font;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &SIZE) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zfont) == FAILURE) {
RETURN_THROWS();
}

font = php_find_gd_font(SIZE);
font = php_find_gd_font(zfont);
RETURN_LONG(arg ? font->h : font->w);
}
/* }}} */
Expand Down Expand Up @@ -2801,15 +2833,16 @@ static void php_gdimagecharup(gdImagePtr im, gdFontPtr f, int x, int y, int c, i
static void php_imagechar(INTERNAL_FUNCTION_PARAMETERS, int mode)
{
zval *IM;
zend_long SIZE, X, Y, COL;
zend_long X, Y, COL;
char *C;
size_t C_len;
gdImagePtr im;
int ch = 0, col, x, y, size, i, l = 0;
int ch = 0, col, x, y, i, l = 0;
unsigned char *str = NULL;
zval *zfont;
gdFontPtr font;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "Olllsl", &IM, gd_image_ce, &SIZE, &X, &Y, &C, &C_len, &COL) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ozllsl", &IM, gd_image_ce, &zfont, &X, &Y, &C, &C_len, &COL) == FAILURE) {
RETURN_THROWS();
}

Expand All @@ -2826,9 +2859,8 @@ static void php_imagechar(INTERNAL_FUNCTION_PARAMETERS, int mode)

y = Y;
x = X;
size = SIZE;

font = php_find_gd_font(size);
font = php_find_gd_font(zfont);

switch (mode) {
case 0:
Expand Down
19 changes: 9 additions & 10 deletions ext/gd/gd.stub.php
Expand Up @@ -2,13 +2,12 @@

/** @generate-function-entries */

final class GdImage
{
}
final class GdImage {}
final class GdFont {}

function gd_info(): array {}

function imageloadfont(string $filename): int|false {}
function imageloadfont(string $filename): GdFont|false {}

function imagesetstyle(GdImage $image, array $style): bool {}

Expand Down Expand Up @@ -187,17 +186,17 @@ function imageopenpolygon(GdImage $image, array $points, int $num_points_or_colo

function imagefilledpolygon(GdImage $image, array $points, int $num_points_or_color, ?int $color = null): bool {}

function imagefontwidth(int $font): int {}
function imagefontwidth(GdFont|int $font): int {}

function imagefontheight(int $font): int {}
function imagefontheight(GdFont|int $font): int {}

function imagechar(GdImage $image, int $font, int $x, int $y, string $char, int $color): bool {}
function imagechar(GdImage $image, GdFont|int $font, int $x, int $y, string $char, int $color): bool {}

function imagecharup(GdImage $image, int $font, int $x, int $y, string $char, int $color): bool {}
function imagecharup(GdImage $image, GdFont|int $font, int $x, int $y, string $char, int $color): bool {}

function imagestring(GdImage $image, int $font, int $x, int $y, string $string, int $color): bool {}
function imagestring(GdImage $image, GdFont|int $font, int $x, int $y, string $string, int $color): bool {}

function imagestringup(GdImage $image, int $font, int $x, int $y, string $string, int $color): bool {}
function imagestringup(GdImage $image, GdFont|int $font, int $x, int $y, string $string, int $color): bool {}

function imagecopy(GdImage $dst_image, GdImage $src_image, int $dst_x, int $dst_y, int $src_x, int $src_y, int $src_width, int $src_height): bool {}

Expand Down
15 changes: 10 additions & 5 deletions ext/gd/gd_arginfo.h
@@ -1,10 +1,10 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 59256d0de105f1a2f5d5fc1e20f8090031b42a76 */
* Stub hash: 23b7c8395c628239fb10d746ca6bba72871ee9f3 */

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gd_info, 0, 0, IS_ARRAY, 0)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_imageloadfont, 0, 1, MAY_BE_LONG|MAY_BE_FALSE)
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_imageloadfont, 0, 1, GdFont, MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
ZEND_END_ARG_INFO()

Expand Down Expand Up @@ -380,14 +380,14 @@ ZEND_END_ARG_INFO()
#define arginfo_imagefilledpolygon arginfo_imagepolygon

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagefontwidth, 0, 1, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, font, IS_LONG, 0)
ZEND_ARG_OBJ_TYPE_MASK(0, font, GdFont, MAY_BE_LONG, NULL)
ZEND_END_ARG_INFO()

#define arginfo_imagefontheight arginfo_imagefontwidth

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagechar, 0, 6, _IS_BOOL, 0)
ZEND_ARG_OBJ_INFO(0, image, GdImage, 0)
ZEND_ARG_TYPE_INFO(0, font, IS_LONG, 0)
ZEND_ARG_OBJ_TYPE_MASK(0, font, GdFont, MAY_BE_LONG, NULL)
ZEND_ARG_TYPE_INFO(0, x, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, y, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, char, IS_STRING, 0)
Expand All @@ -398,7 +398,7 @@ ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagestring, 0, 6, _IS_BOOL, 0)
ZEND_ARG_OBJ_INFO(0, image, GdImage, 0)
ZEND_ARG_TYPE_INFO(0, font, IS_LONG, 0)
ZEND_ARG_OBJ_TYPE_MASK(0, font, GdFont, MAY_BE_LONG, NULL)
ZEND_ARG_TYPE_INFO(0, x, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, y, IS_LONG, 0)
ZEND_ARG_TYPE_INFO(0, string, IS_STRING, 0)
Expand Down Expand Up @@ -831,3 +831,8 @@ static const zend_function_entry ext_functions[] = {
static const zend_function_entry class_GdImage_methods[] = {
ZEND_FE_END
};


static const zend_function_entry class_GdFont_methods[] = {
ZEND_FE_END
};

0 comments on commit bc40bce

Please sign in to comment.