Anonymous avatar Anonymous committed cfa7ee3

- sync to 2.0.26

Comments (0)

Files changed (7)

+#!/usr/bin/tclsh
+
+# get names for html-4.0 characters from:
+#          http://www.w3.org/TR/REC-html40/sgml/entities.html
+set f [open entities.html r]
+set entity_name_length_max 0
+set nr_of_entities 0
+while {! [eof $f]} {
+        set rec [gets $f]
+        if {[scan $rec {<!ENTITY %s CDATA "&#%d;"; --} name val] == 2} {
+                set entity($name) $val
+		set entity_name_length [string length $name]
+		if {$entity_name_length > $entity_name_length_max} {
+			set entity_name_length_max $entity_name_length
+		}
+		incr nr_of_entities
+        }
+}
+close $f
+
+set f [open entities.h w]
+puts $f "/*"
+puts $f " * Generated file - do not edit directly."
+puts $f " *"
+puts $f " * This file was generated from:"
+puts $f " *       http://www.w3.org/TR/REC-html40/sgml/entities.html"
+puts $f " * by means of the script:"
+puts $f " *       entities.tcl"
+puts $f " */"
+puts $f ""
+puts $f "struct entities_s {"
+puts $f "	char	*name;"
+puts $f "	int	value;"
+puts $f "} entities\[\] = {"
+foreach name [lsort [array names entity]] {
+        puts $f "	{\"$name\", $entity($name)},"
+}
+puts $f "};"
+puts $f ""
+puts $f "#define ENTITY_NAME_LENGTH_MAX $entity_name_length_max"
+puts $f "#define NR_OF_ENTITIES $nr_of_entities"
+close $f

src/fontwheeltest.c

 }
 
 void
-dowheel (gdImagePtr im, int color, char *fontfile,
-	 int fontsize, double angle, int x, int y, char *string)
+dowheel (gdImagePtr im, int color, char *fontfile, int fontsize,
+	double angle, int x, int y, int offset, char *string)
 {
   int brect[8];
   FILE *err;
-  double curang;
+  double curangrads, curang, x0, y0;
   char *cp;
 
   err = fopen ("err.out", "a");
 
   for (curang = 0.0; curang < 360.0; curang += angle)
     {
+      curangrads = DEGTORAD(curang);
+      x0 = x + cos (curangrads) * offset;
+      y0 = y - sin (curangrads) * offset;
+
       /* The case of newlines is taken care of in the gdImageStringTTF call */
 #if defined(OLDER_GD)
-      cp =
-	gdImageStringTTF (im, brect, color, fontfile, fontsize,
-			  DEGTORAD (curang), x, y, string);
+      cp = gdImageStringTTF (im, brect, color, fontfile, fontsize,
+			  curangrads, x0, y0, string);
 #else
-      cp =
-	gdImageStringFT (im, brect, color, fontfile, fontsize,
-			 DEGTORAD (curang), x, y, string);
+      cp = gdImageStringFT (im, brect, color, fontfile, fontsize,
+			 curangrads, x0, y0, string);
 #endif
       if (cp)
 	doerr (err, cp);
+
+      gdImagePolygon (im, (gdPointPtr)brect, 4, color);
     }
 
   fclose (err);
 }
 
+#if 0
 void
 dolines (gdImagePtr im, int color, double incr, int x, int y, int offset,
 	 int length)
       gdImageLine (im, x0, y0, x1, y1, color);
     }
 }
