Anonymous avatar Anonymous committed 56f110b

- sync to 2.0.1

Comments (0)

Files changed (7)

 #for your system. 
 AR=ar
 
-#If you don't have FreeType, libjpeg and/or Xpm installed, including the
-#header files, uncomment this (default). You really must install
-#libpng and zlib to get anywhere if you wish to create PNG images.
-#CFLAGS=-O -DHAVE_LIBPNG
+#Typical configuration: support for PNG images, JPEG images, and FreeType text.
+#Remove -DHAVE_LIBFREETYPE if you can live without FreeType text.
+#Add -DHAVE_XPM if you have X and xpm installed and you want that feature.
 
-#If you do have FreeType 2.x, libjpeg and/or Xpm fully installed, uncomment a
-#variation of this and comment out the line above. See also LIBS below.
-CFLAGS=-g -DHAVE_LIBXPM -DHAVE_LIBPNG -DHAVE_LIBJPEG \
-	-DHAVE_LIBFREETYPE
-
-#If you don't have FreeType Xpm fully installed, uncomment this
-#(default).
+CFLAGS=-g -DHAVE_LIBPNG -DHAVE_LIBJPEG -DHAVE_LIBFREETYPE
 
 #PLEASE NOTE: YOU MAY HAVE TO JUGGLE THE ORDER OF THE LIBRARIES.
 #Some systems are very picky about link order. They don't all agree
 #on the right order, either. 
-
-#LIBS=-lgd -lpng -lz -lm
-
-#If you do have FreeType, JPEG and/or Xpm fully installed, uncomment a 
-#variation of this and comment out the line above. Note that
-#Xpm requires X11. See also CFLAGS above.
+#
+#Best for most users. If you don't have FreeType, remove -lfreetype.
+#Add -lxpm if you need XPM support.
 
 LIBS=-lgd -lpng -lz -ljpeg -lfreetype -lm
 
 PROGRAMS=$(BIN_PROGRAMS) $(TEST_PROGRAMS)
 
 BIN_PROGRAMS=pngtogd pngtogd2 gdtopng gd2topng gd2copypal gdparttopng webpng
-TEST_PROGRAMS=gdtest gddemo gd2time gdtestft gdtestttf testac
+TEST_PROGRAMS=gdtest gddemo gd2time gdtestft testac
 
 default: instructions
 
 
 gdtestft: gdtestft.o
 	$(CC) --verbose gdtestft.o -o gdtestft $(LIBDIRS) $(LIBS)
-gdtestttf: gdtestttf.o
-	$(CC) --verbose gdtestttf.o -o gdtestttf $(LIBDIRS) $(LIBS)
 
 LIBOBJS=gd.o gd_gd.o gd_gd2.o gd_io.o gd_io_dp.o \
 		gd_io_file.o gd_ss.o gd_io_ss.o gd_png.o gd_jpeg.o gdxpm.o \
 		gdfontt.o gdfonts.o gdfontmb.o gdfontl.o gdfontg.o \
 		gdtables.o gdft.o gdcache.o gdkanji.o wbmp.o \
-		gd_wbmp.o gdhelpers.o gd_topal.o gd_arc_f.o
+		gd_wbmp.o gdhelpers.o gd_topal.o 
 
 #Shared library. This should work fine on any ELF platform (Linux, etc.) with
 #GNU ld or something similarly intelligent. To avoid the chicken-and-egg
 #Static library, if you really need one for some reason.
 libgd.a: ${LIBOBJS}
 	rm -f libgd.a
-	$(AR) rc ${LIBOBJS}
+	$(AR) rc libgd.a ${LIBOBJS}
 	-ranlib libgd.a
 
 clean:
+/* s and e are integers modulo 360 (degrees), with 0 degrees
+  being the rightmost extreme and degrees changing clockwise.
+  cx and cy are the center in pixels; w and h are the horizontal 
+  and vertical diameter in pixels. Nice interface, but slow, since
+  I don't yet use Bresenham (I'm using an inefficient but
+  simple solution with too much work going on in it; generalizing
+  Bresenham to ellipses and partial arcs of ellipses is non-trivial,
+  at least for me) and there are other inefficiencies (small circles
+  do far too much work). */
+
+void gdImageArc(gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color)
+{
+	int i;
+	int lx = 0, ly = 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;
+		if (i != s) {
+			gdImageLine(im, lx, ly, x, y, color);	
+		}
+		lx = x;
+		ly = y;
+	}
+}

src/bresenham_ellipse

+void 
+gdImageEllipse (gdImagePtr im, int cx, int cy, int w, int h, int color)
+{
+  long d, b_sq, b_sq_4, b_sq_6;
+  long a_sq, a_sq_4, a_sq_6;
+  int x, y, switchem;
+  long lsqrt (long);
+  int pix, half, pstart;
+  int thick = im->thick;
+
+  half = thick / 2;
+  w /= 2;			/* ImageArc uses diameter, not radius */
+  h /= 2;
+
+  d = 2 * (long) h *h + (long) w *w - 2 * (long) w *w * h;
+  b_sq = (long) h *h;
+  b_sq_4 = 4 * (long) h *h;
+  b_sq_6 = 6 * (long) h *h;
+  a_sq = (long) w *w;
+  a_sq_4 = 4 * (long) w *w;
+  a_sq_6 = 6 * (long) w *w;
+
+  x = 0;
+  y = -h;
+  switchem = a_sq / lsqrt (a_sq + b_sq);
+
+  while (x <= switchem)
+    {
+      pstart = y - half;
+      for (pix = pstart; pix < pstart + thick; pix++)
+	{
+	  gdImageSetPixel (im, cx + x, cy + pix, color);
+	  gdImageSetPixel (im, cx - x, cy + pix, color);
+	  gdImageSetPixel (im, cx + x, cy - pix, color);
+	  gdImageSetPixel (im, cx - x, cy - pix, color);
+	}
+      if (d < 0)
+	d += b_sq_4 * x++ + b_sq_6;
+      else
+	d += b_sq_4 * x++ + b_sq_6 + a_sq_4 * (++y);
+    }
+
+  /* Middlesplat!
+     ** Go a little further if the thickness is not nominal...
+   */
+  if (thick > 1)
+    {
+      int xp = x;
+      int yp = y;
+      int dp = d;
+      int thick2 = thick + 2;
+      int half2 = half + 1;
+
+      while (xp <= switchem + half)
+	{
+	  pstart = yp - half2;
+	  for (pix = pstart; pix < pstart + thick2; pix++)
+	    {
+	      gdImageSetPixel (im, cx + xp, cy + pix, color);
+	      gdImageSetPixel (im, cx - xp, cy + pix, color);
+	      gdImageSetPixel (im, cx + xp, cy - pix, color);
+	      gdImageSetPixel (im, cx - xp, cy - pix, color);
+	    }
+	  if (dp < 0)
+	    dp += b_sq_4 * xp++ + b_sq_6;
+	  else
+	    dp += b_sq_4 * xp++ + b_sq_6 + a_sq_4 * (++yp);
+	}
+    }
+
+  d += -2 * (long) b_sq + 2 * (long) a_sq - 2 * (long) b_sq *(x - 1) + 2 * (long) a_sq *(y - 1);
+
+  while (y <= 0)
+    {
+      pstart = x - half;
+      for (pix = pstart; pix < pstart + thick; pix++)
+	{
+	  gdImageSetPixel (im, cx + pix, cy + y, color);
+	  gdImageSetPixel (im, cx - pix, cy + y, color);
+	  gdImageSetPixel (im, cx + pix, cy - y, color);
+	  gdImageSetPixel (im, cx - pix, cy - y, color);
+	}
+
+      if (d < 0)
+	d += a_sq_4 * y++ + a_sq_6 + b_sq_4 * (++x);
+      else
+	d += a_sq_4 * y++ + a_sq_6;
+    }
+}

