WinWorkstation.st
changeset 5316 f0dc2e0f0ccf
parent 5269 228502f3be02
child 5317 90d5d8df3101
--- a/WinWorkstation.st	Mon Aug 03 19:18:14 2009 +0200
+++ b/WinWorkstation.st	Mon Aug 03 19:19:53 2009 +0200
@@ -10406,12 +10406,47 @@
 !
 
 drawBits:imageBits bitsPerPixel:bitsPerPixel depth:imageDepth padding:padd
-			  width:imageWidth height:imageHeight
-			      x:srcx y:srcy
-			   into:ignoredDrawableId
-			      x:dstx y:dsty
-			  width:w height:h
-			   with:aGCId
+                          width:imageWidth height:imageHeight
+                              x:srcx y:srcy
+                           into:ignoredDrawableId
+                              x:dstx y:dsty
+                          width:w height:h
+                    sourceAlpha:sourceAlphaOrNil
+                           with:aGCId
+
+    "draw a bitImage which has depth id, width iw and height ih into
+     the drawable. draw a region of w/h pixels from srcx/srcy to dstx/dsty.
+     Individual source pixels have bitsPerPixel bits, allowing to draw
+     depth and pixel-units to be different.
+     It has to be checked elsewhere, that the server can do it with the given
+     depth - otherwise, primitive failure will be signalled.
+     Also it is assumed, that the colormap is setup correctly and the
+     colors are allocated - otherwise the colors may be wrong."
+
+    (self primDrawBits:imageBits bitsPerPixel:bitsPerPixel depth:imageDepth padding:padd
+                                        width:imageWidth height:imageHeight
+                                             x:srcx y:srcy
+                                          into:ignoredDrawableId
+                                             x:dstx y:dsty
+                                         width:w height:h
+                                   sourceAlpha:sourceAlphaOrNil
+                                          with:aGCId)
+    ifFalse:[
+        "
+         also happens, if a segmentation violation occurs in the
+         XPutImage ...
+        "
+        self primitiveFailed
+    ].
+!
+
+drawBits:imageBits bitsPerPixel:bitsPerPixel depth:imageDepth padding:padd
+                          width:imageWidth height:imageHeight
+                              x:srcx y:srcy
+                           into:ignoredDrawableId
+                              x:dstx y:dsty
+                          width:w height:h
+                           with:aGCId
 
     "draw a bitImage which has depth id, width iw and height ih into
      the drawable. draw a region of w/h pixels from srcx/srcy to dstx/dsty.
@@ -10427,18 +10462,19 @@
      an unlimited stack, and thus cannot send primitiveFailed
     "
     (self primDrawBits:imageBits bitsPerPixel:bitsPerPixel depth:imageDepth padding:padd
-					width:imageWidth height:imageHeight
-					     x:srcx y:srcy
-					  into:ignoredDrawableId
-					     x:dstx y:dsty
-					 width:w height:h
-					  with:aGCId)
+                                        width:imageWidth height:imageHeight
+                                             x:srcx y:srcy
+                                          into:ignoredDrawableId
+                                             x:dstx y:dsty
+                                         width:w height:h
+                                   sourceAlpha:nil
+                                          with:aGCId)
     ifFalse:[
-	"
-	 also happens, if a segmentation violation occurs in the
-	 XPutImage ...
-	"
-	self primitiveFailed
+        "
+         also happens, if a segmentation violation occurs in the
+         XPutImage ...
+        "
+        self primitiveFailed
     ].
 !
 
@@ -10650,6 +10686,209 @@
 %}
 !
 
