aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorijliao <ijliao@FreeBSD.org>2002-05-21 15:41:54 +0800
committerijliao <ijliao@FreeBSD.org>2002-05-21 15:41:54 +0800
commit0c3276726a4360219122b630dba18e5b327579b1 (patch)
tree5efca470dbb74c89a18448432bff18e99c8a2e3c
parent06bc2ae5ff02e3754aa726f65ab0ec9334ba18c8 (diff)
downloadfreebsd-ports-gnome-0c3276726a4360219122b630dba18e5b327579b1.tar.gz
freebsd-ports-gnome-0c3276726a4360219122b630dba18e5b327579b1.tar.zst
freebsd-ports-gnome-0c3276726a4360219122b630dba18e5b327579b1.zip
Improved GIF support.
New GIF output functions, w/ or w/o LZW compression. LZW compression is OFF by default to make the package legal in US and Canada. Updated documentation PR: 37455 Submitted by: Alex Dupre <sysadmin@alexdupre.com>
-rw-r--r--graphics/gd2/Makefile31
-rw-r--r--graphics/gd2/distinfo1
-rw-r--r--graphics/gd2/files/Makefile.bsd9
-rw-r--r--graphics/gd2/files/gd2togif.c40
-rw-r--r--graphics/gd2/files/gd_biggif_out.c823
-rw-r--r--graphics/gd2/files/gd_gif_in.c573
-rw-r--r--graphics/gd2/files/gd_gif_out.c46
-rw-r--r--graphics/gd2/files/gd_lzw_out.c795
-rw-r--r--graphics/gd2/files/gdcmpgif.c85
-rw-r--r--graphics/gd2/files/giftogd2.c48
-rw-r--r--graphics/gd2/files/patch-Makefile47
-rw-r--r--graphics/gd2/files/patch-gd.c104
-rw-r--r--graphics/gd2/files/patch-gd.h67
-rw-r--r--graphics/gd2/files/patch-gd_png.c11
-rw-r--r--graphics/gd2/files/patch-gdcache.h11
-rw-r--r--graphics/gd2/files/patch-gdft.c166
-rw-r--r--graphics/gd2/files/patch-gdtest.c81
-rw-r--r--graphics/gd2/files/patch-gdtestft.c99
-rw-r--r--graphics/gd2/files/patch-gif14
-rw-r--r--graphics/gd2/files/patch-index.html320
-rw-r--r--graphics/gd2/files/patch-malloc5
-rw-r--r--graphics/gd2/files/patch-webpng.c66
-rw-r--r--graphics/gd2/pkg-descr28
-rw-r--r--graphics/gd2/pkg-plist7
24 files changed, 3427 insertions, 50 deletions
diff --git a/graphics/gd2/Makefile b/graphics/gd2/Makefile
index bde979b72a1f..731f67663b5d 100644
--- a/graphics/gd2/Makefile
+++ b/graphics/gd2/Makefile
@@ -7,21 +7,15 @@
PORTNAME= gd
PORTVERSION= 2.0.1
-PORTREVISION= 2
+PORTREVISION= 3
CATEGORIES+= graphics
MASTER_SITES= http://www.boutell.com/gd/http/ \
ftp://ftp.boutell.com/pub/boutell/gd/ \
- http://virtual-estates.net/~mi/port-stuff/ \
${MASTER_SITE_RINGSERVER}
MASTER_SITE_SUBDIR= graphics/gd
-DISTFILES= ${DISTNAME}${EXTRACT_SUFX} gd_gif_in.c.bz2
-EXTRACT_ONLY= ${DISTNAME}${EXTRACT_SUFX}
MAINTAINER?= ports@FreeBSD.org
-.if !exists(/usr/bin/bzip2)
-BUILD_DEPENDS+= bzip2:${PORTSDIR}/archivers/bzip2
-.endif
LIB_DEPENDS= png:${PORTSDIR}/graphics/png \
jpeg:${PORTSDIR}/graphics/jpeg \
freetype:${PORTSDIR}/print/freetype2
@@ -46,10 +40,29 @@ MAKE_ARGS+= -j2
MAKE_ARGS+= $v="${$v}"
.endfor
+pre-fetch:
+.if !defined(WITH_LZW)
+ @${ECHO_CMD} "************************************************************"
+ @${ECHO_CMD} "* If you live outside US and Canada, you can set *"
+ @${ECHO_CMD} "* WITH_LZW=1 to enable GIF compression support. *"
+ @${ECHO_CMD} "************************************************************"
+.endif
+
post-extract:
- ${BZIP2_CMD} -d < ${_DISTDIR}/gd_gif_in.c.bz2 > ${WRKSRC}/gd_gif_in.c
+ @${CP} ${FILESDIR}/g* ${WRKSRC}
+
+post-patch:
+.if !defined(WITH_LZW)
+ @${PERL} -pi -e "s|#define LZW_LICENCED||g" ${WRKSRC}/gd_gif_out.c
+.endif
+
+post-install:
+.if !defined(NOPORTDOCS)
+ @${MKDIR} ${DOCSDIR}
+ @${INSTALL_DATA} ${WRKSRC}/index.html ${DOCSDIR}
+.endif
-.ifdef GD_FONTS
+.if defined(GD_FONTS)
SCRIPTS_ENV+= GD_FONTS="${GD_FONTS}"
.endif
diff --git a/graphics/gd2/distinfo b/graphics/gd2/distinfo
index 25da3c3795f9..8bc97eb452ab 100644
--- a/graphics/gd2/distinfo
+++ b/graphics/gd2/distinfo
@@ -1,2 +1 @@
MD5 (gd-2.0.1.tar.gz) = 43af994a97f3300a1165ca4888176ece
-MD5 (gd_gif_in.c.bz2) = 54132aea09471bb997672436dd9a1a96
diff --git a/graphics/gd2/files/Makefile.bsd b/graphics/gd2/files/Makefile.bsd
index 718ca5c3b113..8d8f201616a5 100644
--- a/graphics/gd2/files/Makefile.bsd
+++ b/graphics/gd2/files/Makefile.bsd
@@ -1,10 +1,9 @@
PROGS!= make -V BIN_PROGRAMS -f ${WRKSRC}/Makefile
TESTS!= make -V TEST_PROGRAMS -f ${WRKSRC}/Makefile
OBJS!= make -V LIBOBJS -f ${WRKSRC}/Makefile
-OBJS+= gd_gif_in.o
SRCS= ${OBJS:.o=.c}
LIB=gd
-SHLIB_MAJOR=3
+SHLIB_MAJOR=4
SHLIB_MINOR=0
INCS= gd.h gd_io.h gdcache.h gdfontg.h gdfontl.h gdfontmb.h \
gdfonts.h gdfontt.h
@@ -42,12 +41,12 @@ ${PROGS} ${TESTS}: ${SHLIB_NAME} lib${LIB}.a
install:
mkdir -p ${PREFIX}/include
- make LIB=${LIB} LIBDIR="${PREFIX}/lib" NOPROFILE=true \
+ make LIB=${LIB} LIBDIR=${PREFIX}/lib NOPROFILE=true \
SHLIB_MAJOR=${SHLIB_MAJOR} SHLIB_MINOR=${SHLIB_MINOR} \
-f bsd.lib.mk install
cd ${.CURDIR} && ${INSTALL_DATA} ${INCS} ${PREFIX}/include
- cd ${.CURDIR} && ${INSTALL_PROGRAM} ${PROGS} "${PREFIX}/bin/"
- ${INSTALL_SCRIPT} "${.CURDIR}/bdftogd" "${PREFIX}/bin/"
+ cd ${.CURDIR} && ${INSTALL_PROGRAM} ${PROGS} ${PREFIX}/bin/
+ ${INSTALL_SCRIPT} ${.CURDIR}/bdftogd ${PREFIX}/bin/
.if exists(${.CURDIR}/Makefile.fonts)
.include "Makefile.fonts"
diff --git a/graphics/gd2/files/gd2togif.c b/graphics/gd2/files/gd2togif.c
new file mode 100644
index 000000000000..d5fbb8921c3a
--- /dev/null
+++ b/graphics/gd2/files/gd2togif.c
@@ -0,0 +1,40 @@
+#include <stdio.h>
+#include "gd.h"
+
+/* A short program which converts a .gif file into a .gd file, for
+ your convenience in creating images on the fly from a
+ basis image that must be loaded quickly. The .gd format
+ is not intended to be a general-purpose format. */
+
+int main(int argc, char **argv)
+{
+ gdImagePtr im;
+ FILE *in, *out;
+ if (argc != 3) {
+ fprintf(stderr, "Usage: gd2togif filename.gd2 filename.gif\n");
+ exit(1);
+ }
+ in = fopen(argv[1], "rb");
+ if (!in) {
+ fprintf(stderr, "Input file does not exist!\n");
+ exit(1);
+ }
+ im = gdImageCreateFromGd2(in);
+ fclose(in);
+ if (!im) {
+ fprintf(stderr, "Input is not in GIF format!\n");
+ exit(1);
+ }
+ out = fopen(argv[2], "wb");
+ if (!out) {
+ fprintf(stderr, "Output file cannot be written to!\n");
+ gdImageDestroy(im);
+ exit(1);
+ }
+ gdImageGif(im, out);
+ fclose(out);
+ gdImageDestroy(im);
+
+ return 0;
+}
+
diff --git a/graphics/gd2/files/gd_biggif_out.c b/graphics/gd2/files/gd_biggif_out.c
new file mode 100644
index 000000000000..3f4ac1fa4cca
--- /dev/null
+++ b/graphics/gd2/files/gd_biggif_out.c
@@ -0,0 +1,823 @@
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include "gd.h"
+
+/*
+** Wrapper functions for this module.
+*/
+
+void gdImageBigGif(gdImagePtr im, FILE *outFile)
+{
+ gdIOCtx *out = gdNewFileCtx(outFile);
+ gdImageBigGifCtx(im, out);
+ out->free(out);
+}
+
+void* gdImageBigGifPtr(gdImagePtr im, int *size)
+{
+ void *rv;
+ gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
+ gdImageBigGifCtx(im, out);
+ rv = gdDPExtractData(out,size);
+ out->free(out);
+ return rv;
+}
+
+/* Code drawn from ppmtogif.c, from the pbmplus package
+**
+** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A
+** Lempel-Zim compression based on "compress".
+**
+** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
+**
+** Copyright (C) 1989 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+**
+** The Graphics Interchange Format(c) is the Copyright property of
+** CompuServe Incorporated. GIF(sm) is a Service Mark property of
+** CompuServe Incorporated.
+*
+* Heavily modified by Mouse, 1998-02-12.
+* Remove LZW compression.
+* Added miGIF run length compression.
+*
+*/
+
+/*
+ * a code_int must be able to hold 2**GIFBITS values of type int, and also -1
+ */
+typedef int code_int;
+
+static int colorstobpp(int colors);
+static void BumpPixel (void);
+static int GIFNextPixel (gdImagePtr im);
+static void GIFEncode (gdIOCtx *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im);
+/*static void Putword (int w, gdIOCtx *fp); */
+static void GIFcompress (int, gdIOCtx *, gdImagePtr, int);
+static void output (code_int code);
+
+/* UNUSED
+* static void char_init (void);
+* static void char_out (int c);
+*/
+
+/* Allows for reuse */
+static void init_statics(void);
+
+void gdImageBigGifCtx(gdImagePtr im, gdIOCtx *out)
+{
+ int interlace, transparent, BitsPerPixel;
+
+ interlace = im->interlace;
+ transparent = im->transparent;
+
+ BitsPerPixel = colorstobpp(im->colorsTotal);
+ /* Clear any old values in statics strewn through the GIF code */
+ init_statics();
+ /* All set, let's do it. */
+ GIFEncode(
+ out, im->sx, im->sy, interlace, 0, transparent, BitsPerPixel,
+ im->red, im->green, im->blue, im);
+}
+
+static int
+colorstobpp(int colors)
+{
+ int bpp = 0;
+
+ if ( colors <= 2 )
+ bpp = 1;
+ else if ( colors <= 4 )
+ bpp = 2;
+ else if ( colors <= 8 )
+ bpp = 3;
+ else if ( colors <= 16 )
+ bpp = 4;
+ else if ( colors <= 32 )
+ bpp = 5;
+ else if ( colors <= 64 )
+ bpp = 6;
+ else if ( colors <= 128 )
+ bpp = 7;
+ else if ( colors <= 256 )
+ bpp = 8;
+ return bpp;
+ }
+
+/*****************************************************************************
+ *
+ * GIFENCODE.C - GIF Image compression interface
+ *
+ * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent,
+ * BitsPerPixel, Red, Green, Blue, gdImagePtr )
+ *
+ *****************************************************************************/
+
+#define TRUE 1
+#define FALSE 0
+
+static int Width, Height;
+static int curx, cury;
+static long CountDown;
+static int Pass = 0;
+static int Interlace;
+
+/*
+ * Bump the 'curx' and 'cury' to point to the next pixel
+ */
+static void
+BumpPixel(void)
+{
+ /*
+ * Bump the current X position
+ */
+ ++curx;
+
+ /*
+ * If we are at the end of a scan line, set curx back to the beginning
+ * If we are interlaced, bump the cury to the appropriate spot,
+ * otherwise, just increment it.
+ */
+ if( curx == Width ) {
+ curx = 0;
+
+ if( !Interlace )
+ ++cury;
+ else {
+ switch( Pass ) {
+
+ case 0:
+ cury += 8;
+ if( cury >= Height ) {
+ ++Pass;
+ cury = 4;
+ }
+ break;
+
+ case 1:
+ cury += 8;
+ if( cury >= Height ) {
+ ++Pass;
+ cury = 2;
+ }
+ break;
+
+ case 2:
+ cury += 4;
+ if( cury >= Height ) {
+ ++Pass;
+ cury = 1;
+ }
+ break;
+
+ case 3:
+ cury += 2;
+ break;
+ }
+ }
+ }
+}
+
+/*
+ * Return the next pixel from the image
+ */
+static int
+GIFNextPixel(gdImagePtr im)
+{
+ int r;
+
+ if( CountDown == 0 )
+ return EOF;
+
+ --CountDown;
+
+ r = gdImageGetPixel(im, curx, cury);
+
+ BumpPixel();
+
+ return r;
+}
+
+/* public */
+
+static void
+GIFEncode(gdIOCtx *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im)
+{
+ int B;
+ int RWidth, RHeight;
+ int LeftOfs, TopOfs;
+ int Resolution;
+ int ColorMapSize;
+ int InitCodeSize;
+ int i;
+
+ Interlace = GInterlace;
+
+ ColorMapSize = 1 << BitsPerPixel;
+
+ RWidth = Width = GWidth;
+ RHeight = Height = GHeight;
+ LeftOfs = TopOfs = 0;
+
+ Resolution = BitsPerPixel;
+
+ /*
+ * Calculate number of bits we are expecting
+ */
+ CountDown = (long)Width * (long)Height;
+
+ /*
+ * Indicate which pass we are on (if interlace)
+ */
+ Pass = 0;
+
+ /*
+ * The initial code size
+ */
+ if( BitsPerPixel <= 1 )
+ InitCodeSize = 2;
+ else
+ InitCodeSize = BitsPerPixel;
+
+ /*
+ * Set up the current x and y position
+ */
+ curx = cury = 0;
+
+ /*
+ * Write the Magic header
+ */
+ gdPutBuf( Transparent < 0 ? "GIF87a" : "GIF89a", 6, fp );
+
+ /*
+ * Write out the screen width and height
+ */
+ Putword( RWidth, fp );
+ Putword( RHeight, fp );
+
+ /*
+ * Indicate that there is a global colour map
+ */
+ B = 0x80; /* Yes, there is a color map */
+
+ /*
+ * OR in the resolution
+ */
+ B |= (Resolution - 1) << 4;
+
+ /*
+ * OR in the Bits per Pixel
+ */
+ B |= (BitsPerPixel - 1);
+
+ /*
+ * Write it out
+ */
+ gdPutC( B, fp );
+
+ /*
+ * Write out the Background colour
+ */
+ gdPutC( Background, fp );
+
+ /*
+ * Byte of 0's (future expansion)
+ */
+ gdPutC( 0, fp );
+
+ /*
+ * Write out the Global Colour Map
+ */
+ for( i=0; i<ColorMapSize; ++i ) {
+ gdPutC( Red[i], fp );
+ gdPutC( Green[i], fp );
+ gdPutC( Blue[i], fp );
+ }
+
+ /*
+ * Write out extension for transparent colour index, if necessary.
+ */
+ if ( Transparent >= 0 ) {
+ gdPutC( '!', fp );
+ gdPutC( 0xf9, fp );
+ gdPutC( 4, fp );
+ gdPutC( 1, fp );
+ gdPutC( 0, fp );
+ gdPutC( 0, fp );
+ gdPutC( (unsigned char) Transparent, fp );
+ gdPutC( 0, fp );
+ }
+
+ /*
+ * Write an Image separator
+ */
+ gdPutC( ',', fp );
+
+ /*
+ * Write the Image header
+ */
+
+ Putword( LeftOfs, fp );
+ Putword( TopOfs, fp );
+ Putword( Width, fp );
+ Putword( Height, fp );
+
+ /*
+ * Write out whether or not the image is interlaced
+ */
+ if( Interlace )
+ gdPutC( 0x40, fp );
+ else
+ gdPutC( 0x00, fp );
+
+ /*
+ * Write out the initial code size
+ */
+ gdPutC( InitCodeSize, fp );
+
+ /*
+ * Go and actually compress the data
+ */
+ GIFcompress( InitCodeSize+1, fp, im, Background );
+
+ /*
+ * Write out a Zero-length packet (to end the series)
+ */
+ gdPutC( 0, fp );
+
+ /*
+ * Write the GIF file terminator
+ */
+ gdPutC( ';', fp );
+}
+
+/* Write out a word to the GIF file */
+/*static void */
+/*Putword(int w, gdIOCtx *fp) */
+/*{ */
+/* fputc( w & 0xff, fp ); */
+/* fputc( (w / 256) & 0xff, fp ); */
+/*} */
+
+#define GIFBITS 12
+
+/*-----------------------------------------------------------------------
+ *
+ * miGIF Compression - mouse and ivo's GIF-compatible compression
+ *
+ * -run length encoding compression routines-
+ *
+ * Copyright (C) 1998 Hutchison Avenue Software Corporation
+ * http://www.hasc.com
+ * info@hasc.com
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. This software is provided "AS IS." The Hutchison Avenue
+ * Software Corporation disclaims all warranties, either express or implied,
+ * including but not limited to implied warranties of merchantability and
+ * fitness for a particular purpose, with respect to this code and accompanying
+ * documentation.
+ *
+ * The miGIF compression routines do not, strictly speaking, generate files
+ * conforming to the GIF spec, since the image data is not LZW-compressed
+ * (this is the point: in order to avoid transgression of the Unisys patent
+ * on the LZW algorithm.) However, miGIF generates data streams that any
+ * reasonably sane LZW decompresser will decompress to what we want.
+ *
+ * miGIF compression uses run length encoding. It compresses horizontal runs
+ * of pixels of the same color. This type of compression gives good results
+ * on images with many runs, for example images with lines, text and solid
+ * shapes on a solid-colored background. It gives little or no compression
+ * on images with few runs, for example digital or scanned photos.
+ *
+ * der Mouse
+ * mouse@rodents.montreal.qc.ca
+ * 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
+ *
+ * ivo@hasc.com
+ *
+ * The Graphics Interchange Format(c) is the Copyright property of
+ * CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ * CompuServe Incorporated.
+ *
+ */
+
+static int rl_pixel;
+static int rl_basecode;
+static int rl_count;
+static int rl_table_pixel;
+static int rl_table_max;
+static int just_cleared;
+static int out_bits;
+static int out_bits_init;
+static int out_count;
+static int out_bump;
+static int out_bump_init;
+static int out_clear;
+static int out_clear_init;
+static int max_ocodes;
+static int code_clear;
+static int code_eof;
+static unsigned int obuf;
+static int obits;
+static gdIOCtx *ofile;
+static unsigned char oblock[256];
+static int oblen;
+
+/* Used only when debugging GIF compression code */
+/* #define DEBUGGING_ENVARS */
+
+#ifdef DEBUGGING_ENVARS
+
+static int verbose_set = 0;
+static int verbose;
+#define VERBOSE (verbose_set?verbose:set_verbose())
+
+static int set_verbose(void)
+{
+ verbose = !!getenv("GIF_VERBOSE");
+ verbose_set = 1;
+ return(verbose);
+}
+
+#else
+
+#define VERBOSE 0
+
+#endif
+
+
+static const char *binformat(unsigned int v, int nbits)
+{
+ static char bufs[8][64];
+ static int bhand = 0;
+ unsigned int bit;
+ int bno;
+ char *bp;
+
+ bhand --;
+ if (bhand < 0) bhand = (sizeof(bufs)/sizeof(bufs[0]))-1;
+ bp = &bufs[bhand][0];
+ for (bno=nbits-1,bit=1U<<bno;bno>=0;bno--,bit>>=1)
+ { *bp++ = (v & bit) ? '1' : '0';
+ if (((bno&3) == 0) && (bno != 0)) *bp++ = '.';
+ }
+ *bp = '\0';
+ return(&bufs[bhand][0]);
+}
+
+static void write_block(void)
+{
+ int i;
+
+ if (VERBOSE)
+ { printf("write_block %d:",oblen);
+ for (i=0;i<oblen;i++) printf(" %02x",oblock[i]);
+ printf("\n");
+ }
+ gdPutC(oblen,ofile);
+ gdPutBuf(&oblock[0],oblen,ofile);
+ oblen = 0;
+}
+
+static void block_out(unsigned char c)
+{
+ if (VERBOSE) printf("block_out %s\n",binformat(c,8));
+ oblock[oblen++] = c;
+ if (oblen >= 255) write_block();
+}
+
+static void block_flush(void)
+{
+ if (VERBOSE) printf("block_flush\n");
+ if (oblen > 0) write_block();
+}
+
+static void output(int val)
+{
+ if (VERBOSE) printf("output %s [%s %d %d]\n",binformat(val,out_bits),binformat(obuf,obits),obits,out_bits);
+ obuf |= val << obits;
+ obits += out_bits;
+ while (obits >= 8)
+ { block_out(obuf&0xff);
+ obuf >>= 8;
+ obits -= 8;
+ }
+ if (VERBOSE) printf("output leaving [%s %d]\n",binformat(obuf,obits),obits);
+}
+
+static void output_flush(void)
+{
+ if (VERBOSE) printf("output_flush\n");
+ if (obits > 0) block_out(obuf);
+ block_flush();
+}
+
+static void did_clear(void)
+{
+ if (VERBOSE) printf("did_clear\n");
+ out_bits = out_bits_init;
+ out_bump = out_bump_init;
+ out_clear = out_clear_init;
+ out_count = 0;
+ rl_table_max = 0;
+ just_cleared = 1;
+}
+
+static void output_plain(int c)
+{
+ if (VERBOSE) printf("output_plain %s\n",binformat(c,out_bits));
+ just_cleared = 0;
+ output(c);
+ out_count ++;
+ if (out_count >= out_bump)
+ { out_bits ++;
+ out_bump += 1 << (out_bits - 1);
+ }
+ if (out_count >= out_clear)
+ { output(code_clear);
+ did_clear();
+ }
+}
+
+static unsigned int isqrt(unsigned int x)
+{
+ unsigned int r;
+ unsigned int v;
+
+ if (x < 2) return(x);
+ for (v=x,r=1;v;v>>=2,r<<=1) ;
+ while (1)
+ { v = ((x / r) + r) / 2;
+ if ((v == r) || (v == r+1)) return(r);
+ r = v;
+ }
+}
+
+static unsigned int compute_triangle_count(unsigned int count, unsigned int nrepcodes)
+{
+ unsigned int perrep;
+ unsigned int cost;
+
+ cost = 0;
+ perrep = (nrepcodes * (nrepcodes+1)) / 2;
+ while (count >= perrep)
+ { cost += nrepcodes;
+ count -= perrep;
+ }
+ if (count > 0)
+ { unsigned int n;
+ n = isqrt(count);
+ while ((n*(n+1)) >= 2*count) n --;
+ while ((n*(n+1)) < 2*count) n ++;
+ cost += n;
+ }
+ return(cost);
+}
+
+static void max_out_clear(void)
+{
+ out_clear = max_ocodes;
+}
+
+static void reset_out_clear(void)
+{
+ out_clear = out_clear_init;
+ if (out_count >= out_clear)
+ { output(code_clear);
+ did_clear();
+ }
+}
+
+static void rl_flush_fromclear(int count)
+{
+ int n;
+
+ if (VERBOSE) printf("rl_flush_fromclear %d\n",count);
+ max_out_clear();
+ rl_table_pixel = rl_pixel;
+ n = 1;
+ while (count > 0)
+ { if (n == 1)
+ { rl_table_max = 1;
+ output_plain(rl_pixel);
+ count --;
+ }
+ else if (count >= n)
+ { rl_table_max = n;
+ output_plain(rl_basecode+n-2);
+ count -= n;
+ }
+ else if (count == 1)
+ { rl_table_max ++;
+ output_plain(rl_pixel);
+ count = 0;
+ }
+ else
+ { rl_table_max ++;
+ output_plain(rl_basecode+count-2);
+ count = 0;
+ }
+ if (out_count == 0) n = 1; else n ++;
+ }
+ reset_out_clear();
+ if (VERBOSE) printf("rl_flush_fromclear leaving table_max=%d\n",rl_table_max);
+}
+
+static void rl_flush_clearorrep(int count)
+{
+ int withclr;
+
+ if (VERBOSE) printf("rl_flush_clearorrep %d\n",count);
+ withclr = 1 + compute_triangle_count(count,max_ocodes);
+ if (withclr < count)
+ { output(code_clear);
+ did_clear();
+ rl_flush_fromclear(count);
+ }
+ else
+ { for (;count>0;count--) output_plain(rl_pixel);
+ }
+}
+
+static void rl_flush_withtable(int count)
+{
+ int repmax;
+ int repleft;
+ int leftover;
+
+ if (VERBOSE) printf("rl_flush_withtable %d\n",count);
+ repmax = count / rl_table_max;
+ leftover = count % rl_table_max;
+ repleft = (leftover ? 1 : 0);
+ if (out_count+repmax+repleft > max_ocodes)
+ { repmax = max_ocodes - out_count;
+ leftover = count - (repmax * rl_table_max);
+ repleft = 1 + compute_triangle_count(leftover,max_ocodes);
+ }
+ if (VERBOSE) printf("rl_flush_withtable repmax=%d leftover=%d repleft=%d\n",repmax,leftover,repleft);
+ if (1+compute_triangle_count(count,max_ocodes) < repmax+repleft)
+ { output(code_clear);
+ did_clear();
+ rl_flush_fromclear(count);
+ return;
+ }
+ max_out_clear();
+ for (;repmax>0;repmax--) output_plain(rl_basecode+rl_table_max-2);
+ if (leftover)
+ { if (just_cleared)
+ { rl_flush_fromclear(leftover);
+ }
+ else if (leftover == 1)
+ { output_plain(rl_pixel);
+ }
+ else
+ { output_plain(rl_basecode+leftover-2);
+ }
+ }
+ reset_out_clear();
+}
+
+static void rl_flush(void)
+{
+ /* UNUSED int table_reps; */
+ /* UNUSED int table_extra; */
+
+ if (VERBOSE) printf("rl_flush [ %d %d\n",rl_count,rl_pixel);
+ if (rl_count == 1)
+ { output_plain(rl_pixel);
+ rl_count = 0;
+ if (VERBOSE) printf("rl_flush ]\n");
+ return;
+ }
+ if (just_cleared)
+ { rl_flush_fromclear(rl_count);
+ }
+ else if ((rl_table_max < 2) || (rl_table_pixel != rl_pixel))
+ { rl_flush_clearorrep(rl_count);
+ }
+ else
+ { rl_flush_withtable(rl_count);
+ }
+ if (VERBOSE) printf("rl_flush ]\n");
+ rl_count = 0;
+}
+
+static void GIFcompress(int init_bits, gdIOCtx *outfile, gdImagePtr im, int background)
+{
+ int c;
+
+ ofile = outfile;
+ obuf = 0;
+ obits = 0;
+ oblen = 0;
+ code_clear = 1 << (init_bits - 1);
+ code_eof = code_clear + 1;
+ rl_basecode = code_eof + 1;
+ out_bump_init = (1 << (init_bits - 1)) - 1;
+ /* for images with a lot of runs, making out_clear_init larger will
+ give better compression. */
+ out_clear_init = (init_bits <= 3) ? 9 : (out_bump_init-1);
+#ifdef DEBUGGING_ENVARS
+ { const char *ocienv;
+ ocienv = getenv("GIF_OUT_CLEAR_INIT");
+ if (ocienv)
+ { out_clear_init = atoi(ocienv);
+ if (VERBOSE) printf("[overriding out_clear_init to %d]\n",out_clear_init);
+ }
+ }
+#endif
+ out_bits_init = init_bits;
+ max_ocodes = (1 << GIFBITS) - ((1 << (out_bits_init - 1)) + 3);
+ did_clear();
+ output(code_clear);
+ rl_count = 0;
+ while (1)
+ { c = GIFNextPixel(im);
+ if ((rl_count > 0) && (c != rl_pixel)) rl_flush();
+ if (c == EOF) break;
+ if (rl_pixel == c)
+ { rl_count ++;
+ }
+ else
+ { rl_pixel = c;
+ rl_count = 1;
+ }
+ }
+ output(code_eof);
+ output_flush();
+}
+
+/*-----------------------------------------------------------------------
+ *
+ * End of miGIF section - See copyright notice at start of section.
+ *
+ *-----------------------------------------------------------------------
+*/
+
+/******************************************************************************
+ *
+ * GIF Specific routines
+ *
+ ******************************************************************************/
+
+/*
+ * Number of characters so far in this 'packet'
+ */
+static int a_count;
+
+/*
+ * Set up the 'byte output' routine
+ */
+
+/* UNUSED
+* static void
+* char_init(void)
+* {
+* a_count = 0;
+* }
+*/
+
+/*
+ * Define the storage for the packet accumulator
+ */
+
+/* UNUSED static char accum[ 256 ]; */
+
+static void init_statics(void) {
+ /* Some of these are properly initialized later. What I'm doing
+ here is making sure code that depends on C's initialization
+ of statics doesn't break when the code gets called more
+ than once. */
+ Width = 0;
+ Height = 0;
+ curx = 0;
+ cury = 0;
+ CountDown = 0;
+ Pass = 0;
+ Interlace = 0;
+ a_count = 0;
+}
+
+
+/* +-------------------------------------------------------------------+ */
+/* | Copyright 1990, 1991, 1993, David Koblas. (koblas@netcom.com) | */
+/* | Permission to use, copy, modify, and distribute this software | */
+/* | and its documentation for any purpose and without fee is hereby | */
+/* | granted, provided that the above copyright notice appear in all | */
+/* | copies and that both that copyright notice and this permission | */
+/* | notice appear in supporting documentation. This software is | */
+/* | provided "as is" without express or implied warranty. | */
+/* +-------------------------------------------------------------------+ */
+
diff --git a/graphics/gd2/files/gd_gif_in.c b/graphics/gd2/files/gd_gif_in.c
new file mode 100644
index 000000000000..e600b804703f
--- /dev/null
+++ b/graphics/gd2/files/gd_gif_in.c
@@ -0,0 +1,573 @@
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include "gd.h"
+
+/* Used only when debugging GIF compression code */
+/* #define DEBUGGING_ENVARS */
+
+#ifdef DEBUGGING_ENVARS
+
+static int verbose_set = 0;
+static int verbose;
+#define VERBOSE (verbose_set?verbose:set_verbose())
+
+static int set_verbose(void)
+{
+ verbose = !!getenv("GIF_VERBOSE");
+ verbose_set = 1;
+ return(verbose);
+}
+
+#else
+
+#define VERBOSE 0
+
+#endif
+
+
+#define MAXCOLORMAPSIZE 256
+
+#define TRUE 1
+#define FALSE 0
+
+#define CM_RED 0
+#define CM_GREEN 1
+#define CM_BLUE 2
+
+#define MAX_LWZ_BITS 12
+
+#define INTERLACE 0x40
+#define LOCALCOLORMAP 0x80
+#define BitSet(byte, bit) (((byte) & (bit)) == (bit))
+
+#define ReadOK(file,buffer,len) (gdGetBuf(buffer, len, file) != 0)
+
+#define LM_to_uint(a,b) (((b)<<8)|(a))
+
+/* We may eventually want to use this information, but def it out for now */
+#if 0
+static struct {
+ unsigned int Width;
+ unsigned int Height;
+ unsigned char ColorMap[3][MAXCOLORMAPSIZE];
+ unsigned int BitPixel;
+ unsigned int ColorResolution;
+ unsigned int Background;
+ unsigned int AspectRatio;
+} GifScreen;
+#endif
+
+static struct {
+ int transparent;
+ int delayTime;
+ int inputFlag;
+ int disposal;
+} Gif89 = { -1, -1, -1, 0 };
+
+static int ReadColorMap (gdIOCtx *fd, int number, unsigned char (*buffer)[256]);
+static int DoExtension (gdIOCtx *fd, int label, int *Transparent);
+static int GetDataBlock (gdIOCtx *fd, unsigned char *buf);
+static int GetCode (gdIOCtx *fd, int code_size, int flag);
+static int LWZReadByte (gdIOCtx *fd, int flag, int input_code_size);
+
+static void ReadImage (gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap)[256], int interlace); /*1.4//, int ignore); */
+
+int ZeroDataBlock;
+
+gdImagePtr gdImageCreateFromGifSource(gdSourcePtr inSource)
+{
+ gdIOCtx *in = gdNewSSCtx(inSource, NULL);
+ gdImagePtr im;
+
+ im = gdImageCreateFromGifCtx(in);
+
+ in->free(in);
+
+ return im;
+}
+
+gdImagePtr
+gdImageCreateFromGif(FILE *fdFile)
+{
+ gdIOCtx *fd = gdNewFileCtx(fdFile);
+ gdImagePtr im = 0;
+
+ im = gdImageCreateFromGifCtx(fd);
+
+ fd->free(fd);
+
+ return im;
+}
+
+gdImagePtr
+gdImageCreateFromGifCtx(gdIOCtxPtr fd)
+{
+/* 1.4 int imageNumber; */
+ int BitPixel;
+ int ColorResolution;
+ int Background;
+ int AspectRatio;
+ int Transparent = (-1);
+ unsigned char buf[16];
+ unsigned char c;
+ unsigned char ColorMap[3][MAXCOLORMAPSIZE];
+ unsigned char localColorMap[3][MAXCOLORMAPSIZE];
+ int imw, imh;
+ int useGlobalColormap;
+ int bitPixel;
+ int i;
+ /*1.4//int imageCount = 0; */
+ char version[4];
+
+ gdImagePtr im = 0;
+ ZeroDataBlock = FALSE;
+
+ /*1.4//imageNumber = 1; */
+ if (! ReadOK(fd,buf,6)) {
+ return 0;
+ }
+ if (strncmp((char *)buf,"GIF",3) != 0) {
+ return 0;
+ }
+ strncpy(version, (char *)buf + 3, 3);
+ version[3] = '\0';
+
+ if ((strcmp(version, "87a") != 0) && (strcmp(version, "89a") != 0)) {
+ return 0;
+ }
+ if (! ReadOK(fd,buf,7)) {
+ return 0;
+ }
+ BitPixel = 2<<(buf[4]&0x07);
+ ColorResolution = (int) (((buf[4]&0x70)>>3)+1);
+ Background = buf[5];
+ AspectRatio = buf[6];
+
+ if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
+ if (ReadColorMap(fd, BitPixel, ColorMap)) {
+ return 0;
+ }
+ }
+ for (;;) {
+ if (! ReadOK(fd,&c,1)) {
+ return 0;
+ }
+ if (c == ';') { /* GIF terminator */
+ goto terminated;
+ }
+
+ if (c == '!') { /* Extension */
+ if (! ReadOK(fd,&c,1)) {
+ return 0;
+ }
+ DoExtension(fd, c, &Transparent);
+ continue;
+ }
+
+ if (c != ',') { /* Not a valid start character */
+ continue;
+ }
+
+ /*1.4//++imageCount; */
+
+ if (! ReadOK(fd,buf,9)) {
+ return 0;
+ }
+
+ 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) {
+ if (ReadColorMap(fd, bitPixel, localColorMap)) {
+ return 0;
+ }
+ ReadImage(im, fd, imw, imh, localColorMap,
+ BitSet(buf[8], INTERLACE));
+ /*1.4//imageCount != imageNumber); */
+ } else {
+ ReadImage(im, fd, imw, imh,
+ ColorMap,
+ BitSet(buf[8], INTERLACE));
+ /*1.4//imageCount != imageNumber); */
+ }
+ if (Transparent != (-1)) {
+ gdImageColorTransparent(im, Transparent);
+ }
+ goto terminated;
+ }
+
+terminated:
+ /* Terminator before any image was declared! */
+ if (!im) {
+ return 0;
+ }
+ /* Check for open colors at the end, so
+ we can reduce colorsTotal and ultimately
+ BitsPerPixel */
+ for (i=((im->colorsTotal-1)); (i>=0); i--) {
+ if (im->open[i]) {
+ im->colorsTotal--;
+ } else {
+ break;
+ }
+ }
+ return im;
+}
+
+static int
+ReadColorMap(gdIOCtx *fd, int number, unsigned char (*buffer)[256])
+{
+ int i;
+ unsigned char rgb[3];
+
+
+ for (i = 0; i < number; ++i) {
+ if (! ReadOK(fd, rgb, sizeof(rgb))) {
+ return TRUE;
+ }
+ buffer[CM_RED][i] = rgb[0] ;
+ buffer[CM_GREEN][i] = rgb[1] ;
+ buffer[CM_BLUE][i] = rgb[2] ;
+ }
+
+
+ return FALSE;
+}
+
+static int
+DoExtension(gdIOCtx *fd, int label, int *Transparent)
+{
+ static unsigned char buf[256];
+
+ switch (label) {
+ case 0xf9: /* Graphic Control Extension */
+ (void) GetDataBlock(fd, (unsigned char*) buf);
+ Gif89.disposal = (buf[0] >> 2) & 0x7;
+ Gif89.inputFlag = (buf[0] >> 1) & 0x1;
+ Gif89.delayTime = LM_to_uint(buf[1],buf[2]);
+ if ((buf[0] & 0x1) != 0)
+ *Transparent = buf[3];
+
+ while (GetDataBlock(fd, (unsigned char*) buf) != 0)
+ ;
+ return FALSE;
+ default:
+ break;
+ }
+ while (GetDataBlock(fd, (unsigned char*) buf) != 0)
+ ;
+
+ return FALSE;
+}
+
+static int
+GetDataBlock_(gdIOCtx *fd, unsigned char *buf)
+{
+ unsigned char count;
+
+ if (! ReadOK(fd,&count,1)) {
+ return -1;
+ }
+
+ ZeroDataBlock = count == 0;
+
+ if ((count != 0) && (! ReadOK(fd, buf, count))) {
+ return -1;
+ }
+
+ return count;
+}
+
+static int
+GetDataBlock(gdIOCtx *fd, unsigned char *buf)
+{
+ int rv;
+ int i;
+
+ rv = GetDataBlock_(fd,buf);
+ if (VERBOSE)
+ { printf("[GetDataBlock returning %d",rv);
+ if (rv > 0)
+ { printf(":");
+ for (i=0;i<rv;i++) printf(" %02x",buf[i]);
+ }
+ printf("]\n");
+ }
+ return(rv);
+}
+
+static int
+GetCode_(gdIOCtx *fd, int code_size, int flag)
+{
+ static unsigned char buf[280];
+ static int curbit, lastbit, done, last_byte;
+ int i, j, ret;
+ unsigned char count;
+
+ if (flag) {
+ curbit = 0;
+ lastbit = 0;
+ done = FALSE;
+ return 0;
+ }
+
+ if ( (curbit+code_size) >= lastbit) {
+ if (done) {
+ if (curbit >= lastbit) {
+ /* Oh well */
+ }
+ return -1;
+ }
+ buf[0] = buf[last_byte-2];
+ buf[1] = buf[last_byte-1];
+
+ if ((count = GetDataBlock(fd, &buf[2])) == 0)
+ done = TRUE;
+
+ last_byte = 2 + count;
+ curbit = (curbit - lastbit) + 16;
+ 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;
+
+ curbit += code_size;
+ return ret;
+}
+
+static int
+GetCode(gdIOCtx *fd, int code_size, int flag)
+{
+ int rv;
+
+ rv = GetCode_(fd,code_size,flag);
+ 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)
+{
+ 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;
+
+ 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);
+
+ fresh = TRUE;
+
+ for (i = 0; i < clear_code; ++i) {
+ table[0][i] = 0;
+ table[1][i] = i;
+ }
+ for (; i < (1<<MAX_LWZ_BITS); ++i)
+ table[0][i] = table[1][0] = 0;
+
+ sp = stack;
+
+ return 0;
+ } else if (fresh) {
+ fresh = FALSE;
+ do {
+ firstcode = oldcode =
+ GetCode(fd, code_size, FALSE);
+ } while (firstcode == clear_code);
+ return firstcode;
+ }
+
+ if (sp > stack)
+ return *--sp;
+
+ while ((code = GetCode(fd, code_size, FALSE)) >= 0) {
+ if (code == clear_code) {
+ for (i = 0; i < clear_code; ++i) {
+ table[0][i] = 0;
+ table[1][i] = i;
+ }
+ for (; i < (1<<MAX_LWZ_BITS); ++i)
+ table[0][i] = table[1][i] = 0;
+ code_size = set_code_size+1;
+ max_code_size = 2*clear_code;
+ max_code = clear_code+2;
+ sp = stack;
+ firstcode = oldcode =
+ GetCode(fd, code_size, FALSE);
+ return firstcode;
+ } else if (code == end_code) {
+ int count;
+ unsigned char buf[260];
+
+ if (ZeroDataBlock)
+ return -2;
+
+ while ((count = GetDataBlock(fd, buf)) > 0)
+ ;
+
+ if (count != 0)
+ return -2;
+ }
+
+ incode = code;
+
+ if (sp == (stack + STACK_SIZE)) {
+ /* Bad compressed data stream */
+ return -1;
+ }
+
+ if (code >= max_code) {
+ *sp++ = firstcode;
+ code = oldcode;
+ }
+
+ while (code >= clear_code) {
+ if (sp == (stack + STACK_SIZE)) {
+ /* Bad compressed data stream */
+ return -1;
+ }
+ *sp++ = table[1][code];
+ if (code == table[0][code]) {
+ /* Oh well */
+ }
+ code = table[0][code];
+ }
+
+ *sp++ = firstcode = table[1][code];
+
+ if ((code = max_code) <(1<<MAX_LWZ_BITS)) {
+ table[0][code] = oldcode;
+ table[1][code] = firstcode;
+ ++max_code;
+ if ((max_code >= max_code_size) &&
+ (max_code_size < (1<<MAX_LWZ_BITS))) {
+ max_code_size *= 2;
+ ++code_size;
+ }
+ }
+
+ oldcode = incode;
+
+ if (sp > stack)
+ return *--sp;
+ }
+ return code;
+}
+
+static int
+LWZReadByte(gdIOCtx *fd, int flag, int input_code_size)
+{
+ int rv;
+
+ rv = LWZReadByte_(fd,flag,input_code_size);
+ if (VERBOSE) printf("[LWZReadByte(,%d,%d) returning %d]\n",flag,input_code_size,rv);
+ return(rv);
+}
+
+static void
+ReadImage(gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap)[256], int interlace) /*1.4//, int ignore) */
+{
+ unsigned char c;
+ int v;
+ int xpos = 0, ypos = 0, pass = 0;
+ int i;
+ /* Stash the color map into the image */
+ for (i=0; (i<gdMaxColors); i++) {
+ im->red[i] = cmap[CM_RED][i];
+ im->green[i] = cmap[CM_GREEN][i];
+ im->blue[i] = cmap[CM_BLUE][i];
+ im->open[i] = 1;
+ }
+ /* 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) < 0) {
+ return;
+ }
+
+ /*
+ ** If this is an "uninteresting picture" ignore it.
+ ** REMOVED For 1.4
+ */
+ /*if (ignore) { */
+ /* while (LWZReadByte(fd, FALSE, c) >= 0) */
+ /* ; */
+ /* return; */
+ /*} */
+
+ while ((v = LWZReadByte(fd,FALSE,c)) >= 0 ) {
+ /* This how we recognize which colors are actually used. */
+ if (im->open[v]) {
+ im->open[v] = 0;
+ }
+ gdImageSetPixel(im, xpos, ypos, v);
+ ++xpos;
+ if (xpos == len) {
+ xpos = 0;
+ if (interlace) {
+ switch (pass) {
+ case 0:
+ case 1:
+ ypos += 8; break;
+ case 2:
+ ypos += 4; break;
+ case 3:
+ ypos += 2; break;
+ }
+
+ if (ypos >= height) {
+ ++pass;
+ switch (pass) {
+ case 1:
+ ypos = 4; break;
+ case 2:
+ ypos = 2; break;
+ case 3:
+ ypos = 1; break;
+ default:
+ goto fini;
+ }
+ }
+ } else {
+ ++ypos;
+ }
+ }
+ if (ypos >= height)
+ break;
+ }
+
+fini:
+ if (LWZReadByte(fd,FALSE,c)>=0) {
+ /* Ignore extra */
+ }
+}
+
diff --git a/graphics/gd2/files/gd_gif_out.c b/graphics/gd2/files/gd_gif_out.c
new file mode 100644
index 000000000000..7ab2f21f8ca2
--- /dev/null
+++ b/graphics/gd2/files/gd_gif_out.c
@@ -0,0 +1,46 @@
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include "gd.h"
+
+/*
+** Wrapper functions for GIF output.
+*/
+
+#define LZW_LICENCED
+
+void gdImageGifToSink(gdImagePtr im, gdSinkPtr outSink)
+{
+ gdIOCtx *out = gdNewSSCtx(NULL,outSink);
+ gdImageGifCtx(im, out);
+ out->free(out);
+}
+
+void gdImageGifCtx(gdImagePtr im, gdIOCtx *out)
+{
+#ifdef LZW_LICENCED
+ gdImageLzwCtx(im, out);
+#else
+ gdImageBigGifCtx(im, out);
+#endif
+}
+
+void gdImageGif(gdImagePtr im, FILE *outFile)
+{
+#ifdef LZW_LICENCED
+ gdImageLzw(im, outFile);
+#else
+ gdImageBigGif(im, outFile);
+#endif
+}
+
+void* gdImageGifPtr(gdImagePtr im, int *size)
+{
+#ifdef LZW_LICENCED
+ return gdImageLzwPtr(im, size);
+#else
+ return gdImageBigGifPtr(im, size);
+#endif
+}
+
diff --git a/graphics/gd2/files/gd_lzw_out.c b/graphics/gd2/files/gd_lzw_out.c
new file mode 100644
index 000000000000..8c58bdfd24e3
--- /dev/null
+++ b/graphics/gd2/files/gd_lzw_out.c
@@ -0,0 +1,795 @@
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <stdlib.h>
+#include "gd.h"
+
+/* Code drawn from ppmtogif.c, from the pbmplus package
+**
+** Based on GIFENCOD by David Rowley <mgardi@watdscu.waterloo.edu>. A
+** Lempel-Zim compression based on "compress".
+**
+** Modified by Marcel Wijkstra <wijkstra@fwi.uva.nl>
+**
+** Copyright (C) 1989 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+**
+** The Graphics Interchange Format(c) is the Copyright property of
+** CompuServe Incorporated. GIF(sm) is a Service Mark property of
+** CompuServe Incorporated.
+*/
+
+/*
+ * a code_int must be able to hold 2**GIFBITS values of type int, and also -1
+ */
+typedef int code_int;
+
+#ifdef SIGNED_COMPARE_SLOW
+typedef unsigned long int count_int;
+typedef unsigned short int count_short;
+#else /*SIGNED_COMPARE_SLOW*/
+typedef long int count_int;
+#endif /*SIGNED_COMPARE_SLOW*/
+
+static int colorstobpp(int colors);
+static void BumpPixel (void);
+static int GIFNextPixel (gdImagePtr im);
+static void GIFEncode (gdIOCtx *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im);
+/*static void Putword (int w, gdIOCtx *fp); */
+static void compress (int init_bits, gdIOCtx *outfile, gdImagePtr im);
+static void output (code_int code);
+static void cl_block (void);
+static void cl_hash (register count_int hsize);
+static void char_init (void);
+static void char_out (int c);
+static void flush_char (void);
+/* Allows for reuse */
+static void init_statics(void);
+
+void gdImageLzwCtx(gdImagePtr im, gdIOCtx *out)
+{
+ int interlace, transparent, BitsPerPixel;
+
+ interlace = im->interlace;
+ transparent = im->transparent;
+
+ BitsPerPixel = colorstobpp(im->colorsTotal);
+ /* Clear any old values in statics strewn through the GIF code */
+ init_statics();
+ /* All set, let's do it. */
+ GIFEncode(
+ out, im->sx, im->sy, interlace, 0, transparent, BitsPerPixel,
+ im->red, im->green, im->blue, im);
+}
+
+void gdImageLzw(gdImagePtr im, FILE *outFile)
+{
+ gdIOCtx *out = gdNewFileCtx(outFile);
+ gdImageLzwCtx(im, out);
+ out->free(out);
+}
+
+void* gdImageLzwPtr(gdImagePtr im, int *size)
+{
+ void *rv;
+ gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
+ gdImageLzwCtx(im, out);
+ rv = gdDPExtractData(out,size);
+ out->free(out);
+ return rv;
+}
+
+
+
+static int
+colorstobpp(int colors)
+{
+ int bpp = 0;
+
+ if ( colors <= 2 )
+ bpp = 1;
+ else if ( colors <= 4 )
+ bpp = 2;
+ else if ( colors <= 8 )
+ bpp = 3;
+ else if ( colors <= 16 )
+ bpp = 4;
+ else if ( colors <= 32 )
+ bpp = 5;
+ else if ( colors <= 64 )
+ bpp = 6;
+ else if ( colors <= 128 )
+ bpp = 7;
+ else if ( colors <= 256 )
+ bpp = 8;
+ return bpp;
+ }
+
+/*****************************************************************************
+ *
+ * GIFENCODE.C - GIF Image compression interface
+ *
+ * GIFEncode( FName, GHeight, GWidth, GInterlace, Background, Transparent,
+ * BitsPerPixel, Red, Green, Blue, gdImagePtr )
+ *
+ *****************************************************************************/
+
+#define TRUE 1
+#define FALSE 0
+
+static int Width, Height;
+static int curx, cury;
+static long CountDown;
+static int Pass = 0;
+static int Interlace;
+
+/*
+ * Bump the 'curx' and 'cury' to point to the next pixel
+ */
+static void
+BumpPixel(void)
+{
+ /*
+ * Bump the current X position
+ */
+ ++curx;
+
+ /*
+ * If we are at the end of a scan line, set curx back to the beginning
+ * If we are interlaced, bump the cury to the appropriate spot,
+ * otherwise, just increment it.
+ */
+ if( curx == Width ) {
+ curx = 0;
+
+ if( !Interlace )
+ ++cury;
+ else {
+ switch( Pass ) {
+
+ case 0:
+ cury += 8;
+ if( cury >= Height ) {
+ ++Pass;
+ cury = 4;
+ }
+ break;
+
+ case 1:
+ cury += 8;
+ if( cury >= Height ) {
+ ++Pass;
+ cury = 2;
+ }
+ break;
+
+ case 2:
+ cury += 4;
+ if( cury >= Height ) {
+ ++Pass;
+ cury = 1;
+ }
+ break;
+
+ case 3:
+ cury += 2;
+ break;
+ }
+ }
+ }
+}
+
+/*
+ * Return the next pixel from the image
+ */
+static int
+GIFNextPixel(gdImagePtr im)
+{
+ int r;
+
+ if( CountDown == 0 )
+ return EOF;
+
+ --CountDown;
+
+ r = gdImageGetPixel(im, curx, cury);
+
+ BumpPixel();
+
+ return r;
+}
+
+/* public */
+
+static void
+GIFEncode(gdIOCtx *fp, int GWidth, int GHeight, int GInterlace, int Background, int Transparent, int BitsPerPixel, int *Red, int *Green, int *Blue, gdImagePtr im)
+{
+ int B;
+ int RWidth, RHeight;
+ int LeftOfs, TopOfs;
+ int Resolution;
+ int ColorMapSize;
+ int InitCodeSize;
+ int i;
+
+ Interlace = GInterlace;
+
+ ColorMapSize = 1 << BitsPerPixel;
+
+ RWidth = Width = GWidth;
+ RHeight = Height = GHeight;
+ LeftOfs = TopOfs = 0;
+
+ Resolution = BitsPerPixel;
+
+ /*
+ * Calculate number of bits we are expecting
+ */
+ CountDown = (long)Width * (long)Height;
+
+ /*
+ * Indicate which pass we are on (if interlace)
+ */
+ Pass = 0;
+
+ /*
+ * The initial code size
+ */
+ if( BitsPerPixel <= 1 )
+ InitCodeSize = 2;
+ else
+ InitCodeSize = BitsPerPixel;
+
+ /*
+ * Set up the current x and y position
+ */
+ curx = cury = 0;
+
+ /*
+ * Write the Magic header
+ */
+ gdPutBuf( Transparent < 0 ? "GIF87a" : "GIF89a", 6, fp );
+
+ /*
+ * Write out the screen width and height
+ */
+ Putword( RWidth, fp );
+ Putword( RHeight, fp );
+
+ /*
+ * Indicate that there is a global colour map
+ */
+ B = 0x80; /* Yes, there is a color map */
+
+ /*
+ * OR in the resolution
+ */
+ B |= (Resolution - 1) << 5;
+
+ /*
+ * OR in the Bits per Pixel
+ */
+ B |= (BitsPerPixel - 1);
+
+ /*
+ * Write it out
+ */
+ gdPutC( B, fp );
+
+ /*
+ * Write out the Background colour
+ */
+ gdPutC( Background, fp );
+
+ /*
+ * Byte of 0's (future expansion)
+ */
+ gdPutC( 0, fp );
+
+ /*
+ * Write out the Global Colour Map
+ */
+ for( i=0; i<ColorMapSize; ++i ) {
+ gdPutC( Red[i], fp );
+ gdPutC( Green[i], fp );
+ gdPutC( Blue[i], fp );
+ }
+
+ /*
+ * Write out extension for transparent colour index, if necessary.
+ */
+ if ( Transparent >= 0 ) {
+ gdPutC( '!', fp );
+ gdPutC( 0xf9, fp );
+ gdPutC( 4, fp );
+ gdPutC( 1, fp );
+ gdPutC( 0, fp );
+ gdPutC( 0, fp );
+ gdPutC( (unsigned char) Transparent, fp );
+ gdPutC( 0, fp );
+ }
+
+ /*
+ * Write an Image separator
+ */
+ gdPutC( ',', fp );
+
+ /*
+ * Write the Image header
+ */
+
+ Putword( LeftOfs, fp );
+ Putword( TopOfs, fp );
+ Putword( Width, fp );
+ Putword( Height, fp );
+
+ /*
+ * Write out whether or not the image is interlaced
+ */
+ if( Interlace )
+ gdPutC( 0x40, fp );
+ else
+ gdPutC( 0x00, fp );
+
+ /*
+ * Write out the initial code size
+ */
+ gdPutC( InitCodeSize, fp );
+
+ /*
+ * Go and actually compress the data
+ */
+ compress( InitCodeSize+1, fp, im );
+
+ /*
+ * Write out a Zero-length packet (to end the series)
+ */
+ gdPutC( 0, fp );
+
+ /*
+ * Write the GIF file terminator
+ */
+ gdPutC( ';', fp );
+}
+
+/* */
+/* * Write out a word to the GIF file */
+/* */
+/*static void */
+/*Putword(int w, FILE *fp) */
+/*{ */
+/* fputc( w & 0xff, fp ); */
+/* fputc( (w / 256) & 0xff, fp ); */
+/*} */
+
+
+/***************************************************************************
+ *
+ * GIFCOMPR.C - GIF Image compression routines
+ *
+ * Lempel-Ziv compression based on 'compress'. GIF modifications by
+ * David Rowley (mgardi@watdcsu.waterloo.edu)
+ *
+ ***************************************************************************/
+
+/*
+ * General DEFINEs
+ */
+
+#define GIFBITS 12
+
+#define HSIZE 5003 /* 80% occupancy */
+
+#ifdef NO_UCHAR
+ typedef char char_type;
+#else /*NO_UCHAR*/
+ typedef unsigned char char_type;
+#endif /*NO_UCHAR*/
+
+/*
+ *
+ * GIF Image compression - modified 'compress'
+ *
+ * Based on: compress.c - File compression ala IEEE Computer, June 1984.
+ *
+ * By Authors: Spencer W. Thomas (decvax!harpo!utah-cs!utah-gr!thomas)
+ * Jim McKie (decvax!mcvax!jim)
+ * Steve Davies (decvax!vax135!petsd!peora!srd)
+ * Ken Turkowski (decvax!decwrl!turtlevax!ken)
+ * James A. Woods (decvax!ihnp4!ames!jaw)
+ * Joe Orost (decvax!vax135!petsd!joe)
+ *
+ */
+#include <ctype.h>
+
+#define ARGVAL() (*++(*argv) || (--argc && *++argv))
+
+static int n_bits; /* number of bits/code */
+static int maxbits = GIFBITS; /* user settable max # bits/code */
+static code_int maxcode; /* maximum code, given n_bits */
+static code_int maxmaxcode = (code_int)1 << GIFBITS; /* should NEVER generate this code */
+#ifdef COMPATIBLE /* But wrong! */
+# define MAXCODE(n_bits) ((code_int) 1 << (n_bits) - 1)
+#else /*COMPATIBLE*/
+# define MAXCODE(n_bits) (((code_int) 1 << (n_bits)) - 1)
+#endif /*COMPATIBLE*/
+
+static count_int htab [HSIZE];
+static unsigned short codetab [HSIZE];
+#define HashTabOf(i) htab[i]
+#define CodeTabOf(i) codetab[i]
+
+static code_int hsize = HSIZE; /* for dynamic table sizing */
+
+/*
+ * To save much memory, we overlay the table used by compress() with those
+ * used by decompress(). The tab_prefix table is the same size and type
+ * as the codetab. The tab_suffix table needs 2**GIFBITS characters. We
+ * get this from the beginning of htab. The output stack uses the rest
+ * of htab, and contains characters. There is plenty of room for any
+ * possible stack (stack used to be 8000 characters).
+ */
+
+#define tab_prefixof(i) CodeTabOf(i)
+#define tab_suffixof(i) ((char_type*)(htab))[i]
+#define de_stack ((char_type*)&tab_suffixof((code_int)1<<GIFBITS))
+
+static code_int free_ent = 0; /* first unused entry */
+
+/*
+ * block compression parameters -- after all codes are used up,
+ * and compression rate changes, start over.
+ */
+static int clear_flg = 0;
+
+static int offset;
+static long int in_count = 1; /* length of input */
+static long int out_count = 0; /* # of codes output (for debugging) */
+
+/*
+ * compress stdin to stdout
+ *
+ * Algorithm: use open addressing double hashing (no chaining) on the
+ * prefix code / next character combination. We do a variant of Knuth's
+ * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
+ * secondary probe. Here, the modular division first probe is gives way
+ * to a faster exclusive-or manipulation. Also do block compression with
+ * an adaptive reset, whereby the code table is cleared when the compression
+ * ratio decreases, but after the table fills. The variable-length output
+ * codes are re-sized at this point, and a special CLEAR code is generated
+ * for the decompressor. Late addition: construct the table according to
+ * file size for noticeable speed improvement on small files. Please direct
+ * questions about this implementation to ames!jaw.
+ */
+
+static int g_init_bits;
+static gdIOCtx* g_outfile;
+
+static int ClearCode;
+static int EOFCode;
+
+static void
+compress(int init_bits, gdIOCtx *outfile, gdImagePtr im)
+{
+ register long fcode;
+ register code_int i /* = 0 */;
+ register int c;
+ register code_int ent;
+ register code_int disp;
+ register code_int hsize_reg;
+ register int hshift;
+
+ /*
+ * Set up the globals: g_init_bits - initial number of bits
+ * g_outfile - pointer to output file
+ */
+ g_init_bits = init_bits;
+ g_outfile = outfile;
+
+ /*
+ * Set up the necessary values
+ */
+ offset = 0;
+ out_count = 0;
+ clear_flg = 0;
+ in_count = 1;
+ maxcode = MAXCODE(n_bits = g_init_bits);
+
+ ClearCode = (1 << (init_bits - 1));
+ EOFCode = ClearCode + 1;
+ free_ent = ClearCode + 2;
+
+ char_init();
+
+ ent = GIFNextPixel( im );
+
+ hshift = 0;
+ for ( fcode = (long) hsize; fcode < 65536L; fcode *= 2L )
+ ++hshift;
+ hshift = 8 - hshift; /* set hash code range bound */
+
+ hsize_reg = hsize;
+ cl_hash( (count_int) hsize_reg); /* clear hash table */
+
+ output( (code_int)ClearCode );
+
+#ifdef SIGNED_COMPARE_SLOW
+ while ( (c = GIFNextPixel( im )) != (unsigned) EOF ) {
+#else /*SIGNED_COMPARE_SLOW*/
+ while ( (c = GIFNextPixel( im )) != EOF ) { /* } */
+#endif /*SIGNED_COMPARE_SLOW*/
+
+ ++in_count;
+
+ fcode = (long) (((long) c << maxbits) + ent);
+ i = (((code_int)c << hshift) ^ ent); /* xor hashing */
+
+ if ( HashTabOf (i) == fcode ) {
+ ent = CodeTabOf (i);
+ continue;
+ } else if ( (long)HashTabOf (i) < 0 ) /* empty slot */
+ goto nomatch;
+ disp = hsize_reg - i; /* secondary hash (after G. Knott) */
+ if ( i == 0 )
+ disp = 1;
+probe:
+ if ( (i -= disp) < 0 )
+ i += hsize_reg;
+
+ if ( HashTabOf (i) == fcode ) {
+ ent = CodeTabOf (i);
+ continue;
+ }
+ if ( (long)HashTabOf (i) > 0 )
+ goto probe;
+nomatch:
+ output ( (code_int) ent );
+ ++out_count;
+ ent = c;
+#ifdef SIGNED_COMPARE_SLOW
+ if ( (unsigned) free_ent < (unsigned) maxmaxcode) {
+#else /*SIGNED_COMPARE_SLOW*/
+ if ( free_ent < maxmaxcode ) { /* } */
+#endif /*SIGNED_COMPARE_SLOW*/
+ CodeTabOf (i) = free_ent++; /* code -> hashtable */
+ HashTabOf (i) = fcode;
+ } else
+ cl_block();
+ }
+ /*
+ * Put out the final code.
+ */
+ output( (code_int)ent );
+ ++out_count;
+ output( (code_int) EOFCode );
+}
+
+/*****************************************************************
+ * TAG( output )
+ *
+ * Output the given code.
+ * Inputs:
+ * code: A n_bits-bit integer. If == -1, then EOF. This assumes
+ * that n_bits =< (long)wordsize - 1.
+ * Outputs:
+ * Outputs code to the file.
+ * Assumptions:
+ * Chars are 8 bits long.
+ * Algorithm:
+ * Maintain a GIFBITS character long buffer (so that 8 codes will
+ * fit in it exactly). Use the VAX insv instruction to insert each
+ * code in turn. When the buffer fills up empty it and start over.
+ */
+
+static unsigned long cur_accum = 0;
+static int cur_bits = 0;
+
+static unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
+ 0x001F, 0x003F, 0x007F, 0x00FF,
+ 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
+ 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
+
+static void
+output(code_int code)
+{
+ cur_accum &= masks[ cur_bits ];
+
+ if( cur_bits > 0 )
+ cur_accum |= ((long)code << cur_bits);
+ else
+ cur_accum = code;
+
+ cur_bits += n_bits;
+
+ while( cur_bits >= 8 ) {
+ char_out( (unsigned int)(cur_accum & 0xff) );
+ cur_accum >>= 8;
+ cur_bits -= 8;
+ }
+
+ /*
+ * If the next entry is going to be too big for the code size,
+ * then increase it, if possible.
+ */
+ if ( free_ent > maxcode || clear_flg ) {
+
+ if( clear_flg ) {
+
+ maxcode = MAXCODE (n_bits = g_init_bits);
+ clear_flg = 0;
+
+ } else {
+
+ ++n_bits;
+ if ( n_bits == maxbits )
+ maxcode = maxmaxcode;
+ else
+ maxcode = MAXCODE(n_bits);
+ }
+ }
+
+ if( code == EOFCode ) {
+ /*
+ * At EOF, write the rest of the buffer.
+ */
+ while( cur_bits > 0 ) {
+ char_out( (unsigned int)(cur_accum & 0xff) );
+ cur_accum >>= 8;
+ cur_bits -= 8;
+ }
+
+ flush_char();
+
+/* fflush( g_outfile ); */
+/* */
+/* if( ferror( g_outfile ) ) */
+/* return; */
+ }
+}
+
+/*
+ * Clear out the hash table
+ */
+static void
+cl_block (void) /* table clear for block compress */
+{
+
+ cl_hash ( (count_int) hsize );
+ free_ent = ClearCode + 2;
+ clear_flg = 1;
+
+ output( (code_int)ClearCode );
+}
+
+static void
+cl_hash(register count_int hsize) /* reset code table */
+
+{
+
+ register count_int *htab_p = htab+hsize;
+
+ register long i;
+ register long m1 = -1;
+
+ i = hsize - 16;
+ do { /* might use Sys V memset(3) here */
+ *(htab_p-16) = m1;
+ *(htab_p-15) = m1;
+ *(htab_p-14) = m1;
+ *(htab_p-13) = m1;
+ *(htab_p-12) = m1;
+ *(htab_p-11) = m1;
+ *(htab_p-10) = m1;
+ *(htab_p-9) = m1;
+ *(htab_p-8) = m1;
+ *(htab_p-7) = m1;
+ *(htab_p-6) = m1;
+ *(htab_p-5) = m1;
+ *(htab_p-4) = m1;
+ *(htab_p-3) = m1;
+ *(htab_p-2) = m1;
+ *(htab_p-1) = m1;
+ htab_p -= 16;
+ } while ((i -= 16) >= 0);
+
+ for ( i += 16; i > 0; --i )
+ *--htab_p = m1;
+}
+
+/******************************************************************************
+ *
+ * GIF Specific routines
+ *
+ ******************************************************************************/
+
+/*
+ * Number of characters so far in this 'packet'
+ */
+static int a_count;
+
+/*
+ * Set up the 'byte output' routine
+ */
+static void
+char_init(void)
+{
+ a_count = 0;
+}
+
+/*
+ * Define the storage for the packet accumulator
+ */
+static char accum[ 256 ];
+
+/*
+ * Add a character to the end of the current packet, and if it is 254
+ * characters, flush the packet to disk.
+ */
+static void
+char_out(int c)
+{
+ accum[ a_count++ ] = c;
+ if( a_count >= 254 )
+ flush_char();
+}
+
+/*
+ * Flush the packet to disk, and reset the accumulator
+ */
+static void
+flush_char(void)
+{
+ if( a_count > 0 ) {
+ gdPutC( a_count, g_outfile );
+ gdPutBuf( accum, a_count, g_outfile );
+ a_count = 0;
+ }
+}
+
+static void init_statics(void) {
+ /* Some of these are properly initialized later. What I'm doing
+ here is making sure code that depends on C's initialization
+ of statics doesn't break when the code gets called more
+ than once. */
+ Width = 0;
+ Height = 0;
+ curx = 0;
+ cury = 0;
+ CountDown = 0;
+ Pass = 0;
+ Interlace = 0;
+ a_count = 0;
+ cur_accum = 0;
+ cur_bits = 0;
+ g_init_bits = 0;
+ g_outfile = 0;
+ ClearCode = 0;
+ EOFCode = 0;
+ free_ent = 0;
+ clear_flg = 0;
+ offset = 0;
+ in_count = 1;
+ out_count = 0;
+ hsize = HSIZE;
+ n_bits = 0;
+ maxbits = GIFBITS;
+ maxcode = 0;
+ maxmaxcode = (code_int)1 << GIFBITS;
+}
+
+
+/* +-------------------------------------------------------------------+ */
+/* | Copyright 1990, 1991, 1993, David Koblas. (koblas@netcom.com) | */
+/* | Permission to use, copy, modify, and distribute this software | */
+/* | and its documentation for any purpose and without fee is hereby | */
+/* | granted, provided that the above copyright notice appear in all | */
+/* | copies and that both that copyright notice and this permission | */
+/* | notice appear in supporting documentation. This software is | */
+/* | provided "as is" without express or implied warranty. | */
+/* +-------------------------------------------------------------------+ */
diff --git a/graphics/gd2/files/gdcmpgif.c b/graphics/gd2/files/gdcmpgif.c
new file mode 100644
index 000000000000..13c243014d2b
--- /dev/null
+++ b/graphics/gd2/files/gdcmpgif.c
@@ -0,0 +1,85 @@
+#include <stdio.h>
+#include <unistd.h> /* For unlink function */
+#include "gd.h"
+
+/* A short program which converts a .png file into a .gd file, for
+ your convenience in creating images on the fly from a
+ basis image that must be loaded quickly. The .gd format
+ is not intended to be a general-purpose format. */
+
+void CompareImages(char *msg, gdImagePtr im1, gdImagePtr im2);
+
+
+int main(int argc, char **argv)
+{
+ gdImagePtr im1, im2;
+ FILE *in;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: gdcmpgif filename.gif filename.gif\n");
+ exit(1);
+ }
+ in = fopen(argv[1], "rb");
+ if (!in) {
+ fprintf(stderr, "Input file does not exist!\n");
+ exit(1);
+ }
+ im1 = gdImageCreateFromGif(in);
+ fclose(in);
+
+ if (!im1) {
+ fprintf(stderr, "Input is not in GIF format!\n");
+ exit(1);
+ }
+
+ in = fopen(argv[2], "rb");
+ if (!in) {
+ fprintf(stderr, "Input file 2 does not exist!\n");
+ exit(1);
+ }
+ im2 = gdImageCreateFromGif(in);
+ fclose(in);
+
+ if (!im2) {
+ fprintf(stderr, "Input 2 is not in GIF format!\n");
+ exit(1);
+ }
+
+ CompareImages("gdcmpgif", im1, im2);
+
+ gdImageDestroy(im1);
+ gdImageDestroy(im2);
+
+ return 0;
+}
+
+void CompareImages(char *msg, gdImagePtr im1, gdImagePtr im2)
+{
+ int cmpRes;
+
+ cmpRes = gdImageCompare(im1, im2);
+
+ if (cmpRes & GD_CMP_IMAGE) {
+ printf("%%%s: ERROR images differ: BAD\n",msg);
+ } else if (cmpRes != 0) {
+ printf("%%%s: WARNING images differ: WARNING - Probably OK\n",msg);
+ } else {
+ printf("%%%s: OK\n",msg);
+ return;
+ }
+
+ if (cmpRes & (GD_CMP_SIZE_X + GD_CMP_SIZE_Y)) {
+ printf("-%s: INFO image sizes differ\n",msg);
+ }
+
+ if (cmpRes & GD_CMP_NUM_COLORS) {
+ printf("-%s: INFO number of pallette entries differ %d Vs. %d\n",msg,
+ im1->colorsTotal, im2->colorsTotal);
+ }
+
+ if (cmpRes & GD_CMP_COLOR) {
+ printf("-%s: INFO actual colours of pixels differ\n",msg);
+ }
+}
+
+
diff --git a/graphics/gd2/files/giftogd2.c b/graphics/gd2/files/giftogd2.c
new file mode 100644
index 000000000000..3753b56ac4c6
--- /dev/null
+++ b/graphics/gd2/files/giftogd2.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "gd.h"
+
+/* A short program which converts a .gif file into a .gd file, for
+ your convenience in creating images on the fly from a
+ basis image that must be loaded quickly. The .gd format
+ is not intended to be a general-purpose format. */
+
+int main(int argc, char **argv)
+{
+ gdImagePtr im;
+ FILE *in, *out;
+ int cs, fmt;
+
+ if (argc != 5) {
+ fprintf(stderr, "Usage: giftogd2 filename.gif filename.gd2 cs fmt\n");
+ fprintf(stderr, " where cs is the chunk size\n");
+ fprintf(stderr, " fmt is 1 for raw, 2 for compressed\n");
+ exit(1);
+ }
+ in = fopen(argv[1], "rb");
+ if (!in) {
+ fprintf(stderr, "Input file does not exist!\n");
+ exit(1);
+ }
+ im = gdImageCreateFromGif(in);
+ fclose(in);
+ if (!im) {
+ fprintf(stderr, "Input is not in GIF format!\n");
+ exit(1);
+ }
+ out = fopen(argv[2], "wb");
+ if (!out) {
+ fprintf(stderr, "Output file cannot be written to!\n");
+ gdImageDestroy(im);
+ exit(1);
+ }
+ cs = atoi(argv[3]);
+ fmt = atoi(argv[4]);
+ gdImageGd2(im, out, cs, fmt);
+ fclose(out);
+ gdImageDestroy(im);
+
+ return 0;
+}
+
diff --git a/graphics/gd2/files/patch-Makefile b/graphics/gd2/files/patch-Makefile
new file mode 100644
index 000000000000..487b38c3ed06
--- /dev/null
+++ b/graphics/gd2/files/patch-Makefile
@@ -0,0 +1,47 @@
+--- Makefile.orig Thu Apr 25 14:14:43 2002
++++ Makefile Thu Apr 25 14:10:10 2002
+@@ -67,7 +67,7 @@
+
+ PROGRAMS=$(BIN_PROGRAMS) $(TEST_PROGRAMS)
+
+-BIN_PROGRAMS=pngtogd pngtogd2 gdtopng gd2topng gd2copypal gdparttopng webpng
++BIN_PROGRAMS=pngtogd pngtogd2 gdtopng gd2topng gd2copypal gdparttopng webpng gd2togif gdcmpgif giftogd2
+ TEST_PROGRAMS=gdtest gddemo gd2time gdtestft testac
+
+ default: instructions
+@@ -94,6 +94,9 @@
+ sh ./install-item 755 gd2topng $(INSTALL_BIN)/gd2topng
+ sh ./install-item 755 gd2copypal $(INSTALL_BIN)/gd2copypal
+ sh ./install-item 755 gdparttopng $(INSTALL_BIN)/gdparttopng
++ sh ./install-item 755 gd2togif $(INSTALL_BIN)/gd2togif
++ sh ./install-item 755 gdcmpgif $(INSTALL_BIN)/gdcmpgif
++ sh ./install-item 755 giftogd2 $(INSTALL_BIN)/giftogd2
+ sh ./install-item 755 webpng $(INSTALL_BIN)/webpng
+ sh ./install-item 755 bdftogd $(INSTALL_BIN)/bdftogd
+ sh ./install-item 644 gd.h $(INSTALL_INCLUDE)/gd.h
+@@ -141,8 +144,18 @@
+ gdtestft: gdtestft.o
+ $(CC) --verbose gdtestft.o -o gdtestft $(LIBDIRS) $(LIBS)
+
++gd2togif: gd2togif.o libgd.a
++ $(CC) --verbose gd2togif.o -o gd2togif $(LIBDIRS) $(LIBS)
++
++gdcmpgif: gdcmpgif.o libgd.a
++ $(CC) --verbose gdcmpgif.o -o gdcmpgif $(LIBDIRS) $(LIBS)
++
++giftogd2: giftogd2.o libgd.a
++ $(CC) --verbose giftogd2.o -o giftogd2 $(LIBDIRS) $(LIBS)
++
+ LIBOBJS=gd.o gd_gd.o gd_gd2.o gd_io.o gd_io_dp.o \
+ gd_io_file.o gd_ss.o gd_io_ss.o gd_png.o gd_jpeg.o gdxpm.o \
++ gd_gif_in.o gd_gif_out.o gd_biggif_out.o gd_lzw_out.o \
+ gdfontt.o gdfonts.o gdfontmb.o gdfontl.o gdfontg.o \
+ gdtables.o gdft.o gdcache.o gdkanji.o wbmp.o \
+ gd_wbmp.o gdhelpers.o gd_topal.o
+@@ -171,5 +184,4 @@
+ -ranlib libgd.a
+
+ clean:
+- rm -f *.o *.a *.so ${PROGRAMS} test/gdtest.jpg test/gdtest.wbmp
+-
++ rm -f *.o *.a *.so ${PROGRAMS} test/gdtest.jpg test/gdtest.wbmp demoout.png test/fttest.png
diff --git a/graphics/gd2/files/patch-gd.c b/graphics/gd2/files/patch-gd.c
new file mode 100644
index 000000000000..ff3512f60e22
--- /dev/null
+++ b/graphics/gd2/files/patch-gd.c
@@ -0,0 +1,104 @@
+--- gd.c.orig Thu Apr 25 14:15:15 2002
++++ gd.c Thu Apr 25 12:43:55 2002
+@@ -1651,18 +1651,37 @@
+ if (dst->trueColor)
+ {
+ /* 2.0: much easier when the destination is truecolor. */
++
++ 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,
+- c);
++ gdTrueColor(src->red[c], src->green[c], src->blue[c]));
++ }
+ }
+ }
+ }
+@@ -1795,18 +1814,18 @@
+ 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)
+- + gdImageRed (dst, dc) * g *
++ + g *
+ ((100 - pct) / 100.0);
+ ncG = gdImageGreen (src, c) * (pct / 100.0)
+- + gdImageGreen (dst, dc) * g *
++ + g *
+ ((100 - pct) / 100.0);
+ ncB = gdImageBlue (src, c) * (pct / 100.0)
+- + gdImageBlue (dst, dc) * g *
++ + g *
+ ((100 - pct) / 100.0);
+
+ /* First look for an exact match */
+@@ -2211,7 +2230,17 @@
+ }
+
+ void
+-gdImagePolygon (gdImagePtr im, gdPointPtr p, int n, int c)
++gdImagePolygon(gdImagePtr im, gdPointPtr p, int n, int c)
++{
++ if (!n) {
++ return;
++ }
++ gdImageLine(im, p->x, p->y, p[n-1].x, p[n-1].y, c);
++ gdImageOpenPolygon(im, p, n, c);
++}
++
++void
++gdImageOpenPolygon (gdImagePtr im, gdPointPtr p, int n, int c)
+ {
+ int i;
+ int lx, ly;
+@@ -2221,7 +2250,6 @@
+ }
+ lx = p->x;
+ ly = p->y;
+- gdImageLine (im, lx, ly, p[n - 1].x, p[n - 1].y, c);
+ for (i = 1; (i < n); i++)
+ {
+ p++;
+@@ -2461,8 +2489,8 @@
+ {
+ for (x = 0; (x < sx); x++)
+ {
+- p1 = im1->pixels[y][x];
+- p2 = im2->pixels[y][x];
++ p1 = im1->trueColor ? gdImageTrueColorPixel(im1, x, y) : gdImagePalettePixel(im1, x, y);
++ p2 = im2->trueColor ? gdImageTrueColorPixel(im2, x, y) : gdImagePalettePixel(im2, x, y);
+ if (gdImageRed (im1, p1) != gdImageRed (im2, p2))
+ {
+ cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE;
diff --git a/graphics/gd2/files/patch-gd.h b/graphics/gd2/files/patch-gd.h
new file mode 100644
index 000000000000..d44b8c99f707
--- /dev/null
+++ b/graphics/gd2/files/patch-gd.h
@@ -0,0 +1,67 @@
+--- gd.h.orig Thu Apr 25 14:15:24 2002
++++ gd.h Thu Apr 25 12:43:55 2002
+@@ -201,6 +201,10 @@
+
+ gdImagePtr gdImageCreateFromPngSource(gdSourcePtr in);
+
++gdImagePtr gdImageCreateFromGif(FILE *fd);
++gdImagePtr gdImageCreateFromGifCtx(gdIOCtxPtr in);
++gdImagePtr gdImageCreateFromGifSource(gdSourcePtr in);
++
+ gdImagePtr gdImageCreateFromGd(FILE *in);
+ gdImagePtr gdImageCreateFromGdCtx(gdIOCtxPtr in);
+
+@@ -251,12 +255,26 @@
+ char *gdImageStringFT(gdImage *im, int *brect, int fg, char *fontlist,
+ double ptsize, double angle, int x, int y, char *string);
+
++typedef struct {
++ int flags; /* for future expansion logical OR of gdFTEX_ values */
++ double linespacing; /* fine tune line spacing for '\n' */
++} gdFTStringExtra, *gdFTStringExtraPtr;
++#define gdFTEX_LINESPACE 1
++
++/* FreeType 2 text output with fine tuning */
++char *
++gdImageStringFTEx(gdImage * im, int *brect, int fg, char * fontlist,
++ double ptsize, double angle, int x, int y, char * string,
++ gdFTStringExtraPtr strex);
++
++
+ /* Point type for use in polygon drawing. */
+ typedef struct {
+ int x, y;
+ } gdPoint, *gdPointPtr;
+
+ void gdImagePolygon(gdImagePtr im, gdPointPtr p, int n, int c);
++void gdImageOpenPolygon(gdImagePtr im, gdPointPtr p, int n, int c);
+ void gdImageFilledPolygon(gdImagePtr im, gdPointPtr p, int n, int c);
+
+ /* These functions still work with truecolor images,
+@@ -347,6 +365,14 @@
+ /* Best to free this memory with gdFree(), not free() */
+ void *gdImageJpegPtr(gdImagePtr im, int *size, int quality);
+
++void gdImageLzw(gdImagePtr im, FILE *out);
++void* gdImageLzwPtr(gdImagePtr im, int *size);
++void gdImageLzwCtx(gdImagePtr im, gdIOCtxPtr out);
++
++void gdImageBigGif(gdImagePtr im, FILE *out);
++void* gdImageBigGifPtr(gdImagePtr im, int *size);
++void gdImageBigGifCtx(gdImagePtr im, gdIOCtxPtr out);
++
+ /* A custom data sink. For backwards compatibility. Use
+ gdIOCtx instead. */
+ /* The sink function must return -1 on error, otherwise the number
+@@ -358,6 +384,11 @@
+ } gdSink, *gdSinkPtr;
+
+ void gdImagePngToSink(gdImagePtr im, gdSinkPtr out);
++
++void gdImageGif(gdImagePtr im, FILE *out);
++void* gdImageGifPtr(gdImagePtr im, int *size);
++void gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out);
++void gdImageGifToSink(gdImagePtr im, gdSinkPtr out);
+
+ void gdImageGd(gdImagePtr im, FILE *out);
+ void gdImageGd2(gdImagePtr im, FILE *out, int cs, int fmt);
diff --git a/graphics/gd2/files/patch-gd_png.c b/graphics/gd2/files/patch-gd_png.c
new file mode 100644
index 000000000000..f81c6db6c87d
--- /dev/null
+++ b/graphics/gd2/files/patch-gd_png.c
@@ -0,0 +1,11 @@
+--- gd_png.c.orig Thu Apr 25 14:15:42 2002
++++ gd_png.c Thu Apr 25 12:43:55 2002
+@@ -225,7 +225,7 @@
+ im->alpha[i] = gdAlphaMax - (trans[i] >> 1);
+ if ((trans[i] == 0) && (firstZero))
+ {
+- im->transparent = i;
++ transparent = i;
+ firstZero = 0;
+ }
+ }
diff --git a/graphics/gd2/files/patch-gdcache.h b/graphics/gd2/files/patch-gdcache.h
new file mode 100644
index 000000000000..c0ea11ecbd22
--- /dev/null
+++ b/graphics/gd2/files/patch-gdcache.h
@@ -0,0 +1,11 @@
+--- gdcache.h.orig Thu Apr 25 14:16:05 2002
++++ gdcache.h Thu Apr 25 12:48:41 2002
+@@ -40,7 +40,7 @@
+ /* header */
+ /*********************************************************/
+
+-#include <malloc.h>
++#include <stdlib.h>
+ #ifndef NULL
+ #define NULL (void *)0
+ #endif
diff --git a/graphics/gd2/files/patch-gdft.c b/graphics/gd2/files/patch-gdft.c
new file mode 100644
index 000000000000..1426fb7c6ad1
--- /dev/null
+++ b/graphics/gd2/files/patch-gdft.c
@@ -0,0 +1,166 @@
+--- gdft.c.orig Thu Apr 25 14:16:21 2002
++++ gdft.c Thu Apr 25 12:43:55 2002
+@@ -513,7 +513,8 @@
+ gdTrueColorGetRed (fg),
+ gdTrueColorGetGreen (fg),
+ gdTrueColorGetBlue (fg),
+- gdAlphaMax - (gdTrueColorGetAlpha (fg) * pixel / NUMCOLORS));
++ gdAlphaMax - ((gdAlphaMax - gdTrueColorGetAlpha (fg)) * pixel / NUMCOLORS)
++ );
+ }
+ else
+ {
+@@ -566,76 +567,53 @@
+
+ for (col = 0; col < bitmap.width; col++, pc++)
+ {
+- if (bitmap.pixel_mode == ft_pixel_mode_grays)
+- {
++ 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:
+ /*
+ * 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);
+- }
+- else if (bitmap.pixel_mode == ft_pixel_mode_mono)
+- {
++ break;
++ case ft_pixel_mode_mono:
+ tc_key.pixel = ((bitmap.buffer[pc / 8]
+ << (pc % 8)) & 128) ? NUMCOLORS : 0;
+- }
+- else
+- {
++ break;
++ default:
+ return "Unsupported ft_pixel_mode";
+ }
+
+ 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 */
+- if (im->trueColor)
+ {
+- tpixel = &im->tpixels[y][x];
++
++ if (im->trueColor) {
++ tc_elem = (tweencolor_t *) gdCacheGet (
++ tc_cache, &tc_key);
++
++ gdImageSetPixel(im, x, y, tc_elem->tweencolor);
+ }
+- else
+- {
++ else {
+ pixel = &im->pixels[y][x];
+- }
+ if (tc_key.pixel == NUMCOLORS)
+- {
+- /* use fg color directly */
+- if (im->trueColor)
+- {
+- *tpixel = fg;
+- }
+- else
+- {
+ *pixel = fg;
+- }
+- }
+- else
+- {
+- /* find antialised color */
+- if (im->trueColor)
+- {
+- tc_key.bgcolor = *tpixel;
+- }
+- else
+- {
++ else {
+ tc_key.bgcolor = *pixel;
+- }
+ tc_elem = (tweencolor_t *) gdCacheGet (
+ tc_cache, &tc_key);
+- if (im->trueColor)
+- {
+- *tpixel = tc_elem->tweencolor;
+- }
+- else
+- {
+ *pixel = tc_elem->tweencolor;
++
+ }
++
+ }
+ }
+ }
+@@ -647,11 +625,18 @@
+
+ /********************************************************************/
+ /* 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)
+ {
++ return gdImageStringFTEx(im, brect, fg, fontlist, ptsize, angle, x, y, string, NULL);
++}
++
++char *
++gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
++ double ptsize, double angle, int x, int y, char *string,
++ gdFTStringExtra * strex)
++{
+ FT_BBox bbox, glyph_bbox;
+ FT_Matrix matrix;
+ FT_Vector pen, delta, penf;
+@@ -672,6 +657,9 @@
+ int render = (im && (im->trueColor || (fg <= 255 && fg >= -255)));
+ FT_BitmapGlyph bm;
+
++ /* fine tuning */
++ double linespace = LINESPACE;
++
+ /***** initialize font library and font cache on first call ******/
+ static gdCache_head_t *fontCache;
+ static FT_Library library;
+@@ -704,6 +692,14 @@
+ return "Could not set character size";
+ }
+
++ /* 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;
+@@ -754,7 +750,7 @@
+ /* newlines */
+ if (ch == '\n')
+ {
+- penf.y -= face->size->metrics.height * LINESPACE;
++ penf.y -= face->size->metrics.height * linespace;
+ penf.y = (penf.y - 32) & -64; /* round to next pixel row */
+ x1 = (penf.x * cos_a - penf.y * sin_a + 32) / 64;
+ y1 = (penf.x * sin_a + penf.y * cos_a + 32) / 64;
diff --git a/graphics/gd2/files/patch-gdtest.c b/graphics/gd2/files/patch-gdtest.c
new file mode 100644
index 000000000000..292daaedfaa1
--- /dev/null
+++ b/graphics/gd2/files/patch-gdtest.c
@@ -0,0 +1,81 @@
+--- gdtest.c.orig Thu Apr 25 14:16:47 2002
++++ gdtest.c Tue Nov 6 15:53:38 2001
+@@ -84,6 +84,35 @@
+ gdImageDestroy (im2);
+ ctx->free (ctx);
+
++ /* */
++ /* Send to GIF File then Ptr */
++ /* */
++ sprintf(of, "%s.gif", argv[1]);
++ out = fopen(of, "wb");
++ gdImageGif(im, out);
++ fclose(out);
++
++ in = fopen(of, "rb");
++ if (!in) {
++ fprintf(stderr, "GIF Output file does not exist!\n");
++ exit(1);
++ }
++ im2 = gdImageCreateFromGif(in);
++ fclose(in);
++
++ CompareImages("GD->GIF File->GD", ref, im2);
++
++ unlink(of);
++ gdImageDestroy(im2);
++
++ iptr = gdImageGifPtr(im,&sz);
++ ctx = gdNewDynamicCtx(sz,iptr);
++ im2 = gdImageCreateFromGifCtx(ctx);
++
++ CompareImages("GD->GIF ptr->GD", ref, im2);
++
++ gdImageDestroy(im2);
++ ctx->free(ctx);
+
+ /* */
+ /* Send to GD2 File then Ptr */
+@@ -200,7 +229,30 @@
+ gdImageDestroy (im2);
+ };
+
+- unlink (of);
++ /*
++ ** Test gdImageCreateFromGifSource
++ **/
++
++ in = fopen(of, "rb");
++
++ if (!in)
++ {
++ fprintf (stderr, "GD Source: ERROR - GD Source input file does not exist - Sink may have failed!\n");
++ };
++
++ imgsrc.source = freadWrapper;
++ imgsrc.context = in;
++ im2 = gdImageCreateFromGifSource(&imgsrc);
++ fclose(in);
++
++ if (im2 == NULL) {
++ printf("GD Source (GIF): ERROR Null returned by gdImageCreateFromGifSource\n");
++ } else {
++ CompareImages("GD Source (GIF)", ref, im2);
++ gdImageDestroy(im2);
++ };
++
++ unlink(of);
+
+ /* */
+ /* Test Extraction */
+@@ -266,6 +318,10 @@
+
+ printf ("[Merged Image has %d colours]\n", im2->colorsTotal);
+ CompareImages ("Merged (gdtest.png, gdtest_merge.png)", im2, im3);
++
++ out = fopen ("test/gdtest_merge_out.png", "wb");
++ gdImagePng(im2, out);
++ close(out);
+
+ gdImageDestroy (im2);
+ gdImageDestroy (im3);
diff --git a/graphics/gd2/files/patch-gdtestft.c b/graphics/gd2/files/patch-gdtestft.c
new file mode 100644
index 000000000000..9f71e2a8dccb
--- /dev/null
+++ b/graphics/gd2/files/patch-gdtestft.c
@@ -0,0 +1,99 @@
+--- gdtestft.c.orig Thu Apr 25 14:17:03 2002
++++ gdtestft.c Wed Nov 7 00:43:02 2001
+@@ -18,6 +18,8 @@
+ #define MAXY(x) MAX4(x[1],x[3],x[5],x[7])
+ #define MINY(x) MIN4(x[1],x[3],x[5],x[7])
+
++void CompareImages(char *msg, gdImagePtr im1, gdImagePtr im2);
++
+ int
+ main (int argc, char *argv[])
+ {
+@@ -28,13 +30,13 @@
+ fprintf (stderr, "make clean, and type make again.\n");
+ return 1;
+ #else
+- gdImagePtr im;
++ gdImagePtr im, ref;
+ int black;
+ int white;
+ int brect[8];
+ int x, y;
+ char *err;
+- FILE *out;
++ FILE *out, *in;
+ #ifdef JISX0208
+ char *s = "Hello. こんにちは Qyjpqg,"; /* String to draw. */
+ #else
+@@ -67,8 +69,8 @@
+ /* create an image just big enough for the string */
+ x = MAXX (brect) - MINX (brect) + 6;
+ y = MAXY (brect) - MINY (brect) + 6;
+-#if 0
+- im = gdImageCreate (500, 500);
++#if 0
++ im = gdImageCreate (x, y);
+ #else
+ /* gd 2.0: true color images can use freetype too */
+ im = gdImageCreateTrueColor (x, y);
+@@ -90,6 +92,16 @@
+ fprintf (stderr, err);
+ return 1;
+ }
++
++ in = fopen("test/fttestref.png", "rb");
++ if (!in) {
++ fprintf(stderr, "Input file does not exist!\n");
++ exit(1);
++ }
++ ref = gdImageCreateFromPng(in);
++
++ fclose(in);
++
+ /* TBB: Write img to test/fttest.png */
+ out = fopen ("test/fttest.png", "wb");
+ if (!out)
+@@ -100,9 +112,43 @@
+ gdImagePng (im, out);
+ fclose (out);
+ fprintf (stderr, "Test image written to test/fttest.png\n");
++
++ CompareImages("FTTest Image", ref, im);
++
+ /* Destroy it */
+ gdImageDestroy (im);
++ gdImageDestroy(ref);
+
+ return 0;
+ #endif /* HAVE_FREETYPE */
+ }
++
++void CompareImages(char *msg, gdImagePtr im1, gdImagePtr im2)
++{
++ int cmpRes;
++
++ cmpRes = gdImageCompare(im1, im2);
++
++ if (cmpRes & GD_CMP_IMAGE) {
++ printf("%%%s: ERROR images differ: BAD\n",msg);
++ } else if (cmpRes != 0) {
++ printf("%%%s: WARNING images differ: WARNING - Probably OK\n",msg);
++ } else {
++ printf("%%%s: OK\n",msg);
++ return;
++ }
++
++ if (cmpRes & (GD_CMP_SIZE_X + GD_CMP_SIZE_Y)) {
++ printf("-%s: INFO image sizes differ\n",msg);
++ }
++
++ if (cmpRes & GD_CMP_NUM_COLORS) {
++ printf("-%s: INFO number of pallette entries differ %d Vs. %d\n",msg,
++ im1->colorsTotal, im2->colorsTotal);
++ }
++
++ if (cmpRes & GD_CMP_COLOR) {
++ printf("-%s: INFO actual colours of pixels differ\n",msg);
++ }
++}
++
diff --git a/graphics/gd2/files/patch-gif b/graphics/gd2/files/patch-gif
deleted file mode 100644
index b7b3b4441963..000000000000
--- a/graphics/gd2/files/patch-gif
+++ /dev/null
@@ -1,14 +0,0 @@
-This patch together with the old implementation (from gd-1.5) of
-gd_gif_in.c restore GD's ability to read GIF images. The writing of such
-images is troubled because of Unisys' zeal in patent enforcement.
-
---- gd.h Tue Feb 6 14:44:01 2001
-+++ gd.h Fri Jul 27 16:10:38 2001
-@@ -184,1 +184,3 @@
-+gdImagePtr gdImageCreateFromGif(FILE *fd);
-+gdImagePtr gdImageCreateFromGifCtx(gdIOCtxPtr in);
- gdImagePtr gdImageCreateFromPng(FILE *fd);
---- gd_gif_in.c Fri Jul 27 16:13:45 2001
-+++ gd_gif_in.c Fri Jul 27 16:14:46 2001
-@@ -6,1 +6,0 @@
--#include "io.h"
diff --git a/graphics/gd2/files/patch-index.html b/graphics/gd2/files/patch-index.html
new file mode 100644
index 000000000000..dfb4a4c7697d
--- /dev/null
+++ b/graphics/gd2/files/patch-index.html
@@ -0,0 +1,320 @@
+--- index.html.orig Thu Apr 25 14:17:36 2002
++++ index.html Tue Nov 6 23:31:10 2001
+@@ -24,7 +24,12 @@
+ more compatible with the major Web browsers than even PNG is. WBMP is
+ intended for wireless devices (not regular web browsers). Existing
+ code will need modification to call gdImagePng or gdImageJpeg instead
+-of gdImageGif. <strong>Please do not ask us to send you the old GIF
++of gdImageGif.
++<p>
++Note: The version at this site also supports GIF format, for those people
++who have not yet managed to move away from GIFs.
++<p>
++<strong>Please do not ask the original author to send you the old GIF
+ version of GD.</strong> Unisys holds a patent on the LZW compression
+ algorithm, which is used in fully compressed GIF images. The best
+ solution is to move to legally unencumbered, well-compressed,
+@@ -103,6 +108,18 @@
+ <p>
+ Portions relating to libttf copyright 1999, 2000 John Ellson (ellson@lucent.com).
+ <p>
++GIF decompression code copyright 1990, 1991, 1993, by David Koblas
++(koblas@netcom.com).
++<p>
++Non-LZW-based GIF compression code copyright 1998, by Hutchison Avenue
++Software Corporation (<a href="http://www.hasc.com">http://www.hasc.com/</a>,
++info@hasc.com).
++<p>
++LZW-based GIF compression code David Rowley.
++Obtaining a license for the Unisys LZW compression patent is
++entirely between the user and Unisys. The authors of gd can provide
++NO assistance in this matter.
++<p>
+ Portions relating to JPEG and to color quantization copyright 2000, Doug
+ Becker and copyright (C) 1994-1998, Thomas G. Lane. This software is based
+ in part on the work of the Independent JPEG Group. See the file
+@@ -193,6 +210,26 @@
+ <li><a href="http://s27w007.pswfs.gov/tgd/">tgd</a>, by Bradley K. Sherman
+ <li><a href="http://www.unimelb.edu.au/fly/fly.html">fly</a>, by Martin Gleeson
+ </ul>
++
++<P><A NAME="gifpatch"><H3>What's new in the patched version?</H3></A>
++
++This version reinstates GIF support. Specifically, the following functions are added:
++<ul>
++<li><a href=#gdImageOpenPolygon>gdImageOpenPolygon</a>. This is basically the same as
++gdImagePolygon, but it does not join the start and end points. It is required by GD.pm.
++<li><a href=#gdImageGif>gdImageGif</a>
++<li><a href=#gdImageGifPtr>gdImageGifPtr</a>
++<li><a href=#gdImageGifCtx>gdImageGifCtx</a>
++<li><a href=#gdImageGifToSink>gdImageGifToSink</a>
++<li><a href=#gdImageCreateFromGif>gdImageCreateFromGif</a>
++<li><a href=#gdImageCreateFromGifCtx>gdImageCreateFromGifCtx</a>
++<li>Other functions added, but not documented, are: gdImageLzw, gdImageLzwPtr,
++gdImageLzwCtx, gdImageBigGif, gdImageBigGifPtr, gdImageBigGifCtx.
++</ul>
++<p>
++Note: While every effort has been made to ensure that the _WinNT_ build works, it has not
++been tested.
++
+ <P><A NAME="whatsnew2.0.1"><H3>What's new in version 2.0.1?</H3></A>
+ <ul>
+ <li>Workaround for a bug in gcc, apparently found in gcc 2.7.2 and up.
+@@ -311,6 +348,7 @@
+ preprocessing them, this should not be a big problem. gd 2.0 should
+ read old .gd and .gd2 files correctly.
+ </ul>
++
+ <P><A NAME="whatsnew1.8.4"><H3>What's new in version 1.8.4?</H3></A>
+ <ul>
+ <li>Add support for FreeType2 (John Ellson ellson@lucent.com)
+@@ -343,6 +381,7 @@
+ corrected
+ <li>Updated links to fast-moving, always dodging libpng and zlib web sites
+ </ul>
++
+ <P><A NAME="whatsnew1.8.1"><H3>What's new in version 1.8.1?</H3></A>
+ <ul>
+ <li>Optional components no longer built by default (following the
+@@ -420,6 +459,7 @@
+ <a href="#gdImageCreateFromXpm"><code>gdImageCreateFromXpm</code></a>
+ function, if the Xpm library is available. Thanks to Caolan McNamara.
+ </ul>
++
+ <P><A NAME="whatsnew1.6.3"><H3>What's new in version 1.6.3?</H3></A>
+ Version 1.6.3 corrects a memory leak in gd_png.c. This leak caused
+ a significant amount of memory to be allocated and not freed when
+@@ -911,7 +951,8 @@
+ <DT><A NAME="gdPoint">gdPoint</A> <strong>(TYPE)</strong>
+ <DD>
+ Represents a point in the coordinate space of the image; used
+-by <A HREF="#gdImagePolygon">gdImagePolygon</A> and
++by <A HREF="#gdImagePolygon">gdImagePolygon</A>,
++<A HREF="#gdImageOpenPolygon">gdImageOpenPolygon</A>, and
+ <A HREF="#gdImageFilledPolygon">gdImageFilledPolygon</A>.
+ <PRE>
+ typedef struct {
+@@ -921,7 +962,8 @@
+ <DT><A NAME="gdPointPtr">gdPointPtr</A> <strong>(TYPE)</strong>
+ <DD>
+ A pointer to a <A HREF="#gdPoint">gdPoint</A> structure; passed
+-as an argument to <A HREF="#gdImagePolygon">gdImagePolygon</A>
++as an argument to <A HREF="#gdImagePolygon">gdImagePolygon</A>,
++<A HREF="#gdImageOpenPolygon">gdImageOpenPolygon</A>,
+ and <A HREF="#gdImageFilledPolygon">gdImageFilledPolygon</A>.
+ </DL>
+ <DT><A NAME="gdSource">gdSource</A> <strong>(TYPE)</strong>
+@@ -1024,6 +1066,75 @@
+ /* ... Use the image ... */
+ <A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+ </PRE>
++
++<DT><A NAME="gdImageCreateFromGif">gdImageCreateFromGif(FILE *in)</A>
++<strong>(FUNCTION)</strong>
++<BR><A NAME="gdImageCreateFromGifCtx">gdImageCreateFromGifCtx(<a href=#gdioctx>gdIOCtx</a> *in)</A>
++<strong>(FUNCTION)</strong>
++<p>
++<DD>
++gdImageCreateFromGif is called to load images from GIF format files.
++Invoke gdImageCreateFromGif with an already opened pointer to a file
++containing the desired image.
++gdImageCreateFromGif
++returns a <A HREF="#gdImagePtr">gdImagePtr</A> to the new image, or NULL
++if unable to load the image (most often because the file is corrupt or
++does not contain a GIF image). gdImageCreateFromGif does <em>not</em>
++close the file. You can inspect the sx and sy members of the
++image to determine its size. The image must eventually be destroyed
++using <A HREF="#gdImageDestroy">gdImageDestroy()</A>.
++<PRE>
++<A HREF="#gdImagePtr">gdImagePtr</A> im;
++... inside a function ...
++FILE *in;
++in = fopen("mygif.gif", "rb");
++im = gdImageCreateFromGif(in);
++fclose(in);
++/* ... Use the image ... */
++<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
++</PRE>
++<DT><A NAME="gdImageCreateFromGifSource">gdImageCreateFromGifSource(gdSourcePtr in)</A>
++<strong>(FUNCTION)</strong>
++<dd>
++gdImageCreateFromGifSource is called to load a GIF from
++a data source other than a file. Usage is very similar to
++the <a href="#gdImageCreateFromGif">gdImageCreateFromGif</a> function,
++except that the programmer provides a custom data source.
++<p>
++The programmer must write an input function which accepts
++a context pointer, a buffer, and a number of bytes to be
++read as arguments. This function must read the number of
++bytes requested, unless the end of the file has been reached,
++in which case the function should return zero, or an error
++has occurred, in which case the function should return
++<code>-1</code>. The programmer then creates a
++<a href="#gdSource">gdSource</a> structure and sets
++the <code>source</code> pointer to the input function and
++the context pointer to any value which is useful to the
++programmer.
++<p>
++The example below
++implements <a href="#gdImageCreateFromGif">gdImageCreateFromGif</a>
++by creating a custom data source and invoking gdImageCreateFromGifSource.
++<pre>
++static int freadWrapper(void *context, char *buf, int len);
++
++gdImagePtr gdImageCreateFromGif(FILE *in)
++{
++ gdSource s;
++ s.source = freadWrapper;
++ s.context = in;
++ return gdImageCreateFromGifSource(&s);
++}
++
++static int freadWrapper(void *context, char *buf, int len)
++{
++ int got = fread(buf, 1, len, (FILE *) context);
++ return got;
++}
++</pre>
++
++
+ <DT><A NAME="gdImageCreateFromPng">gdImageCreateFromPng(FILE *in)</A>
+ <strong>(FUNCTION)</strong>
+ <BR><A NAME="gdImageCreateFromPngCtx">gdImageCreateFromPngCtx(<a href=#gdioctx>gdIOCtx</a> *in)</A>
+@@ -1239,6 +1350,92 @@
+ /* Now destroy it */
+ <A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+ </PRE>
++
++<DT><A NAME="gdImageGif">
++void gdImageGif(gdImagePtr im, FILE *out)</A>
++<STRONG>(FUNCTION)</STRONG>
++<DD>
++gdImageGif outputs the specified image to the specified
++file in GIF format. The file must be open for writing. Under MSDOS
++and all versions of Windows, it is important to use "wb" as opposed
++to simply "w" as the mode when opening the file, and under Unix there
++is no penalty for doing so. gdImageGif does <em>not</em>
++close the file; your code must do so.
++<PRE>
++... inside a function ...
++<A HREF="#gdImagePtr">gdImagePtr</A> im;
++int black, white;
++FILE *out;
++/* Create the image */
++im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
++/* Allocate background */
++white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);
++/* Allocate drawing color */
++black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);
++/* Draw rectangle */
++<A HREF="#gdImageRectangle">gdImageRectangle</A>(im, 0, 0, 99, 99, black);
++/* Open output file in binary mode */
++out = fopen("rect.gif", "wb");
++/* Write GIF */
++gdImageGif(im, out);
++/* Close file */
++fclose(out);
++/* Destroy image */
++<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
++</PRE>
++
++<DT><A NAME="gdImageGifCtx">
++void* gdImageGifCtx(gdImagePtr im, gdIOCtxPtr out)</A>
++<STRONG>(FUNCTION)</STRONG>
++<DD>Identical to gdImageGif except that it writes the GIF to a
++<a href=#gdIOCtx>gdIOCtx</a>.
++<p>
++<DT><A NAME="gdImageGifPtr">
++void* gdImageGifPtr(gdImagePtr im, int *size)</A>
++<STRONG>(FUNCTION)</STRONG>
++<DD>Identical to gdImageGif except that it returns a pointer to a memory
++area with the GIF data. This memory must be freed by the caller when it is
++no longer needed. The 'size' parameter received the total size of the block
++of memory.
++<p>
++
++<DT><A NAME="gdImageGifToSink">gdImageGifToSink(gdImagePtr im, gdSinkPtr out)</A>
++<strong>(FUNCTION)</strong>
++<dd>
++gdImageGifToSink is called to write a GIF to
++a data "sink" (destination) other than a file. Usage is very similar to
++the <a href="#gdImageGif">gdImageGif</a> function,
++except that the programmer provides a custom data sink.
++<p>
++The programmer must write an output function which accepts
++a context pointer, a buffer, and a number of bytes to be
++written as arguments. This function must write the number of
++bytes requested and return that number, unless an error
++has occurred, in which case the function should return
++<code>-1</code>. The programmer then creates a
++<a href="#gdSink">gdSink</a> structure and sets
++the <code>sink</code> pointer to the output function and
++the context pointer to any value which is useful to the
++programmer.
++<p>
++The example below
++implements <a href="#gdImageGif">gdImageGif</a>
++by creating a custom data source and invoking gdImageGifFromSink.
++<pre>
++static int stdioSink(void *context, char *buffer, int len)
++{
++ return fwrite(buffer, 1, len, (FILE *) context);
++}
++
++void gdImageGif(gdImagePtr im, FILE *out)
++{
++ gdSink mySink;
++ mySink.context = (void *) out;
++ mySink.sink = stdioSink;
++ gdImageGifToSink(im, &mySink);
++}
++</pre>
++
+ <DT><A NAME="gdImageJpeg">
+ void gdImageJpeg(gdImagePtr im, FILE *out, int quality)</A>
+ <STRONG>(FUNCTION)</STRONG><BR>
+@@ -1642,6 +1839,15 @@
+ /* Destroy it */
+ <A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+ </PRE>
++
++<DT><A NAME="gdImageOpenPolygon">void gdImageOpenPolygon(gdImagePtr im, gdPointPtr points, int pointsTotal, int color)</A>
++<STRONG>(FUNCTION)</STRONG>
++<DD>
++gdImageOpenPolygon is used to draw an open polygon (ie. series of line segments). It is almost identical
++to <A HREF="#gdImagePolygon">gdImagePolygon</A>, except that it does not join the last point to the
++first point.
++<P>
++
+ <DT><A NAME="gdImageRectangle">void gdImageRectangle(gdImagePtr im, int x1, int y1, int x2, int y2, int color)</A>
+ <STRONG>(FUNCTION)</STRONG>
+ <DD>
+@@ -3552,6 +3758,9 @@
+ <A HREF="#gdImageCreateFromGd">gdImageCreateFromGd</A> |
+ <A HREF="#gdImageCreateFromGd2">gdImageCreateFromGd2</A> |
+ <A HREF="#gdImageCreateFromGd2Part">gdImageCreateFromGd2Part</A> |
++<A HREF="#gdImageCreateFromGif">gdImageCreateFromGif</A> |
++<A HREF="#gdImageCreateFromGifCtx">gdImageCreateFromGifCtx</A> |
++<A HREF="#gdImageCreateFromGifSource">gdImageCreateFromGifSource</A> |
+ <A HREF="#gdImageCreateFromJpeg">gdImageCreateFromJpeg</A> |
+ <A HREF="#gdImageCreateFromPng">gdImageCreateFromPng</A> |
+ <A HREF="#gdImageCreateFromPngSource">gdImageCreateFromPngSource</A> |
+@@ -3569,6 +3778,10 @@
+ <A HREF="#gdImageGetInterlaced">gdImageGetInterlaced</A> |
+ <A HREF="#gdImageGetPixel">gdImageGetPixel</A> |
+ <A HREF="#gdImageGetTransparent">gdImageGetTransparent</A> |
++<A HREF="#gdImageGif">gdImageGif</A> |
++<A HREF="#gdImageGifCtx">gdImageGifCtx</A> |
++<A HREF="#gdImageGifPtr">gdImageGifPtr</A> |
++<A HREF="#gdImageGifToSink">gdImageGifToSink</A> |
+ <A HREF="#gdImageGreen">gdImageGreen</A> |
+ <A HREF="#gdImageInterlace">gdImageInterlace</A> |
+ <A HREF="#gdImageJpeg">gdImageJpeg</A> |
+@@ -3578,6 +3791,7 @@
+ <A HREF="#gdImagePng">gdImagePng</A> |
+ <A HREF="#gdImagePngToSink">gdImagePngToSink</A> |
+ <A HREF="#gdImagePolygon">gdImagePolygon</A> |
++<A HREF="#gdImageOpenPolygon">gdImageOpenPolygon</A> |
+ <A HREF="#gdImagePtr">gdImagePtr</A> |
+ <A HREF="#gdImageWBMP">gdImageWBMP</A> |
+ <A HREF="#gdImageRectangle">gdImageRectangle</A> |
diff --git a/graphics/gd2/files/patch-malloc b/graphics/gd2/files/patch-malloc
deleted file mode 100644
index fa33bbc023f2..000000000000
--- a/graphics/gd2/files/patch-malloc
+++ /dev/null
@@ -1,5 +0,0 @@
---- gdcache.h Tue Feb 6 14:44:02 2001
-+++ gdcache.h Fri Aug 24 08:10:41 2001
-@@ -43 +43 @@
--#include <malloc.h>
-+#include <stdlib.h>
diff --git a/graphics/gd2/files/patch-webpng.c b/graphics/gd2/files/patch-webpng.c
new file mode 100644
index 000000000000..fef8b31f40f4
--- /dev/null
+++ b/graphics/gd2/files/patch-webpng.c
@@ -0,0 +1,66 @@
+--- webpng.c.orig Thu Apr 25 14:19:03 2002
++++ webpng.c Thu Apr 25 12:43:55 2002
+@@ -168,12 +168,12 @@
+ t = gdImageGetTransparent (im);
+ if (t != (-1))
+ {
+- printf ("First 100% transparent index: %d\n", t);
++ printf ("First 100%% transparent index: %d\n", t);
+ }
+ else
+ {
+ /* -1 means the image is not transparent. */
+- printf ("First 100% transparent index: none\n");
++ printf ("First 100%% transparent index: none\n");
+ }
+ if (gdImageGetInterlaced (im))
+ {
+@@ -185,6 +185,40 @@
+ }
+ no = 0;
+ }
++ else if (!strcmp(argv[i], "-a"))
++ {
++ int maxx, maxy, x, y, alpha, pix, nalpha = 0;
++
++ maxx = gdImageSX(im);
++ maxy = gdImageSY(im);
++
++ printf("alpha channel information:\n");
++
++ if (im->trueColor) {
++ for (y = 0; y < maxy; y++) {
++ for (x = 0; x < maxx; x++) {
++ pix = gdImageGetPixel(im, x, y);
++ alpha = gdTrueColorGetAlpha(pix);
++
++ if (alpha > gdAlphaOpaque) {
++ /* Use access macros to learn colors. */
++ printf ("%d %d %d %d\n",
++ gdTrueColorGetRed(pix),
++ gdTrueColorGetGreen(pix),
++ gdTrueColorGetBlue(pix),
++ alpha);
++ nalpha++;
++ }
++
++ }
++ }
++ }
++ else
++ printf("NOT a true color image\n");
++ no = 0;
++ printf("%d alpha channels\n", nalpha);
++
++ }
+ else
+ {
+ fprintf (stderr, "Unknown argument: %s\n", argv[i]);
+@@ -202,6 +236,7 @@
+ " -l Prints the table of color indexes\n"
+ " -t [index] Set the transparent color to the specified index (0-255 or \"none\")\n"
+ " -d Reports the dimensions and other characteristics of the image.\n"
++ " -a Prints all alpha channels that are not 100%% opaque.\n"
+ "\n"
+ "If you specify '-' as the input file, stdin/stdout will be used input/output.\n"
+ );
diff --git a/graphics/gd2/pkg-descr b/graphics/gd2/pkg-descr
index 35883e4a4624..f7507cc8d13f 100644
--- a/graphics/gd2/pkg-descr
+++ b/graphics/gd2/pkg-descr
@@ -1,18 +1,16 @@
-gd is a graphics library. It allows your code to quickly draw images
-complete with lines, arcs, text, multiple colors, cut and paste from
-other images, and flood fills, and write out the result as a PNG or JPEG
-file. This is particularly useful in World Wide Web applications, where
-PNG and JPEG are two of the formats accepted for inline images by most
-browsers.
+gd is a graphics library. It allows your code to quickly draw images
+complete with lines, arcs, text, multiple colors, cut and paste from
+other images, and flood fills, and write out the result as a PNG, GIF
+or JPEG file. This is particularly useful in World Wide Web applications,
+where PNG, GIF and JPEG are three of the formats accepted for inline
+images by most browsers.
-gd does not provide for every possible desirable graphics operation.
-It is not necessary or desirable for gd to become a kitchen-sink
-graphics package, but version 2.0 does include most frequently requested
-features, including both truecolor and palette images, resampling
-(smooth resizing of truecolor images) and so forth.
-
-AUTHOR
- gd was written by Thomas Boutell and is currently distributed by
- boutell.com, Inc.
+gd does not provide for every possible desirable graphics operation,
+but version 2.0 does include most frequently requested features,
+including both truecolor and palette images, resampling (smooth
+resizing of truecolor images) and so forth.
WWW: http://www.boutell.com/gd/
+
+- Alex Dupre
+sysadmin@alexdupre.com
diff --git a/graphics/gd2/pkg-plist b/graphics/gd2/pkg-plist
index 1b1b3125513d..c26106efe446 100644
--- a/graphics/gd2/pkg-plist
+++ b/graphics/gd2/pkg-plist
@@ -1,8 +1,11 @@
bin/bdftogd
bin/gd2copypal
+bin/gd2togif
bin/gd2topng
+bin/gdcmpgif
bin/gdparttopng
bin/gdtopng
+bin/giftogd2
bin/pngtogd
bin/pngtogd2
bin/webpng
@@ -16,4 +19,6 @@ include/gdfonts.h
include/gdfontt.h
lib/libgd.a
lib/libgd.so
-lib/libgd.so.3.0
+lib/libgd.so.4
+%%PORTDOCS%%share/doc/gd/index.html
+%%PORTDOCS%%@dirrm share/doc/gd