Anonymous avatar Anonymous committed 0a3439a

- sync to 2.0.23

Comments (0)

Files changed (18)

src/circletexttest.c

 int
 main (int argc, char *argv[])
 {
-	/* 2.0.22: can't depend on PNG either  */
+  /* 2.0.22: can't depend on PNG either  */
 #ifndef HAVE_LIBPNG
-	fprintf(stderr, "Requires PNG support, gd was compiled without it\n");
-	exit(0);
+  fprintf (stderr, "Requires PNG support, gd was compiled without it\n");
+  exit (0);
 #else
-	FILE *in = 0;
-	FILE *out;
-	gdImagePtr im;
-	int radius;
-	/* Create an image of text on a circle, with an
-		alpha channel so that we can copy it onto a
-		background */
-	/* TBB: 2.0.18: shouldn't depend on JPEG */
+  FILE *in = 0;
+  FILE *out;
+  gdImagePtr im;
+  int radius;
+  /* Create an image of text on a circle, with an
+     alpha channel so that we can copy it onto a
+     background */
+  /* TBB: 2.0.18: shouldn't depend on JPEG */
 #ifdef HAVE_LIBJPEG
-	in = fopen("eleanor.jpg", "rb");
-	if (!in) {
-		im = gdImageCreateTrueColor(300, 300);
-	} else {
-		im = gdImageCreateFromJpeg(in);
-		fclose(in);
-	}
+  in = fopen ("eleanor.jpg", "rb");
+  if (!in)
+    {
+      im = gdImageCreateTrueColor (300, 300);
+    }
+  else
+    {
+      im = gdImageCreateFromJpeg (in);
+      fclose (in);
+    }
 #else
-	im = gdImageCreateTrueColor(300, 300);
-#endif /* HAVE_LIBJPEG */	
-	if (gdImageSX(im) < gdImageSY(im)) {
-		radius = gdImageSX(im) / 2;
-	} else {
-		radius = gdImageSY(im) / 2;
-	}
-	gdImageStringFTCircle(
-		im,
-		gdImageSX(im) / 2,
-		gdImageSY(im) / 2,
-		radius,
-		radius / 2,
-		0.8,
-		"arial",
-		24,
-		"top text",
-		"bottom text",
-		gdTrueColorAlpha(192, 100, 255, 32));
-	out = fopen("gdfx.png", "wb");
-	if (!out) {
-		fprintf(stderr, "Can't create gdfx.png\n");
-		return 1;
-	}
-	gdImagePng(im, out);
-	fclose(out);
-	gdImageDestroy(im);
+  im = gdImageCreateTrueColor (300, 300);
+#endif /* HAVE_LIBJPEG */
+  if (gdImageSX (im) < gdImageSY (im))
+    {
+      radius = gdImageSX (im) / 2;
+    }
+  else
+    {
+      radius = gdImageSY (im) / 2;
+    }
+  gdImageStringFTCircle (im,
+			 gdImageSX (im) / 2,
+			 gdImageSY (im) / 2,
+			 radius,
+			 radius / 2,
+			 0.8,
+			 "arial",
+			 24,
+			 "top text",
+			 "bottom text", gdTrueColorAlpha (192, 100, 255, 32));
+  out = fopen ("gdfx.png", "wb");
+  if (!out)
+    {
+      fprintf (stderr, "Can't create gdfx.png\n");
+      return 1;
+    }
+  gdImagePng (im, out);
+  fclose (out);
+  gdImageDestroy (im);
 #endif /* HAVE_LIBPNG */
-	return 0;
+  return 0;
 }
-
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.57 for GD 2.0.22.
+# Generated by GNU Autoconf 2.57 for GD 2.0.23.
 #
 # Report bugs to <gd@boutell.com>.
 #
 # Identity of this package.
 PACKAGE_NAME='GD'
 PACKAGE_TARNAME='gd'
-PACKAGE_VERSION='2.0.22'
-PACKAGE_STRING='GD 2.0.22'
+PACKAGE_VERSION='2.0.23'
+PACKAGE_STRING='GD 2.0.23'
 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.22 to adapt to many kinds of systems.
