--- a/DeviceGraphicsContext.st Tue Apr 11 21:18:55 2017 +0200
+++ b/DeviceGraphicsContext.st Tue Apr 11 21:19:12 2017 +0200
@@ -1910,11 +1910,44 @@
!DeviceGraphicsContext methodsFor:'drawing in device coordinates'!
-displayDeviceForm:aForm x:x y:y
+displayDeviceForm:aFormOrImage x:x y:y
"draw a form or image non opaque (i.e. only foreground color is drawn);
If it's 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 it's 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 have been allocated on the same device,
+ otherwise it's 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)."
+
+ (aFormOrImage isImage and:[aFormOrImage photometric == #rgba]) ifTrue:[
+ Error handle:[:ex |
+ Logger error:'error when drawinf alpha: %1' with:ex description.
+ ] do:[
+ self displayDeviceFormWithAlpha:aFormOrImage x:x y:y.
+ ^ self.
+ ].
+ ].
+ self displayDeviceFormNoAlpha:aFormOrImage x:x y:y.
+
+ "Modified: / 11-04-2017 / 18:29:56 / cg"
+!
+
+displayDeviceFormNoAlpha:aForm x:x y:y
+ "draw a form or image non opaque (i.e. only foreground color is drawn);
+ If it's 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 it's 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.
@@ -1996,8 +2029,7 @@
"/ stamp out using mask
device
- setForeground:0 background:allBits in:gcId;
- setFunction:#and in:gcId;
+ setForeground:0 background:allBits function:#and in:gcId;
copyPlaneFromPixmapId:maskId
x:0 y:0 gc:deviceMaskGcId
to:drawableId
@@ -2037,9 +2069,7 @@
] ifFalse:[
"/ must do it slow, using a temporary form ..
- "
- create temp-form;
- "
+ "/ create temp-form;
tmpForm := Form width:w height:h depth:device depth onDevice:device.
tmpForm isNil ifTrue:[
'DeviceGraphicsContext [warning]: cannot create temp form' errorPrintCR.
@@ -2048,15 +2078,11 @@
tmpId := tmpForm drawableId.
tmpGCId := tmpForm initGC.
- "
- fill tempform with image
- "
+ "/ fill tempform with image
depth == 1 ifTrue:[
(colorMap := deviceForm colorMap) notNil ifTrue:[
colorMap size < 2 ifTrue:[
- device
- setForegroundColor:(colorMap at:1)
- in:tmpGCId.
+ device setForegroundColor:(colorMap at:1) in:tmpGCId.
] ifFalse:[
device
setForegroundColor:(colorMap at:2)
@@ -2067,66 +2093,45 @@
device
copyPlaneFromPixmapId:id
x:0 y:0 gc:deviceFormGCId
- to:tmpId
- x:0 y:0 gc:tmpGCId
+ 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
+ to:tmpId x:0 y:0 gc:tmpGCId
width:w height:h.
].
- "
- stamp out mask in temp form
- set unmasked pixels to allBits and masked pixels to 0
- "
+ "/ stamp out mask in temp form
+ "/ set unmasked pixels to allBits and masked pixels to 0
device
- setForeground:allBits background:0 in:tmpGCId;
- setFunction:#and in:tmpGCId;
+ setForeground:allBits background:0 function:#and in:tmpGCId;
copyPlaneFromPixmapId:maskId
x:0 y:0 gc:deviceMaskGcId
- to:tmpId
- x:0 y:0 gc:tmpGCId
+ to:tmpId x:0 y:0 gc:tmpGCId
width:w height:h.
-"/Debug = 1 ifTrue:[
-"/ Debug := 0.
-"/ tmpForm asImage inspect.
-"/ deviceForm inspect.
-"/].
-
- "
- stamp out mask in destination
- set unmasked pixels to 0 and masked pixels to allBits
- "
+
+ "/ stamp out mask in destination
+ "/ set unmasked pixels to 0 and masked pixels to allBits
device
- setForeground:0 background:allBits in:gcId;
- setFunction:#and in:gcId;
+ setForeground:0 background:allBits function:#and in:gcId;
copyPlaneFromPixmapId:maskId
x:0 y:0 gc:deviceMaskGcId
- to:drawableId
- x:pX y:pY gc:gcId
+ to:drawableId x:pX y:pY gc:gcId
width:w height:h.
- "
- or-in tempform-bits ...
- "
+ "/ or-in tempform-bits ...
device
- setForeground:0 background:0 in:gcId;
- setFunction:#or in:gcId;
+ setForeground:0 background:0 function:#or in:gcId;
copyFromPixmapId:tmpId
x:0 y:0 gc:tmpGCId
- to:drawableId
- x:pX y:pY gc: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 ...)
- "
+ "/ release tempForm immediately
+ "/ (although GC will eventually do it,
+ "/ this creates less stress to the Xserver in the meanwhile ...)
tmpForm destroy.
].
@@ -2142,7 +2147,6 @@
]
]
].
-
device
copyFromPixmapId:id
x:0 y:0 gc:deviceFormGCId
@@ -2152,17 +2156,13 @@
^ 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 device's capabilities has to be added here)
- (just assume drawing a bitmap with dithered paint color ... sigh)
- "
+ "/ 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 device's 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 ...
- "
+ "/ if paint is not a real color, we have to do it the hard way ...
easy ifTrue:[
paint isColor ifTrue:[
paintDither := paint ditherForm.
@@ -2179,23 +2179,15 @@
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 ...
- "
+ "/ 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.
+ "/ clear fg-bits ...
+ device setForeground:0 background:allBits function:#and in:gcId.
device
copyPlaneFromPixmapId:id
x:0 y:0 gc:deviceFormGCId
@@ -2205,11 +2197,8 @@
].
fgId ~~ 0 ifTrue:[
- "
- or-in fg-bits ...
- "
- device setForeground:fgId background:0 in:gcId.
- device setFunction:#or in:gcId.
+ "/ or-in fg-bits ...
+ device setForeground:fgId background:0 function:#or in:gcId.
device
copyPlaneFromPixmapId:id
x:0 y:0 gc:deviceFormGCId
@@ -2217,12 +2206,8 @@
x:pX y:pY gc:gcId
width:w height:h
].
- "
- flush foreground/background cache
- "
+ "/ flush foreground/background cache
device setForegroundColor:foreground backgroundColor:background in:gcId.
- "/ foreground := nil.
- "/ background := nil.
device setFunction:function in:gcId.
^ self
].
@@ -2240,9 +2225,7 @@
fgId := paint colorId.
fgId ~~ 0 ifTrue:[
- "
- or-in fg-bits ...
- "
+ "/ or-in fg-bits ...
device setForeground:fgId background:0 in:gcId.
device
copyPlaneFromPixmapId:id
@@ -2251,89 +2234,184 @@
x:pX y:pY gc:gcId
width:w height:h
].
- "
- flush foreground/background cache
- "
+ "/ flush foreground/background cache
foreground := nil.
background := nil.
^ self
].
].
- "
- hard case; paint is a dithered color
- "
-
+ "/ hard case; paint is a dithered color
noColor := Color noColor.
- "
- create temp-form;
- "
+ "/ create temp-form;
tmpForm := Form width:w height:h depth:device depth onDevice: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.
+
+ "/ fill tempform
+ tmpForm paint:paint; fillRectangleX:0 y:0 width:w height:h.
+
+ "/ stamp out background
+ tmpForm paint:allColor on:noColor; 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.
+
+ "/ stamp out foreground from destination
+ device setForeground:0 background:allBits function:#and in:gcId.
device
copyPlaneFromPixmapId:id
- x:0
- y:0
+ 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.
+ to:drawableId x:pX y:pY
+ gc:gcId width:w height:h.
+
+ "/ or-in temp into destination
+ device setForeground:allBits background:0 function:#or in:gcId.
device
copyFromPixmapId:tmpForm drawableId
- x:0
- y:0
+ 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 ...)
- "
+ 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
- "
+
+ "/ flush foreground/background cache
foreground := nil.
background := nil.
device setFunction:function in:gcId.
- "Modified: / 15-03-2017 / 12:45:36 / cg"
+ "Created: / 11-04-2017 / 16:45:18 / cg"
+!
+
+displayDeviceFormWithAlpha:anImage x:x y:y
+ "draw a form or image non opaque (i.e. only foreground color is drawn);
+ If it's 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 it's 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 have been allocated on the same device,
+ otherwise it's 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)."
+
+ |bytesPerLine orgDstData dstData imgData info w h pX pY bppDrawable
+ dstBytesPerRow "{Class: SmallInteger}"
+ imgBytesPerRow "{Class: SmallInteger}"
+ dstIndex "{Class: SmallInteger}"
+ imgIndex "{Class: SmallInteger}"
+ dstRowIndex "{Class: SmallInteger}"
+ imgRowIndex "{Class: SmallInteger}"|
+
+ device sync.
+
+ w := anImage width.
+ h := anImage height.
+ (w = 0 or:[h = 0]) ifTrue:[^ self].
+
+ pX := x rounded.
+ pY := y rounded.
+
+ "/ give it more than enough bytes
+ bytesPerLine := (w * 32 + 31) // 32 * 4.
+ dstData := ByteArray uninitializedNew:(bytesPerLine * h).
+ drawableType == #pixmap ifTrue:[
+ info := device getBitsFromPixmapId:(self drawableId) x:pX y:pY width:w height:h into:dstData.
+ ] ifFalse:[
+ info := device getBitsFromViewId:(self drawableId) x:pX y:pY width:w height:h into:dstData.
+ ].
+
+ dstBytesPerRow := info at:#bytesPerLine.
+ imgBytesPerRow := anImage bytesPerRow.
+
+ imgData := anImage bits.
+ orgDstData := dstData copy.
+
+ bppDrawable := info at:#bitsPerPixel.
+ bppDrawable == 32 ifTrue:[
+ "/ data is coming as bytes in r,g,b,a order
+ dstRowIndex := 1.
+ imgRowIndex := 1.
+
+ "/ draw "by hand" here
+ 0 to:h-1 do:[:y |
+ dstIndex := dstRowIndex.
+ imgIndex := imgRowIndex.
+ 0 to:w-1 do:[:x |
+ |rD "{Class: SmallInteger}"
+ gD "{Class: SmallInteger}"
+ bD "{Class: SmallInteger}"
+ rI "{Class: SmallInteger}"
+ gI "{Class: SmallInteger}"
+ bI "{Class: SmallInteger}"
+ aI "{Class: SmallInteger}"
+ aD "{Class: SmallInteger}"
+ nR "{Class: SmallInteger}"
+ nG "{Class: SmallInteger}"
+ nB "{Class: SmallInteger}"|
+
+ rD := dstData at:(dstIndex+0).
+ gD := dstData at:(dstIndex+1).
+ bD := dstData at:(dstIndex+2).
+
+ rI := imgData at:(imgIndex).
+ gI := imgData at:(imgIndex+1).
+ bI := imgData at:(imgIndex+2).
+ aI := imgData at:(imgIndex+3).
+
+ aI == 255 ifTrue:[
+ nR := rI.
+ nG := gI.
+ nB := bI.
+ ] ifFalse:[
+ aI == 0 ifTrue:[
+ nR := rD.
+ nG := gD.
+ nB := bD.
+ ] ifFalse:[
+ aD := 255 - aI.
+
+ nR := (((rI * aI)+(rD * aD)) // 255).
+ nG := (((gI * aI)+(gD * aD)) // 255).
+ nB := (((bI * aI)+(bD * aD)) // 255).
+ ].
+ ].
+ dstData at:(dstIndex+1) put:nR.
+ dstData at:(dstIndex+2) put:nG.
+ dstData at:(dstIndex+3) put:nB.
+
+ dstIndex := dstIndex + 4.
+ imgIndex := imgIndex + 4.
+ ].
+ dstRowIndex := dstRowIndex + dstBytesPerRow.
+ imgRowIndex := imgRowIndex + imgBytesPerRow.
+ ].
+ "/ draw the pixels (always MSB)
+ device
+ drawBits:dstData msb:true bitsPerPixel:32 depth:24 padding:32
+ width:w height:h x:0 y:0
+ into:(self drawableId) x:pX y:pY width:w height:h with:gcId.
+ ^ self.
+ ].
+ self halt.
+
+ "Created: / 11-04-2017 / 16:45:39 / cg"
+ "Modified (format): / 11-04-2017 / 21:11:50 / cg"
!
displayDeviceLineFromX:x0 y:y0 toX:x1 y:y1