src/gd_arc_f_buggy.c

+/* This is potentially great stuff, but fails against the test
+   program at the end. This would probably be much more 
+   efficent than the implementation currently in gd.c if the 
+   errors in the output were corrected. TBB */
+
+#if 0
+
+#include "gd.h"
+#include <math.h>
+
+/* Courtesy of F J Franklin. */
+
+static gdPoint gdArcClosest (int width, int height, int angle);
+
+void
+gdImageFilledEllipse (gdImagePtr im, int cx, int cy, int width, int height, int color)
+{
+  gdImageFilledArc (im, cx, cy, width, height, 0, 360, color, gdChord);
+}
+
+void
+gdImageFilledArc (gdImagePtr im, int cx, int cy, int width, int height, int s, int e, int color, int style)
+{
+  gdPoint pt[7];
+  gdPoint axis_pt[4];
+
+  int angle;
+
+  int have_s = 0;
+  int have_e = 0;
+
+  int flip_x = 0;
+  int flip_y = 0;
+
+  int conquer = 0;
+
+  int i;
+
+  int a;
+  int b;
+
+  int x;
+  int y;
+
+  long s_sin = 0;
+  long s_cos = 0;
+  long e_sin = 0;
+  long e_cos = 0;
+
+  long w;			/* a * 2 */
+  long h;			/* b * 2 */
+
+  long x2;			/* x * 2 */
+  long y2;			/* y * 2 */
+  long lx2;			/* x * 2 (line) */
+  long ly2;			/* y * 2 (line) */
+
+  long ws;			/* (a * 2)^2 */
+  long hs;			/* (b * 2)^2 */
+
+  long whs;			/* (a * 2)^2 * (b * 2)^2 */
+
+  long g;			/* decision variable */
+  long lg;			/* decision variable (line) */
+
+  width = (width & 1) ? (width + 1) : (width);
+  height = (height & 1) ? (height + 1) : (height);
+
+  a = width / 2;
+  b = height / 2;
+
+  axis_pt[0].x = a;
+  axis_pt[0].y = 0;
+  axis_pt[1].x = 0;
+  axis_pt[1].y = b;
+  axis_pt[2].x = -a;
+  axis_pt[2].y = 0;
+  axis_pt[3].x = 0;
+  axis_pt[3].y = -b;
+
+  if (s == e)
+    return;
+
+  if ((e - s) >= 360)
+    {
+      s = 0;
+      e = 0;
+    }
+
+  while (s < 0)
+    s += 360;
+  while (s >= 360)
+    s -= 360;
+  while (e < 0)
+    e += 360;
+  while (e >= 360)
+    e -= 360;
+
+  if (e <= s)
+    e += 360;
+
+  /* I'm assuming a chord-rule at the moment. Need to add origin to get a
+   * pie-rule, but will need to set chord-rule before recursion...
+   */
+
+  for (i = 0; i < 4; i++)
+    {
+      if ((s < (i + 1) * 90) && (e > (i + 1) * 90))
+	{
+	  gdImageFilledArc (im, cx, cy, width, height, s, (i + 1) * 90, color, gdChord);
+	  pt[0] = gdArcClosest (width, height, s);
+	  pt[0].x += cx;
+	  pt[0].y += cy;
+	  pt[1].x = cx + axis_pt[(i + 1) & 3].x;
+	  pt[1].y = cy + axis_pt[(i + 1) & 3].y;
+	  if (e <= (i + 2) * 90)
+	    {
+	      gdImageFilledArc (im, cx, cy, width, height, (i + 1) * 90, e, color, gdChord);
+	      pt[2] = gdArcClosest (width, height, e);
+	      pt[2].x += cx;
+	      pt[2].y += cy;
+	      if (style == gdChord)
+		{
+		  gdImageFilledPolygon (im, pt, 3, color);
+		  gdImagePolygon (im, pt, 3, color);
+		}
+	      else if (style == gdPie)
+		{
+		  pt[3].x = cx;
+		  pt[3].y = cy;
+		  gdImageFilledPolygon (im, pt, 4, color);
+		  gdImagePolygon (im, pt, 4, color);
+		}
+	    }
+	  else
+	    {
+	      gdImageFilledArc (im, cx, cy, width, height, (i + 1) * 90, (i + 2) * 90, color, gdChord);
+	      pt[2].x = cx + axis_pt[(i + 2) & 3].x;
+	      pt[2].y = cy + axis_pt[(i + 2) & 3].y;
+	      if (e <= (i + 3) * 90)
+		{
+		  gdImageFilledArc (im, cx, cy, width, height, (i + 2) * 90, e, color, gdChord);
+		  pt[3] = gdArcClosest (width, height, e);
+		  pt[3].x += cx;
+		  pt[3].y += cy;
+		  if (style == gdChord)
+		    {
+		      gdImageFilledPolygon (im, pt, 4, color);
+		      gdImagePolygon (im, pt, 4, color);
+		    }
+		  else if (style == gdPie)
+		    {
+		      pt[4].x = cx;
+		      pt[4].y = cy;
+		      gdImageFilledPolygon (im, pt, 5, color);
+		      gdImagePolygon (im, pt, 5, color);
+		    }
+		}
+	      else
+		{
+		  gdImageFilledArc (im, cx, cy, width, height, (i + 2) * 90, (i + 3) * 90, color, gdChord);
+		  pt[3].x = cx + axis_pt[(i + 3) & 3].x;
+		  pt[3].y = cy + axis_pt[(i + 3) & 3].y;
+		  if (e <= (i + 4) * 90)
+		    {
+		      gdImageFilledArc (im, cx, cy, width, height, (i + 3) * 90, e, color, gdChord);
+		      pt[4] = gdArcClosest (width, height, e);
+		      pt[4].x += cx;
+		      pt[4].y += cy;
+		      if (style == gdChord)
+			{
+			  gdImageFilledPolygon (im, pt, 5, color);
+			  gdImagePolygon (im, pt, 5, color);
+			}
+		      else if (style == gdPie)
+			{
+			  pt[5].x = cx;
+			  pt[5].y = cy;
+			  gdImageFilledPolygon (im, pt, 6, color);
+			  gdImagePolygon (im, pt, 6, color);
+			}
+		    }
+		  else
+		    {
+		      gdImageFilledArc (im, cx, cy, width, height, (i + 3) * 90, (i + 4) * 90, color, gdChord);
+		      pt[4].x = cx + axis_pt[(i + 4) & 3].x;
+		      pt[4].y = cy + axis_pt[(i + 4) & 3].y;
+
+		      gdImageFilledArc (im, cx, cy, width, height, (i + 4) * 90, e, color, gdChord);
+		      pt[5] = gdArcClosest (width, height, e);
+		      pt[5].x += cx;
+		      pt[5].y += cy;
+		      if (style == gdChord)
+			{
+			  gdImageFilledPolygon (im, pt, 6, color);
+			  gdImagePolygon (im, pt, 6, color);
+			}
+		      else if (style == gdPie)
+			{
+			  pt[6].x = cx;
+			  pt[6].y = cy;
+			  gdImageFilledPolygon (im, pt, 7, color);
+			  gdImagePolygon (im, pt, 7, color);
+			}
+		    }
+		}
+	    }
+	  return;
+	}
+    }
+
+  /* At this point we have only arcs that lies within a quadrant -
+   * map this to first quadrant...
+   */
+
+  if ((s >= 90) && (e <= 180))
+    {
+      angle = s;
+      s = 180 - e;
+      e = 180 - angle;
+      flip_x = 1;
+    }
+  if ((s >= 180) && (e <= 270))
+    {
+      s = s - 180;
+      e = e - 180;
+      flip_x = 1;
+      flip_y = 1;
+    }
+  if ((s >= 270) && (e <= 360))
+    {
+      angle = s;
+      s = 360 - e;
+      e = 360 - angle;
+      flip_y = 1;
+    }
+
+  if (s == 0)
+    {
+      s_sin = 0;
+      s_cos = (long) ((double) 32768);
+    }
+  else
+    {
+      s_sin = (long) ((double) 32768 * sin ((double) s * M_PI / (double) 180));
+      s_cos = (long) ((double) 32768 * cos ((double) s * M_PI / (double) 180));
+    }
+  if (e == 0)
+    {
+      e_sin = (long) ((double) 32768);
+      e_cos = 0;
+    }
+  else
+    {
+      e_sin = (long) ((double) 32768 * sin ((double) e * M_PI / (double) 180));
+      e_cos = (long) ((double) 32768 * cos ((double) e * M_PI / (double) 180));
+    }
+
+  w = (long) width;
+  h = (long) height;
+
+  ws = w * w;
+  hs = h * h;
+
+  whs = 1;
+  while ((ws > 32768) || (hs > 32768))
+    {
+      ws = (ws + 1) / 2;	/* Unfortunate limitations on integers makes */
+      hs = (hs + 1) / 2;	/* drawing large  ellipses problematic...    */
+      whs *= 2;
+    }
+  while ((ws * hs) > (0x04000000L / whs))
+    {
+      ws = (ws + 1) / 2;
+      hs = (hs + 1) / 2;
+      whs *= 2;
+    }
+  whs *= ws * hs;
+
+  pt[0].x = w / 2;
+  pt[0].y = 0;
+
+  pt[2].x = 0;
+  pt[2].y = h / 2;
+
+  have_s = 0;
+  have_e = 0;
+
+  if (s == 0)
+    have_s = 1;
+  if (e == 90)
+    have_e = 1;
+
+  x2 = w;
+  y2 = 0;			/* Starting point is exactly on ellipse */
+
+  g = x2 - 1;
+  g = g * g * hs + 4 * ws - whs;
+
+  while ((x2 * hs) > (y2 * ws))	/* Keep |tangent| > 1 */
+    {
+      y2 += 2;
+      g += ws * 4 * (y2 + 1);
+
+      if (g > 0)		/* Need to drop */
+	{
+	  x2 -= 2;
+	  g -= hs * 4 * x2;
+	}
+
+      if ((have_s == 0) && ((s_sin * x2) <= (y2 * s_cos)))
+	{
+	  pt[0].x = (int) (x2 / 2);
+	  pt[0].y = (int) (y2 / 2);
+	  have_s = 1;
+	}
+
+      if ((have_e == 0) && ((e_sin * x2) <= (y2 * e_cos)))
+	{
+	  pt[2].x = (int) (x2 / 2);
+	  pt[2].y = (int) (y2 / 2);
+	  have_e = 1;
+	}
+    }
+  pt[1].x = (int) (x2 / 2);
+  pt[1].y = (int) (y2 / 2);
+
+  x2 = 0;
+  y2 = h;			/* Starting point is exactly on ellipse */
+
+  g = y2 - 1;
+  g = g * g * ws + 4 * hs - whs;
+
+  while ((x2 * hs) < (y2 * ws))
+    {
+      x2 += 2;
+      g += hs * 4 * (x2 + 1);
+
+      if (g > 0)		/* Need to drop */
+	{
+	  y2 -= 2;
+	  g -= ws * 4 * y2;
+	}
+
+      if ((have_s == 0) && ((s_sin * x2) >= (y2 * s_cos)))
+	{
+	  pt[0].x = (int) (x2 / 2);
+	  pt[0].y = (int) (y2 / 2);
+	  have_s = 1;
+	}
+
+      if ((have_e == 0) && ((e_sin * x2) >= (y2 * e_cos)))
+	{
+	  pt[2].x = (int) (x2 / 2);
+	  pt[2].y = (int) (y2 / 2);
+	  have_e = 1;
+	}
+    }
+
+  if ((have_s == 0) || (have_e == 0))
+    return;			/* Bizarre case */
+
+  if (style == gdPie)
+    {
+      pt[3] = pt[0];
+      pt[4] = pt[1];
+      pt[5] = pt[2];
+
+      pt[0].x = cx + (flip_x ? (-pt[0].x) : pt[0].x);
+      pt[0].y = cy + (flip_y ? (-pt[0].y) : pt[0].y);
+      pt[1].x = cx;
+      pt[1].y = cy;
+      pt[2].x = cx + (flip_x ? (-pt[2].x) : pt[2].x);
+      pt[2].y = cy + (flip_y ? (-pt[2].y) : pt[2].y);
+      gdImageFilledPolygon (im, pt, 3, color);
+      gdImagePolygon (im, pt, 3, color);
+
+      pt[0] = pt[3];
+      pt[1] = pt[4];
+      pt[2] = pt[5];
+    }
+
+  if (((s_cos * hs) > (s_sin * ws)) && ((e_cos * hs) < (e_sin * ws)))
+    {				/* the points are on different parts of the curve...
+				 * this is too tricky to try to handle, so divide and conquer:
+				 */
+      pt[3] = pt[0];
+      pt[4] = pt[1];
+      pt[5] = pt[2];
+
+      pt[0].x = cx + (flip_x ? (-pt[0].x) : pt[0].x);
+      pt[0].y = cy + (flip_y ? (-pt[0].y) : pt[0].y);
+      pt[1].x = cx + (flip_x ? (-pt[1].x) : pt[1].x);
+      pt[1].y = cy + (flip_y ? (-pt[1].y) : pt[1].y);
+      pt[2].x = cx + (flip_x ? (-pt[2].x) : pt[2].x);
+      pt[2].y = cy + (flip_y ? (-pt[2].y) : pt[2].y);
+      gdImageFilledPolygon (im, pt, 3, color);
+      gdImagePolygon (im, pt, 3, color);
+
+      pt[0] = pt[3];
+      pt[2] = pt[4];
+
+      conquer = 1;
+    }
+
+  if (conquer || (((s_cos * hs) > (s_sin * ws)) && ((e_cos * hs) > (e_sin * ws))))
+    {				/* This is the best bit... */
+      /* steep line + ellipse */
+      /* go up & left from pt[0] to pt[2] */
+
+      x2 = w;
+      y2 = 0;			/* Starting point is exactly on ellipse */
+
+      g = x2 - 1;
+      g = g * g * hs + 4 * ws - whs;
+
+      while ((x2 * hs) > (y2 * ws))	/* Keep |tangent| > 1 */
+	{
+	  if ((s_sin * x2) <= (y2 * s_cos))
+	    break;
+
+	  y2 += 2;
+	  g += ws * 4 * (y2 + 1);
+
+	  if (g > 0)		/* Need to drop */
+	    {
+	      x2 -= 2;
+	      g -= hs * 4 * x2;
+	    }
+	}
+
+      lx2 = x2;
+      ly2 = y2;
+
+      lg = lx2 * (pt[0].y - pt[2].y) - ly2 * (pt[0].x - pt[2].x);
+      lg = (lx2 - 1) * (pt[0].y - pt[2].y) - (ly2 + 2) * (pt[0].x - pt[2].x) - lg;
+
+      while (y2 < (2 * pt[2].y))
+	{
+	  y2 += 2;
+	  g += ws * 4 * (y2 + 1);
+
+	  if (g > 0)		/* Need to drop */
+	    {
+	      x2 -= 2;
+	      g -= hs * 4 * x2;
+	    }
+
+	  ly2 += 2;
+	  lg -= 2 * (pt[0].x - pt[2].x);
+
+	  if (lg < 0)		/* Need to drop */
+	    {
+	      lx2 -= 2;
+	      lg -= 2 * (pt[0].y - pt[2].y);
+	    }
+
+	  y = (int) (y2 / 2);
+	  for (x = (int) (lx2 / 2); x <= (int) (x2 / 2); x++)
+	    {
+	      gdImageSetPixel (im, ((flip_x) ? (cx - x) : (cx + x)),
+			       ((flip_y) ? (cy - y) : (cy + y)), color);
+	    }
+	}
+    }
+  if (conquer)
+    {
+      pt[0] = pt[4];
+      pt[2] = pt[5];
+    }
+  if (conquer || (((s_cos * hs) < (s_sin * ws)) && ((e_cos * hs) < (e_sin * ws))))
+    {				/* This is the best bit... */
+      /* gradual line + ellipse */
+      /* go down & right from pt[2] to pt[0] */
+
+      x2 = 0;
+      y2 = h;			/* Starting point is exactly on ellipse */
+
+      g = y2 - 1;
+      g = g * g * ws + 4 * hs - whs;
+
+      while ((x2 * hs) < (y2 * ws))
+	{
+	  x2 += 2;
+	  g += hs * 4 * (x2 + 1);
+
+	  if (g > 0)		/* Need to drop */
+	    {
+	      y2 -= 2;
+	      g -= ws * 4 * y2;
+	    }
+
+	  if ((e_sin * x2) >= (y2 * e_cos))
+	    break;
+	}
+
+      lx2 = x2;
+      ly2 = y2;
+
+      lg = lx2 * (pt[0].y - pt[2].y) - ly2 * (pt[0].x - pt[2].x);
+      lg = (lx2 + 2) * (pt[0].y - pt[2].y) - (ly2 - 1) * (pt[0].x - pt[2].x) - lg;
+
+      while (x2 < (2 * pt[0].x))
+	{
+	  x2 += 2;
+	  g += hs * 4 * (x2 + 1);
+
+	  if (g > 0)		/* Need to drop */
+	    {
+	      y2 -= 2;
+	      g -= ws * 4 * y2;
+	    }
+
+	  lx2 += 2;
+	  lg += 2 * (pt[0].y - pt[2].y);
+
+	  if (lg < 0)		/* Need to drop */
+	    {
+	      ly2 -= 2;
+	      lg += 2 * (pt[0].x - pt[2].x);
+	    }
+
+	  x = (int) (x2 / 2);
+	  for (y = (int) (ly2 / 2); y <= (int) (y2 / 2); y++)
+	    {
+	      gdImageSetPixel (im, ((flip_x) ? (cx - x) : (cx + x)),
+			       ((flip_y) ? (cy - y) : (cy + y)), color);
+	    }
+	}
+    }
+}
+
+static gdPoint
+gdArcClosest (int width, int height, int angle)
+{
+  gdPoint pt;
+
+  int flip_x = 0;
+  int flip_y = 0;
+
+  long a_sin = 0;
+  long a_cos = 0;
+
+  long w;			/* a * 2 */
+  long h;			/* b * 2 */
+
+  long x2;			/* x * 2 */
+  long y2;			/* y * 2 */
+
+  long ws;			/* (a * 2)^2 */
+  long hs;			/* (b * 2)^2 */
+
+  long whs;			/* (a * 2)^2 * (b * 2)^2 */
+
+  long g;			/* decision variable */
+
+  w = (long) ((width & 1) ? (width + 1) : (width));
+  h = (long) ((height & 1) ? (height + 1) : (height));
+
+  while (angle < 0)
+    angle += 360;
+  while (angle >= 360)
+    angle -= 360;
+
+  if (angle == 0)
+    {
+      pt.x = w / 2;
+      pt.y = 0;
+      return (pt);
+    }
+  if (angle == 90)
+    {
+      pt.x = 0;
+      pt.y = h / 2;
+      return (pt);
+    }
+  if (angle == 180)
+    {
+      pt.x = -w / 2;
+      pt.y = 0;
+      return (pt);
+    }
+  if (angle == 270)
+    {
+      pt.x = 0;
+      pt.y = -h / 2;
+      return (pt);
+    }
+
+  pt.x = 0;
+  pt.y = 0;
+
+  if ((angle > 90) && (angle < 180))
+    {
+      angle = 180 - angle;
+      flip_x = 1;
+    }
+  if ((angle > 180) && (angle < 270))
+    {
+      angle = angle - 180;
+      flip_x = 1;
+      flip_y = 1;
+    }
+  if ((angle > 270) && (angle < 360))
+    {
+      angle = 360 - angle;
+      flip_y = 1;
+    }
+
+  a_sin = (long) ((double) 32768 * sin ((double) angle * M_PI / (double) 180));
+  a_cos = (long) ((double) 32768 * cos ((double) angle * M_PI / (double) 180));
+
+  ws = w * w;
+  hs = h * h;
+
+  whs = 1;
+  while ((ws > 32768) || (hs > 32768))
+    {
+      ws = (ws + 1) / 2;	/* Unfortunate limitations on integers makes */
+      hs = (hs + 1) / 2;	/* drawing large  ellipses problematic...    */
+      whs *= 2;
+    }
+  while ((ws * hs) > (0x04000000L / whs))
+    {
+      ws = (ws + 1) / 2;
+      hs = (hs + 1) / 2;
+      whs *= 2;
+    }
+  whs *= ws * hs;
+
+  if ((a_cos * hs) > (a_sin * ws))
+    {
+      x2 = w;
+      y2 = 0;			/* Starting point is exactly on ellipse */
+
+      g = x2 - 1;
+      g = g * g * hs + 4 * ws - whs;
+
+      while ((x2 * hs) > (y2 * ws))	/* Keep |tangent| > 1 */
+	{
+	  y2 += 2;
+	  g += ws * 4 * (y2 + 1);
+
+	  if (g > 0)		/* Need to drop */
+	    {
+	      x2 -= 2;
+	      g -= hs * 4 * x2;
+	    }
+
+	  if ((a_sin * x2) <= (y2 * a_cos))
+	    {
+	      pt.x = (int) (x2 / 2);
+	      pt.y = (int) (y2 / 2);
+	      break;
+	    }
+	}
+    }
+  else
+    {
+      x2 = 0;
+      y2 = h;			/* Starting point is exactly on ellipse */
+
+      g = y2 - 1;
+      g = g * g * ws + 4 * hs - whs;
+
+      while ((x2 * hs) < (y2 * ws))
+	{
+	  x2 += 2;
+	  g += hs * 4 * (x2 + 1);
+
+	  if (g > 0)		/* Need to drop */
+	    {
+	      y2 -= 2;
+	      g -= ws * 4 * y2;
+	    }
+
+	  if ((a_sin * x2) >= (y2 * a_cos))
+	    {
+	      pt.x = (int) (x2 / 2);
+	      pt.y = (int) (y2 / 2);
+	      break;
+	    }
+	}
+    }
+
+  if (flip_x)
+    pt.x = -pt.x;
+  if (flip_y)
+    pt.y = -pt.y;
+
+  return (pt);
+}
+
+#include "gd.h"
+#include <string.h>
+#include <math.h>
+
+#define WIDTH	500
+#define HEIGHT	300
+
+int 
+main (int argc, char *argv[])
+{
+  gdImagePtr im = gdImageCreate (WIDTH, HEIGHT);
+  int white = gdImageColorResolve (im, 0xFF, 0xFF, 0xFF), black = gdImageColorResolve (im, 0, 0, 0),
+    red = gdImageColorResolve (im, 0xFF, 0xA0, 0xA0);
+  FILE *out;
+
+  /* filled arc - circle */
+  gdImageFilledArc (im, WIDTH / 5, HEIGHT / 4, 200, 200, 45, 90, red, gdPie);
+  gdImageArc (im, WIDTH / 5, HEIGHT / 4, 200, 200, 45, 90, black);
+
+  /* filled arc - ellipse */
+  gdImageFilledArc (im, WIDTH / 2, HEIGHT / 4, 200, 150, 45, 90, red, gdPie);
+  gdImageArc (im, WIDTH / 2, HEIGHT / 4, 200, 150, 45, 90, black);
+
+
+  /* reference lines */
+  gdImageLine (im, 0, HEIGHT / 4, WIDTH, HEIGHT / 4, black);
+  gdImageLine (im, WIDTH / 5, 0, WIDTH / 5, HEIGHT, black);
+  gdImageLine (im, WIDTH / 2, 0, WIDTH / 2, HEIGHT, black);
+  gdImageLine (im, WIDTH / 2, HEIGHT / 4, WIDTH / 2 + 300, HEIGHT / 4 + 300, black);
+  gdImageLine (im, WIDTH / 5, HEIGHT / 4, WIDTH / 5 + 300, HEIGHT / 4 + 300, black);
+
+  /* TBB: Write img to test/arctest.png */
+  out = fopen ("test/arctest.png", "wb");
+  if (!out)
+    {
+      fprintf (stderr, "Can't create test/arctest.png\n");
+      exit (1);
+    }
+  gdImagePng (im, out);
+  fclose (out);
+  fprintf (stderr, "Test image written to test/arctest.png\n");
+  /* Destroy it */
+  gdImageDestroy (im);
+
+  return 0;
+}
+
+#endif
 <HTML>
 <HEAD>
