pajoye          Wed Jul 23 11:37:14 2003 EDT

  Modified files:              (Branch: PHP_4_3)
    /php-src/ext/gd/libgd       gd.c 
  Log:
  MFH (#24594)
  
  
Index: php-src/ext/gd/libgd/gd.c
diff -u php-src/ext/gd/libgd/gd.c:1.24.2.19 php-src/ext/gd/libgd/gd.c:1.24.2.20
--- php-src/ext/gd/libgd/gd.c:1.24.2.19 Wed Jul  9 20:11:11 2003
+++ php-src/ext/gd/libgd/gd.c   Wed Jul 23 11:37:14 2003
@@ -868,6 +868,36 @@
        }
 }
 
+
+static int gdImageTileGet (gdImagePtr im, int x, int y)
+{
+       int srcx, srcy;
+       int tileColor,p;
+       if (!im->tile) {
+               return -1;
+       }
+       srcx = x % gdImageSX(im->tile);
+       srcy = y % gdImageSY(im->tile);
+       p = gdImageGetPixel(im->tile, srcx, srcy);
+
+       if (im->trueColor) {
+               if (im->tile->trueColor) {
+                       tileColor = p;
+               } else {
+                       tileColor = gdTrueColorAlpha( gdImageRed(im->tile,p), 
gdImageGreen(im->tile,p), gdImageBlue (im->tile,p), gdImageAlpha (im->tile,p));
+               }
+       } else {
+               if (im->tile->trueColor) {
+                       tileColor = gdImageColorResolveAlpha(im, gdTrueColorGetRed 
(p), gdTrueColorGetGreen (p), gdTrueColorGetBlue (p), gdTrueColorGetAlpha (p));
+               } else {
+                       tileColor = p;
+                       tileColor = gdImageColorResolveAlpha(im, gdImageRed 
(im->tile,p), gdImageGreen (im->tile,p), gdImageBlue (im->tile,p), gdImageAlpha 
(im->tile,p));
+               }
+       }
+       return tileColor;
+}
+
+
 static void gdImageAntiAliasedApply (gdImagePtr im, int px, int py)
 {
        float p_dist, p_alpha;
@@ -1799,106 +1829,172 @@
        }
 }
 
