Skip to content

Commit bc40bce

Browse files
committed
Convert gdFont from resource to object
1 parent b4503fb commit bc40bce

File tree

3 files changed

+117
-81
lines changed

3 files changed

+117
-81
lines changed

ext/gd/gd.c

Lines changed: 98 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@
5757

5858
#include "gd_compat.h"
5959

60-
static int le_gd_font;
61-
6260
#include <gd.h>
6361
#include <gd_errors.h>
6462
#include <gdfontt.h> /* 1 Tiny font */
@@ -235,6 +233,75 @@ static void php_gd_object_minit_helper()
235233
php_gd_image_object_handlers.offset = XtOffsetOf(php_gd_image_object, std);
236234
}
237235

236+
static zend_class_entry *gd_font_ce = NULL;
237+
static zend_object_handlers php_gd_font_object_handlers;
238+
239+
typedef struct _php_gd_font_object {
240+
gdFontPtr font;
241+
zend_object std;
242+
} php_gd_font_object;
243+
244+
static php_gd_font_object *php_gd_font_object_from_zend_object(zend_object *zobj)
245+
{
246+
return ((php_gd_font_object*)(zobj + 1)) - 1;
247+
}
248+
249+
static zend_object *php_gd_font_object_to_zend_object(php_gd_font_object *obj)
250+
{
251+
return ((zend_object*)(obj + 1)) - 1;
252+
}
253+
254+
static zend_object *php_gd_font_object_create(zend_class_entry *ce)
255+
{
256+
php_gd_font_object *obj = zend_object_alloc(sizeof(php_gd_font_object), ce);
257+
zend_object *zobj = php_gd_font_object_to_zend_object(obj);
258+
259+
obj->font = NULL;
260+
zend_object_std_init(zobj, ce);
261+
object_properties_init(zobj, ce);
262+
zobj->handlers = &php_gd_font_object_handlers;
263+
264+
return zobj;
265+
}
266+
267+
static void php_gd_font_object_free(zend_object *zobj)
268+
{
269+
php_gd_font_object *obj = php_gd_font_object_from_zend_object(zobj);
270+
271+
if (obj->font) {
272+
if (obj->font->data) {
273+
efree(obj->font->data);
274+
}
275+
efree(obj->font);
276+
obj->font = NULL;
277+
}
278+
279+
zend_object_std_dtor(zobj);
280+
}
281+
282+
static zend_function *php_gd_font_object_get_constructor(zend_object *object)
283+
{
284+
zend_throw_error(NULL, "You cannot initialize a GdImage object except through helper functions");
285+
return NULL;
286+
}
287+
288+
static void php_gd_font_minit_helper()
289+
{
290+
zend_class_entry ce;
291+
INIT_CLASS_ENTRY(ce, "GdFont", class_GdFont_methods);
292+
gd_font_ce = zend_register_internal_class(&ce);
293+
gd_font_ce->ce_flags |= ZEND_ACC_FINAL;
294+
gd_font_ce->create_object = php_gd_font_object_create;
295+
gd_font_ce->serialize = zend_class_serialize_deny;
296+
gd_font_ce->unserialize = zend_class_unserialize_deny;
297+
298+
/* setting up the object handlers for the GdFont class */
299+
memcpy(&php_gd_font_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
300+
php_gd_font_object_handlers.clone_obj = NULL;
301+
php_gd_font_object_handlers.free_obj = php_gd_font_object_free;
302+
php_gd_font_object_handlers.get_constructor = php_gd_font_object_get_constructor;
303+
php_gd_font_object_handlers.offset = XtOffsetOf(php_gd_font_object, std);
304+
}
238305

239306
/*********************************************************
240307
*
@@ -265,19 +332,6 @@ PHP_INI_BEGIN()
265332
PHP_INI_END()
266333
/* }}} */
267334

268-
/* {{{ php_free_gd_font */
269-
static void php_free_gd_font(zend_resource *rsrc)
270-
{
271-
gdFontPtr fp = (gdFontPtr) rsrc->ptr;
272-
273-
if (fp->data) {
274-
efree(fp->data);
275-
}
276-
277-
efree(fp);
278-
}
279-
/* }}} */
280-
281335
/* {{{ php_gd_error_method */
282336
void php_gd_error_method(int type, const char *format, va_list args)
283337
{
@@ -302,8 +356,8 @@ void php_gd_error_method(int type, const char *format, va_list args)
302356
/* {{{ PHP_MINIT_FUNCTION */
303357
PHP_MINIT_FUNCTION(gd)
304358
{
305-
le_gd_font = zend_register_list_destructors_ex(php_free_gd_font, NULL, "gd font", module_number);
306359
php_gd_object_minit_helper();
360+
php_gd_font_minit_helper();
307361

308362
#if defined(HAVE_GD_FREETYPE) && defined(HAVE_GD_BUNDLED)
309363
gdFontCacheMutexSetup();
@@ -614,7 +668,6 @@ PHP_FUNCTION(gd_info)
614668
/* {{{ Load a new font */
615669
PHP_FUNCTION(imageloadfont)
616670
{
617-
zval *ind;
618671
zend_string *file;
619672
int hdr_size = sizeof(gdFont) - sizeof(char *);
620673
int body_size, n = 0, b, i, body_size_check;
@@ -704,13 +757,8 @@ PHP_FUNCTION(imageloadfont)
704757
}
705758
php_stream_close(stream);
706759

707-
ind = zend_list_insert(font, le_gd_font);
708-
709-
/* Adding 5 to the font index so we will never have font indices
710-
* that overlap with the old fonts (with indices 1-5). The first
711-
* list index given out is always 1.
712-
*/
713-
RETURN_LONG(Z_RES_HANDLE_P(ind) + 5);
760+
object_init_ex(return_value, gd_font_ce);
761+
php_gd_font_object_from_zend_object(Z_OBJ_P(return_value))->font = font;
714762
}
715763
/* }}} */
716764

@@ -2695,42 +2743,26 @@ PHP_FUNCTION(imagefilledpolygon)
26952743
/* }}} */
26962744

26972745
/* {{{ php_find_gd_font */
2698-
static gdFontPtr php_find_gd_font(int size)
2746+
static gdFontPtr php_find_gd_font(zval *zfont)
26992747
{
2700-
gdFontPtr font;
2748+
if ((Z_TYPE_P(zfont) == IS_OBJECT) && instanceof_function(Z_OBJCE_P(zfont), gd_font_ce)) {
2749+
return php_gd_font_object_from_zend_object(Z_OBJ_P(zfont))->font;
2750+
}
27012751

2702-
switch (size) {
2703-
case 1:
2704-
font = gdFontTiny;
2705-
break;
2706-
case 2:
2707-
font = gdFontSmall;
2708-
break;
2709-
case 3:
2710-
font = gdFontMediumBold;
2711-
break;
2712-
case 4:
2713-
font = gdFontLarge;
2714-
break;
2715-
case 5:
2716-
font = gdFontGiant;
2717-
break;
2718-
default: {
2719-
zval *zv = zend_hash_index_find(&EG(regular_list), size - 5);
2720-
if (!zv || (Z_RES_P(zv))->type != le_gd_font) {
2721-
if (size < 1) {
2722-
font = gdFontTiny;
2723-
} else {
2724-
font = gdFontGiant;
2725-
}
2726-
} else {
2727-
font = (gdFontPtr)Z_RES_P(zv)->ptr;
2728-
}
2729-
}
2730-
break;
2731-
}
2732-
2733-
return font;
2752+
if (Z_TYPE_P(zfont) != IS_LONG) {
2753+
/* In practice, type checks should prevent us from reaching here. */
2754+
return gdFontTiny;
2755+
}
2756+
2757+
switch (Z_LVAL_P(zfont)) {
2758+
case 1: return gdFontTiny;
2759+
case 2: return gdFontSmall;
2760+
case 3: return gdFontMediumBold;
2761+
case 4: return gdFontLarge;
2762+
case 5: return gdFontGiant;
2763+
}
2764+
2765+
return (Z_LVAL_P(zfont) < 1) ? gdFontTiny : gdFontGiant;
27342766
}
27352767
/* }}} */
27362768

@@ -2740,14 +2772,14 @@ static gdFontPtr php_find_gd_font(int size)
27402772
*/
27412773
static void php_imagefontsize(INTERNAL_FUNCTION_PARAMETERS, int arg)
27422774
{
2743-
zend_long SIZE;
2775+
zval *zfont;
27442776
gdFontPtr font;
27452777

2746-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &SIZE) == FAILURE) {
2778+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zfont) == FAILURE) {
27472779
RETURN_THROWS();
27482780
}
27492781

