drawing bitmaps
authorfm
Fri, 19 Oct 2007 15:47:23 +0200
changeset 2338 d170c690a945
parent 2337 1ed848a70875
child 2339 1926485dda73
drawing bitmaps
WinPrinterContext.st
--- a/WinPrinterContext.st	Fri Oct 19 15:23:40 2007 +0200
+++ b/WinPrinterContext.st	Fri Oct 19 15:47:23 2007 +0200
@@ -333,33 +333,6 @@
     "Created: / 07-08-2006 / 12:09:48 / fm"
     "Modified: / 07-08-2006 / 14:11:17 / fm"
     "Modified: / 16-04-2007 / 15:37:41 / cg"
-!
-
-printImage: anImage
-    "Opens a print dialog and prints the given image"
-
-    | printerInfo printer |
-
-    printerInfo := PrintingDialog getPrinterInfo.
-    printerInfo isNil ifTrue:[^self].
-
-    printer := self fromPrinterInfo: printerInfo.
-    [
-	printer startPrintJob: 'Image'.
-	printer background:Color white.
-	anImage displayOn:printer x:1000 y:1000.
-	printer endPrintJob.
-    ] forkAt: 3
-
-    "
-     WinPrinterContext printImage: (Image fromFile:'C:\vsw311\pavheadr.gif').
-     WinPrinterContext printImage: XPToolbarIconLibrary help32x32Icon.
-     WinPrinterContext printImage: XPToolbarIconLibrary eraseXP28x28Icon.
-
-    "
-
-    "Created: / 07-08-2006 / 11:46:52 / fm"
-    "Modified: / 16-04-2007 / 15:37:34 / cg"
 ! !
 
 !WinPrinterContext class methodsFor:'testing & examples'!
@@ -629,12 +602,12 @@
 
     printer := self fromPrinterInfo: printerInfo.
     [
-	printer
-	    print: aString
-	    font: aFont
-	    title: aTitle
-	    wordWrap: wordWrap
-	    marginsRect: nil
+        printer
+            print: aString
+            font: aFont
+            title: aTitle
+            wordWrap: wordWrap
+            marginsRect: nil
     ] forkAt: 3
 
     "
@@ -707,6 +680,34 @@
     "Modified: / 16-04-2007 / 15:37:38 / cg"
 !
 
+printImage: anImage
+    "Opens a print dialog and prints the given image"
+
+    | printerInfo printer |
+
+    printerInfo := PrintingDialog getPrinterInfo.
+    printerInfo isNil ifTrue:[^self].
+
+    printer := self fromPrinterInfo: printerInfo.
+    [
+        printer startPrintJob: 'Image'.
+        printer background:Color white.
+        anImage displayOn:printer x:1000 y:1000.
+        printer endPrintJob.
+    ] forkAt: 3
+
+    "
+     WinPrinterContext printImage: (Image fromFile:'C:\vsw311\pavheadr.gif').
+     WinPrinterContext printImage: XPToolbarIconLibrary help32x32Icon.
+     WinPrinterContext printImage: XPToolbarIconLibrary eraseXP28x28Icon.
+     WinPrinterContext printImage: XPToolbarIconLibrary saveImageBlack22x22Icon.
+     WinPrinterContext printImage: XPToolbarIconLibrary changesBrowser18x22Icon.
+    "
+
+    "Created: / 07-08-2006 / 11:46:52 / fm"
+    "Modified: / 16-04-2007 / 15:37:34 / cg"
+!
+
 printLines: pairOfPointsWithContextArray
     "Opens a print dialog and prints the given lines"
 
@@ -918,6 +919,10 @@
 
 !WinPrinterContext methodsFor:'accessing'!
 
+bitsPerPixel
+    ^ printerInfo bitsPerPixel ? 8
+!
+
 depth
     ^ 24
 !
@@ -2590,8 +2595,87 @@
      ^Display bitsRed
 !
 
+compressColorMapImage: image
+    "calculates a new color map for the image, using only used colors"
+
+    |depth newColorMap newImage oldImage usedColors oldToNew oldBits newBits tmpBits| 
+
+    oldImage := image.
+    depth := oldImage depth.
+
+    oldImage photometric ~~ #palette ifTrue:[
+        Transcript showCR:'Compress colorMap: Only palette images have colormaps.'.
+        ^ image
+    ].
+
+    usedColors := oldImage realUsedColors.
+    usedColors size == (1 bitShift:depth) ifTrue:[
+        Transcript showCR:'Compress colorMap: All colors are used - no compression.'.
+        ^ image
+    ].
+    usedColors size == oldImage colorMap size ifTrue:[
+        Transcript showCR:'Compress colorMap: Colormap already compressed - no compression.'.
+        ^ image
+    ].
+
+        "/ translation table
+        oldToNew := ByteArray new:(1 bitShift:depth).
+        newColorMap := usedColors asArray.
+        newColorMap sort:self sortBlockForColors.
+
+        oldImage colorMap asArray keysAndValuesDo:[:oldIdx :clr |
+            |newPixel|
+
+            (usedColors includes:clr) ifTrue:[
+                newPixel := newColorMap indexOf:clr.
+                oldToNew at:oldIdx put:newPixel-1.
+            ]
+        ].
+
+        oldBits := oldImage bits.
+        newBits := ByteArray new:(oldBits size).
+        depth ~~ 8 ifTrue:[
+            "/ expand/compress can only handle 8bits
+            tmpBits := ByteArray uninitializedNew:(oldImage width*oldImage height).
+            oldBits
+                expandPixels:depth
+                width:oldImage width
+                height:oldImage height 
+                into:tmpBits
+                mapping:oldToNew.
+            tmpBits
+                compressPixels:depth 
+                width:oldImage width 
+                height:oldImage height 
+                into:newBits 
+                mapping:nil
+        ] ifFalse:[
+            oldBits
+                expandPixels:depth
+                width:oldImage width
+                height:oldImage height 
+                into:newBits
+                mapping:oldToNew.
+        ].
+
+        newImage := oldImage species new
+                        width:oldImage width
+                        height:oldImage height
+                        depth:depth
+                        fromArray:newBits.
+
+        newImage colorMap:newColorMap.  
+        newImage fileName:oldImage fileName.
+        newImage mask:(oldImage mask copy).
+
+        ^ newImage
+
+    "Created: / 28.7.1998 / 20:03:11 / cg"
+    "Modified: / 15.9.1998 / 17:53:32 / cg"
+!
+
 copyFromId:sourceId x:srcX y:srcY gc:srcGCId to:destId x:dstX y:dstY gc:dstGCId