-<TITLE>gd 2.0.0</TITLE>
+<TITLE>gd 2.0.1</TITLE>
 </HEAD>
 <BODY>
 <!-- BANNER HERE -->
-<h1>This is gd 2.0.0 BETA.</h1>
+<h1>This is gd 2.0.1 BETA.</h1>
 <strong>If you have problems, report them
 in detail, and consider using gd 1.8.4 until gd 2.0 final is out.</strong>
 <p>
 The gd 2.0 documentation update is not complete, but most new features
 are documented to some degree and the what's new section is reasonably
 complete. Enjoy!
-<H2>gd 2.0.0</H2>
+<H2>gd 2.0.1</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
 of this document</A>.</H3>
 <blockquote>
 <strong>HEY! READ THIS!</strong>
-gd 2.0.0 creates PNG, JPEG and WBMP images, not GIF images. This is a 
+gd 2.0.1 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 well 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>
-gd 2.0.0 <strong>requires</strong> that the following libraries 
+gd 2.0.1 <strong>requires</strong> that the following libraries 
 also be installed:
 <p>
 libpng (see the <a href="http://www.libpng.org/pub/png/">libpng home page</a>)
 <H3>Table of Contents</H3>
 <UL>
 <LI><A HREF="#notice">Credits and license terms</A>
-<LI><A HREF="#whatsnew2.0">What's new in version "XYZ" of GD?</A>
+<LI><A HREF="#whatsnew2.0.1">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>
 fitness for a particular purpose, with respect to this code and accompanying
 documentation.
 <p>
-Although their code does not appear in gd 2.0.0, the authors wish to 
+Although their code does not appear in gd 2.0.1, the authors wish to 
 thank David Koblas, David Rowley, and Hutchison Avenue Software 
 Corporation for their prior contributions.
 </blockquote>
 <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.0.
+with 2.0.1.
 <h4>Perl</h4>
 gd can also be used from Perl, courtesy of
 Lincoln Stein's
 <li><a href="http://s27w007.pswfs.gov/tgd/">tgd</a>, by Bradley K. Sherman
 <li><a href="http://www.unimelb.edu.au/fly/fly.html">fly</a>, by Martin Gleeson
 </ul>
+<P><A NAME="whatsnew2.0.1"><H3>What's new in version 2.0.1?</H3></A>
+<ul>
+<li>Workaround for a bug in gcc, apparently found in gcc 2.7.2 and up.
+I reproduced and fixed it while using gcc 2.9.5.2. The bug occurred only
+when the -g option was in use. This problem caused gcc to spew
+internal error messages unrelated to the correctness of the code
+in gd_gd2.c. Howard Jones was first to report it.
+<li><a href="#gdImageFilledEllipse">gdImageFilledEllipse</a> documented
+and altered; no longer requires a superfluous style argument. Thanks to
+Francis James Franklin.
+<li>The Makefile now offers the correct syntax for
+optionally creating a static library. Thanks to Jean-Lous Regez,
+among others.
+<li>A nested comment, an attempt to return the value of a void function,
+and a potentially significant error in gdImageCopyResampled were fixed
+thanks to Joseph Shirley.
+<li>A bug preventing proper truecolor text rendering was fixed,
+thanks to Jason Gallagher.
+<li><a href="#gdImageStringFT">gdImageStringFT</a> (FreeType) should 
+now work better against a transparent or semitransparent background,
+and should act in a manner consistent with the most recent
+<a href="#gdImageAlphaBlending">gdImageAlphaBlending</a> setting.
+Antialiasing is now done via the alpha channel mechanism if the
+image is a truecolor image. 
+<li>Bugs in the output of gdImageArc and gdImageFilledArc were reported
+by Bruce Verderaime. A simple and correct but inefficient implementation
+has been substituted until fixes are contributed for the faster code,
+which is in gd_arc_f_buggy.c along with the test program that reproduces
+the bug(s).
+<li><a href="#gdImageFilledArc">gdImageFilledArc</a> now offers additional
+style options, which can be combined to produce various effects.  
+<li>Masahito Yamaga (ma@yama-ga.com) sent a patch to improve
+support for Japanese output via <a href="#gdImageStringFT">gdImageStringFT</a>. 
+He also added a new <code>readme.jpn</code> file.
+<li>Zillions of documentation fixes.
+</ul>
 <P><A NAME="whatsnew2.0"><H3>What's new in version 2.0?</H3></A>
 <ul>
 <li><strong>Support for truecolor images!</strong> Version 2.0 can
 <A NAME="getgd"><H3>How do I get gd?</H3></A>
 <h4>By HTTP</h4>
 <ul>
