Commit message: - #18, Removed invalid gdFree call when overflow2 fails
- #17, Free im->pixels as well on error
CVE: CVE-2016-5767
CWE: CWE-190
Vulnerability description: Integer overflow in the gdImageCreate function in gd.c in the GD Graphics Library (aka libgd) before 2.0.34RC1, as used in PHP before 5.5.37, 5.6.x before 5.6.23, and 7.x before 7.0.8, allows remote attackers to cause a denial of service (heap-based buffer overflow and application crash) or possibly have unspecified other impact via a crafted image dimensions.

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e,
		  int color, int style)
{
  gdPoint pts[3];
  int i;
  int lx = 0, ly = 0;
  int fx = 0, fy = 0;
  while (e < s)
    {
      e += 360;
    }
  for (i = s; (i <= e); i++)
    {
      int x, y;
      x = ((long) gdCosT[i % 360] * (long) w / (2 * 1024)) + cx;
      y = ((long) gdSinT[i % 360] * (long) h / (2 * 1024)) + cy;
      if (i != s)
	{
	  if (!(style & gdChord))
	    {
	      if (style & gdNoFill)
		{
		  gdImageLine (im, lx, ly, x, y, color);
		}
	      else
		{
		  /* This is expensive! */
		  pts[0].x = lx;
		  pts[0].y = ly;
		  pts[1].x = x;
		  pts[1].y = y;
		  pts[2].x = cx;
		  pts[2].y = cy;
		  gdImageFilledPolygon (im, pts, 3, color);
		}
	    }
	}
      else
	{
	  fx = x;
	  fy = y;
	}
      lx = x;
      ly = y;
    }
  if (style & gdChord)
    {
      if (style & gdNoFill)
	{
	  if (style & gdEdged)
	    {
	      gdImageLine (im, cx, cy, lx, ly, color);
	      gdImageLine (im, cx, cy, fx, fy, color);
	    }
	  gdImageLine (im, fx, fy, lx, ly, color);
	}
      else
	{
	  pts[0].x = fx;
	  pts[0].y = fy;
	  pts[1].x = lx;
	  pts[1].y = ly;
	  pts[2].x = cx;
	  pts[2].y = cy;
	  gdImageFilledPolygon (im, pts, 3, color);
	}
    }
  else
    {
      if (style & gdNoFill)
	{
	  if (style & gdEdged)
	    {
	      gdImageLine (im, cx, cy, lx, ly, color);
	      gdImageLine (im, cx, cy, fx, fy, color);
	    }
	}
    }
}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, int dstY,
		    int srcX, int srcY, int dstW, int dstH, int srcW,
		    int srcH)
{
  int c;
  int x, y;
  int tox, toy;
  int ydest;
  int i;
  int colorMap[gdMaxColors];
  /* Stretch vectors */
  int *stx;
  int *sty;
  /* We only need to use floating point to determine the correct
     stretch vector for one line's worth. */
  if (overflow2(sizeof (int), srcW)) {
    return;
  }
  if (overflow2(sizeof (int), srcH)) {
    return;
  }
  stx = (int *) gdMalloc (sizeof (int) * srcW);
  sty = (int *) gdMalloc (sizeof (int) * srcH);
  /* Fixed by Mao Morimoto 2.0.16 */
  for (i = 0; (i < srcW); i++)
    {
      stx[i] = dstW * (i + 1) / srcW - dstW * i / srcW;
    }
  for (i = 0; (i < srcH); i++)
    {
      sty[i] = dstH * (i + 1) / srcH - dstH * i / srcH;
    }
  for (i = 0; (i < gdMaxColors); i++)
    {
      colorMap[i] = (-1);
    }
  toy = dstY;
  for (y = srcY; (y < (srcY + srcH)); y++)
    {
      for (ydest = 0; (ydest < sty[y - srcY]); ydest++)
	{
	  tox = dstX;
	  for (x = srcX; (x < (srcX + srcW)); x++)
	    {
	      int nc = 0;
	      int mapTo;
	      if (!stx[x - srcX])
		{
		  continue;
		}
	      if (dst->trueColor)
		{
		  /* 2.0.9: Thorben Kundinger: Maybe the source image is not 
		     a truecolor image */
		  if (!src->trueColor)
		    {
		      int tmp = gdImageGetPixel (src, x, y);
		      mapTo = gdImageGetTrueColorPixel (src, x, y);
		      if (gdImageGetTransparent (src) == tmp)
			{
			  /* 2.0.21, TK: not tox++ */
			  tox += stx[x - srcX];
			  continue;
			}
		    }
		  else
		    {
		      /* TK: old code follows */
		      mapTo = gdImageGetTrueColorPixel (src, x, y);
		      /* Added 7/24/95: support transparent copies */
		      if (gdImageGetTransparent (src) == mapTo)
			{
			  /* 2.0.21, TK: not tox++ */
			  tox += stx[x - srcX];
			  continue;
			}
		    }
		}
	      else
		{
		  c = gdImageGetPixel (src, x, y);
		  /* Added 7/24/95: support transparent copies */
		  if (gdImageGetTransparent (src) == c)
		    {
		      tox += stx[x - srcX];
		      continue;
		    }
		  if (src->trueColor)
		    {
		      /* Remap to the palette available in the
		         destination image. This is slow and
		         works badly. */
		      mapTo = gdImageColorResolveAlpha (dst,
							gdTrueColorGetRed (c),
							gdTrueColorGetGreen
							(c),
							gdTrueColorGetBlue
							(c),
							gdTrueColorGetAlpha
							(c));
		    }
		  else
		    {
		      /* Have we established a mapping for this color? */
		      if (colorMap[c] == (-1))
			{
			  /* If it's the same image, mapping is trivial */
			  if (dst == src)
			    {
			      nc = c;
			    }
			  else
			    {
			      /* Find or create the best match */
			      /* 2.0.5: can't use gdTrueColorGetRed, etc with palette */
			      nc = gdImageColorResolveAlpha (dst,
							     gdImageRed (src,
									 c),
							     gdImageGreen
							     (src, c),
							     gdImageBlue (src,
									  c),
							     gdImageAlpha
							     (src, c));
			    }
			  colorMap[c] = nc;
			}
		      mapTo = colorMap[c];
		    }
		}
	      for (i = 0; (i < stx[x - srcX]); i++)
		{
		  gdImageSetPixel (dst, tox, toy, mapTo);
		  tox++;
		}
	    }
	  toy++;
	}
    }
  gdFree (stx);
  gdFree (sty);
}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImageCopyRotated (gdImagePtr dst,
		    gdImagePtr src,
		    double dstX, double dstY,
		    int srcX, int srcY,
		    int srcWidth, int srcHeight, int angle)
{
  double dx, dy;
  double radius = sqrt (srcWidth * srcWidth + srcHeight * srcHeight);
  double aCos = cos (angle * .0174532925);
  double aSin = sin (angle * .0174532925);
  double scX = srcX + ((double) srcWidth) / 2;
  double scY = srcY + ((double) srcHeight) / 2;
  int cmap[gdMaxColors];
  int i;
  for (i = 0; (i < gdMaxColors); i++)
    {
      cmap[i] = (-1);
    }
  for (dy = dstY - radius; (dy <= dstY + radius); dy++)
    {
      for (dx = dstX - radius; (dx <= dstX + radius); dx++)
	{
	  double sxd = (dx - dstX) * aCos - (dy - dstY) * aSin;
	  double syd = (dy - dstY) * aCos + (dx - dstX) * aSin;
	  int sx = sxd + scX;
	  int sy = syd + scY;
	  if ((sx >= srcX) && (sx < srcX + srcWidth) &&
	      (sy >= srcY) && (sy < srcY + srcHeight))
	    {
	      int c = gdImageGetPixel (src, sx, sy);
	      if (!src->trueColor)
		{
		  /* Use a table to avoid an expensive
		     lookup on every single pixel */
		  if (cmap[c] == -1)
		    {
		      cmap[c] = gdImageColorResolveAlpha (dst,
							  gdImageRed (src, c),
							  gdImageGreen (src,
									c),
							  gdImageBlue (src,
								       c),
							  gdImageAlpha (src,
									c));
		    }
		  gdImageSetPixel (dst, dx, dy, cmap[c]);
		}
	      else
		{
		  gdImageSetPixel (dst,
				   dx, dy,
				   gdImageColorResolveAlpha (dst,
							     gdImageRed (src,
									 c),
							     gdImageGreen
							     (src, c),
							     gdImageBlue (src,
									  c),
							     gdImageAlpha
							     (src, c)));
		}
	    }
	}
    }
}