-		width:w height:h
+                width:w height:h
     "do a bit-blt; copy bits from the rectangle defined by
      srcX/srcY and w/h from the sourceId drawable to the rectangle
      below dstX/dstY in the destId drawable. Trigger an error if any
@@ -2604,39 +2688,39 @@
 
     if (! __isExternalAddressLike(srcGCId)
      || ! __isExternalAddressLike(dstGCId)) {
-	goto fail;
+        goto fail;
     }
 
     if (__bothSmallInteger(w, h)
      && __bothSmallInteger(srcX, srcY)
      && __bothSmallInteger(dstX, dstY)) {
-	HANDLE srcDC = (HANDLE)(__externalAddressVal(srcGCId));
-	HANDLE dstDC = (HANDLE)(__externalAddressVal(dstGCId));
-
-	int fun, aFunctionSymbol;
-	int src_fg, src_bg, dst_fg, dst_bg;
-	char buf[5];
+        HANDLE srcDC = (HANDLE)(__externalAddressVal(srcGCId));
+        HANDLE dstDC = (HANDLE)(__externalAddressVal(dstGCId));
+
+        int fun, aFunctionSymbol;
+        int src_fg, src_bg, dst_fg, dst_bg;
+        char buf[5];
 
 //          fun = dstGcData->bitbltrop2;
 
-	aFunctionSymbol= __INST(function);
-
-	if (aFunctionSymbol == @symbol(copy)) {
-	    fun = SRCCOPY /* R2_COPYPEN */ ;
+        aFunctionSymbol= __INST(function);
+
+        if (aFunctionSymbol == @symbol(copy)) {
+            fun = SRCCOPY /* R2_COPYPEN */ ;
 /*            bfun = BITBLT_COPY;                                          */
-	} else if (aFunctionSymbol == @symbol(copyInverted)) {
-	    fun = NOTSRCCOPY /* R2_NOTCOPYPEN */;
+        } else if (aFunctionSymbol == @symbol(copyInverted)) {
+            fun = NOTSRCCOPY /* R2_NOTCOPYPEN */;
 /*            bfun = BITBLT_COPYINVERTED;                                  */
-	} else if (aFunctionSymbol == @symbol(xor)) {
-	    fun = SRCINVERT /* R2_XORPEN */;
+        } else if (aFunctionSymbol == @symbol(xor)) {
+            fun = SRCINVERT /* R2_XORPEN */;
 /*            bfun = BITBLT_XOR;                                           */
-	} else if (aFunctionSymbol == @symbol(and)) {
-	    fun = SRCAND /* R2_MASKPEN */ ;
+        } else if (aFunctionSymbol == @symbol(and)) {
+            fun = SRCAND /* R2_MASKPEN */ ;
 /*            bfun = BITBLT_AND;                                           */
-	} else if (aFunctionSymbol == @symbol(or)) {
-	    fun = MERGECOPY /* R2_MERGEPEN */ ;
+        } else if (aFunctionSymbol == @symbol(or)) {
+            fun = MERGECOPY /* R2_MERGEPEN */ ;
 /*            bfun = BITBLT_OR;                                            */
-	}
+        }
 
     // convert 123 to string [buf]
     // itoa(fun, buf, 10);
@@ -2645,75 +2729,75 @@
 
 /*
 #if 0
-	switch (fun) {
-	  case BITBLT_COPY:
-	    console_printf("BITBLT_COPY\n");
-	    break;
-	  case BITBLT_COPYINVERTED:
-	    console_printf("BITBLT_COPYINVERTED\n");
-	    break;
-	  case BITBLT_XOR:
-	    console_printf("BITBLT_XOR\n");
-	    break;
-	  case BITBLT_AND:
-	    console_printf("BITBLT_AND\n");
-	    break;
-	  case BITBLT_OR:
-	    console_printf("BITBLT_OR\n");
-	    break;
-	}
+        switch (fun) {
+          case BITBLT_COPY:
+            console_printf("BITBLT_COPY\n");
+            break;
+          case BITBLT_COPYINVERTED:
+            console_printf("BITBLT_COPYINVERTED\n");
+            break;
+          case BITBLT_XOR:
+            console_printf("BITBLT_XOR\n");
+            break;
+          case BITBLT_AND:
+            console_printf("BITBLT_AND\n");
+            break;
+          case BITBLT_OR:
+            console_printf("BITBLT_OR\n");
+            break;
+        }
 #endif
 */
 
 //          fun = dstGcData->bitbltrop2;
 
-	if (0 /* fun == BITBLT_COPY */) {
-	    src_fg = dst_fg = 0xFFFFFF;
-	    src_bg = dst_bg = 0x000000;
-	} else {
-	    src_fg = GetTextColor(srcDC) /* srcGcData->fgColor */;
-	    src_bg = GetBkColor(dstDC) /* srcGcData->bgColor */;
-	    dst_fg = GetTextColor(srcDC) /* dstGcData->fgColor */;
-	    dst_bg = GetBkColor(dstDC) /* dstGcData->bgColor */;
-	}
-
-	SetBkColor(dstDC, dst_fg);
-	SetTextColor(dstDC, dst_bg);
-
-	SetBkColor(srcDC, src_fg);
-	SetTextColor(srcDC, src_bg);
+        if (0 /* fun == BITBLT_COPY */) {
+            src_fg = dst_fg = 0xFFFFFF;
+            src_bg = dst_bg = 0x000000;
+        } else {
+            src_fg = GetTextColor(srcDC) /* srcGcData->fgColor */;
+            src_bg = GetBkColor(dstDC) /* srcGcData->bgColor */;
+            dst_fg = GetTextColor(srcDC) /* dstGcData->fgColor */;
+            dst_bg = GetBkColor(dstDC) /* dstGcData->bgColor */;
+        }
+
+        SetBkColor(dstDC, dst_fg);
+        SetTextColor(dstDC, dst_bg);
+
+        SetBkColor(srcDC, src_fg);
+        SetTextColor(srcDC, src_bg);
 
 /*
-	CPRINTF(("bitblt src f:%x b:%x",GetTextColor(srcDC),GetBkColor(srcDC)));
-	CPRINTF(("dst f:%x b:%x\n",GetTextColor(dstDC),GetBkColor(dstDC)));
+        CPRINTF(("bitblt src f:%x b:%x",GetTextColor(srcDC),GetBkColor(srcDC)));
+        CPRINTF(("dst f:%x b:%x\n",GetTextColor(dstDC),GetBkColor(dstDC)));
 */
-	if (BitBlt(dstDC,
-	     __intVal(dstX), __intVal(dstY),
-	     __intVal(w), __intVal(h),
-	     srcDC,
-	     __intVal(srcX), __intVal(srcY),
-	     fun)
-	   == 0
-	  ) {
-	    console_fprintf(stderr, "WinWorkstation [info]: ERROR in BitBlt\n");
-	}
+        if (BitBlt(dstDC,
+             __intVal(dstX), __intVal(dstY),
+             __intVal(w), __intVal(h),
+             srcDC,
+             __intVal(srcX), __intVal(srcY),
+             fun)
+           == 0
+          ) {
+            console_fprintf(stderr, "WinWorkstation [info]: ERROR in BitBlt\n");
+        }
 
 /*
-	if (dstGcData != srcGcData) {
-	    SetBkColor(dstDC, dstGcData->bgColor);
-	    SetTextColor(dstDC, dstGcData->fgColor);
-	}
-	SetBkColor(srcDC, srcGcData->bgColor);
-	SetTextColor(srcDC, srcGcData->fgColor);
+        if (dstGcData != srcGcData) {
+            SetBkColor(dstDC, dstGcData->bgColor);
+            SetTextColor(dstDC, dstGcData->fgColor);
+        }
+        SetBkColor(srcDC, srcGcData->bgColor);
+        SetTextColor(srcDC, srcGcData->fgColor);
 */
 
 /*
-	if (srcGcData != dstGcData) {
-	    _releaseDC(srcGcData);
-	}
-	_releaseDC(dstGcData);
+        if (srcGcData != dstGcData) {
+            _releaseDC(srcGcData);
+        }
+        _releaseDC(dstGcData);
 */
-	RETURN ( self );
+        RETURN ( self );
     }
 
  fail: ;