2750-
font = php_find_gd_font(SIZE);
2782+
font = php_find_gd_font(zfont);
27512783
RETURN_LONG(arg ? font->h : font->w);
27522784
}
27532785
/* }}} */
@@ -2801,15 +2833,16 @@ static void php_gdimagecharup(gdImagePtr im, gdFontPtr f, int x, int y, int c, i
28012833
static void php_imagechar(INTERNAL_FUNCTION_PARAMETERS, int mode)
28022834
{
28032835
zval *IM;
2804-
zend_long SIZE, X, Y, COL;
2836+
zend_long X, Y, COL;
28052837
char *C;
28062838
size_t C_len;
28072839
gdImagePtr im;
2808-
int ch = 0, col, x, y, size, i, l = 0;
2840+
int ch = 0, col, x, y, i, l = 0;
28092841
unsigned char *str = NULL;
2842+
zval *zfont;
28102843
gdFontPtr font;
28112844

2812-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "Olllsl", &IM, gd_image_ce, &SIZE, &X, &Y, &C, &C_len, &COL) == FAILURE) {
2845+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ozllsl", &IM, gd_image_ce, &zfont, &X, &Y, &C, &C_len, &COL) == FAILURE) {
28132846
RETURN_THROWS();
28142847
}
28152848

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

