summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRasmus Lerdorf <rasmus@php.net>2002-10-29 23:08:01 +0000
committerRasmus Lerdorf <rasmus@php.net>2002-10-29 23:08:01 +0000
commita24534a1ed1a38024fba0c5fe5374effb7432d0b (patch)
treed60c061c3cec25d29c4d99026eee958b75aa4a34
parent8c95cefac6db0ec18002e9c46b55895c584c8c07 (diff)
downloadphp-git-a24534a1ed1a38024fba0c5fe5374effb7432d0b.tar.gz
Update bundled gd library with relevant changes from gd-2.0.4
I still need to add a configure check for the gdIOCtx struct changes so building against older external gd libs will work again.
-rw-r--r--ext/gd/gd.c6
-rw-r--r--ext/gd/gd_ctx.c4
-rw-r--r--ext/gd/libgd/gd.c24
-rw-r--r--ext/gd/libgd/gd.h7
-rw-r--r--ext/gd/libgd/gd2topng.c4
-rw-r--r--ext/gd/libgd/gd_gd.c8
-rw-r--r--ext/gd/libgd/gd_gd2.c35
-rw-r--r--ext/gd/libgd/gd_gif_in.c4
-rw-r--r--ext/gd/libgd/gd_io.h2
-rw-r--r--ext/gd/libgd/gd_io_dp.c3
-rw-r--r--ext/gd/libgd/gd_io_file.c2
-rw-r--r--ext/gd/libgd/gd_io_ss.c2
-rw-r--r--ext/gd/libgd/gd_jpeg.c20
-rw-r--r--ext/gd/libgd/gd_png.c17
-rw-r--r--ext/gd/libgd/gd_ss.c19
-rw-r--r--ext/gd/libgd/gd_wbmp.c6
-rw-r--r--ext/gd/libgd/gdcache.h5
-rw-r--r--ext/gd/libgd/gdft.c313
-rw-r--r--ext/gd/libgd/gdhelpers.h2
-rw-r--r--ext/gd/libgd/gdkanji.c2
-rw-r--r--ext/gd/libgd/gdparttopng.c4
-rw-r--r--ext/gd/libgd/gdtest.c6
22 files changed, 327 insertions, 168 deletions
diff --git a/ext/gd/gd.c b/ext/gd/gd.c
index f56aa1c17f..0f560b0c01 100644
--- a/ext/gd/gd.c
+++ b/ext/gd/gd.c
@@ -1073,10 +1073,10 @@ static int _php_image_type (char data[8])
io_ctx = gdNewDynamicCtx (8, data);
if (io_ctx) {
if (getmbi((int(*)(void*))gdGetC, io_ctx) == 0 && skipheader((int(*)(void*))gdGetC, io_ctx) == 0 ) {
- io_ctx->free(io_ctx);
+ io_ctx->gd_free(io_ctx);
return PHP_GDIMG_TYPE_WBM;
} else
- io_ctx->free(io_ctx);
+ io_ctx->gd_free(io_ctx);
}
}
#endif
@@ -1253,7 +1253,7 @@ static void _php_image_create_from(INTERNAL_FUNCTION_PARAMETERS, int image_type,
} else {
im = (*ioctx_func_p)(io_ctx);
}
- io_ctx->free(io_ctx);
+ io_ctx->gd_free(io_ctx);
#endif
}
else {
diff --git a/ext/gd/gd_ctx.c b/ext/gd/gd_ctx.c
index 3e6b17dead..e836757f07 100644
--- a/ext/gd/gd_ctx.c
+++ b/ext/gd/gd_ctx.c
@@ -67,7 +67,7 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type,
ctx = emalloc(sizeof(gdIOCtx));
ctx->putC = _php_image_output_putc;
ctx->putBuf = _php_image_output_putbuf;
- ctx->free = _php_image_output_ctxfree;
+ ctx->gd_free = _php_image_output_ctxfree;
#if APACHE && defined(CHARSET_EBCDIC)
/* XXX this is unlikely to work any more thies@thieso.net */
@@ -95,7 +95,7 @@ static void _php_image_output_ctx(INTERNAL_FUNCTION_PARAMETERS, int image_type,
break;
}
- ctx->free(ctx);
+ ctx->gd_free(ctx);
if(fp) {
fflush(fp);
diff --git a/ext/gd/libgd/gd.c b/ext/gd/libgd/gd.c
index 2d712a6db3..f946b15f71 100644
--- a/ext/gd/libgd/gd.c
+++ b/ext/gd/libgd/gd.c
@@ -90,6 +90,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);
gdImagePtr
gdImageCreate (int sx, int sy)
@@ -152,8 +153,13 @@ gdImageCreateTrueColor (int sx, int sy)
im->transparent = (-1);
im->interlace = 0;
im->trueColor = 1;
- im->saveAlphaFlag = 1;
- im->alphaBlendingFlag = 0;
+ /* 2.0.2: alpha blending is now on by default, and saving of alpha is
+ off by default. This allows font antialiasing to work as expected
+ on the first try in JPEGs -- quite important -- and also allows
+ for smaller PNGs when saving of alpha channel is not really
+ desired, which it usually isn't! */
+ im->saveAlphaFlag = 0;
+ im->alphaBlendingFlag = 1;
im->thick = 1;
return im;
}
@@ -217,7 +223,8 @@ gdImageColorClosestAlpha (gdImagePtr im, int r, int g, int b, int a)
rd = (im->red[i] - r);
gd = (im->green[i] - g);
bd = (im->blue[i] - b);
- ad = (im->blue[i] - b);
+ /* gd 2.02: whoops, was - b (thanks to David Marwood) */
+ ad = (im->blue[i] - a);
dist = rd * rd + gd * gd + bd * bd + ad * ad;
if (first || (dist < mindist))
{
@@ -509,6 +516,12 @@ gdImageColorResolveAlpha (gdImagePtr im, int r, int g, int b, int a)
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);
@@ -1336,7 +1349,7 @@ gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int
gdPoint pts[3];
int i;
int lx = 0, ly = 0;
- int fx, fy;
+ int fx = 0, fy = 0;
int w2, h2;
w2 = w / 2;
h2 = h / 2;
@@ -1975,7 +1988,7 @@ gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX
tox = dstX;
for (x = srcX; (x < (srcX + srcW)); x++)
{
- int nc;
+ int nc = 0;
int mapTo;
if (!stx[x - srcX])
{
@@ -2073,7 +2086,6 @@ gdImageCopyResampled (gdImagePtr dst,
{
for (x = dstX; (x < dstX + dstW); x++)
{
- /*int pd = gdImageGetPixel (dst, x, y);*/
float sy1, sy2, sx1, sx2;
float sx, sy;
float spixels = 0.0f;
diff --git a/ext/gd/libgd/gd.h b/ext/gd/libgd/gd.h
index ab38a577c9..21c3c5515b 100644
--- a/ext/gd/libgd/gd.h
+++ b/ext/gd/libgd/gd.h
@@ -7,7 +7,7 @@ extern "C" {
#ifndef WIN32
/* default fontpath for unix systems */
-#define DEFAULT_FONTPATH "/usr/share/fonts/truetype"
+#define DEFAULT_FONTPATH "/usr/X11R6/lib/X11/fonts/TrueType:/usr/X11R6/lib/X11/fonts/truetype:/usr/X11R6/lib/X11/fonts/TTF:/usr/share/fonts/TrueType:/usr/share/fonts/truetype:/usr/openwin/lib/X11/fonts/TrueType:/usr/X11R6/lib/X11/fonts/Type1"
#define PATHSEPARATOR ":"
#else
/* default fontpath for windows systems */
@@ -254,6 +254,9 @@ 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();
+
/* Calls gdImageStringFT. Provided for backwards compatibility only. */
char *gdImageStringTTF(gdImage *im, int *brect, int fg, char *fontlist,
double ptsize, double angle, int x, int y, char *string);
@@ -370,6 +373,8 @@ void gdFree(void *m);
/* Best to free this memory with gdFree(), not free() */
void *gdImageWBMPPtr(gdImagePtr im, int *size, int fg);
+/* 100 is highest quality (there is always a little loss with JPEG).
+ 0 is lowest. 10 is about the lowest useful setting. */
void gdImageJpeg(gdImagePtr im, FILE *out, int quality);
void gdImageJpegCtx(gdImagePtr im, gdIOCtx *out, int quality);
diff --git a/ext/gd/libgd/gd2topng.c b/ext/gd/libgd/gd2topng.c
index c898f25e18..6db5eb3003 100644
--- a/ext/gd/libgd/gd2topng.c
+++ b/ext/gd/libgd/gd2topng.c
@@ -37,7 +37,11 @@ main (int argc, char **argv)
gdImageDestroy (im);
exit (1);
}
+#ifdef HAVE_LIBPNG
gdImagePng (im, out);
+#else
+ fprintf(stderr, "No PNG library support available.\n");
+#endif
fclose (out);
gdImageDestroy (im);
diff --git a/ext/gd/libgd/gd_gd.c b/ext/gd/libgd/gd_gd.c
index 60037395c3..53b1c71f99 100644
--- a/ext/gd/libgd/gd_gd.c
+++ b/ext/gd/libgd/gd_gd.c
@@ -147,7 +147,7 @@ gdImageCreateFromGd (FILE * inFile)
in = gdNewFileCtx (inFile);
im = gdImageCreateFromGdCtx (in);
- in->free (in);
+ in->gd_free (in);
return im;
}
@@ -196,7 +196,7 @@ _gdPutColors (gdImagePtr im, gdIOCtx * out)
{
int i;
- gdPutC ((unsigned char)im->trueColor, out);
+ gdPutC (im->trueColor, out);
if (!im->trueColor)
{
gdPutWord (im->colorsTotal, out);
@@ -256,7 +256,7 @@ gdImageGd (gdImagePtr im, FILE * outFile)
{
gdIOCtx *out = gdNewFileCtx (outFile);
_gdImageGd (im, out);
- out->free (out);
+ out->gd_free (out);
}
void *
@@ -266,6 +266,6 @@ gdImageGdPtr (gdImagePtr im, int *size)
gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
_gdImageGd (im, out);
rv = gdDPExtractData (out, size);
- out->free (out);
+ out->gd_free (out);
return rv;
}
diff --git a/ext/gd/libgd/gd_gd2.c b/ext/gd/libgd/gd_gd2.c
index 98e619b19a..66d98f0915 100644
--- a/ext/gd/libgd/gd_gd2.c
+++ b/ext/gd/libgd/gd_gd2.c
@@ -15,10 +15,11 @@
#include <math.h>
#include <string.h>
#include <stdlib.h>
-#include <zlib.h>
#include "gd.h"
#include "gdhelpers.h"
+#include <zlib.h>
+
#define TRUE 1
#define FALSE 0
@@ -250,7 +251,7 @@ gdImageCreateFromGd2 (FILE * inFile)
im = gdImageCreateFromGd2Ctx (in);
- in->free (in);
+ in->gd_free (in);
return im;
}
@@ -266,10 +267,10 @@ gdImageCreateFromGd2Ctx (gdIOCtxPtr in)
t_chunk_info *chunkIdx = NULL; /* So we can gdFree it with impunity. */
unsigned char *chunkBuf = NULL; /* So we can gdFree it with impunity. */
int chunkNum = 0;
- int chunkMax;
+ int chunkMax = 0;
uLongf chunkLen;
- int chunkPos;
- int compMax;
+ int chunkPos = 0;
+ int compMax = 0;
int bytesPerPixel;
char *compBuf = NULL; /* So we can gdFree it with impunity. */
@@ -433,7 +434,7 @@ gdImageCreateFromGd2Part (FILE * inFile, int srcx, int srcy, int w, int h)
im = gdImageCreateFromGd2PartCtx (in, srcx, srcy, w, h);
- in->free (in);
+ in->gd_free (in);
return im;
}
@@ -450,9 +451,9 @@ gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w, int h)
t_chunk_info *chunkIdx = NULL;
char *chunkBuf = NULL;
int chunkNum;
- int chunkMax;
+ int chunkMax = 0;
uLongf chunkLen;
- int chunkPos;
+ int chunkPos = 0;
int compMax;
char *compBuf = NULL;
@@ -635,10 +636,10 @@ gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int srcy, int w, int h)
{
if (im->trueColor)
{
- ch = (chunkBuf[chunkPos++] << 24)
- + (chunkBuf[chunkPos++] << 16)
- + (chunkBuf[chunkPos++] << 8)
- + (chunkBuf[chunkPos++]);
+ ch = chunkBuf[chunkPos++];
+ ch = (ch << 8) + chunkBuf[chunkPos++];
+ ch = (ch << 8) + chunkBuf[chunkPos++];
+ ch = (ch << 8) + chunkBuf[chunkPos++];
}
else
{
@@ -710,12 +711,12 @@ _gdImageGd2 (gdImagePtr im, gdIOCtx * out, int cs, int fmt)
char *chunkData = NULL; /* So we can gdFree it with impunity. */
char *compData = NULL; /* So we can gdFree it with impunity. */
uLongf compLen;
- int idxPos;
+ int idxPos = 0;
int idxSize;
t_chunk_info *chunkIdx = NULL;
int posSave;
int bytesPerPixel = im->trueColor ? 4 : 1;
- int compMax;
+ int compMax = 0;
/*printf("Trying to write GD2 file\n"); */
@@ -762,7 +763,7 @@ _gdImageGd2 (gdImagePtr im, gdIOCtx * out, int cs, int fmt)
/* The zlib notes say output buffer size should be (input size) * 1.01 * 12 */
/* - we'll use 1.02 to be paranoid. */
/* */
- compMax = (int)(cs * bytesPerPixel * cs * 1.02f + 12);
+ compMax = cs * bytesPerPixel * cs * 1.02 + 12;
/* */
/* Allocate the buffers. */
@@ -908,7 +909,7 @@ gdImageGd2 (gdImagePtr im, FILE * outFile, int cs, int fmt)
{
gdIOCtx *out = gdNewFileCtx (outFile);
_gdImageGd2 (im, out, cs, fmt);
- out->free (out);
+ out->gd_free (out);
}
void *
@@ -918,6 +919,6 @@ gdImageGd2Ptr (gdImagePtr im, int cs, int fmt, int *size)
gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
_gdImageGd2 (im, out, cs, fmt);
rv = gdDPExtractData (out, size);
- out->free (out);
+ out->gd_free (out);
return rv;
}
diff --git a/ext/gd/libgd/gd_gif_in.c b/ext/gd/libgd/gd_gif_in.c
index e600b80470..fc1b587cc8 100644
--- a/ext/gd/libgd/gd_gif_in.c
+++ b/ext/gd/libgd/gd_gif_in.c
@@ -83,7 +83,7 @@ gdImagePtr gdImageCreateFromGifSource(gdSourcePtr inSource)
im = gdImageCreateFromGifCtx(in);
- in->free(in);
+ in->gd_free(in);
return im;
}
@@ -96,7 +96,7 @@ gdImageCreateFromGif(FILE *fdFile)
im = gdImageCreateFromGifCtx(fd);
- fd->free(fd);
+ fd->gd_free(fd);
return im;
}
diff --git a/ext/gd/libgd/gd_io.h b/ext/gd/libgd/gd_io.h
index 5c0bd24879..c28379abd8 100644
--- a/ext/gd/libgd/gd_io.h
+++ b/ext/gd/libgd/gd_io.h
@@ -13,7 +13,7 @@ typedef struct gdIOCtx {
int (*seek)(struct gdIOCtx*, const int);
long (*tell)(struct gdIOCtx*);
- void (*free)(struct gdIOCtx*);
+ void (*gd_free)(struct gdIOCtx*);
} gdIOCtx;
diff --git a/ext/gd/libgd/gd_io_dp.c b/ext/gd/libgd/gd_io_dp.c
index d28dfb01a4..c41743e78f 100644
--- a/ext/gd/libgd/gd_io_dp.c
+++ b/ext/gd/libgd/gd_io_dp.c
@@ -1,4 +1,3 @@
-
/*
* io_dp.c
*
@@ -95,7 +94,7 @@ gdNewDynamicCtx (int initialSize, void *data)
ctx->ctx.seek = dynamicSeek;
ctx->ctx.tell = dynamicTell;
- ctx->ctx.free = gdFreeDynamicCtx;
+ ctx->ctx.gd_free = gdFreeDynamicCtx;
return (gdIOCtx *) ctx;
}
diff --git a/ext/gd/libgd/gd_io_file.c b/ext/gd/libgd/gd_io_file.c
index d0efd1af79..713646120e 100644
--- a/ext/gd/libgd/gd_io_file.c
+++ b/ext/gd/libgd/gd_io_file.c
@@ -71,7 +71,7 @@ gdNewFileCtx (FILE * f)
ctx->ctx.tell = fileTell;
ctx->ctx.seek = fileSeek;
- ctx->ctx.free = gdFreeFileCtx;
+ ctx->ctx.gd_free = gdFreeFileCtx;
return (gdIOCtx *) ctx;
}
diff --git a/ext/gd/libgd/gd_io_ss.c b/ext/gd/libgd/gd_io_ss.c
index 1ea78d568b..dd96fdfa45 100644
--- a/ext/gd/libgd/gd_io_ss.c
+++ b/ext/gd/libgd/gd_io_ss.c
@@ -71,7 +71,7 @@ gdNewSSCtx (gdSourcePtr src, gdSinkPtr snk)
ctx->ctx.tell = NULL;
ctx->ctx.seek = NULL;
- ctx->ctx.free = gdFreeSsCtx;
+ ctx->ctx.gd_free = gdFreeSsCtx;
return (gdIOCtx *) ctx;
}
diff --git a/ext/gd/libgd/gd_jpeg.c b/ext/gd/libgd/gd_jpeg.c
index 96b895ec38..b0bfb0a065 100644
--- a/ext/gd/libgd/gd_jpeg.c
+++ b/ext/gd/libgd/gd_jpeg.c
@@ -1,5 +1,3 @@
-
-
/*
* gd_jpeg.c: Read and write JPEG (JFIF) format image files using the
* gd graphics library (http://www.boutell.com/gd/).
@@ -20,20 +18,21 @@
* major CGI brain damage
*/
-/* TBB: move this up so include files are not brought in */
-#ifdef HAVE_LIBJPEG
-
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <limits.h>
#include <string.h>
+#include "gd.h"
+/* TBB: move this up so include files are not brought in */
+/* JCE: arrange HAVE_LIBJPEG so that it can be set in gd.h */
+#ifdef HAVE_LIBJPEG
+#include "gdhelpers.h"
+
/* 1.8.1: remove dependency on jinclude.h */
#include "jpeglib.h"
#include "jerror.h"
-#include "gd.h"
-#include "gdhelpers.h"
static const char *const GD_JPEG_VERSION = "1.0";
@@ -85,7 +84,7 @@ gdImageJpeg (gdImagePtr im, FILE * outFile, int quality)
{
gdIOCtx *out = gdNewFileCtx (outFile);
gdImageJpegCtx (im, out, quality);
- out->free (out);
+ out->gd_free (out);
}
void *
@@ -95,7 +94,7 @@ gdImageJpegPtr (gdImagePtr im, int *size, int quality)
gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
gdImageJpegCtx (im, out, quality);
rv = gdDPExtractData (out, size);
- out->free (out);
+ out->gd_free (out);
return rv;
}
@@ -249,7 +248,6 @@ gdImageJpegCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
}
}
jpeg_finish_compress (&cinfo);
-/*error:*/
jpeg_destroy_compress (&cinfo);
gdFree (row);
}
@@ -260,7 +258,7 @@ gdImageCreateFromJpeg (FILE * inFile)
gdImagePtr im;
gdIOCtx *in = gdNewFileCtx (inFile);
im = gdImageCreateFromJpegCtx (in);
- in->free (in);
+ in->gd_free (in);
return im;
}
diff --git a/ext/gd/libgd/gd_png.c b/ext/gd/libgd/gd_png.c
index 19f74cdef2..1c91eaa16c 100644
--- a/ext/gd/libgd/gd_png.c
+++ b/ext/gd/libgd/gd_png.c
@@ -1,11 +1,12 @@
-
-#ifdef HAVE_LIBPNG
-
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include "gd.h"
+
+/* JCE: Arrange HAVE_LIBPNG so that it can be set in gd.h */
+#ifdef HAVE_LIBPNG
+
#include "gdhelpers.h"
#include "png.h" /* includes zlib.h and setjmp.h */
@@ -101,7 +102,7 @@ gdImageCreateFromPng (FILE * inFile)
gdImagePtr im;
gdIOCtx *in = gdNewFileCtx (inFile);
im = gdImageCreateFromPngCtx (in);
- in->free (in);
+ in->gd_free (in);
return im;
}
@@ -125,7 +126,7 @@ gdImageCreateFromPngCtx (gdIOCtx * infile)
png_bytep image_data = NULL;
png_bytepp row_pointers = NULL;
gdImagePtr im = NULL;
- int i, j, *open;
+ int i, j, *open = NULL;
png_uint_32 ui, uj;
volatile int transparent = -1;
volatile int palette_allocated = FALSE;
@@ -422,7 +423,7 @@ gdImagePng (gdImagePtr im, FILE * outFile)
{
gdIOCtx *out = gdNewFileCtx (outFile);
gdImagePngCtx (im, out);
- out->free (out);
+ out->gd_free (out);
}
void *
@@ -432,7 +433,7 @@ gdImagePngPtr (gdImagePtr im, int *size)
gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
gdImagePngCtx (im, out);
rv = gdDPExtractData (out, size);
- out->free (out);
+ out->gd_free (out);
return rv;
}
@@ -443,7 +444,7 @@ gdImagePngPtr (gdImagePtr im, int *size)
void
gdImagePngCtx (gdImagePtr im, gdIOCtx * outfile)
{
- int i, j, bit_depth, interlace_type;
+ int i, j, bit_depth = 0, interlace_type;
int width = im->sx;
int height = im->sy;
int colors = im->colorsTotal;
diff --git a/ext/gd/libgd/gd_ss.c b/ext/gd/libgd/gd_ss.c
index 200442ba0f..d640a2193d 100644
--- a/ext/gd/libgd/gd_ss.c
+++ b/ext/gd/libgd/gd_ss.c
@@ -16,12 +16,13 @@ extern gdImagePtr gdImageCreateFromPngSource (gdSourcePtr inSource);
/*#define GD_SS_DBG(s) (s) */
#define GD_SS_DBG(s)
+#ifdef HAVE_LIBPNG
void
gdImagePngToSink (gdImagePtr im, gdSinkPtr outSink)
{
gdIOCtx *out = gdNewSSCtx (NULL, outSink);
gdImagePngCtx (im, out);
- out->free (out);
+ out->gd_free (out);
}
gdImagePtr
@@ -32,7 +33,21 @@ gdImageCreateFromPngSource (gdSourcePtr inSource)
im = gdImageCreateFromPngCtx (in);
- in->free (in);
+ in->gd_free (in);
return im;
}
+#else /* no HAVE_LIBPNG */
+void
+gdImagePngToSink (gdImagePtr im, gdSinkPtr outSink)
+{
+ fprintf(stderr,"PNG support is not available\n");
+}
+gdImagePtr
+gdImageCreateFromPngSource (gdSourcePtr inSource)
+{
+ fprintf(stderr,"PNG support is not available\n");
+ return NULL;
+}
+#endif /* HAVE_LIBPNG */
+
diff --git a/ext/gd/libgd/gd_wbmp.c b/ext/gd/libgd/gd_wbmp.c
index c7948f9865..02abaf6a5b 100644
--- a/ext/gd/libgd/gd_wbmp.c
+++ b/ext/gd/libgd/gd_wbmp.c
@@ -188,7 +188,7 @@ gdImageCreateFromWBMP (FILE * inFile)
gdImagePtr im;
gdIOCtx *in = gdNewFileCtx (inFile);
im = gdImageCreateFromWBMPCtx (in);
- in->free (in);
+ in->gd_free (in);
return (im);
}
@@ -200,7 +200,7 @@ gdImageWBMP (gdImagePtr im, int fg, FILE * outFile)
{
gdIOCtx *out = gdNewFileCtx (outFile);
gdImageWBMPCtx (im, fg, out);
- out->free (out);
+ out->gd_free (out);
}
/* gdImageWBMPPtr
@@ -213,6 +213,6 @@ gdImageWBMPPtr (gdImagePtr im, int *size, int fg)
gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
gdImageWBMPCtx (im, fg, out);
rv = gdDPExtractData (out, size);
- out->free (out);
+ out->gd_free (out);
return rv;
}
diff --git a/ext/gd/libgd/gdcache.h b/ext/gd/libgd/gdcache.h
index f2e8509106..2446d614bd 100644
--- a/ext/gd/libgd/gdcache.h
+++ b/ext/gd/libgd/gdcache.h
@@ -40,7 +40,10 @@
/* header */
/*********************************************************/
-#include <malloc.h>
+#include <stdlib.h>
+#ifdef HAVE_MALLOC_H
+ #include <malloc.h>
+#endif
#ifndef NULL
#define NULL (void *)0
#endif
diff --git a/ext/gd/libgd/gdft.c b/ext/gd/libgd/gdft.c
index 520e49f351..8345c78894 100644
--- a/ext/gd/libgd/gdft.c
+++ b/ext/gd/libgd/gdft.c
@@ -15,7 +15,7 @@
#ifndef MSWIN32
#include <unistd.h>
#else
-#define R_OK 2
+#include <io.h>
#endif
#ifdef WIN32
extern int access(const char *pathname, int mode);
@@ -352,7 +352,6 @@ fontFetch (char **error, void *key)
fontsearchpath = getenv ("GDFONTPATH");
if (!fontsearchpath)
fontsearchpath = DEFAULT_FONTPATH;
- path = strdup (fontsearchpath);
fontlist = strdup (a->fontlist);
/*
@@ -362,6 +361,8 @@ fontFetch (char **error, void *key)
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.
@@ -369,7 +370,7 @@ fontFetch (char **error, void *key)
fullname = gdRealloc (fullname,
strlen (fontsearchpath) + strlen (name) + 6);
/* if name is an absolute filename then test directly */
- if (*name == '/')
+ if (*name == '/' || (name[0] != 0 && name[1] == ':' && (name[2] == '/' || name[2] == '\\')))
{
sprintf (fullname, "%s", name);
if (access (fullname, R_OK) == 0)
@@ -387,11 +388,23 @@ fontFetch (char **error, void *key)
font_found++;
break;
}
+ sprintf (fullname, "%s/%s.pfa", dir, name);
+ if (access (fullname, R_OK) == 0)
+ {
+ font_found++;
+ break;
}
- if (font_found)
+ sprintf (fullname, "%s/%s.pfb", dir, name);
+ if (access (fullname, R_OK) == 0)
+ {
+ font_found++;
break;
}
+ }
gdFree (path);
+ if (font_found)
+ break;
+ }
gdFree (fontlist);
if (!font_found)
{
@@ -481,7 +494,10 @@ tweenColorTest (void *element, void *key)
* Computes a color in im's color table that is part way between
* the background and foreground colors proportional to the gray
* pixel value in the range 0-NUMCOLORS. The fg and bg colors must already
- * be in the color table.
+ * be in the color table for palette images. For truecolor images the
+ * returned value simply has an alpha component and gdImageAlphaBlend
+ * does the work so that text can be alpha blended across a complex
+ * background (TBB; and for real in 2.0.2).
*/
static void *
tweenColorFetch (char **error, void *key)
@@ -500,31 +516,34 @@ tweenColorFetch (char **error, void *key)
/* if fg is specified by a negative color idx, then don't antialias */
if (fg < 0)
{
+ if ((pixel + pixel) >= NUMCOLORS)
a->tweencolor = -fg;
+ else
+ a->tweencolor = bg;
}
else
{
npixel = NUMCOLORS - pixel;
if (im->trueColor)
- {
- /* 2.0.1: use gdImageSetPixel to do the alpha blending work,
- or to just store the alpha level. All we have to do here
- is incorporate our knowledge of the percentage of this
- pixel that is really "lit" by pushing the alpha value
- up toward transparency in edge regions. */
- a->tweencolor = gdTrueColorAlpha (
- gdTrueColorGetRed (fg),
- gdTrueColorGetGreen (fg),
- gdTrueColorGetBlue (fg),
- gdAlphaMax - ((gdAlphaMax - gdTrueColorGetAlpha (fg)) * pixel / NUMCOLORS) );
- }
+ {
+ /* 2.0.1: use gdImageSetPixel to do the alpha blending work,
+ or to just store the alpha level. All we have to do here
+ is incorporate our knowledge of the percentage of this
+ pixel that is really "lit" by pushing the alpha value
+ up toward transparency in edge regions. */
+ a->tweencolor = gdTrueColorAlpha (
+ gdTrueColorGetRed (fg),
+ gdTrueColorGetGreen (fg),
+ gdTrueColorGetBlue (fg),
+ gdAlphaMax - (gdTrueColorGetAlpha (fg) * pixel / NUMCOLORS));
+ }
else
- {
+ {
a->tweencolor = gdImageColorResolve (im,
(pixel * im->red[fg] + npixel * im->red[bg]) / NUMCOLORS,
(pixel * im->green[fg] + npixel * im->green[bg]) / NUMCOLORS,
(pixel * im->blue[fg] + npixel * im->blue[bg]) / NUMCOLORS);
- }
+ }
}
return (void *) a;
}
@@ -537,29 +556,84 @@ tweenColorRelease (void *element)
/* 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;
+ unsigned char *pixel = NULL;
+ int *tpixel = NULL;
int x, y, row, col, pc;
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;
+ /* Truecolor version; does not require the cache */
+ if (im->trueColor)
+ {
+ for (row = 0; row < bitmap.rows; row++)
+ {
+ pc = row * bitmap.pitch;
+ y = pen_y + row;
+ /* clip if out of bounds */
+ if (y >= im->sy || y < 0)
+ continue;
+ for (col = 0; col < bitmap.width; col++, pc++)
+ {
+ int level;
+ if (bitmap.pixel_mode == ft_pixel_mode_grays)
+ {
+ /*
+ * Scale to 128 levels of alpha for gd use.
+ * alpha 0 is opacity, so be sure to invert at the end
+ */
+ level = (bitmap.buffer[pc] * gdAlphaMax /
+ (bitmap.num_grays - 1));
+ }
+ else if (bitmap.pixel_mode == ft_pixel_mode_mono)
+ {
+ level = ((bitmap.buffer[pc / 8]
+ << (pc % 8)) & 128) ? gdAlphaOpaque :
+ gdAlphaTransparent;
+ }
+ else
+ {
+ return "Unsupported ft_pixel_mode";
+ }
+ if (fg >= 0) {
+ /* Consider alpha in the foreground color itself to be an
+ upper bound on how opaque things get */
+ level = level * (gdAlphaMax - gdTrueColorGetAlpha(fg)) / gdAlphaMax;
+ }
+ level = gdAlphaMax - level;
+ x = pen_x + col;
+ /* clip if out of bounds */
+ if (x >= im->sx || x < 0)
+ continue;
+ /* get pixel location in gd buffer */
+ tpixel = &im->tpixels[y][x];
+ if (fg < 0) {
+ if (level < (gdAlphaMax / 2)) {
+ *tpixel = -fg;
+ }
+ } else {
+ if (im->alphaBlendingFlag) {
+ *tpixel = gdAlphaBlend(*tpixel, (level << 24) + (fg & 0xFFFFFF));
+ } else {
+ *tpixel = (level << 24) + (fg & 0xFFFFFF);
+ }
+ }
+ }
+ }
+ return (char *) NULL;
+ }
+ /* Non-truecolor case, restored to its more or less original form */
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 */
@@ -568,53 +642,49 @@ gdft_draw_bitmap (gdImage * im, int fg, FT_Bitmap bitmap, int pen_x, int pen_y)
for (col = 0; col < bitmap.width; col++, pc++)
{
- x = pen_x + col;
-
- /* clip if out of bounds */
- if (x >= im->sx || x < 0)
- continue;
-
- switch(bitmap.pixel_mode) {
- case ft_pixel_mode_grays:
+ if (bitmap.pixel_mode == ft_pixel_mode_grays)
+ {
/*
* Round to NUMCOLORS levels of antialiasing for
* index color images since only 256 colors are
* available.
*/
-
tc_key.pixel = ((bitmap.buffer[pc] * NUMCOLORS)
+ bitmap.num_grays / 2)
/ (bitmap.num_grays - 1);
- break;
- case ft_pixel_mode_mono:
+ }
+ else if (bitmap.pixel_mode == ft_pixel_mode_mono)
+ {
tc_key.pixel = ((bitmap.buffer[pc / 8]
<< (pc % 8)) & 128) ? NUMCOLORS : 0;
- break;
- default:
+ }
+ else
+ {
return "Unsupported ft_pixel_mode";
}
-
- if (tc_key.pixel > 0)
+ if (tc_key.pixel > 0) /* if not background */
+ {
+ x = pen_x + col;
+
+ /* clip if out of bounds */
+ if (x >= im->sx || x < 0)
+ continue;
+ /* get pixel location in gd buffer */
+ pixel = &im->pixels[y][x];
+ if (tc_key.pixel == NUMCOLORS)
{
-
- if (im->trueColor) {
- tc_elem = (tweencolor_t *) gdCacheGet (
- tc_cache, &tc_key);
-
- gdImageSetPixel(im, x, y, tc_elem->tweencolor);
+ /* use fg color directly. gd 2.0.2: watch out for
+ negative indexes (thanks to David Marwood). */
+ *pixel = (fg < 0) ? -fg : fg;
}
- else {
- pixel = &im->pixels[y][x];
- if (tc_key.pixel == NUMCOLORS)
- *pixel = fg;
- else {
- tc_key.bgcolor = *pixel;
+ else
+ {
+ /* find antialised color */
+
+ tc_key.bgcolor = *pixel;
tc_elem = (tweencolor_t *) gdCacheGet (
tc_cache, &tc_key);
- *pixel = tc_elem->tweencolor;
-
- }
-
+ *pixel = tc_elem->tweencolor;
}
}
}
@@ -622,23 +692,38 @@ gdft_draw_bitmap (gdImage * im, int fg, FT_Bitmap bitmap, int pen_x, int pen_y)
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 */
char *
gdImageStringFT (gdImage * im, int *brect, int fg, char *fontlist,
- double ptsize, double angle, int x, int y, char *string)
+ double ptsize, double angle, int x, int y, char *string)
{
- return gdImageStringFTEx(im, brect, fg, fontlist, ptsize, angle, x, y, string, 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);
+ return gdImageStringFTEx(im, brect, fg, fontlist, ptsize, angle, x, y, string, NULL);
}
char *
@@ -665,18 +750,30 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
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;
+
+ /* fine tuning */
+ double linespace = LINESPACE;
+
+ /*
+ * 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 );
- /* fine tuning */
- double linespace = LINESPACE;
-
/***** initialize font library and font cache on first call ******/
- static gdCache_head_t *fontCache;
- static FT_Library library;
if (!fontCache)
{
if (FT_Init_FreeType (&library))
{
+ gdCacheDelete( tc_cache );
return "Failure to initialize font library";
}
fontCache = gdCacheCreate (FONTCACHESIZE,
@@ -690,6 +787,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
font = (font_t *) gdCacheGet (fontCache, &fontkey);
if (!font)
{
+ gdCacheDelete( tc_cache );
return fontCache->error;
}
face = font->face; /* shortcut */
@@ -698,17 +796,16 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
if (FT_Set_Char_Size (face, 0, (FT_F26Dot6) (ptsize * 64),
GD_RESOLUTION, GD_RESOLUTION))
{
+ gdCacheDelete( tc_cache );
return "Could not set character size";
}
- /* pull in supplied extended settings */
- if (strex) {
- if ((strex->flags & gdFTEX_LINESPACE) == gdFTEX_LINESPACE)
- linespace = strex->linespacing;
-
- }
+ /* pull in supplied extended settings */
+ if (strex) {
+ if ((strex->flags & gdFTEX_LINESPACE) == gdFTEX_LINESPACE)
+ linespace = strex->linespacing;
+ }
-
matrix.xx = (FT_Fixed) (cos_a * (1 << 16));
matrix.yx = (FT_Fixed) (sin_a * (1 << 16));
matrix.xy = -matrix.yx;
@@ -720,12 +817,16 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
use_kerning = FT_HAS_KERNING (face);
previous = 0;
+ if (fg < 0)
+ {
+ render_mode |= FT_LOAD_MONOCHROME;
+ }
#ifndef JISX0208
if (font->have_char_map_sjis)
{
#endif
- if ((tmpstr = (char *) gdMalloc (BUFSIZ)) != NULL)
+ if ((tmpstr = (char *) gdMalloc (BUFSIZ)))
{
any2eucjp (tmpstr, string, BUFSIZ);
next = tmpstr;
@@ -749,8 +850,8 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
if (ch == '\r')
{
penf.x = 0;
- x1 = (int)(penf.x * cos_a - penf.y * sin_a + 32) / 64;
- y1 = (int)(penf.x * sin_a + penf.y * cos_a + 32) / 64;
+ x1 = (penf.x * cos_a - penf.y * sin_a + 32) / 64;
+ y1 = (penf.x * sin_a + penf.y * cos_a + 32) / 64;
pen.x = pen.y = 0;
previous = 0; /* clear kerning flag */
next++;
@@ -759,10 +860,10 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
/* newlines */
if (ch == '\n')
{
- penf.y -= (long)(face->size->metrics.height * linespace);
+ penf.y -= face->size->metrics.height * LINESPACE;
penf.y = (penf.y - 32) & -64; /* round to next pixel row */
- x1 = (int)(penf.x * cos_a - penf.y * sin_a + 32) / 64;
- y1 = (int)(penf.x * sin_a + penf.y * cos_a + 32) / 64;
+ x1 = (penf.x * cos_a - penf.y * sin_a + 32) / 64;
+ y1 = (penf.x * sin_a + penf.y * cos_a + 32) / 64;
pen.x = pen.y = 0;
previous = 0; /* clear kerning flag */
next++;
@@ -826,6 +927,9 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
}
}
+ /* set rotation transform */
+ FT_Set_Transform(face, &matrix, NULL);
+
/* Convert character code to glyph index */
glyph_index = FT_Get_Char_Index (face, ch);
@@ -838,24 +942,33 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
}
/* 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)
+ {
+ 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 (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)
@@ -864,24 +977,25 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
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)
+ {
+ 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);
}
@@ -927,6 +1041,7 @@ gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
if (tmpstr)
gdFree (tmpstr);
+ gdCacheDelete( tc_cache );
return (char *) NULL;
}
diff --git a/ext/gd/libgd/gdhelpers.h b/ext/gd/libgd/gdhelpers.h
index aefcc18b99..fdc690a2ec 100644
--- a/ext/gd/libgd/gdhelpers.h
+++ b/ext/gd/libgd/gdhelpers.h
@@ -1,6 +1,8 @@
#ifndef GDHELPERS_H
#define GDHELPERS_H 1
+#include <sys/types.h>
+
/* TBB: strtok_r is not universal; provide an implementation of it. */
extern char *gd_strtok_r(char *s, char *sep, char **state);
diff --git a/ext/gd/libgd/gdkanji.c b/ext/gd/libgd/gdkanji.c
index 98ed4b7c7a..21eb2d373d 100644
--- a/ext/gd/libgd/gdkanji.c
+++ b/ext/gd/libgd/gdkanji.c
@@ -360,7 +360,7 @@ do_convert (unsigned char *to, unsigned char *from, const char *code)
from_len = strlen ((const char *) from) + 1;
to_len = BUFSIZ;
- if (iconv (cd, (const char **) &from, &from_len,
+ if (iconv (cd, (char **) &from, &from_len,
(char **) &to, &to_len) == -1)
{
#ifdef HAVE_ERRNO_H
diff --git a/ext/gd/libgd/gdparttopng.c b/ext/gd/libgd/gdparttopng.c
index 03386b86be..677a0b5710 100644
--- a/ext/gd/libgd/gdparttopng.c
+++ b/ext/gd/libgd/gdparttopng.c
@@ -47,7 +47,11 @@ main (int argc, char **argv)
gdImageDestroy (im);
exit (1);
}
+#ifdef HAVE_LIBPNG
gdImagePng (im, out);
+#else
+ fprintf(stderr, "No PNG library support.\n");
+#endif
fclose (out);
gdImageDestroy (im);
diff --git a/ext/gd/libgd/gdtest.c b/ext/gd/libgd/gdtest.c
index 68d1d23a2b..f4300bb3fd 100644
--- a/ext/gd/libgd/gdtest.c
+++ b/ext/gd/libgd/gdtest.c
@@ -82,7 +82,7 @@ main (int argc, char **argv)
CompareImages ("GD->PNG ptr->GD", ref, im2);
gdImageDestroy (im2);
- ctx->free (ctx);
+ ctx->gd_free (ctx);
/* */
@@ -117,7 +117,7 @@ main (int argc, char **argv)
CompareImages ("GD->GD2 ptr->GD", ref, im2);
gdImageDestroy (im2);
- ctx->free (ctx);
+ ctx->gd_free (ctx);
/* */
@@ -152,7 +152,7 @@ main (int argc, char **argv)
CompareImages ("GD->GD ptr->GD", ref, im2);
gdImageDestroy (im2);
- ctx->free (ctx);
+ ctx->gd_free (ctx);
/*
** Test gdImageCreateFromPngSource'