@@ -2813,450 +2897,48 @@
 !
 
 displayDeviceForm:aForm x:x y:y
-    "draw a form or image non opaque (i.e. only foreground color is drawn); 
-     If its a 1-plane bitmap, 1-bits are drawn in the
-     current paint-color, leaving pixels with 0-bits unchanged
-     (i.e. only 1-bits are drawn from the form).
-     If its a deep form (i.e. a pixmap) the current paint
-     settings are ignored and the form is drawn as-is; 
-     however, the mask is applied if present.
-
-     The form should must have been allocated on the same device,
-     otherwise its converted here, which slows down the draw.
-     No transformation or scaling is done.
-     Care must be taken, that the paint color is correctly allocated 
-     (by sending #on: to the color) before doing so.
-     Using functions other than #copy only makes sense if you are
-     certain, that the colors are real colors (actually, only for
-     noColor or allColor)."
-
-"/    |id w h easy paintDither tmpForm tmpId tmpGCId 
-"/     fgId noColor allColor allBits pX pY 
-"/     mask maskId deviceForm deviceFormGCId deviceMask colorMap|
-"/
-"/    w := aForm width.
-"/    h := aForm height.
-"/
-"/    pX := x rounded.
-"/    pY := y rounded.
-"/
-"/    deviceForm := aForm asFormOn:device.
-"/    deviceForm isNil ifTrue:[
-"/        'DeviceGraphicsContext [warning]: cannot create device-form' errorPrintCR.
-"/        ^self
-"/    ].
-"/    id := deviceForm id.
-"/
-"/    id isNil ifTrue:[
-"/        'DeviceGraphicsContext [warning]: invalid form draw - ignored' errorPrintCR.
-"/        ^ self
-"/    ].
-"/    gcId isNil ifTrue:[
-"/        self initGC
-"/    ].
-"/    (deviceFormGCId := deviceForm gcId) isNil ifTrue:[
-"/        "/ device needGCForBitmapSource  - i.e. WIN32
-"/        device platformName ~= 'X11' ifTrue:[
-"/            deviceForm initGC.
-"/            deviceFormGCId := deviceForm gcId.
-"/        ]
-"/    ].
-"/
-"/    "
-"/     a deep form ignores paint/bgPaint settings
-"/    "
-"/    mask := aForm mask.
-"/
-"/    ((aForm depth ~~ 1) 
-"/    or:[mask notNil]) ifTrue:[
-"/        mask notNil ifTrue:[
-"/            mask depth == 1 ifFalse:[
-"/                'DEVGC: alpha channel not yet supported' errorPrintCR.
-"/            ] ifTrue:[
-"/                deviceMask := mask asFormOn:device.
-"/                deviceMask isNil ifTrue:[
-"/                    'DeviceGraphicsContext [warning]: cannot create device-mask' errorPrintCR.
-"/                    ^self
-"/                ].
-"/                maskId := deviceMask id.
-"/                maskId notNil ifTrue:[
-"/                    deviceMask gcId isNil ifTrue:[deviceMask initGC].
-"/                    allColor := Color allColor.
-"/                    allBits := allColor colorId.
-"/
-"/                    (deviceForm depth == device depth 
-"/                    and:[aForm maskedPixelsAre0]) ifTrue:[
-"/                        "/ can do it without a temporary pixmap:
-"/                        "/   or-in the form into the inverse stamped-out area 
-"/                        "/   of the destination.
-"/                        "/   Oring is of course only possible if we know that
-"/                        "/   masked pixels are already zero in the form.
-"/
-"/                        "/ stamp out using mask
-"/                        device setForeground:0 background:allBits in:gcId.
-"/                        device setFunction:#and in:gcId.
-"/                        device
-"/                            copyPlaneFromPixmapId:maskId
-"/                            x:0 
-"/                            y:0 
-"/                            gc:(deviceMask gcId)
-"/                            to:drawableId
-"/                            x:pX 
-"/                            y:pY 
-"/                            gc:gcId
-"/                            width:w 
-"/                            height:h.
-"/                        "/ or-in the form
-"/                        device setFunction:#or in:gcId.
-"/                        device
-"/                            copyFromPixmapId:id
-"/                            x:0 
-"/                            y:0 
-"/                            gc:deviceFormGCId
-"/                            to:drawableId
-"/                            x:pX 
-"/                            y:pY 
-"/                            gc:gcId
-"/                            width:w 
-"/                            height:h.
-"/                    ] ifFalse:[
-"/                        "/ must do it slow, using a temporary form ..
-"/
-"/                        "
-"/                         create temp-form;
-"/                        "
-"/                        tmpForm := Form width:w height:h depth:device depth on:device.
-"/                        tmpForm isNil ifTrue:[
-"/                            'DeviceGraphicsContext [warning]: cannot create temp form' errorPrintCR.
-"/                            ^self
-"/                        ].
-"/                        tmpForm initGC.
-"/                        tmpId := tmpForm id.
-"/                        tmpGCId := tmpForm gcId.
-"/
-"/                        "
-"/                         fill tempform with image
-"/                        "
-"/                        aForm depth == 1 ifTrue:[
-"/                            (colorMap := aForm colorMap) notNil ifTrue:[
-"/                                colorMap size < 2 ifTrue:[
-"/                                    device 
-"/                                        setForegroundColor:(colorMap at:1) 
-"/                                        in:tmpGCId.
-"/                                ] ifFalse:[
-"/                                    device 
-"/                                        setForegroundColor:(colorMap at:2) 
-"/                                        backgroundColor:(colorMap at:1) 
-"/                                        in:tmpGCId.
-"/                                ]
-"/                            ].
-"/                            device
-"/                                copyPlaneFromPixmapId:id
-"/                                x:0 
-"/                                y:0 
-"/                                gc:deviceFormGCId
-"/                                to:tmpId
-"/                                x:0 
-"/                                y:0 
-"/                                gc:tmpGCId
-"/                                width:w 
-"/                                height:h.
-"/                        ] ifFalse:[
-"/                            device
-"/                                copyFromPixmapId:id
-"/                                x:0 
-"/                                y:0 
-"/                                gc:deviceFormGCId
-"/                                to:tmpId
-"/                                x:0 
-"/                                y:0 
-"/                                gc:tmpGCId
-"/                                width:w 
-"/                                height:h.
-"/                        ].
-"/
-"/                        "
-"/                         stamp out mask in temp form
-"/                        "
-"/                        device setForeground:allBits background:0 in:tmpGCId.
-"/                        device setFunction:#and in:tmpGCId.
-"/                        device
-"/                            copyPlaneFromPixmapId:maskId
-"/                            x:0 
-"/                            y:0 
-"/                            gc:(deviceMask gcId)
-"/                            to:tmpId
-"/                            x:0 
-"/                            y:0 
-"/                            gc:tmpGCId
-"/                            width:w 
-"/                            height:h.
-"/
-"/                        "
-"/                         stamp out mask in destination
-"/                        "
-"/                        device setForeground:0 background:allBits in:gcId.
-"/                        device setFunction:#and in:gcId.
-"/                        device
-"/                            copyPlaneFromPixmapId:maskId
-"/                            x:0 
-"/                            y:0 
-"/                            gc:(deviceMask gcId)
-"/                            to:drawableId
-"/                            x:pX 
-"/                            y:pY 
-"/                            gc:gcId
-"/                            width:w 
-"/                            height:h.
-"/
-"/                        "
-"/                         or-in tempform-bits ...
-"/                        "
-"/                        device setFunction:#or in:gcId.
-"/                        device
-"/                            copyFromPixmapId:tmpId
-"/                            x:0 
-"/                            y:0 
-"/                            gc:tmpGCId
-"/                            to:drawableId
-"/                            x:pX 
-"/                            y:pY 
-"/                            gc:gcId
-"/                            width:w 
-"/                            height:h.
-"/
-"/                        "
-"/                         release tempForm immediately
-"/                         (although GC will eventually do it, 
-"/                          this creates less stress to the Xserver in the meanwhile ...)
-"/                        "
-"/                        tmpForm destroy.
-"/                    ].
-"/
-"/                    "/ restore GC
-"/                    foreground notNil ifTrue:[
-"/                        device setForegroundColor:foreground in:gcId.
-"/                    ].
-"/                    background notNil ifTrue:[
-"/                        device setBackgroundColor:background in:gcId 
-"/                    ].
-"/                    device setFunction:function in:gcId.
-"/                    ^ self
-"/                ]
-"/            ]
-"/        ].
-"/
-"/        device
-"/            copyFromPixmapId:id
-"/            x:0 
-"/            y:0 
-"/            gc:deviceForm gcId
-"/            to:drawableId
-"/            x:pX 
-"/            y:pY 
-"/            gc:gcId
-"/            width:w 
-"/            height:h.
-"/        ^ self
-"/    ].
-"/
-"/    "
-"/     the following code is somewhat complicated, since it has to deal
-"/     with dithered paint colors, which cannot be done directly on most
-"/     devices (actually, a test for the devices capabilities has to be added here)
-"/     (just assume drawing a bitmap with dithered paint color ... sigh)
-"/    "
-"/
-"/    easy := (function == #copy).
-"/
-"/    "
-"/     if paint is not a real color, we have to do it the hard way ...
-"/    "
-"/    easy ifTrue:[
-"/        paint isColor ifFalse:[
-"/            paintDither := paint.
-"/            easy := false
-"/        ] ifTrue:[
-"/            paintDither := paint ditherForm.
-"/            paintDither notNil ifTrue:[
-"/                easy := false.
-"/            ]
-"/        ].
-"/    ].
-"/
-"/    allColor := Color allColor.
-"/    allBits := allColor colorId.
-"/
-"/    easy ifTrue:[
-"/        "
-"/         paint is a real color
-"/        "
-"/
-"/        "
-"/         if paint color is all-0 or all-1's, we can do it in one
-"/         operation ...
-"/        "
-"/        fgId := paint colorId.
-"/
-"/        ((fgId ~~ ((1 bitShift:device depth)-1))
-"/        and:[fgId ~~ allBits]) ifTrue:[
-"/            "
-"/             clear fg-bits ...
-"/            "
-"/            device setForeground:0 background:allBits in:gcId.
-"/            device setFunction:#and in:gcId.
-"/            device
-"/                copyPlaneFromPixmapId:id
-"/                x:0 
-"/                y:0 
-"/                gc:deviceFormGCId
-"/                to:drawableId
-"/                x:pX 
-"/                y:pY 
-"/                gc:gcId
-"/                width:w 
-"/                height:h.
-"/        ].
-"/
-"/        fgId ~~ 0 ifTrue:[
-"/            "
-"/             or-in fg-bits ...
-"/            "
-"/            device setForeground:fgId background:0 in:gcId.
-"/            device setFunction:#or in:gcId.
-"/            device
-"/                copyPlaneFromPixmapId:id
-"/                x:0 
-"/                y:0 
-"/                gc:deviceFormGCId
-"/                to:drawableId
-"/                x:pX 
-"/                y:pY 
-"/                gc:gcId
-"/                width:w 
-"/                height:h
-"/        ].
-"/        "
-"/         flush foreground/background cache
-"/        "
-"/        foreground := nil.
-"/        background := nil.
-"/        device setFunction:function in:gcId.
-"/        ^ self
-"/    ].
-"/
-"/    function == #or ifTrue:[
-"/        easy := paint notNil
-"/                and:[paint isColor
-"/                and:[paint ditherForm isNil]].
-"/        easy ifTrue:[
-"/            easy := bgPaint isNil
-"/                        or:[bgPaint isColor
-"/                            and:[bgPaint colorId == 0]]
-"/        ].
-"/        easy ifTrue:[
-"/            fgId := paint colorId.
-"/
-"/            fgId ~~ 0 ifTrue:[
-"/                "
-"/                 or-in fg-bits ...
-"/                "
-"/                device setForeground:fgId background:0 in:gcId.
-"/                device
-"/                    copyPlaneFromPixmapId:id
-"/                    x:0 
-"/                    y:0 
-"/                    gc:deviceFormGCId
-"/                    to:drawableId
-"/                    x:pX 
-"/                    y:pY 
-"/                    gc:gcId
-"/                    width:w 
-"/                    height:h
-"/            ].
-"/            "
-"/             flush foreground/background cache
-"/            "
-"/            foreground := nil.
-"/            background := nil.
-"/            ^ self
-"/        ].
-"/    ].
-"/
-"/    "
-"/     hard case; paint is a dithered color
-"/    "
-"/
-"/    noColor := Color noColor.
-"/
-"/    "
-"/     create temp-form;
-"/    "
-"/    tmpForm := Form width:w height:h depth:device depth on:device.
-"/    tmpForm isNil ifTrue:[
-"/        'DeviceGraphicsContext [warning]: cannot create temp form' errorPrintCR.
-"/        ^self
-"/    ].
-"/    "
-"/     fill tempform
-"/    "
-"/    tmpForm paint:paint.
-"/    tmpForm fillRectangleX:0 y:0 width:w height:h.
-"/    "
-"/     stamp out background
-"/    "
-"/    tmpForm paint:allColor on:noColor.
-"/    tmpForm function:#and.
-"/    tmpForm displayOpaqueForm:deviceForm x:0 y:0.
-"/    "
-"/     stamp out foreground from destination
-"/    "
-"/    device setForeground:0 background:allBits in:gcId.
-"/    device setFunction:#and in:gcId.
-"/    device
-"/        copyPlaneFromPixmapId:id
-"/        x:0 
-"/        y:0 
-"/        gc:deviceFormGCId
-"/        to:drawableId
-"/        x:pX 
-"/        y:pY 
-"/        gc:gcId
-"/        width:w 
-"/        height:h.
-"/    "
-"/     or-in temp into destination
-"/    "
-"/    device setForeground:allBits background:0 in:gcId.
-"/    device setFunction:#or in:gcId.
-"/
-"/    device
-"/        copyFromPixmapId:tmpForm id
-"/        x:0 
-"/        y:0 
-"/        gc:tmpForm gcId
-"/        to:drawableId
-"/        x:pX 
-"/        y:pY 
-"/        gc:gcId
-"/        width:w 
-"/        height:h.
-"/
-"/    "
-"/     release tempForm immediately
-"/     (although GC will eventually do it, 
-"/      this creates less stress to the Xserver in the meanwhile ...)
-"/    "
-"/
-"/    tmpForm destroy.
-"/    "
-"/     flush foreground/background cache
-"/    "
-"/    foreground := nil.
-"/    background := nil.
-"/    device setFunction:function in:gcId.
-
-    "Modified: / 27.7.1998 / 20:07:22 / cg"
+
+    |sortedImage formMask bitsWithTransparency|
+
+    sortedImage := aForm.
+"/    sortedImage := self sortColorMapImage: aForm.
+    sortedImage := self compressColorMapImage: sortedImage.
+
+    formMask := sortedImage mask.
+    formMask isNil 
+        ifTrue:[bitsWithTransparency := aForm bits ]
+        ifFalse:[
+            |bitsWithTransparencySize|
+            formMask := formMask asImageWithDepth: aForm depth.
+            bitsWithTransparency := sortedImage bits copy.
+            bitsWithTransparencySize := bitsWithTransparency size.
+            formMask bits doWithIndex:[:maskBit :index |
+                bitsWithTransparencySize >= index ifTrue:[
+                    maskBit == 0 ifTrue:[bitsWithTransparency at: index put: 255 "60" "bitClearAt: index"].
+"/                maskBit == 1 ifTrue:[bitsWithTransparency at: index put: (bitsWithTransparency at: index)].
+                ].
+            ].
+    ].
+
+"/    sortedImage colorMap redVector at:255 put: 255.
+"/    sortedImage colorMap greenVector at:255 put: 255.
+"/    sortedImage colorMap blueVector at:255 put: 255.
+
+    self 
+         drawBits: bitsWithTransparency ? sortedImage bits
+        redVector: sortedImage colorMap redVector
+      greenVector: sortedImage colorMap greenVector
+       blueVector: sortedImage colorMap blueVector
+     bitsPerPixel: sortedImage bitsPerPixel
+            depth: sortedImage depth
+            width: sortedImage width 
+           height: sortedImage height
+             into: self id
+                x: x 
+                y: y
+            width: sortedImage width 
+           height: sortedImage height
+             with: gcId.
 !
 
 drawBits:imageBits bitsPerPixel:bitsPerPixel depth:imageDepth padding:padd
@@ -3296,6 +2978,41 @@
     ].
 !
 