+\`configure' configures GD 2.0.23 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.22:";;
+     short | recursive ) echo "Configuration of GD 2.0.23:";;
    esac
   cat <<\_ACEOF
 
 test -n "$ac_init_help" && exit 0
 if $ac_init_version; then
   cat <<\_ACEOF
-GD configure 2.0.22
+GD configure 2.0.23
 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.22, which was
+It was created by GD $as_me 2.0.23, which was
 generated by GNU Autoconf 2.57.  Invocation command line was
 
   $ $0 $@
 
 GDLIB_MAJOR=2
 GDLIB_MINOR=0
-GDLIB_REVISION=22
+GDLIB_REVISION=23
 GDLIBNAME=gd
 
 
 
 # Define the identity of the package.
  PACKAGE=gd
- VERSION=2.0.22
+ VERSION=2.0.23
 
 
 cat >>confdefs.h <<_ACEOF
 fi
 
 #TBB: png12's png_create_read_struct is just as good
-
-if test "$ac_cv_lib_png12_png_create_read_struct" == yes; then
+#2.0.23: should be = not ==
+if test "$ac_cv_lib_png12_png_create_read_struct" = yes; then
   ac_cv_lib_png_png_create_read_struct=yes
 fi
 
 } >&5
 cat >&5 <<_CSEOF
 
-This file was extended by GD $as_me 2.0.22, which was
+This file was extended by GD $as_me 2.0.23, 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.22
+GD config.status 2.0.23
 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.22], [gd@boutell.com])
+AC_INIT([GD], [2.0.23], [gd@boutell.com])
 AC_CONFIG_SRCDIR([gd.c])
 AC_CONFIG_AUX_DIR(config)
 
 GDLIB_MAJOR=2
 GDLIB_MINOR=0
-GDLIB_REVISION=22
+GDLIB_REVISION=23
 GDLIBNAME=gd
 
 AC_SUBST(GDLIB_MAJOR)
 fi
 
 #TBB: png12's png_create_read_struct is just as good 
-
-if test "$ac_cv_lib_png12_png_create_read_struct" == yes; then
+#2.0.23: should be = not ==  
+if test "$ac_cv_lib_png12_png_create_read_struct" = yes; then
   ac_cv_lib_png_png_create_read_struct=yes
 fi 
 
 #endif
 
 /* some might want to set DEFAULT_FONTPATH from configure in config.h */
+
+/* 2.0.23: more Type 1 fonts */
 #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"
+#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:/usr/lib/X11/fonts/Type1:/usr/openwin/lib/X11/fonts/Type1"
 #endif
 #ifndef PATHSEPARATOR
 #define PATHSEPARATOR ":"
 				   gdFTEX_Shift_JIS, or gdFTEX_Big5;
 				   when not specified, maps are searched
 				   for in the above order. */
+    int hdpi;                   /* if (flags & gdFTEX_RESOLUTION) */
+    int vdpi;			/* if (flags & gdFTEX_RESOLUTION) */
+
   }
   gdFTStringExtra, *gdFTStringExtraPtr;
 
 #define gdFTEX_LINESPACE 1
 #define gdFTEX_CHARMAP 2
+#define gdFTEX_RESOLUTION 4
 
 /* These are NOT flags; set one in 'charmap' if you set the
 	gdFTEX_CHARMAP bit in 'flags'. */
 }
 
 gdImagePtr
-gdImageCreateFromGd2PartPtr (int size, void *data, int srcx, int srcy, int w, int h)
+gdImageCreateFromGd2PartPtr (int size, void *data, int srcx, int srcy, int w,
+			     int h)
 {
   gdImagePtr im;
   gdIOCtx *in = gdNewDynamicCtxEx (size, data, 0);
 	      if (!_gd2ReadChunk (chunkIdx[chunkNum].offset,
 				  compBuf,
 				  chunkIdx[chunkNum].size,
-				  (char*) chunkBuf, &chunkLen, in))
+				  (char *) chunkBuf, &chunkLen, in))
 		{
 		  printf ("Error reading comproessed chunk\n");
 		  goto fail2;
 		    {
 		      if (im->trueColor)
 			{
-			  if (!gdGetInt ( (int*) &ch, in))
+			  if (!gdGetInt ((int *) &ch, in))
 			    {
 			      ch = 0;
 			      /*printf("EOF while reading file\n"); */
 		      else
 			{
 			  ch = gdGetC (in);
-			  if ((int)ch == EOF)
+			  if ((int) ch == EOF)
 			    {
 			      ch = 0;
 			      /*printf("EOF while reading file\n"); */
 gdIOCtx *
 gdNewDynamicCtx (int initialSize, void *data)
 {
-  gdNewDynamicCtxEx(initialSize, data, 1);
+  /* 2.0.23: Phil Moore: 'return' keyword was missing! */
+  return gdNewDynamicCtxEx (initialSize, data, 1);
 }
 
 gdIOCtx *
   if (bytesNeeded > dp->realSize)
     {
       /* 2.0.21 */
-      if (!dp->freeOK) {
-        return FALSE;
-      }
+      if (!dp->freeOK)
+	{
+	  return FALSE;
+	}
       if (!gdReallocDynamic (dp, dp->realSize * 2))
 	{
 	  dp->dataGood = FALSE;
   if (bytesNeeded > dp->realSize)
     {
       /* 2.0.21 */
-      if (!dp->freeOK) {
-        return FALSE;
-      }
+      if (!dp->freeOK)
+	{
+	  return FALSE;
+	}
       if (!gdReallocDynamic (dp, bytesNeeded * 2))
 	{
 	  dp->dataGood = FALSE;
 trimDynamic (dynamicPtr * dp)
 {
   /* 2.0.21: we don't reallocate memory we don't own */
-  if (!dp->freeOK) {
-    return TRUE;
-  }
+  if (!dp->freeOK)
+    {
+      return TRUE;
+    }
   return gdReallocDynamic (dp, dp->logicalSize);
 }
 
 void jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile);
 
-static int CMYKToRGB(int c, int m, int y, int k, int inverted);
+static int CMYKToRGB (int c, int m, int y, int k, int inverted);
 
 /* 
  * Create a gd-format image from the JPEG-format INFILE.  Returns the
   jpeg_gdIOCtx_src (&cinfo, infile);
 
   /* 2.0.22: save the APP14 marker to check for Adobe Photoshop CMYK
-    files with inverted components. */
-  jpeg_save_markers(&cinfo, JPEG_APP0 + 14, 256);
+     files with inverted components. */
+  jpeg_save_markers (&cinfo, JPEG_APP0 + 14, 256);
 
   retval = jpeg_read_header (&cinfo, TRUE);
   if (retval != JPEG_HEADER_OK)
     fprintf (stderr, "gd-jpeg: warning: jpeg_read_header returns"
 	     " %d, expected %d\n", retval, JPEG_HEADER_OK);
-  
+
   if (cinfo.image_height > INT_MAX)
     fprintf (stderr, "gd-jpeg: warning: JPEG image height (%u) is"
 	     " greater than INT_MAX (%d) (and thus greater than"
       goto error;
     }
   /* 2.0.22: very basic support for reading CMYK colorspace files. Nice for
-    thumbnails but there's no support for fussy adjustment of the
-    assumed properties of inks and paper. */
+     thumbnails but there's no support for fussy adjustment of the
+     assumed properties of inks and paper. */
   if ((cinfo.jpeg_color_space == JCS_CMYK) ||
-    (cinfo.jpeg_color_space == JCS_YCCK))
-  {
-    cinfo.out_color_space = JCS_CMYK;
-  } else {
-    cinfo.out_color_space = JCS_RGB;
-  }
+      (cinfo.jpeg_color_space == JCS_YCCK))
+    {
+      cinfo.out_color_space = JCS_CMYK;
+    }
+  else
+    {
+      cinfo.out_color_space = JCS_RGB;
+    }
 
   if (jpeg_start_decompress (&cinfo) != TRUE)
     fprintf (stderr, "gd-jpeg: warning: jpeg_start_decompress"
 #if 0
   gdImageInterlace (im, cinfo.progressive_mode != 0);
 #endif
-  if (cinfo.out_color_space == JCS_RGB) 
-  {
-    if (cinfo.output_components != 3)
+  if (cinfo.out_color_space == JCS_RGB)
     {
-      fprintf (stderr, "gd-jpeg: error: JPEG color quantization"
-	       " request resulted in output_components == %d"
-	       " (expected 3 for RGB)\n", cinfo.output_components);
-      goto error;
+      if (cinfo.output_components != 3)
+	{
+	  fprintf (stderr, "gd-jpeg: error: JPEG color quantization"
+		   " request resulted in output_components == %d"
+		   " (expected 3 for RGB)\n", cinfo.output_components);
+	  goto error;
+	}
+      channels = 3;
     }
-    channels = 3;
-  } else if (cinfo.out_color_space == JCS_CMYK) {
-    jpeg_saved_marker_ptr marker;
-    if (cinfo.output_components != 4)
+  else if (cinfo.out_color_space == JCS_CMYK)
     {
-      fprintf (stderr, "gd-jpeg: error: JPEG color quantization"
-	       " request resulted in output_components == %d"
-	       " (expected 4 for CMYK)\n", cinfo.output_components);
+      jpeg_saved_marker_ptr marker;
+      if (cinfo.output_components != 4)
+	{
+	  fprintf (stderr, "gd-jpeg: error: JPEG color quantization"
+		   " request resulted in output_components == %d"
+		   " (expected 4 for CMYK)\n", cinfo.output_components);
+	  goto error;
+	}
+      channels = 4;
+      marker = cinfo.marker_list;
+      while (marker)
+	{
+	  if ((marker->marker == (JPEG_APP0 + 14)) &&
+	      (marker->data_length >= 12)
+	      && (!strncmp ((const char *) marker->data, "Adobe", 5)))
+	    {
+	      inverted = 1;
+	      break;
+	    }
+	  marker = marker->next;
+	}
+    }
+  else
+    {
+      fprintf (stderr, "gd-jpeg: error: unexpected colorspace\n");
       goto error;
     }
-    channels = 4;
-    marker = cinfo.marker_list;
-    while (marker) {
-      if ((marker->marker == (JPEG_APP0 + 14)) &&
-        (marker->data_length >= 12) && (!strncmp((const char *) marker->data,
-          "Adobe", 5)))
-      {
-        inverted = 1;
-        break;
-      }
-      marker = marker->next;
-    }
-  } else {
-    fprintf (stderr, "gd-jpeg: error: unexpected colorspace\n");
-    goto error;
-  }
 #if BITS_IN_JSAMPLE == 12
   fprintf (stderr, "gd-jpeg: error: jpeg library was compiled for 12-bit\n"
 	   "precision. This is mostly useless, because JPEGs on the web are\n"
       goto error;
     }
   rowptr[0] = row;
-  if (cinfo.out_color_space == JCS_CMYK) {
-    for (i = 0; i < cinfo.output_height; i++)
-      {
-        register JSAMPROW currow = row;
-        register int *tpix = im->tpixels[i];
-        nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
-        if (nrows != 1)
-  	{
-  	  fprintf (stderr, "gd-jpeg: error: jpeg_read_scanlines"
-  		   " returns %u, expected 1\n", nrows);
-  	  goto error;
-  	}
-        for (j = 0; j < cinfo.output_width; j++, currow += 4, tpix++)
-  	{
-  	  *tpix = CMYKToRGB (currow[0], currow[1], currow[2], currow[3], inverted);
-  	}
-      }
-  } else {
-    for (i = 0; i < cinfo.output_height; i++)
-      {
-        register JSAMPROW currow = row;
-        register int *tpix = im->tpixels[i];
-        nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
-        if (nrows != 1)
-  	{
-  	  fprintf (stderr, "gd-jpeg: error: jpeg_read_scanlines"
-  		   " 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]);
-  	}
-      }
-  } 
+  if (cinfo.out_color_space == JCS_CMYK)
+    {
+      for (i = 0; i < cinfo.output_height; i++)
+	{
+	  register JSAMPROW currow = row;
+	  register int *tpix = im->tpixels[i];
+	  nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
+	  if (nrows != 1)
+	    {
+	      fprintf (stderr, "gd-jpeg: error: jpeg_read_scanlines"
+		       " returns %u, expected 1\n", nrows);
+	      goto error;
+	    }
+	  for (j = 0; j < cinfo.output_width; j++, currow += 4, tpix++)
+	    {
+	      *tpix =
+		CMYKToRGB (currow[0], currow[1], currow[2], currow[3],
+			   inverted);
+	    }
+	}
+    }
+  else
+    {
+      for (i = 0; i < cinfo.output_height; i++)
+	{
+	  register JSAMPROW currow = row;
+	  register int *tpix = im->tpixels[i];
+	  nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
+	  if (nrows != 1)
+	    {
+	      fprintf (stderr, "gd-jpeg: error: jpeg_read_scanlines"
+		       " 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]);
+	    }
+	}
+    }
   if (jpeg_finish_decompress (&cinfo) != TRUE)
     fprintf (stderr, "gd-jpeg: warning: jpeg_finish_decompress"
 	     " reports suspended data source\n");
   /* Thanks to Truxton Fulton */
-  if(cinfo.err->num_warnings>0)
-    goto error ;
+  if (cinfo.err->num_warnings > 0)
+    goto error;
 
   jpeg_destroy_decompress (&cinfo);
   gdFree (row);
 }
 
 /* A very basic conversion approach, TBB */
- 
-static int CMYKToRGB(int c, int m, int y, int k, int inverted)
+
+static int
+CMYKToRGB (int c, int m, int y, int k, int inverted)
 {
-  if (inverted) {
-    c = 255 - c;
-    m = 255 - m;
-    y = 255 - y;
-    k = 255 - k;
-  }
-  return gdTrueColor((255 - c) * (255 - k) / 255,
-     (255 - m) * (255 - k) / 255, 
-     (255 - y) * (255 - k) / 255);
+  if (inverted)
+    {
+      c = 255 - c;
+      m = 255 - m;
+      y = 255 - y;
+      k = 255 - k;
+    }
+  return gdTrueColor ((255 - c) * (255 - k) / 255,
+		      (255 - m) * (255 - k) / 255,
+		      (255 - y) * (255 - k) / 255);
 #if 0
-  if (inverted) {
-    c = 255 - c;
-    m = 255 - m;
-    y = 255 - y;
-    k = 255 - k;
-  }
+  if (inverted)
+    {
+      c = 255 - c;
+      m = 255 - m;
+      y = 255 - y;
+      k = 255 - k;
+    }
   c = c * (255 - k) / 255 + k;
-  if (c > 255) {
-    c = 255;
-  }
-  if (c < 0) {
-    c = 0;
-  } 
+  if (c > 255)
+    {
+      c = 255;
+    }
+  if (c < 0)
+    {
+      c = 0;
+    }
   m = m * (255 - k) / 255 + k;
-  if (m > 255) {
-    m = 255;
-  }
-  if (m < 0) {
-    m = 0;
-  } 
+  if (m > 255)
+    {
+      m = 255;
+    }
+  if (m < 0)
+    {
+      m = 0;
+    }
   y = y * (255 - k) / 255 + k;
-  if (y > 255) {
-    y = 255;
-  }
-  if (y < 0) {
-    y = 0;
-  } 
+  if (y > 255)
+    {
+      y = 255;
+    }
+  if (y < 0)
+    {
+      y = 0;
+    }
   c = 255 - c;
   m = 255 - m;
   y = 255 - y;
-  return gdTrueColor(c, m, y);
+  return gdTrueColor (c, m, y);
 #endif
 }
 
   my_src_ptr src = (my_src_ptr) cinfo->src;
   /* 2.0.12: signed size. Thanks to Geert Jansen */
   /* 2.0.14: some platforms (mingw-msys) don't have ssize_t. Call 
-    an int an int. */
+     an int an int. */
   int nbytes = 0;
   memset (src->buffer, 0, INPUT_BUF_SIZE);
 
      fussing with such things. */
 
   /* Faster if this is uncommented, but may produce larger truecolor files.
-    Wait for gdImagePngCtxEx. */
+     Wait for gdImagePngCtxEx. */
 #if 0
-   png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
+  png_set_filter (png_ptr, 0, PNG_FILTER_NONE);
 #endif
 
   /* 2.0.12: this is finally a parameter */
       int channels = im->saveAlphaFlag ? 4 : 3;
       /* Our little 7-bit alpha channel trick costs us a bit here. */
       png_bytep *row_pointers;
-      unsigned char* pOutputRow;
-      int **ptpixels=im->tpixels;
+      unsigned char *pOutputRow;
+      int **ptpixels = im->tpixels;
       int *pThisRow;
       unsigned char a;
       int thisPixel;
       png_bytep *prow_pointers;
-      int saveAlphaFlag=im->saveAlphaFlag;
+      int saveAlphaFlag = im->saveAlphaFlag;
       row_pointers = gdMalloc (sizeof (png_bytep) * height);
       if (row_pointers == NULL)
 	{
 	  fprintf (stderr, "gd-png error: unable to allocate row_pointers\n");
 	}
-      prow_pointers=row_pointers;
+      prow_pointers = row_pointers;
       for (j = 0; j < height; ++j)
 	{
-         if ((*prow_pointers = 
+	  if ((*prow_pointers =
 	       (png_bytep) gdMalloc (width * channels)) == NULL)
 	    {
 	      fprintf (stderr, "gd-png error: unable to allocate rows\n");
 		gdFree (row_pointers[i]);
 	      return;
 	    }
-         pOutputRow=*prow_pointers++;
-         pThisRow=*ptpixels++;
+	  pOutputRow = *prow_pointers++;
+	  pThisRow = *ptpixels++;
 	  for (i = 0; i < width; ++i)
 	    {
-            thisPixel=*pThisRow++;
-            *pOutputRow++=gdTrueColorGetRed(thisPixel);
-            *pOutputRow++=gdTrueColorGetGreen(thisPixel);
-            *pOutputRow++=gdTrueColorGetBlue(thisPixel);
+	      thisPixel = *pThisRow++;
+	      *pOutputRow++ = gdTrueColorGetRed (thisPixel);
+	      *pOutputRow++ = gdTrueColorGetGreen (thisPixel);
+	      *pOutputRow++ = gdTrueColorGetBlue (thisPixel);
 
-            if (saveAlphaFlag)
+	      if (saveAlphaFlag)
 		{
 		  /* convert the 7-bit alpha channel to an 8-bit alpha channel.
 		     We do a little bit-flipping magic, repeating the MSB
 		     as the LSB, to ensure that 0 maps to 0 and
 		     127 maps to 255. We also have to invert to match
 		     PNG's convention in which 255 is opaque. */
-               a = gdTrueColorGetAlpha (thisPixel);
+		  a = gdTrueColorGetAlpha (thisPixel);
 		  /* Andrew Hull: >> 6, not >> 7! (gd 2.0.5) */
-               *pOutputRow++ = 255 - ((a << 1) + (a >> 6));
+		  *pOutputRow++ = 255 - ((a << 1) + (a >> 6));
 		}
 	    }
 	}
   cinfo->colormap[2][icolor] = (JSAMPLE) ((c2total + (total >> 1)) / total);
 #else
   /* 2.0.16: Paul den Dulk found an occasion where total can be 0 */
-  if (count) {
-    im->red[icolor] = (int) ((c0total + (total >> 1)) / total);
-    im->green[icolor] = (int) ((c1total + (total >> 1)) / total);
-    im->blue[icolor] = (int) ((c2total + (total >> 1)) / total);
-  } else {
-    im->red[icolor] = 255;
-    im->green[icolor] = 255;
-    im->blue[icolor] = 255;
-  }
+  if (count)
+    {
+      im->red[icolor] = (int) ((c0total + (total >> 1)) / total);
+      im->green[icolor] = (int) ((c1total + (total >> 1)) / total);
+      im->blue[icolor] = (int) ((c2total + (total >> 1)) / total);
+    }
+  else
+    {
+      im->red[icolor] = 255;
+      im->green[icolor] = 255;
+      im->blue[icolor] = 255;
+    }
 #endif
 }
 
       gdImageLine (im_out, 0, 255, 255, 0, gdStyledBrushed);
     }
   /* Text (non-truetype; see gdtestft for a freetype demo) */
-  fonts[0] = gdFontGetTiny();
-  fonts[1] = gdFontGetSmall();
-  fonts[2] = gdFontGetMediumBold();
-  fonts[3] = gdFontGetLarge();
-  fonts[4] = gdFontGetGiant();
+  fonts[0] = gdFontGetTiny ();
+  fonts[1] = gdFontGetSmall ();
+  fonts[2] = gdFontGetMediumBold ();
+  fonts[3] = gdFontGetLarge ();
+  fonts[4] = gdFontGetGiant ();
   y = 0;
-  for (i = 0; (i <= 4); i++) {
-    gdImageString (im_out, fonts[i], 32, 32 + y, (unsigned char *) "hi", red);
-    y += fonts[i]->h;
-  }
+  for (i = 0; (i <= 4); i++)
+    {
+      gdImageString (im_out, fonts[i], 32, 32 + y, (unsigned char *) "hi",
+		     red);
+      y += fonts[i]->h;
+    }
   y = 0;
-  for (i = 0; (i <= 4); i++) {
-    gdImageStringUp (im_out, fonts[i], 64 + y, 64, 
-    (unsigned char *) "hi", red);
-    y += fonts[i]->h;
-  }
+  for (i = 0; (i <= 4); i++)
+    {
+      gdImageStringUp (im_out, fonts[i], 64 + y, 64,
+		       (unsigned char *) "hi", red);
+      y += fonts[i]->h;
+    }
   /* Random antialiased lines; coordinates all over the image, 
-    but the output will respect a small clipping rectangle */
-  gdImageSetClip(im_out, 0, gdImageSY(im_out) - 100,
-    100, gdImageSY(im_out)); 
+     but the output will respect a small clipping rectangle */
+  gdImageSetClip (im_out, 0, gdImageSY (im_out) - 100,
+		  100, gdImageSY (im_out));
   /* Fixed seed for reproducibility of results */
-  srand(100);
-  for (i = 0; (i < 100); i++) {
-    int x1 = rand() % gdImageSX(im_out);
-    int y1 = rand() % gdImageSY(im_out);
-    int x2 = rand() % gdImageSX(im_out);
-    int y2 = rand() % gdImageSY(im_out);
-    gdImageSetAntiAliased(im_out, white);
-    gdImageLine (im_out, x1, y1, x2, y2, gdAntiAliased);
-  }
+  srand (100);
+  for (i = 0; (i < 100); i++)
+    {
+      int x1 = rand () % gdImageSX (im_out);
+      int y1 = rand () % gdImageSY (im_out);
+      int x2 = rand () % gdImageSX (im_out);
+      int y2 = rand () % gdImageSY (im_out);
+      gdImageSetAntiAliased (im_out, white);
+      gdImageLine (im_out, x1, y1, x2, y2, gdAntiAliased);
+    }
   /* Make output image interlaced (progressive, in the case of JPEG) */
   gdImageInterlace (im_out, 1);
   out = fopen ("demoout.png", "wb");
 
 BGD_EXPORT_DATA_IMPL gdFontPtr gdFontGiant = &gdFontGiantRep;
 
-gdFontPtr gdFontGetGiant(void)
+gdFontPtr
+gdFontGetGiant (void)
 {
-	return gdFontGiant;
+  return gdFontGiant;
 }
 
 /* This file has not been truncated. */
 
 BGD_EXPORT_DATA_IMPL gdFontPtr gdFontLarge = &gdFontLargeRep;
 
-gdFontPtr gdFontGetLarge(void)
+gdFontPtr
+gdFontGetLarge (void)
 {
-	return gdFontLarge;
+  return gdFontLarge;
 }
 
 /* This file has not been truncated. */
 
 BGD_EXPORT_DATA_IMPL gdFontPtr gdFontMediumBold = &gdFontMediumBoldRep;
 
-gdFontPtr gdFontGetMediumBold(void)
+gdFontPtr
+gdFontGetMediumBold (void)
 {
-	return gdFontMediumBold;
+  return gdFontMediumBold;
 }
 
 /* This file has not been truncated. */
 
 BGD_EXPORT_DATA_IMPL gdFontPtr gdFontSmall = &gdFontSmallRep;
 
-gdFontPtr gdFontGetSmall(void)
+gdFontPtr
+gdFontGetSmall (void)
 {
-	return gdFontSmall;
+  return gdFontSmall;
 }
 
 /* This file has not been truncated. */
 
 BGD_EXPORT_DATA_IMPL gdFontPtr gdFontTiny = &gdFontTinyRep;
 
-gdFontPtr gdFontGetTiny(void) 
+gdFontPtr
+gdFontGetTiny (void)
 {
-	return gdFontTiny;
+  return gdFontTiny;
 }
 
 /* This file has not been truncated. */
        * Allocate an oversized buffer that is guaranteed to be
        * big enough for all paths to be tested.
        */
+      /* 2.0.22: Thorben Kundinger: +8 is needed, not +6. */
       fullname = gdRealloc (fullname,
-			    strlen (fontsearchpath) + strlen (name) + 6);
+			    strlen (fontsearchpath) + strlen (name) + 8);
       /* if name is an absolute or relative pathname then test directly */
       if (strchr (name, '/')
 	  || (name[0] != 0 && name[1] == ':'
 	  if (access (fullname, R_OK) == 0)
 	    {
 	      font_found++;
-              /* 2.0.16: memory leak fixed, Gustavo Scotti */ 		
-              gdFree(path);
+	      /* 2.0.16: memory leak fixed, Gustavo Scotti */
+	      gdFree (path);
 	      break;
 	    }
 	}
       platform = charmap->platform_id;
       encoding = charmap->encoding_id;
 
-/* EAM DEBUG - Newer versions of libfree2 make it easier by defining encodings */
-#if (defined(FREETYPE_MAJOR) && (FREETYPE_MAJOR >=2 ) && (FREETYPE_MINOR >= 1))
+/* EAM DEBUG - Newer versions of libfree2 make it easier 
+	by defining encodings */
+/* TBB: get this exactly right: 2.1.3 *or better*, all possible cases. */
+
+#if ((defined(FREETYPE_MAJOR)) && (((FREETYPE_MAJOR == 2) && (((FREETYPE_MINOR == 1) && (FREETYPE_PATCH >= 3)) || (FREETYPE_MINOR > 1))) || (FREETYPE_MAJOR > 2)))
       if (charmap->encoding == FT_ENCODING_MS_SYMBOL
-      ||  charmap->encoding == FT_ENCODING_ADOBE_CUSTOM
-      ||  charmap->encoding == FT_ENCODING_ADOBE_STANDARD) {
-      	a->have_char_map_unicode = 1;
-	found = charmap;
-	a->face->charmap = charmap;
-	return (void *)a;
-      }
+	  || charmap->encoding == FT_ENCODING_ADOBE_CUSTOM
+	  || charmap->encoding == FT_ENCODING_ADOBE_STANDARD)
+	{
+	  a->have_char_map_unicode = 1;
+	  found = charmap;
+	  a->face->charmap = charmap;
+	  return (void *) a;
+	}
 #endif /* Freetype 2.1 or better */
 /* EAM DEBUG */
 
 	  pcr = pc;
 	  y = pen_y + row;
 	  /* clip if out of bounds */
-          /* 2.0.16: clipping rectangle, not image bounds */		
+	  /* 2.0.16: clipping rectangle, not image bounds */
 	  if ((y > im->cy2) || (y < im->cy1))
 	    continue;
 	  for (col = 0; col < bitmap.width; col++, pc++)
 	      level = gdAlphaMax - level;
 	      x = pen_x + col;
 	      /* clip if out of bounds */
-              /* 2.0.16: clip to clipping rectangle, Matt McNabb */
+	      /* 2.0.16: clip to clipping rectangle, Matt McNabb */
 	      if ((x > im->cx2) || (x < im->cx1))
 		continue;
 	      /* get pixel location in gd buffer */
 /* Fonts can be used across multiple images */
 
 /* 2.0.16: thread safety (the font cache is shared) */
-gdMutexDeclare(gdFontCacheMutex);
+gdMutexDeclare (gdFontCacheMutex);
 static gdCache_head_t *fontCache;
 static FT_Library library;
 
 void
 gdFreeFontCache ()
 {
-  gdFontCacheShutdown();
+  gdFontCacheShutdown ();
 }
 
 void
 {
   if (fontCache)
     {
-      gdMutexShutdown(gdFontCacheMutex);
+      gdMutexShutdown (gdFontCacheMutex);
       gdCacheDelete (fontCache);
       FT_Done_FreeType (library);
       /* 2.0.16: Gustavo Scotti: make sure we don't free this twice */
 			    ptsize, angle, x, y, string, 0);
 }
 
-int gdFontCacheSetup(void)
+int
+gdFontCacheSetup (void)
 {
-	if (fontCache) {
-		/* Already set up */
-		return 0;
-	}
-	gdMutexSetup(gdFontCacheMutex);
-	if (FT_Init_FreeType (&library))
-	{
-		gdMutexShutdown(gdFontCacheMutex);
-		return -1;
-	}
-	fontCache = gdCacheCreate (FONTCACHESIZE,
-		 fontTest, fontFetch, fontRelease);
-	return 0;
+  if (fontCache)
+    {
+      /* Already set up */
+      return 0;
+    }
+  gdMutexSetup (gdFontCacheMutex);
+  if (FT_Init_FreeType (&library))
+    {
+      gdMutexShutdown (gdFontCacheMutex);
+      return -1;
+    }
+  fontCache = gdCacheCreate (FONTCACHESIZE, fontTest, fontFetch, fontRelease);
+  return 0;
 }
 
+
 char *
 gdImageStringFTEx (gdImage * im, int *brect, int fg, char *fontlist,
 		   double ptsize, double angle, int x, int y, char *string,
   int render = (im && (im->trueColor || (fg <= 255 && fg >= -255)));
   FT_BitmapGlyph bm;
   /* 2.0.13: Bob Ostermann: don't force autohint, that's just for testing 
-    freetype and doesn't look as good */
+     freetype and doesn't look as good */
   int render_mode = FT_LOAD_DEFAULT;
   int m, mfound;
   /* Now tuneable thanks to Wez Furlong */
    *   colorindexes.          -- 27.06.2001 <krisku@arrak.fi>
    */
   gdCache_head_t *tc_cache;
+  /* Tuneable horizontal and vertical resolution in dots per inch */
+  int hdpi, vdpi;
   if (strex)
     {
       if ((strex->flags & gdFTEX_LINESPACE) == gdFTEX_LINESPACE)
 /***** initialize font library and font cache on first call ******/
   if (!fontCache)
     {
-      if (gdFontCacheSetup() != 0) {
-	gdCacheDelete (tc_cache);
-        return "Failure to initialize font library";
-      }
+      if (gdFontCacheSetup () != 0)
+	{
+	  gdCacheDelete (tc_cache);
+	  return "Failure to initialize font library";
+	}
     }
 /*****/
-  gdMutexLock(gdFontCacheMutex);
+  gdMutexLock (gdFontCacheMutex);
   /* get the font (via font cache) */
   fontkey.fontlist = fontlist;
   fontkey.library = &library;
   if (!font)
     {
       gdCacheDelete (tc_cache);
-      gdMutexUnlock(gdFontCacheMutex);
+      gdMutexUnlock (gdFontCacheMutex);
       return fontCache->error;
     }
   face = font->face;		/* shortcut */
   slot = face->glyph;		/* shortcut */
 
-  if (FT_Set_Char_Size (face, 0, (FT_F26Dot6) (ptsize * 64),
-			GD_RESOLUTION, GD_RESOLUTION))
+  /*
+   * Added hdpi and vdpi to support images at non-screen resolutions, i.e. 300 dpi TIFF,
+   *    or 100h x 50v dpi FAX format. 2.0.23.
+   * 2004/02/27 Mark Shackelford, mark.shackelford@acs-inc.com
+   */
+  hdpi = GD_RESOLUTION;
+  vdpi = GD_RESOLUTION;
+  if (strex && (strex->flags & gdFTEX_RESOLUTION))
+    {
+      hdpi = strex->hdpi;
+      vdpi = strex->vdpi;
+    }
+
+  if (FT_Set_Char_Size (face, 0, (FT_F26Dot6) (ptsize * 64), hdpi, vdpi))
     {
       gdCacheDelete (tc_cache);
-      gdMutexUnlock(gdFontCacheMutex);
+      gdMutexUnlock (gdFontCacheMutex);
       return "Could not set character size";
     }
 
   if (!mfound)
     {
       /* No character set found! */
-      gdMutexUnlock(gdFontCacheMutex);
+      gdMutexUnlock (gdFontCacheMutex);
       return "No character set found";
     }
 
       /* newlines */
       if (ch == '\n')
 	{
-          /* 2.0.13: reset penf.x. Christopher J. Grayce */
+	  /* 2.0.13: reset penf.x. Christopher J. Grayce */
 	  penf.x = 0;
 	  penf.y -= face->size->metrics.height * linespace;
 	  penf.y = (penf.y - 32) & -64;	/* round to next pixel row */
 #if (defined(FREETYPE_MAJOR) && (FREETYPE_MAJOR >=2 ) && (FREETYPE_MINOR >= 1))
       if (font->face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
 	{
-         /* I do not know the significance of the constant 0xf000. */
-         /* It was determined by inspection of the character codes */
-         /* stored in Microsoft font symbol.ttf                    */
-           len = gdTcl_UtfToUniChar (next, &ch);
-           ch |= 0xf000;
-           next += len;
-	} else
+	  /* I do not know the significance of the constant 0xf000. */
+	  /* It was determined by inspection of the character codes */
+	  /* stored in Microsoft font symbol.ttf                    */
+	  len = gdTcl_UtfToUniChar (next, &ch);
+	  ch |= 0xf000;
+	  next += len;
+	}
+      else
 #endif /* Freetype 2.1 or better */
 /* EAM DEBUG */
-	
-      switch (m)
-	{
-	case gdFTEX_Unicode:
-	  if (font->have_char_map_unicode)
-	    {
-	      /* use UTF-8 mapping from ASCII */
-	      len = gdTcl_UtfToUniChar (next, &ch);
-	      next += len;
-	    }
-	  break;
-	case gdFTEX_Shift_JIS:
-	  if (font->have_char_map_sjis)
-	    {
-	      unsigned char c;
-	      int jiscode;
-	      c = *next;
-	      if (0xA1 <= c && c <= 0xFE)
-		{
-		  next++;
-		  jiscode = 0x100 * (c & 0x7F) + ((*next) & 0x7F);
-
-		  ch = (jiscode >> 8) & 0xFF;
-		  jiscode &= 0xFF;
 
-		  if (ch & 1)
-		    jiscode += 0x40 - 0x21;
-		  else
-		    jiscode += 0x9E - 0x21;
-
-		  if (jiscode >= 0x7F)
-		    jiscode++;
-		  ch = (ch - 0x21) / 2 + 0x81;
-		  if (ch >= 0xA0)
-		    ch += 0x40;
-
-		  ch = (ch << 8) + jiscode;
-		}
-	      else
-		{
-		  ch = c & 0xFF;	/* don't extend sign */
-		}
-	      next++;
-	    }
-	  break;
-	case gdFTEX_Big5:
+	switch (m)
 	  {
-	    /*
-	     * Big 5 mapping:
-	     * use "JIS-8 half-width katakana" coding from 8-bit characters. Ref:
-	     * ftp://ftp.ora.com/pub/examples/nutshell/ujip/doc/japan.inf-032092.sjs
-	     */
-	    ch = (*next) & 0xFF;	/* don't extend sign */
-	    next++;
-	    if (ch >= 161	/* first code of JIS-8 pair */
-		&& *next)
-	      {			/* don't advance past '\0' */
-		/* TBB: Fix from Kwok Wah On: & 255 needed */
-		ch = (ch * 256) + ((*next) & 255);
+	  case gdFTEX_Unicode:
+	    if (font->have_char_map_unicode)
+	      {
+		/* use UTF-8 mapping from ASCII */
+		len = gdTcl_UtfToUniChar (next, &ch);
+		next += len;
+	      }
+	    break;
+	  case gdFTEX_Shift_JIS:
+	    if (font->have_char_map_sjis)
+	      {
+		unsigned char c;
+		int jiscode;
+		c = *next;
+		if (0xA1 <= c && c <= 0xFE)
+		  {
+		    next++;
+		    jiscode = 0x100 * (c & 0x7F) + ((*next) & 0x7F);
+
+		    ch = (jiscode >> 8) & 0xFF;
+		    jiscode &= 0xFF;
+
+		    if (ch & 1)
+		      jiscode += 0x40 - 0x21;
+		    else
+		      jiscode += 0x9E - 0x21;
+
+		    if (jiscode >= 0x7F)
+		      jiscode++;
+		    ch = (ch - 0x21) / 2 + 0x81;
+		    if (ch >= 0xA0)
+		      ch += 0x40;
+
+		    ch = (ch << 8) + jiscode;
+		  }
+		else
+		  {
+		    ch = c & 0xFF;	/* don't extend sign */
+		  }
 		next++;
 	      }
+	    break;
+	  case gdFTEX_Big5:
+	    {
+	      /*
+	       * Big 5 mapping:
+	       * use "JIS-8 half-width katakana" coding from 8-bit characters. Ref:
+	       * ftp://ftp.ora.com/pub/examples/nutshell/ujip/doc/japan.inf-032092.sjs
+	       */
+	      ch = (*next) & 0xFF;	/* don't extend sign */
+	      next++;
+	      if (ch >= 161	/* first code of JIS-8 pair */
+		  && *next)
+		{		/* don't advance past '\0' */
+		  /* TBB: Fix from Kwok Wah On: & 255 needed */
+		  ch = (ch * 256) + ((*next) & 255);
+		  next++;
+		}
+	    }
+	    break;
 	  }
-	  break;
-	}
       /* set rotation transform */
       FT_Set_Transform (face, &matrix, NULL);
       /* Convert character code to glyph index */
       if (err)
 	{
 	  gdCacheDelete (tc_cache);
-          gdMutexUnlock(gdFontCacheMutex);
+	  gdMutexUnlock (gdFontCacheMutex);
 	  return "Problem loading glyph";
 	}
 
 	      if (err)
 		{
 		  gdCacheDelete (tc_cache);
-                  gdMutexUnlock(gdFontCacheMutex);
+		  gdMutexUnlock (gdFontCacheMutex);
 		  return "Problem rendering glyph";
 		}
 	    }
   if (tmpstr)
     gdFree (tmpstr);
   gdCacheDelete (tc_cache);
-  gdMutexUnlock(gdFontCacheMutex);
+  gdMutexUnlock (gdFontCacheMutex);
   return (char *) NULL;
 }
 
 #define MAXY(x) MAX4(x[1],x[3],x[5],x[7])
 #define MINY(x) MIN4(x[1],x[3],x[5],x[7])
 
-char *gdImageStringFTCircle(
-	gdImagePtr im,
-	int cx,
-	int cy,
-	double radius,
-	double textRadius,
-	double fillPortion,
-	char *font,
-	double points,
-	char *top,
-	char *bottom,
-	int fgcolor)
+char *
+gdImageStringFTCircle (gdImagePtr im,
+		       int cx,
+		       int cy,
+		       double radius,
+		       double textRadius,
+		       double fillPortion,
+		       char *font,
+		       double points, char *top, char *bottom, int fgcolor)
 {
-	char *err;
-	int w;
-	int brect[8];
-	int sx1, sx2, sy1, sy2, sx, sy;
-	int x, y;
-	int fr, fg, fb, fa;
-	int ox, oy;
-	double prop;
-	gdImagePtr im1;
-	gdImagePtr im2;
-	gdImagePtr im3;
-	/* obtain brect so that we can size the image */
-	err = gdImageStringFT ((gdImagePtr) NULL, 
-		&brect[0], 0, font, points * MAG, 0, 0, 0, bottom);
-	if (err)
+  char *err;
+  int w;
+  int brect[8];
+  int sx1, sx2, sy1, sy2, sx, sy;
+  int x, y;
+  int fr, fg, fb, fa;
+  int ox, oy;
+  double prop;
+  gdImagePtr im1;
+  gdImagePtr im2;
+  gdImagePtr im3;
+  /* obtain brect so that we can size the image */
+  err = gdImageStringFT ((gdImagePtr) NULL,
+			 &brect[0], 0, font, points * MAG, 0, 0, 0, bottom);
+  if (err)
+    {
+      return err;
+    }
+  sx1 = MAXX (brect) - MINX (brect) + 6;
+  sy1 = MAXY (brect) - MINY (brect) + 6;
+  err = gdImageStringFT ((gdImagePtr) NULL,
+			 &brect[0], 0, font, points * MAG, 0, 0, 0, top);
+  if (err)
+    {
+      return err;
+    }
+  sx2 = MAXX (brect) - MINX (brect) + 6;
+  sy2 = MAXY (brect) - MINY (brect) + 6;
+  /* Pad by 4 pixels to allow for slight errors
+     observed in the bounding box returned by freetype */
+  if (sx1 > sx2)
+    {
+      sx = sx1 * 2 + 4;
+    }
+  else
+    {
+      sx = sx2 * 2 + 4;
+    }
+  if (sy1 > sy2)
+    {
+      sy = sy1;
+    }
+  else
+    {
+      sy = sy2;
+    }
+  im1 = gdImageCreateTrueColor (sx, sy);
+  if (!im1)
+    {
+      return "could not create first image";
+    }
+  err = gdImageStringFT (im1, 0, gdTrueColor (255, 255, 255),
+			 font, points * MAG,
+			 0, ((sx / 2) - sx1) / 2, points * MAG, bottom);
+  if (err)
+    {
+      gdImageDestroy (im1);
+      return err;
+    }
+  /* We don't know the descent, which would be needed to do this
+     with the angle parameter. Instead, implement a simple
+     flip operation ourselves. */
+  err = gdImageStringFT (im1, 0, gdTrueColor (255, 255, 255),
+			 font, points * MAG,
+			 0, sx / 2 + ((sx / 2) - sx2) / 2, points * MAG, top);
+  if (err)
+    {
+      gdImageDestroy (im1);
+      return err;
+    }
+  /* Flip in place is tricky, be careful not to double-swap things */
+  if (sy & 1)
+    {
+      for (y = 0; (y <= (sy / 2)); y++)
 	{
-		return err;
+	  int xlimit = sx - 2;
+	  if (y == (sy / 2))
+	    {
+	      /* If there is a "middle" row, be careful
+	         not to swap twice! */
+	      xlimit -= (sx / 4);
+	    }
+	  for (x = (sx / 2) + 2; (x < xlimit); x++)
+	    {
+	      int t;
+	      int ox = sx - x + (sx / 2) - 1;
+	      int oy = sy - y - 1;
+	      t = im1->tpixels[oy][ox];
+	      im1->tpixels[oy][ox] = im1->tpixels[y][x];
+	      im1->tpixels[y][x] = t;
+	    }
 	}
-	sx1 = MAXX (brect) - MINX (brect) + 6;
-	sy1 = MAXY (brect) - MINY (brect) + 6;
-	err = gdImageStringFT ((gdImagePtr) NULL, 
-		&brect[0], 0, font, points * MAG, 0, 0, 0, top);
-	if (err)
+    }
+  else
+    {
+      for (y = 0; (y < (sy / 2)); y++)
 	{
-		return err;
-	}
-	sx2 = MAXX (brect) - MINX (brect) + 6;
-	sy2 = MAXY (brect) - MINY (brect) + 6;
-	/* Pad by 4 pixels to allow for slight errors
-		observed in the bounding box returned by freetype */
-	if (sx1 > sx2) {
-		sx = sx1 * 2 + 4;
-	} else {
-		sx = sx2 * 2 + 4;
-	}
-	if (sy1 > sy2) {
-		sy = sy1;
-	} else {
-		sy = sy2;
-	}
-	im1 = gdImageCreateTrueColor(sx, sy); 
-	if (!im1) {
-		return "could not create first image";
-	}
-	err = gdImageStringFT (im1, 0, gdTrueColor(255, 255, 255), 
-		font, points * MAG, 
-		0, ((sx / 2) - sx1) / 2, points * MAG, bottom);
-	if (err) {
-		gdImageDestroy(im1);
-		return err;
-	}
-	/* We don't know the descent, which would be needed to do this
-		with the angle parameter. Instead, implement a simple
-		flip operation ourselves. */
-	err = gdImageStringFT (im1, 0, gdTrueColor(255, 255, 255), 
-		font, points * MAG, 
-		0, sx / 2 + ((sx / 2) - sx2) / 2, points * MAG, top);
-	if (err) {
-		gdImageDestroy(im1);
-		return err;
-	}
-	/* Flip in place is tricky, be careful not to double-swap things */
-	if (sy & 1) {
-		for (y = 0; (y <= (sy / 2)); y++) {
-			int xlimit = sx - 2;
-			if (y == (sy / 2)) {
-				/* If there is a "middle" row, be careful
-					not to swap twice! */
-				xlimit -= (sx / 4);
-			}
-			for (x = (sx / 2) + 2; (x < xlimit); x++) {
-				int t;
-				int ox = sx - x + (sx / 2) - 1;
-				int oy = sy - y - 1;
-				t = im1->tpixels[oy][ox];
-				im1->tpixels[oy][ox] = im1->tpixels[y][x];
-				im1->tpixels[y][x] = t;
-			}
-		}
-	} else {
-		for (y = 0; (y < (sy / 2)); y++) {
-			int xlimit = sx - 2;
-			for (x = (sx / 2) + 2; (x < xlimit); x++) {
-				int t;
-				int ox = sx - x + (sx / 2) - 1;
-				int oy = sy - y - 1;
-				t = im1->tpixels[oy][ox];
-				im1->tpixels[oy][ox] = im1->tpixels[y][x];
-				im1->tpixels[y][x] = t;
-			}
-		}
+	  int xlimit = sx - 2;
+	  for (x = (sx / 2) + 2; (x < xlimit); x++)
+	    {
+	      int t;
+	      int ox = sx - x + (sx / 2) - 1;
+	      int oy = sy - y - 1;
+	      t = im1->tpixels[oy][ox];
+	      im1->tpixels[oy][ox] = im1->tpixels[y][x];
+	      im1->tpixels[y][x] = t;
+	    }
 	}
+    }
 #if STEP_PNGS
-	{
-		FILE *out = fopen("gdfx1.png", "wb");
-		gdImagePng(im1, out);
-		fclose(out);
-	}
+  {
+    FILE *out = fopen ("gdfx1.png", "wb");
+    gdImagePng (im1, out);
+    fclose (out);
+  }
 #endif /* STEP_PNGS */
-	/* Resample taller; the exact proportions of the text depend on the
-		ratio of textRadius to radius, and the value of fillPortion */
-	if (sx > sy * 10) {
-		w = sx;
-	} else {
-		w = sy * 10;
-	}
-	im2 = gdImageCreateTrueColor(w, w);
-	if (!im2) {
-		gdImageDestroy(im1);
-		return "could not create resampled image";
-	}
-	prop = textRadius / radius;
-	gdImageCopyResampled(im2, im1, 
-		gdImageSX(im2) * (1.0 - fillPortion) / 4, 
-		sy * 10 * (1.0 - prop), 
-		0, 0,
-		gdImageSX(im2) * fillPortion / 2, sy * 10 * prop,
-		gdImageSX(im1) / 2, gdImageSY(im1));
-	gdImageCopyResampled(im2, im1, 
-		(gdImageSX(im2) / 2) + 
-			gdImageSX(im2) * (1.0 - fillPortion) / 4, 
-		sy * 10 * (1.0 - prop), 
-		gdImageSX(im1) / 2, 0,
-		gdImageSX(im2) * fillPortion / 2, sy * 10 * prop,
-		gdImageSX(im1) / 2, gdImageSY(im1));
+  /* Resample taller; the exact proportions of the text depend on the
+     ratio of textRadius to radius, and the value of fillPortion */
+  if (sx > sy * 10)
+    {
+      w = sx;
+    }
+  else
+    {
+      w = sy * 10;
+    }
+  im2 = gdImageCreateTrueColor (w, w);
+  if (!im2)
+    {
+      gdImageDestroy (im1);
+      return "could not create resampled image";
+    }
+  prop = textRadius / radius;
+  gdImageCopyResampled (im2, im1,
+			gdImageSX (im2) * (1.0 - fillPortion) / 4,
+			sy * 10 * (1.0 - prop),
+			0, 0,
+			gdImageSX (im2) * fillPortion / 2, sy * 10 * prop,
+			gdImageSX (im1) / 2, gdImageSY (im1));
+  gdImageCopyResampled (im2, im1,
+			(gdImageSX (im2) / 2) +
+			gdImageSX (im2) * (1.0 - fillPortion) / 4,
+			sy * 10 * (1.0 - prop),
+			gdImageSX (im1) / 2, 0,
+			gdImageSX (im2) * fillPortion / 2, sy * 10 * prop,
+			gdImageSX (im1) / 2, gdImageSY (im1));
 #if STEP_PNGS
+  {
+    FILE *out = fopen ("gdfx2.png", "wb");
+    gdImagePng (im2, out);
+    fclose (out);
+  }
+#endif /* STEP_PNGS */
+  /* Ready to produce a circle */
+  im3 = gdImageSquareToCircle (im2, radius);
+  gdImageDestroy (im1);
+  gdImageDestroy (im2);
+  /* Now blend im3 with the destination. Cheat a little. The
+     source (im3) is white-on-black, so we can use the
+     red component as a basis for alpha as long as we're
+     careful to shift off the extra bit and invert
+     (alpha ranges from 0 to 127 where 0 is OPAQUE). 
+     Also be careful to allow for an alpha component
+     in the fgcolor parameter itself (gug!) */
+  fr = gdTrueColorGetRed (fgcolor);
+  fg = gdTrueColorGetGreen (fgcolor);
+  fb = gdTrueColorGetBlue (fgcolor);
+  fa = gdTrueColorGetAlpha (fgcolor);
+  ox = cx - (im3->sx / 2);
+  oy = cy - (im3->sy / 2);
+  for (y = 0; (y < im3->sy); y++)
+    {
+      for (x = 0; (x < im3->sx); x++)
 	{
-		FILE *out = fopen("gdfx2.png", "wb");
-		gdImagePng(im2, out);
-		fclose(out);
+	  int a = gdTrueColorGetRed (im3->tpixels[y][x]) >> 1;
+	  a *= (127 - fa);
+	  a /= 127;
+	  a = 127 - a;
+	  gdImageSetPixel (im, x + ox, y + oy,
+			   gdTrueColorAlpha (fr, fg, fb, a));
 	}
-#endif /* STEP_PNGS */
-	/* Ready to produce a circle */
-	im3 = gdImageSquareToCircle(im2, radius);
-	gdImageDestroy(im1);
-	gdImageDestroy(im2);
-	/* Now blend im3 with the destination. Cheat a little. The
-		source (im3) is white-on-black, so we can use the
-		red component as a basis for alpha as long as we're
-		careful to shift off the extra bit and invert
-		(alpha ranges from 0 to 127 where 0 is OPAQUE). 
-		Also be careful to allow for an alpha component
-		in the fgcolor parameter itself (gug!) */
-	fr = gdTrueColorGetRed(fgcolor);
-	fg = gdTrueColorGetGreen(fgcolor);
-	fb = gdTrueColorGetBlue(fgcolor);
-	fa = gdTrueColorGetAlpha(fgcolor);
-	ox = cx - (im3->sx / 2); 
-	oy = cy - (im3->sy / 2); 
-	for (y = 0; (y < im3->sy); y++) {
-		for (x = 0; (x < im3->sx); x++) {
-			int a = gdTrueColorGetRed(im3->tpixels[y][x]) >> 1;
-			a *= (127 - fa);
-			a /= 127;
-			a = 127 - a;	
-			gdImageSetPixel(im, x + ox, y + oy,
-				gdTrueColorAlpha(fr, fg, fb, a));
-		}
-	}			
-	gdImageDestroy(im3);
-	return 0;
+    }
+  gdImageDestroy (im3);
+  return 0;
 }
 
 #if GDFX_MAIN
 int
 main (int argc, char *argv[])
 {
-	FILE *in;
-	FILE *out;
-	gdImagePtr im;
-	int radius;
-	/* Create an image of text on a circle, with an
-		alpha channel so that we can copy it onto a
-		background */
-	in = fopen("eleanor.jpg", "rb");
-	if (!in) {
-		im = gdImageCreateTrueColor(300, 300);
-	} else {
-		im = gdImageCreateFromJpeg(in);
-		fclose(in);
-	}
-	if (gdImageSX(im) < gdImageSY(im)) {
-		radius = gdImageSX(im) / 2;
-	} else {
-		radius = gdImageSY(im) / 2;
-	}
-	gdStringFTCircle(
-		im,
-		gdImageSX(im) / 2,
-		gdImageSY(im) / 2,
-		radius,
-		radius / 2,
-		0.8,
-		"arial",
-		24,
-		"top text",
-		"bottom text",
-		gdTrueColorAlpha(240, 240, 255, 32));
-	out = fopen("gdfx.png", "wb");
-	if (!out) {
-		fprintf(stderr, "Can't create gdfx.png\n");
-		return 1;
-	}
-	gdImagePng(im, out);
-	fclose(out);
-	gdImageDestroy(im);
-	return 0;
+  FILE *in;
+  FILE *out;
+  gdImagePtr im;
+  int radius;
+  /* Create an image of text on a circle, with an
+     alpha channel so that we can copy it onto a
+     background */
+  in = fopen ("eleanor.jpg", "rb");
+  if (!in)
+    {
+      im = gdImageCreateTrueColor (300, 300);
+    }
+  else
+    {
+      im = gdImageCreateFromJpeg (in);
+      fclose (in);
+    }
+  if (gdImageSX (im) < gdImageSY (im))
+    {
+      radius = gdImageSX (im) / 2;
+    }
+  else
+    {
+      radius = gdImageSY (im) / 2;
+    }
+  gdStringFTCircle (im,
+		    gdImageSX (im) / 2,
+		    gdImageSY (im) / 2,
+		    radius,
+		    radius / 2,
+		    0.8,
+		    "arial",
+		    24,
+		    "top text",
+		    "bottom text", gdTrueColorAlpha (240, 240, 255, 32));
+  out = fopen ("gdfx.png", "wb");
+  if (!out)
+    {
+      fprintf (stderr, "Can't create gdfx.png\n");
+      return 1;
+    }
+  gdImagePng (im, out);
+  fclose (out);
+  gdImageDestroy (im);
+  return 0;
 }
 
 #endif /* GDFX_MAIN */
 #define SUPERBITS1 1
 #define SUPERBITS2 2
 
-gdImagePtr gdImageSquareToCircle(gdImagePtr im, int radius)
+gdImagePtr
+gdImageSquareToCircle (gdImagePtr im, int radius)
 {
-	int x, y;
-	double c;
-	gdImagePtr im2;
-	if (im->sx != im->sy) {
-		/* Source image must be square */
-		return 0;
+  int x, y;
+  double c;
+  gdImagePtr im2;
+  if (im->sx != im->sy)
+    {
+      /* Source image must be square */
+      return 0;
+    }
+  im2 = gdImageCreateTrueColor (radius * 2, radius * 2);
+  /* Supersampling for a nicer result */
+  c = (im2->sx / 2) * SUPER;
+  for (y = 0; (y < im2->sy * SUPER); y++)
+    {
+      for (x = 0; (x < im2->sx * SUPER); x++)
+	{
+	  double rho = sqrt ((x - c) * (x - c) + (y - c) * (y - c));
+	  int pix;
+	  int cpix;
+	  double theta;
+	  double ox;
+	  double oy;
+	  int red, green, blue, alpha;
+	  if (rho > c)
+	    {
+	      continue;
+	    }
+	  theta = atan2 (x - c, y - c) + PI / 2;
+	  if (theta < 0)
+	    {
+	      theta += 2 * PI;
+	    }
+	  /* Undo supersampling */
+	  oy = (rho * im->sx) / (im2->sx * SUPER / 2);
+	  ox = theta * im->sx / (3.141592653 * 2);
+	  pix = gdImageGetPixel (im, ox, oy);
+	  cpix = im2->tpixels[y >> SUPERBITS1][x >> SUPERBITS1];
+	  red =
+	    (gdImageRed (im, pix) >> SUPERBITS2) + gdTrueColorGetRed (cpix);
+	  green =
+	    (gdImageGreen (im, pix) >> SUPERBITS2) +
+	    gdTrueColorGetGreen (cpix);
+	  blue =
+	    (gdImageBlue (im, pix) >> SUPERBITS2) + gdTrueColorGetBlue (cpix);
+	  alpha =
+	    (gdImageAlpha (im, pix) >> SUPERBITS2) +
+	    gdTrueColorGetAlpha (cpix);
+	  im2->tpixels[y >> SUPERBITS1][x >> SUPERBITS1] =
+	    gdTrueColorAlpha (red, green, blue, alpha);
 	}
-	im2 = gdImageCreateTrueColor(radius * 2, radius * 2);
-	/* Supersampling for a nicer result */
-	c = (im2->sx / 2) * SUPER;
-	for (y = 0; (y < im2->sy * SUPER); y++) {
-		for (x = 0; (x < im2->sx * SUPER); x++) {
-			double rho = sqrt((x - c) * (x - c) +
-				(y - c) * (y - c));
-			int pix;
-			int cpix;
-			double theta;
-			double ox;
-			double oy;
-			int red, green, blue, alpha;
-			if (rho > c) {
-				continue;
-			}
-			theta = atan2(x - c, y - c) + PI / 2;
-			if (theta < 0) {
-				theta += 2 * PI;
-			}
-			/* Undo supersampling */
-			oy = (rho * im->sx) / (im2->sx * SUPER / 2);
-			ox = theta * im->sx / (3.141592653 * 2);
-			pix = gdImageGetPixel(im, ox, oy); 
-			cpix = im2->tpixels[y >> SUPERBITS1][x >> SUPERBITS1];
-			red = (gdImageRed(im, pix) >> SUPERBITS2) + gdTrueColorGetRed(cpix);
-			green = (gdImageGreen(im, pix) >> SUPERBITS2) + gdTrueColorGetGreen(cpix);
-			blue = (gdImageBlue(im, pix) >> SUPERBITS2) + gdTrueColorGetBlue(cpix);
-			alpha = (gdImageAlpha(im, pix) >> SUPERBITS2) + gdTrueColorGetAlpha(cpix);
-			im2->tpixels[y >> SUPERBITS1][x >> SUPERBITS1] = gdTrueColorAlpha(
-				red, green, blue, alpha);
-		}
-	}	
-	/* Restore full dynamic range, 0-63 yields 0-252. Replication of
-		first 2 bits in last 2 bits has the desired effect. Note
-		slightly different arithmetic for alpha which is 7-bit. 
-		NOTE: only correct for SUPER == 2 */
-	for (y = 0; (y < im2->sy); y++) {
-		for (x = 0; (x < im2->sx); x++) {
-			/* Copy first 2 bits to last 2 bits, matching the
-				dynamic range of the original cheaply */
-			int cpix = im2->tpixels[y][x];
-
-			im2->tpixels[y][x] = gdTrueColorAlpha(
-					(gdTrueColorGetRed(cpix) & 0xFC) +
-					((gdTrueColorGetRed(cpix) & 0xC0) >> 6),
-					(gdTrueColorGetGreen(cpix) & 0xFC) +
-					((gdTrueColorGetGreen(cpix) & 0xC0) >> 6),
-					(gdTrueColorGetBlue(cpix) & 0xFC) +
-					((gdTrueColorGetBlue(cpix) & 0xC0) >> 6),
-					(gdTrueColorGetAlpha(cpix) & 0x7C) +
-					((gdTrueColorGetAlpha(cpix) & 0x60) >> 6));
-		}	
-	}					
-	return im2;
+    }
+  /* Restore full dynamic range, 0-63 yields 0-252. Replication of
+     first 2 bits in last 2 bits has the desired effect. Note
+     slightly different arithmetic for alpha which is 7-bit. 
+     NOTE: only correct for SUPER == 2 */
+  for (y = 0; (y < im2->sy); y++)
+    {
+      for (x = 0; (x < im2->sx); x++)
+	{
+	  /* Copy first 2 bits to last 2 bits, matching the
+	     dynamic range of the original cheaply */
+	  int cpix = im2->tpixels[y][x];
+
+	  im2->tpixels[y][x] = gdTrueColorAlpha ((gdTrueColorGetRed (cpix) &
+						  0xFC) +
+						 ((gdTrueColorGetRed (cpix) &
+						   0xC0) >> 6),
+						 (gdTrueColorGetGreen (cpix) &
+						  0xFC) +
+						 ((gdTrueColorGetGreen (cpix)
+						   & 0xC0) >> 6),
+						 (gdTrueColorGetBlue (cpix) &
+						  0xFC) +
+						 ((gdTrueColorGetBlue (cpix) &
+						   0xC0) >> 6),
+						 (gdTrueColorGetAlpha (cpix) &
+						  0x7C) +
+						 ((gdTrueColorGetAlpha (cpix)
+						   & 0x60) >> 6));
+	}
+    }
+  return im2;
 }
 
 /* 2.0.16: Called by gdImageSharpen to avoid excessive code repetition
 returns new colour for centre pixel
 */
 
-int gdImageSubSharpen (int pc, int c, int nc, float inner_coeff, float 
-outer_coeff) {
-         float red, green, blue, alpha;
-
-         red = inner_coeff * gdTrueColorGetRed (c) + outer_coeff * 
-(gdTrueColorGetRed (pc) + gdTrueColorGetRed (nc));
-         green = inner_coeff * gdTrueColorGetGreen (c) + outer_coeff * 
-(gdTrueColorGetGreen (pc) + gdTrueColorGetGreen (nc));
-         blue = inner_coeff * gdTrueColorGetBlue (c) + outer_coeff * 
-(gdTrueColorGetBlue (pc) + gdTrueColorGetBlue (nc));
-         alpha = gdTrueColorGetAlpha (c);
-
-         /* Clamping, as can overshoot bounds in either direction */
-         if (red > 255.0f) {
-                 red = 255.0f;
-         }
-         if (green > 255.0f) {
-                 green = 255.0f;
-         }
-         if (blue > 255.0f) {
-                 blue = 255.0f;
-         }
-         if (red < 0.0f) {
-                 red = 0.0f;
-         }
-         if (green < 0.0f) {
-                 green = 0.0f;
-         }
-         if (blue < 0.0f) {
-                 blue = 0.0f;
-         }
-
-         return gdTrueColorAlpha ((int) red, (int) green, (int) blue, 
-(int) alpha);
+int
+gdImageSubSharpen (int pc, int c, int nc, float inner_coeff, float
+		   outer_coeff)
+{
+  float red, green, blue, alpha;
+
+  red = inner_coeff * gdTrueColorGetRed (c) + outer_coeff *
+    (gdTrueColorGetRed (pc) + gdTrueColorGetRed (nc));
+  green = inner_coeff * gdTrueColorGetGreen (c) + outer_coeff *
+    (gdTrueColorGetGreen (pc) + gdTrueColorGetGreen (nc));
+  blue = inner_coeff * gdTrueColorGetBlue (c) + outer_coeff *
+    (gdTrueColorGetBlue (pc) + gdTrueColorGetBlue (nc));
+  alpha = gdTrueColorGetAlpha (c);
+
+  /* Clamping, as can overshoot bounds in either direction */
+  if (red > 255.0f)
+    {
+      red = 255.0f;
+    }
+  if (green > 255.0f)
+    {
+      green = 255.0f;
+    }
+  if (blue > 255.0f)
+    {
+      blue = 255.0f;
+    }
+  if (red < 0.0f)
+    {
+      red = 0.0f;
+    }
+  if (green < 0.0f)
+    {
+      green = 0.0f;
+    }
+  if (blue < 0.0f)
+    {
+      blue = 0.0f;
+    }
+
+  return gdTrueColorAlpha ((int) red, (int) green, (int) blue, (int) alpha);
 }
 
 /*
   * Silently does nothing for pct<0, as not a useful blurring function
   * Leaves transparency/alpha-channel untouched
   */
-void gdImageSharpen (gdImagePtr im, int pct)
+void
+gdImageSharpen (gdImagePtr im, int pct)
 {
-         int x, y;
-         int sx, sy;
-         float inner_coeff, outer_coeff;
-
-         sx = im->sx;
-         sy = im->sy;
-
-         /* Must sum to 1 to avoid overall change in brightness.
-          * Scaling chosen so that pct=100 gives 1-D filter [-1 6 -1]/4,
-          * resulting in a 2-D filter [1 -6 1; -6 36 -6; 1 -6 1]/16,
-          * which gives noticeable, but not excessive, sharpening
-          */
-
-         outer_coeff = -pct / 400.0;
-         inner_coeff = 1 - 2 * outer_coeff;
-
-         /* Don't try to do anything with non-truecolor images, as 
-pointless,
-          * nor for pct<=0, as small kernel size leads to nasty 
-artefacts when blurring
-          */
-         if ( (im->trueColor) && (pct>0) ) {
-
-                 /* First pass, 1-D convolution column-wise */
-                 for (x = 0; x < sx; x++) {
-
-                         /* pc is colour of previous pixel; c of the 
-current pixel and nc of the next */
-                         int pc, c, nc;
-
-                         /* Replicate edge pixel at image boundary */
-                         pc = gdImageGetPixel (im, x, 0);
-
-                         /* Stop looping before last pixel to avoid 
-conditional within loop */
-                         for (y = 0; y < sy-1; y++) {
-
-                                 c = gdImageGetPixel (im, x, y);
-
-                                 nc = gdImageGetTrueColorPixel (im, x, 
-y+1);
-
-                                 /* Update centre pixel to new colour */
-                                 gdImageSetPixel(im, x, y, 
-gdImageSubSharpen (pc, c, nc, inner_coeff, outer_coeff) );
-
-                                 /* Save original colour of current 
-pixel for next time round */
-                                 pc = c;
-                         }
-
-                         /* Deal with last pixel, replicating current 
-pixel at image boundary */
-                         c = gdImageGetPixel (im, x, y);
-                         gdImageSetPixel(im, x, y, gdImageSubSharpen 
-(pc, c, c, inner_coeff, outer_coeff) );
-                 }
-
-                 /* Second pass, 1-D convolution row-wise */
-                 for (y = 0; y < sy; y++) {
-                         int pc, c, nc;
-                         pc = gdImageGetPixel (im, 0, y);
-                         for (x = 0; x < sx-1; x++) {
-                                 int c, nc;
-                                 c = gdImageGetPixel (im, x, y);
-                                 nc = gdImageGetTrueColorPixel (im, x+1, 
-y);
-                                 gdImageSetPixel(im, x, y, 
-gdImageSubSharpen (pc, c, nc, inner_coeff, outer_coeff) );
-                                 pc = c;
-                         }
-                         c = gdImageGetPixel (im, x, y);
-                         gdImageSetPixel(im, x, y, gdImageSubSharpen 
-(pc, c, c, inner_coeff, outer_coeff) );
-                 }
-         }
-}
+  int x, y;
+  int sx, sy;
+  float inner_coeff, outer_coeff;
+
+  sx = im->sx;
+  sy = im->sy;
+
+  /* Must sum to 1 to avoid overall change in brightness.
+   * Scaling chosen so that pct=100 gives 1-D filter [-1 6 -1]/4,
+   * resulting in a 2-D filter [1 -6 1; -6 36 -6; 1 -6 1]/16,
+   * which gives noticeable, but not excessive, sharpening
+   */
+
+  outer_coeff = -pct / 400.0;
+  inner_coeff = 1 - 2 * outer_coeff;
+
+  /* Don't try to do anything with non-truecolor images, as 
+     pointless,
+     * nor for pct<=0, as small kernel size leads to nasty 
+     artefacts when blurring
+   */
+  if ((im->trueColor) && (pct > 0))
+    {
+
+      /* First pass, 1-D convolution column-wise */
+      for (x = 0; x < sx; x++)
+	{
+
+	  /* pc is colour of previous pixel; c of the 
+	     current pixel and nc of the next */
+	  int pc, c, nc;
+
+	  /* Replicate edge pixel at image boundary */
+	  pc = gdImageGetPixel (im, x, 0);
+
+	  /* Stop looping before last pixel to avoid 
+	     conditional within loop */
+	  for (y = 0; y < sy - 1; y++)
+	    {
 
+	      c = gdImageGetPixel (im, x, y);
 
+	      nc = gdImageGetTrueColorPixel (im, x, y + 1);
+
+	      /* Update centre pixel to new colour */
+	      gdImageSetPixel (im, x, y,
+			       gdImageSubSharpen (pc, c, nc, inner_coeff,
+						  outer_coeff));
+
+	      /* Save original colour of current 
+	         pixel for next time round */
+	      pc = c;
+	    }
+
+	  /* Deal with last pixel, replicating current 
+	     pixel at image boundary */
+	  c = gdImageGetPixel (im, x, y);
+	  gdImageSetPixel (im, x, y, gdImageSubSharpen
+			   (pc, c, c, inner_coeff, outer_coeff));
+	}
+
+      /* Second pass, 1-D convolution row-wise */
+      for (y = 0; y < sy; y++)
+	{
+	  int pc, c, nc;
+	  pc = gdImageGetPixel (im, 0, y);
+	  for (x = 0; x < sx - 1; x++)
+	    {
+	      int c, nc;
+	      c = gdImageGetPixel (im, x, y);
+	      nc = gdImageGetTrueColorPixel (im, x + 1, y);
+	      gdImageSetPixel (im, x, y,
+			       gdImageSubSharpen (pc, c, nc, inner_coeff,
+						  outer_coeff));
+	      pc = c;
+	    }
+	  c = gdImageGetPixel (im, x, y);
+	  gdImageSetPixel (im, x, y, gdImageSubSharpen
+			   (pc, c, c, inner_coeff, outer_coeff));
+	}
+    }
+}
 <!-- REMEMBER TO EDIT index.html.source -->
 <head>
-<TITLE>gd 2.0.22</TITLE>
+<TITLE>gd 2.0.23</TITLE>
 </head>
 <body bgcolor="#FFFFFF">
 <!-- BANNER HERE -->
-<H2>gd 2.0.22</H2>
+<H2>gd 2.0.23</H2>
 <H3>A graphics library for fast image creation</H3>
 <H3>Follow this link to the
 <A HREF="http://www.boutell.com/gd/">latest version
 new installation overwrites the old.
 <p>
 <strong>ABOUT GD AND GIF:</strong>
-gd 2.0.22 creates PNG, JPEG and WBMP images, not GIF images. This is a 
+gd 2.0.23 creates PNG, JPEG and WBMP images, not GIF images. This is a 
 good thing.  PNG is a more compact format, and full compression is
 available.  JPEG works best with photographic images, and is still
 more compatible with the major Web browsers than even PNG is. WBMP is
 modern image formats such as PNG and JPEG as soon as possible.
 
 <p>
-When building from soruce, gd 2.0.22 <strong>requires</strong> that the 
+When building from soruce, gd 2.0.23 <strong>requires</strong> that the 
 following libraries also be installed, in order to produce the related 
 image formats. The win32 binary release (bgd) already contains the
 appropriate libraries.
 <H3>Table of Contents</H3>
 <UL>
 <LI><A HREF="#notice">Credits and license terms</A>
-<LI><A HREF="#whatsnew2.0.22">What's new in version "XYZ" of GD?</A>
+<LI><A HREF="#whatsnew2.0.23">What's new in version "XYZ" of GD?</A>
 <LI><A HREF="#whatis">What is gd?</A>
 <LI><A HREF="#gdother">What if I want to use another programming language?</A>
 <LI><A HREF="#required">What else do I need to use gd?</A>
 </pre>
 <blockquote>
 
-Portions copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 by Cold Spring
+Portions copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 by Cold Spring
 Harbor Laboratory. Funded under Grant P41-RR02188 by the National
 Institutes of Health.
 <P>
-Portions copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 by Boutell.Com, Inc.
+Portions copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 by Boutell.Com, Inc.
 <p>
-Portions relating to GD2 format copyright 1999, 2000, 2001, 2002 Philip Warner.
+Portions relating to GD2 format copyright 1999, 2000, 2001, 2002, 2003, 2004 Philip Warner.
 <p>
-Portions relating to PNG copyright 1999, 2000, 2001, 2002 Greg Roelofs.
+Portions relating to PNG copyright 1999, 2000, 2001, 2002, 2003, 2004 Greg Roelofs.
 <p>
-Portions relating to gdttf.c copyright 1999, 2000, 2001, 2002 John Ellson (ellson@graphviz.org).
+Portions relating to gdttf.c copyright 1999, 2000, 2001, 2002, 2003, 2004 John Ellson (ellson@graphviz.org).
 <p>
-Portions relating to gdft.c copyright 2001, 2002 John Ellson (ellson@graphviz.org).
+Portions relating to gdft.c copyright 2001, 2002, 2003, 2004 John Ellson (ellson@graphviz.org).
 <p>
-Portions relating to JPEG and to color quantization copyright 2000, 2001, 2002, Doug Becker and copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, Thomas G. Lane.  This software is based 
+Portions relating to JPEG and to color quantization copyright 2000, 2001, 2002, 2003, 2004, Doug Becker and copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Thomas G. Lane.  This software is based 
 in part on the work of the Independent JPEG Group. See the file
 README-JPEG.TXT for more information.
 <p>
-Portions relating to WBMP copyright 2000, 2001, 2002 Maurice Szmurlo and Johan Van 
+Portions relating to WBMP copyright 2000, 2001, 2002, 2003, 2004 Maurice Szmurlo and Johan Van 
 den Brande.
 <p>
 <strong>Permission has been granted to copy, distribute and modify gd in any
 <A NAME="gdother"><H3>What if I want to use another programming
 language?</h3></A>
 Not all of these tools are necessarily up to date and fully compatible
-with 2.0.22.
+with 2.0.23.
 <h4>PHP</h4>
 A variant of gd 2.x is included in PHP 4.3.0. It is also possible
-to patch PHP 4.2.3 for use with gd 2.0.22; see the
+to patch PHP 4.2.3 for use with gd 2.0.23; see the
 <a href="http://www.boutell.com/gd/">gd home page</a> for a link to
 that information. It would be a Good Idea to merge all of the things
 that are better in mainstream gd and all of the things that are
 <li><a href="http://martin.gleeson.com/fly/">fly</a>, by Martin Gleeson
 </ul>
 <P>
+<A NAME="whatsnew2.0.23"><H3>What's new in version 2.0.23?</H3></A>
+<P>
+Output dpi specification option added to the
+<code>gdFTStringExtra</code> structure, thanks to
+Mark Shackelford. See <a href="#gdImageStringFTEx">gdImageStringFTEx</a>.
+<P>
 <A NAME="whatsnew2.0.22"><H3>What's new in version 2.0.22?</H3></A>
 <P>
 <ul>
           in file sizes comparable to GIFs, with the ability to access parts
           of large images without having to read the entire image into memory.
 <p>
-	This format also supports version numbers and rudimentary validity
-	checks, so it should be more 'supportable' than the previous GD format.
+  This format also supports version numbers and rudimentary validity
+  checks, so it should be more 'supportable' than the previous GD format.
 <p>
 <dt><b>Re-arranged source files</b>
 <dd>      gd.c has been broken into constituant parts: io, gif, gd, gd2 and
 </ul>
 <h4>Source Code:</h4>
 <ul>
-<li><a href="http://www.boutell.com/gd/http/gd-2.0.22.tar.gz">Gzipped Tar File (Unix)</a>
-<li><a href="http://www.boutell.com/gd/http/gd-2.0.22.zip">.ZIP File of SOURCE CODE (Windows)</a>
+<li><a href="http://www.boutell.com/gd/http/gd-2.0.23.tar.gz">Gzipped Tar File (Unix)</a>
+<li><a href="http://www.boutell.com/gd/http/gd-2.0.23.zip">.ZIP File of SOURCE CODE (Windows)</a>
 </ul>
 <P>
 <A NAME="buildgd"><H3>How do I build gd?</H3></A>
 consult with an experienced user of your system. Sorry, we cannot
 answer questions about basic Internet skills.
 <p>
-Unpacking the archive will produce a directory called "gd-2.0.22".
+Unpacking the archive will produce a directory called "gd-2.0.23".
 <p>
 <h4>For Unix</h4>
-<code>cd</code> to the 2.0.22 directory and type: