Commits

Anonymous committed 9fc2ebf

- sync to 2.0.10

Comments (0)

Files changed (6)

 #include "gd.h"
 #include "gdhelpers.h"
 
+#define gdImageBoundsSafeMacro(im, x, y) (!((((y) < 0) || ((y) >= (im)->sy)) || (((x) < 0) || ((x) >= (im)->sx))))
+
 #ifdef _OSD_POSIX		/* BS2000 uses the EBCDIC char set instead of ASCII */
 #define CHARSET_EBCDIC
 #define __attribute__(any)	/*nothing */
 
 }
 
+/* 2.0.10: before the drawing routines, some code to clip points that are
+ * outside the drawing window.  Nick Atty (nick@canalplan.org.uk)
+ *
+ * This is the Sutherland Hodgman Algorithm, as implemented by
+ * Duvanenko, Robbins and Gyurcsik - SH(DRG) for short.  See Dr Dobb's
+ * Journal, January 1996, pp107-110 and 116-117
+ *
+ * Given the end points of a line, and a bounding rectangle (which we
+ * know to be from (0,0) to (SX,SY)), adjust the endpoints to be on
+ * the edges of the rectangle if the line should be drawn at all,
+ * otherwise return a failure code */
+
+/* this does "one-dimensional" clipping: note that the second time it
+   is called, all the x parameters refer to height and the y to width
+   - the comments ignore this (if you can understand it when it's
+   looking at the X parameters, it should become clear what happens on
+   the second call!)  The code is simplified from that in the article,
+   as we know that gd images always start at (0,0) */
+
+static int clip_1d(int *x0, int *y0, int *x1, int *y1, int maxdim) {
+  double m;      /* gradient of line */
+  if(*x0 < 0) {  /* start of line is left of window */
+    if(*x1 < 0)  /* as is the end, so the line never cuts the window */
+      return 0;
+    m = (*y1 - *y0)/(double)(*x1 - *x0);  /* calculate the slope of the line */
+    /* adjust x0 to be on the left boundary (ie to be zero), and y0 to match */
+    *y0 -= m * *x0;
+    *x0 = 0;
+    /* now, perhaps, adjust the far end of the line as well */
+    if(*x1 > maxdim) {
+      *y1 += m * (maxdim - *x1);
+      *x1 = maxdim;
+    }
+    return 1;
+  }
+  if(*x0 > maxdim) {   /* start of line is right of window -
+                          complement of above */
+    if(*x1 > maxdim)   /* as is the end, so the line misses the window */
+      return 0;
+    m = (*y1 - *y0)/(double)(*x1 - *x0);  /* calculate the slope of the line */
+    *y0 += m * (maxdim - *x0);    /* adjust so point is on the right
+                                     boundary */
+    *x0 = maxdim;                  
+    /* now, perhaps, adjust the end of the line */
+    if(*x1 < 0) {
+      *y1 -= m * *x1;
+      *x1 = 0;
+    }
+    return 1;
+  }
+  /* the final case - the start of the line is inside the window */
+  if(*x1 > maxdim) {  /* other end is outside to the right */
+    m = (*y1 - *y0)/(double)(*x1 - *x0);  /* calculate the slope of the line */
+    *y1 += m * (maxdim - *x1);
+    *x1 = maxdim;
+    return 1;
+  }
+  if(*x1 < 0) {      /* other end is outside to the left */
+    m = (*y1 - *y0)/(double)(*x1 - *x0);  /* calculate the slope of the line */
+    *y1 -= m * *x1;
+    *x1 = 0;
+    return 1;
+  }
+  /* only get here if both points are inside the window */
+  return 1;
+}
+
+/* end of line clipping code */
+
 void
 gdImageSetPixel (gdImagePtr im, int x, int y, int color)
 {
       gdImageTileApply (im, x, y);
       break;
     default:
-      if (gdImageBoundsSafe (im, x, y))
+      if (gdImageBoundsSafeMacro (im, x, y))
 	{
 	  if (im->trueColor)
 	    {
 int
 gdImageGetPixel (gdImagePtr im, int x, int y)
 {
-  if (gdImageBoundsSafe (im, x, y))
+  if (gdImageBoundsSafeMacro (im, x, y))
     {
       if (im->trueColor)
 	{
   int wid;
   int w, wstart;
   int thick = im->thick;
+
+  /* 2.0.10: Nick Atty: clip to edges of drawing rectangle, return if no
+     points need to be drawn */
+
+  if(clip_1d(&x1,&y1,&x2,&y2,gdImageSX(im)) == 0)
+    return;
+  if(clip_1d(&y1,&x1,&y2,&x2,gdImageSY(im)) == 0)
+    return;
+
   dx = abs (x2 - x1);
   dy = abs (y2 - y1);
   if (dy <= dx)
 int
 gdImageBoundsSafe (gdImagePtr im, int x, int y)
 {
-  return (!(((y < 0) || (y >= im->sy)) || ((x < 0) || (x >= im->sx))));
+  return gdImageBoundsSafeMacro(im, x, y);
 }
 
 void
 			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++)
   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. */
       for (y = 0; (y < h); y++)
 	{
 	  for (x = 0; (x < w); x++)
 	    {
-	      int c = gdImageGetTrueColorPixel (src, srcX + x,
+              int p = gdImageGetPixel(src, srcX + x, srcY + y);
+              if (p != src->transparent) {
+	        int c = gdImageGetTrueColorPixel (src, srcX + x,
 						srcY + y);
-	      if (c != src->transparent)
-		{
-		  gdImageSetPixel (dst, dstX + x, dstY + y, c);
-		}
+		gdImageSetPixel (dst, dstX + x, dstY + y, c);
+              }
 	    }
 	}
       return;
    arithmetic. The routine below is shamelessly, gloriously
    floating point. TBB */
 
+/* 2.0.10: cast instead of floor() yields 35% performance improvement. 
+	Thanks to John Buckman. */
+
+#define floor2(exp) ((long) exp)
+/*#define floor2(exp) floor(exp)*/
+
 void
 gdImageCopyResampled (gdImagePtr dst,
 		      gdImagePtr src,
 	  do
 	    {
 	      float yportion;
-	      if (floor (sy) == floor (sy1))
+	      if (floor2 (sy) == floor2 (sy1))
 		{
-		  yportion = 1.0 - (sy - floor (sy));
+		  yportion = 1.0 - (sy - floor2 (sy));
 		  if (yportion > sy2 - sy1)
 		    {
 		      yportion = sy2 - sy1;
 		    }
-		  sy = floor (sy);
+		  sy = floor2 (sy);
 		}
-	      else if (sy == floor (sy2))
+	      else if (sy == floor2 (sy2))
 		{
-		  yportion = sy2 - floor (sy2);
+		  yportion = sy2 - floor2 (sy2);
 		}
 	      else
 		{
 		  float xportion;
 		  float pcontribution;
 		  int p;
-		  if (floor (sx) == floor (sx1))
+		  if (floor2 (sx) == floor2 (sx1))
 		    {
-		      xportion = 1.0 - (sx - floor (sx));
+		      xportion = 1.0 - (sx - floor2 (sx));
 		      if (xportion > sx2 - sx1)
 			{
 			  xportion = sx2 - sx1;
 			}
-		      sx = floor (sx);
+		      sx = floor2 (sx);
 		    }
-		  else if (sx == floor (sx2))
+		  else if (sx == floor2 (sx2))
 		    {
-		      xportion = sx2 - floor (sx2);
+		      xportion = sx2 - floor2 (sx2);
 		    }
 		  else
 		    {
 				       int h);
   gdImagePtr gdImageCreateFromGd2PartCtx (gdIOCtxPtr in, int srcx, int srcy,
 					  int w, int h);
-
-  gdImagePtr gdImageCreateFromXbm (FILE * fd);
+  /* 2.0.10: prototype was missing */
+  gdImagePtr gdImageCreateFromXpm (char *filename);
+  gdImagePtr gdImageCreateFromXbm (FILE * in);
 
   void gdImageDestroy (gdImagePtr im);
 
  * Modification 4/18/00 TBB: JPEG_DEBUG rather than just DEBUG,
  * so VC++ builds don't spew to standard output, causing
  * major CGI brain damage
+ *
+ * 2.0.10: more efficient gdImageCreateFromJpegCtx, thanks to
+ * Christian Aberger 
  */
 
 #ifdef HAVE_CONFIG_H
     }
   rowptr[0] = row;
 
-  for (i = 0; i < cinfo.output_height; i++)
+  for (i = 0; i < cinfo.output_height; i++) 
     {
+      register JSAMPROW currow = row;
+      register int *tpix = im->tpixels[i];
       nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
       if (nrows != 1)
 	{
 		   " returns %u, expected 1\n", nrows);
 	  goto error;
 	}
-
-      for (j = 0; j < cinfo.output_width; j++)
-	im->tpixels[i][j] = gdTrueColor (row[j * 3], row[j * 3 + 1],
-					 row[j * 3 + 2]);
+      for (j = 0; j < cinfo.output_width; j++, currow += 3, tpix++) 
+         {
+           *tpix = gdTrueColor (currow[0], currow[1], currow[2]);
+         }
     }
 
   if (jpeg_finish_decompress (&cinfo) != TRUE)
   gdIOCtx *infile;		/* source stream */
   unsigned char *buffer;	/* start of buffer */
   safeboolean start_of_file;	/* have we gotten any data yet? */
- 
+ 
+}
 my_source_mgr;
 
 typedef my_source_mgr *my_src_ptr;
  * Data beyond this point must be rescanned after resumption, so move it to
  * the front of the buffer rather than discarding it.
  */
-
-#define END_JPEG_SEQUENCE "\r\n[*]--:END JPEG:--[*]\r\n"
+
+#define END_JPEG_SEQUENCE "\r\n[*]--:END JPEG:--[*]\r\n"
   safeboolean
 fill_input_buffer (j_decompress_ptr cinfo)
 {
   my_src_ptr src = (my_src_ptr) cinfo->src;
   size_t nbytes = 0;
-  
+  
     /* size_t got; */
     /* char *s; */
     memset (src->buffer, 0, INPUT_BUF_SIZE);
-  
+  
+while (nbytes < INPUT_BUF_SIZE)
     {
-      
+      
+int got = gdGetBuf (src->buffer + nbytes, 
+INPUT_BUF_SIZE - nbytes,
 			   src->infile);
-      
+      
+if ((got == EOF) || (got == 0))
 	{
-	  
-	    /* EOF or error. If we got any data, don't worry about it.
-	       If we didn't, then this is unexpected. */ 
+	  
+	    /* EOF or error. If we got any data, don't worry about it.
+	       If we didn't, then this is unexpected. */ 
 	    if (!nbytes)
 	    {
-	      
-	    
-	  
-	
-      
-    
-  
+	      
+nbytes = -1;
+	    
+}
+	  
+break;
+	
+}
+      
+nbytes += got;
+    
+}
+  
+if (nbytes <= 0)
     {
       if (src->start_of_file)	/* Treat empty input file as fatal error */
 	ERREXIT (cinfo, JERR_INPUT_EMPTY);
 void
 term_source (j_decompress_ptr cinfo)
 {
-  
+  
 #if 0
 /* never used */
     my_src_ptr src = (my_src_ptr) cinfo->src;
-  
+  
 #endif
 }
 
       src->buffer = (unsigned char *)
 	(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
 				    INPUT_BUF_SIZE * sizeof (unsigned char));
-    
+    
+}
 
   src = (my_src_ptr) cinfo->src;
   src->pub.init_source = init_source;
       im_in = gdImageCreateFromPng (in);
       fclose (in);
       /* Now copy, and magnify as we do so */
-      gdImageCopyResized (im_out, im_in, 32, 32, 0, 0, 192, 192, 255, 255);
+      gdImageCopyResampled (im_out, im_in, 32, 32, 0, 0, 192, 192, 255, 255);
       /* Now display variously rotated space shuttles in a circle of our own */
       for (a = 0; (a < 360); a += 45)
 	{
 #include "gd.h"
 #include "gdhelpers.h"
 
-#ifndef MSWIN32
+/* 2.0.10: WIN32, not MSWIN32 */
+#ifndef WIN32
 #include <unistd.h>
 #else
 #include <io.h>
   /* create an image just big enough for the string (x3) */
   sx = MAXX (brect) - MINX (brect) + 6;
   sy = MAXY (brect) - MINY (brect) + 6;
-#if 1
+#if 0
   /* Would be palette color 8-bit (which of course is still allowed,
      but not impressive when used with a JPEG background and antialiasing
      and alpha channel and so on!) */
 	  fprintf (stderr, "Can't create test/fttest.png\n");
 	  exit (1);
 	}
-#ifdef HAVE_LIBJPEG
+	/* 2.0.10: correct ifdef, thanks to Gabriele Verzeletti */
+#ifdef HAVE_LIBPNG
       gdImagePng (im, out);
 #else
       fprintf (stderr, "No PNG library support.\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.