-<li><a href="http://www.boutell.com/gd/http/gd-2.0.0.tar.gz">Gzipped Tar File (Unix)</a>
-<li><a href="http://www.boutell.com/gd/http/gd-2.0.0.zip">.ZIP File (Windows)</a>
+<li><a href="http://www.boutell.com/gd/http/gd-2.0.1.tar.gz">Gzipped Tar File (Unix)</a>
+<li><a href="http://www.boutell.com/gd/http/gd-2.0.1.zip">.ZIP File (Windows)</a>
 </ul>
 <h4>By FTP</h4>
 <ul>
-<li><a href="ftp://ftp.boutell.com/pub/boutell/gd/gd-2.0.0.tar.gz">Gzipped Tar File (Unix)</a>
-<li><a href="ftp://ftp.boutell.com/pub/boutell/gd/gd-2.0.0.zip">.ZIP File (Windows)</a>
+<li><a href="ftp://ftp.boutell.com/pub/boutell/gd/gd-2.0.1.tar.gz">Gzipped Tar File (Unix)</a>
+<li><a href="ftp://ftp.boutell.com/pub/boutell/gd/gd-2.0.1.zip">.ZIP File (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.0".
+Unpacking the archive will produce a directory called "gd-2.0.1".
 <p>
 <h4>For Unix</h4>
-<code>cd</code> to the 2.0.0 directory. Edit the Makefile with
+<code>cd</code> to the 2.0.1 directory. Edit the Makefile with
 your preferred text editor and make any necessary changes to the
 settings at the top, especially if you want Xpm or TrueType support.
 Next, type "make install". Because gd 2.0 and above installs
 <strong>(FUNCTION)</strong>
 <DD>
 gdImageCreateTrueColor is called to create truecolor images, with 
-an essentially unlimited number of colors. Invoke gdImageCreate
-with the x and y dimensions of the desired image. gdImageCreate
+an essentially unlimited number of colors. Invoke gdImageCreateTrueColor
+with the x and y dimensions of the desired image. gdImageCreateTrueColor
 returns a <A HREF="#gdImagePtr">gdImagePtr</A> to the new image, or
 NULL if unable to
 allocate the image. The image must eventually be destroyed
 using <A HREF="#gdImageDestroy">gdImageDestroy()</A>.
+<p>
+Truecolor images are always filled with black at creation time.
 <PRE>
 ... inside a function ...
 <A HREF="#gdImagePtr">gdImagePtr</A> im;
-im = gdImageCreate(64, 64);
+im = gdImageCreateTrueColor(64, 64);
 /* ... Use the image ... */
 <A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
 </PRE>
 <DT><A NAME="gdImageFilledArc">void gdImageFilledArc(gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color, int style)</A>
 <STRONG> (FUNCTION)</STRONG>
 <DD>
-gdImageArc is used to draw a partial ellipse centered at the given point,
+gdImageFilledArc is used to draw a partial ellipse centered at the given point,
 with the specified width and height in pixels. The arc begins at
 the position in degrees specified by <code>s</code> and ends at
 the position specified by <code>e</code>. The arc is filled in
 the color specified by the second to last argument. A circle can be drawn
 by beginning from 0 degrees and ending at 360 degrees, with
 width and height being equal. e must be greater than s. Values greater
-than 360 are interpreted modulo 360. The last argument specifies
-whether the function should draw a triangular chord 
-(<code>gdImageChord</code>) or the more frequently desired pie slice
-(<code>gdImagePie</code>).
+than 360 are interpreted modulo 360. The last argument is a bitwise
+OR of the following possibilities:
+<ul>
+<li>gdArc
+<li>gdChord
+<li>gdPie (synonym for gdChord)
+<li>gdNoFill
+<li>gdEdged
+</ul>
+gdArc and gdChord are mutually exclusive;
+gdChord just connects the starting and ending
+angles with a straight line, while gdArc produces
+a rounded edge. gdPie is a synonym for gdArc.
+gdNoFill indicates that the arc or chord should be
+outlined, not filled. gdEdged, used together with
+gdNoFill, indicates that the beginning and ending
+angles should be connected to the center; this is
+a good way to outline (rather than fill) a
+'pie slice'.
+
 <PRE>
 ... inside a function ...
 <A HREF="#gdImagePtr">gdImagePtr</A> im;
 /* Allocate the color white (red, green and blue all maximum). */
 white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);	
 /* Inscribe a filled pie slice in the image. */