28272860
y = Y;
28282861
x = X;
2829-
size = SIZE;
28302862

2831-
font = php_find_gd_font(size);
2863+
font = php_find_gd_font(zfont);
28322864

28332865
switch (mode) {
28342866
case 0:

ext/gd/gd.stub.php

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22

33
/** @generate-function-entries */
44

5-
final class GdImage
6-
{
7-
}
5+
final class GdImage {}
6+
final class GdFont {}
87

98
function gd_info(): array {}
109

11-
function imageloadfont(string $filename): int|false {}
10+
function imageloadfont(string $filename): GdFont|false {}
1211

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

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

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

190-
function imagefontwidth(int $font): int {}
189+
function imagefontwidth(GdFont|int $font): int {}
191190

192-
function imagefontheight(int $font): int {}
191+
function imagefontheight(GdFont|int $font): int {}
193192

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

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

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

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

202201
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 {}
203202

ext/gd/gd_arginfo.h

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: 59256d0de105f1a2f5d5fc1e20f8090031b42a76 */
2+
* Stub hash: 23b7c8395c628239fb10d746ca6bba72871ee9f3 */
33

44
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gd_info, 0, 0, IS_ARRAY, 0)
55
ZEND_END_ARG_INFO()
66

7-
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_imageloadfont, 0, 1, MAY_BE_LONG|MAY_BE_FALSE)
7+
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_imageloadfont, 0, 1, GdFont, MAY_BE_FALSE)
88
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
99
ZEND_END_ARG_INFO()
1010

@@ -380,14 +380,14 @@ ZEND_END_ARG_INFO()
380380
#define arginfo_imagefilledpolygon arginfo_imagepolygon
381381

382382
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagefontwidth, 0, 1, IS_LONG, 0)
383-
ZEND_ARG_TYPE_INFO(0, font, IS_LONG, 0)
383+
ZEND_ARG_OBJ_TYPE_MASK(0, font, GdFont, MAY_BE_LONG, NULL)
384384
ZEND_END_ARG_INFO()
385385

386386
#define arginfo_imagefontheight arginfo_imagefontwidth
387387

388388
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagechar, 0, 6, _IS_BOOL, 0)
389389
ZEND_ARG_OBJ_INFO(0, image, GdImage, 0)
390-
ZEND_ARG_TYPE_INFO(0, font, IS_LONG, 0)
390+
ZEND_ARG_OBJ_TYPE_MASK(0, font, GdFont, MAY_BE_LONG, NULL)
391391
ZEND_ARG_TYPE_INFO(0, x, IS_LONG, 0)
392392
ZEND_ARG_TYPE_INFO(0, y, IS_LONG, 0)
393393
ZEND_ARG_TYPE_INFO(0, char, IS_STRING, 0)
@@ -398,7 +398,7 @@ ZEND_END_ARG_INFO()
398398

399399
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imagestring, 0, 6, _IS_BOOL, 0)
400400
ZEND_ARG_OBJ_INFO(0, image, GdImage, 0)
401-
ZEND_ARG_TYPE_INFO(0, font, IS_LONG, 0)
401+
ZEND_ARG_OBJ_TYPE_MASK(0, font, GdFont, MAY_BE_LONG, NULL)
402402
ZEND_ARG_TYPE_INFO(0, x, IS_LONG, 0)
403403
ZEND_ARG_TYPE_INFO(0, y, IS_LONG, 0)
404404
ZEND_ARG_TYPE_INFO(0, string, IS_STRING, 0)
@@ -831,3 +831,8 @@ static const zend_function_entry ext_functions[] = {
831831
static const zend_function_entry class_GdImage_methods[] = {
832832
ZEND_FE_END
833833
};
834+
835+
836+
static const zend_function_entry class_GdFont_methods[] = {
837+
ZEND_FE_END
838+
};

0 commit comments

Comments
 (0)