Project: libgd
File: gd.c

BGD_DECLARE(gdImagePtr) gdImageCreateFromXbm (FILE * fd)
{
  gdImagePtr im;
  int bit;
  int w, h;
  int bytes;
  int ch;
  int i, x, y;
  char *sp;
  char s[161];
  if (!fgets (s, 160, fd))
    {
      return 0;
    }
  sp = &s[0];
  /* Skip #define */
  sp = strchr (sp, ' ');
  if (!sp)
    {
      return 0;
    }
  /* Skip width label */
  sp++;
  sp = strchr (sp, ' ');
  if (!sp)
    {
      return 0;
    }
  /* Get width */
  w = atoi (sp + 1);
  if (!w)
    {
      return 0;
    }
  if (!fgets (s, 160, fd))
    {
      return 0;
    }
  sp = s;
  /* Skip #define */
  sp = strchr (sp, ' ');
  if (!sp)
    {
      return 0;
    }
  /* Skip height label */
  sp++;
  sp = strchr (sp, ' ');
  if (!sp)
    {
      return 0;
    }
  /* Get height */
  h = atoi (sp + 1);
  if (!h)
    {
      return 0;
    }
  /* Skip declaration line */
  if (!fgets (s, 160, fd))
    {
      return 0;
    }
  bytes = (w * h / 8) + 1;
  im = gdImageCreate (w, h);
  gdImageColorAllocate (im, 255, 255, 255);
  gdImageColorAllocate (im, 0, 0, 0);
  x = 0;
  y = 0;
  for (i = 0; (i < bytes); i++)
    {
      char h[3];
      unsigned int b;
      /* Skip spaces, commas, CRs, 0x */
      while (1)
	{
	  ch = getc (fd);
	  if (ch == EOF)
	    {
	      goto fail;
	    }
	  if (ch == 'x')
	    {
	      break;
	    }
	}
      /* Get hex value */
      ch = getc (fd);
      if (ch == EOF)
	{
	  goto fail;
	}
      h[0] = ch;
      ch = getc (fd);
      if (ch == EOF)
	{
	  goto fail;
	}
      h[1] = ch;
      h[2] = '\0';
      sscanf (h, "%x", &b);
      for (bit = 1; (bit <= 128); (bit = bit << 1))
	{
	  gdImageSetPixel (im, x++, y, (b & bit) ? 1 : 0);
	  if (x == im->sx)
	    {
	      x = 0;
	      y++;
	      if (y == im->sy)
		{
		  return im;
		}
	      /* Fix 8/8/95 */
	      break;
	    }
	}
    }
  /* Shouldn't happen */
  fprintf (stderr, "Error: bug in gdImageCreateFromXbm!\n");
  return 0;
fail:
  gdImageDestroy (im);
  return 0;
}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2,
			int color)
{
  int x, y;
  /* Nick Atty: limit the points at the edge.  Note that this also
     nicely kills any plotting for rectangles completely outside the
     window as it makes the tests in the for loops fail */
  if (x1 < 0)
    x1 = 0;
  if (x1 > gdImageSX (im))
    x1 = gdImageSX (im);
  if (y1 < 0)
    y1 = 0;
  if (y1 > gdImageSY (im))
    y1 = gdImageSY (im);

  for (y = y1; (y <= y2); y++)
    {
      for (x = x1; (x <= x2); x++)
	{
	  gdImageSetPixel (im, x, y, color);
	}
    }
}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImageCopyMergeGray (gdImagePtr dst, gdImagePtr src, int dstX, int dstY,
		      int srcX, int srcY, int w, int h, int pct)
{

  int c, dc;
  int x, y;
  int tox, toy;
  int ncR, ncG, ncB;
  float g;
  toy = dstY;
  for (y = srcY; (y < (srcY + h)); y++)
    {
      tox = dstX;
      for (x = srcX; (x < (srcX + w)); x++)
	{
	  int nc;
	  c = gdImageGetPixel (src, x, y);
	  /* Added 7/24/95: support transparent copies */
	  if (gdImageGetTransparent (src) == c)
	    {
	      tox++;
	      continue;
	    }
	  /* 
	   * If it's the same image, mapping is NOT trivial since we 
	   * merge with greyscale target, but if pct is 100, the grey 
	   * value is not used, so it becomes trivial. pjw 2.0.12. 
	   */
	  if (dst == src && pct == 100)
	    {
	      nc = c;
	    }
	  else
	    {
	      dc = gdImageGetPixel (dst, tox, toy);
	      g = 0.29900 * dst->red[dc]
		+ 0.58700 * dst->green[dc] + 0.11400 * dst->blue[dc];

	      ncR = gdImageRed (src, c) * (pct / 100.0)
		+ g * ((100 - pct) / 100.0);
	      ncG = gdImageGreen (src, c) * (pct / 100.0)
		+ g * ((100 - pct) / 100.0);
	      ncB = gdImageBlue (src, c) * (pct / 100.0)
		+ g * ((100 - pct) / 100.0);

	      /* First look for an exact match */
	      nc = gdImageColorExact (dst, ncR, ncG, ncB);
	      if (nc == (-1))
		{
		  /* No, so try to allocate it */
		  nc = gdImageColorAllocate (dst, ncR, ncG, ncB);
		  /* If we're out of colors, go for the
		     closest color */
		  if (nc == (-1))
		    {
		      nc = gdImageColorClosest (dst, ncR, ncG, ncB);
		    }
		}
	    }
	  gdImageSetPixel (dst, tox, toy, nc);
	  tox++;
	}
      toy++;
    }
}

