--- tkImgPhoto.c.orig	Sun Sep 28 02:24:02 2003
+++ tkImgPhoto.c	Mon Oct 27 14:00:40 2003
@@ -170,6 +170,10 @@
     struct PhotoInstance *instancePtr;
 				/* First in the list of instances
 				 * associated with this master. */
+
+    short complexAlpha;         /* A boolean for whether or not we have
+				 * alpha values that aren't 0 or 255. */
+    
 } PhotoMaster;
 
 /*
@@ -213,6 +217,12 @@
 				 * windows are using. */
     GC gc;			/* Graphics context for writing images
 				 * to the pixmap. */
+
+    unsigned char *ditheredOverlay;  /* The pix32 array dithered.  Only
+				  * valid if complexAlpha is true. */
+
+    int overlayWidth, overlayHeight; /*MAX of userWidth,width and userHeight,height */
+   
 } PhotoInstance;
 
 /*
@@ -374,6 +384,40 @@
  * Forward declarations
  */
 
+/*GPS*/
+static int              ToggleComplexAlphaIfNeeded _ANSI_ARGS_((
+                            PhotoMaster *mPtr));
+
+static unsigned char *  CopyTo32BitOverlay _ANSI_ARGS_((
+			    unsigned char *from, unsigned char *overlay, size_t len));
+
+
+static int              BuildOverlayFor32Bits _ANSI_ARGS_((
+			    PhotoInstance *iPtr));
+
+
+static unsigned char *  CopyTo15BitOverlay _ANSI_ARGS_((
+			    unsigned char *from, unsigned short *overlay, size_t len));
+
+
+static int              BuildOverlayFor15Bits _ANSI_ARGS_((
+			    PhotoInstance *iPtr));
+
+static int              BuildDitheredOverlayIfNeeded _ANSI_ARGS_((
+                            PhotoInstance *iPtr));
+
+static void             BlendOverlay _ANSI_ARGS_((
+                	    int depth, int xOffset, int yOffset,
+		            int outW, int outH, unsigned char *out,
+			    int overlayW, int overlayH, unsigned char *overlay,
+			    unsigned char *alphaAr));
+
+static void             DisplayComplexAlphaImage _ANSI_ARGS_((
+			    PhotoInstance *iPtr, Drawable d, int dx, int dy,
+			    int xOffset, int yOffset, int width, int height));
+		     
+/*END GPS*/
+
 static void		PhotoFormatThreadExitProc _ANSI_ARGS_((
 			    ClientData clientData));
 static int		ImgPhotoCmd _ANSI_ARGS_((ClientData clientData,
@@ -430,6 +474,190 @@
 #undef MAX
 #define MAX(a, b)	((a) > (b)? (a): (b))
 
+
+static int ToggleComplexAlphaIfNeeded (PhotoMaster *mPtr) {
+    size_t i, end = MAX(mPtr->userWidth, mPtr->width) *
+      MAX(mPtr->userHeight, mPtr->height) * 4;
+    unsigned char c;
+
+    mPtr->complexAlpha = 0;
+    for (i = 3; i < end; i += 4) {
+	c = mPtr->pix32[i];
+	if (255 != c && 0 != c) {
+     	    mPtr->complexAlpha = 1;
+	    break;
+	}
+    }
+    return mPtr->complexAlpha;
+}
+
+static unsigned char *CopyTo32BitOverlay (unsigned char *from, unsigned char *overlay, size_t len) {
+    size_t i;
+
+    for (i = 0; i < len; i += 4) {
+        overlay[i] = from[i + 2];
+	overlay[i + 1] = from[i + 1];
+	overlay[i + 2] = from[i];
+	overlay[i + 3] = 0;
+    }
+    return overlay;
+}
+
+static int BuildOverlayFor32Bits (PhotoInstance *iPtr) {
+    size_t s;
+  
+    iPtr->overlayWidth = MAX(iPtr->masterPtr->userWidth, iPtr->masterPtr->width);
+    iPtr->overlayHeight = MAX(iPtr->masterPtr->userHeight, iPtr->masterPtr->height);
+    s = iPtr->overlayWidth * iPtr->overlayHeight * 4; /* 4 bytes or 32 bits */
+    iPtr->ditheredOverlay = attemptckalloc (s);
+
+    if (NULL == iPtr->ditheredOverlay) {
+        return -1;
+    }
+    CopyTo32BitOverlay (iPtr->masterPtr->pix32, iPtr->ditheredOverlay, s);
+    return 1;
+}
+
+static unsigned char *CopyTo15BitOverlay (unsigned char *from, unsigned short *overlay, size_t len) {
+    size_t i = 0;
+    size_t overlayI = 0;
+    unsigned char r, g, b;
+
+    while (i < len) {
+    	r = from[i]; g = from[i + 1]; b = from[i + 2];
+	overlay[overlayI] = (r >> 3) | ((g >> 3) << 5) | ((b >> 3) << 10);
+	++overlayI;
+	i += 4;
+    }
+    return (unsigned char *) overlay;
+}  
+
+static int BuildOverlayFor15Bits (PhotoInstance *iPtr) {
+    unsigned char *overlay;
+    size_t s;    
+
+    iPtr->overlayWidth = MAX(iPtr->masterPtr->userWidth, iPtr->masterPtr->width);
+    iPtr->overlayHeight = MAX(iPtr->masterPtr->userHeight, iPtr->masterPtr->height);
+    /* 2 bytes or 16 bits per pixel 
+     */
+    s = iPtr->overlayWidth * iPtr->overlayHeight * 2;
+    iPtr->ditheredOverlay = attemptckalloc (s);
+    if (NULL == iPtr->ditheredOverlay) {
+        return -1;
+    }
+    CopyTo15BitOverlay (iPtr->masterPtr->pix32, (unsigned short *) iPtr->ditheredOverlay, s * 2);
+    return 1;
+}
+
+/*-1 not built an error occured*/
+/*0 not-built/not-needed*/
+/*1 built without error*/
+static int BuildDitheredOverlayIfNeeded (PhotoInstance *iPtr) {
+    if (!iPtr->masterPtr->complexAlpha || iPtr->visualInfo.depth < 15) {
+        return 0;
+    }
+    if (NULL != iPtr->ditheredOverlay) {
+	ckfree(iPtr->ditheredOverlay);
+	iPtr->ditheredOverlay = NULL;
+    }
+#ifdef __WIN32__
+    /*Win32 uses 32 in 16 bit mode too*/
+    return BuildOverlayFor32Bits (iPtr);
+#else
+    if (iPtr->visualInfo.depth >= 24) {
+	return BuildOverlayFor32Bits (iPtr);
+    } else if (iPtr->visualInfo.depth >= 15) {
+	return BuildOverlayFor15Bits (iPtr); 
+    }
+#endif 
+    return -1;
+}
+
+#define BlendAlpha(out,overlay,alpha) out += (overlay - out) * alpha / 255
+
+static void BlendOverlay (
+    int depth, int xOffset, int yOffset,
+    int outWidth, int outHeight, unsigned char *out,
+    int overlayWidth, int overlayHeight, unsigned char *overlay,
+    unsigned char *alphaAr
+) {
+  /*I'm still trying to figure this out.  I'll factor it once I'm done experimenting here.*/
+
+
+  fprintf (stderr, "depth %d xOffset %d yOffset %d outW %d outH %d overlayW %d overlayH %d\n",
+	 depth, xOffset, yOffset, outWidth, outHeight, overlayWidth, overlayHeight);
+
+    if (24 == depth || 32 == depth) {
+        unsigned int overlayI, overlayY;
+        unsigned int outI, outY;
+
+	for (overlayY = yOffset, outY = 0;
+	     overlayY < overlayHeight && outY < outHeight;
+	     ++overlayY, ++outY) {
+	    size_t outOffset = outWidth * outY * 4;
+	    size_t overlayOffset = overlayWidth * overlayY * 4;
+
+	    for (overlayI = xOffset * 4, outI = 0;
+		 overlayI < (overlayWidth * 4) && outI < (outWidth * 4);
+		 overlayI += 4, outI += 4) {
+  	        unsigned char alpha = alphaAr[overlayOffset + overlayI + 3];
+
+		BlendAlpha(out[outOffset + outI], overlay[overlayOffset + overlayI], alpha);
+		BlendAlpha(out[outOffset + outI + 1], overlay[overlayOffset + overlayI + 1], alpha);
+		BlendAlpha(out[outOffset + outI + 2], overlay[overlayOffset + overlayI + 2], alpha);
+		out[outOffset + outI + 3] = 0;
+	    }   
+	}
+    } else if (15 == depth || 16 == depth) {
+        size_t outY;
+	size_t i;
+	unsigned short *sout = (unsigned short *) out;
+
+	for (outY = 0; outY < outHeight; ++outY) {
+	  for (i = 0; i < outWidth; ++i) {
+	    sout[(outY * outWidth) + i] = 65535;
+	  }
+	}
+
+      /*We have a range of 0 to 31 or 0 to 1fh*/
+      /*31 << 10 = 31744
+       *31 << 5 = 992
+       *We can get the leftmost color (B) by doing (P & 31744) >> 10  
+       *We can then get the middle like so: (P & 992) >> 5
+       */
+
+    } 
+}
+
+#define GetBackgroundImageFromDrawable(dis,d,x,y,w,h) \
+  XGetImage (dis, d, x, y, (unsigned int )w, (unsigned int)h, AllPlanes, ZPixmap)  
+
+static void DisplayComplexAlphaImage (
+    PhotoInstance *iPtr,
+    Drawable d, int dx, int dy,
+    int xOffset, int yOffset, int width, int height) {
+
+    XImage *bgImg;
+
+    bgImg = GetBackgroundImageFromDrawable (iPtr->display, d, dx, dy, width, height);
+    if ((NULL == bgImg) || (NULL == iPtr->ditheredOverlay)) {
+        return;
+    }
+    BlendOverlay (bgImg->depth, xOffset, yOffset, width, height, bgImg->data,
+		  iPtr->overlayWidth, iPtr->overlayHeight, 
+		  iPtr->ditheredOverlay, iPtr->masterPtr->pix32);
+    
+    /*
+    memset(bgImg->data, 255, (width * height * 2));
+    */
+    TkPutImage(iPtr->colorTablePtr, iPtr->colorTablePtr->numColors,
+		   iPtr->display, d, iPtr->gc, bgImg, 
+		   0, 0, dx, dy, 
+		   (unsigned int) width, (unsigned int) height);	
+
+    XDestroyImage (bgImg);
+}
+
 /*
  *----------------------------------------------------------------------
  *
@@ -592,6 +820,7 @@
     masterPtr->pix32 = NULL;
     masterPtr->instancePtr = NULL;
     masterPtr->validRegion = TkCreateRegion();
+    masterPtr->complexAlpha = 0;
 
     /*
      * Process configuration options given in the image create command.
@@ -2082,6 +2311,9 @@
     if (oldFormat != NULL) {
 	Tcl_DecrRefCount(oldFormat);
     }
+
+    ToggleComplexAlphaIfNeeded(masterPtr);
+
     return TCL_OK;
 
   errorExit:
@@ -2235,6 +2467,8 @@
 	}
     }
 
+    BuildDitheredOverlayIfNeeded(instancePtr);
+    
 }
 
 /*
@@ -2344,6 +2578,7 @@
     instancePtr->height = 0;
     instancePtr->imagePtr = 0;
     instancePtr->nextPtr = masterPtr->instancePtr;
+    instancePtr->ditheredOverlay = NULL;
     masterPtr->instancePtr = instancePtr;
 
     /*
@@ -2428,8 +2663,13 @@
 		masterPtr->width, masterPtr->height);
     }
 
+
+    BuildDitheredOverlayIfNeeded(instancePtr);
+
     return (ClientData) instancePtr;
 }
+
+
 
 /*
  *----------------------------------------------------------------------
@@ -2471,21 +2711,26 @@
 	return;
     }
 
+    if (instancePtr->masterPtr->complexAlpha && instancePtr->visualInfo.depth >= 15) {
+  	DisplayComplexAlphaImage (instancePtr, drawable, drawableX, drawableY, 
+	                          imageX, imageY, width, height);
+    } else {
     /*
      * masterPtr->region describes which parts of the image contain
      * valid data.  We set this region as the clip mask for the gc,
      * setting its origin appropriately, and use it when drawing the
      * image.
      */
-
-    TkSetRegion(display, instancePtr->gc, instancePtr->masterPtr->validRegion);
-    XSetClipOrigin(display, instancePtr->gc, drawableX - imageX,
-	    drawableY - imageY);
-    XCopyArea(display, instancePtr->pixels, drawable, instancePtr->gc,
-	    imageX, imageY, (unsigned) width, (unsigned) height,
-	    drawableX, drawableY);
-    XSetClipMask(display, instancePtr->gc, None);
-    XSetClipOrigin(display, instancePtr->gc, 0, 0);
+	TkSetRegion(display, instancePtr->gc, instancePtr->masterPtr->validRegion);
+	XSetClipOrigin(display, instancePtr->gc, drawableX - imageX,
+	               drawableY - imageY);
+	XCopyArea(display, instancePtr->pixels, drawable, instancePtr->gc,
+	          imageX, imageY, (unsigned) width, (unsigned) height,
+	          drawableX, drawableY);
+	XSetClipMask(display, instancePtr->gc, None);
+	XSetClipOrigin(display, instancePtr->gc, 0, 0);
+    }
+    XFlush (display);
 }
 
 /*
@@ -2789,6 +3034,9 @@
 	    masterPtr->ditherY = 0;
 	}
     }
+
+    /*GPS*/
+    ToggleComplexAlphaIfNeeded (masterPtr);
 
     /*
      * Now adjust the sizes of the pixmaps for all of the instances.
