Commits

Anonymous committed 871d0d8

- sync to 2.0.12

Comments (0)

Files changed (23)

 
 lib_LTLIBRARIES = libgd.la
 
-libgd_la_SOURCES = gd.c gd_gd.c gd_gd2.c gd_io.c gd_io_dp.c gd_io_file.c gd_io_ss.c gd_jpeg.c gd_png.c gd_ss.c gd_topal.c gd_wbmp.c gdcache.c gdfontg.c gdfontl.c gdfontmb.c gdfonts.c gdfontt.c gdft.c gdhelpers.c gdhelpers.h gdkanji.c gdtables.c gdxpm.c jisx0208.h mathmake.c wbmp.c wbmp.h
+libgd_la_SOURCES = gd.c gd_gd.c gd_gd2.c gd_io.c gd_io_dp.c gd_io_file.c gd_io_ss.c gd_jpeg.c gd_png.c gd_ss.c gd_topal.c gd_wbmp.c gdcache.c gdfontg.c gdfontl.c gdfontmb.c gdfonts.c gdfontt.c gdft.c gdhelpers.c gdhelpers.h gdkanji.c gdtables.c gdxpm.c jisx0208.h wbmp.c wbmp.h
 
 libgd_la_LDFLAGS = -version-info 2:0:0
 
 
 lib_LTLIBRARIES = libgd.la
 
-libgd_la_SOURCES = gd.c gd_gd.c gd_gd2.c gd_io.c gd_io_dp.c gd_io_file.c gd_io_ss.c gd_jpeg.c gd_png.c gd_ss.c gd_topal.c gd_wbmp.c gdcache.c gdfontg.c gdfontl.c gdfontmb.c gdfonts.c gdfontt.c gdft.c gdhelpers.c gdhelpers.h gdkanji.c gdtables.c gdxpm.c jisx0208.h mathmake.c wbmp.c wbmp.h
+libgd_la_SOURCES = gd.c gd_gd.c gd_gd2.c gd_io.c gd_io_dp.c gd_io_file.c gd_io_ss.c gd_jpeg.c gd_png.c gd_ss.c gd_topal.c gd_wbmp.c gdcache.c gdfontg.c gdfontl.c gdfontmb.c gdfonts.c gdfontt.c gdft.c gdhelpers.c gdhelpers.h gdkanji.c gdtables.c gdxpm.c jisx0208.h wbmp.c wbmp.h
 
 libgd_la_LDFLAGS = -version-info 2:0:0
 
 	gd_io_file.lo gd_io_ss.lo gd_jpeg.lo gd_png.lo gd_ss.lo \
 	gd_topal.lo gd_wbmp.lo gdcache.lo gdfontg.lo gdfontl.lo \
 	gdfontmb.lo gdfonts.lo gdfontt.lo gdft.lo gdhelpers.lo \
-	gdkanji.lo gdtables.lo gdxpm.lo mathmake.lo wbmp.lo
+	gdkanji.lo gdtables.lo gdxpm.lo wbmp.lo
 libgd_la_OBJECTS = $(am_libgd_la_OBJECTS)
 bin_PROGRAMS = annotate$(EXEEXT) gdparttopng$(EXEEXT) gdtopng$(EXEEXT) \
 	gd2copypal$(EXEEXT) gd2topng$(EXEEXT) pngtogd$(EXEEXT) \
 @AMDEP_TRUE@	./$(DEPDIR)/gdparttopng.Po ./$(DEPDIR)/gdtables.Plo \
 @AMDEP_TRUE@	./$(DEPDIR)/gdtest.Po ./$(DEPDIR)/gdtestft.Po \
 @AMDEP_TRUE@	./$(DEPDIR)/gdtopng.Po ./$(DEPDIR)/gdxpm.Plo \
-@AMDEP_TRUE@	./$(DEPDIR)/mathmake.Plo ./$(DEPDIR)/pngtogd.Po \
-@AMDEP_TRUE@	./$(DEPDIR)/pngtogd2.Po ./$(DEPDIR)/testac.Po \
-@AMDEP_TRUE@	./$(DEPDIR)/wbmp.Plo ./$(DEPDIR)/webpng.Po
+@AMDEP_TRUE@	./$(DEPDIR)/pngtogd.Po ./$(DEPDIR)/pngtogd2.Po \
+@AMDEP_TRUE@	./$(DEPDIR)/testac.Po ./$(DEPDIR)/wbmp.Plo \
+@AMDEP_TRUE@	./$(DEPDIR)/webpng.Po
 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
 	$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
 LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gdtestft.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gdtopng.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gdxpm.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mathmake.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngtogd.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngtogd2.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testac.Po@am__quote@
 int
 main (int argc, char *argv[])
 {
+#ifndef HAVE_LIBFREETYPE
+  /* 2.0.12 */
+  fprintf (stderr, "annotate is not useful without freetype.\n"
+	   "Install freetype, then './configure; make clean; make install'\n"
+	   "the gd library again.\n");
+  return 1;
+#else
   gdImagePtr im;
   char *iin, *iout;
   FILE *in, *out;
   gdImageDestroy (im);
   fclose (out);
   return 0;
+#endif /* HAVE_LIBFREETYPE */
 }
 /* Define to 1 if you have the `jpeg' library (-ljpeg). */
 #undef HAVE_LIBJPEG
 
+/* Define to 1 if you have the `m' library (-lm). */
+#undef HAVE_LIBM
+
 /* Define to 1 if you have the `png' library (-lpng). */
 #undef HAVE_LIBPNG
 
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.57 for GD 2.0.11.
+# Generated by GNU Autoconf 2.57 for GD 2.0.12.
 #
 # Report bugs to <gd@boutell.com>.
 #
 # Identity of this package.
 PACKAGE_NAME='GD'
 PACKAGE_TARNAME='gd'