+drawBits:imageBits redVector:redVector greenVector:greenVector blueVector:blueVector bitsPerPixel:bitsPerPixel depth:imageDepth 
+                              width:imageWidth height:imageHeight
+                               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.
+     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."
+
+    "
+     sorry; I had to separate it into 2 methods, since XPutImage needs
+     an unlimited stack, and thus cannot send primitiveFailed
+    "
+    (self primDrawBits:imageBits redVector:redVector greenVector:greenVector blueVector:blueVector bitsPerPixel:bitsPerPixel depth:imageDepth 
+                              width:imageWidth height:imageHeight
+                               into:ignoredDrawableId
+                                  x:dstx y:dsty
+                              width:w height:h
+                               with:aGCId)
+    ifFalse:[
+        "
+         also happens, if a segmentation violation occurs in the
+         XPutImage ...
+        "
+        self primitiveFailed
+    ].
+!
+
 primCreateBitmapFromArray:anArray width:w height:h
 %{
 
@@ -3394,12 +3111,12 @@
 !
 
 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
+                               with:aGCId
 
     "since XPutImage may allocate huge amount of stack space
      (some implementations use alloca), this must run with unlimited stack."
@@ -3411,9 +3128,9 @@
     unsigned char *__imageBits = 0;
 
     if (__isByteArray(imageBits)) {
-	__imageBits = __ByteArrayInstPtr(imageBits)->ba_element;
+        __imageBits = __ByteArrayInstPtr(imageBits)->ba_element;
     } else if (__isExternalBytesLike(imageBits)) {
-	__imageBits = (unsigned char *)(__externalBytesAddress(imageBits));
+        __imageBits = (unsigned char *)(__externalBytesAddress(imageBits));
     }
 
     if (/* ISCONNECTED
@@ -3426,120 +3143,120 @@
      && __isSmallInteger(padd)
      && __imageBits)
      {
-	struct
-	{
-	  BITMAPINFOHEADER bmiHeader;
-	  DWORD r;
-	  DWORD g;
-	  DWORD b;
-	} bitmap;
-
-	HANDLE hDC = (HANDLE)(__externalAddressVal(aGCId));
-	HBITMAP hBitmap = _HBITMAPVAL(__INST(drawableId));
+        struct
+        {
+          BITMAPINFOHEADER bmiHeader;
+          DWORD r;
+          DWORD g;
+          DWORD b;
+        } bitmap;
+
+        HANDLE hDC = (HANDLE)(__externalAddressVal(aGCId));
+        HBITMAP hBitmap = _HBITMAPVAL(__INST(drawableId));
 
 /*
-	DDPRINTF(("hDC = %x\n", hDC));
+        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;
-	if (__intVal(imageDepth) == 24) {
-	    /*bitmap.bmiHeader.biCompression = BI_BITFIELDS;
-	    bitmap.r = 0xff0000;
-	    bitmap.g = 0x00ff00;
-	    bitmap.b = 0x0000ff;*/
-	    bitmap.bmiHeader.biCompression = BI_RGB;
-	} else if (__intVal(imageDepth) == 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;
-	}
-	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);*/
-
-	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);
+        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;
+        if (__intVal(imageDepth) == 24) {
+            /*bitmap.bmiHeader.biCompression = BI_BITFIELDS;
+            bitmap.r = 0xff0000;
+            bitmap.g = 0x00ff00;
+            bitmap.b = 0x0000ff;*/
+            bitmap.bmiHeader.biCompression = BI_RGB;
+        } else if (__intVal(imageDepth) == 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;
+        }
+        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);*/
+
+        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);
 
 /*
-	SetDIBits(hDC,hBitmap,
-			      0,__intVal(h),
-			      (void *)b_bits,
-			      (BITMAPINFO*)&bitmap,DIB_RGB_COLORS);
+        SetDIBits(hDC,hBitmap,
+                              0,__intVal(h),
+                              (void *)b_bits,
+                              (BITMAPINFO*)&bitmap,DIB_RGB_COLORS);
 */
 /*
-	StretchDIBits(hDC,
-		      __intVal(dstx),(__intVal(dsty)),            //  x & y coord of destination upper-left corner
-		      __intVal(w), __intVal(h),                 // width & height of destination rectangle
-		      __intVal(srcx), __intVal(srcy),           // x & y coord of source upper-left corner
-		      __intVal(w), __intVal(h),                 // width & height of source rectangle
-		      (void *)b_bits,                           // bitmap bits
-		      (BITMAPINFO*)&bitmap,                     // bitmap data
-		      DIB_RGB_COLORS,                           // usage options
-		      SRCCOPY                                   // raster operation code
-	);
+        StretchDIBits(hDC,
+                      __intVal(dstx),(__intVal(dsty)),            //  x & y coord of destination upper-left corner
+                      __intVal(w), __intVal(h),                 // width & height of destination rectangle
+                      __intVal(srcx), __intVal(srcy),           // x & y coord of source upper-left corner
+                      __intVal(w), __intVal(h),                 // width & height of source rectangle
+                      (void *)b_bits,                           // bitmap bits
+                      (BITMAPINFO*)&bitmap,                     // bitmap data
+                      DIB_RGB_COLORS,                           // usage options
+                      SRCCOPY                                   // raster operation code
+        );
 */