Project: libgd
File: gd.c

HWB_Diff (int r1, int g1, int b1, int r2, int g2, int b2)
{
  RGBType RGB1, RGB2;
  HWBType HWB1, HWB2;
  float diff;

  SETUP_RGB (RGB1, r1, g1, b1);
  SETUP_RGB (RGB2, r2, g2, b2);

  RGB_to_HWB (RGB1, &HWB1);
  RGB_to_HWB (RGB2, &HWB2);

  /*
   * I made this bit up; it seems to produce OK results, and it is certainly
   * more visually correct than the current RGB metric. (PJW)
   */

  if ((HWB1.H == HWB_UNDEFINED) || (HWB2.H == HWB_UNDEFINED))
    {
      diff = 0;			/* Undefined hues always match... */
    }
  else
    {
      diff = abs (HWB1.H - HWB2.H);
      if (diff > 3)
	{
	  diff = 6 - diff;	/* Remember, it's a colour circle */
	}
    }

  diff =
    diff * diff + (HWB1.W - HWB2.W) * (HWB1.W - HWB2.W) + (HWB1.B -
							   HWB2.B) * (HWB1.B -
								      HWB2.B);

  return diff;
}

Project: libgd
File: gd.c

BGD_DECLARE(gdImagePtr) gdImageCreateTrueColor (int sx, int sy)
{
  int i;
  gdImagePtr im;
  im = (gdImage *) gdMalloc (sizeof (gdImage));
  memset (im, 0, sizeof (gdImage));
  im->tpixels = (int **) gdMalloc (sizeof (int *) * sy);
  im->polyInts = 0;
  im->polyAllocated = 0;
  im->brush = 0;
  im->tile = 0;
  im->style = 0;
  for (i = 0; (i < sy); i++)
    {
      im->tpixels[i] = (int *) gdCalloc (sx, sizeof (int));
    }
  im->sx = sx;
  im->sy = sy;
  im->transparent = (-1);
  im->interlace = 0;
  im->trueColor = 1;
  /* 2.0.2: alpha blending is now on by default, and saving of alpha is
     off by default. This allows font antialiasing to work as expected
     on the first try in JPEGs -- quite important -- and also allows 
     for smaller PNGs when saving of alpha channel is not really 
     desired, which it usually isn't! */
  im->saveAlphaFlag = 0;
  im->alphaBlendingFlag = 1;
  im->thick = 1;
  im->AA = 0;
  im->cx1 = 0;
  im->cy1 = 0;
  im->cx2 = im->sx - 1;
  im->cy2 = im->sy - 1;
  return im;
}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImageSetStyle (gdImagePtr im, int *style, int noOfPixels)
{
  if (im->style)
    {
      gdFree (im->style);
    }
  if (overflow2(sizeof (int), noOfPixels)) {
    return;
  }   	
  im->style = (int *) gdMalloc (sizeof (int) * noOfPixels);
  memcpy (im->style, style, sizeof (int) * noOfPixels);
  im->styleLength = noOfPixels;
  im->stylePos = 0;
}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImageColorDeallocate (gdImagePtr im, int color)
{
  if (im->trueColor)
    {
      return;
    }
  /* Mark it open. */
  im->open[color] = 1;
}

Project: libgd
File: gd.c

