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, ...)
{
}
}
-static int gdImageGetTrueColorPixel (gdImagePtr im, int x, int y)
+int gdImageGetTrueColorPixel (gdImagePtr im, int x, int y)
{
int p = gdImageGetPixel(im, x, y);
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);
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; */
*/
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));
}
}
}
* 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
}
}
- 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;
}
/* 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;
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 */
/********************************************************************/
/* 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);
}
/*
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++)
{
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];
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 *
/***** 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 */
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";
}
}
if (!mfound) {
/* No character set found! */
+ gdMutexUnlock(gdFontCacheMutex);
return "No character set found";
}
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) {
gdFree(tmpstr);
}
gdCacheDelete(tc_cache);
+ gdMutexUnlock(gdFontCacheMutex);
return "Problem loading glyph";
}
gdFree(tmpstr);
}
gdCacheDelete(tc_cache);
+ gdMutexUnlock(gdFontCacheMutex);
return "Problem rendering glyph";
}
gdFree(tmpstr);
}
gdCacheDelete(tc_cache);
+ gdMutexUnlock(gdFontCacheMutex);
return (char *) NULL;
}