+#endif
 
 void
 dotest (char *font, int size, double incr,
 
   out = fopen (filename, "wb");
 
-  dowheel (im, fc, font, size, incr, xc, yc, string);
+  dowheel (im, fc, font, size, incr, xc, yc, 20, string);
+#if 0
   dolines (im, lc, incr, xc, yc, 20, 120);
+#endif
 
 #if defined(HAVE_LIBPNG)
   gdImagePng (im, out);
 {
 
 #if defined(HAVE_LIBPNG)
-  dotest ("times", 16, 20.0, 400, 400, ".....Hello, there!",
+  dotest ("times", 16, 20.0, 400, 400, "Hello, there!",
 	  "fontwheeltest1.png");
-  dotest ("times", 16, 30.0, 400, 400, ".....Hello, there!",
+  dotest ("times", 16, 30.0, 400, 400, "Hello, there!",
 	  "fontwheeltest2.png");
-  dotest ("arial", 16, 45.0, 400, 400, ".....Hello, there!",
+  dotest ("arial", 16, 45.0, 400, 400, "Hello, there!",
 	  "fontwheeltest3.png");
-  dotest ("arial", 16, 90.0, 400, 400, ".....Hello, there!",
+  dotest ("arial", 16, 90.0, 400, 400, "Hello\nthere!",
 	  "fontwheeltest4.png");
 #elif defined(HAVE_LIBJPEG)
-  dotest ("times", 16, 20.0, 400, 400, ".....Hello, there!",
+  dotest ("times", 16, 20.0, 400, 400, "Hello, there!",
 	  "fontwheeltest1.jpeg");
-  dotest ("times", 16, 30.0, 400, 400, ".....Hello, there!",
+  dotest ("times", 16, 30.0, 400, 400, "Hello, there!",
 	  "fontwheeltest2.jpeg");
-  dotest ("arial", 16, 45.0, 400, 400, ".....Hello, there!",
+  dotest ("arial", 16, 45.0, 400, 400, "Hello, there!",
 	  "fontwheeltest3.jpeg");
-  dotest ("arial", 16, 90.0, 400, 400, ".....Hello, there!",
+  dotest ("arial", 16, 90.0, 400, 400, "Hello\nthere!",
 	  "fontwheeltest4.jpeg");
 #else
   fprintf (stderr, "no PNG or JPEG support\n");
-/* TODO: make sure you didn't break resampling */
-
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
 static void gdImageBrushApply (gdImagePtr im, int x, int y);
 static void gdImageTileApply (gdImagePtr im, int x, int y);
-static void gdImageAntiAliasedApply (gdImagePtr im, int x, int y);
 int gdImageGetTrueColorPixel (gdImagePtr im, int x, int y);
 
 BGD_DECLARE(gdImagePtr) gdImageCreate (int sx, int sy)
   memset (im, 0, sizeof (gdImage));
   /* Row-major ever since gd 1.3 */
   im->pixels = (unsigned char **) gdMalloc (sizeof (unsigned char *) * sy);
-  im->AA_opacity =
-    (unsigned char **) gdMalloc (sizeof (unsigned char *) * sy);
   im->polyInts = 0;
   im->polyAllocated = 0;
   im->brush = 0;
     {
       /* Row-major ever since gd 1.3 */
       im->pixels[i] = (unsigned char *) gdCalloc (sx, sizeof (unsigned char));
-      im->AA_opacity[i] =
-	(unsigned char *) gdCalloc (sx, sizeof (unsigned char));
     }
   im->sx = sx;
   im->sy = sy;
   im->interlace = 0;
   im->thick = 1;
   im->AA = 0;
-  im->AA_polygon = 0;
   for (i = 0; (i < gdMaxColors); i++)
     {
       im->open[i] = 1;
   im = (gdImage *) gdMalloc (sizeof (gdImage));
   memset (im, 0, sizeof (gdImage));
   im->tpixels = (int **) gdMalloc (sizeof (int *) * sy);
-  im->AA_opacity =
-    (unsigned char **) gdMalloc (sizeof (unsigned char *) * sy);
   im->polyInts = 0;
   im->polyAllocated = 0;
   im->brush = 0;
   for (i = 0; (i < sy); i++)
     {
       im->tpixels[i] = (int *) gdCalloc (sx, sizeof (int));
-      im->AA_opacity[i] =
-	(unsigned char *) gdCalloc (sx, sizeof (unsigned char));
     }
   im->sx = sx;
   im->sy = sy;
   im->alphaBlendingFlag = 1;
   im->thick = 1;
   im->AA = 0;
-  im->AA_polygon = 0;
   im->cx1 = 0;
   im->cy1 = 0;
   im->cx2 = im->sx - 1;
 	}
       gdFree (im->tpixels);
     }
-  if (im->AA_opacity)
-    {
-      for (i = 0; (i < im->sy); i++)
-	{
-	  gdFree (im->AA_opacity[i]);
-	}
-      gdFree (im->AA_opacity);
-    }
   if (im->polyInts)
     {
       gdFree (im->polyInts);
    the second call!)  The code is simplified from that in the article,
    as we know that gd images always start at (0,0) */
 
+/* 2.0.26, TBB: we now have to respect a clipping rectangle, it won't
+	necessarily start at 0. */
+
 static int
-clip_1d (int *x0, int *y0, int *x1, int *y1, int maxdim)
+clip_1d (int *x0, int *y0, int *x1, int *y1, int mindim, int maxdim)
 {
   double m;			/* gradient of line */
-  if (*x0 < 0)
+  if (*x0 < mindim)
     {				/* start of line is left of window */
-      if (*x1 < 0)		/* as is the end, so the line never cuts the window */
+      if (*x1 < mindim)		/* as is the end, so the line never cuts the window */
 	return 0;
       m = (*y1 - *y0) / (double) (*x1 - *x0);	/* calculate the slope of the line */
       /* adjust x0 to be on the left boundary (ie to be zero), and y0 to match */
-      *y0 -= m * *x0;
-      *x0 = 0;
+      *y0 -= m * (*x0 - mindim);
+      *x0 = mindim;
       /* now, perhaps, adjust the far end of the line as well */
       if (*x1 > maxdim)
 	{
 					   boundary */
       *x0 = maxdim;
       /* now, perhaps, adjust the end of the line */
-      if (*x1 < 0)
+      if (*x1 < mindim)
 	{
-	  *y1 -= m * *x1;
-	  *x1 = 0;
+	  *y1 -= m * (*x1 - mindim);
+	  *x1 = mindim;
 	}
       return 1;
     }
       *x1 = maxdim;
       return 1;
     }
-  if (*x1 < 0)
+  if (*x1 < mindim)
     {				/* other end is outside to the left */
       m = (*y1 - *y0) / (double) (*x1 - *x0);	/* calculate the slope of the line */
-      *y1 -= m * *x1;
-      *x1 = 0;
+      *y1 -= m * (*x1 - mindim);
+      *x1 = mindim;
       return 1;
     }
   /* only get here if both points are inside the window */
       gdImageTileApply (im, x, y);
       break;
     case gdAntiAliased:
-      gdImageAntiAliasedApply (im, x, y);
+      /* This shouldn't happen (2.0.26) because we just call
+        gdImageAALine now, but do something sane. */
+      gdImageSetPixel(im, x, y, im->AA_color);
       break;
     default:
       if (gdImageBoundsSafeMacro (im, x, y))
     }
 }
 
-static void
-gdImageAntiAliasedApply (gdImagePtr im, int px, int py)
-{
-  float p_dist, p_alpha;
-  unsigned char opacity;
-
-  /* 
-   * Find the perpendicular distance from point C (px, py) to the line 
-   * segment AB that is being drawn.  (Adapted from an algorithm from the
-   * comp.graphics.algorithms FAQ.)
-   */
-
-  int LAC_2, LBC_2;
-
-  int Ax_Cx = im->AAL_x1 - px;
-  int Ay_Cy = im->AAL_y1 - py;
-
-  int Bx_Cx = im->AAL_x2 - px;
-  int By_Cy = im->AAL_y2 - py;
-  /* 2.0.13: bounds check! AA_opacity is just as capable of
-     overflowing as the main pixel array. Arne Jorgensen. 
-     2.0.14: typo fixed. 2.0.15: moved down below declarations
-     to satisfy non-C++ compilers. */
-  if (!gdImageBoundsSafeMacro (im, px, py))
-    {
-      return;
-    }
-  /* Get the squares of the lengths of the segemnts AC and BC. */
-  LAC_2 = (Ax_Cx * Ax_Cx) + (Ay_Cy * Ay_Cy);
-  LBC_2 = (Bx_Cx * Bx_Cx) + (By_Cy * By_Cy);
-
-  if (((im->AAL_LAB_2 + LAC_2) >= LBC_2) &&
-      ((im->AAL_LAB_2 + LBC_2) >= LAC_2))
-    {
-      /* The two angles are acute.  The point lies inside the portion of the 
-       * plane spanned by the line segment. */
-      p_dist = fabs ((float) ((Ay_Cy * im->AAL_Bx_Ax) -
-			      (Ax_Cx * im->AAL_By_Ay)) / im->AAL_LAB);
-    }
-  else
-    {
-      /* The point is past an end of the line segment.  It's length from the 
-       * segment is the shorter of the lengths from the endpoints, but call
-       * the distance -1, so as not to compute the alpha nor draw the pixel.
-       */
-      p_dist = -1;
-    }
-
-  if ((p_dist >= 0) && (p_dist <= (float) (im->thick)))
-    {
-      p_alpha = pow (1.0 - (p_dist / 1.5), 2);
-
-      if (p_alpha > 0)
-	{
-	  if (p_alpha >= 1)
-	    opacity = 255;
-	  else
-	    opacity = (unsigned char) (p_alpha * 255.0);
-	  if (!(im->AA_polygon) || (im->AA_opacity[py][px] < opacity))
-	    im->AA_opacity[py][px] = opacity;
-	}
-    }
-}
-
 BGD_DECLARE(int) gdImageGetPixel (gdImagePtr im, int x, int y)
 {
   if (gdImageBoundsSafeMacro (im, x, y))
 
 BGD_DECLARE(void) gdImageAABlend (gdImagePtr im)
 {
-  float p_alpha, old_alpha;
-  int color = im->AA_color, color_red, color_green, color_blue;
-  int old_color, old_red, old_green, old_blue;
-  int p_color, p_red, p_green, p_blue;
-  int px, py;
-
-  color_red = gdImageRed (im, color);
-  color_green = gdImageGreen (im, color);
-  color_blue = gdImageBlue (im, color);
-
-  /* Impose the anti-aliased drawing on the image. */
-  for (py = 0; py < im->sy; py++)
-    {
-      for (px = 0; px < im->sx; px++)
-	{
-	  if (im->AA_opacity[py][px] != 0)
-	    {
-	      old_color = gdImageGetPixel (im, px, py);
-
-	      if ((old_color != color)
-		  && ((old_color != im->AA_dont_blend)
-		      || (im->AA_opacity[py][px] == 255)))
-		{
-		  /* Only blend with different colors that aren't the 
-		   * dont_blend color. */
-		  p_alpha = (float) (im->AA_opacity[py][px]) / 255.0;
-		  old_alpha = 1.0 - p_alpha;
-
-		  if (p_alpha >= 1.0)
-		    p_color = color;
-		  else
-		    {
-		      old_red = gdImageRed (im, old_color);
-		      old_green = gdImageGreen (im, old_color);
-		      old_blue = gdImageBlue (im, old_color);
-
-		      p_red = (int) (((float) color_red * p_alpha) +
-				     ((float) old_red * old_alpha));
-		      p_green = (int) (((float) color_green * p_alpha) +
-				       ((float) old_green * old_alpha));
-		      p_blue = (int) (((float) color_blue * p_alpha) +
-				      ((float) old_blue * old_alpha));
-		      p_color =
-			gdImageColorResolve (im, p_red, p_green, p_blue);
-		    }
-		  gdImageSetPixel (im, px, py, p_color);
-		}
-	    }
-	}
-      /* Clear the AA_opacity array behind us. */
-      memset (im->AA_opacity[py], 0, im->sx);
-    }
+  /* NO-OP, kept for library compatibility. */
 }
 
+static void gdImageAALine (gdImagePtr im, int x1, int y1, int x2, int y2, int col);
+
 /* Bresenham as presented in Foley & Van Dam */
 BGD_DECLARE(void) gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
 {
   int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
   int wid;
   int w, wstart;
-  int thick = im->thick;
-
+  int thick;
+  if (color == gdAntiAliased)
+    {
+      /* 
+        gdAntiAliased passed as color: use the much faster, much cheaper
+        and equally attractive gdImageAALine implementation. That
+        clips too, so don't clip twice.
+      */
+      gdImageAALine(im, x1, y1, x2, y2, im->AA_color); 
+      return;
+    }
   /* 2.0.10: Nick Atty: clip to edges of drawing rectangle, return if no
-     points need to be drawn */
+     points need to be drawn. 2.0.26, TBB: clip to edges of clipping
+     rectangle. We were getting away with this because gdImageSetPixel
+     is used for actual drawing, but this is still more efficient and opens
+     the way to skip per-pixel bounds checking in the future. */
 
-  if (clip_1d (&x1, &y1, &x2, &y2, gdImageSX (im)) == 0)
+  if (clip_1d (&x1, &y1, &x2, &y2, im->cx1, im->cx2) == 0)
     return;
-  if (clip_1d (&y1, &x1, &y2, &x2, gdImageSY (im)) == 0)
+  if (clip_1d (&y1, &x1, &y2, &x2, im->cy1, im->cy2) == 0)
     return;
-
-  /* gdAntiAliased passed as color: set anti-aliased line (AAL) global vars. */
-  if (color == gdAntiAliased)
-    {
-      im->AAL_x1 = x1;
-      im->AAL_y1 = y1;
-      im->AAL_x2 = x2;
-      im->AAL_y2 = y2;
-
-      /* Compute what we can for point-to-line distance calculation later. */
-      im->AAL_Bx_Ax = x2 - x1;
-      im->AAL_By_Ay = y2 - y1;
-      im->AAL_LAB_2 =
-	(im->AAL_Bx_Ax * im->AAL_Bx_Ax) + (im->AAL_By_Ay * im->AAL_By_Ay);
-      im->AAL_LAB = sqrt (im->AAL_LAB_2);
-
-      /* For AA, we must draw pixels outside the width of the line.  Keep in
-       * mind that this will be curtailed by cos/sin of theta later. */
-      thick += 4;
-    }
+  thick = im->thick;
 
   dx = abs (x2 - x1);
   dy = abs (y2 - y1);
 	}
     }
 
-  /* If this is the only line we are drawing, go ahead and blend. */
-  if ((color == gdAntiAliased) && !(im->AA_polygon))
-    gdImageAABlend (im);
 }
 static void dashedSet (gdImagePtr im, int x, int y, int color,
 		       int *onP, int *dashStepP, int wid, int vert);
       return;
     }
 
-  /* Let it be known that we are drawing a polygon so that the opacity
-   * mask doesn't get cleared after each line. */
-  if (c == gdAntiAliased)
-    im->AA_polygon = 1;
 
   lx = p->x;
   ly = p->y;
       ly = p->y;
     }
 
-  if (c == gdAntiAliased)
-    {
-      im->AA_polygon = 0;
-      gdImageAABlend (im);
-    }
 }
 
-int gdCompareInt (const void *a, const void *b);
-
 /* THANKS to Kirsten Schulz for the polygon fixes! */
 
 /* The intersection finding technique of this code could be improved  */
 /* That could help to adjust intersections  to produce a nice */
 /* interior_extrema. */
 
+static void horizontalLine(gdImagePtr im, int minx, int maxx, int y,
+	int fill_color);
+
 BGD_DECLARE(void) gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int c)
 {
   int i;
+  int j;
+  int index;
   int y;
   int miny, maxy;
   int x1, y1;
       return;
     }
 
-  if (c == gdAntiAliased)
-    fill_color = im->AA_color;
-  else
-    fill_color = c;
 
   if (!im->polyAllocated)
     {
 	}
     }
   /* 2.0.16: Optimization by Ilia Chipitsine -- don't waste time offscreen */
-  if (miny < 0)
+  /* 2.0.26: clipping rectangle is even better */
+  if (miny < im->cy1)
     {
-      miny = 0;
+      miny = im->cy1;
     }
-  if (maxy >= gdImageSY (im))
+  if (maxy > im->cy2)
     {
-      maxy = gdImageSY (im) - 1;
+      maxy = im->cy2;
     }
   /* Fix in 1.3: count a vertex only once */
   for (y = miny; (y <= maxy); y++)
 /*1.4           int interLast = 0; */
 /*              int dirLast = 0; */
 /*              int interFirst = 1; */
+      int yshift = 0;
+      if (c == gdAntiAliased) {
+        fill_color = im->AA_color;
+      } else {
+        fill_color = c;
+      }
       ints = 0;
       for (i = 0; (i < n); i++)
 	{
 	  /* Do the following math as float intermediately, and round to ensure
 	   * that Polygon and FilledPolygon for the same set of points have the
 	   * same footprint. */
+ 
 	  if ((y >= y1) && (y < y2))
 	    {
-	      im->polyInts[ints++] = (float) ((y - y1) * (x2 - x1)) /
-		(float) (y2 - y1) + 0.5 + x1;
+	      im->polyInts[ints++] = (int) ((float) ((y - y1) * (x2 - x1)) /
+		(float) (y2 - y1) + 0.5 + x1);
 	    }
 	  else if ((y == maxy) && (y > y1) && (y <= y2))
 	    {
-	      im->polyInts[ints++] = (float) ((y - y1) * (x2 - x1)) /
-		(float) (y2 - y1) + 0.5 + x1;
-	    }
-	}
-      qsort (im->polyInts, ints, sizeof (int), gdCompareInt);
-
+	      im->polyInts[ints++] = (int) ((float) ((y - y1) * (x2 - x1)) /
+		(float) (y2 - y1) + 0.5 + x1);
+	    }
+	}
+      /* 
+        2.0.26: polygons pretty much always have less than 100 points,
+        and most of the time they have considerably less. For such trivial
+        cases, insertion sort is a good choice. Also a good choice for
+        future implementations that may wish to indirect through a table.
+      */
+      for (i = 1; (i < ints); i++) {
+        index = im->polyInts[i];
+        j = i;
+        while ((j > 0) && (im->polyInts[j - 1] > index)) {
+          im->polyInts[j] = im->polyInts[j - 1];
+          j--;
+        }
+        im->polyInts[j] = index;
+      }
       for (i = 0; (i < (ints)); i += 2)
 	{
-	  gdImageLine (im, im->polyInts[i], y, im->polyInts[i + 1], y,
-		       fill_color);
+          int minx = im->polyInts[i];
+          int maxx = im->polyInts[i + 1];
+          horizontalLine(im, minx, maxx, y, fill_color);
 	}
     }