-PACKAGE_VERSION='2.0.11'
-PACKAGE_STRING='GD 2.0.11'
+PACKAGE_VERSION='2.0.12'
+PACKAGE_STRING='GD 2.0.12'
 PACKAGE_BUGREPORT='gd@boutell.com'
 
 ac_unique_file="gd.c"
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures GD 2.0.11 to adapt to many kinds of systems.
+\`configure' configures GD 2.0.12 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of GD 2.0.11:";;
+     short | recursive ) echo "Configuration of GD 2.0.12:";;
    esac
   cat <<\_ACEOF
 
 test -n "$ac_init_help" && exit 0
 if $ac_init_version; then
   cat <<\_ACEOF
-GD configure 2.0.11
+GD configure 2.0.12
 generated by GNU Autoconf 2.57
 
 Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by GD $as_me 2.0.11, which was
+It was created by GD $as_me 2.0.12, which was
 generated by GNU Autoconf 2.57.  Invocation command line was
 
   $ $0 $@
 
 GDLIB_MAJOR=2
 GDLIB_MINOR=0
-GDLIB_REVISION=11
+GDLIB_REVISION=12
 GDLIBNAME=gd
 
 
 
 # Define the identity of the package.
  PACKAGE=gd
- VERSION=2.0.11
+ VERSION=2.0.12
 
 
 cat >>confdefs.h <<_ACEOF
 #AC_FUNC_VPRINTF
 #AC_CHECK_FUNCS([floor memset sqrt strchr strdup strtol])
 
+echo "$as_me:$LINENO: checking for sin" >&5
+echo $ECHO_N "checking for sin... $ECHO_C" >&6
+if test "${ac_cv_func_sin+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char sin (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char sin ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_sin) || defined (__stub___sin)
+choke me
+#else
+char (*f) () = sin;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != sin;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_func_sin=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_sin=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_sin" >&5
+echo "${ECHO_T}$ac_cv_func_sin" >&6
+if test $ac_cv_func_sin = yes; then
+  :
+else
+
+echo "$as_me:$LINENO: checking for sin in -lm" >&5
+echo $ECHO_N "checking for sin in -lm... $ECHO_C" >&6
+if test "${ac_cv_lib_m_sin+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lm  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char sin ();
+int
+main ()
+{
+sin ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+         { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_m_sin=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_m_sin=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_m_sin" >&5
+echo "${ECHO_T}$ac_cv_lib_m_sin" >&6
+if test $ac_cv_lib_m_sin = yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBM 1
+_ACEOF
+
+  LIBS="-lm $LIBS"
+
+fi
+
+fi
+
+
 echo "$as_me:$LINENO: checking for deflate in -lz" >&5
 echo $ECHO_N "checking for deflate in -lz... $ECHO_C" >&6
 if test "${ac_cv_lib_z_deflate+set}" = set; then
   echo $ECHO_N "(cached) $ECHO_C" >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lz -lm $LIBS"
+LIBS="-lz  $LIBS"
 cat >conftest.$ac_ext <<_ACEOF
 #line $LINENO "configure"
 /* confdefs.h.  */
 echo "$as_me:$LINENO: result: $ac_cv_lib_z_deflate" >&5
 echo "${ECHO_T}$ac_cv_lib_z_deflate" >&6
 if test $ac_cv_lib_z_deflate = yes; then
-  LIBS="-lz -lm $LIBS"
+  LIBS="-lz $LIBS"
 
 cat >>confdefs.h <<\_ACEOF
 #define HAVE_LIBZ 1
   if test -n "$LIBPNG_CONFIG"; then
     libpng_CPPFLAGS=`libpng-config --cflags`
     # should be --ldopts, but it's currently broken
-    libpng_LDFLAGS=`libpng-config --ldflags | sed 's/-l[^ ][^ ]*//g'`
+    libpng_LDFLAGS=`libpng-config --ldflags`
+    libpng_LDFLAGS=`echo " $libpng_LDFLAGS" | sed 's/ -l[^ ][^ ]*//g'`
   elif test -d "$withval"; then
     libpng_CPPFLAGS="-I$withval/include"
     libpng_LDFLAGS="-L$withval/lib"
   if test -n "$FREETYPE_CONFIG"; then
     if test -n "$FREETYPE_DIR"; then
       libft_INCLUDES="`$FREETYPE_CONFIG --cflags` -I$FREETYPE_DIR/include"
-      libft_LDFLAGS=`$FREETYPE_CONFIG --libs |sed 's/-l[^ ][^ ]*//g'`
     else
       libft_INCLUDES=`$FREETYPE_CONFIG --cflags`
-      libft_LDFLAGS=`$FREETYPE_CONFIG --libs |sed 's/-l[^ ][^ ]*//g'`
     fi
+    libft_LDFLAGS=`$FREETYPE_CONFIG --libs`
+    libft_LDFLAGS=`echo " $libft_LDFLAGS" |sed 's/ -l[^ ][^ ]*//g'`
   else
     if test -n "$FREETYPE_DIR"; then
       libft_INCLUDES="-I$FREETYPE_DIR/include/freetype2 -I$FREETYPE_DIR/include"
 } >&5
 cat >&5 <<_CSEOF
 
-This file was extended by GD $as_me 2.0.11, which was
+This file was extended by GD $as_me 2.0.12, which was
 generated by GNU Autoconf 2.57.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
 
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-GD config.status 2.0.11
+GD config.status 2.0.12
 configured by $0, generated by GNU Autoconf 2.57,
   with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
 
 AC_PREREQ(2.54)
 
 #HEY! Change BOTH the vesion number and the GDLIB_REVISION setting!
-AC_INIT([GD], [2.0.11], [gd@boutell.com])
+AC_INIT([GD], [2.0.12], [gd@boutell.com])
 AC_CONFIG_SRCDIR([gd.c])
 AC_CONFIG_AUX_DIR(config)
 
 GDLIB_MAJOR=2
 GDLIB_MINOR=0
-GDLIB_REVISION=11
+GDLIB_REVISION=12
 GDLIBNAME=gd
 
 AC_SUBST(GDLIB_MAJOR)
 #AC_FUNC_VPRINTF
 #AC_CHECK_FUNCS([floor memset sqrt strchr strdup strtol])
 
+dnl do we need to specify -lm explicitly?
+AC_CHECK_FUNC(sin,,[AC_CHECK_LIB(m,sin)])
+
 dnl zlib is required
 AC_CHECK_LIB(z,deflate,
-  [LIBS="-lz -lm $LIBS"
+  [LIBS="-lz $LIBS"
    AC_DEFINE(HAVE_LIBZ, 1, [ Define if you have zlib. ])],
-  [AC_MSG_WARN([zlib is required - see http://www.gzip.org/zlib/])],[-lm])
+  [AC_MSG_WARN([zlib is required - see http://www.gzip.org/zlib/])])
 
 dnl libpng is required
 AC_ARG_WITH(png,dnl
   if test -n "$LIBPNG_CONFIG"; then
     libpng_CPPFLAGS=`libpng-config --cflags`
     # should be --ldopts, but it's currently broken
-    libpng_LDFLAGS=`libpng-config --ldflags | sed 's/-l[[^ ]][[^ ]]*//g'`
+    libpng_LDFLAGS=`libpng-config --ldflags`
+    libpng_LDFLAGS=`echo " $libpng_LDFLAGS" | sed 's/ -l[[^ ]][[^ ]]*//g'`
   elif test -d "$withval"; then
     libpng_CPPFLAGS="-I$withval/include"
     libpng_LDFLAGS="-L$withval/lib"
   if test -n "$FREETYPE_CONFIG"; then
     if test -n "$FREETYPE_DIR"; then
       libft_INCLUDES="`$FREETYPE_CONFIG --cflags` -I$FREETYPE_DIR/include"
-      libft_LDFLAGS=`$FREETYPE_CONFIG --libs |sed 's/-l[[^ ]][[^ ]]*//g'`
     else
       libft_INCLUDES=`$FREETYPE_CONFIG --cflags`
-      libft_LDFLAGS=`$FREETYPE_CONFIG --libs |sed 's/-l[[^ ]][[^ ]]*//g'`
     fi
+    libft_LDFLAGS=`$FREETYPE_CONFIG --libs`
+    libft_LDFLAGS=`echo " $libft_LDFLAGS" |sed 's/ -l[[^ ]][[^ ]]*//g'`
   else
     if test -n "$FREETYPE_DIR"; then
       libft_INCLUDES="-I$FREETYPE_DIR/include/freetype2 -I$FREETYPE_DIR/include"
 #include "gd.h"
 #include "gdhelpers.h"
 
-#define gdImageBoundsSafeMacro(im, x, y) (!((((y) < 0) || ((y) >= (im)->sy)) || (((x) < 0) || ((x) >= (im)->sx))))
+/* 2.0.12: this now checks the clipping rectangle */
+#define gdImageBoundsSafeMacro(im, x, y) (!((((y) < (im)->cy1) || ((y) > (im)->cy2)) || (((x) < (im)->cx1) || ((x) > (im)->cx2))))
 
 #ifdef _OSD_POSIX		/* BS2000 uses the EBCDIC char set instead of ASCII */
 #define CHARSET_EBCDIC
 
 static void gdImageBrushApply (gdImagePtr im, int x, int y);
 static void gdImageTileApply (gdImagePtr im, int x, int y);
+static void gdImageAntiAliasedApply (gdImagePtr im, int x, int y);
 static int gdImageGetTrueColorPixel (gdImagePtr im, int x, int y);
 
 gdImagePtr
   memset (im, 0, sizeof (gdImage));
   /* Row-major ever since gd 1.3 */
   im->pixels = (unsigned char **) gdMalloc (sizeof (unsigned char *) * sy);
+  im->AA_opacity =
+    (unsigned char **) gdMalloc (sizeof (unsigned char *) * sy);
   im->polyInts = 0;
   im->polyAllocated = 0;
   im->brush = 0;
     {
       /* Row-major ever since gd 1.3 */
       im->pixels[i] = (unsigned char *) gdCalloc (sx, sizeof (unsigned char));
+      im->AA_opacity[i] =
+	(unsigned char *) gdCalloc (sx, sizeof (unsigned char));
     }
   im->sx = sx;
   im->sy = sy;
   im->transparent = (-1);
   im->interlace = 0;
   im->thick = 1;
+  im->AA = 0;
+  im->AA_polygon = 0;
   for (i = 0; (i < gdMaxColors); i++)
     {
       im->open[i] = 1;
     };
   im->trueColor = 0;
   im->tpixels = 0;
+  im->cx1 = 0;
+  im->cy1 = 0;
+  im->cx2 = im->sx - 1;
+  im->cy2 = im->sy - 1;
   return im;
 }
 
   im = (gdImage *) gdMalloc (sizeof (gdImage));
   memset (im, 0, sizeof (gdImage));
   im->tpixels = (int **) gdMalloc (sizeof (int *) * sy);
+  im->AA_opacity =
+    (unsigned char **) gdMalloc (sizeof (unsigned char *) * sy);
   im->polyInts = 0;
   im->polyAllocated = 0;
   im->brush = 0;
   for (i = 0; (i < sy); i++)
     {
       im->tpixels[i] = (int *) gdCalloc (sx, sizeof (int));
+      im->AA_opacity[i] =
+	(unsigned char *) gdCalloc (sx, sizeof (unsigned char));
     }
   im->sx = sx;
   im->sy = sy;
   im->saveAlphaFlag = 0;
   im->alphaBlendingFlag = 1;
   im->thick = 1;
+  im->AA = 0;
+  im->AA_polygon = 0;
+  im->cx1 = 0;
+  im->cy1 = 0;
+  im->cx2 = im->sx - 1;
+  im->cy2 = im->sy - 1;
   return im;
 }
 
 	}
       gdFree (im->tpixels);
     }
+  if (im->AA_opacity)
+    {
+      for (i = 0; (i < im->sy); i++)
+	{
+	  gdFree (im->AA_opacity[i]);
+	}
+      gdFree (im->AA_opacity);
+    }
   if (im->polyInts)
     {
       gdFree (im->polyInts);
    the second call!)  The code is simplified from that in the article,
    as we know that gd images always start at (0,0) */
 
-static int clip_1d(int *x0, int *y0, int *x1, int *y1, int maxdim) {
-  double m;      /* gradient of line */
-  if(*x0 < 0) {  /* start of line is left of window */
-    if(*x1 < 0)  /* as is the end, so the line never cuts the window */
-      return 0;
-    m = (*y1 - *y0)/(double)(*x1 - *x0);  /* calculate the slope of the line */
-    /* adjust x0 to be on the left boundary (ie to be zero), and y0 to match */
-    *y0 -= m * *x0;
-    *x0 = 0;
-    /* now, perhaps, adjust the far end of the line as well */
-    if(*x1 > maxdim) {
+static int
+clip_1d (int *x0, int *y0, int *x1, int *y1, int maxdim)
+{
+  double m;			/* gradient of line */
+  if (*x0 < 0)
+    {				/* start of line is left of window */
+      if (*x1 < 0)		/* as is the end, so the line never cuts the window */
+	return 0;
+      m = (*y1 - *y0) / (double) (*x1 - *x0);	/* calculate the slope of the line */
+      /* adjust x0 to be on the left boundary (ie to be zero), and y0 to match */
+      *y0 -= m * *x0;
+      *x0 = 0;
+      /* now, perhaps, adjust the far end of the line as well */
+      if (*x1 > maxdim)
+	{
+	  *y1 += m * (maxdim - *x1);
+	  *x1 = maxdim;
+	}
+      return 1;
+    }
+  if (*x0 > maxdim)
+    {				/* start of line is right of window -
+				   complement of above */
+      if (*x1 > maxdim)		/* as is the end, so the line misses the window */
+	return 0;
+      m = (*y1 - *y0) / (double) (*x1 - *x0);	/* calculate the slope of the line */
+      *y0 += m * (maxdim - *x0);	/* adjust so point is on the right
+					   boundary */
+      *x0 = maxdim;
+      /* now, perhaps, adjust the end of the line */
+      if (*x1 < 0)
+	{
+	  *y1 -= m * *x1;
+	  *x1 = 0;
+	}
+      return 1;
+    }
+  /* the final case - the start of the line is inside the window */
+  if (*x1 > maxdim)
+    {				/* other end is outside to the right */
+      m = (*y1 - *y0) / (double) (*x1 - *x0);	/* calculate the slope of the line */
       *y1 += m * (maxdim - *x1);
       *x1 = maxdim;
+      return 1;
     }
-    return 1;
-  }
-  if(*x0 > maxdim) {   /* start of line is right of window -
-                          complement of above */
-    if(*x1 > maxdim)   /* as is the end, so the line misses the window */
-      return 0;
-    m = (*y1 - *y0)/(double)(*x1 - *x0);  /* calculate the slope of the line */
-    *y0 += m * (maxdim - *x0);    /* adjust so point is on the right
-                                     boundary */
-    *x0 = maxdim;                  
-    /* now, perhaps, adjust the end of the line */
-    if(*x1 < 0) {
+  if (*x1 < 0)
+    {				/* other end is outside to the left */
+      m = (*y1 - *y0) / (double) (*x1 - *x0);	/* calculate the slope of the line */
       *y1 -= m * *x1;
       *x1 = 0;
+      return 1;
     }
-    return 1;
-  }
-  /* the final case - the start of the line is inside the window */
-  if(*x1 > maxdim) {  /* other end is outside to the right */
-    m = (*y1 - *y0)/(double)(*x1 - *x0);  /* calculate the slope of the line */
-    *y1 += m * (maxdim - *x1);
-    *x1 = maxdim;
-    return 1;
-  }
-  if(*x1 < 0) {      /* other end is outside to the left */
-    m = (*y1 - *y0)/(double)(*x1 - *x0);  /* calculate the slope of the line */
-    *y1 -= m * *x1;
-    *x1 = 0;
-    return 1;
-  }
   /* only get here if both points are inside the window */
   return 1;
 }
     case gdTiled:
       gdImageTileApply (im, x, y);
       break;
+    case gdAntiAliased:
+      gdImageAntiAliasedApply (im, x, y);
+      break;
     default:
       if (gdImageBoundsSafeMacro (im, x, y))
 	{
   srcy = 0;
   if (im->trueColor)
     {
-      for (ly = y1; (ly < y2); ly++)
+      if (im->brush->trueColor)
 	{
-	  srcx = 0;
-	  for (lx = x1; (lx < x2); lx++)
+	  for (ly = y1; (ly < y2); ly++)
 	    {
-	      int p;
-	      p = gdImageGetTrueColorPixel (im->brush, srcx, srcy);
-	      /* 2.0.9, Thomas Winzig: apply simple full transparency */
-	      if (p != gdImageGetTransparent (im->brush))
+	      srcx = 0;
+	      for (lx = x1; (lx < x2); lx++)
 		{
-		  gdImageSetPixel (im, lx, ly, p);
+		  int p;
+		  p = gdImageGetTrueColorPixel (im->brush, srcx, srcy);
+		  /* 2.0.9, Thomas Winzig: apply simple full transparency */
+		  if (p != gdImageGetTransparent (im->brush))
+		    {
+		      gdImageSetPixel (im, lx, ly, p);
+		    }
+		  srcx++;
 		}
-	      srcx++;
+	      srcy++;
+	    }
+	}
+      else
+	{
+	  /* 2.0.12: Brush palette, image truecolor (thanks to Thorben Kundinger
+	     for pointing out the issue) */
+	  for (ly = y1; (ly < y2); ly++)
+	    {
+	      srcx = 0;
+	      for (lx = x1; (lx < x2); lx++)
+		{
+		  int p, tc;
+		  p = gdImageGetPixel (im->brush, srcx, srcy);
+		  tc = gdImageGetTrueColorPixel (im->brush, srcx, srcy);
+		  /* 2.0.9, Thomas Winzig: apply simple full transparency */
+		  if (p != gdImageGetTransparent (im->brush))
+		    {
+		      gdImageSetPixel (im, lx, ly, tc);
+		    }
+		  srcx++;
+		}
+	      srcy++;
 	    }
-	  srcy++;
 	}
     }
   else
     }
 }
 
+static void
+gdImageAntiAliasedApply (gdImagePtr im, int px, int py)
+{
+  float p_dist, p_alpha;
+  unsigned char opacity;
+
+  /* 
+   * Find the perpendicular distance from point C (px, py) to the line 
+   * segment AB that is being drawn.  (Adapted from an algorithm from the
+   * comp.graphics.algorithms FAQ.)
+   */
+
+  int LAC_2, LBC_2;
+
+  int Ax_Cx = im->AAL_x1 - px;
+  int Ay_Cy = im->AAL_y1 - py;
+
+  int Bx_Cx = im->AAL_x2 - px;
+  int By_Cy = im->AAL_y2 - py;
+
+  /* Get the squares of the lengths of the segemnts AC and BC. */
+  LAC_2 = (Ax_Cx * Ax_Cx) + (Ay_Cy * Ay_Cy);
+  LBC_2 = (Bx_Cx * Bx_Cx) + (By_Cy * By_Cy);
+
+  if (((im->AAL_LAB_2 + LAC_2) >= LBC_2) &&
+      ((im->AAL_LAB_2 + LBC_2) >= LAC_2))
+    {
+      /* The two angles are acute.  The point lies inside the portion of the 
+       * plane spanned by the line segment. */
+      p_dist = fabs ((float) ((Ay_Cy * im->AAL_Bx_Ax) -
+			      (Ax_Cx * im->AAL_By_Ay)) / im->AAL_LAB);
+    }
+  else
+    {
+      /* The point is past an end of the line segment.  It's length from the 
+       * segment is the shorter of the lengths from the endpoints, but call
+       * the distance -1, so as not to compute the alpha nor draw the pixel.
+       */
+      p_dist = -1;
+    }
+
+  if ((p_dist >= 0) && (p_dist <= (float) (im->thick)))
+    {
+      p_alpha = pow (1.0 - (p_dist / 1.5), 2);
+
+      if (p_alpha > 0)
+	{
+	  if (p_alpha >= 1)
+	    opacity = 255;
+	  else
+	    opacity = (unsigned char) (p_alpha * 255.0);
+	  if (!(im->AA_polygon) || (im->AA_opacity[py][px] < opacity))
+	    im->AA_opacity[py][px] = opacity;
+	}
+    }
+}
+
 int
 gdImageGetPixel (gdImagePtr im, int x, int y)
 {
     }
 }
 
+void
+gdImageAABlend (gdImagePtr im)
+{
+  float p_alpha, old_alpha;
+  int color = im->AA_color, color_red, color_green, color_blue;
+  int old_color, old_red, old_green, old_blue;
+  int p_color, p_red, p_green, p_blue;
+  int px, py;
+
+  color_red = gdImageRed (im, color);
+  color_green = gdImageGreen (im, color);
+  color_blue = gdImageBlue (im, color);
+
+  /* Impose the anti-aliased drawing on the image. */
+  for (py = 0; py < im->sy; py++)
+    {
+      for (px = 0; px < im->sx; px++)
+	{
+	  if (im->AA_opacity[py][px] != 0)
+	    {
+	      old_color = gdImageGetPixel (im, px, py);
+
+	      if ((old_color != color)
+		  && ((old_color != im->AA_dont_blend)
+		      || (im->AA_opacity[py][px] == 255)))
+		{
+		  /* Only blend with different colors that aren't the 
+		   * dont_blend color. */
+		  p_alpha = (float) (im->AA_opacity[py][px]) / 255.0;
+		  old_alpha = 1.0 - p_alpha;
+
+		  if (p_alpha >= 1.0)
+		    p_color = color;
+		  else
+		    {
+		      old_red = gdImageRed (im, old_color);
+		      old_green = gdImageGreen (im, old_color);
+		      old_blue = gdImageBlue (im, old_color);
+
+		      p_red = (int) (((float) color_red * p_alpha) +
+				     ((float) old_red * old_alpha));
+		      p_green = (int) (((float) color_green * p_alpha) +
+				       ((float) old_green * old_alpha));
+		      p_blue = (int) (((float) color_blue * p_alpha) +
+				      ((float) old_blue * old_alpha));
+		      p_color =
+			gdImageColorResolve (im, p_red, p_green, p_blue);
+		    }
+		  gdImageSetPixel (im, px, py, p_color);
+		}
+	    }
+	}
+      /* Clear the AA_opacity array behind us. */
+      memset (im->AA_opacity[py], 0, im->sx);
+    }
+}
+
 /* Bresenham as presented in Foley & Van Dam */
 void
 gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
   /* 2.0.10: Nick Atty: clip to edges of drawing rectangle, return if no
      points need to be drawn */
 
-  if(clip_1d(&x1,&y1,&x2,&y2,gdImageSX(im)) == 0)
+  if (clip_1d (&x1, &y1, &x2, &y2, gdImageSX (im)) == 0)
     return;
-  if(clip_1d(&y1,&x1,&y2,&x2,gdImageSY(im)) == 0)
+  if (clip_1d (&y1, &x1, &y2, &x2, gdImageSY (im)) == 0)
     return;
 
+  /* gdAntiAliased passed as color: set anti-aliased line (AAL) global vars. */
+  if (color == gdAntiAliased)
+    {
+      im->AAL_x1 = x1;
+      im->AAL_y1 = y1;
+      im->AAL_x2 = x2;
+      im->AAL_y2 = y2;
+
+      /* Compute what we can for point-to-line distance calculation later. */
+      im->AAL_Bx_Ax = x2 - x1;
+      im->AAL_By_Ay = y2 - y1;
+      im->AAL_LAB_2 =
+	(im->AAL_Bx_Ax * im->AAL_Bx_Ax) + (im->AAL_By_Ay * im->AAL_By_Ay);
+      im->AAL_LAB = sqrt (im->AAL_LAB_2);
+
+      /* For AA, we must draw pixels outside the width of the line.  Keep in
+       * mind that this will be curtailed by cos/sin of theta later. */
+      thick += 4;
+    }
+
   dx = abs (x2 - x1);
   dy = abs (y2 - y1);
   if (dy <= dx)
 	}
       else
 	{
-	  wid = thick * cos (atan2 (dy, dx));
+	  /* 2.0.12: Michael Schwartz: divide rather than multiply;
+	     TBB: but watch out for /0! */
+	  double ac = cos (atan2 (dy, dx));
+	  if (ac != 0)
+	    {
+	      wid = thick / ac;
+	    }
+	  else
+	    {
+	      wid = 1;
+	    }
 	  if (wid == 0)
 	    {
 	      wid = 1;
   else
     {
       /* More-or-less vertical. use wid for horizontal stroke */
-      wid = thick * sin (atan2 (dy, dx));
+      /* 2.0.12: Michael Schwartz: divide rather than multiply;
+         TBB: but watch out for /0! */
+      double as = sin (atan2 (dy, dx));
+      if (as != 0)
+	{
+	  wid = thick / as;
+	}
+      else
+	{
+	  wid = 1;
+	}
       if (wid == 0)
 	wid = 1;
 
 	    }
 	}
     }
+
+  /* If this is the only line we are drawing, go ahead and blend. */
+  if ((color == gdAntiAliased) && !(im->AA_polygon))
+    gdImageAABlend (im);
 }
 static void dashedSet (gdImagePtr im, int x, int y, int color,
 		       int *onP, int *dashStepP, int wid, int vert);
   if (dy <= dx)
     {
       /* More-or-less horizontal. use wid for vertical stroke */
-      wid = thick * sin (atan2 (dy, dx));
+      /* 2.0.12: Michael Schwartz: divide rather than multiply;
+         TBB: but watch out for /0! */
+      double as = sin (atan2 (dy, dx));
+      if (as != 0)
+	{
+	  wid = thick / as;
+	}
+      else
+	{
+	  wid = 1;
+	}
       vert = 1;
 
       d = 2 * dy - dx;
     }
   else
     {
-      /* More-or-less vertical. use wid for horizontal stroke */
-      wid = thick * sin (atan2 (dy, dx));
+      /* 2.0.12: Michael Schwartz: divide rather than multiply;
+         TBB: but watch out for /0! */
+      double as = sin (atan2 (dy, dx));
+      if (as != 0)
+	{
+	  wid = thick / as;
+	}
+      else
+	{
+	  wid = 1;
+	}
       vert = 0;
 
       d = 2 * dx - dy;
 int
 gdImageBoundsSafe (gdImagePtr im, int x, int y)
 {
-  return gdImageBoundsSafeMacro(im, x, y);
+  return gdImageBoundsSafeMacro (im, x, y);
 }
 
 void
   int i;
   int lx = 0, ly = 0;
   int fx = 0, fy = 0;
-  int w2, h2;
-  w2 = w / 2;
-  h2 = h / 2;
   while (e < s)
     {
       e += 360;
   for (i = s; (i <= e); i++)
     {
       int x, y;
-      x = ((long) gdCosT[i % 360] * (long) w2 / 1024) + cx;
-      y = ((long) gdSinT[i % 360] * (long) h2 / 1024) + cy;
+      x = ((long) gdCosT[i % 360] * (long) w / (2 * 1024)) + cx;
+      y = ((long) gdSinT[i % 360] * (long) h / (2 * 1024)) + cy;
       if (i != s)
 	{
 	  if (!(style & gdChord))
   /* Nick Atty: limit the points at the edge.  Note that this also
      nicely kills any plotting for rectangles completely outside the
      window as it makes the tests in the for loops fail */
-  if(x1 < 0)
-    x1=0;
-  if(x1 > gdImageSX(im))
-    x1=gdImageSX(im);
-  if(y1 < 0)
+  if (x1 < 0)
+    x1 = 0;
+  if (x1 > gdImageSX (im))
+    x1 = gdImageSX (im);
+  if (y1 < 0)
     y1 = 0;
-  if(y1 > gdImageSY(im))
-    y1 = gdImageSY(im);
+  if (y1 > gdImageSY (im))
+    y1 = gdImageSY (im);
 
   for (y = y1; (y <= y2); y++)
     {
     {
       /* 2.0: much easier when the destination is truecolor. */
       /* 2.0.10: needs a transparent-index check that is still valid if
-        the source is not truecolor. Thanks to Frank Warmerdam. */
+         the source is not truecolor. Thanks to Frank Warmerdam. */
       for (y = 0; (y < h); y++)
 	{
 	  for (x = 0; (x < w); x++)
 	    {
-              int p = gdImageGetPixel(src, srcX + x, srcY + y);
-              if (p != src->transparent) {
-	        int c = gdImageGetTrueColorPixel (src, srcX + x,
-						srcY + y);
-		gdImageSetPixel (dst, dstX + x, dstY + y, c);
-              }
+	      int p = gdImageGetPixel (src, srcX + x, srcY + y);
+	      if (p != src->transparent)
+		{
+		  int c = gdImageGetTrueColorPixel (src, srcX + x,
+						    srcY + y);
+		  gdImageSetPixel (dst, dstX + x, dstY + y, c);
+		}
 	    }
 	}
       return;
 	      tox++;
 	      continue;
 	    }
-	  /* If it's the same image, mapping is trivial */
-	  if (dst == src)
+	  /* 
+	   * If it's the same image, mapping is NOT trivial since we 
+	   * merge with greyscale target, but if pct is 100, the grey 
+	   * value is not used, so it becomes trivial. pjw 2.0.12. 
+	   */
+	  if (dst == src && pct == 100)
 	    {
 	      nc = c;
 	    }
 		+ 0.58700 * dst->green[dc] + 0.11400 * dst->blue[dc];
 
 	      ncR = gdImageRed (src, c) * (pct / 100.0)
-		+ gdImageRed (dst, dc) * g * ((100 - pct) / 100.0);
+		+ g * ((100 - pct) / 100.0);
 	      ncG = gdImageGreen (src, c) * (pct / 100.0)
-		+ gdImageGreen (dst, dc) * g * ((100 - pct) / 100.0);
+		+ g * ((100 - pct) / 100.0);
 	      ncB = gdImageBlue (src, c) * (pct / 100.0)
-		+ gdImageBlue (dst, dc) * g * ((100 - pct) / 100.0);
+		+ g * ((100 - pct) / 100.0);
 
 	      /* First look for an exact match */
 	      nc = gdImageColorExact (dst, ncR, ncG, ncB);
     {
       return;
     }
+
+  /* Let it be known that we are drawing a polygon so that the opacity
+   * mask doesn't get cleared after each line. */
+  if (c == gdAntiAliased)
+    im->AA_polygon = 1;
+
   lx = p->x;
   ly = p->y;
   gdImageLine (im, lx, ly, p[n - 1].x, p[n - 1].y, c);
       lx = p->x;
       ly = p->y;
     }
+
+  if (c == gdAntiAliased)
+    {
+      im->AA_polygon = 0;
+      gdImageAABlend (im);
+    }
 }
 
 int gdCompareInt (const void *a, const void *b);
   int x2, y2;
   int ind1, ind2;
   int ints;
+  int fill_color;
   if (!n)
     {
       return;
     }
+
+  if (c == gdAntiAliased)
+    fill_color = im->AA_color;
+  else
+    fill_color = c;
+
   if (!im->polyAllocated)
     {
       im->polyInts = (int *) gdMalloc (sizeof (int) * n);
 	    {
 	      continue;
 	    }
+
+	  /* Do the following math as float intermediately, and round to ensure
+	   * that Polygon and FilledPolygon for the same set of points have the
+	   * same footprint. */
 	  if ((y >= y1) && (y < y2))
 	    {
-	      im->polyInts[ints++] = (y - y1) * (x2 - x1) / (y2 - y1) + x1;
+	      im->polyInts[ints++] = (float) ((y - y1) * (x2 - x1)) /
+		(float) (y2 - y1) + 0.5 + x1;
 	    }
 	  else if ((y == maxy) && (y > y1) && (y <= y2))
 	    {
-	      im->polyInts[ints++] = (y - y1) * (x2 - x1) / (y2 - y1) + x1;
+	      im->polyInts[ints++] = (float) ((y - y1) * (x2 - x1)) /
+		(float) (y2 - y1) + 0.5 + x1;
 	    }
 	}
       qsort (im->polyInts, ints, sizeof (int), gdCompareInt);
 
       for (i = 0; (i < (ints)); i += 2)
 	{
-	  gdImageLine (im, im->polyInts[i], y, im->polyInts[i + 1], y, c);
+	  gdImageLine (im, im->polyInts[i], y, im->polyInts[i + 1], y,
+		       fill_color);
 	}
     }
+
+  /* If we are drawing this AA, then redraw the border with AA lines. */
+  if (c == gdAntiAliased)
+    gdImagePolygon (im, p, n, c);
 }
 
 int
 }
 
 void
+gdImageSetAntiAliased (gdImagePtr im, int c)
+{
+  im->AA = 1;
+  im->AA_color = c;
+  im->AA_dont_blend = -1;
+}
+
+void
+gdImageSetAntiAliasedDontBlend (gdImagePtr im, int c, int dont_blend)
+{
+  im->AA = 1;
+  im->AA_color = c;
+  im->AA_dont_blend = dont_blend;
+}
+
+void
 gdImageInterlace (gdImagePtr im, int interlaceArg)
 {
   im->interlace = interlaceArg;
     {
       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;
 int
 gdAlphaBlend (int dst, int src)
 {
-  return (((((gdAlphaTransparent - gdTrueColorGetAlpha (src)) *
+  /* 2.0.12: TBB: alpha in the destination should be a 
+     component of the result. Thanks to Frank Warmerdam for
+     pointing out the issue. */
+  return ((((gdTrueColorGetAlpha (src) *
+	     gdTrueColorGetAlpha (dst)) / gdAlphaMax) << 24) +
+	  ((((gdAlphaTransparent - gdTrueColorGetAlpha (src)) *
 	     gdTrueColorGetRed (src) / gdAlphaMax) +
 	    (gdTrueColorGetAlpha (src) *
 	     gdTrueColorGetRed (dst)) / gdAlphaMax) << 16) +
 {
   im->saveAlphaFlag = saveAlphaArg;
 }
+
+void
+gdImageSetClip (gdImagePtr im, int x1, int y1, int x2, int y2)
+{
+  if (x1 < 0) {
+    x1 = 0;
+  }
+  if (x1 >= im->sx) {
+    x1 = im->sx - 1;
+  }
+  if (x2 < 0) {
+    x2 = 0;
+  }
+  if (x2 >= im->sx) {
+    x2 = im->sx - 1;
+  }
+  if (y1 < 0) {
+    y1 = 0;
+  }
+  if (y1 >= im->sy) {
+    y1 = im->sy - 1;
+  }
+  if (y2 < 0) {
+    y2 = 0;
+  }
+  if (y2 >= im->sy) {
+    y2 = im->sy - 1;
+  }
+  im->cx1 = x1;
+  im->cy1 = y1;
+  im->cx2 = x2;
+  im->cy2 = y2;
+}
+
+void
+gdImageGetClip (gdImagePtr im, int *x1P, int *y1P, int *x2P, int *y2P)
+{
+  *x1P = im->cx1;
+  *y1P = im->cy1;
+  *x2P = im->cx2;
+  *y2P = im->cy2;
+}
+
 {
 #endif
 
+/* some might want to set DEFAULT_FONTPATH from configure in config.h */
+#ifndef DEFAULT_FONTPATH
 /* default fontpath for unix systems  - whatever happened to standards ! */
 #define DEFAULT_FONTPATH "/usr/X11R6/lib/X11/fonts/TrueType:/usr/X11R6/lib/X11/fonts/truetype:/usr/X11R6/lib/X11/fonts/TTF:/usr/share/fonts/TrueType:/usr/share/fonts/truetype:/usr/openwin/lib/X11/fonts/TrueType:/usr/X11R6/lib/X11/fonts/Type1"
+#endif
+#ifndef PATHSEPARATOR
 #define PATHSEPARATOR ":"
+#endif
 
 /* gd.h: declarations file for the graphic-draw module.
  * Permission to use, copy, modify, and distribute this software and its
        PNG at the moment; other future formats may also
        have that capability. JPEG doesn't. */
     int saveAlphaFlag;
+
+    /* 2.0.12: anti-aliased globals */
+    int AA;
+    int AA_color;
+    int AA_dont_blend;
+    unsigned char **AA_opacity;
+    int AA_polygon;
+    /* Stored and pre-computed variables for determining the perpendicular
+       distance from a point to the anti-aliased line being drawn: */
+    int AAL_x1;
+    int AAL_y1;
+    int AAL_x2;
+    int AAL_y2;
+    int AAL_Bx_Ax;
+    int AAL_By_Ay;
+    int AAL_LAB_2;
+    float AAL_LAB;
+
+    /* 2.0.12: simple clipping rectangle. These values
+      must be checked for safety when set; please use
+      gdImageSetClip */
+    int cx1;
+    int cy1;
+    int cx2;
+    int cy2;
   }
   gdImage;
 
 	This is used in line styles only. */
 #define gdTransparent (-6)
 
+#define gdAntiAliased (-7)
+
 /* Functions to manipulate images. */
 
 /* Creates a palette-based image (up to 256 colors). */
 
   int gdImageGetPixel (gdImagePtr im, int x, int y);
 
+  void gdImageAABlend (gdImagePtr im);
+
   void gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color);
 
 /* For backwards compatibility only. Use gdImageSetStyle()
 /* Solid bar. Upper left corner first, lower right corner second. */
   void gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2,
 			       int color);
+  void gdImageSetClip(gdImagePtr im, int x1, int y1, int x2, int y2);
+  void gdImageGetClip(gdImagePtr im, int *x1P, int *y1P, int *x2P, int *y2P);
   int gdImageBoundsSafe (gdImagePtr im, int x, int y);
   void gdImageChar (gdImagePtr im, gdFontPtr f, int x, int y, int c,
 		    int color);
 
   typedef struct
   {
-    int flags;			/* for future expansion logical OR of gdFTEX_ values */
+    int flags;			/* Logical OR of gdFTEX_ values */
     double linespacing;		/* fine tune line spacing for '\n' */
+    int charmap;		/* TBB: 2.0.12: may be gdFTEX_Unicode,
+				   gdFTEX_Shift_JIS, or gdFTEX_Big5;
+				   when not specified, maps are searched
+				   for in the above order. */
   }
   gdFTStringExtra, *gdFTStringExtraPtr;
 
 #define gdFTEX_LINESPACE 1
+#define gdFTEX_CHARMAP 2
+
+/* These are NOT flags; set one in 'charmap' if you set the
+	gdFTEX_CHARMAP bit in 'flags'. */
+#define gdFTEX_Unicode 0
+#define gdFTEX_Shift_JIS 1
+#define gdFTEX_Big5 2
 
   char *gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
 			   double ptsize, double angle, int x, int y,
   void gdImagePaletteCopy (gdImagePtr dst, gdImagePtr src);
   void gdImagePng (gdImagePtr im, FILE * out);
   void gdImagePngCtx (gdImagePtr im, gdIOCtx * out);
+  /* 2.0.12: Compression level: 0-9 or -1, where 0 is NO COMPRESSION at all,
+     1 is FASTEST but produces larger files, 9 provides the best
+     compression (smallest files) but takes a long time to compress, and
+     -1 selects the default compiled into the zlib library. */
+  void gdImagePngEx (gdImagePtr im, FILE * out, int level);
+  void gdImagePngCtxEx (gdImagePtr im, gdIOCtx * out, int level);
 
   void gdImageWBMP (gdImagePtr image, int fg, FILE * out);
   void gdImageWBMPCtx (gdImagePtr image, int fg, gdIOCtx * out);
 
 /* Best to free this memory with gdFree(), not free() */
   void *gdImagePngPtr (gdImagePtr im, int *size);
+  void *gdImagePngPtrEx (gdImagePtr im, int *size, int level);
 
 /* Best to free this memory with gdFree(), not free() */
   void *gdImageGdPtr (gdImagePtr im, int *size);
 
   void gdImageSetBrush (gdImagePtr im, gdImagePtr brush);
   void gdImageSetTile (gdImagePtr im, gdImagePtr tile);
+  void gdImageSetAntiAliased (gdImagePtr im, int c);
+  void gdImageSetAntiAliasedDontBlend (gdImagePtr im, int c, int dont_blend);
   void gdImageSetStyle (gdImagePtr im, int *style, int noOfPixels);
 /* Line thickness (defaults to 1). Affects lines, ellipses, 
 	rectangles, polygons and so forth. */
   int x, y, w, h;
   if ((argc != 3) && (argc != 7))
     {
-      fprintf (stderr, "Usage: gd2topng filename.gd2 filename.png [srcx srcy width height]\n");
-      fprintf (stderr, "If the coordinates are absent,t he entire image is converted.\n");
+      fprintf (stderr,
+	       "Usage: gd2topng filename.gd2 filename.png [srcx srcy width height]\n");
+      fprintf (stderr,
+	       "If the coordinates are absent,t he entire image is converted.\n");
       exit (1);
     }
-  if (argc == 7) {
-    x = atoi(argv[3]);
-    y = atoi(argv[4]);
-    w = atoi(argv[5]);
-    h = atoi(argv[6]);
-  }
+  if (argc == 7)
+    {
+      x = atoi (argv[3]);
+      y = atoi (argv[4]);
+      w = atoi (argv[5]);
+      h = atoi (argv[6]);
+    }
   in = fopen (argv[1], "rb");
   if (!in)
     {
       fprintf (stderr, "Input file does not exist!\n");
       exit (1);
     }
-  if (argc == 7) {
-    im = gdImageCreateFromGd2Part (in, x, y, w, h);
-  } else {
-    im = gdImageCreateFromGd2 (in);
-  }
+  if (argc == 7)
+    {
+      im = gdImageCreateFromGd2Part (in, x, y, w, h);
+    }
+  else
+    {
+      im = gdImageCreateFromGd2 (in);
+    }
   fclose (in);
   if (!im)
     {
   int i;
   if (gd2xFlag)
     {
-      if (!gdGetByte (&im->trueColor, in))
+      int trueColorFlag;
+      if (!gdGetByte (&trueColorFlag, in))
+	{
+	  goto fail1;
+	}
+      /* 2.0.12: detect bad truecolor .gd files created by pre-2.0.12.
+         Beginning in 2.0.12 truecolor is indicated by the initial 2-byte
+         signature. */
+      if (trueColorFlag != im->trueColor)
 	{
 	  goto fail1;
 	}
   GD2_DBG (printf
 	   ("Pallette had %d colours (T=%d)\n", im->colorsTotal,
 	    im->transparent));
-
+  if (im->trueColor)
+    {
+      return TRUE;
+    }
   for (i = 0; (i < gdMaxColors); i++)
     {
       if (!gdGetByte (&im->red[i], in))
 
 /* */
 /* Use the common basic header info to make the image object. */
-/* This is also called from _gd2CreateFromFile */
 /* */
 static gdImagePtr
 _gdCreateFromFile (gdIOCtx * in, int *sx, int *sy)
 {
   gdImagePtr im;
   int gd2xFlag = 0;
+  int trueColorFlag = 0;
   if (!gdGetWord (sx, in))
     {
       goto fail1;
     }
-  if (*sx == 65535)
+  if ((*sx == 65535) || (*sx == 65534))
     {
       /* This is a gd 2.0 .gd file */
       gd2xFlag = 1;
+      /* 2.0.12: 65534 signals a truecolor .gd file. 
+         There is a slight redundancy here but we can
+         live with it. */
+      if (*sx == 65534)
+	{
+	  trueColorFlag = 1;
+	}
       if (!gdGetWord (sx, in))
 	{
 	  goto fail1;
     }
 
   GD2_DBG (printf ("Image is %dx%d\n", *sx, *sy));
-
-  im = gdImageCreate (*sx, *sy);
-
+  if (trueColorFlag)
+    {
+      im = gdImageCreateTrueColor (*sx, *sy);
+    }
+  else
+    {
+      im = gdImageCreate (*sx, *sy);
+    }
   if (!_gdGetColors (in, im, gd2xFlag))
     {
       goto fail2;
     };
 
   /* Then the data... */
-  for (y = 0; (y < sy); y++)
+  /* 2.0.12: support truecolor properly in .gd as well as in .gd2.
+     Problem reported by Andreas Pfaller. */
+  if (im->trueColor)
     {
-      for (x = 0; (x < sx); x++)
+      for (y = 0; (y < sy); y++)
 	{
-	  int ch;
-	  ch = gdGetC (in);
-	  if (ch == EOF)
+	  for (x = 0; (x < sx); x++)
 	    {
-	      goto fail2;
+	      int pix;
+	      if (!gdGetInt (&pix, in))
+		{
+		  goto fail2;
+		}
+	      im->tpixels[y][x] = pix;
+	    }
+	}
+    }
+  else
+    {
+      for (y = 0; (y < sy); y++)
+	{
+	  for (x = 0; (x < sx); x++)
+	    {
+	      int ch;
+	      ch = gdGetC (in);
+	      if (ch == EOF)
+		{
+		  goto fail2;
+		}
+	      /* ROW-MAJOR IN GD 1.3 */
+	      im->pixels[y][x] = ch;
 	    }
-	  /* ROW-MAJOR IN GD 1.3 */
-	  im->pixels[y][x] = ch;
 	}
     }
-
   return im;
 
 fail2:
 static void
 _gdPutHeader (gdImagePtr im, gdIOCtx * out)
 {
-  /* 65535 indicates this is a gd 2.x .gd file. */
-  gdPutWord (65535, out);
+  /* 65535 indicates this is a gd 2.x .gd file. 
+     2.0.12: 65534 indicates truecolor. */
+  if (im->trueColor)
+    {
+      gdPutWord (65534, out);
+    }
+  else
+    {
+      gdPutWord (65535, out);
+    }
   gdPutWord (im->sx, out);
   gdPutWord (im->sy, out);
 
   GD2_DBG (printf ("Format: %d\n", *fmt));
 
   if ((*fmt != GD2_FMT_RAW) && (*fmt != GD2_FMT_COMPRESSED) &&
-		(*fmt != GD2_FMT_TRUECOLOR_RAW) &&
-		(*fmt != GD2_FMT_TRUECOLOR_COMPRESSED))
+      (*fmt != GD2_FMT_TRUECOLOR_RAW) &&
+      (*fmt != GD2_FMT_TRUECOLOR_COMPRESSED))
     {
       GD2_DBG (printf ("Bad data format: %d\n", *fmt));
       goto fail1;
     };
   GD2_DBG (printf ("%d Chunks vertically\n", *ncy));
 
-  if (gd2_compressed(*fmt))
+  if (gd2_compressed (*fmt))
     {
       nc = (*ncx) * (*ncy);
       GD2_DBG (printf ("Reading %d chunk index entries\n", nc));
       GD2_DBG (printf ("Bad GD2 header\n"));
       goto fail1;
     }
-  if (gd2_truecolor(*fmt)) {
-    im = gdImageCreateTrueColor (*sx, *sy);
-  } else {
-    im = gdImageCreate (*sx, *sy);
-  }
+  if (gd2_truecolor (*fmt))
+    {
+      im = gdImageCreateTrueColor (*sx, *sy);
+    }
+  else
+    {
+      im = gdImageCreate (*sx, *sy);
+    }
   if (im == NULL)
     {
       GD2_DBG (printf ("Could not create gdImage\n"));
   bytesPerPixel = im->trueColor ? 4 : 1;
   nc = ncx * ncy;
 
-  if (gd2_compressed(fmt)) 
+  if (gd2_compressed (fmt))
     {
       /* Find the maximum compressed chunk size. */
       compMax = 0;
 		   ("Processing Chunk %d (%d, %d), y from %d to %d\n",
 		    chunkNum, cx, cy, ylo, yhi));
 
-	  if (gd2_compressed(fmt))
+	  if (gd2_compressed (fmt))
 	    {
 
 	      chunkLen = chunkMax;
 	      if (!_gd2ReadChunk (chunkIdx[chunkNum].offset,
 				  compBuf,
 				  chunkIdx[chunkNum].size,
-				  chunkBuf, &chunkLen, in))
+				  (char *) chunkBuf, &chunkLen, in))
 		{
 		  GD2_DBG (printf ("Error reading comproessed chunk\n"));
 		  goto fail2;
 		  xhi = im->sx;
 		};
 	      /*GD2_DBG(printf("y=%d: ",y)); */
-	      if (!gd2_compressed(fmt)) 
+	      if (!gd2_compressed (fmt))
 		{
 		  for (x = xlo; x < xhi; x++)
 		    {
 			  int r = chunkBuf[chunkPos++] << 16;
 			  int g = chunkBuf[chunkPos++] << 8;
 			  int b = chunkBuf[chunkPos++];
-                          /* 2.0.11: tpixels */
+			  /* 2.0.11: tpixels */
 			  im->tpixels[y][x] = a + r + g + b;
 			}
 		      else
   int x, y, ylo, yhi, xlo, xhi;
   int dstart, dpos;
   int i;
-  int ch, vers, fmt;
+  /* 2.0.12: unsigned is correct; fixes problems with color munging.
+     Thanks to Steven Brown. */
+  unsigned int ch;
+  int vers, fmt;
   t_chunk_info *chunkIdx = NULL;
-  char *chunkBuf = NULL;
+  unsigned char *chunkBuf = NULL;
   int chunkNum;
   int chunkMax = 0;
   uLongf chunkLen;
   GD2_DBG (printf ("File size is %dx%d\n", fsx, fsy));
 
   /* This is the difference - make a file based on size of chunks. */
-  if (gd2_truecolor(fmt)) {
-    im = gdImageCreateTrueColor (w, h);
-  } else {
-    im = gdImageCreate (w, h);
-  }
+  if (gd2_truecolor (fmt))
+    {
+      im = gdImageCreateTrueColor (w, h);
+    }
+  else
+    {
+      im = gdImageCreate (w, h);
+    }
   if (im == NULL)
     {
       goto fail1;
   /* Process the header info */
   nc = ncx * ncy;
 
-  if (gd2_compressed(fmt)) 
+  if (gd2_compressed (fmt))
     {
       /* Find the maximum compressed chunk size. */
       compMax = 0;
 		   ("Processing Chunk (%d, %d), from %d to %d\n", cx, cy, ylo,
 		    yhi));
 
-	  if (!gd2_compressed(fmt)) 
+	  if (!gd2_compressed (fmt))
 	    {
 	      GD2_DBG (printf ("Using raw format data\n"));
 	      if (im->trueColor)
 		{
 		  dpos =
-		    (cy * (cs * fsx) * 4 + cx * cs * (yhi - ylo) * 4) + dstart;
+		    (cy * (cs * fsx) * 4 + cx * cs * (yhi - ylo) * 4) +
+		    dstart;
 		}
 	      else
 		{
 		  dpos = cy * (cs * fsx) + cx * cs * (yhi - ylo) + dstart;
 		}
-              /* gd 2.0.11: gdSeek returns TRUE on success, not 0.
-                 Longstanding bug. 01/16/03 */
+	      /* gd 2.0.11: gdSeek returns TRUE on success, not 0.
+	         Longstanding bug. 01/16/03 */
 	      if (!gdSeek (in, dpos))
 		{
 		  printf ("Error from seek: %d\n", errno);
 
 	      for (x = xlo; x < xhi; x++)
 		{
-		  if (!gd2_compressed(fmt)) 
+		  if (!gd2_compressed (fmt))
 		    {
 		      if (im->trueColor)
 			{
 		      && (y >= srcy) && (y < (srcy + h)) && (y < fsy)
 		      && (y >= 0))
 		    {
-                      /* 2.0.11: tpixels */
-                      if (im->trueColor) {  
-		        im->tpixels[y - srcy][x - srcx] = ch;
-                      } else {
-		        im->pixels[y - srcy][x - srcx] = ch;
-                      }   
+		      /* 2.0.11: tpixels */
+		      if (im->trueColor)
+			{
+			  im->tpixels[y - srcy][x - srcx] = ch;
+			}
+		      else
+			{
+			  im->pixels[y - srcy][x - srcx] = ch;
+			}
 		    }
 		};
 	    };
   /* Force fmt to a valid value since we don't return anything. */
   /* */
   if ((fmt != GD2_FMT_RAW) && (fmt != GD2_FMT_COMPRESSED))
-  { 	
+    {
       fmt = im->trueColor ? GD2_FMT_TRUECOLOR_COMPRESSED : GD2_FMT_COMPRESSED;
-  };
-  if (im->trueColor) {
-    fmt += 2;
-  }
+    };
+  if (im->trueColor)
+    {
+      fmt += 2;
+    }
   /* */
   /* Make sure chunk size is valid. These are arbitrary values; 64 because it seems */
   /* a little silly to expect performance improvements on a 64x64 bit scale, and  */
   /* Write the standard header. */
   _gd2PutHeader (im, out, cs, fmt, ncx, ncy);
 
-  if (gd2_compressed(fmt)) 
+  if (gd2_compressed (fmt))
     {
       /* */
       /* Work out size of buffer for compressed data, If CHUNKSIZE is large, */
 		  xhi = im->sx;
 		};
 
-	      if (gd2_compressed(fmt))
+	      if (gd2_compressed (fmt))
 		{
 		  for (x = xlo; x < xhi; x++)
 		    {
-                      /* 2.0.11: use truecolor pixel array. TBB */
+		      /* 2.0.11: use truecolor pixel array. TBB */
 		      /*GD2_DBG(printf("%d...",x)); */
 		      if (im->trueColor)
 			{
-		          int p = im->tpixels[y][x];
+			  int p = im->tpixels[y][x];
 			  chunkData[chunkLen++] = gdTrueColorGetAlpha (p);
 			  chunkData[chunkLen++] = gdTrueColorGetRed (p);
 			  chunkData[chunkLen++] = gdTrueColorGetGreen (p);
 			}
 		      else
 			{
-		          int p = im->pixels[y][x];
+			  int p = im->pixels[y][x];
 			  chunkData[chunkLen++] = p;
 			}
 		    };
 		};
 	      /*GD2_DBG(printf("y=%d done.\n",y)); */
 	    };
-	  if (gd2_compressed(fmt))
+	  if (gd2_compressed (fmt))
 	    {
 	      compLen = compMax;
 	      if (compress ((unsigned char *)
 	    };
 	};
     };
-  if (gd2_compressed(fmt))
+  if (gd2_compressed (fmt))
     {
       /* Save the position, write the index, restore position (paranoia). */
       GD2_DBG (printf ("Seeking %d to write index\n", idxPos));
 
 #include <stdio.h>
 
+#ifdef VMS
+#define Putchar gdPutchar
+#endif
+
 typedef struct gdIOCtx
 {
   int (*getC) (struct gdIOCtx *);
   int (*putBuf) (struct gdIOCtx *, const void *, int);
 
   /* seek must return 1 on SUCCESS, 0 on FAILURE. Unlike fseek! */
-  int (*seek) (struct gdIOCtx *, const int); 
+  int (*seek) (struct gdIOCtx *, const int);
 
   long (*tell) (struct gdIOCtx *);
 
     }
   rowptr[0] = row;
 
-  for (i = 0; i < cinfo.output_height; i++) 
+  for (i = 0; i < cinfo.output_height; i++)
     {
       register JSAMPROW currow = row;
       register int *tpix = im->tpixels[i];
 		   " returns %u, expected 1\n", nrows);
 	  goto error;
 	}
-      for (j = 0; j < cinfo.output_width; j++, currow += 3, tpix++) 
-         {
-           *tpix = gdTrueColor (currow[0], currow[1], currow[2]);
-         }
+      for (j = 0; j < cinfo.output_width; j++, currow += 3, tpix++)
+	{
+	  *tpix = gdTrueColor (currow[0], currow[1], currow[2]);
+	}
     }
 
   if (jpeg_finish_decompress (&cinfo) != TRUE)
   gdIOCtx *infile;		/* source stream */
   unsigned char *buffer;	/* start of buffer */
   safeboolean start_of_file;	/* have we gotten any data yet? */
- 
+
 }
 my_source_mgr;
 
  */
 
 #define END_JPEG_SEQUENCE "\r\n[*]--:END JPEG:--[*]\r\n"
-  safeboolean
+safeboolean
 fill_input_buffer (j_decompress_ptr cinfo)
 {
   my_src_ptr src = (my_src_ptr) cinfo->src;
-  size_t nbytes = 0;
-  
-    /* size_t got; */
-    /* char *s; */
-    memset (src->buffer, 0, INPUT_BUF_SIZE);
-  
-while (nbytes < INPUT_BUF_SIZE)
+  /* 2.0.12: signed size. Thanks to Geert Jansen */
+  ssize_t nbytes = 0;
+
+  /* ssize_t got; */
+  /* char *s; */
+  memset (src->buffer, 0, INPUT_BUF_SIZE);
+
+  while (nbytes < INPUT_BUF_SIZE)
     {
-      
-int got = gdGetBuf (src->buffer + nbytes, 
-INPUT_BUF_SIZE - nbytes,
-			   src->infile);
-      
-if ((got == EOF) || (got == 0))
+
+      int got = gdGetBuf (src->buffer + nbytes,
+			  INPUT_BUF_SIZE - nbytes,
+			  src->infile);
+
+      if ((got == EOF) || (got == 0))
 	{
-	  
-	    /* EOF or error. If we got any data, don't worry about it.
-	       If we didn't, then this is unexpected. */ 
-	    if (!nbytes)
+
+	  /* EOF or error. If we got any data, don't worry about it.
+	     If we didn't, then this is unexpected. */
+	  if (!nbytes)
 	    {
-	      
-nbytes = -1;
-	    
-}
-	  
-break;
-	
-}
-      
-nbytes += got;
-    
-}
-  
-if (nbytes <= 0)
+
+	      nbytes = -1;
+
+	    }
+
+	  break;
+
+	}
+
+      nbytes += got;
+
+    }
+
+  if (nbytes <= 0)
     {
       if (src->start_of_file)	/* Treat empty input file as fatal error */
 	ERREXIT (cinfo, JERR_INPUT_EMPTY);
 void
 term_source (j_decompress_ptr cinfo)
 {
-  
+
 #if 0
 /* never used */
-    my_src_ptr src = (my_src_ptr) cinfo->src;
-  
+  my_src_ptr src = (my_src_ptr) cinfo->src;
+
 #endif
 }
 
       src->buffer = (unsigned char *)
 	(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
 				    INPUT_BUF_SIZE * sizeof (unsigned char));
-    
-}
+
+    }
 
   src = (my_src_ptr) cinfo->src;
   src->pub.init_source = init_source;
   if (!im->trueColor)
     {
       im->colorsTotal = num_palette;
-      im->transparent = transparent;
       /* load the palette and mark all entries "open" (unused) for now */
       open = im->open;
       for (i = 0; i < num_palette; ++i)
 	  open[i] = 1;
 	}
     }
+  /* 2.0.12: Slaven Rezic: palette images are not the only images
+     with a simple transparent color setting */
+  im->transparent = transparent;
   im->interlace = (interlace_type == PNG_INTERLACE_ADAM7);
 
   /* can't nuke structs until done with palette */
 
 
 void
+gdImagePngEx (gdImagePtr im, FILE * outFile, int level)
+{
+  gdIOCtx *out = gdNewFileCtx (outFile);
+  gdImagePngCtxEx (im, out, level);
+  out->gd_free (out);
+}
+
+void
 gdImagePng (gdImagePtr im, FILE * outFile)
 {
   gdIOCtx *out = gdNewFileCtx (outFile);
-  gdImagePngCtx (im, out);
+  gdImagePngCtxEx (im, out, -1);
   out->gd_free (out);
 }
 
 {
   void *rv;
   gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
-  gdImagePngCtx (im, out);
+  gdImagePngCtxEx (im, out, -1);
   rv = gdDPExtractData (out, size);
   out->gd_free (out);
   return rv;
 }
 
+void *
+gdImagePngPtrEx (gdImagePtr im, int *size, int level)
+{
+  void *rv;
+  gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
+  gdImagePngCtxEx (im, out, level);
+  rv = gdDPExtractData (out, size);
+  out->gd_free (out);
+  return rv;
+}
+
+void
+gdImagePngCtx (gdImagePtr im, gdIOCtx * outfile)
+{
+  return gdImagePngCtxEx (im, outfile, -1);
+}
+
 /* This routine is based in part on code from Dale Lutz (Safe Software Inc.)
  *  and in part on demo code from Chapter 15 of "PNG: The Definitive Guide"
  *  (http://www.cdrom.com/pub/png/pngbook.html).
  */
 void
-gdImagePngCtx (gdImagePtr im, gdIOCtx * outfile)
+gdImagePngCtxEx (gdImagePtr im, gdIOCtx * outfile, int level)
 {
   int i, j, bit_depth = 0, interlace_type;
   int width = im->sx;
      fussing with such things. */
 /*  png_set_filter(png_ptr, 0, PNG_FILTER_NONE);  */
 
-  /* may want to force maximum compression, but time penalty is large */
-/*  png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);  */
+  /* 2.0.12: this is finally a parameter */
+  png_set_compression_level (png_ptr, level);
 
   /* can set this to a smaller value without compromising compression if all
    * image data is 16K or less; will save some decoder memory [min == 8] */
+/* 2.0.12: a new adaptation from the same original, this time
+	by Barend Gehrels. My attempt to incorporate alpha channel
+	into the result worked poorly and degraded the quality of
+	palette conversion even when the source contained no
+	alpha channel data. This version does not attempt to produce
+	an output file with transparency in some of the palette
+	indexes, which, in practice, doesn't look so hot anyway. TBB */
+
 /*
- * gd_topal.c 
- * 
- * This code is adapted pretty much entirely from jquant2.c,
- * Copyright (C) 1991-1996, Thomas G. Lane. That file is
- * part of the Independent JPEG Group's software. Conditions of
- * use are compatible with the gd license. See the gd license 
- * statement and README-JPEG.TXT for additional information.
+ * gd_topal, adapted from jquant2.c
+ *
+ * Copyright (C) 1991-1996, Thomas G. Lane.
+ * This file is part of the Independent JPEG Group's software.
+ * For conditions of distribution and use, see the accompanying README file.
  *
  * This file contains 2-pass color quantization (color mapping) routines.
  * These routines provide selection of a custom color map for an image,
  * followed by mapping of the image to that color map, with optional
  * Floyd-Steinberg dithering.
- *
  * It is also possible to use just the second pass to map to an arbitrary
  * externally-given color map.
  *
  * Note: ordered dithering is not supported, since there isn't any fast
  * way to compute intercolor distances; it's unclear that ordered dither's
  * fundamental assumptions even hold with an irregularly spaced color map.
- *
- * SUPPORT FOR ALPHA CHANNELS WAS HACKED IN BY THOMAS BOUTELL, who also
- * adapted the code to work within gd rather than within libjpeg, and
- * may not have done a great job of either. It's not Thomas G. Lane's fault.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#ifdef ORIGINAL_LIB_JPEG
+
+#define JPEG_INTERNALS
+
+#include "jinclude.h"
+#include "jpeglib.h"
+
+#else
+
+/*
+ * THOMAS BOUTELL & BAREND GEHRELS, february 2003
+ * adapted the code to work within gd rather than within libjpeg.
+ * If it is not working, it's not Thomas G. Lane's fault.
+ */
+
+/* 
+  SETTING THIS ONE CAUSES STRIPED IMAGE
+  to be done: solve this
+  #define ORIGINAL_LIB_JPEG_REVERSE_ODD_ROWS
+ */
 
 #include <string.h>
 #include "gd.h"
 #include "gdhelpers.h"
 
+/* (Re)define some defines known by libjpeg */
+#define QUANT_2PASS_SUPPORTED
+
+#define RGB_RED		0
+#define RGB_GREEN	1
+#define RGB_BLUE	2
+
+#define JSAMPLE unsigned char
+#define MAXJSAMPLE (gdMaxColors-1)
+#define BITS_IN_JSAMPLE 8
+
+#define JSAMPROW int*
+#define JDIMENSION int
+
+#define METHODDEF(type) static type
+#define LOCAL(type)	static type
+
+
+/* We assume that right shift corresponds to signed division by 2 with
+ * rounding towards minus infinity.  This is correct for typical "arithmetic
+ * shift" instructions that shift in copies of the sign bit.  But some
+ * C compilers implement >> with an unsigned shift.  For these machines you
+ * must define RIGHT_SHIFT_IS_UNSIGNED.
+ * RIGHT_SHIFT provides a proper signed right shift of an INT32 quantity.
+ * It is only applied with constant shift counts.  SHIFT_TEMPS must be
+ * included in the variables of any routine using RIGHT_SHIFT.
+ */
+
+#ifdef RIGHT_SHIFT_IS_UNSIGNED
+#define SHIFT_TEMPS	INT32 shift_temp;
+#define RIGHT_SHIFT(x,shft)  \
+	((shift_temp = (x)) < 0 ? \
+	 (shift_temp >> (shft)) | ((~((INT32) 0)) << (32-(shft))) : \
+	 (shift_temp >> (shft)))
+#else
+#define SHIFT_TEMPS
+#define RIGHT_SHIFT(x,shft)	((x) >> (shft))
+#endif
+
+
+#define range_limit(x) { if(x<0) x=0; if (x>255) x=255; }
+
+
+#ifndef INT16
+#define INT16  short
+#endif
+
+#ifndef UINT16
+#define UINT16 unsigned short
+#endif
+
+#ifndef INT32
+#define INT32 int
+#endif
+
+#ifndef FAR
+#define FAR
+#endif
+
+
+
+#ifndef boolean
+#define boolean int
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+
+#define input_buf (im->tpixels)
+#define output_buf (im->pixels)
+
+#endif
+
+#ifdef QUANT_2PASS_SUPPORTED
+
+
 /*
  * This module implements the well-known Heckbert paradigm for color
  * quantization.  Most of the ideas used here can be traced back to
  * The present code works in the post-conversion color space, typically RGB.
  *
  * To improve the visual quality of the results, we actually work in scaled
- * RGBA space, giving G distances more weight than R, and R in turn more than
- * B.  Alpha is weighted least. To do everything in integer math, we must 
- * use integer scale factors. The 2/3/1 scale factors used here correspond 
- * loosely to the relative weights of the colors in the NTSC grayscale 
- * equation. 
+ * RGB space, giving G distances more weight than R, and R in turn more than
+ * B.  To do everything in integer math, we must use integer scale factors.
+ * The 2/3/1 scale factors used here correspond loosely to the relative
+ * weights of the colors in the NTSC grayscale equation.
+ * If you want to use this code to quantize a non-RGB color space, you'll
+ * probably need to change these scale factors.
  */
 
-#ifndef TRUE
-#define TRUE 1
-#endif /* TRUE */
-
-#ifndef FALSE
-#define FALSE 0
-#endif /* FALSE */
-
 #define R_SCALE 2		/* scale R distances by this much */
 #define G_SCALE 3		/* scale G distances by this much */
 #define B_SCALE 1		/* and B by this much */
-#define A_SCALE 4		/* and alpha by this much. This really
-				   only scales by 1 because alpha
-				   values are 7-bit to begin with. */
 
-/* Channel ordering (fixed in gd) */
+/* Relabel R/G/B as components 0/1/2, respecting the RGB ordering defined
+ * in jmorecfg.h.  As the code stands, it will do the right thing for R,G,B
+ * and B,G,R orders.  If you define some other weird order in jmorecfg.h,
+ * you'll get compile errors until you extend this logic.  In that case
+ * you'll probably want to tweak the histogram sizes too.
+ */
+
+#if RGB_RED == 0
 #define C0_SCALE R_SCALE
+#endif
+#if RGB_BLUE == 0
+#define C0_SCALE B_SCALE
+#endif
+#if RGB_GREEN == 1
 #define C1_SCALE G_SCALE
+#endif
+#if RGB_RED == 2
+#define C2_SCALE R_SCALE
+#endif
+#if RGB_BLUE == 2
 #define C2_SCALE B_SCALE
-#define C3_SCALE A_SCALE
+#endif
+
 
 /*
  * First we have the histogram data structure and routines for creating it.
  * arrays are in far memory (same arrangement as we use for image arrays).
  */
 
-#define MAXNUMCOLORS  (gdMaxColors)	/* maximum size of colormap */
+#define MAXNUMCOLORS  (MAXJSAMPLE+1)	/* maximum size of colormap */
 
-#define HIST_C0_BITS  5		/* bits of precision in R histogram */
+/* These will do the right thing for either R,G,B or B,G,R color order,
+ * but you may not like the results for other color orders.
+ */
+#define HIST_C0_BITS  5		/* bits of precision in R/B histogram */
 #define HIST_C1_BITS  6		/* bits of precision in G histogram */
-#define HIST_C2_BITS  5		/* bits of precision in B histogram */
-#define HIST_C3_BITS  3		/* bits of precision in A histogram */
+#define HIST_C2_BITS  5		/* bits of precision in B/R histogram */