static void horizontalLine(gdImagePtr im, int minx, int maxx, int y,
	int fill_color)
{
  /* 2.0.27: potential corruption fixed by John Ellson */
  if (minx < im->cx1) minx = im->cx1;
  if (maxx < minx) maxx = minx;
  if (maxx > im->cx2) maxx = im->cx2;
  if (minx > maxx) minx = maxx;
                                                                                                                                        
  if (y < im->cy1) y = im->cy1;
  if (y > im->cy2) y = im->cy2;
                                                                                                                                        
  if (im->trueColor) {
    while (minx <= maxx) {
      im->tpixels[y][minx++] = fill_color;
    }
  } else {
    while (minx <= maxx) {
      im->pixels[y][minx++] = fill_color;
    }
  }
}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImagePaletteCopy (gdImagePtr to, gdImagePtr from)
{
  int i;
  int x, y, p;
  int xlate[256];
  if (to->trueColor)
    {
      return;
    }
  if (from->trueColor)
    {
      return;
    }

  for (i = 0; i < 256; i++)
    {
      xlate[i] = -1;
    };

  for (x = 0; x < (to->sx); x++)
    {
      for (y = 0; y < (to->sy); y++)
	{
          /* Optimization: no gdImageGetPixel */
	  p = to->pixels[y][x];
	  if (xlate[p] == -1)
	    {
	      /* This ought to use HWB, but we don't have an alpha-aware
	         version of that yet. */
	      xlate[p] =
		gdImageColorClosestAlpha (from, to->red[p], to->green[p],
					  to->blue[p], to->alpha[p]);
	      /*printf("Mapping %d (%d, %d, %d, %d) to %d (%d, %d, %d, %d)\n", */
	      /*      p,  to->red[p], to->green[p], to->blue[p], to->alpha[p], */
	      /*      xlate[p], from->red[xlate[p]], from->green[xlate[p]], from->blue[xlate[p]], from->alpha[xlate[p]]); */
	    };
          /* Optimization: no gdImageSetPixel */
	  to->pixels[y][x] = xlate[p];
	};
    };

  for (i = 0; (i < (from->colorsTotal)); i++)
    {
      /*printf("Copying color %d (%d, %d, %d, %d)\n", i, from->red[i], from->blue[i], from->green[i], from->alpha[i]); */
      to->red[i] = from->red[i];
      to->blue[i] = from->blue[i];
      to->green[i] = from->green[i];
      to->alpha[i] = from->alpha[i];
      to->open[i] = 0;
    };

  for (i = from->colorsTotal; (i < to->colorsTotal); i++)
    {
      to->open[i] = 1;
    };

  to->colorsTotal = from->colorsTotal;

}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImageCopyResampled (gdImagePtr dst,
		      gdImagePtr src,
		      int dstX, int dstY,
		      int srcX, int srcY,
		      int dstW, int dstH, int srcW, int srcH)
{
  int x, y;
  double sy1, sy2, sx1, sx2;
  if (!dst->trueColor)
    {
      gdImageCopyResized (dst, src, dstX, dstY, srcX, srcY, dstW, dstH,
			  srcW, srcH);
      return;
    }
  for (y = dstY; (y < dstY + dstH); y++)
    {
      sy1 = ((double) y - (double) dstY) * (double) srcH / (double) dstH;
      sy2 = ((double) (y + 1) - (double) dstY) * (double) srcH /
	(double) dstH;
      for (x = dstX; (x < dstX + dstW); x++)
	{
	  double sx, sy;
	  double spixels = 0;
	  double red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
	  sx1 = ((double) x - (double) dstX) * (double) srcW / dstW;
	  sx2 = ((double) (x + 1) - (double) dstX) * (double) srcW / dstW;
	  sy = sy1;
	  do
	    {
	      double yportion;
	      if (floor2 (sy) == floor2 (sy1))
		{
		  yportion = 1.0 - (sy - floor2 (sy));
		  if (yportion > sy2 - sy1)
		    {
		      yportion = sy2 - sy1;
		    }
		  sy = floor2 (sy);
		}
	      else if (sy == floor2 (sy2))
		{
		  yportion = sy2 - floor2 (sy2);
		}
	      else
		{
		  yportion = 1.0;
		}
	      sx = sx1;
	      do
		{
		  double xportion;
		  double pcontribution;
		  int p;
		  if (floor2 (sx) == floor2 (sx1))
		    {
		      xportion = 1.0 - (sx - floor2 (sx));
		      if (xportion > sx2 - sx1)
			{
			  xportion = sx2 - sx1;
			}
		      sx = floor2 (sx);
		    }
		  else if (sx == floor2 (sx2))
		    {
		      xportion = sx2 - floor2 (sx2);
		    }
		  else
		    {
		      xportion = 1.0;
		    }
		  pcontribution = xportion * yportion;
		  /* 2.08: previously srcX and srcY were ignored. 
		     Andrew Pattison */
		  p = gdImageGetTrueColorPixel (src,
						(int) sx + srcX,
						(int) sy + srcY);
		  red += gdTrueColorGetRed (p) * pcontribution;
		  green += gdTrueColorGetGreen (p) * pcontribution;
		  blue += gdTrueColorGetBlue (p) * pcontribution;
		  alpha += gdTrueColorGetAlpha (p) * pcontribution;
		  spixels += xportion * yportion;
		  sx += 1.0;
		}
	      while (sx < sx2);
	      sy += 1.0;
	    }
	  while (sy < sy2);
	  if (spixels != 0.0)
	    {
	      red /= spixels;
	      green /= spixels;
	      blue /= spixels;
	      alpha /= spixels;
	    }
	  /* Clamping to allow for rounding errors above */
	  if (red > 255.0)
	    {
	      red = 255.0;
	    }
	  if (green > 255.0)
	    {
	      green = 255.0;
	    }
	  if (blue > 255.0)
	    {
	      blue = 255.0;
	    }
	  if (alpha > gdAlphaMax)
	    {
	      alpha = gdAlphaMax;
	    }
	  gdImageSetPixel (dst,
			   x, y,
			   gdTrueColorAlpha ((int) red,
					     (int) green,
					     (int) blue, (int) alpha));
	}
    }
}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImageAABlend (gdImagePtr im)
{
  /* NO-OP, kept for library compatibility. */
}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImageRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
{
	int x1h = x1, x1v = x1, y1h = y1, y1v = y1, x2h = x2, x2v = x2, y2h = y2, y2v = y2;
	int thick = im->thick;
	int half1 = 1;
	int t;

	if (y2 < y1) {
		t=y1;
		y1 = y2;
		y2 = t;

		t = x1;
		x1 = x2;
		x2 = t;
	}

	x1h = x1; x1v = x1; y1h = y1; y1v = y1; x2h = x2; x2v = x2; y2h = y2; y2v = y2;
	if (thick > 1) {
		int cx, cy, x1ul, y1ul, x2lr, y2lr;
		int half = thick >> 1;
		half1 = thick - half;
		x1ul = x1 - half;
		y1ul = y1 - half;
		
		x2lr = x2 + half;
		y2lr = y2 + half;

		cy = y1ul + thick;
		while (cy-- > y1ul) {
			cx = x1ul - 1;
			while (cx++ < x2lr) {
				gdImageSetPixel(im, cx, cy, color);
			}
		}

		cy = y2lr - thick;
		while (cy++ < y2lr) {
			cx = x1ul - 1;
			while (cx++ < x2lr) {
				gdImageSetPixel(im, cx, cy, color);
			}
		}

		cy = y1ul + thick - 1;
		while (cy++ < y2lr -thick) {
			cx = x1ul - 1;
			while (cx++ < x1ul + thick) {
				gdImageSetPixel(im, cx, cy, color);
			}
		}

		cy = y1ul + thick - 1;
		while (cy++ < y2lr -thick) {
			cx = x2lr - thick - 1;
			while (cx++ < x2lr) {
				gdImageSetPixel(im, cx, cy, color);
			}
		}

		return;
	} else {
		y1v = y1h + 1;
		y2v = y2h - 1;
		gdImageLine(im, x1h, y1h, x2h, y1h, color);
		gdImageLine(im, x1h, y2h, x2h, y2h, color);
		gdImageLine(im, x1v, y1v, x1v, y2v, color);
		gdImageLine(im, x2v, y1v, x2v, y2v, color);
	}
}

