mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Synchronized bundled GD library with GD 2.0.17
. GD is now thread-safe thanks to wrappers around freetype library . Significant optimization to png writing code. . Miscellaneous fixes. Fixed memory leak inside php_imagettftext_common() Make ext/gd compile with GD 2.0.17+ (gdFreeFontCache() is not avaliable)
This commit is contained in:
@@ -258,6 +258,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
|
||||
|
||||
16
ext/gd/gd.c
16
ext/gd/gd.c
@@ -442,14 +442,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
|
||||
@@ -3077,7 +3081,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
|
||||
@@ -3120,7 +3124,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);
|
||||
@@ -3156,8 +3159,11 @@ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode, int
|
||||
l = strlen(str);
|
||||
|
||||
#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);
|
||||
|
||||
@@ -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 *) gdMalloc (sizeof (int) * srcH);
|
||||
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);
|
||||
@@ -3019,6 +3011,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; */
|
||||
|
||||
@@ -295,8 +295,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,
|
||||
|
||||
@@ -539,7 +539,7 @@ gdImagePtr gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w,
|
||||
}
|
||||
} else {
|
||||
ch = gdGetC(in);
|
||||
if (ch == EOF) {
|
||||
if ((int)ch == EOF) {
|
||||
ch = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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...
|
||||
|
||||
@@ -34,8 +34,6 @@ typedef struct fileIOCtx
|
||||
FILE *f;
|
||||
} fileIOCtx;
|
||||
|
||||
struct fileIOCtx *fileIOCtxPtr;
|
||||
|
||||
gdIOCtx *newFileCtx (FILE * f);
|
||||
|
||||
static int fileGetbuf (gdIOCtx *, void *, int);
|
||||
|
||||
@@ -328,6 +328,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);
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -92,8 +92,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
|
||||
@@ -408,26 +412,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;
|
||||
@@ -458,6 +454,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;
|
||||
@@ -467,6 +473,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 */
|
||||
@@ -511,16 +531,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);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -610,7 +626,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++)
|
||||
{
|
||||
@@ -645,7 +662,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];
|
||||
@@ -745,30 +763,47 @@ 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,
|
||||
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 *
|
||||
@@ -815,20 +850,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 */
|
||||
@@ -836,6 +872,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";
|
||||
}
|
||||
|
||||
@@ -887,6 +924,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";
|
||||
}
|
||||
|
||||
@@ -928,6 +966,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) {
|
||||
@@ -1005,6 +1058,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi
|
||||
gdFree(tmpstr);
|
||||
}
|
||||
gdCacheDelete(tc_cache);
|
||||
gdMutexUnlock(gdFontCacheMutex);
|
||||
return "Problem loading glyph";
|
||||
}
|
||||
|
||||
@@ -1047,6 +1101,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi
|
||||
gdFree(tmpstr);
|
||||
}
|
||||
gdCacheDelete(tc_cache);
|
||||
gdMutexUnlock(gdFontCacheMutex);
|
||||
return "Problem rendering glyph";
|
||||
}
|
||||
|
||||
@@ -1097,6 +1152,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsi
|
||||
gdFree(tmpstr);
|
||||
}
|
||||
gdCacheDelete(tc_cache);
|
||||
gdMutexUnlock(gdFontCacheMutex);
|
||||
return (char *) NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user