-gdImageFilledArc(im, 50, 25, 98, 48, 0, 45, white, gdPie);
+gdImageFilledArc(im, 50, 25, 98, 48, 0, 45, white, gdArc);
 /* ... Do something with the image, such as saving it to a file... */
 /* Destroy it */
 <A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
-</PRE><DT><A NAME="gdImageFillToBorder">void gdImageFillToBorder(gdImagePtr im, int x, int y, int border, int color)
+</PRE>
+<DT><A NAME="gdImageFilledEllipse">void gdImageFilledEllipse(gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color)</A>
+<STRONG> (FUNCTION)</STRONG>
+<DD>
+gdImageFilledEllipse is used to draw an ellipse centered at the given point,
+with the specified width and height in pixels. The ellipse is filled in
+the color specified by the last argument. A circle can be drawn
+by beginning from 0 degrees and ending at 360 degrees, with
+width and height being equal. e must be greater than s. Values greater
+than 360 are interpreted modulo 360.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int white;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 50);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);	
+/* Allocate the color white (red, green and blue all maximum). */
+white = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 255, 255, 255);	
+/* Inscribe a filled ellipse in the image. */
+gdImageFilledEllipse(im, 50, 25, 98, 48, white);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
+<DT><A NAME="gdImageFillToBorder">void gdImageFillToBorder(gdImagePtr im, int x, int y, int border, int color)
 <STRONG> (FUNCTION)</STRONG>
 <DD>
 gdImageFillToBorder floods a portion of the image with the specified
 int red, blue;
 im = <A HREF="#gdImageCreate">gdImageCreateTrueColor</A>(100, 100);
 /* Background color */
-red = <A HREF="#gdTrueColor">gdTrueColor</A>(im, 255, 0, 0);	
+red = <A HREF="#gdTrueColor">gdTrueColor</A>(255, 0, 0);	
 gdImageFilledRectangle(im, 0, 0, 100, 100, red);
 /* Drawing color. Full transparency would be an alpha channel value
 	of 127 (gd has a 7 bit alpha chnanel). 0 is opaque,
 	127 is transparent. So cut gdAlphaTransparent in half to get
 	50% blending. */
-blue = <A HREF="#gdTrueColor">gdTrueColorAlpha</A>(im, 0, 0, 255, gdAlphaTransparent / 2);	
+blue = <A HREF="#gdTrueColor">gdTrueColorAlpha</A>(0, 0, 255, gdAlphaTransparent / 2);	
 /* Draw with blending. Result will be 50% red, 50% blue: yellow 
 	(emitted light, remember, not reflected light. What you learned 
 	in Kindergarten is wrong here). */
 gdImageColorAllocate finds the first available color index in
 the image specified, sets its RGB values to those requested
 (255 is the maximum for each),
-and returns the index of the new color table entry. When
-creating a new image, the first time you invoke this function,
-you are setting the background color for that image.
+and returns the index of the new color table entry, or an RGBA
+value in the case of a truecolor image; in either case you can
+then use the returned value as a parameter to drawing functions. When
+creating a new palette-based image, the first time you invoke this function,
+you are setting the background color for that image. 
 <P>
 In the event that all <A HREF="#gdMaxColors">gdMaxColors</A> colors
 (256) have already been allocated, gdImageColorAllocate will
 does not check for existing colors that match your request;
 see <A HREF="#gdImageColorExact">gdImageColorExact</A>,
 <A HREF="#gdImageColorClosest">gdImageColorClosest</A> and
-<A HREF="#gdImageColorClosest">gdImageColorClosestHWB</A>
+<A HREF="#gdImageColorClosestHWB">gdImageColorClosestHWB</A>
 for ways to locate existing colors that approximate the
 color desired in situations where a new color is not available.
 Also see <A HREF="#gdImageColorResolve">gdImageColorResolve</A>,
 /* Destroy it */
 <A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
 </PRE>