Project: libgd
File: gd.c

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;
  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. 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, im->cx1, im->cx2) == 0)
    return;
  if (clip_1d (&y1, &x1, &y2, &x2, im->cy1, im->cy2) == 0)
    return;
  thick = im->thick;

  dx = abs (x2 - x1);
  dy = abs (y2 - y1);
  if (dy <= dx)
    {
      /* More-or-less horizontal. use wid for vertical stroke */
      /* Doug Claar: watch out for NaN in atan2 (2.0.5) */
      if ((dx == 0) && (dy == 0))
	{
	  wid = 1;
	}
      else
	{
	  /* 2.0.12: Michael Schwartz: divide rather than multiply;
	     TBB: but watch out for /0! */
	  double ac = cos (atan2 (dy, dx));
	  if (ac != 0)
	    {
	      wid = thick / ac;
	    }
	  else
	    {
	      wid = 1;
	    }
	  if (wid == 0)
	    {
	      wid = 1;
	    }
	}
      d = 2 * dy - dx;
      incr1 = 2 * dy;
      incr2 = 2 * (dy - dx);
      if (x1 > x2)
	{
	  x = x2;
	  y = y2;
	  ydirflag = (-1);
	  xend = x1;
	}
      else
	{
	  x = x1;
	  y = y1;
	  ydirflag = 1;
	  xend = x2;
	}

      /* Set up line thickness */
      wstart = y - wid / 2;
      for (w = wstart; w < wstart + wid; w++)
	gdImageSetPixel (im, x, w, color);

      if (((y2 - y1) * ydirflag) > 0)
	{
	  while (x < xend)
	    {
	      x++;
	      if (d < 0)
		{
		  d += incr1;
		}
	      else
		{
		  y++;
		  d += incr2;
		}
	      wstart = y - wid / 2;
	      for (w = wstart; w < wstart + wid; w++)
		gdImageSetPixel (im, x, w, color);
	    }
	}
      else
	{
	  while (x < xend)
	    {
	      x++;
	      if (d < 0)
		{
		  d += incr1;
		}
	      else
		{
		  y--;
		  d += incr2;
		}
	      wstart = y - wid / 2;
	      for (w = wstart; w < wstart + wid; w++)
		gdImageSetPixel (im, x, w, color);
	    }
	}
    }
  else
    {
      /* More-or-less vertical. use wid for horizontal stroke */
      /* 2.0.12: Michael Schwartz: divide rather than multiply;
         TBB: but watch out for /0! */
      double as = sin (atan2 (dy, dx));
      if (as != 0)
	{
	  wid = thick / as;
	}
      else
	{
	  wid = 1;
	}
      if (wid == 0)
	wid = 1;

      d = 2 * dx - dy;
      incr1 = 2 * dx;
      incr2 = 2 * (dx - dy);
      if (y1 > y2)
	{
	  y = y2;
	  x = x2;
	  yend = y1;
	  xdirflag = (-1);
	}
      else
	{
	  y = y1;
	  x = x1;
	  yend = y2;
	  xdirflag = 1;
	}

      /* Set up line thickness */
      wstart = x - wid / 2;
      for (w = wstart; w < wstart + wid; w++)
	gdImageSetPixel (im, w, y, color);

      if (((x2 - x1) * xdirflag) > 0)
	{
	  while (y < yend)
	    {
	      y++;
	      if (d < 0)
		{
		  d += incr1;
		}
	      else
		{
		  x++;
		  d += incr2;
		}
	      wstart = x - wid / 2;
	      for (w = wstart; w < wstart + wid; w++)
		gdImageSetPixel (im, w, y, color);
	    }
	}
      else
	{
	  while (y < yend)
	    {
	      y++;
	      if (d < 0)
		{
		  d += incr1;
		}
	      else
		{
		  x--;
		  d += incr2;
		}
	      wstart = x - wid / 2;
	      for (w = wstart; w < wstart + wid; w++)
		gdImageSetPixel (im, w, y, color);
	    }
	}
    }

}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImageCopy (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX,
	     int srcY, int w, int h)
{
  int c;
  int x, y;
  int tox, toy;
  int i;
  int colorMap[gdMaxColors];

  if (dst->trueColor) {
	  /* 2.0: much easier when the destination is truecolor. */
	  /* 2.0.10: needs a transparent-index check that is still valid if
	   *          * the source is not truecolor. Thanks to Frank Warmerdam.
	   *                   */

	  if (src->trueColor) {
		  for (y = 0; (y < h); y++) {
			  for (x = 0; (x < w); x++) {
				  int c = gdImageGetTrueColorPixel (src, srcX + x, srcY + y);
				  gdImageSetPixel (dst, dstX + x, dstY + y, c);
			  }
		  }
	  } else {
		  /* source is palette based */
		  for (y = 0; (y < h); y++) {
			  for (x = 0; (x < w); x++) {
				  int c = gdImageGetPixel (src, srcX + x, srcY + y);
				  if (c != src->transparent) {
					  gdImageSetPixel(dst, dstX + x, dstY + y, gdTrueColorAlpha(src->red[c], src->green[c], src->blue[c], src->alpha[c]));
				  }
			  }
		  }
	  }
	  return;
  }

  for (i = 0; (i < gdMaxColors); i++)
  {
	  colorMap[i] = (-1);
  }
  toy = dstY;
  for (y = srcY; (y < (srcY + h)); y++)
  {
	  tox = dstX;
	  for (x = srcX; (x < (srcX + w)); x++)
	  {
		  int nc;
		  int mapTo;
		  c = gdImageGetPixel (src, x, y);
		  /* Added 7/24/95: support transparent copies */
		  if (gdImageGetTransparent (src) == c)
		  {
			  tox++;
			  continue;
		  }
		  /* Have we established a mapping for this color? */
		  if (src->trueColor)
		  {
			  /* 2.05: remap to the palette available in the
				 destination image. This is slow and
				 works badly, but it beats crashing! Thanks 
				 to Padhrig McCarthy. */
	      mapTo = gdImageColorResolveAlpha (dst,
						gdTrueColorGetRed (c),
						gdTrueColorGetGreen (c),
						gdTrueColorGetBlue (c),
						gdTrueColorGetAlpha (c));
	    }
	  else if (colorMap[c] == (-1))
	    {
	      /* If it's the same image, mapping is trivial */
	      if (dst == src)
		{
		  nc = c;
		}
	      else
		{
		  /* Get best match possible. This
		     function never returns error. */
		  nc = gdImageColorResolveAlpha (dst,
						 src->red[c], src->green[c],
						 src->blue[c], src->alpha[c]);
		}
	      colorMap[c] = nc;
	      mapTo = colorMap[c];
	    }
	  else
	    {
	      mapTo = colorMap[c];
	    }
	  gdImageSetPixel (dst, tox, toy, mapTo);
	  tox++;
	}
      toy++;
    }
}