+primDrawBits:imageBits
+	bitsPerPixel:bitsPerPixel depth:imageDepth padding:padd
+	width:imageWidth height:imageHeight
+	x:srcx y:srcy
+	into:ignoredDrawableId
+	x:dstx y:dsty
+	width:w height:h
+	sourceAlpha:sourceAlphaOrNil
+	with:aGCId
+
+%{
+    unsigned char fastBits[10000];
+    unsigned char *b_bits = 0;
+    unsigned char *allocatedBits = 0;
+    struct gcData *gcData = 0;
+    HDC hDC = (HDC)0;
+    unsigned char *__imageBits = 0;
+    int _sourceAlpha = 0;
+
+    if (__isByteArray(imageBits)) {
+	__imageBits = __ByteArrayInstPtr(imageBits)->ba_element;
+    } else if (__isExternalBytesLike(imageBits)) {
+	__imageBits = (unsigned char *)(__externalBytesAddress(imageBits));
+    }
+
+    if (ISCONNECTED
+     && __isExternalAddress(aGCId)
+     && __bothSmallInteger(srcx, srcy)
+     && __bothSmallInteger(dstx, dsty)
+     && __bothSmallInteger(w, h)
+     && __bothSmallInteger(imageWidth, imageHeight)
+     && __bothSmallInteger(imageDepth, bitsPerPixel)
+     && __isSmallInteger(padd)
+     && __imageBits)
+     {
+	struct
+	{
+	  BITMAPINFOHEADER bmiHeader;
+	  DWORD r;
+	  DWORD g;
+	  DWORD b;
+	} bitmap;
+
+	gcData = _GCDATA(aGCId);
+	if (! gcData )
+	    goto fail;
+	hDC = _getDC(gcData);
+	DDPRINTF(("hDC = %x\n", hDC));
+
+	if (__intVal(padd) != WIN32PADDING) {
+	    int row, col;
+	    unsigned char *cp;
+	    unsigned char *pBits;
+	    int b_width, b_height, bytesPerRowST, bytesPerRowWN, padding, nBytes;
+	    int bi = __intVal(bitsPerPixel);
+
+	    b_width = __intVal(w);
+	    b_height = __intVal(h);
+	    bytesPerRowST = (b_width * bi + (__intVal(padd)-1)) / __intVal(padd);
+	    bytesPerRowWN = (b_width * bi + (WIN32PADDING-1)) / WIN32PADDING * (WIN32PADDING/8);
+	    padding = bytesPerRowWN - bytesPerRowST;
+	    nBytes = b_height * bytesPerRowWN;
+	    /*console_printf("padd %d bs %d bw %d p %d\n",__intVal(padd),bytesPerRowST,bytesPerRowWN,padding);*/
+	    if (padding) {
+		if (nBytes < sizeof(fastBits)) {
+		    cp = b_bits = fastBits;
+		} else {
+		    cp = b_bits = allocatedBits = (unsigned char *) malloc(nBytes);
+		}
+		if (cp) {
+		    pBits = __imageBits;
+		    for (row = b_height; row; row--) {
+			for (col = bytesPerRowST; col; col--) {
+			    *cp++ = *pBits++;
+			}
+			cp += padding;
+		    }
+		} else
+		    goto fail;
+	    }
+	}
+
+	if (b_bits == 0) {
+	    b_bits = __imageBits;
+	}
+
+	bitmap.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+	bitmap.bmiHeader.biPlanes = 1;
+	switch (__intVal(imageDepth)) {
+	    case 16:
+		/*bitmap.bmiHeader.biCompression = BI_RGB;
+		bitmap.bmiHeader.biCompression = BI_BITFIELDS;
+		bitmap.b = 0x001f;
+		bitmap.g = 0x07e0;
+		bitmap.r = 0xf800;*/
+		bitmap.b = 0;
+		bitmap.g = 0;
+		bitmap.r = 0;
+		bitmap.bmiHeader.biCompression = BI_RGB;
+		break;
+
+	    case 24:
+		/*bitmap.bmiHeader.biCompression = BI_BITFIELDS;
+		bitmap.r = 0xff0000;
+		bitmap.g = 0x00ff00;
+		bitmap.b = 0x0000ff;*/
+		bitmap.bmiHeader.biCompression = BI_RGB;
+		break;
+
+	    case 32:
+		/*bitmap.bmiHeader.biCompression = BI_BITFIELDS;
+		bitmap.r = 0xff0000;
+		bitmap.g = 0x00ff00;
+		bitmap.b = 0x0000ff;*/
+		bitmap.bmiHeader.biCompression = BI_RGB;
+		_sourceAlpha = __intVal(sourceAlphaOrNil);
+		break;
+	}
+
+	bitmap.bmiHeader.biSizeImage = 0;
+	bitmap.bmiHeader.biXPelsPerMeter = 0;
+	bitmap.bmiHeader.biYPelsPerMeter = 0;
+	bitmap.bmiHeader.biClrUsed = 0;
+	bitmap.bmiHeader.biClrImportant = 0;
+	bitmap.bmiHeader.biWidth = __intVal(imageWidth);
+	bitmap.bmiHeader.biHeight = -(__intVal(imageHeight));
+	bitmap.bmiHeader.biBitCount = __intVal(bitsPerPixel);
+	/*console_printf("drawBits depth:%d bitsPerPixel:%d IW%d W:%d H:%d\n",__intVal(imageDepth),bitmap.bmiHeader.biBitCount,bitmap.bmiHeader.biWidth,__intVal(w),bitmap.bmiHeader.biHeight);*/
+
+	if (sourceAlphaOrNil == nil) {
+	    SetDIBitsToDevice(hDC,
+				__intVal(dstx), __intVal(dsty),
+				__intVal(w), __intVal(h),
+				__intVal(srcx), __intVal(srcy),
+				0, __intVal(h),
+				(void *)b_bits,
+				(BITMAPINFO*)&bitmap,
+				DIB_RGB_COLORS);
+	} else {
+	    HDC ahdc;
+	    HBITMAP ahbitmap;
+	    void *pvBits;
+	    BLENDFUNCTION bf;
+	    static BOOL (__stdcall *P_AlphaBlend)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION );
+
+	    if (P_AlphaBlend == 0) {
+		/* as I dont have AlphaBlend in the inport32.lib (bcc sucks),
+		 * fetch its address dynamically...
+		 */
+		HINSTANCE hWinGDI = LoadLibrary("wingdi.dll");
+
+		if (hWinGDI) {
+		    P_AlphaBlend = (BOOL (__stdcall *)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION ))
+					GetProcAddress(hWinGDI, "AlphaBlend");
+		}
+	    }
+	    if (P_AlphaBlend != 0) {
+		ahdc = CreateCompatibleDC(hDC);
+		ahbitmap = CreateDIBSection(ahdc, &(bitmap.bmiHeader),
+					    DIB_RGB_COLORS, &pvBits, NULL, 0);
+		SelectObject(ahdc, ahbitmap);
+
+		bf.BlendOp = AC_SRC_OVER;
+		bf.BlendFlags = 0;
+		bf.SourceConstantAlpha = 0xFF;
+		bf.AlphaFormat = AC_SRC_ALPHA;
+
+		(*P_AlphaBlend) (hDC,
+				__intVal(dstx), __intVal(dsty),
+				__intVal(w), __intVal(h),
+				ahdc,
+				__intVal(srcx), __intVal(srcy),
+				0, __intVal(h),
+				bf);
+		DeleteObject(ahbitmap);
+		DeleteDC(ahdc);
+	    }
+	}
+	if (allocatedBits) {
+	    free(allocatedBits);
+	}
+#ifndef CACHE_LAST_DC
+	_releaseDC(gcData);
+#endif
+	RETURN ( true );
+    }
+
+fail: ;
+    PRINTF(("create temp bitmap FAILED!!!\n"));
+    if (allocatedBits) {
+	PRINTF(("freeing up temp bitmap bits ...\n"));
+	free(allocatedBits);
+    }
+#ifndef CACHE_LAST_DC
+    if (hDC) {
+	_releaseDC(gcData);
+    }
+#endif
+%}
+.
+    ^ false
+!
+
 primDrawBits:imageBits bitsPerPixel:bitsPerPixel depth:imageDepth padding:padd
 			      width:imageWidth height:imageHeight
 				  x:srcx y:srcy
@@ -18287,7 +18526,7 @@
 !WinWorkstation class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview/WinWorkstation.st,v 1.395 2009-05-29 14:55:46 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libview/WinWorkstation.st,v 1.396 2009-08-03 17:19:53 cg Exp $'
 ! !
 
 WinWorkstation initialize!