+<DT><A NAME="gdImageColorAllocateAlpha">
+int gdImageColorAllocateAlpha(gdImagePtr im, int r, int g, int b, int a)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageColorAllocateAlpha finds the first available color index in
+the image specified, sets its RGBA values to those requested
+(255 is the maximum for red, green and blue, and 127 represents
+full transparency for alpha),
+and returns the index of the new color table entry, or an RGBA
+value in the case of a truecolor image; in either case you can
+then use the returned value as a parameter to drawing functions. When
+creating a new palette-based image, the first time you invoke this function,
+you are setting the background color for that image. 
+<P>
+In the event that all <A HREF="#gdMaxColors">gdMaxColors</A> colors
+(256) have already been allocated, gdImageColorAllocate will
+return -1 to indicate failure. (This is not uncommon when
+working with existing palette-based PNG files that already use 256 colors.)
+Note that gdImageColorAllocateAlpha
+does not check for existing colors that match your request;
+see <A HREF="#gdImageColorExactAlpha">gdImageColorExactAlpha</A> and
+<A HREF="#gdImageColorClosestAlpha">gdImageColorClosestAlpha</A>
+for ways to locate existing colors that approximate the
+color desired in situations where a new color is not available.
+Also see <A HREF="#gdImageColorResolveAlpha">gdImageColorResolveAlpha</A>.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int black;
+int red;
+im = <A HREF="#gdImageCreate">gdImageCreate</A>(100, 100);
+/* Background color (first allocated) */
+black = <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A>(im, 0, 0, 0);	
+/* Allocate the color red, 50% transparent. */
+red = <A HREF="#gdImageColorAllocateAlpha">gdImageColorAllocateAlpha</A>(im, 255, 0, 0, 64);	
+/* Draw a dashed line from the upper left corner to the lower right corner. */
+gdImageDashedLine(im, 0, 0, 99, 99, red);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
 <DT><A NAME="gdImageColorClosest">
 int gdImageColorClosest(gdImagePtr im, int r, int g, int b)</A>
 <STRONG>(FUNCTION)</STRONG>
 <P>
 If no colors have yet been allocated in the image,
 gdImageColorClosest returns -1.
+<p>
+When applied to a truecolor image, this function always
+succeeds in returning the desired color.
 <P>
 This function is most useful as a backup method for choosing
 a drawing color when an image already contains
 /* Destroy it */
 <A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
 </PRE>
+<DT><A NAME="gdImageColorClosestAlpha">
+int gdImageColorClosestAlpha(gdImagePtr im, int r, int g, int b, int a)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageColorClosest searches the colors which have been
+defined thus far in the image specified and returns the
+index of the color with RGBA values closest to those of the
+request. (Closeness is determined by Euclidian distance,
+which is used to determine the distance in four-dimensional color/alpha
+space between colors.)
+<P>
+If no colors have yet been allocated in the image,
+gdImageColorClosestAlpha returns -1.
+<p>
+When applied to a truecolor image, this function always
+succeeds in returning the desired color.
+<P>
+This function is most useful as a backup method for choosing
+a drawing color when a palette-based image already contains
+<A HREF="#gdMaxColors">gdMaxColors</A> (256) colors and
+no more can be allocated. (This is not uncommon when
+working with existing palette-based PNG files that already use many colors.)
+See <A HREF="#gdImageColorExactAlpha">gdImageColorExactAlpha</A>
+for a method of locating exact matches only.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+FILE *in;
+int red;
+/* Let's suppose that photo.png is a scanned photograph with
+	many colors. */
+in = fopen("photo.png", "rb");
+im = <A HREF="#gdImageCreateFromPng">gdImageCreateFromPng</A>(in);
+fclose(in);
+/* Try to allocate red, 50% transparent, directly */
+red = <A HREF="#gdImageColorAllocateAlpha">gdImageColorAllocateAlpha</A>(im, 255, 0, 0, 64);	
+/* If we fail to allocate red... */
+if (red == (-1)) {
+	/* Find the <em>closest</em> color instead. */
+	red = gdImageColorClosestAlpha(im, 255, 0, 0, 64);
+}
+/* Draw a dashed line from the upper left corner to the lower right corner */
+gdImageDashedLine(im, 0, 0, 99, 99, red);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
 <DT><A NAME="gdImageColorClosestHWB">
 int gdImageColorClosestHWB(gdImagePtr im, int r, int g, int b)</A>
 <STRONG>(FUNCTION)</STRONG>
 <P>
 If no colors have yet been allocated in the image,
 gdImageColorClosestHWB returns -1.
+<p>
+When applied to a truecolor image, this function always
+succeeds in returning the desired color.
 <P>
 This function is most useful as a backup method for choosing
 a drawing color when an image already contains
 /* ... Do something with the image, such as saving it to a file... */
 /* Destroy it */
 <A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
-</PRE><DT><A NAME="gdImageColorExact">
+</PRE>
+<DT><A NAME="gdImageColorExact">
 int gdImageColorExact(gdImagePtr im, int r, int g, int b)</A>
 <STRONG>(FUNCTION)</STRONG>
 <DD>
 request precisely, gdImageColorExact returns -1.
 See <A HREF="#gdImageColorClosest">gdImageColorClosest</A>
 for a way to find the color closest to the color requested.
+<p>
+When applied to a truecolor image, this function always
+succeeds in returning the desired color.
 <PRE>
 ... inside a function ...
 <A HREF="#gdImagePtr">gdImagePtr</A> im;
 exact color.  If there is no space left in the color table then
 gdImageColorResolve returns the closest color (as in gdImageColorClosest).
 This function always returns an index of a color.
+<p>
+When applied to a truecolor image, this function always
+succeeds in returning the desired color.
 <PRE>
 ... inside a function ...
 <A HREF="#gdImagePtr">gdImagePtr</A> im;
 /* Destroy it */
 <A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
 </PRE>
+<DT><A NAME="gdImageColorResolveAlpha">
+int gdImageColorResolveAlpha(gdImagePtr im, int r, int g, int b, int a)</A>
+<STRONG>(FUNCTION)</STRONG>
+<DD>
+gdImageColorResolveAlpha searches the colors which have been
+defined thus far in the image specified and returns the
+index of the first color with RGBA values which exactly
+match those of the request. If no allocated color matches the
+request precisely, then gdImageColorResolveAlpha tries to allocate the
+exact color. If there is no space left in the color table then
+gdImageColorResolveAlpha returns the closest color (as in gdImageColorClosestAlpha).
+This function always returns an index of a color.
+<p>
+When applied to a truecolor image, this function always
+succeeds in returning the desired color.
+<PRE>
+... inside a function ...
+<A HREF="#gdImagePtr">gdImagePtr</A> im;
+int red;
+in = fopen("photo.png", "rb");
+im = <A HREF="#gdImageCreateFromPng">gdImageCreateFromPng</A>(in);
+fclose(in);
+/* The image may already contain red; if it does, we'll save a slot
+	in the color table by using that color. */
+/* Get index of red, 50% transparent, or the next best thing */
+red = gdImageColorResolveAlpha(im, 255, 0, 0, 64);
+/* Draw a dashed line from the upper left corner to the lower right corner */
+gdImageDashedLine(im, 0, 0, 99, 99, red);
+/* ... Do something with the image, such as saving it to a file... */
+/* Destroy it */
+<A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
+</PRE>
 <DT><A NAME="gdImageColorsTotal">
 int gdImageColorsTotal(gdImagePtr im)</A>
 <STRONG>(MACRO)</STRONG>
 <DD>
 gdImageColorsTotal is a macro which returns the number of