Project: libgd
File: gd.c

void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc)
{
	int i,l, x1, x2, dy;
	int oc;   /* old pixel value */
	int tiled;
	int wx2,wy2;
	/* stack of filled segments */
	struct seg *stack;
	struct seg *sp;

	int **pts;
	if(!im->tile){
		return;
	}

	wx2=im->sx;wy2=im->sy;
	tiled = nc==gdTiled;

	nc =  gdImageTileGet(im,x,y);
	pts = (int **) gdCalloc(sizeof(int *) * im->sy, sizeof(int));

	for (i=0; i<im->sy;i++) {
		pts[i] = (int *) gdCalloc(im->sx, sizeof(int));
	}

	stack = (struct seg *)gdMalloc(sizeof(struct seg) * ((int)(im->sy*im->sx)/4));
	sp = stack;

	oc = gdImageGetPixel(im, x, y);

	/* required! */
	FILL_PUSH(y,x,x,1);
	/* seed segment (popped 1st) */
 	FILL_PUSH(y+1, x, x, -1);
	while (sp>stack) {
		FILL_POP(y, x1, x2, dy);
		for (x=x1; x>=0 && (!pts[y][x] && gdImageGetPixel(im,x,y)==oc); x--) {
			if (pts[y][x]){
				/* we should never be here */
				break;
			}
			nc = gdImageTileGet(im,x,y);
			pts[y][x]=1;
			gdImageSetPixel(im,x, y, nc);
		}
		if (x>=x1) {
			goto skip;
		}
		l = x+1;

		/* leak on left? */
		if (l<x1) {
			FILL_PUSH(y, l, x1-1, -dy);
		}
		x = x1+1;
		do {
			for (; x<=wx2 && (!pts[y][x] && gdImageGetPixel(im,x, y)==oc) ; x++) {
				if (pts[y][x]){
					/* we should never be here */
					break;
				}
				nc = gdImageTileGet(im,x,y);
				pts[y][x]=1;
				gdImageSetPixel(im, x, y, nc);
			}
			FILL_PUSH(y, l, x-1, dy);
			/* leak on right? */
			if (x>x2+1) {
				FILL_PUSH(y, x2+1, x-1, -dy);
			}
skip:			for (x++; x<=x2 && (pts[y][x] || gdImageGetPixel(im,x, y)!=oc); x++);
			l = x;
		} while (x<=x2);
	}
	for (i=0; i<im->sy;i++) {
		gdFree(pts[i]);
	}
	gdFree(pts);
	gdFree(stack);
}

Project: libgd
File: gd.c

gdImageTileApply (gdImagePtr im, int x, int y)
{
  int srcx, srcy;
  int p;
  if (!im->tile)
    {
      return;
    }
  srcx = x % gdImageSX (im->tile);
  srcy = y % gdImageSY (im->tile);
  if (im->trueColor)
    {
      p = gdImageGetTrueColorPixel (im->tile, srcx, srcy);
      gdImageSetPixel (im, x, y, p);
    }
  else
    {
      p = gdImageGetPixel (im->tile, srcx, srcy);
      /* Allow for transparency */
      if (p != gdImageGetTransparent (im->tile))
	{
	  if (im->tile->trueColor)
	    {
	      /* Truecolor tile. Very slow
	         on a palette destination. */
	      gdImageSetPixel (im, x, y,
			       gdImageColorResolveAlpha (im,
							 gdTrueColorGetRed
							 (p),
							 gdTrueColorGetGreen
							 (p),
							 gdTrueColorGetBlue
							 (p),
							 gdTrueColorGetAlpha
							 (p)));
	    }
	  else
	    {
	      gdImageSetPixel (im, x, y, im->tileColorMap[p]);
	    }
	}
    }
}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImagePolygon (gdImagePtr im, gdPointPtr p, int n, int c)
{
  if (!n)
    {
      return;
    }


  gdImageLine (im, p->x, p->y, p[n - 1].x, p[n - 1].y, c);
  gdImageOpenPolygon (im, p, n, c);
}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImageOpenPolygon (gdImagePtr im, gdPointPtr p, int n, int c)
{
  int i;
  int lx, ly;
  if (!n)
    {
      return;
    }


  lx = p->x;
  ly = p->y;
  for (i = 1; (i < n); i++)
    {
      p++;
      gdImageLine (im, lx, ly, p->x, p->y, c);
      lx = p->x;
      ly = p->y;
    }

}

Project: libgd
File: gd.c

BGD_DECLARE(gdImagePtr) gdImageCreate (int sx, int sy)
{
  int i;
  gdImagePtr im;

  if (overflow2(sizeof (unsigned char *), sy)) {
		return NULL;
  }
  if (overflow2(sizeof (unsigned char *), sx)) {
		return NULL;
  }

  im = (gdImage *) gdMalloc (sizeof (gdImage));
	if (!im) {
		return NULL;
	}

  memset (im, 0, sizeof (gdImage));
  /* Row-major ever since gd 1.3 */
  im->pixels = (unsigned char **) gdMalloc (sizeof (unsigned char *) * sy);
	if (!im->pixels) {
		gdFree(im);
		return NULL;
	}

  im->polyInts = 0;
  im->polyAllocated = 0;
  im->brush = 0;
  im->tile = 0;
  im->style = 0;
  for (i = 0; (i < sy); i++)
    {
      /* Row-major ever since gd 1.3 */
      im->pixels[i] = (unsigned char *) gdCalloc (sx, sizeof (unsigned char));
			if (!im->pixels[i]) 
			{
				for (--i ; i >= 0; i--)
				{
					gdFree(im->pixels[i]);
				}
				gdFree(im->pixels);
				gdFree(im);
				return NULL;
			}

    }
  im->sx = sx;
  im->sy = sy;
  im->colorsTotal = 0;
  im->transparent = (-1);
  im->interlace = 0;
  im->thick = 1;
  im->AA = 0;
  for (i = 0; (i < gdMaxColors); i++)
    {
      im->open[i] = 1;
      im->red[i] = 0;
      im->green[i] = 0;
      im->blue[i] = 0;
    };
  im->trueColor = 0;
  im->tpixels = 0;
  im->cx1 = 0;
  im->cy1 = 0;
  im->cx2 = im->sx - 1;
  im->cy2 = im->sy - 1;
  return im;
}

