Index: generic/tkImgPhoto.c
===================================================================
RCS file: /cvsroot/tktoolkit/tk/generic/tkImgPhoto.c,v
retrieving revision 1.36.2.2
diff -u -r1.36.2.2 tkImgPhoto.c
--- generic/tkImgPhoto.c	17 Jul 2003 13:05:53 -0000	1.36.2.2
+++ generic/tkImgPhoto.c	24 Oct 2003 23:34:11 -0000
@@ -178,10 +178,14 @@
  *				components.
  * IMAGE_CHANGED:		1 means that the instances of this image
  *				need to be redithered.
+ * COMPLEX_ALPHA:		1 means that rendering this image is
+ *				non-trivial and requires blending with
+ *				whatever is behind the image.
  */
 
 #define COLOR_IMAGE		1
 #define IMAGE_CHANGED		2
+#define COMPLEX_ALPHA		4
 
 /*
  * The following data structure represents all of the instances of
@@ -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 COMPLEX_ALPHA flag is set. */
+
+    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,234 @@
 #undef MAX
 #define MAX(a, b)	((a) > (b)? (a): (b))
 
+/*GPS*/
+static int
+ToggleComplexAlphaIfNeeded(mPtr)
+    PhotoMaster *mPtr;
+{
+    size_t i, end = MAX(mPtr->userWidth, mPtr->width) *
+	    MAX(mPtr->userHeight, mPtr->height) * 4;
+    unsigned char c;
+
+    mPtr->flags &= ~COMPLEX_ALPHA;
+    for (i = 3; i < end; i += 4) {
+	c = mPtr->pix32[i];
+	if (255 != c && 0 != c) {
+     	    mPtr->flags |= COMPLEX_ALPHA;
+	    break;
+	}
+    }
+    return mPtr->flags & COMPLEX_ALPHA;
+}
+
+/*GPS*/
+static unsigned char *
+CopyTo32BitOverlay(from, overlay, len)
+    unsigned char *from, *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;
+}
+
+/*GPS*/ 
+static int
+BuildOverlayFor32Bits(iPtr)
+    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 */
+    if (s == 0) {
+	return -1;
+    }
+    iPtr->ditheredOverlay = attemptckalloc(s);
+
+    if (NULL == iPtr->ditheredOverlay) {
+        return -1;
+    }
+    CopyTo32BitOverlay(iPtr->masterPtr->pix32, iPtr->ditheredOverlay, s);
+    return 1;
+}
+
+/*GPS*/
+static unsigned char *
+CopyTo15BitOverlay(from, overlay, len)
+    unsigned char *from;
+    unsigned short *overlay;
+    size_t len;
+{
+    size_t i = 0, 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;
+}  
+
+/*GPS*/
+static int
+BuildOverlayFor15Bits(iPtr)
+    PhotoInstance *iPtr;
+{
+    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;
+}
+
+/*GPS*/
+/*-1 not built an error occured*/
+/*0 not-built/not-needed*/
+/*1 built without error*/
+static int
+BuildDitheredOverlayIfNeeded(iPtr)
+    PhotoInstance *iPtr;
+{
+    if (!(iPtr->masterPtr->flags & COMPLEX_ALPHA)
+	    || iPtr->visualInfo.depth < 15) {
+        return 0;
+    }
+    if (NULL != iPtr->ditheredOverlay) {
+	ckfree(iPtr->ditheredOverlay);
+	iPtr->ditheredOverlay = NULL;
+    }
+#ifdef __WIN32__
+    return BuildOverlayFor32Bits(iPtr);
+#else
+    if (iPtr->visualInfo.depth >= 24) {
+	return BuildOverlayFor32Bits(iPtr);
+    } else if (iPtr->visualInfo.depth >= 15) {
+	return BuildOverlayFor15Bits(iPtr); 
+    }
+#endif 
+    return -1;
+}
+
+/*GPS*/
+#define BlendAlpha(out,overlay,alpha) out += (overlay - out) * alpha / 255
+
+static void
+BlendOverlay(depth, xOffset, yOffset, outWidth, outHeight, out,
+	overlayWidth, overlayHeight, overlay, alphaAr)
+    int depth, xOffset, yOffset, outWidth, outHeight;
+    int overlayWidth, overlayHeight;
+    unsigned char *out, *overlay, *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;
+
+	puts("FOO");
+
+	for (outY = 0; outY < outHeight; ++outY) {
+	    for (i = 0; i < outWidth; ++i) {
+		sout[(outY * outWidth) + i] = 32767;
+	    }
+	}
+
+	/*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
+	 */
+
+    } else {
+
+    }
+}
+
+#define GetBackgroundImageFromDrawable(dis,d,x,y,w,h) \
+	XGetImage(dis, d, x, y, (unsigned int )w, (unsigned int)h, AllPlanes, ZPixmap)  
+
+
+/*0 TkPutImage an error occured or something isn't ready*/
+/*1 TkPutImage worked */
+static void
+DisplayComplexAlphaImage(iPtr, d, dx, dy, xOffset, yOffset, width, height)
+    PhotoInstance *iPtr;
+    Drawable d;
+    int dx, dy, xOffset, yOffset, width, height;
+{
+    XImage *bgImg;
+
+    bgImg = GetBackgroundImageFromDrawable(iPtr->display, d, dx, dy,
+	    width, height);
+    if ((NULL == bgImg) || (NULL == iPtr->ditheredOverlay)) {
+        return;
+    }
+    /*Possible bug: Tk's XGetImage in Windows seems to always have a depth of 32*/
+    BlendOverlay(bgImg->depth, xOffset, yOffset, width, height, bgImg->data,
+	    iPtr->overlayWidth, iPtr->overlayHeight, 
+	    iPtr->ditheredOverlay, iPtr->masterPtr->pix32);
+
+    TkPutImage(iPtr->colorTablePtr, iPtr->colorTablePtr->numColors,
+	    iPtr->display, d, iPtr->gc, bgImg, 0, 0, dx, dy, 
+	    (unsigned int) width, (unsigned int) height);	
+}
+
 /*
  *----------------------------------------------------------------------
  *
@@ -2082,6 +2354,9 @@
     if (oldFormat != NULL) {
 	Tcl_DecrRefCount(oldFormat);
     }
+
+    ToggleComplexAlphaIfNeeded(masterPtr);
+
     return TCL_OK;
 
   errorExit:
@@ -2235,6 +2510,7 @@
 	}
     }
 
+    BuildDitheredOverlayIfNeeded(instancePtr);
 }
 
 /*
@@ -2344,6 +2620,7 @@
     instancePtr->height = 0;
     instancePtr->imagePtr = 0;
     instancePtr->nextPtr = masterPtr->instancePtr;
+    instancePtr->ditheredOverlay = NULL;
     masterPtr->instancePtr = instancePtr;
 
     /*
@@ -2428,8 +2705,13 @@
 		masterPtr->width, masterPtr->height);
     }
 
+
+    BuildDitheredOverlayIfNeeded(instancePtr);
+
     return (ClientData) instancePtr;
 }
+
+
 
 /*
  *----------------------------------------------------------------------
@@ -2471,21 +2753,27 @@
 	return;
     }
 
-    /*
-     * 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);
+    if ((instancePtr->masterPtr->flags & COMPLEX_ALPHA)
+	    && 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);
+    }
+    XFlush (display);
 }
 
 /*
@@ -2789,6 +3077,9 @@
 	    masterPtr->ditherY = 0;
 	}
     }
+
+    /*GPS*/
+    ToggleComplexAlphaIfNeeded(masterPtr);
 
     /*
      * Now adjust the sizes of the pixmaps for all of the instances.