-colors currently allocated in the image. Use this macro
-to obtain this information; do not access the structure
-directly.
+colors currently allocated in a palette image. For truecolor
+images, the result of this call is undefined and should not
+be used.
 <DT><A NAME="gdImageColorRed">
 int gdImageColorRed(gdImagePtr im, int c)</A>
 <STRONG>(MACRO)</STRONG>
 <DD>
 gdImageColorRed is a macro which returns the red portion
-of the specified color in the image. Use this macro
-to obtain this information; do not access the structure
-directly.
+of the specified color in the image. This macro works
+for both palette and truecolor images.
 <DT><A NAME="gdImageColorGreen">
 int gdImageColorGreen(gdImagePtr im, int c)</A>
 <STRONG>(MACRO)</STRONG>
 <DD>
 gdImageColorGreen is a macro which returns the green portion
-of the specified color in the image. Use this macro
-to obtain this information; do not access the structure
-directly.
+of the specified color in the image.  This macro works
+for both palette and truecolor images.
 <DT><A NAME="gdImageColorBlue">
 int gdImageColorBlue(gdImagePtr im, int c)</A>
 <STRONG>(MACRO)</STRONG>
 <DD>
 gdImageColorBlue is a macro which returns the green portion
-of the specified color in the image. Use this macro
-to obtain this information; do not access the structure
-directly.
+of the specified color in the image.  This macro works
+for both palette and truecolor images.
 <DT><A NAME="gdImageGetInterlaced">
 int gdImageGetInterlaced(gdImagePtr im)</A>
 <STRONG>(MACRO)</STRONG>
 /* Destroy it */
 <A HREF="#gdImageDestroy">gdImageDestroy</A>(im);
 </PRE>
-</DL>
+<DT><A NAME="gdImageTrueColor">
+void gdImageTrueColor(int red, int green, int blue)</A>
+<STRONG>(MACRO)</STRONG>
+<DD>
+gdImageTrueColor returns an RGBA color value for use when
+drawing on a truecolor image. Red, green, and blue are all
+in the range between 0 (off) and 255 (maximum). This macro should 
+not be used with palette-based images. If you need to write
+code which is compatible with both palette-based and
+truecolor images, use <a href="#gdImageColorResolve">gdImageColorResolve</a>.
+<DT><A NAME="gdImageTrueColorAlpha">
+void gdImageTrueColorAlpha(int red, int green, int blue, int alpha)</A>
+<STRONG>(MACRO)</STRONG>
+<DD>
+gdImageTrueColorAlpha returns an RGBA color value for use when
+drawing on a truecolor image with alpha channel transparency. Red, 
+green, and blue are all
+in the range between 0 (off) and 255 (maximum). Alpha is in the
+range between 0 (opaque) and 127 (fully transparent). This macro should 
+not be used with palette-based images. If you need to write
+code which is compatible with both palette-based and
+truecolor images, use <a href="#gdImageColorResolveAlpha">gdImageColorResolveAlpha</a>.</DL>
 <H3><A NAME="copying">Copying and resizing functions</A></H3>
 <DL>
 
 <A HREF="#gdImageChar">gdImageChar</A> |
 <A HREF="#gdImageCharUp">gdImageCharUp</A> |
 <A HREF="#gdImageColorAllocate">gdImageColorAllocate</A> |
+<A HREF="#gdImageColorAllocateAlpha">gdImageColorAllocateAlpha</A> |
 <A HREF="#gdImageColorClosest">gdImageColorClosest</A> |
+<A HREF="#gdImageColorClosestAlpha">gdImageColorClosestAlpha</A> |
 <A HREF="#gdImageColorDeallocate">gdImageColorDeallocate</A> |
 <A HREF="#gdImageColorExact">gdImageColorExact</A> |
+<A HREF="#gdImageColorExactAlpha">gdImageColorExactAlpha</A> |
 <A HREF="#gdImageColorResolve">gdImageColorResolve</A> |
+<A HREF="#gdImageColorResolveAlpha">gdImageColorResolveAlpha</A> |
 <A HREF="#gdImageColorTransparent">gdImageColorTransparent</A> |
 <A HREF="#gdImageCopy">gdImageCopy</A> |
 <A HREF="#gdImageCopyMerge">gdImageCopyMerge</A> |
 <A HREF="#gdImageDashedLine">gdImageDashedLine</A> |
 <A HREF="#gdImageDestroy">gdImageDestroy</A> |
 <A HREF="#gdImageFill">gdImageFill</A> |
-<A HREF="#gdImageArc">gdImageFilledArc</A> |
+<A HREF="#gdImageFilledArc">gdImageFilledArc</A> |
+<A HREF="#gdImageFilledEllipse">gdImageFilledEllipse</A> |
 <A HREF="#gdImageFillToBorder">gdImageFillToBorder</A> |
 <A HREF="#gdImageFilledRectangle">gdImageFilledRectangle</A> |
 <A HREF="#gdImageGd">gdImageGd</A> |

Binary file modified.

 int basis[91];
 int cost[360];
 
-main(void) {
-	int i;
-	printf("#define costScale %d\n", scale);
-	printf("int cost[] = {\n  ");
-	for (i=0; (i <= 90); i++) {
-		basis[i] = cos((double)i * .0174532925) * scale;
+main (void)
+{
+  int i;
+  printf ("#define costScale %d\n", scale);
+  printf ("int cost[] = {\n  ");
+  for (i = 0; (i <= 90); i++)
+    {
+      basis[i] = cos ((double) i * .0174532925) * scale;
+    }
+  for (i = 0; (i < 90); i++)
+    {
+      printf ("%d,\n  ", cost[i] = basis[i]);
+    }
+  for (i = 90; (i < 180); i++)
+    {
+      printf ("%d,\n  ", cost[i] = -basis[180 - i]);
+    }
+  for (i = 180; (i < 270); i++)
+    {
+      printf ("%d,\n  ", cost[i] = -basis[i - 180]);
+    }
+  for (i = 270; (i < 359); i++)
+    {
+      printf ("%d,\n  ", cost[i] = basis[360 - i]);
+    }
+  printf ("%d\n", cost[359] = basis[1]);
+  printf ("};\n");
+  printf ("#define sintScale %d\n", scale);
+  printf ("int sint[] = {\n  ");
+  for (i = 0; (i < 360); i++)
+    {
+      int val;
+      val = cost[(i + 270) % 360];
+      if (i != 359)
+	{
+	  printf ("%d,\n  ", val);
 	}
-	for (i=0; (i < 90); i++) {
-		printf("%d,\n  ", cost[i] = basis[i]);
+      else
+	{
+	  printf ("%d\n", val);
 	}
-	for (i=90; (i < 180); i++) {
-		printf("%d,\n  ", cost[i] = -basis[180-i]);
-	}
-	for (i=180; (i < 270); i++) {
-		printf("%d,\n  ", cost[i] = -basis[i-180]);
-	}
-	for (i=270; (i < 359); i++) {
-		printf("%d,\n  ", cost[i] = basis[360-i]);
-	}
-	printf("%d\n", cost[359] = basis[1]);
-	printf("};\n");
-	printf("#define sintScale %d\n", scale);
-	printf("int sint[] = {\n  ");
-	for (i=0; (i<360); i++) {
-		int val;
-		val = cost[(i + 270) % 360];
-		if (i != 359) {
-			printf("%d,\n  ", val);
-		} else {
-			printf("%d\n", val);
-		}
-	}
-	printf("};\n");
+    }
+  printf ("};\n");
 }
-		
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.