Project: libgd
File: gd.c

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);
		}
	}
}

Project: libgd
File: gd.c

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;
  int x2, y2;
  int ind1, ind2;
  int ints;
  int fill_color;
  if (!n)
    {
      return;
    }


  if (!im->polyAllocated)
    {
      if (overflow2(sizeof (int), n)) {
        return;
      }
      im->polyInts = (int *) gdMalloc (sizeof (int) * n);
      im->polyAllocated = n;
    }
  if (im->polyAllocated < n)
    {
      while (im->polyAllocated < n)
	{
	  im->polyAllocated *= 2;
	}
      if (overflow2(sizeof (int), im->polyAllocated)) {
        return;
      }
      im->polyInts = (int *) gdRealloc (im->polyInts,
					sizeof (int) * im->polyAllocated);
    }
  miny = p[0].y;
  maxy = p[0].y;
  for (i = 1; (i < n); i++)
    {
      if (p[i].y < miny)
	{
	  miny = p[i].y;
	}
      if (p[i].y > maxy)
	{
	  maxy = p[i].y;
	}
    }
  /* 2.0.16: Optimization by Ilia Chipitsine -- don't waste time offscreen */
  /* 2.0.26: clipping rectangle is even better */
  if (miny < im->cy1)
    {
      miny = im->cy1;
    }
  if (maxy > im->cy2)
    {
      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; */
/* 2.0.26+      int yshift = 0; */
      if (c == gdAntiAliased) {
        fill_color = im->AA_color;
      } else {
        fill_color = c;
      }
      ints = 0;
      for (i = 0; (i < n); i++)
	{
	  if (!i)
	    {
	      ind1 = n - 1;
	      ind2 = 0;
	    }
	  else
	    {
	      ind1 = i - 1;
	      ind2 = i;
	    }
	  y1 = p[ind1].y;
	  y2 = p[ind2].y;
	  if (y1 < y2)
	    {
	      x1 = p[ind1].x;
	      x2 = p[ind2].x;
	    }
	  else if (y1 > y2)
	    {
	      y2 = p[ind1].y;
	      y1 = p[ind2].y;
	      x2 = p[ind1].x;
	      x1 = p[ind2].x;
	    }
	  else
	    {
	      continue;
	    }

	  /* Do the following math as float intermediately, and round to ensure
	   * that Polygon and FilledPolygon for the same set of points have the
	   * same footprint. */
 
	  if ((y >= y1) && (y < y2))
	    {
	      im->polyInts[ints++] = (int) ((float) ((y - y1) * (x2 - x1)) /
		(float) (y2 - y1) + 0.5 + x1);
	    }
	  else if ((y == maxy) && (y > y1) && (y <= y2))
	    {
	      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)
	{
#if 0
          int minx = im->polyInts[i];
          int maxx = im->polyInts[i + 1];
#endif
          /* 2.0.29: back to gdImageLine to prevent segfaults when
            performing a pattern fill */
          gdImageLine (im, im->polyInts[i], y, im->polyInts[i + 1], y,
            fill_color);
	}
    }
  /* If we are drawing this AA, then redraw the border with AA lines. */
  /* This doesn't work as well as I'd like, but it doesn't clash either. */
  if (c == gdAntiAliased) {
    gdImagePolygon (im, p, n, c);
  } 
}