-void gdImageFill (gdImagePtr im, int x, int y, int color)
-{
-       int lastBorder;
-       int old;
-       int leftLimit, rightLimit;
-       int i;
-  
-       if (x >= im->sx) {
-               x = im->sx - 1;
-       }
-  
-       if (y >= im->sy) {
-               y = im->sy - 1;
+
+/*
+ * set the pixel at (x,y) and its 4-connected neighbors
+ * with the same pixel value to the new pixel value nc (new color).
+ * A 4-connected neighbor:  pixel above, below, left, or right of a pixel.
+ * ideas from comp.graphics discussions.
+ * For tiled fill, the use of a flag buffer is mandatory. As the tile image can
+ * contain the same color as the color to fill. To do not bloat normal filling
+ * code I added a 2nd private function.
+ */
+
+/* horizontal segment of scan line y */
+struct seg {int y, xl, xr, dy;};
+
+/* max depth of stack */
+#define FILL_MAX 1200000
+#define FILL_PUSH(Y, XL, XR, DY) \
+    if (sp<stack+FILL_MAX*10 && Y+(DY)>=0 && Y+(DY)<wy2) \
+    {sp->y = Y; sp->xl = XL; sp->xr = XR; sp->dy = DY; sp++;}
+
+#define FILL_POP(Y, XL, XR, DY) \
+    {sp--; Y = sp->y+(DY = sp->dy); XL = sp->xl; XR = sp->xr;}
+
+void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc);
+
+void gdImageFill(gdImagePtr im, int x, int y, int nc)
+{
+       int l, x1, x2, dy;
+       int oc;   /* old pixel value */
+       int wx2,wy2;
+       /* stack of filled segments */
+       //struct seg stack[FILL_MAX],*sp = stack;;
+       struct seg *stack;
+       struct seg *sp;
+
+       if (nc==gdTiled){
+               _gdImageFillTiled(im,x,y,nc);
+               return;
        }
-  
-       old = gdImageGetPixel(im, x, y);
-       if (color == gdTiled) {
-               /* Tile fill -- got to watch out! */
-               int p, tileColor;
-               int srcx, srcy;
-               if (!im->tile) {
-                       return;
-               }
-               /* Refuse to flood-fill with a transparent pattern I can't do it 
without allocating another image */
-               if (gdImageGetTransparent(im->tile) != (-1)) {
-                       return;
-               }
-               srcx = x % gdImageSX(im->tile);
-               srcy = y % gdImageSY(im->tile);
-               p = gdImageGetPixel(im->tile, srcx, srcy);
-               if (im->trueColor) {
-                       tileColor = p;
-               } else {
-                       if (im->tile->trueColor) {
-                               tileColor = gdImageColorResolveAlpha(im, 
gdTrueColorGetRed (p), gdTrueColorGetGreen (p), gdTrueColorGetBlue (p), 
gdTrueColorGetAlpha (p));
-                       } else {
-                               tileColor = im->tileColorMap[p];
-                       }
-               }
-               if (old == tileColor) {
-                       /* Nothing to be done */
-                       return;
+
+       wx2=im->sx;wy2=im->sy;
+       oc = gdImageGetPixel(im, x, y);
+       if (oc==nc || x<0 || x>wx2 || y<0 || y>wy2) return;
+
+       stack = (struct seg *)emalloc(sizeof(struct seg) * ((int)(im->sy*im->sx)/4)+1);
+       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);
                }
-       } else {
-               if (old == color) {
-                       /* Nothing to be done */
-                       return;
+               if (x>=x1) {
+                       goto skip;
                }
-       }
-       /* Seek left */
-       leftLimit = (-1);
-       for (i = x; i >= 0; i--) {
-               if (gdImageGetPixel(im, i, y) != old) {
-                       break;
+               l = x+1;
+
+                /* leak on left? */
+               if (l<x1) {
+                       FILL_PUSH(y, l, x1-1, -dy);
                }
-               gdImageSetPixel(im, i, y, color);
-               leftLimit = i;
+               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);
        }
-       if (leftLimit == (-1)) {
+       efree(stack);
+}
+
+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;
        }
-       /* Seek right */
-       rightLimit = x;
-       for (i = (x + 1); i < im->sx; i++) {
-               if (gdImageGetPixel(im, i, y) != old) {
-                       break;
-               }
-               gdImageSetPixel(im, i, y, color);
-               rightLimit = i;
+
+       wx2=im->sx;wy2=im->sy;
+       tiled = nc==gdTiled;
+
+       nc =  gdImageTileGet(im,x,y);
+       pts = (int **) ecalloc(sizeof(int *) * im->sy, sizeof(int));
+
+       for (i=0; i<im->sy;i++) {
+               pts[i] = (int *) ecalloc(im->sx, sizeof(int));
        }
-       /* 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 && c == old) {
-                               gdImageFill (im, i, y - 1, color);
-                               lastBorder = 0;
-                       } else if (c != old) {
-                               lastBorder = 1;
-                       }
-               }
+
+       stack = (struct seg *)emalloc(sizeof(struct seg) * ((int)(im->sy*im->sx)/4)+1);
+       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);
        }
-       /* Below */
-       if (y < (im->sy - 1)) {
-               lastBorder = 1;
-               for (i = leftLimit; i <= rightLimit; i++) {
-                       int c;
-                       c = gdImageGetPixel(im, i, y + 1);
-                       if (lastBorder && c == old) {
-                               gdImageFill(im, i, y + 1, color);
-                               lastBorder = 0;
-                       } else if (c != old) {
-                               lastBorder = 1;
-                       }
-               }
+       for (i=0; i<im->sy;i++) {
+               efree(pts[i]);
        }
+       efree(pts);
+       efree(stack);
 }
+
+
 
 void gdImageRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
 {



-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to