-	if (allocatedBits) {
-	    free(allocatedBits);
-	}
+        if (allocatedBits) {
+            free(allocatedBits);
+        }
 /*
 #ifndef CACHE_LAST_DC
-	_releaseDC(gcData);
+        _releaseDC(gcData);
 #endif
 */
-	RETURN ( true );
+        RETURN ( true );
     }
 
 fail: ;
@@ -3548,14 +3265,211 @@
 */
     if (allocatedBits) {
 /*
-	PRINTF(("freeing up temp bitmap bits ...\n"));
+        PRINTF(("freeing up temp bitmap bits ...\n"));
 */
-	free(allocatedBits);
+        free(allocatedBits);
     }
 /*
 #ifndef CACHE_LAST_DC
     if (hDC) {
-	_releaseDC(gcData);
+        _releaseDC(gcData);
+    }
+#endif
+*/
+%}
+.
+    ^ false
+!
+
+primDrawBits:imageBits redVector:redVector greenVector:greenVector blueVector:blueVector bitsPerPixel:bitsPerPixel depth:imageDepth 
+                              width:imageWidth height:imageHeight
+                               into:ignoredDrawableId
+                                  x:dstx y:dsty
+                              width:w height:h
+                               with:aGCId
+
+    "since XPutImage may allocate huge amount of stack space
+     (some implementations use alloca), this must run with unlimited stack."
+
+%{
+    unsigned char fastBits[10000];
+    unsigned char *b_bits = 0;
+    unsigned char *allocatedBits = 0;
+    unsigned char *__imageBits = 0;
+    unsigned char *__redVector = 0;
+    unsigned char *__greenVector = 0;
+    unsigned char *__blueVector = 0;
+    int padd = 8;
+
+    if (__isByteArray(imageBits)) {
+        __imageBits = __ByteArrayInstPtr(imageBits)->ba_element;
+    } else if (__isExternalBytesLike(imageBits)) {
+        __imageBits = (unsigned char *)(__externalBytesAddress(imageBits));
+    }
+
+    if (__isByteArray(redVector)) {
+        __redVector = __ByteArrayInstPtr(redVector)->ba_element;
+    } else if (__isExternalBytesLike(redVector)) {
+        __redVector = (unsigned char *)(__externalBytesAddress(redVector));
+    }
+
+    if (__isByteArray(greenVector)) {
+        __greenVector = __ByteArrayInstPtr(greenVector)->ba_element;
+    } else if (__isExternalBytesLike(greenVector)) {
+        __greenVector = (unsigned char *)(__externalBytesAddress(greenVector));
+    }
+
+    if (__isByteArray(blueVector)) {
+        __blueVector = __ByteArrayInstPtr(blueVector)->ba_element;
+    } else if (__isExternalBytesLike(blueVector)) {
+        __blueVector = (unsigned char *)(__externalBytesAddress(blueVector));
+    }
+
+    if (/* ISCONNECTED
+     && */ __isExternalAddressLike(aGCId)
+//     && __bothSmallInteger(srcx, srcy)
+     && __bothSmallInteger(dstx, dsty)
+     && __bothSmallInteger(w, h)
+     && __bothSmallInteger(imageWidth, imageHeight)
+     && __bothSmallInteger(imageDepth, bitsPerPixel)
+     && __imageBits
+     && __redVector
+     && __greenVector
+     && __blueVector)
+     {
+        struct
+        {
+          BITMAPINFOHEADER bmiHeader;
+          RGBQUAD bmiColors[256];
+        } bitmap;
+
+        HANDLE hDC = (HANDLE)(__externalAddressVal(aGCId));
+        HBITMAP hBitmap = _HBITMAPVAL(__INST(drawableId));
+        int col;
+/*
+        DDPRINTF(("hDC = %x\n", hDC));
+*/
+
+        if (padd != WIN32PADDING) {
+
+            int row, col;
+            unsigned char *cp;
+            unsigned char *pBits;
+            int b_width, b_height, bytesPerRowST, bytesPerRowWN, padding, nBytes;
+            int bi = __intVal(bitsPerPixel);
+
+            console_fprintf(stderr, "Non WIN32PADDING");
+
+            b_width = __intVal(w);
+            b_height = __intVal(h);
+            bytesPerRowST = (b_width * bi + (padd - 1 )) / 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;
+        bitmap.bmiHeader.biCompression = BI_RGB;
+        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 (__intVal(imageDepth) == 8) {
+            for(col=0;col<256;col++)
+             {
+                if (__redVector[col] == 0) {
+                    console_fprintf(stderr, "__redVector[col] 0");
+                }
+              bitmap.bmiColors[col].rgbBlue = __blueVector[col];    // Microsoft idea: change rgbBlue to rgbRed
+              bitmap.bmiColors[col].rgbGreen = __greenVector[col];
+              bitmap.bmiColors[col].rgbRed = __redVector[col];         // Microsoft idea: change rgbRed to rgbBlue
+              bitmap.bmiColors[col].rgbReserved = 0;
+
+            }
+        }
+
+        bitmap.bmiColors[255].rgbBlue=255;
+        bitmap.bmiColors[255].rgbGreen=255;
+        bitmap.bmiColors[255].rgbRed =255;
+
+        SetDIBitsToDevice(hDC,__intVal(dstx),__intVal(dsty),
+                              __intVal(w), __intVal(h),
+                              0, 0, /* __intVal(srcx), __intVal(srcy),    */
+                              0,__intVal(h),
+                              (void *)b_bits,
+                              (BITMAPINFO*)&bitmap,DIB_RGB_COLORS);
+/*
+        SetDIBits(hDC,hBitmap,
+                              0,__intVal(h),
+                              (void *)b_bits,
+                              (BITMAPINFO*)&bitmap,DIB_RGB_COLORS);
+*/
+/*
+        StretchDIBits(hDC,
+                      __intVal(dstx),(__intVal(dsty)),            //  x & y coord of destination upper-left corner
+                      __intVal(w), __intVal(h),                 // width & height of destination rectangle
+                      __intVal(srcx), __intVal(srcy),           // x & y coord of source upper-left corner
+                      __intVal(w), __intVal(h),                 // width & height of source rectangle
+                      (void *)b_bits,                           // bitmap bits
+                      (BITMAPINFO*)&bitmap,                     // bitmap data
+                      DIB_RGB_COLORS,                           // usage options
+                      SRCCOPY                                   // raster operation code
+        );
+*/
+        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
 */
@@ -3635,6 +3549,91 @@
 "/    ^ bitsRed
 
      ^Display shiftRed
+!
+
+sortBlockForColors
+
+    ^ [:a :b |
+            a redByte == b redByte ifTrue:[
+                a greenByte == b greenByte ifTrue:[
+                    a blueByte < b blueByte
+                ] ifFalse:[
+                    a greenByte < b greenByte 
+                ]
+            ] ifFalse:[
+                a redByte < b redByte 
+            ]
+      ].
+!
+
+sortColorMapImage: image
+    "calculates a new color map for the image, sorting colors"
+
+    |sortBlock depth newColorMap newImage oldImage usedColors oldToNew oldBits newBits tmpBits| 
+
+    sortBlock := self sortBlockForColors.
+    oldImage := image.
+    depth := oldImage depth.
+
+    oldImage photometric ~~ #palette ifTrue:[
+        Transcript showCR:'Compress colorMap: Only palette images have colormaps.'.
+        ^ image
+    ].
+
+    usedColors := oldImage realColorMap.
+
+
+        "/ translation table
+        oldToNew := ByteArray new:(1 bitShift:depth).
+        newColorMap := usedColors asArray.
+        newColorMap sort:sortBlock.
+
+        oldImage colorMap asArray keysAndValuesDo:[:oldIdx :clr |
+            |newPixel|
+
+            (usedColors includes:clr) ifTrue:[
+                newPixel := newColorMap indexOf:clr.
+                oldToNew at:oldIdx put:newPixel-1.
+            ]
+        ].
+
+        oldBits := oldImage bits.
+        newBits := ByteArray new:(oldBits size).
+        depth ~~ 8 ifTrue:[
+            "/ expand/compress can only handle 8bits
+            tmpBits := ByteArray uninitializedNew:(oldImage width*oldImage height).
+            oldBits
+                expandPixels:depth
+                width:oldImage width
+                height:oldImage height 
+                into:tmpBits
+                mapping:oldToNew.
+            tmpBits
+                compressPixels:depth 
+                width:oldImage width 
+                height:oldImage height 
+                into:newBits 
+                mapping:nil
+        ] ifFalse:[
+            oldBits
+                expandPixels:depth
+                width:oldImage width
+                height:oldImage height 
+                into:newBits
+                mapping:oldToNew.
+        ].
+
+        newImage := oldImage species new
+                        width:oldImage width
+                        height:oldImage height
+                        depth:depth
+                        fromArray:newBits.
+
+        newImage colorMap:newColorMap.  
+        newImage fileName:oldImage fileName.
+        newImage mask:(oldImage mask copy).
+
+        ^newImage
 ! !
 
 !WinPrinterContext methodsFor:'font stuff'!
@@ -4542,48 +4541,48 @@
 %{  /* NOCONTEXT */
 
     if (__isExternalAddress(aDrawableId)){
-	BITMAP bitmap;
-	HBITMAP hBitmap = _HBITMAPVAL(aDrawableId);
-	HBITMAP memBM;
-	HANDLE compatibleDC, rootDC, hdcScreen;
+        BITMAP bitmap;
+        HBITMAP hBitmap = _HBITMAPVAL(aDrawableId);
+        HBITMAP memBM;
+        HANDLE compatibleDC, rootDC, hdcScreen;
    //     HANDLE printerDC = (HANDLE)(__externalAddressVal(__INST(gcId)));
 
-
-	if (! hBitmap) {
-	    RETURN (nil);
-	}
-
-	if (GetObject(hBitmap, sizeof(bitmap), &bitmap)) {
+        if (! hBitmap) {
+            RETURN (nil);
+        }
+
+        if (GetObject(hBitmap, sizeof(bitmap), &bitmap)) {
 /*
-	    DDPRINTF(("bitmap info:%d\n", bitmap.bmBitsPixel));
+            DDPRINTF(("bitmap info:%d\n", bitmap.bmBitsPixel));
 */
-	} else {
+        } else {
 /*
-	    DPRINTF(("noinfo returned for bitmap\n"));
+            DPRINTF(("noinfo returned for bitmap\n"));
 */
-	    /* mhmh - can this happen ? */
-	    bitmap.bmBitsPixel = 1;
-	}
+            /* mhmh - can this happen ? */
+            bitmap.bmBitsPixel = 1;
+        }
 /*
-	gcData->hBitmap = hBitmap;
-	gcData->bitmapColorBitCount = bitmap.bmBitsPixel;
+        gcData->hBitmap = hBitmap;
+        gcData->bitmapColorBitCount = bitmap.bmBitsPixel;
 */
 
-	rootDC  = CreateDC("DISPLAY", NULL, NULL, NULL);
-	compatibleDC = CreateCompatibleDC(rootDC);
-	SelectObject(compatibleDC, hBitmap);
+        rootDC  = CreateDC("DISPLAY", NULL, NULL, NULL);
+        compatibleDC = CreateCompatibleDC(rootDC);
+        SelectObject(compatibleDC, hBitmap);
 
    //     hdcScreen= CreateDC("NULL", NULL, NULL, NULL);
    //       compatibleDC =  rootDC;
    //     compatibleDC = CreateCompatibleDC(printerDC);
    //     compatibleDC = CreateCompatibleDC(0);
+
    //     memBM = CreateCompatibleBitmap ( compatibleDC, bitmap.bmWidth, bitmap.bmHeight );
    //     SelectObject ( compatibleDC, memBM );
 
-	RETURN (__MKOBJ(compatibleDC));
+        RETURN (__MKOBJ(compatibleDC));
 
 /*
-	RETURN ( __MKOBJ(gcData) );
+        RETURN ( __MKOBJ(gcData) );
 */
     }
     RETURN (nil);
@@ -4800,58 +4799,6 @@
 %}
 !
 
-xgcForBitmap:aDrawableId
-
-%{  /* NOCONTEXT */
-
-    if (__isExternalAddress(aDrawableId)){
-	BITMAP bitmap;
-	HBITMAP hBitmap = _HBITMAPVAL(aDrawableId);
-	HBITMAP memBM;
-	HANDLE compatibleDC, rootDC, hdcScreen;
-	HANDLE hDC = (HANDLE)(__externalAddressVal(__INST(gcId)));
-
-	if (! hBitmap) {
-	    RETURN (nil);
-	}
-
-	if (GetObject(hBitmap, sizeof(bitmap), &bitmap)) {
-/*
-	    DDPRINTF(("bitmap info:%d\n", bitmap.bmBitsPixel));
-*/
-	} else {
-/*
-	    DPRINTF(("noinfo returned for bitmap\n"));
-*/
-	    /* mhmh - can this happen ? */
-	    bitmap.bmBitsPixel = 1;
-	}
-/*
-	gcData->hBitmap = hBitmap;
-	gcData->bitmapColorBitCount = bitmap.bmBitsPixel;
-*/
-
-	rootDC  = CreateDC("DISPLAY", NULL, NULL, NULL);
-	compatibleDC = CreateCompatibleDC(hDC);
-	SelectObject(compatibleDC, hBitmap);
-
-   //     hdcScreen= CreateDC("NULL", NULL, NULL, NULL);
-   //       compatibleDC =  rootDC;
-   //     compatibleDC = CreateCompatibleDC(0);
-   //         compatibleDC = CreateCompatibleDC(hDC);
-   //     memBM = CreateCompatibleBitmap ( compatibleDC, bitmap.bmWidth, bitmap.bmHeight );
-   //     SelectObject ( compatibleDC, memBM );
-
-	RETURN (__MKOBJ(compatibleDC));
-
-/*
-	RETURN ( __MKOBJ(gcData) );
-*/
-    }
-    RETURN (nil);
-%}
-!
-
 xprimDrawBits:imageBits bitsPerPixel:bitsPerPixel depth:imageDepth padding:padd width:imageWidth height:imageHeight
 				  x:srcx y:srcy
 			       into:ignoredDrawableId
@@ -5267,5 +5214,5 @@
 !WinPrinterContext class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview2/WinPrinterContext.st,v 1.15 2007-05-03 13:59:24 fm Exp $'
+    ^ '$Header: /cvs/stx/stx/libview2/WinPrinterContext.st,v 1.16 2007-10-19 13:47:23 fm Exp $'
 ! !