Project: libgd
File: gd.c

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);
}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImageFilledEllipse (gdImagePtr im, int mx, int my, int w, int h, int c)
{
	int x=0,mx1=0,mx2=0,my1=0,my2=0;
	long aq,bq,dx,dy,r,rx,ry,a,b;
	int i;
	int old_y1,old_y2;

	a=w>>1;
	b=h>>1;

	gdImageLine(im, mx-a, my, mx+a, my, c);

	mx1 = mx-a;my1 = my;
	mx2 = mx+a;my2 = my;

	aq = a * a;
	bq = b * b;
	dx = aq << 1;
	dy = bq << 1;
	r  = a * bq;
	rx = r << 1;
	ry = 0;
	x = a;
	old_y2=-2;
	old_y1=-2;
	while (x > 0){
		if (r > 0) {
			my1++;my2--;
			ry +=dx;
			r  -=ry;
		}
		if (r <= 0){
			x--;
			mx1++;mx2--;
			rx -=dy;
			r  +=rx;
		}
		if(old_y2!=my2){
			for(i=mx1;i<=mx2;i++){
				gdImageSetPixel(im,i,my1,c);
			}
		}
		if(old_y2!=my2){
			for(i=mx1;i<=mx2;i++){
				gdImageSetPixel(im,i,my2,c);
			}
		}
		old_y2 = my2;
		old_y1 = my1;
	}
}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImageSetPixel (gdImagePtr im, int x, int y, int color)
{
  int p;
  switch (color)
    {
    case gdStyled:
      if (!im->style)
	{
	  /* Refuse to draw if no style is set. */
	  return;
	}
      else
	{
	  p = im->style[im->stylePos++];
	}
      if (p != (gdTransparent))
	{
	  gdImageSetPixel (im, x, y, p);
	}
      im->stylePos = im->stylePos % im->styleLength;
      break;
    case gdStyledBrushed:
      if (!im->style)
	{
	  /* Refuse to draw if no style is set. */
	  return;
	}
      p = im->style[im->stylePos++];
      if ((p != gdTransparent) && (p != 0))
	{
	  gdImageSetPixel (im, x, y, gdBrushed);
	}
      im->stylePos = im->stylePos % im->styleLength;
      break;
    case gdBrushed:
      gdImageBrushApply (im, x, y);
      break;
    case gdTiled:
      gdImageTileApply (im, x, y);
      break;
    case gdAntiAliased:
      /* 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))
	{
	  if (im->trueColor)
	    {
	      if (im->alphaBlendingFlag)
		{
		  im->tpixels[y][x] = gdAlphaBlend (im->tpixels[y][x], color);
		}
	      else
		{
		  im->tpixels[y][x] = color;
		}
	    }
	  else
	    {
	      im->pixels[y][x] = color;
	    }
	}
      break;
    }
}

Project: libgd
File: gd.c

clip_1d (int *x0, int *y0, int *x1, int *y1, int mindim, int maxdim)
{
  double m;			/* gradient of line */
  if (*x0 < mindim)
    {				/* start of line is left of 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 - mindim);
      *x0 = mindim;
      /* now, perhaps, adjust the far end of the line as well */
      if (*x1 > maxdim)
	{
	  *y1 += m * (maxdim - *x1);
	  *x1 = maxdim;
	}
      return 1;
    }
  if (*x0 > maxdim)
    {				/* start of line is right of window -
				   complement of above */
      if (*x1 > maxdim)		/* as is the end, so the line misses the window */
	return 0;
      m = (*y1 - *y0) / (double) (*x1 - *x0);	/* calculate the slope of the line */
      *y0 += m * (maxdim - *x0);	/* adjust so point is on the right
					   boundary */
      *x0 = maxdim;
      /* now, perhaps, adjust the end of the line */
      if (*x1 < mindim)
	{
	  *y1 -= m * (*x1 - mindim);
	  *x1 = mindim;
	}
      return 1;
    }
  /* the final case - the start of the line is inside the window */
  if (*x1 > maxdim)
    {				/* other end is outside to the right */
      m = (*y1 - *y0) / (double) (*x1 - *x0);	/* calculate the slope of the line */
      *y1 += m * (maxdim - *x1);
      *x1 = maxdim;
      return 1;
    }
  if (*x1 < mindim)
    {				/* other end is outside to the left */
      m = (*y1 - *y0) / (double) (*x1 - *x0);	/* calculate the slope of the line */
      *y1 -= m * (*x1 - mindim);
      *x1 = mindim;
      return 1;
    }
  /* only get here if both points are inside the window */
  return 1;
}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImageColorTransparent (gdImagePtr im, int color)
{
  if (!im->trueColor)
    {
      if (im->transparent != -1)
	{
	  im->alpha[im->transparent] = gdAlphaOpaque;
	}
      if (color != -1)
	{
	  im->alpha[color] = gdAlphaTransparent;
	}
    }
  im->transparent = color;
}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImageFillToBorder (gdImagePtr im, int x, int y, int border, int color)
{
  int lastBorder;
  /* Seek left */
  int leftLimit, rightLimit;
  int i;
  leftLimit = (-1);
  if (border < 0)
    {
      /* Refuse to fill to a non-solid border */
      return;
    }
  for (i = x; (i >= 0); i--)
    {
      if (gdImageGetPixel (im, i, y) == border)
	{
	  break;
	}
      gdImageSetPixel (im, i, y, color);
      leftLimit = i;
    }
  if (leftLimit == (-1))
    {
      return;
    }
  /* Seek right */
  rightLimit = x;
  for (i = (x + 1); (i < im->sx); i++)
    {
      if (gdImageGetPixel (im, i, y) == border)
	{
	  break;
	}
      gdImageSetPixel (im, i, y, color);
      rightLimit = i;
    }
  /* Look at lines above and below and start paints */
  /* Above */
  if (y > 0)
    {
      lastBorder = 1;
      for (i = leftLimit; (i <= rightLimit); i++)
	{
	  int c;
	  c = gdImageGetPixel (im, i, y - 1);
	  if (lastBorder)
	    {
	      if ((c != border) && (c != color))
		{
		  gdImageFillToBorder (im, i, y - 1, border, color);
		  lastBorder = 0;
		}
	    }
	  else if ((c == border) || (c == color))
	    {
	      lastBorder = 1;
	    }
	}
    }
  /* Below */
  if (y < ((im->sy) - 1))
    {
      lastBorder = 1;
      for (i = leftLimit; (i <= rightLimit); i++)
	{
	  int c;
	  c = gdImageGetPixel (im, i, y + 1);
	  if (lastBorder)
	    {
	      if ((c != border) && (c != color))
		{
		  gdImageFillToBorder (im, i, y + 1, border, color);
		  lastBorder = 0;
		}
	    }
	  else if ((c == border) || (c == color))
	    {
	      lastBorder = 1;
	    }
	}
    }
}

Project: libgd
File: gd.c

BGD_DECLARE(void) gdImageFill(gdImagePtr im, int x, int y, int nc)
{
	int l, x1, x2, dy;
	int oc;   /* old pixel value */
	int wx2,wy2;

	int alphablending_bak;

	/* stack of filled segments */
	/* struct seg stack[FILL_MAX],*sp = stack;; */
	struct seg *stack;
	struct seg *sp;

	if (!im->trueColor && nc > im->colorsTotal) {
		return;
	}

	alphablending_bak = im->alphaBlendingFlag;	
	im->alphaBlendingFlag = 0;
	if (nc==gdTiled) {
		_gdImageFillTiled(im,x,y,nc);
		im->alphaBlendingFlag = alphablending_bak;
		return;
	}

	wx2=im->sx;wy2=im->sy;
	oc = gdImageGetPixel(im, x, y);
	if (oc==nc || x<0 || x>wx2 || y<0 || y>wy2) {
		im->alphaBlendingFlag = alphablending_bak;	
		return;
	}

	stack = (struct seg *)gdMalloc(sizeof(struct seg) * ((int)(im->sy*im->sx)/4));
	sp = stack;

	/* required! */
	FILL_PUSH(y,x,x,1);
	/* seed segment (popped 1st) */
 	FILL_PUSH(y+1, x, x, -1);
	while (sp>stack) {
		FILL_POP(y, x1, x2, dy);

		for (x=x1; x>=0 && gdImageGetPixel(im,x, y)==oc; x--) {
			gdImageSetPixel(im,x, y, nc);
		}
		if (x>=x1) {
			goto skip;
		}
		l = x+1;

                /* leak on left? */
		if (l<x1) {
			FILL_PUSH(y, l, x1-1, -dy);
		}
		x = x1+1;
		do {
			for (; x<=wx2 && gdImageGetPixel(im,x, y)==oc; x++) {
				gdImageSetPixel(im, x, y, nc);
			}
			FILL_PUSH(y, l, x-1, dy);
			/* leak on right? */
			if (x>x2+1) {
				FILL_PUSH(y, x2+1, x-1, -dy);
			}
skip:			for (x++; x<=x2 && (gdImageGetPixel(im, x, y)!=oc); x++);

			l = x;
		} while (x<=x2);
	}
	gdFree(stack);
	im->alphaBlendingFlag = alphablending_bak;	
}