-
   /* If we are drawing this AA, then redraw the border with AA lines. */
-  if (c == gdAntiAliased)
+  /* This doesn't work as well as I'd like, but it doesn't clash either. */
+  if (c == gdAntiAliased) {
     gdImagePolygon (im, p, n, c);
-}
-
-int
-gdCompareInt (const void *a, const void *b)
-{
-  return (*(const int *) a) - (*(const int *) b);
-}
+  } 
+}
+
+static void horizontalLine(gdImagePtr im, int minx, int maxx, int y,
+	int fill_color)
+{
+  if (minx < im->cx1) {
+    minx = im->cx1;
+  } 
+  if (maxx > im->cx2) {
+    maxx = im->cx2;
+  } 
+  if (y < im->cy1) {
+    y = im->cy1;
+  }
+  if (y > im->cy2) {
+    y = im->cy2;
+  }
+  if (minx > maxx) {
+    int t = maxx;
+    maxx = minx;
+    minx = t;
+  } 
+  if (im->trueColor) {
+    while (minx <= maxx) {
+      im->tpixels[y][minx++] = fill_color;
+    }
+  } else {
+    while (minx <= maxx) {
+      im->pixels[y][minx++] = fill_color;
+    }
+  }
+}
+
+inline static void gdImageSetAAPixelColor(gdImagePtr im, int x, int y, int color, int t);
 
 BGD_DECLARE(void) gdImageSetStyle (gdImagePtr im, int *style, int noOfPixels)
 {
   *x2P = im->cx2;
   *y2P = im->cy2;
 }
