From ab3ea8b27f99779af9e0675211fddc0db9c9d54b Mon Sep 17 00:00:00 2001 From: ellson Date: Thu, 26 Jul 2007 18:21:54 +0000 Subject: [PATCH] upgrade mylibgd tree to gd-2.0.35 use system gd-2.0.34 or later on fc7 or later distros --- lib/gd/annotate.c | 4 +- lib/gd/circletexttest.c | 3 - lib/gd/fontwheeltest.c | 12 +- lib/gd/gd.c | 848 +++++++++++++++++++++++++++++----------- lib/gd/gd.h | 17 +- lib/gd/gd_gd2.c | 73 +++- lib/gd/gd_gif_in.c | 341 +++++++++------- lib/gd/gd_gif_out.c | 9 +- lib/gd/gd_io.h | 2 +- lib/gd/gd_io_dp.c | 6 +- lib/gd/gd_io_ss.c | 2 +- lib/gd/gd_jpeg.c | 2 +- 12 files changed, 907 insertions(+), 412 deletions(-) diff --git a/lib/gd/annotate.c b/lib/gd/annotate.c index a4dc3b274..7324e4337 100644 --- a/lib/gd/annotate.c +++ b/lib/gd/annotate.c @@ -19,7 +19,7 @@ enum int main (int argc, char *argv[]) { -#ifndef HAVE_LIBFREETYPE +#ifndef HAVE_FREETYPE2 /* 2.0.12 */ fprintf (stderr, "annotate is not useful without freetype.\n" "Install freetype, then './configure; make clean; make install'\n" @@ -207,5 +207,5 @@ main (int argc, char *argv[]) gdImageDestroy (im); fclose (out); return 0; -#endif /* HAVE_LIBFREETYPE */ +#endif /* HAVE_FREETYPE2 */ } diff --git a/lib/gd/circletexttest.c b/lib/gd/circletexttest.c index 079ed8432..1c6658ff4 100644 --- a/lib/gd/circletexttest.c +++ b/lib/gd/circletexttest.c @@ -5,9 +5,6 @@ #include #include "gd.h" -/* 2.0.22: oops, we need config.h */ -#include "config.h" - int main (int argc, char *argv[]) { diff --git a/lib/gd/fontwheeltest.c b/lib/gd/fontwheeltest.c index b8e4f59ae..b552b6a9c 100644 --- a/lib/gd/fontwheeltest.c +++ b/lib/gd/fontwheeltest.c @@ -22,8 +22,6 @@ dowheel (gdImagePtr im, int color, char *fontfile, int fontsize, double angle, int x, int y, int offset, char *string) { int brect[8]; - gdPoint points[4]; - int i; FILE *err; double curangrads, curang, x0, y0; char *cp; @@ -51,15 +49,7 @@ dowheel (gdImagePtr im, int color, char *fontfile, int fontsize, if (cp) doerr (err, cp); - /* FIXME - this is silly, but if we try to cast int[] to gdPointPtr - * we get a "warning: dereferencing type-punned pointer will break strict -aliasing rules" from gcc - * The proper fix probably requires an API change to use gdPoint[] in gdImageString* - */ - for (i = 0; i < 4; i++) { - points[i].x = brect[2*i]; - points[i].y = brect[2*i + 1]; - } - gdImagePolygon (im, points, 4, color); + gdImagePolygon (im, (gdPointPtr)brect, 4, color); } fclose (err); diff --git a/lib/gd/gd.c b/lib/gd/gd.c index e809613c8..30920c094 100644 --- a/lib/gd/gd.c +++ b/lib/gd/gd.c @@ -1,3 +1,4 @@ +/* $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -71,17 +72,27 @@ BGD_DECLARE(gdImagePtr) gdImageCreate (int sx, int sy) { int i; gdImagePtr im; + + if (overflow2(sizeof (unsigned char *), sy)) { + return NULL; + } + if (overflow2(sizeof (unsigned char *), sx)) { + return NULL; + } + im = (gdImage *) gdMalloc (sizeof (gdImage)); - if (!im) - return NULL; + if (!im) { + return NULL; + } + memset (im, 0, sizeof (gdImage)); /* Row-major ever since gd 1.3 */ im->pixels = (unsigned char **) gdMalloc (sizeof (unsigned char *) * sy); - if (!im->pixels) - { - free(im); - return NULL; - } + if (!im->pixels) { + gdFree(im); + return NULL; + } + im->polyInts = 0; im->polyAllocated = 0; im->brush = 0; @@ -91,15 +102,17 @@ BGD_DECLARE(gdImagePtr) gdImageCreate (int sx, int sy) { /* Row-major ever since gd 1.3 */ im->pixels[i] = (unsigned char *) gdCalloc (sx, sizeof (unsigned char)); - if (!im->pixels[i]) - { - for (--i ; i >= 0; i--) - { - gdFree(im->pixels[i]); - } - gdFree(im); - return NULL; - } + if (!im->pixels[i]) + { + for (--i ; i >= 0; i--) + { + gdFree(im->pixels[i]); + } + gdFree(im->pixels); + gdFree(im); + return NULL; + } + } im->sx = sx; im->sy = sy; @@ -128,9 +141,30 @@ BGD_DECLARE(gdImagePtr) gdImageCreateTrueColor (int sx, int sy) { int i; gdImagePtr im; + + if (overflow2(sx, sy)) { + return NULL; + } + + if (overflow2(sizeof (int *), sy)) { + return 0; + } + + if (overflow2(sizeof(int), sx)) { + return NULL; + } + im = (gdImage *) gdMalloc (sizeof (gdImage)); + if (!im) { + return 0; + } memset (im, 0, sizeof (gdImage)); + im->tpixels = (int **) gdMalloc (sizeof (int *) * sy); + if (!im->tpixels) { + gdFree(im); + return 0; + } im->polyInts = 0; im->polyAllocated = 0; im->brush = 0; @@ -139,6 +173,17 @@ BGD_DECLARE(gdImagePtr) gdImageCreateTrueColor (int sx, int sy) for (i = 0; (i < sy); i++) { im->tpixels[i] = (int *) gdCalloc (sx, sizeof (int)); + if (!im->tpixels[i]) { + /* 2.0.34 */ + i--; + while (i >= 0) { + gdFree(im->tpixels[i]); + i--; + } + gdFree(im->tpixels); + gdFree(im); + return 0; + } } im->sx = sx; im->sy = sy; @@ -311,7 +356,7 @@ HWB_Diff (int r1, int g1, int b1, int r2, int g2, int b2) } else { - diff = abs (HWB1.H - HWB2.H); + diff = fabs (HWB1.H - HWB2.H); if (diff > 3) { diff = 6 - diff; /* Remember, it's a colour circle */ @@ -892,7 +937,9 @@ gdImageTileApply (gdImagePtr im, int x, int y) if (im->trueColor) { p = gdImageGetTrueColorPixel (im->tile, srcx, srcy); - gdImageSetPixel (im, x, y, p); + if (p != gdImageGetTransparent (im->tile)) { + gdImageSetPixel (im, x, y, p); + } } else { @@ -949,7 +996,7 @@ BGD_DECLARE(int) gdImageGetTrueColorPixel (gdImagePtr im, int x, int y) { return gdTrueColorAlpha (im->red[p], im->green[p], im->blue[p], (im->transparent == p) ? gdAlphaTransparent : - gdAlphaOpaque); + im->alpha[p]); } else { @@ -964,6 +1011,44 @@ BGD_DECLARE(void) gdImageAABlend (gdImagePtr im) static void gdImageAALine (gdImagePtr im, int x1, int y1, int x2, int y2, int col); +static void gdImageHLine(gdImagePtr im, int y, int x1, int x2, int col) +{ + if (im->thick > 1) { + int thickhalf = im->thick >> 1; + gdImageFilledRectangle(im, x1, y - thickhalf, x2, y + im->thick - thickhalf - 1, col); + } else { + if (x2 < x1) { + int t = x2; + x2 = x1; + x1 = t; + } + + for (;x1 <= x2; x1++) { + gdImageSetPixel(im, x1, y, col); + } + } + return; +} + +static void gdImageVLine(gdImagePtr im, int x, int y1, int y2, int col) +{ + if (im->thick > 1) { + int thickhalf = im->thick >> 1; + gdImageFilledRectangle(im, x - thickhalf, y1, x + im->thick - thickhalf - 1, y2, col); + } else { + if (y2 < y1) { + int t = y1; + y1 = y2; + y2 = t; + } + + for (;y1 <= y2; y1++) { + gdImageSetPixel(im, x, y1, col); + } + } + return; +} + /* Bresenham as presented in Foley & Van Dam */ BGD_DECLARE(void) gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color) { @@ -971,6 +1056,7 @@ BGD_DECLARE(void) gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, in int wid; int w, wstart; int thick; + if (color == gdAntiAliased) { /* @@ -995,6 +1081,15 @@ BGD_DECLARE(void) gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, in dx = abs (x2 - x1); dy = abs (y2 - y1); + + if (dx == 0) { + gdImageVLine(im, x1, y1, y2, color); + return; + } else if (dy == 0) { + gdImageHLine(im, y1, x1, x2, color); + return; + } + if (dy <= dx) { /* More-or-less horizontal. use wid for vertical stroke */ @@ -1513,10 +1608,31 @@ BGD_DECLARE(void) gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int i; int lx = 0, ly = 0; int fx = 0, fy = 0; - while (e < s) - { - e += 360; - } + + if ((s % 360) == (e % 360)) { + s = 0; e = 360; + } else { + if (s > 360) { + s = s % 360; + } + + if (e > 360) { + e = e % 360; + } + + while (s < 0) { + s += 360; + } + + while (e < s) { + e += 360; + } + + if (s == e) { + s = 0; e = 360; + } + } + for (i = s; (i <= e); i++) { int x, y; @@ -1526,7 +1642,7 @@ BGD_DECLARE(void) gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, { if (!(style & gdChord)) { - if (style & gdNoFill) + if (style & gdNoFill) { gdImageLine (im, lx, ly, x, y, color); } @@ -1586,9 +1702,56 @@ BGD_DECLARE(void) gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, } } -BGD_DECLARE(void) gdImageFilledEllipse (gdImagePtr im, int cx, int cy, int w, int h, int color) +BGD_DECLARE(void) gdImageFilledEllipse (gdImagePtr im, int mx, int my, int w, int h, int c) { - gdImageFilledArc (im, cx, cy, w, h, 0, 360, color, gdPie); + int x=0,mx1=0,mx2=0,my1=0,my2=0; + long aq,bq,dx,dy,r,rx,ry,a,b; + int i; + int old_y1,old_y2; + + a=w>>1; + b=h>>1; + + gdImageLine(im, mx-a, my, mx+a, my, c); + + mx1 = mx-a;my1 = my; + mx2 = mx+a;my2 = my; + + aq = a * a; + bq = b * b; + dx = aq << 1; + dy = bq << 1; + r = a * bq; + rx = r << 1; + ry = 0; + x = a; + old_y2=-2; + old_y1=-2; + while (x > 0){ + if (r > 0) { + my1++;my2--; + ry +=dx; + r -=ry; + } + if (r <= 0){ + x--; + mx1++;mx2--; + rx -=dy; + r +=rx; + } + if(old_y2!=my2){ + for(i=mx1;i<=mx2;i++){ + gdImageSetPixel(im,i,my1,c); + } + } + if(old_y2!=my2){ + for(i=mx1;i<=mx2;i++){ + gdImageSetPixel(im,i,my2,c); + } + } + old_y2 = my2; + old_y1 = my1; + } } BGD_DECLARE(void) gdImageFillToBorder (gdImagePtr im, int x, int y, int border, int color) @@ -1597,12 +1760,19 @@ BGD_DECLARE(void) gdImageFillToBorder (gdImagePtr im, int x, int y, int border, /* Seek left */ int leftLimit, rightLimit; int i; - leftLimit = (-1); + int restoreAlphaBleding; + if (border < 0) { /* Refuse to fill to a non-solid border */ return; } + + leftLimit = (-1); + + restoreAlphaBleding = im->alphaBlendingFlag; + im->alphaBlendingFlag = 0; + for (i = x; (i >= 0); i--) { if (gdImageGetPixel (im, i, y) == border) @@ -1614,6 +1784,7 @@ BGD_DECLARE(void) gdImageFillToBorder (gdImagePtr im, int x, int y, int border, } if (leftLimit == (-1)) { + im->alphaBlendingFlag = restoreAlphaBleding; return; } /* Seek right */ @@ -1656,8 +1827,7 @@ BGD_DECLARE(void) gdImageFillToBorder (gdImagePtr im, int x, int y, int border, lastBorder = 1; for (i = leftLimit; (i <= rightLimit); i++) { - int c; - c = gdImageGetPixel (im, i, y + 1); + int c = gdImageGetPixel (im, i, y + 1); if (lastBorder) { if ((c != border) && (c != color)) @@ -1672,165 +1842,329 @@ BGD_DECLARE(void) gdImageFillToBorder (gdImagePtr im, int x, int y, int border, } } } + im->alphaBlendingFlag = restoreAlphaBleding; +} + +/* + * set the pixel at (x,y) and its 4-connected neighbors + * with the same pixel value to the new pixel value nc (new color). + * A 4-connected neighbor: pixel above, below, left, or right of a pixel. + * ideas from comp.graphics discussions. + * For tiled fill, the use of a flag buffer is mandatory. As the tile image can + * contain the same color as the color to fill. To do not bloat normal filling + * code I added a 2nd private function. + */ + +static int gdImageTileGet (gdImagePtr im, int x, int y) +{ + int srcx, srcy; + int tileColor,p; + if (!im->tile) { + return -1; + } + srcx = x % gdImageSX(im->tile); + srcy = y % gdImageSY(im->tile); + p = gdImageGetPixel(im->tile, srcx, srcy); + if (p == im->tile->transparent) { + tileColor = im->transparent; + } else if (im->trueColor) { + if (im->tile->trueColor) { + tileColor = p; + } else { + tileColor = gdTrueColorAlpha( gdImageRed(im->tile,p), gdImageGreen(im->tile,p), gdImageBlue (im->tile,p), gdImageAlpha (im->tile,p)); + } + } else { + if (im->tile->trueColor) { + tileColor = gdImageColorResolveAlpha(im, gdTrueColorGetRed (p), gdTrueColorGetGreen (p), gdTrueColorGetBlue (p), gdTrueColorGetAlpha (p)); + } else { + tileColor = p; + tileColor = gdImageColorResolveAlpha(im, gdImageRed (im->tile,p), gdImageGreen (im->tile,p), gdImageBlue (im->tile,p), gdImageAlpha (im->tile,p)); + } + } + return tileColor; } -BGD_DECLARE(void) gdImageFill (gdImagePtr im, int x, int y, int color) + + +/* horizontal segment of scan line y */ +struct seg {int y, xl, xr, dy;}; + +/* max depth of stack */ +#define FILL_MAX 1200000 +#define FILL_PUSH(Y, XL, XR, DY) \ + if (sp=0 && Y+(DY)y = Y; sp->xl = XL; sp->xr = XR; sp->dy = DY; sp++;} + +#define FILL_POP(Y, XL, XR, DY) \ + {sp--; Y = sp->y+(DY = sp->dy); XL = sp->xl; XR = sp->xr;} + +void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc); +BGD_DECLARE(void) gdImageFill(gdImagePtr im, int x, int y, int nc) { - int lastBorder; - int old; - int leftLimit, rightLimit; - int i; - old = gdImageGetPixel (im, x, y); - if (color == gdTiled) - { - /* Tile fill -- got to watch out! */ - int p, tileColor; - int srcx, srcy; - if (!im->tile) - { - return; + int l, x1, x2, dy; + int oc; /* old pixel value */ + int wx2,wy2; + + int alphablending_bak; + + /* stack of filled segments */ + /* struct seg stack[FILL_MAX],*sp = stack;; */ + struct seg *stack; + struct seg *sp; + + if (!im->trueColor && nc > (im->colorsTotal - 1)) { + return; } - /* Refuse to flood-fill with a transparent pattern -- - I can't do it without allocating another image */ - if (gdImageGetTransparent (im->tile) != (-1)) - { - return; + + alphablending_bak = im->alphaBlendingFlag; + im->alphaBlendingFlag = 0; + + if (nc==gdTiled) { + _gdImageFillTiled(im,x,y,nc); + im->alphaBlendingFlag = alphablending_bak; + return; } - srcx = x % gdImageSX (im->tile); - srcy = y % gdImageSY (im->tile); - p = gdImageGetPixel (im->tile, srcx, srcy); - if (im->trueColor) - { - tileColor = p; + + wx2=im->sx;wy2=im->sy; + oc = gdImageGetPixel(im, x, y); + if (oc==nc || x<0 || x>wx2 || y<0 || y>wy2) { + im->alphaBlendingFlag = alphablending_bak; + return; } - else - { - if (im->tile->trueColor) - { - tileColor = gdImageColorResolveAlpha (im, - gdTrueColorGetRed (p), - gdTrueColorGetGreen (p), - gdTrueColorGetBlue (p), - gdTrueColorGetAlpha (p)); - } - else - { - tileColor = im->tileColorMap[p]; - } + + /* Do not use the 4 neighbors implementation with + * small images + */ + if (im->sx < 4) { + int ix = x, iy = y, c; + do { + c = gdImageGetPixel(im, ix, iy); + if (c != oc) { + goto done; + } + gdImageSetPixel(im, ix, iy, nc); + } while(ix++ < (im->sx -1)); + ix = x; iy = y + 1; + do { + c = gdImageGetPixel(im, ix, iy); + if (c != oc) { + goto done; + } + gdImageSetPixel(im, ix, iy, nc); + } while(ix++ < (im->sx -1)); + goto done; } - if (old == tileColor) - { - /* Nothing to be done */ - return; + + stack = (struct seg *)gdMalloc(sizeof(struct seg) * ((int)(im->sy*im->sx)/4)); + if (!stack) { + return; } - } - else - { - if (old == color) - { - /* Nothing to be done */ - return; + sp = stack; + + /* required! */ + FILL_PUSH(y,x,x,1); + /* seed segment (popped 1st) */ + FILL_PUSH(y+1, x, x, -1); + while (sp>stack) { + FILL_POP(y, x1, x2, dy); + + for (x=x1; x>=0 && gdImageGetPixel(im,x, y)==oc; x--) { + gdImageSetPixel(im,x, y, nc); + } + if (x>=x1) { + goto skip; + } + l = x+1; + + /* leak on left? */ + if (lx2+1) { + FILL_PUSH(y, x2+1, x-1, -dy); + } +skip: for (x++; x<=x2 && (gdImageGetPixel(im, x, y)!=oc); x++); + + l = x; + } while (x<=x2); } - } - /* Seek left */ - leftLimit = (-1); - for (i = x; (i >= 0); i--) - { - if (gdImageGetPixel (im, i, y) != old) - { - break; + + gdFree(stack); + +done: + im->alphaBlendingFlag = alphablending_bak; +} + +void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc) +{ + int i,l, x1, x2, dy; + int oc; /* old pixel value */ + int tiled; + int wx2,wy2; + /* stack of filled segments */ + struct seg *stack; + struct seg *sp; + + int **pts; + if(!im->tile){ + return; } - gdImageSetPixel (im, i, y, color); - leftLimit = i; - } - if (leftLimit == (-1)) - { - return; - } - /* Seek right */ - rightLimit = x; - for (i = (x + 1); (i < im->sx); i++) - { - if (gdImageGetPixel (im, i, y) != old) - { - break; + + wx2=im->sx;wy2=im->sy; + tiled = nc==gdTiled; + + nc = gdImageTileGet(im,x,y); + pts = (int **) gdCalloc(sizeof(int *) * im->sy, sizeof(int)); + if (!pts) { + return; } - gdImageSetPixel (im, i, y, color); - rightLimit = i; - } - /* Look at lines above and below and start paints */ - /* Above */ - if (y > 0) - { - lastBorder = 1; - for (i = leftLimit; (i <= rightLimit); i++) - { - int c; - c = gdImageGetPixel (im, i, y - 1); - if (lastBorder) - { - if (c == old) - { - gdImageFill (im, i, y - 1, color); - lastBorder = 0; + + for (i=0; isy;i++) { + pts[i] = (int *) gdCalloc(im->sx, sizeof(int)); + + if (!pts[i]) { + for (--i ; i >= 0; i--) { + gdFree(pts[i]); + } + return; } - } - else if (c != old) - { - lastBorder = 1; - } } - } - /* Below */ - if (y < ((im->sy) - 1)) - { - lastBorder = 1; - for (i = leftLimit; (i <= rightLimit); i++) - { - int c; - c = gdImageGetPixel (im, i, y + 1); - if (lastBorder) - { - if (c == old) - { - gdImageFill (im, i, y + 1, color); - lastBorder = 0; + + stack = (struct seg *)gdMalloc(sizeof(struct seg) * ((int)(im->sy*im->sx)/4)); + if (!stack) { + return; + } + sp = stack; + + oc = gdImageGetPixel(im, x, y); + + /* required! */ + FILL_PUSH(y,x,x,1); + /* seed segment (popped 1st) */ + FILL_PUSH(y+1, x, x, -1); + while (sp>stack) { + FILL_POP(y, x1, x2, dy); + for (x=x1; x>=0 && (!pts[y][x] && gdImageGetPixel(im,x,y)==oc); x--) { + if (pts[y][x]){ + /* we should never be here */ + break; + } + nc = gdImageTileGet(im,x,y); + pts[y][x]=1; + gdImageSetPixel(im,x, y, nc); } - } - else if (c != old) - { - lastBorder = 1; - } + if (x>=x1) { + goto skip; + } + l = x+1; + + /* leak on left? */ + if (lx2+1) { + FILL_PUSH(y, x2+1, x-1, -dy); + } +skip: for (x++; x<=x2 && (pts[y][x] || gdImageGetPixel(im,x, y)!=oc); x++); + l = x; + } while (x<=x2); } - } + for (i=0; isy;i++) { + gdFree(pts[i]); + } + gdFree(pts); + gdFree(stack); } BGD_DECLARE(void) gdImageRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color) { - int x1h = x1, x1v = x1, y1h = y1, y1v = y1, x2h = x2, x2v = x2, y2h = y2, - y2v = y2; - int thick = im->thick; - if (thick > 1) - { - int half = thick / 2; - int half1 = thick - half; + int x1h = x1, x1v = x1, y1h = y1, y1v = y1, x2h = x2, x2v = x2, y2h = y2, y2v = y2; + int thick = im->thick; + int half1 = 1; + int t; + + if (y2 < y1) { + t=y1; + y1 = y2; + y2 = t; + + t = x1; + x1 = x2; + x2 = t; + } + + x1h = x1; x1v = x1; y1h = y1; y1v = y1; x2h = x2; x2v = x2; y2h = y2; y2v = y2; + if (thick > 1) { + int cx, cy, x1ul, y1ul, x2lr, y2lr; + int half = thick >> 1; + half1 = thick - half; + x1ul = x1 - half; + y1ul = y1 - half; + + x2lr = x2 + half; + y2lr = y2 + half; + + cy = y1ul + thick; + while (cy-- > y1ul) { + cx = x1ul - 1; + while (cx++ < x2lr) { + gdImageSetPixel(im, cx, cy, color); + } + } - if (y1 < y2) - { - y1v = y1h - half; - y2v = y2h + half1 - 1; - } - else - { - y1v = y1h + half1 - 1; - y2v = y2h - half; - } - } + cy = y2lr - thick; + while (cy++ < y2lr) { + cx = x1ul - 1; + while (cx++ < x2lr) { + gdImageSetPixel(im, cx, cy, color); + } + } - gdImageLine (im, x1h, y1h, x2h, y1h, color); - gdImageLine (im, x1h, y2h, x2h, y2h, color); - gdImageLine (im, x1v, y1v, x1v, y2v, color); - gdImageLine (im, x2v, y1v, x2v, y2v, color); + cy = y1ul + thick - 1; + while (cy++ < y2lr -thick) { + cx = x1ul - 1; + while (cx++ < x1ul + thick) { + gdImageSetPixel(im, cx, cy, color); + } + } + + cy = y1ul + thick - 1; + while (cy++ < y2lr -thick) { + cx = x2lr - thick - 1; + while (cx++ < x2lr) { + gdImageSetPixel(im, cx, cy, color); + } + } + + return; + } else { + y1v = y1h + 1; + y2v = y2h - 1; + gdImageLine(im, x1h, y1h, x2h, y1h, color); + gdImageLine(im, x1h, y2h, x2h, y2h, color); + gdImageLine(im, x1v, y1v, x1v, y2v, color); + gdImageLine(im, x2v, y1v, x2v, y2v, color); + } } BGD_DECLARE(void) gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, @@ -1841,13 +2175,24 @@ BGD_DECLARE(void) gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, nicely kills any plotting for rectangles completely outside the window as it makes the tests in the for loops fail */ if (x1 < 0) - x1 = 0; + x1 = 0; if (x1 > gdImageSX (im)) - x1 = gdImageSX (im); + x1 = gdImageSX (im); if (y1 < 0) - y1 = 0; + y1 = 0; if (y1 > gdImageSY (im)) - y1 = gdImageSY (im); + y1 = gdImageSY (im); + + if (x1 > x2) { + x = x1; + x1 = x2; + x2 = x; + } + if (y1 > y2) { + y = y1; + y1 = y2; + y2 = y; + } for (y = y1; (y <= y2); y++) { @@ -1866,52 +2211,60 @@ BGD_DECLARE(void) gdImageCopy (gdImagePtr dst, gdImagePtr src, int dstX, int dst int tox, toy; int i; int colorMap[gdMaxColors]; - if (dst->trueColor) - { - /* 2.0: much easier when the destination is truecolor. */ - /* 2.0.10: needs a transparent-index check that is still valid if - the source is not truecolor. Thanks to Frank Warmerdam. */ - for (y = 0; (y < h); y++) - { - for (x = 0; (x < w); x++) - { - int p = gdImageGetPixel (src, srcX + x, srcY + y); - if (p != src->transparent) - { - int c = gdImageGetTrueColorPixel (src, srcX + x, - srcY + y); - gdImageSetPixel (dst, dstX + x, dstY + y, c); - } - } - } - return; - } + + if (dst->trueColor) { + /* 2.0: much easier when the destination is truecolor. */ + /* 2.0.10: needs a transparent-index check that is still valid if + * * the source is not truecolor. Thanks to Frank Warmerdam. + */ + + if (src->trueColor) { + for (y = 0; (y < h); y++) { + for (x = 0; (x < w); x++) { + int c = gdImageGetTrueColorPixel (src, srcX + x, srcY + y); + gdImageSetPixel (dst, dstX + x, dstY + y, c); + } + } + } else { + /* source is palette based */ + for (y = 0; (y < h); y++) { + for (x = 0; (x < w); x++) { + int c = gdImageGetPixel (src, srcX + x, srcY + y); + if (c != src->transparent) { + gdImageSetPixel(dst, dstX + x, dstY + y, gdTrueColorAlpha(src->red[c], src->green[c], src->blue[c], src->alpha[c])); + } + } + } + } + return; + } + for (i = 0; (i < gdMaxColors); i++) - { - colorMap[i] = (-1); - } + { + colorMap[i] = (-1); + } toy = dstY; for (y = srcY; (y < (srcY + h)); y++) - { - tox = dstX; - for (x = srcX; (x < (srcX + w)); x++) - { - int nc; - int mapTo; - c = gdImageGetPixel (src, x, y); - /* Added 7/24/95: support transparent copies */ - if (gdImageGetTransparent (src) == c) - { - tox++; - continue; - } - /* Have we established a mapping for this color? */ - if (src->trueColor) - { - /* 2.05: remap to the palette available in the - destination image. This is slow and - works badly, but it beats crashing! Thanks - to Padhrig McCarthy. */ + { + tox = dstX; + for (x = srcX; (x < (srcX + w)); x++) + { + int nc; + int mapTo; + c = gdImageGetPixel (src, x, y); + /* Added 7/24/95: support transparent copies */ + if (gdImageGetTransparent (src) == c) + { + tox++; + continue; + } + /* Have we established a mapping for this color? */ + if (src->trueColor) + { + /* 2.05: remap to the palette available in the + destination image. This is slow and + works badly, but it beats crashing! Thanks + to Padhrig McCarthy. */ mapTo = gdImageColorResolveAlpha (dst, gdTrueColorGetRed (c), gdTrueColorGetGreen (c), @@ -2034,8 +2387,8 @@ BGD_DECLARE(void) gdImageCopyMergeGray (gdImagePtr dst, gdImagePtr src, int dstX else { dc = gdImageGetPixel (dst, tox, toy); - g = 0.29900 * dst->red[dc] - + 0.58700 * dst->green[dc] + 0.11400 * dst->blue[dc]; + g = 0.29900 * gdImageRed(dst, dc) + + 0.58700 * gdImageGreen(dst, dc) + 0.11400 * gdImageBlue(dst, dc); ncR = gdImageRed (src, c) * (pct / 100.0) + g * ((100 - pct) / 100.0); @@ -2087,7 +2440,15 @@ BGD_DECLARE(void) gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, return; } stx = (int *) gdMalloc (sizeof (int) * srcW); + if (!stx) { + return; + } + sty = (int *) gdMalloc (sizeof (int) * srcH); + if (!sty) { + return; + } + /* Fixed by Mao Morimoto 2.0.16 */ for (i = 0; (i < srcW); i++) { @@ -2230,6 +2591,17 @@ BGD_DECLARE(void) gdImageCopyRotated (gdImagePtr dst, double scY = srcY + ((double) srcHeight) / 2; int cmap[gdMaxColors]; int i; + + /* + 2.0.34: transparency preservation. The transparentness of + the transparent color is more important than its hue. + */ + if (src->transparent != -1) { + if (dst->transparent == -1) { + dst->transparent = src->transparent; + } + } + for (i = 0; (i < gdMaxColors); i++) { cmap[i] = (-1); @@ -2245,9 +2617,14 @@ BGD_DECLARE(void) gdImageCopyRotated (gdImagePtr dst, if ((sx >= srcX) && (sx < srcX + srcWidth) && (sy >= srcY) && (sy < srcY + srcHeight)) { - int c = gdImageGetPixel (src, sx, sy); - if (!src->trueColor) - { + int c = gdImageGetPixel (src, sx, sy); + /* 2.0.34: transparency wins */ + if (c == src->transparent) + { + gdImageSetPixel (dst, dx, dy, dst->transparent); + } + else if (!src->trueColor) + { /* Use a table to avoid an expensive lookup on every single pixel */ if (cmap[c] == -1) @@ -2478,6 +2855,10 @@ BGD_DECLARE(gdImagePtr) gdImageCreateFromXbm (FILE * fd) } bytes = (w * h / 8) + 1; im = gdImageCreate (w, h); + if (!im) { + return 0; + } + gdImageColorAllocate (im, 255, 255, 255); gdImageColorAllocate (im, 0, 0, 0); x = 0; @@ -2608,6 +2989,9 @@ BGD_DECLARE(void) gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int return; } im->polyInts = (int *) gdMalloc (sizeof (int) * n); + if (!im->polyInts) { + return; + } im->polyAllocated = n; } if (im->polyAllocated < n) @@ -2616,8 +3000,14 @@ BGD_DECLARE(void) gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int { im->polyAllocated *= 2; } + if (overflow2(sizeof (int), im->polyAllocated)) { + return; + } im->polyInts = (int *) gdRealloc (im->polyInts, sizeof (int) * im->polyAllocated); + if (!im->polyInts) { + return; + } } miny = p[0].y; maxy = p[0].y; @@ -2772,6 +3162,9 @@ BGD_DECLARE(void) gdImageSetStyle (gdImagePtr im, int *style, int noOfPixels) return; } im->style = (int *) gdMalloc (sizeof (int) * noOfPixels); + if (!im->style) { + return; + } memcpy (im->style, style, sizeof (int) * noOfPixels); im->styleLength = noOfPixels; im->stylePos = 0; @@ -3048,6 +3441,11 @@ nc = (cc) + (((((c) - (cc)) * (a)) + ((((c) - (cc)) * (a)) >> 8) + 0x80) >> 8); static void gdImageSetAAPixelColor(gdImagePtr im, int x, int y, int color, int t) { int dr,dg,db,p,r,g,b; + + /* 2.0.34: watch out for out of range calls */ + if (!gdImageBoundsSafeMacro(im, x, y)) { + return; + } p = gdImageGetPixel(im,x,y); /* TBB: we have to implement the dont_blend stuff to provide the full feature set of the old implementation */ @@ -3068,7 +3466,7 @@ static void gdImageSetAAPixelColor(gdImagePtr im, int x, int y, int color, int t BLEND_COLOR(t, dr, r, dr); BLEND_COLOR(t, dg, g, dg); BLEND_COLOR(t, db, b, db); - im->tpixels[y][x]=gdTrueColorAlpha(dr, dg, db, gdAlphaOpaque); + im->tpixels[y][x] = gdTrueColorAlpha(dr, dg, db, gdAlphaOpaque); } static void gdImageAALine (gdImagePtr im, int x1, int y1, int x2, int y2, int col) @@ -3076,6 +3474,7 @@ static void gdImageAALine (gdImagePtr im, int x1, int y1, int x2, int y2, int co /* keep them as 32bits */ long x, y, inc; long dx, dy,tmp; + if (!im->trueColor) { /* TBB: don't crash when the image is of the wrong type */ gdImageLine(im, x1, y1, x2, y2, col); @@ -3089,6 +3488,15 @@ static void gdImageAALine (gdImagePtr im, int x1, int y1, int x2, int y2, int co dx = x2 - x1; dy = y2 - y1; + /* Axis aligned lines */ + if (dx == 0) { + gdImageVLine(im, x1, y1, y2, col); + return; + } else if (dy == 0) { + gdImageHLine(im, y1, x1, x2, col); + return; + } + if (dx == 0 && dy == 0) { /* TBB: allow setting points */ gdImageSetAAPixelColor(im, x1, y1, col, 0xFF); diff --git a/lib/gd/gd.h b/lib/gd/gd.h index 03f3a018f..f136ea658 100644 --- a/lib/gd/gd.h +++ b/lib/gd/gd.h @@ -5,6 +5,13 @@ extern "C" { #ifndef GD_H #define GD_H 1 +#define GD_MAJOR_VERSION 2 +#define GD_MINOR_VERSION 0 +#define GD_RELEASE_VERSION 35 +#define GD_EXTRA_VERSION "" +#define GD_VERSION_STRING "2.0.35" + + /* Do the DLL dance: dllexport when building the DLL, dllimport when importing from it, nothing when not on Silly Silly Windows (tm Aardman Productions). */ @@ -55,6 +62,11 @@ extern "C" #endif /* some might want to set DEFAULT_FONTPATH from configure in config.h */ +#ifdef NETWARE +/* default fontpath for netware systems, could probably be handled in configure for 2.1 */ +#define DEFAULT_FONTPATH "sys:/java/nwgfx/lib/x11/fonts/ttf;." +#define PATHSEPARATOR ";" +#endif /* 2.0.23: more Type 1 fonts */ #ifndef DEFAULT_FONTPATH @@ -390,7 +402,8 @@ BGD_DECLARE(char *) gdImageStringFT (gdImage * im, int *brect, int fg, char *fon int flags; /* Logical OR of gdFTEX_ values */ double linespacing; /* fine tune line spacing for '\n' */ int charmap; /* TBB: 2.0.12: may be gdFTEX_Unicode, - gdFTEX_Shift_JIS, or gdFTEX_Big5; + gdFTEX_Shift_JIS, gdFTEX_Big5, + or gdFTEX_Adobe_Custom; when not specified, maps are searched for in the above order. */ int hdpi; /* if (flags & gdFTEX_RESOLUTION) */ @@ -446,6 +459,7 @@ BGD_DECLARE(int) gdFTUseFontConfig(int flag); #define gdFTEX_Unicode 0 #define gdFTEX_Shift_JIS 1 #define gdFTEX_Big5 2 +#define gdFTEX_Adobe_Custom 3 BGD_DECLARE(char *) gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist, double ptsize, double angle, int x, int y, @@ -645,6 +659,7 @@ BGD_DECLARE(void) gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int e, int color, int style); BGD_DECLARE(void) gdImageArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color); +BGD_DECLARE(void) gdImageEllipse(gdImagePtr im, int cx, int cy, int w, int h, int color); BGD_DECLARE(void) gdImageFilledEllipse (gdImagePtr im, int cx, int cy, int w, int h, int color); BGD_DECLARE(void) gdImageFillToBorder (gdImagePtr im, int x, int y, int border, diff --git a/lib/gd/gd_gd2.c b/lib/gd/gd_gd2.c index 4374e4027..06bac4375 100644 --- a/lib/gd/gd_gd2.c +++ b/lib/gd/gd_gd2.c @@ -171,6 +171,9 @@ _gd2GetHeader (gdIOCtxPtr in, int *sx, int *sy, GD2_DBG (printf ("Reading %d chunk index entries\n", nc)); sidx = sizeof (t_chunk_info) * nc; cidx = gdCalloc (sidx, 1); + if (!cidx) { + goto fail1; + } for (i = 0; i < nc; i++) { if (gdGetInt (&cidx[i].offset, in) != 1) @@ -322,7 +325,8 @@ BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2Ctx (gdIOCtxPtr in) if (im == NULL) { return 0; - }; + } + bytesPerPixel = im->trueColor ? 4 : 1; nc = ncx * ncy; @@ -342,7 +346,14 @@ BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2Ctx (gdIOCtxPtr in) /* Allocate buffers */ chunkMax = cs * bytesPerPixel * cs; chunkBuf = gdCalloc (chunkMax, 1); + if (!chunkBuf) { + goto fail2; + } compBuf = gdCalloc (compMax, 1); + if (!compBuf) { + goto fail2; + } + GD2_DBG (printf ("Largest compressed chunk is %d bytes\n", compMax)); }; @@ -462,11 +473,17 @@ BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2Ctx (gdIOCtxPtr in) fail2: gdImageDestroy (im); - gdFree (chunkBuf); - gdFree (compBuf); - gdFree (chunkIdx); +fail1: + if (chunkBuf) { + gdFree (chunkBuf); + } + if (compBuf) { + gdFree (compBuf); + } + if (chunkIdx) { + gdFree (chunkIdx); + } return 0; - } BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2Part (FILE * inFile, int srcx, int srcy, int w, int h) @@ -571,7 +588,14 @@ BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int chunkMax = cs * cs; } chunkBuf = gdCalloc (chunkMax, 1); + if (!chunkBuf) { + goto fail2; + } compBuf = gdCalloc (compMax, 1); + if (!compBuf) { + goto fail2; + } + }; /* Don't bother with this... */ @@ -748,10 +772,15 @@ BGD_DECLARE(gdImagePtr) gdImageCreateFromGd2PartCtx (gdIOCtx * in, int srcx, int fail2: gdImageDestroy (im); fail1: - gdFree (chunkBuf); - gdFree (compBuf); - gdFree (chunkIdx); - + if (chunkBuf) { + gdFree (chunkBuf); + } + if (compBuf) { + gdFree (compBuf); + } + if (chunkIdx) { + gdFree (chunkIdx); + } return 0; } @@ -851,7 +880,13 @@ _gdImageGd2 (gdImagePtr im, gdIOCtx * out, int cs, int fmt) /* Allocate the buffers. */ /* */ chunkData = gdCalloc (cs * bytesPerPixel * cs, 1); + if (!chunkData) { + goto fail; + } compData = gdCalloc (compMax, 1); + if (!compData) { + goto fail; + } /* */ /* Save the file position of chunk index, and allocate enough space for */ @@ -863,6 +898,9 @@ _gdImageGd2 (gdImagePtr im, gdIOCtx * out, int cs, int fmt) gdSeek (out, idxPos + idxSize); chunkIdx = gdCalloc (idxSize * sizeof (t_chunk_info), 1); + if (!chunkIdx) { + goto fail; + } }; _gdPutColors (im, out); @@ -984,13 +1022,20 @@ _gdImageGd2 (gdImagePtr im, gdIOCtx * out, int cs, int fmt) gdSeek (out, posSave); }; + /*printf("Memory block size is %d\n",gdTell(out)); */ +fail: GD2_DBG (printf ("Freeing memory\n")); - gdFree (chunkData); - gdFree (compData); - gdFree (chunkIdx); - GD2_DBG (printf ("Done\n")); - /*printf("Memory block size is %d\n",gdTell(out)); */ + if (chunkData) { + gdFree (chunkData); + } + if (compData) { + gdFree (compData); + } + if (chunkIdx) { + gdFree (chunkIdx); + } + GD2_DBG (printf ("Done\n")); } diff --git a/lib/gd/gd_gif_in.c b/lib/gd/gd_gif_in.c index e1f1bdbf6..3a1e81423 100644 --- a/lib/gd/gd_gif_in.c +++ b/lib/gd/gd_gif_in.c @@ -1,7 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include #include #include @@ -46,7 +42,7 @@ static int set_verbose(void) #define LOCALCOLORMAP 0x80 #define BitSet(byte, bit) (((byte) & (bit)) == (bit)) -#define ReadOK(file,buffer,len) (gdGetBuf(buffer, len, file) != 0) +#define ReadOK(file,buffer,len) (gdGetBuf(buffer, len, file) > 0) #define LM_to_uint(a,b) (((b)<<8)|(a)) @@ -72,11 +68,29 @@ static struct { } Gif89 = { -1, -1, -1, 0 }; #endif +#define STACK_SIZE ((1<<(MAX_LWZ_BITS))*2) + +typedef struct { + unsigned char buf[280]; + int curbit, lastbit, done, last_byte; +} CODE_STATIC_DATA; + +typedef struct { + int fresh; + int code_size, set_code_size; + int max_code, max_code_size; + int firstcode, oldcode; + int clear_code, end_code; + int table[2][(1<< MAX_LWZ_BITS)]; + int stack[STACK_SIZE], *sp; + CODE_STATIC_DATA scd; +} LZW_STATIC_DATA; + static int ReadColorMap (gdIOCtx *fd, int number, unsigned char (*buffer)[256]); static int DoExtension (gdIOCtx *fd, int label, int *Transparent, int *ZeroDataBlockP); static int GetDataBlock (gdIOCtx *fd, unsigned char *buf, int *ZeroDataBlockP); -static int GetCode (gdIOCtx *fd, int code_size, int flag, int *ZeroDataBlockP); -static int LWZReadByte (gdIOCtx *fd, int flag, int input_code_size, int *ZeroDataBlockP); +static int GetCode (gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP); +static int LWZReadByte (gdIOCtx *fd, LZW_STATIC_DATA *sd, char flag, int input_code_size, int *ZeroDataBlockP); static void ReadImage (gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int *ZeroDataBlockP); /*1.4//, int ignore); */ @@ -114,15 +128,14 @@ BGD_DECLARE(gdImagePtr) gdImageCreateFromGifCtx(gdIOCtxPtr fd) unsigned char c; unsigned char ColorMap[3][MAXCOLORMAPSIZE]; unsigned char localColorMap[3][MAXCOLORMAPSIZE]; - int imw, imh; - int useGlobalColormap; + int imw, imh, screen_width, screen_height; + int gif87a, useGlobalColormap; int bitPixel; int i; /*1.4//int imageCount = 0; */ - char version[4]; /* 2.0.28: threadsafe storage */ int ZeroDataBlock = FALSE; - int maxcount = 1024; + int haveGlobalColormap; gdImagePtr im = 0; if (! ReadOK(fd,buf,6)) { @@ -131,34 +144,43 @@ BGD_DECLARE(gdImagePtr) gdImageCreateFromGifCtx(gdIOCtxPtr fd) if (strncmp((char *)buf,"GIF",3) != 0) { return 0; } - strncpy(version, (char *)buf + 3, 3); - version[3] = '\0'; + if (memcmp((char *)buf+3, "87a", 3) == 0) { + gif87a = 1; + } else if (memcmp((char *)buf+3, "89a", 3) == 0) { + gif87a = 0; + } else { + return 0; + } + + if (! ReadOK(fd,buf,7)) { + return 0; + } - if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) { - return 0; - } - if (! ReadOK(fd,buf,7)) { - return 0; - } BitPixel = 2<<(buf[4]&0x07); #if 0 ColorResolution = (int) (((buf[4]&0x70)>>3)+1); Background = buf[5]; AspectRatio = buf[6]; #endif - - if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */ - if (ReadColorMap(fd, BitPixel, ColorMap)) { - return 0; - } - } + screen_width = imw = LM_to_uint(buf[0],buf[1]); + screen_height = imh = LM_to_uint(buf[2],buf[3]); + + haveGlobalColormap = BitSet(buf[4], LOCALCOLORMAP); /* Global Colormap */ + if (haveGlobalColormap) { + if (ReadColorMap(fd, BitPixel, ColorMap)) { + return 0; + } + } for (;;) { + int top, left; + int width, height; + if (! ReadOK(fd,&c,1)) { return 0; } if (c == ';') { /* GIF terminator */ - goto terminated; - } + goto terminated; + } if (c == '!') { /* Extension */ if (! ReadOK(fd,&c,1)) { @@ -169,8 +191,6 @@ BGD_DECLARE(gdImagePtr) gdImageCreateFromGifCtx(gdIOCtxPtr fd) } if (c != ',') { /* Not a valid start character */ - if (--maxcount < 0) - goto terminated; /* Looping */ continue; } @@ -182,22 +202,36 @@ BGD_DECLARE(gdImagePtr) gdImageCreateFromGifCtx(gdIOCtxPtr fd) useGlobalColormap = ! BitSet(buf[8], LOCALCOLORMAP); - bitPixel = 1<<((buf[8]&0x07)+1); - - imw = LM_to_uint(buf[4],buf[5]); - imh = LM_to_uint(buf[6],buf[7]); - if (!(im = gdImageCreate(imw, imh))) { - return 0; - } - im->interlace = BitSet(buf[8], INTERLACE); - if (! useGlobalColormap) { + bitPixel = 1<<((buf[8]&0x07)+1); + left = LM_to_uint(buf[0], buf[1]); + top = LM_to_uint(buf[2], buf[3]); + width = LM_to_uint(buf[4], buf[5]); + height = LM_to_uint(buf[6], buf[7]); + + if (left + width > screen_width || top + height > screen_height) { + if (VERBOSE) { + printf("Frame is not confined to screen dimension.\n"); + } + return 0; + } + + if (!(im = gdImageCreate(width, height))) { + return 0; + } + im->interlace = BitSet(buf[8], INTERLACE); + if (!useGlobalColormap) { if (ReadColorMap(fd, bitPixel, localColorMap)) { - return 0; + gdImageDestroy(im); + return 0; } - ReadImage(im, fd, imw, imh, localColorMap, + ReadImage(im, fd, width, height, localColorMap, BitSet(buf[8], INTERLACE), &ZeroDataBlock); } else { - ReadImage(im, fd, imw, imh, + if (!haveGlobalColormap) { + gdImageDestroy(im); + return 0; + } + ReadImage(im, fd, width, height, ColorMap, BitSet(buf[8], INTERLACE), &ZeroDataBlock); } @@ -212,6 +246,10 @@ terminated: if (!im) { return 0; } + if (!im->colorsTotal) { + gdImageDestroy(im); + return 0; + } /* Check for open colors at the end, so we can reduce colorsTotal and ultimately BitsPerPixel */ @@ -248,11 +286,11 @@ ReadColorMap(gdIOCtx *fd, int number, unsigned char (*buffer)[256]) static int DoExtension(gdIOCtx *fd, int label, int *Transparent, int *ZeroDataBlockP) { - static unsigned char buf[256]; - int maxcount = 1024; + unsigned char buf[256]; switch (label) { case 0xf9: /* Graphic Control Extension */ + memset(buf, 0, 4); /* initialize a few bytes in the case the next function fails */ (void) GetDataBlock(fd, (unsigned char*) buf, ZeroDataBlockP); #if 0 Gif89.disposal = (buf[0] >> 2) & 0x7; @@ -262,13 +300,12 @@ DoExtension(gdIOCtx *fd, int label, int *Transparent, int *ZeroDataBlockP) if ((buf[0] & 0x1) != 0) *Transparent = buf[3]; - while (GetDataBlock(fd, (unsigned char*) buf, ZeroDataBlockP) != 0 && --maxcount >= 0) - ; + while (GetDataBlock(fd, (unsigned char*) buf, ZeroDataBlockP) > 0); return FALSE; default: break; } - while (GetDataBlock(fd, (unsigned char*) buf, ZeroDataBlockP) != 0 && --maxcount >= 0) + while (GetDataBlock(fd, (unsigned char*) buf, ZeroDataBlockP) > 0) ; return FALSE; @@ -311,185 +348,174 @@ GetDataBlock(gdIOCtx *fd, unsigned char *buf, int *ZeroDataBlockP) } static int -GetCode_(gdIOCtx *fd, int code_size, int flag, int *ZeroDataBlockP) +GetCode_(gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP) { - static unsigned char buf[280]; - static int curbit, lastbit, done, last_byte; - int i, j, ret; - unsigned char count; + int i, j, ret; + unsigned char count; if (flag) { - curbit = 0; - lastbit = 0; - done = FALSE; + scd->curbit = 0; + scd->lastbit = 0; + scd->last_byte = 0; + scd->done = FALSE; return 0; } - if ( (curbit+code_size) >= lastbit) { - if (done) { - if (curbit >= lastbit) { + if ( (scd->curbit + code_size) >= scd->lastbit) { + if (scd->done) { + if (scd->curbit >= scd->lastbit) { /* Oh well */ } return -1; } - buf[0] = buf[last_byte-2]; - buf[1] = buf[last_byte-1]; + scd->buf[0] = scd->buf[scd->last_byte-2]; + scd->buf[1] = scd->buf[scd->last_byte-1]; - if ((count = GetDataBlock(fd, &buf[2], ZeroDataBlockP)) == 0) - done = TRUE; + if ((count = GetDataBlock(fd, &scd->buf[2], ZeroDataBlockP)) <= 0) + scd->done = TRUE; - last_byte = 2 + count; - curbit = (curbit - lastbit) + 16; - lastbit = (2+count)*8 ; + scd->last_byte = 2 + count; + scd->curbit = (scd->curbit - scd->lastbit) + 16; + scd->lastbit = (2+count)*8 ; } ret = 0; - for (i = curbit, j = 0; j < code_size; ++i, ++j) - ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j; + for (i = scd->curbit, j = 0; j < code_size; ++i, ++j) + ret |= ((scd->buf[ i / 8 ] & (1 << (i % 8))) != 0) << j; - curbit += code_size; + scd->curbit += code_size; return ret; } static int -GetCode(gdIOCtx *fd, int code_size, int flag, int *ZeroDataBlockP) +GetCode(gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP) { int rv; - rv = GetCode_(fd,code_size,flag, ZeroDataBlockP); + rv = GetCode_(fd, scd, code_size,flag, ZeroDataBlockP); if (VERBOSE) printf("[GetCode(,%d,%d) returning %d]\n",code_size,flag,rv); return(rv); } -#define STACK_SIZE ((1<<(MAX_LWZ_BITS))*2) static int -LWZReadByte_(gdIOCtx *fd, int flag, int input_code_size, int *ZeroDataBlockP) +LWZReadByte_(gdIOCtx *fd, LZW_STATIC_DATA *sd, char flag, int input_code_size, int *ZeroDataBlockP) { - static int fresh = FALSE; - int code, incode; - static int code_size, set_code_size; - static int max_code, max_code_size; - static int firstcode, oldcode; - static int clear_code, end_code; - static int table[2][(1<< MAX_LWZ_BITS)]; - static int stack[STACK_SIZE], *sp; - register int i; + int code, incode, i; if (flag) { - set_code_size = input_code_size; - code_size = set_code_size+1; - clear_code = 1 << set_code_size ; - end_code = clear_code + 1; - max_code_size = 2*clear_code; - max_code = clear_code+2; - - GetCode(fd, 0, TRUE, ZeroDataBlockP); + sd->set_code_size = input_code_size; + sd->code_size = sd->set_code_size+1; + sd->clear_code = 1 << sd->set_code_size ; + sd->end_code = sd->clear_code + 1; + sd->max_code_size = 2*sd->clear_code; + sd->max_code = sd->clear_code+2; + + GetCode(fd, &sd->scd, 0, TRUE, ZeroDataBlockP); - fresh = TRUE; + sd->fresh = TRUE; - for (i = 0; i < clear_code; ++i) { - table[0][i] = 0; - table[1][i] = i; + for (i = 0; i < sd->clear_code; ++i) { + sd->table[0][i] = 0; + sd->table[1][i] = i; } for (; i < (1<table[0][i] = sd->table[1][0] = 0; - sp = stack; + sd->sp = sd->stack; return 0; - } else if (fresh) { - fresh = FALSE; + } else if (sd->fresh) { + sd->fresh = FALSE; do { - firstcode = oldcode = - GetCode(fd, code_size, FALSE, ZeroDataBlockP); - } while (firstcode == clear_code); - return firstcode; + sd->firstcode = sd->oldcode = + GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP); + } while (sd->firstcode == sd->clear_code); + return sd->firstcode; } - if (sp > stack) - return *--sp; + if (sd->sp > sd->stack) + return *--sd->sp; - while ((code = GetCode(fd, code_size, FALSE, ZeroDataBlockP)) >= 0) { - if (code == clear_code) { - for (i = 0; i < clear_code; ++i) { - table[0][i] = 0; - table[1][i] = i; + while ((code = GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP)) >= 0) { + if (code == sd->clear_code) { + for (i = 0; i < sd->clear_code; ++i) { + sd->table[0][i] = 0; + sd->table[1][i] = i; } for (; i < (1<table[0][i] = sd->table[1][i] = 0; + sd->code_size = sd->set_code_size+1; + sd->max_code_size = 2*sd->clear_code; + sd->max_code = sd->clear_code+2; + sd->sp = sd->stack; + sd->firstcode = sd->oldcode = + GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP); + return sd->firstcode; + } else if (code == sd->end_code) { int count; unsigned char buf[260]; - int maxcount = 1024; if (*ZeroDataBlockP) return -2; - while ((count = GetDataBlock(fd, buf, ZeroDataBlockP)) > 0 && --maxcount >= 0) + while ((count = GetDataBlock(fd, buf, ZeroDataBlockP)) > 0) ; - if (count != 0 || maxcount < 0) + if (count != 0) return -2; } incode = code; - if (sp == (stack + STACK_SIZE)) { + if (sd->sp == (sd->stack + STACK_SIZE)) { /* Bad compressed data stream */ return -1; } - if (code >= max_code) { - *sp++ = firstcode; - code = oldcode; + if (code >= sd->max_code) { + *sd->sp++ = sd->firstcode; + code = sd->oldcode; } - while (code >= clear_code) { - if (sp == (stack + STACK_SIZE)) { + while (code >= sd->clear_code) { + if (sd->sp == (sd->stack + STACK_SIZE)) { /* Bad compressed data stream */ return -1; } - *sp++ = table[1][code]; - if (code == table[0][code]) { + *sd->sp++ = sd->table[1][code]; + if (code == sd->table[0][code]) { /* Oh well */ } - code = table[0][code]; + code = sd->table[0][code]; } - *sp++ = firstcode = table[1][code]; + *sd->sp++ = sd->firstcode = sd->table[1][code]; - if ((code = max_code) <(1<= max_code_size) && - (max_code_size < (1<max_code) <(1<table[0][code] = sd->oldcode; + sd->table[1][code] = sd->firstcode; + ++sd->max_code; + if ((sd->max_code >= sd->max_code_size) && + (sd->max_code_size < (1<max_code_size *= 2; + ++sd->code_size; } } - oldcode = incode; + sd->oldcode = incode; - if (sp > stack) - return *--sp; + if (sd->sp > sd->stack) + return *--sd->sp; } return code; } static int -LWZReadByte(gdIOCtx *fd, int flag, int input_code_size, int *ZeroDataBlockP) +LWZReadByte(gdIOCtx *fd, LZW_STATIC_DATA *sd, char flag, int input_code_size, int *ZeroDataBlockP) { int rv; - rv = LWZReadByte_(fd,flag,input_code_size, ZeroDataBlockP); + rv = LWZReadByte_(fd, sd, flag, input_code_size, ZeroDataBlockP); if (VERBOSE) printf("[LWZReadByte(,%d,%d) returning %d]\n",flag,input_code_size,rv); return(rv); } @@ -501,6 +527,19 @@ ReadImage(gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap) int v; int xpos = 0, ypos = 0, pass = 0; int i; + LZW_STATIC_DATA sd; + + /* + ** Initialize the Compression routines + */ + if (! ReadOK(fd,&c,1)) { + return; + } + + if (c > MAX_LWZ_BITS) { + return; + } + /* Stash the color map into the image */ for (i=0; (ired[i] = cmap[CM_RED][i]; @@ -510,13 +549,7 @@ ReadImage(gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap) } /* Many (perhaps most) of these colors will remain marked open. */ im->colorsTotal = gdMaxColors; - /* - ** Initialize the Compression routines - */ - if (! ReadOK(fd,&c,1)) { - return; - } - if (LWZReadByte(fd, TRUE, c, ZeroDataBlockP) < 0) { + if (LWZReadByte(fd, &sd, TRUE, c, ZeroDataBlockP) < 0) { return; } @@ -525,12 +558,16 @@ ReadImage(gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap) ** REMOVED For 1.4 */ /*if (ignore) { */ - /* while (LWZReadByte(fd, FALSE, c) >= 0) */ + /* while (LWZReadByte(fd, &sd, FALSE, c) >= 0) */ /* ; */ /* return; */ /*} */ - while ((v = LWZReadByte(fd,FALSE,c, ZeroDataBlockP)) >= 0 ) { + while ((v = LWZReadByte(fd, &sd, FALSE, c, ZeroDataBlockP)) >= 0 ) { + if (v >= gdMaxColors) { + v = 0; + } + /* This how we recognize which colors are actually used. */ if (im->open[v]) { im->open[v] = 0; @@ -572,7 +609,7 @@ ReadImage(gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap) } fini: - if (LWZReadByte(fd,FALSE,c, ZeroDataBlockP)>=0) { + if (LWZReadByte(fd, &sd, FALSE, c, ZeroDataBlockP) >=0) { /* Ignore extra */ } } diff --git a/lib/gd/gd_gif_out.c b/lib/gd/gd_gif_out.c index 6c919cc2a..1310677bd 100644 --- a/lib/gd/gd_gif_out.c +++ b/lib/gd/gd_gif_out.c @@ -1,7 +1,3 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include #include #include @@ -139,7 +135,7 @@ BGD_DECLARE(void) gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out) BitsPerPixel = colorstobpp(tim->colorsTotal); /* All set, let's do it. */ GIFEncode( - out, tim->sx, tim->sy, interlace, 0, transparent, BitsPerPixel, + out, tim->sx, tim->sy, interlace, 0, tim->transparent, BitsPerPixel, tim->red, tim->green, tim->blue, tim); if (pim) { /* Destroy palette based temporary image. */ @@ -450,6 +446,9 @@ BGD_DECLARE(void) gdImageGifAnimEnd(FILE *outFile) BGD_DECLARE(void *) gdImageGifAnimEndPtr (int *size) { char *rv = (char *) gdMalloc (1); + if (!rv) { + return 0; + } *rv = ';'; *size = 1; return (void *)rv; diff --git a/lib/gd/gd_io.h b/lib/gd/gd_io.h index 40985756c..7f1c42141 100644 --- a/lib/gd/gd_io.h +++ b/lib/gd/gd_io.h @@ -45,7 +45,7 @@ void Putchar (int c, gdIOCtx * ctx); int gdGetWord (int *result, gdIOCtx * ctx); int gdGetInt (int *result, gdIOCtx * ctx); - int gdSeek (gdIOCtx * ctx, const int); + int gdSeek (gdIOCtx * ctx, const int offset); long gdTell (gdIOCtx * ctx); #endif diff --git a/lib/gd/gd_io_dp.c b/lib/gd/gd_io_dp.c index e57a2d3cb..05ed0729f 100644 --- a/lib/gd/gd_io_dp.c +++ b/lib/gd/gd_io_dp.c @@ -292,7 +292,11 @@ dynamicGetbuf (gdIOCtxPtr ctx, void *buf, int len) { if (remain == 0) { - return EOF; + /* 2.0.34: EOF is incorrect. We use 0 for + errors and EOF, just like fileGetbuf, + which is a simple fread() wrapper. + TBB. Original bug report: Daniel Cowgill. */ + return 0; /* NOT EOF */ } rlen = remain; } diff --git a/lib/gd/gd_io_ss.c b/lib/gd/gd_io_ss.c index 7a68fd165..131366829 100644 --- a/lib/gd/gd_io_ss.c +++ b/lib/gd/gd_io_ss.c @@ -101,7 +101,7 @@ sourceGetbuf (gdIOCtx * ctx, void *buf, int size) if (res == 0) { - return EOF; + return 0; } else if (res < 0) { diff --git a/lib/gd/gd_jpeg.c b/lib/gd/gd_jpeg.c index defa3cfb7..25df8e497 100644 --- a/lib/gd/gd_jpeg.c +++ b/lib/gd/gd_jpeg.c @@ -1,6 +1,6 @@ /* * gd_jpeg.c: Read and write JPEG (JFIF) format image files using the - * gd graphics library (http://www.boutell.com/gd/). + * gd graphics library (http://www.libgd.org). * * This software is based in part on the work of the Independent JPEG * Group. For more information on the IJG JPEG software (and JPEG -- 2.40.0