From a0c6c4f59fca2800d7505208c636566c7f86b0e6 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Thu, 25 Dec 2003 22:33:03 +0000 Subject: [PATCH] MFH: Synchronized bundled GD library with GD 2.0.17 --- ext/gd/config.m4 | 1 + ext/gd/gd.c | 19 +++-- ext/gd/libgd/gd.c | 27 +++---- ext/gd/libgd/gd.h | 12 ++- ext/gd/libgd/gd_gd2.c | 2 +- ext/gd/libgd/gd_io.c | 2 +- ext/gd/libgd/gd_io_file.c | 2 - ext/gd/libgd/gd_jpeg.c | 5 ++ ext/gd/libgd/gd_png.c | 29 +++++--- ext/gd/libgd/gd_topal.c | 15 +++- ext/gd/libgd/gdft.c | 149 ++++++++++++++++++++++++++------------ ext/gd/libgd/gdhelpers.h | 14 ++++ 12 files changed, 192 insertions(+), 85 deletions(-) diff --git a/ext/gd/config.m4 b/ext/gd/config.m4 index a3dbd60e6e..05bf14f513 100644 --- a/ext/gd/config.m4 +++ b/ext/gd/config.m4 @@ -257,6 +257,7 @@ AC_DEFUN(PHP_GD_CHECK_VERSION,[ PHP_CHECK_LIBRARY(gd, gdImageColorResolve, [AC_DEFINE(HAVE_GDIMAGECOLORRESOLVE, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) PHP_CHECK_LIBRARY(gd, gdImageGifCtx, [AC_DEFINE(HAVE_GD_GIF_CTX, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) PHP_CHECK_LIBRARY(gd, gdCacheCreate, [AC_DEFINE(HAVE_GD_CACHE_CREATE, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) + PHP_CHECK_LIBRARY(gd, gdFontCacheShutdown, [AC_DEFINE(HAVE_GD_THREAD_SAFE, 1, [ ])], [], [ -L$GD_LIB $GD_SHARED_LIBADD ]) ]) dnl diff --git a/ext/gd/gd.c b/ext/gd/gd.c index 10b9689c80..8184342ef0 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -379,14 +379,18 @@ PHP_MINIT_FUNCTION(gd) #if HAVE_LIBGD20 && HAVE_GD_STRINGFT PHP_RSHUTDOWN_FUNCTION(gd) { +#if defined(HAVE_GD_THREAD_SAFE) || defined(HAVE_GD_BUNDLED) + gdFontCacheShutdown(); +#else gdFreeFontCache(); +#endif return SUCCESS; } #endif /* }}} */ #if HAVE_GD_BUNDLED -#define PHP_GD_VERSION_STRING "bundled (2.0.15 compatible)" +#define PHP_GD_VERSION_STRING "bundled (2.0.17 compatible)" #elif HAVE_LIBGD20 #define PHP_GD_VERSION_STRING "2.0 or higher" #elif HAVE_GDIMAGECOLORRESOLVE @@ -2960,7 +2964,7 @@ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode, int char *error = NULL; int argc; #if HAVE_GD_STRINGFTEX - gdFTStringExtra strex; + gdFTStringExtra strex = {0}; #endif #if !HAVE_GD_STRINGFTEX @@ -3003,7 +3007,6 @@ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode, int HashPosition pos; convert_to_array_ex(EXT); - memset(&strex, 0, sizeof(strex)); /* walk the assoc array */ zend_hash_internal_pointer_reset_ex(HASH_OF(*EXT), &pos); @@ -3036,15 +3039,19 @@ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode, int str = (unsigned char *) Z_STRVAL_PP(C); l = strlen(str); +/* VCWD_REALPATH(Z_STRVAL_PP(FONTNAME), fontname); */ + #ifdef VIRTUAL_DIR - if(virtual_filepath(Z_STRVAL_PP(FONTNAME), (char**)&fontname TSRMLS_CC)) { - fontname = (unsigned char*)Z_STRVAL_PP(FONTNAME); + { + char tmp_font_path[MAXPATHLEN]; + if (VCWD_REALPATH(Z_STRVAL_PP(FONTNAME), tmp_font_path)) { + fontname = (unsigned char *) Z_STRVAL_PP(FONTNAME); + } } #else fontname = (unsigned char*)Z_STRVAL_PP(FONTNAME); #endif - #ifdef USE_GD_IMGSTRTTF # if HAVE_GD_STRINGFTEX if (extended) { diff --git a/ext/gd/libgd/gd.c b/ext/gd/libgd/gd.c index c74d55d029..e7edf12880 100644 --- a/ext/gd/libgd/gd.c +++ b/ext/gd/libgd/gd.c @@ -94,7 +94,7 @@ static int gdFullAlphaBlend(int dst, int src); static int gdLayerOverlay(int dst, int src); static int gdAlphaBlendColor(int b1, int b2, int a1, int a2); static int gdAlphaOverlayColor(int src, int dst, int max); -static int gdImageGetTrueColorPixel(gdImagePtr im, int x, int y); +int gdImageGetTrueColorPixel(gdImagePtr im, int x, int y); void php_gd_error_ex(int type, const char *format, ...) { @@ -751,7 +751,7 @@ void gdImageSetPixel (gdImagePtr im, int x, int y, int color) } } -static int gdImageGetTrueColorPixel (gdImagePtr im, int x, int y) +int gdImageGetTrueColorPixel (gdImagePtr im, int x, int y) { int p = gdImageGetPixel(im, x, y); @@ -2255,20 +2255,12 @@ void gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int sty = (int *) safe_emalloc(sizeof(int), srcH, 0); accum = 0; + /* Fixed by Mao Morimoto 2.0.16 */ for (i = 0; (i < srcW); i++) { - int got; - accum += (double) dstW / (double) srcW; - got = (int) floor (accum); - stx[i] = got; - accum -= got; + stx[i] = dstW * (i+1) / srcW - dstW * i / srcW ; } - accum = 0; for (i = 0; (i < srcH); i++) { - int got; - accum += (double) dstH / (double) srcH; - got = (int) floor (accum); - sty[i] = got; - accum -= got; + sty[i] = dstH * (i+1) / srcH - dstH * i / srcH ; } for (i = 0; (i < gdMaxColors); i++) { colorMap[i] = (-1); @@ -3027,6 +3019,15 @@ void gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int c) maxy = p[i].y; } } + + /* 2.0.16: Optimization by Ilia Chipitsine -- don't waste time offscreen */ + if (miny < 0) { + miny = 0; + } + if (maxy >= gdImageSY(im)) { + maxy = gdImageSY(im) - 1; + } + /* Fix in 1.3: count a vertex only once */ for (y = miny; y <= maxy; y++) { /*1.4 int interLast = 0; */ diff --git a/ext/gd/libgd/gd.h b/ext/gd/libgd/gd.h index fcad556102..ba2731677a 100644 --- a/ext/gd/libgd/gd.h +++ b/ext/gd/libgd/gd.h @@ -294,8 +294,16 @@ void gdImageStringUp(gdImagePtr im, gdFontPtr f, int x, int y, unsigned char *s, void gdImageString16(gdImagePtr im, gdFontPtr f, int x, int y, unsigned short *s, int color); void gdImageStringUp16(gdImagePtr im, gdFontPtr f, int x, int y, unsigned short *s, int color); -/* clean up after using fonts in gdImageStringFT() */ -void gdFreeFontCache(); +/* 2.0.16: for thread-safe use of gdImageStringFT and friends, + * call this before allowing any thread to call gdImageStringFT. + * Otherwise it is invoked by the first thread to invoke + * gdImageStringFT, with a very small but real risk of a race condition. + * Return 0 on success, nonzero on failure to initialize freetype. + */ +int gdFontCacheSetup(void); + +/* Optional: clean up after application is done using fonts in gdImageStringFT(). */ +void gdFontCacheShutdown(void); /* Calls gdImageStringFT. Provided for backwards compatibility only. */ char *gdImageStringTTF(gdImage *im, int *brect, int fg, char *fontlist, diff --git a/ext/gd/libgd/gd_gd2.c b/ext/gd/libgd/gd_gd2.c index 0a01df72b2..0fadc71536 100644 --- a/ext/gd/libgd/gd_gd2.c +++ b/ext/gd/libgd/gd_gd2.c @@ -540,7 +540,7 @@ gdImagePtr gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w, } } else { ch = gdGetC(in); - if (ch == EOF) { + if ((int)ch == EOF) { ch = 0; } } diff --git a/ext/gd/libgd/gd_io.c b/ext/gd/libgd/gd_io.c index 7cc49d28fd..b65e95205c 100644 --- a/ext/gd/libgd/gd_io.c +++ b/ext/gd/libgd/gd_io.c @@ -3,7 +3,7 @@ /* * io.c * - * Implements the imple I/O 'helper' routines. + * Implements the simple I/O 'helper' routines. * * Not really essential, but these routines were used extensively in GD, * so they were moved here. They also make IOCtx calls look better... diff --git a/ext/gd/libgd/gd_io_file.c b/ext/gd/libgd/gd_io_file.c index 713646120e..339ea042ba 100644 --- a/ext/gd/libgd/gd_io_file.c +++ b/ext/gd/libgd/gd_io_file.c @@ -35,8 +35,6 @@ typedef struct fileIOCtx } fileIOCtx; -struct fileIOCtx *fileIOCtxPtr; - gdIOCtx *newFileCtx (FILE * f); static int fileGetbuf (gdIOCtx *, void *, int); diff --git a/ext/gd/libgd/gd_jpeg.c b/ext/gd/libgd/gd_jpeg.c index 0f0211c4b5..e3f26659f0 100644 --- a/ext/gd/libgd/gd_jpeg.c +++ b/ext/gd/libgd/gd_jpeg.c @@ -332,6 +332,11 @@ gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile) php_gd_error("gd-jpeg: warning: jpeg_finish_decompress reports suspended data source"); } + /* Thanks to Truxton Fulton */ + if (cinfo.err->num_warnings > 0) { + goto error; + } + jpeg_destroy_decompress (&cinfo); gdFree (row); diff --git a/ext/gd/libgd/gd_png.c b/ext/gd/libgd/gd_png.c index 926264bf5f..8db3bf6a36 100644 --- a/ext/gd/libgd/gd_png.c +++ b/ext/gd/libgd/gd_png.c @@ -622,28 +622,39 @@ void gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level) */ if (im->trueColor) { + /* performance optimizations by Phong Tran */ int channels = im->saveAlphaFlag ? 4 : 3; /* Our little 7-bit alpha channel trick costs us a bit here. */ png_bytep *row_pointers; + unsigned char* pOutputRow; + int **ptpixels = im->tpixels; + int *pThisRow; + unsigned char a; + int thisPixel; + png_bytep *prow_pointers; + int saveAlphaFlag = im->saveAlphaFlag; + row_pointers = safe_emalloc(sizeof(png_bytep), height, 0); + prow_pointers = row_pointers; for (j = 0; j < height; ++j) { - int bo = 0; - row_pointers[j] = (png_bytep) safe_emalloc(width, channels, 0); + *prow_pointers = (png_bytep) safe_emalloc(width, channels, 0); + pOutputRow = *prow_pointers++; + pThisRow = *ptpixels++; for (i = 0; i < width; ++i) { - unsigned char a; - row_pointers[j][bo++] = gdTrueColorGetRed(im->tpixels[j][i]); - row_pointers[j][bo++] = gdTrueColorGetGreen(im->tpixels[j][i]); - row_pointers[j][bo++] = gdTrueColorGetBlue(im->tpixels[j][i]); - if (im->saveAlphaFlag) { + thisPixel = *pThisRow++; + *pOutputRow++ = gdTrueColorGetRed(thisPixel); + *pOutputRow++ = gdTrueColorGetGreen(thisPixel); + *pOutputRow++ = gdTrueColorGetBlue(thisPixel); + if (saveAlphaFlag) { /* convert the 7-bit alpha channel to an 8-bit alpha channel. * We do a little bit-flipping magic, repeating the MSB * as the LSB, to ensure that 0 maps to 0 and * 127 maps to 255. We also have to invert to match * PNG's convention in which 255 is opaque. */ - a = gdTrueColorGetAlpha(im->tpixels[j][i]); + a = gdTrueColorGetAlpha(thisPixel); /* Andrew Hull: >> 6, not >> 7! (gd 2.0.5) */ - row_pointers[j][bo++] = 255 - ((a << 1) + (a >> 6)); + *pOutputRow++ = 255 - ((a << 1) + (a >> 6)); } } } diff --git a/ext/gd/libgd/gd_topal.c b/ext/gd/libgd/gd_topal.c index dfaafe0b44..351751c775 100644 --- a/ext/gd/libgd/gd_topal.c +++ b/ext/gd/libgd/gd_topal.c @@ -703,7 +703,7 @@ LOCAL (void) histptr histp; int c0, c1, c2; int c0min, c0max, c1min, c1max, c2min, c2max; - long count; + long count = 0; long total = 0; long c0total = 0; long c1total = 0; @@ -735,9 +735,16 @@ LOCAL (void) cinfo->colormap[1][icolor] = (JSAMPLE) ((c1total + (total >> 1)) / total); cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total >> 1)) / total); #else - im->red[icolor] = (int) ((c0total + (total >> 1)) / total); - im->green[icolor] = (int) ((c1total + (total >> 1)) / total); - im->blue[icolor] = (int) ((c2total + (total >> 1)) / total); + /* 2.0.16: Paul den Dulk found an occasion where total can be 0 */ + if (count) { + im->red[icolor] = (int) ((c0total + (total >> 1)) / total); + im->green[icolor] = (int) ((c1total + (total >> 1)) / total); + im->blue[icolor] = (int) ((c2total + (total >> 1)) / total); + } else { + im->red[icolor] = 255; + im->green[icolor] = 255; + im->blue[icolor] = 255; + } #endif } diff --git a/ext/gd/libgd/gdft.c b/ext/gd/libgd/gdft.c index 783bb1ffda..1f76b141be 100644 --- a/ext/gd/libgd/gdft.c +++ b/ext/gd/libgd/gdft.c @@ -90,8 +90,12 @@ gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist, * if building this version of gd separate from graphviz. */ #ifndef DEFAULT_FONTPATH +#if defined(__APPLE__) || (defined(__MWERKS__) && defined(macintosh)) +#define DEFAULT_FONTPATH "/usr/share/fonts/truetype:/System/Library/Fonts:/Library/Fonts" +#else #define DEFAULT_FONTPATH "/usr/share/fonts/truetype" #endif +#endif #ifndef PATHSEPARATOR #define PATHSEPARATOR ":" #endif @@ -406,26 +410,18 @@ static void *fontFetch (char **error, void *key) } } - snprintf(fullname, sizeof(fullname) - 1, "%s/%s", dir, name); - if (access(fullname, R_OK) == 0) { - font_found++; - break; - } - snprintf(fullname, sizeof(fullname) - 1, "%s/%s.ttf", dir, name); - if (access(fullname, R_OK) == 0) { - font_found++; - break; - } - snprintf(fullname, sizeof(fullname) - 1, "%s/%s.pfa", dir, name); - if (access(fullname, R_OK) == 0) { - font_found++; - break; - } - snprintf(fullname, sizeof(fullname) - 1, "%s/%s.pfb", dir, name); - if (access(fullname, R_OK) == 0) { - font_found++; - break; - } +#define GD_CHECK_FONT_PATH(ext) \ + snprintf(fullname, sizeof(fullname) - 1, "%s/%s%s", dir, name, ext); \ + if (access(fullname, R_OK) == 0) { \ + font_found++; \ + break; \ + } \ + + GD_CHECK_FONT_PATH(""); + GD_CHECK_FONT_PATH(".ttf"); + GD_CHECK_FONT_PATH(".pfa"); + GD_CHECK_FONT_PATH(".pfb"); + GD_CHECK_FONT_PATH(".dfont"); } gdFree(path); path = NULL; @@ -456,6 +452,16 @@ static void *fontFetch (char **error, void *key) } /* FIXME - This mapping stuff is imcomplete - where is the spec? */ + /* EAM - It's worse than that. It's pointless to match character encodings here. + * As currently written, the stored a->face->charmap only matches one of + * the actual charmaps and we cannot know at this stage if it is the right + * one. We should just skip all this stuff, and check in gdImageStringFTEx + * if some particular charmap is preferred and if so whether it is held in + * one of the a->face->charmaps[0..num_charmaps]. + * And why is it so bad not to find any recognized charmap? The user may + * still know what mapping to use, even if we do not. In that case we can + * just use the map in a->face->charmaps[num_charmaps] and be done with it. + */ a->have_char_map_unicode = 0; a->have_char_map_big5 = 0; @@ -465,6 +471,20 @@ static void *fontFetch (char **error, void *key) charmap = a->face->charmaps[n]; platform = charmap->platform_id; encoding = charmap->encoding_id; + +/* EAM DEBUG - Newer versions of libfree2 make it easier by defining encodings */ +#ifdef FT_ENCODING_MS_SYMBOL + if (charmap->encoding == FT_ENCODING_MS_SYMBOL + || charmap->encoding == FT_ENCODING_ADOBE_CUSTOM + || charmap->encoding == FT_ENCODING_ADOBE_STANDARD) { + a->have_char_map_unicode = 1; + found = charmap; + a->face->charmap = charmap; + return (void *)a; + } +#endif /* FT_ENCODING_MS_SYMBOL */ +/* EAM DEBUG */ + if ((platform == 3 && encoding == 1) /* Windows Unicode */ || (platform == 3 && encoding == 0) /* Windows Symbol */ || (platform == 2 && encoding == 1) /* ISO Unicode */ @@ -509,16 +529,12 @@ static void fontRelease (void *element) /********************************************************************/ /* tweencolor cache functions */ -static int -tweenColorTest (void *element, void *key) +static int tweenColorTest (void *element, void *key) { - tweencolor_t *a = (tweencolor_t *) element; - tweencolorkey_t *b = (tweencolorkey_t *) key; + tweencolor_t *a = (tweencolor_t *) element; + tweencolorkey_t *b = (tweencolorkey_t *) key; - return (a->pixel == b->pixel - && a->bgcolor == b->bgcolor - && a->fgcolor == b->fgcolor - && a->im == b->im); + return (a->pixel == b->pixel && a->bgcolor == b->bgcolor && a->fgcolor == b->fgcolor && a->im == b->im); } /* @@ -608,7 +624,8 @@ gdft_draw_bitmap (gdCache_head_t *tc_cache, gdImage * im, int fg, FT_Bitmap bitm pcr = pc; y = pen_y + row; /* clip if out of bounds */ - if (y >= im->sy || y < 0) + /* 2.0.16: clipping rectangle, not image bounds */ + if ((y > im->cy2) || (y < im->cy1)) continue; for (col = 0; col < bitmap.width; col++, pc++) { @@ -643,7 +660,8 @@ gdft_draw_bitmap (gdCache_head_t *tc_cache, gdImage * im, int fg, FT_Bitmap bitm level = gdAlphaMax - level; x = pen_x + col; /* clip if out of bounds */ - if (x >= im->sx || x < 0) + /* 2.0.16: clip to clipping rectangle, Matt McNabb */ + if ((x > im->cx2) || (x < im->cx1)) continue; /* get pixel location in gd buffer */ tpixel = &im->tpixels[y][x]; @@ -743,30 +761,46 @@ gdroundupdown (FT_F26Dot6 v1, int updown) extern int any2eucjp (char *, char *, unsigned int); /* Persistent font cache until explicitly cleared */ -/* Fonts can be used across multiple images */ +/* Fonts can be used across multiple images */ + +/* 2.0.16: thread safety (the font cache is shared) */ +gdMutexDeclare(gdFontCacheMutex); static gdCache_head_t *fontCache = NULL; static FT_Library library; -void -gdFreeFontCache() +void gdFontCacheShutdown() { - if (fontCache) - { - gdCacheDelete(fontCache); - fontCache=NULL; - FT_Done_FreeType(library); - } + if (fontCache) { + gdMutexShutdown(gdFontCacheMutex); + gdCacheDelete(fontCache); + fontCache = NULL; + FT_Done_FreeType(library); + } +} + +int gdFontCacheSetup(void) +{ + if (fontCache) { + /* Already set up */ + return 0; + } + gdMutexSetup(gdFontCacheMutex); + if (FT_Init_FreeType(&library)) { + gdMutexShutdown(gdFontCacheMutex); + return -1; + } + fontCache = gdCacheCreate (FONTCACHESIZE, fontTest, fontFetch, fontRelease); + return 0; } /********************************************************************/ /* gdImageStringFT - render a utf8 string onto a gd image */ char * -gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist, - double ptsize, double angle, int x, int y, char *string) +gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist, + double ptsize, double angle, int x, int y, char *string) { - return gdImageStringFTEx(im, brect, fg, fontlist, - ptsize, angle, x, y, string, 0); + return gdImageStringFTEx(im, brect, fg, fontlist, ptsize, angle, x, y, string, 0); } char * @@ -813,20 +847,21 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi /***** initialize font library and font cache on first call ******/ if (!fontCache) { - if (FT_Init_FreeType (&library)) { - gdCacheDelete( tc_cache ); + if (gdFontCacheSetup() != 0) { + gdCacheDelete(tc_cache); return "Failure to initialize font library"; } - fontCache = gdCacheCreate(FONTCACHESIZE, fontTest, fontFetch, fontRelease); } /*****/ - + + gdMutexLock(gdFontCacheMutex); /* get the font (via font cache) */ fontkey.fontlist = fontlist; fontkey.library = &library; font = (font_t *) gdCacheGet (fontCache, &fontkey); if (!font) { gdCacheDelete(tc_cache); + gdMutexUnlock(gdFontCacheMutex); return fontCache->error; } face = font->face; /* shortcut */ @@ -834,6 +869,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi if (FT_Set_Char_Size (face, 0, (FT_F26Dot6) (ptsize * 64), GD_RESOLUTION, GD_RESOLUTION)) { gdCacheDelete(tc_cache); + gdMutexUnlock(gdFontCacheMutex); return "Could not set character size"; } @@ -885,6 +921,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi } if (!mfound) { /* No character set found! */ + gdMutexUnlock(gdFontCacheMutex); return "No character set found"; } @@ -926,6 +963,21 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi next++; continue; } + +/* EAM DEBUG */ +#ifdef FT_ENCODING_MS_SYMBOL + if (font->face->charmap->encoding == FT_ENCODING_MS_SYMBOL) { + /* I do not know the significance of the constant 0xf000. + * It was determined by inspection of the character codes + * stored in Microsoft font symbol. + */ + len = gdTcl_UtfToUniChar (next, &ch); + ch |= 0xf000; + next += len; + } else +#endif /* FT_ENCODING_MS_SYMBOL */ +/* EAM DEBUG */ + switch (m) { case gdFTEX_Unicode: if (font->have_char_map_unicode) { @@ -1003,6 +1055,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi gdFree(tmpstr); } gdCacheDelete(tc_cache); + gdMutexUnlock(gdFontCacheMutex); return "Problem loading glyph"; } @@ -1045,6 +1098,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi gdFree(tmpstr); } gdCacheDelete(tc_cache); + gdMutexUnlock(gdFontCacheMutex); return "Problem rendering glyph"; } @@ -1095,6 +1149,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi gdFree(tmpstr); } gdCacheDelete(tc_cache); + gdMutexUnlock(gdFontCacheMutex); return (char *) NULL; } diff --git a/ext/gd/libgd/gdhelpers.h b/ext/gd/libgd/gdhelpers.h index 2544e88060..33223318f1 100644 --- a/ext/gd/libgd/gdhelpers.h +++ b/ext/gd/libgd/gdhelpers.h @@ -21,5 +21,19 @@ extern char *gd_strtok_r(char *s, char *sep, char **state); #define gdPFree(ptr) pefree(ptr, 1) #define gdPEstrdup(ptr) pestrdup(ptr, 1) +#ifdef ZTS +#define gdMutexDeclare(x) MUTEX_T x +#define gdMutexSetup(x) x = tsrm_mutex_alloc() +#define gdMutexShutdown(x) tsrm_mutex_free(x) +#define gdMutexLock(x) tsrm_mutex_lock(x) +#define gdMutexUnlock(x) tsrm_mutex_unlock(x) +#else +#define gdMutexDeclare(x) +#define gdMutexSetup(x) +#define gdMutexShutdown(x) +#define gdMutexLock(x) +#define gdMutexUnlock(x) +#endif + #endif /* GDHELPERS_H */ -- 2.40.0