+
+/*
+ * Added on 2003/12 by Pierre-Alain Joye (pajoye@pearfr.org)
+ * */
+#define BLEND_COLOR(a, nc, c, cc) \
+nc = (cc) + (((((c) - (cc)) * (a)) + ((((c) - (cc)) * (a)) >> 8) + 0x80) >> 8);
+
+inline static void gdImageSetAAPixelColor(gdImagePtr im, int x, int y, int color, int t)
+{
+	int dr,dg,db,p,r,g,b;
+	p = gdImageGetPixel(im,x,y);
+        /* TBB: we have to implement the dont_blend stuff to provide
+          the full feature set of the old implementation */
+        if ((p == color)
+	  || ((p == im->AA_dont_blend)
+	      && (t != 0x00)))
+        {
+          return;
+        }
+	dr = gdTrueColorGetRed(color);
+	dg = gdTrueColorGetGreen(color);
+	db = gdTrueColorGetBlue(color);
+
+	r = gdTrueColorGetRed(p);
+	g = gdTrueColorGetGreen(p);
+	b = gdTrueColorGetBlue(p);
+
+	BLEND_COLOR(t, dr, r, dr);
+	BLEND_COLOR(t, dg, g, dg);
+	BLEND_COLOR(t, db, b, db);
+	im->tpixels[y][x]=gdTrueColorAlpha(dr, dg, db,  gdAlphaOpaque);
+}  
+
+static void gdImageAALine (gdImagePtr im, int x1, int y1, int x2, int y2, int col)
+{
+	/* keep them as 32bits */
+	long x, y, inc;
+	long dx, dy,tmp;
+	if (!im->trueColor) {
+		/* TBB: don't crash when the image is of the wrong type */
+		gdImageLine(im, x1, y1, x2, y2, col);
+		return;
+	}
+        /* TBB: use the clipping rectangle */
+        if (clip_1d (&x1, &y1, &x2, &y2, im->cx1, im->cx2) == 0)
+          return;
+        if (clip_1d (&y1, &x1, &y2, &x2, im->cy1, im->cy2) == 0)
+          return;
+	dx = x2 - x1;
+	dy = y2 - y1;
+
+	if (dx == 0 && dy == 0) {
+		/* TBB: allow setting points */
+		gdImageSetAAPixelColor(im, x1, y1, col, 0xFF);
+		return;
+	}
+	if (abs(dx) > abs(dy)) {
+		if (dx < 0) {
+			tmp = x1;
+			x1 = x2;
+			x2 = tmp;
+			tmp = y1;
+			y1 = y2;
+			y2 = tmp;
+			dx = x2 - x1;
+			dy = y2 - y1;
+		}
+		x = x1 << 16;
+		y = y1 << 16;
+		inc = (dy * 65536) / dx;
+		/* TBB: set the last pixel for consistency (<=) */
+		while ((x >> 16) <= x2) {
+			gdImageSetAAPixelColor(im, x >> 16, y >> 16, col, (y >> 8) & 0xFF);
+			gdImageSetAAPixelColor(im, x >> 16, (y >> 16) + 1,col, (~y >> 8) & 0xFF);
+			x += (1 << 16);
+			y += inc;
+		}
+	} else {
+		if (dy < 0) {
+			tmp = x1;
+			x1 = x2;
+			x2 = tmp;
+			tmp = y1;
+			y1 = y2;
+			y2 = tmp;
+			dx = x2 - x1;
+			dy = y2 - y1;
+		}
+		x = x1 << 16;
+		y = y1 << 16;
+		inc = (dx * 65536) / dy;
+		/* TBB: set the last pixel for consistency (<=) */
+		while ((y>>16) <= y2) {
+			gdImageSetAAPixelColor(im, x >> 16, y >> 16, col, (x >> 8) & 0xFF);
+			gdImageSetAAPixelColor(im, (x >> 16) + 1, (y >> 16),col, (~x >> 8) & 0xFF);
+			x += inc;
+			y += (1<<16);
+		}
+	}
+}
        have that capability. JPEG doesn't. */
     int saveAlphaFlag;
 
