]> granicus.if.org Git - php/commitdiff
MFH: Synchronized bundled GD library with GD 2.0.17
authorIlia Alshanetsky <iliaa@php.net>
Thu, 25 Dec 2003 22:33:03 +0000 (22:33 +0000)
committerIlia Alshanetsky <iliaa@php.net>
Thu, 25 Dec 2003 22:33:03 +0000 (22:33 +0000)
12 files changed:
ext/gd/config.m4
ext/gd/gd.c
ext/gd/libgd/gd.c
ext/gd/libgd/gd.h
ext/gd/libgd/gd_gd2.c
ext/gd/libgd/gd_io.c
ext/gd/libgd/gd_io_file.c
ext/gd/libgd/gd_jpeg.c
ext/gd/libgd/gd_png.c
ext/gd/libgd/gd_topal.c
ext/gd/libgd/gdft.c
ext/gd/libgd/gdhelpers.h

index a3dbd60e6e959b66905d835bf60588a6cb5fde43..05bf14f5131cf788961466727f1c716b0808ee0c 100644 (file)
@@ -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
index 10b9689c803b76e1990086fbe59f80477a995731..8184342ef0cd9bdb86fd1284cd8caa614a722b41 100644 (file)
@@ -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)   {
index c74d55d0290f99b0fe78055eda24b1eef9218150..e7edf128808ea375985c8be4deb15f93b9f17715 100644 (file)
@@ -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; */
index fcad5561026fb163fcad3cf9874a6788fb5f5788..ba2731677ac4191836b5977222b00f79b86d7bc3 100644 (file)
@@ -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,
index 0a01df72b21c76c7bc523f5abaf908ee15a193d7..0fadc715363fef1282a9e251d02fa41d5da54f59 100644 (file)
@@ -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;
                                                        }
                                                }
index 7cc49d28fd3ae7650fedc56a07391ed6c6d4e788..b65e95205c403ce825b60743b272c2c62d0343ae 100644 (file)
@@ -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...
index 713646120eefa3417152f28c32a793851a20a1fd..339ea042ba36dbb8b60f40a8dd338a30ca3cae77 100644 (file)
@@ -35,8 +35,6 @@ typedef struct fileIOCtx
   }
 fileIOCtx;
 
-struct fileIOCtx *fileIOCtxPtr;
-
 gdIOCtx *newFileCtx (FILE * f);
 
 static int fileGetbuf (gdIOCtx *, void *, int);
index 0f0211c4b5d5658968ff1259e29d626aa6c9e296..e3f26659f0c221a075e688dad644b10656b62479 100644 (file)
@@ -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);
 
index 926264bf5fc5faf7c5c3ba104300c2d063b16c89..8db3bf6a36960281dd037f8529cce8a865629a6f 100644 (file)
@@ -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));
                                }
                        }
                }
index dfaafe0b44d560f5ab33256757c2003b0fbd04fd..351751c77560dde132925848b236456f9bda66bd 100644 (file)
@@ -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
 }
 
index 783bb1ffdacd5cddf13948330fe482904964e127..1f76b141beb5cde3cf40f979b54f00b23f2ece4e 100644 (file)
@@ -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;
 }
 
index 2544e8806094960e89314327c315f3421348457f..33223318f161f905530e5f2bba84b2e19c0c0955 100644 (file)
@@ -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 */