Browse Source

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.
experimental/threaded
Rasmus Lerdorf 23 years ago
parent
commit
a24534a1ed
  1. 6
      ext/gd/gd.c
  2. 4
      ext/gd/gd_ctx.c
  3. 24
      ext/gd/libgd/gd.c
  4. 7
      ext/gd/libgd/gd.h
  5. 4
      ext/gd/libgd/gd2topng.c
  6. 8
      ext/gd/libgd/gd_gd.c
  7. 35
      ext/gd/libgd/gd_gd2.c
  8. 4
      ext/gd/libgd/gd_gif_in.c
  9. 2
      ext/gd/libgd/gd_io.h
  10. 3
      ext/gd/libgd/gd_io_dp.c
  11. 2
      ext/gd/libgd/gd_io_file.c
  12. 2
      ext/gd/libgd/gd_io_ss.c
  13. 20
      ext/gd/libgd/gd_jpeg.c
  14. 17
      ext/gd/libgd/gd_png.c
  15. 19
      ext/gd/libgd/gd_ss.c
  16. 6
      ext/gd/libgd/gd_wbmp.c
  17. 5
      ext/gd/libgd/gdcache.h
  18. 313
      ext/gd/libgd/gdft.c
  19. 2
      ext/gd/libgd/gdhelpers.h
  20. 2
      ext/gd/libgd/gdkanji.c
  21. 4
      ext/gd/libgd/gdparttopng.c
  22. 6
      ext/gd/libgd/gdtest.c

6
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 {

4
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);

24
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;

7
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);

4
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);

8
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;
}

35
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;
}

4
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;
}

2
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;

3
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;
}

2
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;
}

2
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;
}

20
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;
}

17
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;

19
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 */

6
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;
}

5
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

313
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;
}

2
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);

2
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

4
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);

6
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'

Loading…
Cancel
Save