-    /* 2.0.12: anti-aliased globals */
+    /* There should NEVER BE ACCESSOR MACROS FOR ITEMS BELOW HERE, so this
+       part of the structure can be safely changed in new releases. */
+
+    /* 2.0.12: anti-aliased globals. 2.0.26: just a few vestiges after
+      switching to the fast, memory-cheap implementation from PHP-gd. */
     int AA;
     int AA_color;
     int AA_dont_blend;
-    unsigned char **AA_opacity;
-    int AA_polygon;
-    /* Stored and pre-computed variables for determining the perpendicular
-       distance from a point to the anti-aliased line being drawn: */
-    int AAL_x1;
-    int AAL_y1;
-    int AAL_x2;
-    int AAL_y2;
-    int AAL_Bx_Ax;
-    int AAL_By_Ay;
-    int AAL_LAB_2;
-    float AAL_LAB;
 
     /* 2.0.12: simple clipping rectangle. These values
       must be checked for safety when set; please use
 
 BGD_DECLARE(int) gdImageGetPixel (gdImagePtr im, int x, int y);
 
+/* Now a No-Op, but kept for binary compatibility. */
 BGD_DECLARE(void) gdImageAABlend (gdImagePtr im);
 
 BGD_DECLARE(void) gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color);
       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);
+      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);
 #include <math.h>
 #include "gd.h"
 #include "gdhelpers.h"
+#include "entities.h"
 
 /* 2.0.10: WIN32, not MSWIN32 */
 #ifndef WIN32
 #include "jisx0208.h"
 #endif
 
