--- /dev/null
+diff -Nur gd-2.0.1.orig/gd.c gd-2.0.1/gd.c
+--- gd-2.0.1.orig/gd.c Sat Aug 10 23:19:14 2002
++++ gd-2.0.1/gd.c Sat Aug 10 23:39:35 2002
+@@ -473,6 +473,12 @@
+ op = c; /* Save open slot */
+ continue; /* Color not in use */
+ }
++ if (c == im->transparent)
++ {
++ /* don't ever resolve to the color that has
++ * been designated as the transparent color */
++ continue;
++ }
+ rd = (long) (im->red[c] - r);
+ gd = (long) (im->green[c] - g);
+ bd = (long) (im->blue[c] - b);
+@@ -1928,7 +1934,7 @@
+ else
+ {
+ /* Find or create the best match */
+- mapTo = gdImageColorResolveAlpha (dst,
++ nc = gdImageColorResolveAlpha (dst,
+ gdTrueColorGetRed (c),
+ gdTrueColorGetGreen (c),
+ gdTrueColorGetBlue (c),
+@@ -1978,7 +1984,7 @@
+ {
+ for (x = dstX; (x < dstX + dstW); x++)
+ {
+- int pd = gdImageGetPixel (dst, x, y);
++ /* int pd = gdImageGetPixel (dst, x, y); -- not used */
+ float sy1, sy2, sx1, sx2;
+ float sx, sy;
+ float spixels = 0;
+diff -Nur gd-2.0.1.orig/gd_gd2.c gd-2.0.1/gd_gd2.c
+--- gd-2.0.1.orig/gd_gd2.c Tue Apr 3 22:44:41 2001
++++ gd-2.0.1/gd_gd2.c Sat Aug 10 23:48:23 2002
+@@ -635,10 +635,10 @@
+ {
+ if (im->trueColor)
+ {
+- ch = chunkBuf[chunkPos++] << 24 +
+- chunkBuf[chunkPos++] << 16 +
+- chunkBuf[chunkPos++] << 8 +
+- chunkBuf[chunkPos++];
++ ch = chunkBuf[chunkPos++] << 24;
++ ch += chunkBuf[chunkPos++] << 16;
++ ch += chunkBuf[chunkPos++] << 8;
++ ch += chunkBuf[chunkPos++];
+ }
+ else
+ {
+diff -Nur gd-2.0.1.orig/gd_topal.c gd-2.0.1/gd_topal.c
+--- gd-2.0.1.orig/gd_topal.c Tue Apr 3 22:44:42 2001
++++ gd-2.0.1/gd_topal.c Sat Aug 10 23:55:17 2002
+@@ -1035,6 +1035,8 @@
+ xx2 = inc2;
+ for (ic2 = BOX_C2_ELEMS - 1; ic2 >= 0; ic2--)
+ {
++ dist3 = dist2;
++ xx3 = inc3;
+ for (ic3 = BOX_C3_ELEMS - 1; ic3 >= 0; ic3--)
+ {
+ if (dist3 < *bptr)
+diff -Nur gd-2.0.1.orig/gdft.c gd-2.0.1/gdft.c
+--- gd-2.0.1.orig/gdft.c Tue Apr 3 22:44:42 2001
++++ gd-2.0.1/gdft.c Sun Aug 11 00:19:56 2002
+@@ -349,7 +349,6 @@
+ fontsearchpath = getenv ("GDFONTPATH");
+ if (!fontsearchpath)
+ fontsearchpath = DEFAULT_FONTPATH;
+- path = strdup (fontsearchpath);
+ fontlist = strdup (a->fontlist);
+
+ /*
+@@ -358,7 +357,8 @@
+ for (name = gd_strtok_r (fontlist, LISTSEPARATOR, &strtok_ptr); name;
+ name = gd_strtok_r (0, LISTSEPARATOR, &strtok_ptr))
+ {
+-
++ /* make a fresh copy each time - strtok corrupts it. */
++ path = strdup (fontsearchpath);
+ /*
+ * Allocate an oversized buffer that is guaranteed to be
+ * big enough for all paths to be tested.
+@@ -384,11 +384,23 @@
+ font_found++;
+ break;
+ }
++ sprintf (fullname, "%s/%s.pfa", dir, name);
++ if (access (fullname, R_OK) == 0)
++ {
++ font_found++;
++ break;
++ }
++ sprintf (fullname, "%s/%s.pfb", dir, name);
++ if (access (fullname, R_OK) == 0)
++ {
++ font_found++;
++ break;
++ }
+ }
+ if (font_found)
+ break;
++ gdFree (path);
+ }
+- gdFree (path);
+ gdFree (fontlist);
+ if (!font_found)
+ {
+@@ -497,7 +509,10 @@
+ /* if fg is specified by a negative color idx, then don't antialias */
+ if (fg < 0)
+ {
+- a->tweencolor = -fg;
++ if ((pixel + pixel) >= NUMCOLORS)
++ a->tweencolor = -fg;
++ else
++ a->tweencolor = bg;
+ }
+ else
+ {
+@@ -534,7 +549,7 @@
+
+ /* draw_bitmap - transfers glyph bitmap to GD image */
+ static char *
+-gdft_draw_bitmap (gdImage * im, int fg, FT_Bitmap bitmap, int pen_x, int pen_y)
++gdft_draw_bitmap (gdCache_head_t *tc_cache, gdImage * im, int fg, FT_Bitmap bitmap, int pen_x, int pen_y)
+ {
+ unsigned char *pixel;
+ int *tpixel;
+@@ -543,21 +558,15 @@
+ tweencolor_t *tc_elem;
+ tweencolorkey_t tc_key;
+
+- /* initialize tweenColorCache on first call */
+- static gdCache_head_t *tc_cache;
+-
+- if (!tc_cache)
+- {
+- tc_cache = gdCacheCreate (TWEENCOLORCACHESIZE,
+- tweenColorTest, tweenColorFetch, tweenColorRelease);
+- }
+-
+ /* copy to image, mapping colors */
+ tc_key.fgcolor = fg;
+ tc_key.im = im;
+ for (row = 0; row < bitmap.rows; row++)
+ {
+ pc = row * bitmap.pitch;
++ if(bitmap.pixel_mode==ft_pixel_mode_mono)
++ pc *= 8; /* pc is measured in bits for monochrome images */
++
+ y = pen_y + row;
+
+ /* clip if out of bounds */
+@@ -608,11 +617,11 @@
+ /* use fg color directly */
+ if (im->trueColor)
+ {
+- *tpixel = fg;
++ *tpixel = abs( fg );
+ }
+ else
+ {
+- *pixel = fg;
++ *pixel = abs( fg );
+ }
+ }
+ else
+@@ -643,8 +652,29 @@
+ return (char *) NULL;
+ }
+
++static int
++gdroundupdown (FT_F26Dot6 v1, int updown)
++{
++ return (!updown)
++ ? (v1 < 0 ? ((v1 - 63) >> 6) : v1 >> 6)
++ : (v1 > 0 ? ((v1 + 63) >> 6) : v1 >> 6);
++}
++
+ extern int any2eucjp (char *, char *, unsigned int);
+
++/* Persistent font cache until explicitly cleared */
++/* Fonts can be used across multiple images */
++static gdCache_head_t *fontCache;
++static FT_Library library;
++
++void
++gdFreeFontCache() {
++ if (fontCache) {
++ gdCacheDelete(fontCache);
++ FT_Done_FreeType(library);
++ }
++}
++
+ /********************************************************************/
+ /* gdImageStringFT - render a utf8 string onto a gd image */
+
+@@ -671,15 +701,26 @@
+ char *tmpstr = 0;
+ int render = (im && (im->trueColor || (fg <= 255 && fg >= -255)));
+ FT_BitmapGlyph bm;
++ int render_mode = FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT;
+
+-/***** initialize font library and font cache on first call ******/
+- static gdCache_head_t *fontCache;
+- static FT_Library library;
++ /*
++ * make a new tweenColorCache on every call
++ * because caching colormappings between calls
++ * is not safe. If the im-pointer points to a
++ * brand new image, the cache gives out bogus
++ * colorindexes. -- 27.06.2001 <krisku@arrak.fi>
++ */
++ gdCache_head_t *tc_cache;
++
++ tc_cache = gdCacheCreate( TWEENCOLORCACHESIZE,
++ tweenColorTest, tweenColorFetch, tweenColorRelease );
+
++/***** initialize font library and font cache on first call ******/
+ if (!fontCache)
+ {
+ if (FT_Init_FreeType (&library))
+ {
++ gdCacheDelete( tc_cache );
+ return "Failure to initialize font library";
+ }
+ fontCache = gdCacheCreate (FONTCACHESIZE,
+@@ -693,6 +734,7 @@
+ font = (font_t *) gdCacheGet (fontCache, &fontkey);
+ if (!font)
+ {
++ gdCacheDelete( tc_cache );
+ return fontCache->error;
+ }
+ face = font->face; /* shortcut */
+@@ -701,6 +743,7 @@
+ if (FT_Set_Char_Size (face, 0, (FT_F26Dot6) (ptsize * 64),
+ GD_RESOLUTION, GD_RESOLUTION))
+ {
++ gdCacheDelete( tc_cache );
+ return "Could not set character size";
+ }
+
+@@ -715,6 +758,10 @@
+
+ use_kerning = FT_HAS_KERNING (face);
+ previous = 0;
++ if (fg < 0)
++ {
++ render_mode |= FT_LOAD_MONOCHROME;
++ }
+
+ #ifndef JISX0208
+ if (font->have_char_map_sjis)
+@@ -821,6 +868,9 @@
+ }
+ }
+
++ /* set rotation transform */
++ FT_Set_Transform(face, &matrix, NULL);
++
+ /* Convert character code to glyph index */
+ glyph_index = FT_Get_Char_Index (face, ch);
+
+@@ -833,50 +883,60 @@
+ }
+
+ /* load glyph image into the slot (erase previous one) */
+- err = FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT);
++ err = FT_Load_Glyph (face, glyph_index, render_mode);
+ if (err)
+- return "Problem loading glyph";
++ {
++ gdCacheDelete( tc_cache );
++ return "Problem loading glyph";
++ }
+
+ /* transform glyph image */
+ FT_Get_Glyph (slot, &image);
+ if (brect)
+ { /* only if need brect */
+ FT_Glyph_Get_CBox (image, ft_glyph_bbox_gridfit, &glyph_bbox);
+- if (!i)
+- { /* if first character, init BB corner values */
+- bbox.xMin = bbox.yMin = (1 << 30) - 1;
+- bbox.xMax = bbox.yMax = -bbox.xMin;
+- }
+ glyph_bbox.xMin += penf.x;
+ glyph_bbox.yMin += penf.y;
+ glyph_bbox.xMax += penf.x;
+ glyph_bbox.yMax += penf.y;
+- if (bbox.xMin > glyph_bbox.xMin)
+- bbox.xMin = glyph_bbox.xMin;
+- if (bbox.yMin > glyph_bbox.yMin)
+- bbox.yMin = glyph_bbox.yMin;
+- if (bbox.xMax < glyph_bbox.xMax)
+- bbox.xMax = glyph_bbox.xMax;
+- if (bbox.yMax < glyph_bbox.yMax)
+- bbox.yMax = glyph_bbox.yMax;
++ if (ch == ' ') /* special case for trailing space */
++ glyph_bbox.xMax += slot->metrics.horiAdvance;
++ if (!i)
++ { /* if first character, init BB corner values */
++ bbox.xMin = glyph_bbox.xMin;
++ bbox.yMin = glyph_bbox.yMin;
++ bbox.xMax = glyph_bbox.xMax;
++ bbox.yMax = glyph_bbox.yMax;
++ }
++ else
++ {
++ if (bbox.xMin > glyph_bbox.xMin)
++ bbox.xMin = glyph_bbox.xMin;
++ if (bbox.yMin > glyph_bbox.yMin)
++ bbox.yMin = glyph_bbox.yMin;
++ if (bbox.xMax < glyph_bbox.xMax)
++ bbox.xMax = glyph_bbox.xMax;
++ if (bbox.yMax < glyph_bbox.yMax)
++ bbox.yMax = glyph_bbox.yMax;
++ }
+ i++;
+ }
+
+- /* transform glyph image */
+- FT_Glyph_Transform (image, &matrix, 0);
+-
+ if (render)
+ {
+ if (image->format != ft_glyph_format_bitmap)
+ {
+ err = FT_Glyph_To_Bitmap (&image, ft_render_mode_normal, 0, 1);
+ if (err)
+- return "Problem rendering glyph";
++ {
++ gdCacheDelete( tc_cache );
++ return "Problem rendering glyph";
++ }
+ }
+
+ /* now, draw to our target surface */
+ bm = (FT_BitmapGlyph) image;
+- gdft_draw_bitmap (im, fg, bm->bitmap,
++ gdft_draw_bitmap (tc_cache, im, fg, bm->bitmap,
+ x + x1 + ((pen.x + 31) >> 6) + bm->left,
+ y - y1 + ((pen.y + 31) >> 6) - bm->top);
+ }
+@@ -922,15 +982,8 @@
+
+ if (tmpstr)
+ gdFree (tmpstr);
++ gdCacheDelete (tc_cache);
+ return (char *) NULL;
+ }
+
+-int
+-gdroundupdown (FT_F26Dot6 v1, int updown)
+-{
+- return (!updown)
+- ? (v1 < 0 ? ((v1 - 63) >> 6) : v1 >> 6)
+- : (v1 > 0 ? ((v1 + 63) >> 6) : v1 >> 6);
+-}
+-
+ #endif /* HAVE_LIBFREETYPE */