+static int comp_entities(const void *e1, const void *e2) {
+  struct entities_s *en1 = (struct entities_s *) e1;
+  struct entities_s *en2 = (struct entities_s *) e2;
+  return strcmp(en1->name, en2->name);
+}
+
 #define Tcl_UniChar int
 #define TCL_UTF_MAX 3
 static int
 /* chPtr is the int for the result */
 {
   int byte;
+  char entity_name_buf[ENTITY_NAME_LENGTH_MAX+1];
+  char *p;
+  struct entities_s key, *res;
 
   /* HTML4.0 entities in decimal form, e.g. &#197; */
+  /*           or in hexadecimal form, e.g. &#x6C34; */
   byte = *((unsigned char *) str);
   if (byte == '&')
     {
       byte = *((unsigned char *) (str + 1));
       if (byte == '#')
 	{
-	  for (i = 2; i < 8; i++)
-	    {
-	      byte = *((unsigned char *) (str + i));
-	      if (byte >= '0' && byte <= '9')
-		{
-		  n = (n * 10) + (byte - '0');
+          byte = *((unsigned char *) (str + 2));
+          if (byte == 'x' || byte == 'X')
+            {
+              for (i = 3; i < 8; i++)
+                {
+                  byte = *((unsigned char *) (str + i));
+                  if (byte >= 'A' && byte <= 'F')
+                    byte = byte - 'A' + 10;
+                  else if (byte >= 'a' && byte <= 'f')
+                    byte = byte - 'a' + 10;
+                  else if (byte >= '0' && byte <= '9')
+                    byte = byte - '0';
+                  else
+                    break;
+                  n = (n * 16) + byte;
+                }
+            }
+          else
+            {
+	      for (i = 2; i < 8; i++)
+	        {
+	          byte = *((unsigned char *) (str + i));
+	          if (byte >= '0' && byte <= '9')
+	            n = (n * 10) + (byte - '0');
+	          else
+		    break;
 		}
-	      else
-		break;
 	    }
 	  if (byte == ';')
 	    {
 	      return ++i;
 	    }
 	}
+      else
+        {
+          key.name = p = entity_name_buf;
+          for (i = 1; i < 1 + ENTITY_NAME_LENGTH_MAX; i++)
+            {
+              byte = *((unsigned char *) (str + i));
+              if (byte == '\0')
+                break;
+              if (byte == ';')
+                {
+                  *p++ = '\0';
+                  res = bsearch(&key, entities, NR_OF_ENTITIES,
+                       sizeof(entities[0]), *comp_entities);
+                  if (res)
+                    {
+                      *chPtr = (Tcl_UniChar) res->value;
+                      return ++i;
+                    }
+                  break;
+               }
+              *p++ = byte;
+            }
+        }
     }
 
   /*
       for (dir = strtok (path, PATHSEPARATOR); dir;
 	   dir = strtok (0, PATHSEPARATOR))
 	{
+          if (strchr (name, '.'))
+            {
+              sprintf (fullname, "%s/%s", dir, name);
+              if (access (fullname, R_OK) == 0)
+                {
+                  font_found++;
+                  break;
+                }
+              else
+                {
+                  continue;
+                }
+            }
 	  sprintf (fullname, "%s/%s.ttf", dir, name);
 	  if (access (fullname, R_OK) == 0)
 	    {
 {
   unsigned char *pixel = NULL;
   int *tpixel = NULL;
+  int opixel;
   int x, y, row, col, pc, pcr;
 
   tweencolor_t *tc_elem;
 		{
 		  return "Unsupported ft_pixel_mode";
 		}
+              if (level == 0)  /* if background */
+		continue;
+
 	      if ((fg >= 0) && (im->trueColor))
 		{
 		  /* Consider alpha in the foreground color itself to be an
 		    level * (gdAlphaMax -
 			     gdTrueColorGetAlpha (fg)) / gdAlphaMax;
 		}
-	      level = gdAlphaMax - level;
+	      level = gdAlphaMax - level;   /* inverting to get alpha */
 	      x = pen_x + col;
 	      /* clip if out of bounds */
 	      /* 2.0.16: clip to clipping rectangle, Matt McNabb */
 		{
 		  if (im->alphaBlendingFlag)
 		    {
-		      *tpixel =
-			gdAlphaBlend (*tpixel,
+		      opixel = *tpixel;
+		      if (gdTrueColorGetAlpha(opixel) != gdAlphaTransparent)
+			{
+			  *tpixel = gdAlphaBlend (opixel,
 				      (level << 24) + (fg & 0xFFFFFF));
+			}
+		      else
+			{
+			  *tpixel = (level << 24) + (fg & 0xFFFFFF);
+			}
 		    }
 		  else
 		    {
 	    {
 	      return "Unsupported ft_pixel_mode";
 	    }
-	  if (tc_key.pixel > 0)	/* if not background */
-	    {
-	      x = pen_x + col;
+	  if (tc_key.pixel == 0)	/* if background */
+	    continue;
 
-	      /* clip if out of bounds */
-	      if (x >= im->sx || x < 0)
-		continue;
-	      /* get pixel location in gd buffer */
-	      pixel = &im->pixels[y][x];
-	      if (tc_key.pixel == NUMCOLORS)
-		{
-		  /* use fg color directly. gd 2.0.2: watch out for
-		     negative indexes (thanks to David Marwood). */
-		  *pixel = (fg < 0) ? -fg : fg;
-		}
-	      else
-		{
-		  /* find antialised color */
+	  x = pen_x + col;
 
-		  tc_key.bgcolor = *pixel;
-		  tc_elem = (tweencolor_t *) gdCacheGet (tc_cache, &tc_key);
-		  *pixel = tc_elem->tweencolor;
-		}
+	  /* clip if out of bounds */
+	  if (x >= im->sx || x < 0)
+	    continue;
+	  /* get pixel location in gd buffer */
+	  pixel = &im->pixels[y][x];
+	  if (tc_key.pixel == NUMCOLORS)
+	    {
+	      /* use fg color directly. gd 2.0.2: watch out for
+	         negative indexes (thanks to David Marwood). */
+	      *pixel = (fg < 0) ? -fg : fg;
+	    }
+	  else
+	    {
+	      /* find antialised color */
+
+	      tc_key.bgcolor = *pixel;
+	      tc_elem = (tweencolor_t *) gdCacheGet (tc_cache, &tc_key);
+	      *pixel = tc_elem->tweencolor;
 	    }
 	}
     }
   return (char *) NULL;
 }
 
-static int
-gdroundupdown (FT_F26Dot6 v1, int updown)
-{
-  return (!updown)
-    ? (v1 < 0 ? ((v1 - 63) >> 6) : v1 >> 6)
-    : (v1 > 0 ? ((v1 + 63) >> 6) : v1 >> 6);
-}
-
 extern int any2eucjp (char *, char *, unsigned int);
 
 /* Persistent font cache until explicitly cleared */
 		   double ptsize, double angle, int x, int y, char *string,
 		   gdFTStringExtraPtr strex)
 {
-  FT_BBox bbox, glyph_bbox;
   FT_Matrix matrix;
-  FT_Vector pen, delta, penf;
+  FT_Vector penf, delta, total_min, total_max, glyph_min, glyph_max;
   FT_Face face;
   FT_Glyph image;
   FT_GlyphSlot slot;
   FT_UInt glyph_index, previous;
   double sin_a = sin (angle);
   double cos_a = cos (angle);
-  int len, i = 0, ch;
-  int x1 = 0, y1 = 0;
+  int len, i, ch;
   font_t *font;
   fontkey_t fontkey;
   char *next;
   matrix.xy = -matrix.yx;
   matrix.yy = matrix.xx;
 
-  penf.x = penf.y = 0;		/* running position of non-rotated string */
-  pen.x = pen.y = 0;		/* running position of rotated string */
-  bbox.xMin = bbox.xMax = bbox.yMin = bbox.yMax = 0;
-
   use_kerning = FT_HAS_KERNING (face);
   previous = 0;
   if (fg < 0)
       next = string;
     }
 #endif
-  while (*next)
+
+  penf.x = penf.y = 0;	/* running position of non-rotated glyphs */
+
+  for (i=0; *next; i++)
     {
+
       ch = *next;
 
       /* carriage returns */
       if (ch == '\r')
 	{
 	  penf.x = 0;
-	  x1 = (penf.x * cos_a - penf.y * sin_a + 32) / 64;
-	  y1 = (penf.x * sin_a + penf.y * cos_a + 32) / 64;
-	  pen.x = pen.y = 0;
 	  previous = 0;		/* clear kerning flag */
 	  next++;
 	  continue;
 	{
 	  /* 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 */
-	  x1 = (penf.x * cos_a - penf.y * sin_a + 32) / 64;
-	  y1 = (penf.x * sin_a + penf.y * cos_a + 32) / 64;
-	  pen.x = pen.y = 0;
+	  penf.y += face->size->metrics.height * linespace;
+	  penf.y = (penf.y + 32) & -64;	/* round to next pixel row */
 	  previous = 0;		/* clear kerning flag */
 	  next++;
 	  continue;
 	{
 	  FT_Get_Kerning (face, previous, glyph_index,
 			  ft_kerning_default, &delta);
-	  pen.x += delta.x;
 	  /* 2.0.12: indispensable for an accurate bounding box. */
 	  penf.x += delta.x;
 	}
 	  return "Problem loading glyph";
 	}
 
-      /* transform glyph image */
-      FT_Get_Glyph (slot, &image);
       if (brect)
 	{			/* only if need brect */
-	  FT_Glyph_Get_CBox (image, ft_glyph_bbox_gridfit, &glyph_bbox);
-	  glyph_bbox.xMin += penf.x;
-	  glyph_bbox.yMin += penf.y;
-	  glyph_bbox.xMax += penf.x;
-	  glyph_bbox.yMax += penf.y;
-	  if (ch == ' ')	/* special case for trailing space */
-	    glyph_bbox.xMax += slot->metrics.horiAdvance;
-	  if (!i)
-	    {			/* if first character, init BB corner values */
-	      bbox.xMin = glyph_bbox.xMin;
-	      bbox.yMin = glyph_bbox.yMin;
-	      bbox.xMax = glyph_bbox.xMax;
-	      bbox.yMax = glyph_bbox.yMax;
+
+	  glyph_min.x = penf.x + slot->metrics.horiBearingX;
+	  glyph_min.y = penf.y - slot->metrics.horiBearingY;
+
+	  if (ch == ' ')        /* special case for trailing space */
+            {
+	      glyph_max.x = penf.x + slot->metrics.horiAdvance;
+            }
+          else
+            {
+	      glyph_max.x = glyph_min.x + slot->metrics.width;
+            }
+	  glyph_max.y = glyph_min.y + slot->metrics.height;
+
+	  if (i==0)
+	    {
+	      total_min = glyph_min;
+	      total_max = glyph_max;
 	    }
 	  else
 	    {
-	      if (bbox.xMin > glyph_bbox.xMin)
-		bbox.xMin = glyph_bbox.xMin;
-	      if (bbox.yMin > glyph_bbox.yMin)
-		bbox.yMin = glyph_bbox.yMin;
-	      if (bbox.xMax < glyph_bbox.xMax)
-		bbox.xMax = glyph_bbox.xMax;
-	      if (bbox.yMax < glyph_bbox.yMax)
-		bbox.yMax = glyph_bbox.yMax;
+              if (glyph_min.x < total_min.x)
+                  total_min.x = glyph_min.x;
+              if (glyph_min.y < total_min.y)
+                  total_min.y = glyph_min.y;
+              if (glyph_max.x > total_max.x)
+                  total_max.x = glyph_max.x;
+              if (glyph_max.y > total_max.y)
+                  total_max.y = glyph_max.y;
 	    }
-	  i++;
 	}
 
       if (render)
 	{
+          /* transform glyph image */
+          FT_Get_Glyph (slot, &image);
+
 	  if (image->format != ft_glyph_format_bitmap)
 	    {
 	      err = FT_Glyph_To_Bitmap (&image, ft_render_mode_normal, 0, 1);
 	  /* now, draw to our target surface */
 	  bm = (FT_BitmapGlyph) image;
 	  gdft_draw_bitmap (tc_cache, im, fg, bm->bitmap,
-			    x + x1 + ((pen.x + 31) >> 6) + bm->left,
-			    y - y1 + ((pen.y + 31) >> 6) - bm->top);
+		    x + (penf.x * cos_a + penf.y * sin_a + 32)/64 + bm->left,
+		    y - (penf.x * sin_a - penf.y * cos_a - 32)/64 - bm->top);
+
+          FT_Done_Glyph (image);
 	}
 
       /* record current glyph index for kerning */
       previous = glyph_index;
 
-      /* increment pen position */
-      pen.x += image->advance.x >> 10;
-      pen.y -= image->advance.y >> 10;
-
+      /* advance character position */ 
       penf.x += slot->metrics.horiAdvance;
-
-      FT_Done_Glyph (image);
     }
 
   if (brect)
     {				/* only if need brect */
-      /* For perfect rounding, must get sin(a + pi/4) and sin(a - pi/4). */
-      double d1 = sin (angle + 0.78539816339744830962);
-      double d2 = sin (angle - 0.78539816339744830962);
-
-      /* rotate bounding rectangle */
-      brect[0] = (int) (bbox.xMin * cos_a - bbox.yMin * sin_a);
-      brect[1] = (int) (bbox.xMin * sin_a + bbox.yMin * cos_a);
-      brect[2] = (int) (bbox.xMax * cos_a - bbox.yMin * sin_a);
-      brect[3] = (int) (bbox.xMax * sin_a + bbox.yMin * cos_a);
-      brect[4] = (int) (bbox.xMax * cos_a - bbox.yMax * sin_a);
-      brect[5] = (int) (bbox.xMax * sin_a + bbox.yMax * cos_a);
-      brect[6] = (int) (bbox.xMin * cos_a - bbox.yMax * sin_a);
-      brect[7] = (int) (bbox.xMin * sin_a + bbox.yMax * cos_a);
-
-      /* scale, round and offset brect */
-      brect[0] = x + gdroundupdown (brect[0], d2 > 0);
-      brect[1] = y - gdroundupdown (brect[1], d1 < 0);
-      brect[2] = x + gdroundupdown (brect[2], d1 > 0);
-      brect[3] = y - gdroundupdown (brect[3], d2 > 0);
-      brect[4] = x + gdroundupdown (brect[4], d2 < 0);
-      brect[5] = y - gdroundupdown (brect[5], d1 > 0);
-      brect[6] = x + gdroundupdown (brect[6], d1 < 0);
-      brect[7] = y - gdroundupdown (brect[7], d2 < 0);
+
+      /* increase by 1 pixel to allow for rounding */
+      total_min.x -= 64;
+      total_min.y -= 64;
+      total_max.x += 64;
+      total_max.y += 64;
+ 
+      /* rotate bounding rectangle, scale and round to int pixels, and translate */
+      brect[0] = x + (total_min.x * cos_a + total_min.y * sin_a + 32)/64;
+      brect[1] = y - (total_min.x * sin_a - total_min.y * cos_a + 32)/64;
+      brect[2] = x + (total_max.x * cos_a + total_min.y * sin_a + 32)/64;
+      brect[3] = y - (total_max.x * sin_a - total_min.y * cos_a + 32)/64;
+      brect[4] = x + (total_max.x * cos_a + total_max.y * sin_a + 32)/64;
+      brect[5] = y - (total_max.x * sin_a - total_max.y * cos_a + 32)/64;
+      brect[6] = x + (total_min.x * cos_a + total_max.y * sin_a + 32)/64;
+      brect[7] = y - (total_min.x * sin_a - total_max.y * cos_a + 32)/64;
     }
 
   if (tmpstr)
+#ifdef HAVE_CONFIG_H                                                  #include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include "gd.h"
+
+#define FALSE 0
+#define TRUE (!FALSE)
+
+int
+main (int argc, char *argv[])
+{
+#ifdef HAVE_LIBFREETYPE
+  	FILE *out;
+	int transparent, green, black;
+	gdImagePtr im;
+
+	im = gdImageCreateTrueColor(100,100);
+
+        black =  gdImageColorResolveAlpha(im, 0, 0, 0, gdAlphaOpaque);
+        green =  gdImageColorResolveAlpha(im, 0, gdGreenMax, 0, gdAlphaOpaque);
+        transparent = gdImageColorResolveAlpha(im,
+                        gdRedMax-1, gdGreenMax, gdBlueMax, gdAlphaTransparent);
+        gdImageColorTransparent(im, transparent);
+
+	/* Blending must be off to lay a transparent basecolor.
+                Nothing to blend with anyway. */
+        gdImageAlphaBlending(im, FALSE);
+        gdImageFill (im, im->sx/2, im->sy/2, transparent);
+        /* Blend everything else together,
+                especially fonts over non-transparent backgrounds */
+        gdImageAlphaBlending(im, TRUE);
+
+	gdImageFilledRectangle (im, 30, 30, 70, 70, green);
+	gdImageStringFT (im, NULL, black, "times", 18, 0, 50, 50, "Hello");
+
+	gdImageSaveAlpha (im, TRUE);
+
+	out = fopen ("testtr.png", "wb");
+	gdImagePng (im, out);
+	fclose (out);
+
+	gdImageDestroy (im);
+
+	return 0;
+#else
+	fprintf(stderr, "Compiled without freetype support\n");
+	return 0;
+#endif /* HAVE_LIBFREETYPE */
+}
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.