<div dir="ltr"><div>Note that I have these "changes" working for 5 months now, so they should be reasonnably stable<br></div>I'm not particularly happy with the proliferation of type hint and some of them might well be unecessary, but I don't believe in chirurgical patch: too fragile, I prefer uniformity.<br></div><div class="gmail_extra"><br><div class="gmail_quote">2016-03-31 22:06 GMT+02:00 <span dir="ltr"><<a href="mailto:commits@source.squeak.org" target="_blank">commits@source.squeak.org</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
Nicolas Cellier uploaded a new version of VMMaker to project VM Maker:<br>
<a href="http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1754.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/VMMaker/VMMaker.oscog-nice.1754.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: VMMaker.oscog-nice.1754<br>
Author: nice<br>
Time: 31 March 2016, 10:04:44.274 pm<br>
UUID: a0138c60-3e62-446e-a1d8-b00b7bb6c92b<br>
Ancestors: VMMaker.oscog-eem.1753<br>
<br>
BitBltSimulation is operating on bits of 32bits words, therefore it's better to declare its operans as 'unsigned int' rather than sqInt.<br>
<br>
On 32bits VM, this should not change anything, but on 64bits spur, it makes this snippet work:<br>
<br>
| wideString source pos blt expectedWideString |<br>
source := #[1 64 255 14 1 64 48 251].<br>
expectedWideString := WideString fromByteArray: source.<br>
wideString := WideString new: source size // 4.<br>
pos := 0.<br>
blt := (BitBlt<br>
toForm: (Form new hackBits: wideString))<br>
sourceForm: (Form new hackBits: source).<br>
blt<br>
combinationRule: Form over;<br>
sourceX: 0;<br>
sourceY: pos // 4;<br>
height: wideString byteSize // 4;<br>
width: 4;<br>
destX: 0;<br>
destY: 0;<br>
copyBits.<br>
wideString restoreEndianness.<br>
self assert: wideString = expectedWideString<br>
<br>
Hence it fix loading/diffing MCZ with wide character.<br>
<br>
=============== Diff against VMMaker.oscog-eem.1753 ===============<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>addWord:with: (in category 'combination rules') -----<br>
addWord: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
^sourceWord + destinationWord!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>alphaBlend:with: (in category 'combination rules') -----<br>
alphaBlend: sourceWord with: destinationWord<br>
"Blend sourceWord with destinationWord, assuming both are 32-bit pixels.<br>
The source is assumed to have 255*alpha in the high 8 bits of each pixel,<br>
while the high 8 bits of the destinationWord will be ignored.<br>
The blend produced is alpha*source + (1-alpha)*dest, with<br>
the computation being performed independently on each color<br>
component. The high byte of the result will be 0."<br>
| alpha unAlpha result blendRB blendAG |<br>
<inline: false><br>
+ <returnTypeC: 'unsigned int'><br>
- <return: 'unsigned int'><br>
<var: #sourceWord type: 'unsigned int'><br>
<var: #destinationWord type: 'unsigned int'><br>
<var: #blendRB type: 'unsigned int'><br>
<var: #blendAG type: 'unsigned int'><br>
<var: #result type: 'unsigned int'><br>
<var: #alpha type: 'unsigned int'><br>
<var: #unAlpha type: 'unsigned int'><br>
alpha := sourceWord >> 24. "High 8 bits of source pixel"<br>
alpha = 0 ifTrue: [ ^ destinationWord ].<br>
alpha = 255 ifTrue: [ ^ sourceWord ].<br>
unAlpha := 255 - alpha.<br>
<br>
blendRB := ((sourceWord bitAnd: 16rFF00FF) * alpha) +<br>
((destinationWord bitAnd: 16rFF00FF) * unAlpha)<br>
+ 16rFF00FF. "blend red and blue"<br>
<br>
blendAG := (((sourceWord>> 8 bitOr: 16rFF0000) bitAnd: 16rFF00FF) * alpha) +<br>
((destinationWord>>8 bitAnd: 16rFF00FF) * unAlpha)<br>
+ 16rFF00FF. "blend alpha and green"<br>
<br>
blendRB := blendRB + (blendRB - 16r10001 >> 8 bitAnd: 16rFF00FF) >> 8 bitAnd: 16rFF00FF. "divide by 255"<br>
blendAG := blendAG + (blendAG - 16r10001 >> 8 bitAnd: 16rFF00FF) >> 8 bitAnd: 16rFF00FF.<br>
result := blendRB bitOr: blendAG<<8.<br>
^ result<br>
!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>alphaBlendConst:with: (in category 'combination rules') -----<br>
alphaBlendConst: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
<br>
^ self alphaBlendConst: sourceWord with: destinationWord paintMode: false!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>alphaBlendConst:with:paintMode: (in category 'combination rules') -----<br>
alphaBlendConst: sourceWord with: destinationWord paintMode: paintMode<br>
"Blend sourceWord with destinationWord using a constant alpha.<br>
Alpha is encoded as 0 meaning 0.0, and 255 meaning 1.0.<br>
The blend produced is alpha*source + (1.0-alpha)*dest, with the<br>
computation being performed independently on each color component.<br>
This function could eventually blend into any depth destination,<br>
using the same color averaging and mapping as warpBlt.<br>
paintMode = true means do nothing if the source pixel value is zero."<br>
<br>
"This first implementation works with dest depths of 16 and 32 bits only.<br>
Normal color mapping will allow sources of lower depths in this case,<br>
and results can be mapped directly by truncation, so no extra color maps are needed.<br>
To allow storing into any depth will require subsequent addition of two other<br>
colormaps, as is the case with WarpBlt."<br>
<br>
| pixMask destShifted sourceShifted destPixVal rgbMask sourcePixVal unAlpha result pixBlend shift blend maskShifted bitsPerColor blendAG blendRB |<br>
<inline: false><br>
+ <returnTypeC: 'unsigned int'><br>
- <return: 'unsigned int'><br>
<var: #sourceWord type: 'unsigned int'><br>
<var: #destinationWord type: 'unsigned int'><br>
<var: #blendRB type: 'unsigned int'><br>
<var: #blendAG type: 'unsigned int'><br>
<var: #result type: 'unsigned int'><br>
<var: #sourceAlpha type: 'unsigned int'><br>
<var: #unAlpha type: 'unsigned int'><br>
+ <var: #sourceShifted type: 'unsigned int'><br>
+ <var: #destShifted type: 'unsigned int'><br>
+ <var: #maskShifted type: 'unsigned int'><br>
+ <var: #pixMask type: 'unsigned int'><br>
+ <var: #rgbMask type: 'unsigned int'><br>
+ <var: #pixBlend type: 'unsigned int'><br>
+ <var: #blend type: 'unsigned int'><br>
destDepth < 16 ifTrue: [^ destinationWord "no-op"].<br>
unAlpha := 255 - sourceAlpha.<br>
result := destinationWord.<br>
destPPW = 1 ifTrue:["32bpp blends include alpha"<br>
paintMode & (sourceWord = 0) "painting a transparent pixel" ifFalse:[<br>
<br>
blendRB := ((sourceWord bitAnd: 16rFF00FF) * sourceAlpha) +<br>
((destinationWord bitAnd: 16rFF00FF) * unAlpha) + 16rFF00FF. "blendRB red and blue"<br>
<br>
blendAG := ((sourceWord>> 8 bitAnd: 16rFF00FF) * sourceAlpha) +<br>
((destinationWord>>8 bitAnd: 16rFF00FF) * unAlpha) + 16rFF00FF. "blendRB alpha and green"<br>
<br>
blendRB := blendRB + (blendRB - 16r10001 >> 8 bitAnd: 16rFF00FF) >> 8 bitAnd: 16rFF00FF. "divide by 255"<br>
blendAG := blendAG + (blendAG - 16r10001 >> 8 bitAnd: 16rFF00FF) >> 8 bitAnd: 16rFF00FF.<br>
result := blendRB bitOr: blendAG<<8.<br>
].<br>
] ifFalse:[<br>
pixMask := maskTable at: destDepth.<br>
bitsPerColor := 5.<br>
rgbMask := 16r1F.<br>
maskShifted := destMask.<br>
destShifted := destinationWord.<br>
sourceShifted := sourceWord.<br>
1 to: destPPW do:[:j |<br>
sourcePixVal := sourceShifted bitAnd: pixMask.<br>
((maskShifted bitAnd: pixMask) = 0 "no effect if outside of dest rectangle"<br>
or: [paintMode & (sourcePixVal = 0) "or painting a transparent pixel"])<br>
ifFalse:<br>
[destPixVal := destShifted bitAnd: pixMask.<br>
pixBlend := 0.<br>
1 to: 3 do:<br>
[:i | shift := (i-1)*bitsPerColor.<br>
blend := (((sourcePixVal>>shift bitAnd: rgbMask) * sourceAlpha)<br>
+ ((destPixVal>>shift bitAnd: rgbMask) * unAlpha))<br>
+ 254 // 255 bitAnd: rgbMask.<br>
pixBlend := pixBlend bitOr: blend<<shift].<br>
result := (result bitAnd: (pixMask << (j-1*16)) bitInvert32)<br>
bitOr: pixBlend << (j-1*16)].<br>
maskShifted := maskShifted >> destDepth.<br>
sourceShifted := sourceShifted >> destDepth.<br>
destShifted := destShifted >> destDepth].<br>
].<br>
^ result<br>
!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>alphaBlendScaled:with: (in category 'combination rules') -----<br>
alphaBlendScaled: sourceWord with: destinationWord<br>
"Blend sourceWord with destinationWord using the alpha value from sourceWord.<br>
Alpha is encoded as 0 meaning 0.0, and 255 meaning 1.0.<br>
In contrast to alphaBlend:with: the color produced is<br>
<br>
srcColor + (1-srcAlpha) * dstColor<br>
<br>
e.g., it is assumed that the source color is already scaled."<br>
| unAlpha rb ag |<br>
<inline: false> "Do NOT inline this into optimized loops"<br>
+ <returnTypeC: 'unsigned int'><br>
<var: #sourceWord type: 'unsigned int'><br>
<var: #destinationWord type: 'unsigned int'><br>
<var: #rb type: 'unsigned int'><br>
<var: #ag type: 'unsigned int'><br>
<var: #unAlpha type: 'unsigned int'><br>
unAlpha := 255 - (sourceWord >> 24). "High 8 bits of source pixel is source opacity (ARGB format)"<br>
rb := ((destinationWord bitAnd: 16rFF00FF) * unAlpha >> 8 bitAnd: 16rFF00FF) + (sourceWord bitAnd: 16rFF00FF). "blend red and blue components"<br>
ag := ((destinationWord>>8 bitAnd: 16rFF00FF) * unAlpha >> 8 bitAnd: 16rFF00FF) + (sourceWord>>8 bitAnd: 16rFF00FF). "blend alpha and green components"<br>
rb := (rb bitAnd: 16rFF00FF) bitOr: (rb bitAnd: 16r1000100) * 16rFF >> 8. "saturate red and blue components if there is a carry"<br>
ag := (ag bitAnd: 16rFF00FF) << 8 bitOr: (ag bitAnd: 16r1000100) * 16rFF. "saturate alpha and green components if there is a carry"<br>
^ag bitOr: rb "recompose"!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>alphaPaintConst:with: (in category 'combination rules') -----<br>
alphaPaintConst: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
<br>
sourceWord = 0 ifTrue: [^ destinationWord "opt for all-transparent source"].<br>
^ self alphaBlendConst: sourceWord with: destinationWord paintMode: true!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>alphaSourceBlendBits16 (in category 'inner loop') -----<br>
alphaSourceBlendBits16<br>
"This version assumes<br>
combinationRule = 34<br>
sourcePixSize = 32<br>
destPixSize = 16<br>
sourceForm ~= destForm.<br>
"<br>
| srcIndex dstIndex sourceWord srcAlpha destWord deltaX deltaY<br>
srcY dstY dstMask srcShift ditherBase ditherIndex ditherThreshold |<br>
<inline: false> "This particular method should be optimized in itself"<br>
+ <var: #sourceWord type: #'unsigned int'><br>
+ <var: #destWord type: #'unsigned int'><br>
+ <var: #dstMask type: #'unsigned int'><br>
deltaY := bbH + 1. "So we can pre-decrement"<br>
srcY := sy.<br>
dstY := dy.<br>
srcShift := (dx bitAnd: 1) * 16.<br>
destMSB ifTrue:[srcShift := 16 - srcShift].<br>
mask1 := 16rFFFF << (16 - srcShift).<br>
"This is the outer loop"<br>
[(deltaY := deltaY - 1) ~= 0] whileTrue:[<br>
srcIndex := sourceBits + (srcY * sourcePitch) + (sx * 4).<br>
dstIndex := destBits + (dstY * destPitch) + (dx // 2 * 4).<br>
ditherBase := (dstY bitAnd: 3) * 4.<br>
ditherIndex := (sx bitAnd: 3) - 1. "For pre-increment"<br>
deltaX := bbW + 1. "So we can pre-decrement"<br>
dstMask := mask1.<br>
dstMask = 16rFFFF ifTrue:[srcShift := 16] ifFalse:[srcShift := 0].<br>
<br>
"This is the inner loop"<br>
[(deltaX := deltaX - 1) ~= 0] whileTrue:[<br>
ditherThreshold := ditherMatrix4x4 at: ditherBase + (ditherIndex := ditherIndex + 1 bitAnd: 3).<br>
sourceWord := self srcLongAt: srcIndex.<br>
srcAlpha := sourceWord >> 24.<br>
srcAlpha = 255 ifTrue:[<br>
"Dither from 32 to 16 bit"<br>
sourceWord := self dither32To16: sourceWord threshold: ditherThreshold.<br>
sourceWord = 0<br>
ifTrue:[sourceWord := 1 << srcShift]<br>
ifFalse: [sourceWord := sourceWord << srcShift].<br>
"Store masked value"<br>
self dstLongAt: dstIndex put: sourceWord mask: dstMask.<br>
] ifFalse:[ "srcAlpha ~= 255"<br>
srcAlpha = 0 ifFalse:[ "0 < srcAlpha < 255"<br>
"If we have to mix colors then just copy a single word"<br>
destWord := self dstLongAt: dstIndex.<br>
destWord := destWord bitAnd: dstMask bitInvert32.<br>
destWord := destWord >> srcShift.<br>
"Expand from 16 to 32 bit by adding zero bits"<br>
destWord := (((destWord bitAnd: 16r7C00) bitShift: 9) bitOr:<br>
((destWord bitAnd: 16r3E0) bitShift: 6)) bitOr:<br>
(((destWord bitAnd: 16r1F) bitShift: 3) bitOr:<br>
16rFF000000).<br>
"Mix colors"<br>
sourceWord := self alphaBlendScaled: sourceWord with: destWord.<br>
"And dither"<br>
sourceWord := self dither32To16: sourceWord threshold: ditherThreshold.<br>
sourceWord = 0<br>
ifTrue:[sourceWord := 1 << srcShift]<br>
ifFalse:[sourceWord := sourceWord << srcShift].<br>
"Store back"<br>
self dstLongAt: dstIndex put: sourceWord mask: dstMask.<br>
].<br>
].<br>
srcIndex := srcIndex + 4.<br>
destMSB<br>
ifTrue:[srcShift = 0 ifTrue:[dstIndex := dstIndex + 4]]<br>
ifFalse:[srcShift = 0 ifFalse:[dstIndex := dstIndex + 4]].<br>
srcShift := srcShift bitXor: 16. "Toggle between 0 and 16"<br>
dstMask := dstMask bitInvert32. "Mask other half word"<br>
].<br>
srcY := srcY + 1.<br>
dstY := dstY + 1.<br>
].!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>alphaSourceBlendBits32 (in category 'inner loop') -----<br>
alphaSourceBlendBits32<br>
"This version assumes<br>
combinationRule = 34<br>
sourcePixSize = destPixSize = 32<br>
sourceForm ~= destForm.<br>
Note: The inner loop has been optimized for dealing<br>
with the special cases of srcAlpha = 0.0 and srcAlpha = 1.0<br>
"<br>
| srcIndex dstIndex sourceWord srcAlpha destWord deltaX deltaY srcY dstY |<br>
<inline: false> "This particular method should be optimized in itself"<br>
+ <var: #sourceWord type: #'unsigned int'><br>
+ <var: #destWord type: #'unsigned int'><br>
<br>
"Give the compile a couple of hints"<br>
<br>
"The following should be declared as pointers so the compiler will<br>
notice that they're used for accessing memory locations<br>
(good to know on an Intel architecture) but then the increments<br>
would be different between ST code and C code so must hope the<br>
compiler notices what happens (MS Visual C does)"<br>
<br>
deltaY := bbH + 1. "So we can pre-decrement"<br>
srcY := sy.<br>
dstY := dy.<br>
<br>
"This is the outer loop"<br>
[(deltaY := deltaY - 1) ~= 0] whileTrue:[<br>
srcIndex := sourceBits + (srcY * sourcePitch) + (sx * 4).<br>
dstIndex := destBits + (dstY * destPitch) + (dx * 4).<br>
deltaX := bbW + 1. "So we can pre-decrement"<br>
<br>
"This is the inner loop"<br>
[(deltaX := deltaX - 1) ~= 0] whileTrue:[<br>
sourceWord := self srcLongAt: srcIndex.<br>
srcAlpha := sourceWord >> 24.<br>
srcAlpha = 255 ifTrue:[<br>
self dstLongAt: dstIndex put: sourceWord.<br>
srcIndex := srcIndex + 4.<br>
dstIndex := dstIndex + 4.<br>
"Now copy as many words as possible with alpha = 255"<br>
[(deltaX := deltaX - 1) ~= 0 and:[<br>
(sourceWord := self srcLongAt: srcIndex) >> 24 = 255]]<br>
whileTrue:[<br>
self dstLongAt: dstIndex put: sourceWord.<br>
srcIndex := srcIndex + 4.<br>
dstIndex := dstIndex + 4.<br>
].<br>
"Adjust deltaX"<br>
deltaX := deltaX + 1.<br>
] ifFalse:[ "srcAlpha ~= 255"<br>
srcAlpha = 0 ifTrue:[<br>
srcIndex := srcIndex + 4.<br>
dstIndex := dstIndex + 4.<br>
"Now skip as many words as possible,"<br>
[(deltaX := deltaX - 1) ~= 0 and:[<br>
(sourceWord := self srcLongAt: srcIndex) >> 24 = 0]]<br>
whileTrue:[<br>
srcIndex := srcIndex + 4.<br>
dstIndex := dstIndex + 4.<br>
].<br>
"Adjust deltaX"<br>
deltaX := deltaX + 1.<br>
] ifFalse:[ "0 < srcAlpha < 255"<br>
"If we have to mix colors then just copy a single word"<br>
destWord := self dstLongAt: dstIndex.<br>
destWord := self alphaBlendScaled: sourceWord with: destWord.<br>
self dstLongAt: dstIndex put: destWord.<br>
srcIndex := srcIndex + 4.<br>
dstIndex := dstIndex + 4.<br>
].<br>
].<br>
].<br>
srcY := srcY + 1.<br>
dstY := dstY + 1.<br>
].!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>alphaSourceBlendBits8 (in category 'inner loop') -----<br>
alphaSourceBlendBits8<br>
"This version assumes<br>
combinationRule = 34<br>
sourcePixSize = 32<br>
destPixSize = 8<br>
sourceForm ~= destForm.<br>
Note: This is not real blending since we don't have the source colors available.<br>
"<br>
| srcIndex dstIndex sourceWord srcAlpha destWord deltaX deltaY<br>
srcY dstY dstMask srcShift adjust mappingTable mapperFlags |<br>
<inline: false><br>
<var: #mappingTable type:'unsigned int *'><br>
+ <var: #sourceWord type: #'unsigned int'><br>
+ <var: #destWord type: #'unsigned int'><br>
+ <var: #dstMask type: #'unsigned int'><br>
mappingTable := self default8To32Table.<br>
mapperFlags := cmFlags bitAnd: ColorMapNewStyle bitInvert32.<br>
deltaY := bbH + 1. "So we can pre-decrement"<br>
srcY := sy.<br>
dstY := dy.<br>
mask1 := ((dx bitAnd: 3) * 8).<br>
destMSB ifTrue:[mask1 := 24 - mask1].<br>
mask2 := AllOnes bitXor:(16rFF << mask1).<br>
(dx bitAnd: 1) = 0<br>
ifTrue:[adjust := 0]<br>
ifFalse:[adjust := 16r1F1F1F1F].<br>
(dy bitAnd: 1) = 0<br>
ifTrue:[adjust := adjust bitXor: 16r1F1F1F1F].<br>
"This is the outer loop"<br>
[(deltaY := deltaY - 1) ~= 0] whileTrue:[<br>
adjust := adjust bitXor: 16r1F1F1F1F.<br>
srcIndex := sourceBits + (srcY * sourcePitch) + (sx * 4).<br>
dstIndex := destBits + (dstY * destPitch) + (dx // 4 * 4).<br>
deltaX := bbW + 1. "So we can pre-decrement"<br>
srcShift := mask1.<br>
dstMask := mask2.<br>
<br>
"This is the inner loop"<br>
[(deltaX := deltaX - 1) ~= 0] whileTrue:[<br>
sourceWord := ((self srcLongAt: srcIndex) bitAnd: (adjust bitInvert32)) + adjust.<br>
srcAlpha := sourceWord >> 24.<br>
srcAlpha > 31 ifTrue:["Everything below 31 is transparent"<br>
srcAlpha < 224 ifTrue:["Everything above 224 is opaque"<br>
destWord := self dstLongAt: dstIndex.<br>
destWord := destWord bitAnd: dstMask bitInvert32.<br>
destWord := destWord >> srcShift.<br>
destWord := mappingTable at: destWord.<br>
sourceWord := self alphaBlendScaled: sourceWord with: destWord.<br>
].<br>
sourceWord := self mapPixel: sourceWord flags: mapperFlags.<br>
sourceWord := sourceWord << srcShift.<br>
"Store back"<br>
self dstLongAt: dstIndex put: sourceWord mask: dstMask.<br>
].<br>
srcIndex := srcIndex + 4.<br>
destMSB ifTrue:[<br>
srcShift = 0<br>
ifTrue:[dstIndex := dstIndex + 4.<br>
srcShift := 24.<br>
dstMask := 16r00FFFFFF]<br>
ifFalse:[srcShift := srcShift - 8.<br>
dstMask := (dstMask >> 8) bitOr: 16rFF000000].<br>
] ifFalse:[<br>
srcShift = 24<br>
ifTrue:[dstIndex := dstIndex + 4.<br>
srcShift := 0.<br>
dstMask := 16rFFFFFF00]<br>
ifFalse:[srcShift := srcShift + 8.<br>
dstMask := dstMask << 8 bitOr: 255].<br>
].<br>
adjust := adjust bitXor: 16r1F1F1F1F.<br>
].<br>
srcY := srcY + 1.<br>
dstY := dstY + 1.<br>
].!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>bitAnd:with: (in category 'combination rules') -----<br>
bitAnd: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
^sourceWord bitAnd: destinationWord!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>bitAndInvert:with: (in category 'combination rules') -----<br>
bitAndInvert: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
^sourceWord bitAnd: destinationWord bitInvert32!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>bitInvertAnd:with: (in category 'combination rules') -----<br>
bitInvertAnd: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
^sourceWord bitInvert32 bitAnd: destinationWord!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>bitInvertAndInvert:with: (in category 'combination rules') -----<br>
bitInvertAndInvert: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
^sourceWord bitInvert32 bitAnd: destinationWord bitInvert32!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>bitInvertDestination:with: (in category 'combination rules') -----<br>
bitInvertDestination: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
^destinationWord bitInvert32!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>bitInvertOr:with: (in category 'combination rules') -----<br>
bitInvertOr: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
^sourceWord bitInvert32 bitOr: destinationWord!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>bitInvertOrInvert:with: (in category 'combination rules') -----<br>
bitInvertOrInvert: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
^sourceWord bitInvert32 bitOr: destinationWord bitInvert32!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>bitInvertSource:with: (in category 'combination rules') -----<br>
bitInvertSource: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
^sourceWord bitInvert32!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>bitInvertXor:with: (in category 'combination rules') -----<br>
bitInvertXor: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
^sourceWord bitInvert32 bitXor: destinationWord!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>bitOr:with: (in category 'combination rules') -----<br>
bitOr: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
^sourceWord bitOr: destinationWord!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>bitOrInvert:with: (in category 'combination rules') -----<br>
bitOrInvert: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
^sourceWord bitOr: destinationWord bitInvert32!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>bitXor:with: (in category 'combination rules') -----<br>
bitXor: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
^sourceWord bitXor: destinationWord!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>clearWord:with: (in category 'combination rules') -----<br>
+ clearWord: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
- clearWord: source with: destination<br>
^ 0!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>copyLoop (in category 'inner loop') -----<br>
copyLoop<br>
| prevWord thisWord skewWord halftoneWord mergeWord hInc y unskew skewMask notSkewMask mergeFnwith destWord |<br>
"This version of the inner loop assumes noSource = false."<br>
<inline: false><br>
+ <var: #mergeFnwith declareC: 'unsigned int (*mergeFnwith)(unsigned int, unsigned int)'><br>
+ <var: #prevWord type: #'unsigned int'><br>
+ <var: #thisWord type: #'unsigned int'><br>
+ <var: #skewWord type: #'unsigned int'><br>
+ <var: #halftoneWord type: #'unsigned int'><br>
+ <var: #mergeWord type: #'unsigned int'><br>
+ <var: #destWord type: #'unsigned int'><br>
+ <var: #skewMask type: #'unsigned int'><br>
+ <var: #notSkewMask type: #'unsigned int'><br>
+ mergeFnwith := self cCoerce: (opTable at: combinationRule+1) to: 'unsigned int (*)(unsigned int, unsigned int)'.<br>
- <var: #mergeFnwith declareC: 'sqInt (*mergeFnwith)(sqInt, sqInt)'><br>
- mergeFnwith := self cCoerce: (opTable at: combinationRule+1) to: 'sqInt (*)(sqInt, sqInt)'.<br>
mergeFnwith. "null ref for compiler"<br>
<br>
hInc := hDir*4. "Byte delta"<br>
"degenerate skew fixed for Sparc. 10/20/96 ikp"<br>
skew == -32<br>
ifTrue: [skew := unskew := skewMask := 0]<br>
ifFalse: [skew < 0<br>
ifTrue:<br>
[unskew := skew+32.<br>
skewMask := AllOnes << (0-skew)]<br>
ifFalse:<br>
[skew = 0<br>
ifTrue:<br>
[unskew := 0.<br>
skewMask := AllOnes]<br>
ifFalse:<br>
[unskew := skew-32.<br>
skewMask := AllOnes >> skew]]].<br>
notSkewMask := skewMask bitInvert32.<br>
noHalftone<br>
ifTrue: [halftoneWord := AllOnes. halftoneHeight := 0]<br>
ifFalse: [halftoneWord := self halftoneAt: 0].<br>
<br>
y := dy.<br>
1 to: bbH do: "here is the vertical loop"<br>
[ :i |<br>
halftoneHeight > 1 ifTrue: "Otherwise, its always the same"<br>
[halftoneWord := self halftoneAt: y.<br>
y := y + vDir].<br>
preload ifTrue:<br>
["load the 64-bit shifter"<br>
prevWord := self srcLongAt: sourceIndex.<br>
self incSrcIndex: hInc]<br>
ifFalse:<br>
[prevWord := 0].<br>
<br>
"Note: the horizontal loop has been expanded into three parts for speed:"<br>
<br>
"This first section requires masking of the destination store..."<br>
destMask := mask1.<br>
thisWord := self srcLongAt: sourceIndex. "pick up next word"<br>
self incSrcIndex: hInc.<br>
skewWord := ((prevWord bitAnd: notSkewMask) bitShift: unskew)<br>
bitOr: "32-bit rotate"<br>
((thisWord bitAnd: skewMask) bitShift: skew).<br>
prevWord := thisWord.<br>
destWord := self dstLongAt: destIndex.<br>
mergeWord := self mergeFn: (skewWord bitAnd: halftoneWord) with: destWord.<br>
destWord := (destMask bitAnd: mergeWord) bitOr:<br>
(destWord bitAnd: destMask bitInvert32).<br>
self dstLongAt: destIndex put: destWord.<br>
self incDestIndex: hInc.<br>
<br>
"This central horizontal loop requires no store masking"<br>
destMask := AllOnes.<br>
combinationRule = 3<br>
ifTrue: [(skew = 0) & (halftoneWord = AllOnes)<br>
ifTrue:<br>
["Very special inner loop for STORE mode with no skew -- just move words"<br>
hDir = -1<br>
ifTrue: ["Woeful patch: revert to older code for hDir = -1"<br>
2 to: nWords-1 do:<br>
[ :word |<br>
thisWord := self srcLongAt: sourceIndex.<br>
self incSrcIndex: hInc.<br>
self dstLongAt: destIndex put: thisWord.<br>
self incDestIndex: hInc]]<br>
ifFalse: [2 to: nWords-1 do:<br>
[ :word | "Note loop starts with prevWord loaded (due to preload)"<br>
self dstLongAt: destIndex put: prevWord.<br>
self incDestIndex: hInc.<br>
prevWord := self srcLongAt: sourceIndex.<br>
self incSrcIndex: hInc]]]<br>
ifFalse:<br>
["Special inner loop for STORE mode -- no need to call merge"<br>
2 to: nWords-1 do:<br>
[ :word |<br>
thisWord := self srcLongAt: sourceIndex.<br>
self incSrcIndex: hInc.<br>
skewWord := ((prevWord bitAnd: notSkewMask) bitShift: unskew)<br>
bitOr: "32-bit rotate"<br>
((thisWord bitAnd: skewMask) bitShift: skew).<br>
prevWord := thisWord.<br>
self dstLongAt: destIndex put: (skewWord bitAnd: halftoneWord).<br>
self incDestIndex: hInc]]<br>
] ifFalse: [2 to: nWords-1 do: "Normal inner loop does merge:"<br>
[ :word |<br>
thisWord := self srcLongAt: sourceIndex. "pick up next word"<br>
self incSrcIndex: hInc.<br>
skewWord := ((prevWord bitAnd: notSkewMask) bitShift: unskew)<br>
bitOr: "32-bit rotate"<br>
((thisWord bitAnd: skewMask) bitShift: skew).<br>
prevWord := thisWord.<br>
mergeWord := self mergeFn: (skewWord bitAnd: halftoneWord)<br>
with: (self dstLongAt: destIndex).<br>
self dstLongAt: destIndex put: mergeWord.<br>
self incDestIndex: hInc]<br>
].<br>
<br>
"This last section, if used, requires masking of the destination store..."<br>
nWords > 1 ifTrue:<br>
[destMask := mask2.<br>
thisWord := self srcLongAt: sourceIndex. "pick up next word"<br>
self incSrcIndex: hInc.<br>
skewWord := ((prevWord bitAnd: notSkewMask) bitShift: unskew)<br>
bitOr: "32-bit rotate"<br>
((thisWord bitAnd: skewMask) bitShift: skew).<br>
destWord := self dstLongAt: destIndex.<br>
mergeWord := self mergeFn: (skewWord bitAnd: halftoneWord) with: destWord.<br>
destWord := (destMask bitAnd: mergeWord) bitOr:<br>
(destWord bitAnd: destMask bitInvert32).<br>
self dstLongAt: destIndex put: destWord.<br>
self incDestIndex: hInc].<br>
<br>
self incSrcIndex: sourceDelta.<br>
self incDestIndex: destDelta]!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>copyLoopNoSource (in category 'inner loop') -----<br>
copyLoopNoSource<br>
"Faster copyLoop when source not used. hDir and vDir are both<br>
positive, and perload and skew are unused"<br>
| halftoneWord mergeWord mergeFnwith destWord |<br>
<inline: false><br>
+ <var: #mergeFnwith declareC: 'unsigned int (*mergeFnwith)(unsigned int, unsigned int)'><br>
+ <var: #halftoneWord type: #'unsigned int'><br>
+ <var: #mergeWord type: #'unsigned int'><br>
+ <var: #destWord type: #'unsigned int'><br>
+ mergeFnwith := self cCoerce: (opTable at: combinationRule+1) to: 'unsigned int (*)(unsigned int, unsigned int)'.<br>
- <var: #mergeFnwith declareC: 'sqInt (*mergeFnwith)(sqInt, sqInt)'><br>
- mergeFnwith := self cCoerce: (opTable at: combinationRule+1) to: 'sqInt (*)(sqInt, sqInt)'.<br>
mergeFnwith. "null ref for compiler"<br>
<br>
1 to: bbH do: "here is the vertical loop"<br>
[ :i |<br>
noHalftone<br>
ifTrue: [halftoneWord := AllOnes]<br>
ifFalse: [halftoneWord := self halftoneAt: dy+i-1].<br>
<br>
"Note: the horizontal loop has been expanded into three parts for speed:"<br>
<br>
"This first section requires masking of the destination store..."<br>
destMask := mask1.<br>
destWord := self dstLongAt: destIndex.<br>
mergeWord := self mergeFn: halftoneWord<br>
with: destWord.<br>
destWord := (destMask bitAnd: mergeWord) bitOr:<br>
(destWord bitAnd: destMask bitInvert32).<br>
self dstLongAt: destIndex put: destWord.<br>
self incDestIndex: 4.<br>
<br>
"This central horizontal loop requires no store masking"<br>
destMask := AllOnes.<br>
combinationRule = 3 ifTrue: ["Special inner loop for STORE"<br>
destWord := halftoneWord.<br>
2 to: nWords-1 do:[ :word |<br>
self dstLongAt: destIndex put: destWord.<br>
self incDestIndex: 4].<br>
] ifFalse:[ "Normal inner loop does merge"<br>
2 to: nWords-1 do:[ :word | "Normal inner loop does merge"<br>
destWord := self dstLongAt: destIndex.<br>
mergeWord := self mergeFn: halftoneWord with: destWord.<br>
self dstLongAt: destIndex put: mergeWord.<br>
self incDestIndex: 4].<br>
].<br>
<br>
"This last section, if used, requires masking of the destination store..."<br>
nWords > 1 ifTrue:<br>
[destMask := mask2.<br>
destWord := self dstLongAt: destIndex.<br>
mergeWord := self mergeFn: halftoneWord with: destWord.<br>
destWord := (destMask bitAnd: mergeWord) bitOr:<br>
(destWord bitAnd: destMask bitInvert32).<br>
self dstLongAt: destIndex put: destWord.<br>
self incDestIndex: 4].<br>
<br>
self incDestIndex: destDelta]!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>copyLoopPixMap (in category 'inner loop') -----<br>
copyLoopPixMap<br>
"This version of the inner loop maps source pixels<br>
to a destination form with different depth. Because it is already<br>
unweildy, the loop is not unrolled as in the other versions.<br>
Preload, skew and skewMask are all overlooked, since pickSourcePixels<br>
delivers its destination word already properly aligned.<br>
Note that pickSourcePixels could be copied in-line at the top of<br>
the horizontal loop, and some of its inits moved out of the loop."<br>
"ar 12/7/1999:<br>
The loop has been rewritten to use only one pickSourcePixels call.<br>
The idea is that the call itself could be inlined. If we decide not<br>
to inline pickSourcePixels we could optimize the loop instead."<br>
| skewWord halftoneWord mergeWord scrStartBits nSourceIncs startBits endBits sourcePixMask destPixMask mergeFnwith nPix srcShift dstShift destWord words srcShiftInc dstShiftInc dstShiftLeft mapperFlags |<br>
<inline: false><br>
+ <var: #mergeFnwith declareC: 'unsigned int (*mergeFnwith)(unsigned int, unsigned int)'><br>
+ <var: #skewWord type: #'unsigned int'><br>
+ <var: #halftoneWord type: #'unsigned int'><br>
+ <var: #mergeWord type: #'unsigned int'><br>
+ <var: #destWord type: #'unsigned int'><br>
+ <var: #sourcePixMask type: #'unsigned int'><br>
+ <var: #destPixMask type: #'unsigned int'><br>
+ mergeFnwith := self cCoerce: (opTable at: combinationRule+1) to: 'unsigned int (*)(unsigned int, unsigned int)'.<br>
- <var: #mergeFnwith declareC: 'sqInt (*mergeFnwith)(sqInt, sqInt)'><br>
- mergeFnwith := self cCoerce: (opTable at: combinationRule+1) to: 'sqInt (*)(sqInt, sqInt)'.<br>
mergeFnwith. "null ref for compiler"<br>
<br>
"Additional inits peculiar to unequal source and dest pix size..."<br>
sourcePPW := 32//sourceDepth.<br>
sourcePixMask := maskTable at: sourceDepth.<br>
destPixMask := maskTable at: destDepth.<br>
mapperFlags := cmFlags bitAnd: ColorMapNewStyle bitInvert32.<br>
sourceIndex := sourceBits +<br>
(sy * sourcePitch) + ((sx // sourcePPW) *4).<br>
scrStartBits := sourcePPW - (sx bitAnd: sourcePPW-1).<br>
bbW < scrStartBits<br>
ifTrue: [nSourceIncs := 0]<br>
ifFalse: [nSourceIncs := (bbW - scrStartBits)//sourcePPW + 1].<br>
sourceDelta := sourcePitch - (nSourceIncs * 4).<br>
<br>
"Note following two items were already calculated in destmask setup!!"<br>
startBits := destPPW - (dx bitAnd: destPPW-1).<br>
endBits := ((dx + bbW - 1) bitAnd: destPPW-1) + 1.<br>
<br>
bbW < startBits ifTrue:[startBits := bbW].<br>
<br>
"Precomputed shifts for pickSourcePixels"<br>
srcShift := ((sx bitAnd: sourcePPW - 1) * sourceDepth).<br>
dstShift := ((dx bitAnd: destPPW - 1) * destDepth).<br>
srcShiftInc := sourceDepth.<br>
dstShiftInc := destDepth.<br>
dstShiftLeft := 0.<br>
sourceMSB ifTrue:[<br>
srcShift := 32 - sourceDepth - srcShift.<br>
srcShiftInc := 0 - srcShiftInc].<br>
destMSB ifTrue:[<br>
dstShift := 32 - destDepth - dstShift.<br>
dstShiftInc := 0 - dstShiftInc.<br>
dstShiftLeft := 32 - destDepth].<br>
<br>
1 to: bbH do: "here is the vertical loop"<br>
[ :i |<br>
"*** is it possible at all that noHalftone == false? ***"<br>
noHalftone<br>
ifTrue:[halftoneWord := AllOnes]<br>
ifFalse: [halftoneWord := self halftoneAt: dy+i-1].<br>
"setup first load"<br>
srcBitShift := srcShift.<br>
dstBitShift := dstShift.<br>
destMask := mask1.<br>
nPix := startBits.<br>
"Here is the horizontal loop..."<br>
words := nWords.<br>
["pick up the word"<br>
skewWord := self pickSourcePixels: nPix flags: mapperFlags<br>
srcMask: sourcePixMask destMask: destPixMask<br>
srcShiftInc: srcShiftInc dstShiftInc: dstShiftInc.<br>
"align next word to leftmost pixel"<br>
dstBitShift := dstShiftLeft.<br>
<br>
destMask = AllOnes ifTrue:["avoid read-modify-write"<br>
mergeWord := self mergeFn: (skewWord bitAnd: halftoneWord)<br>
with: (self dstLongAt: destIndex).<br>
self dstLongAt: destIndex put: (destMask bitAnd: mergeWord).<br>
] ifFalse:[ "General version using dest masking"<br>
destWord := self dstLongAt: destIndex.<br>
mergeWord := self mergeFn: (skewWord bitAnd: halftoneWord)<br>
with: (destWord bitAnd: destMask).<br>
destWord := (destMask bitAnd: mergeWord) bitOr:<br>
(destWord bitAnd: destMask bitInvert32).<br>
self dstLongAt: destIndex put: destWord.<br>
].<br>
self incDestIndex: 4.<br>
words = 2 "e.g., is the next word the last word?"<br>
ifTrue:["set mask for last word in this row"<br>
destMask := mask2.<br>
nPix := endBits]<br>
ifFalse:["use fullword mask for inner loop"<br>
destMask := AllOnes.<br>
nPix := destPPW].<br>
(words := words - 1) = 0] whileFalse.<br>
"--- end of inner loop ---"<br>
self incSrcIndex: sourceDelta.<br>
self incDestIndex: destDelta]<br>
!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>destinationWord:with: (in category 'combination rules') -----<br>
destinationWord: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
^destinationWord!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>dither32To16:threshold: (in category 'pixel mapping') -----<br>
dither32To16: srcWord threshold: ditherValue<br>
"Dither the given 32bit word to 16 bit. Ignore alpha."<br>
| addThreshold |<br>
<inline: true> "You bet"<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #srcWord type: 'unsigned int'><br>
addThreshold := ditherValue bitShift: 8.<br>
^((dither8Lookup at: (addThreshold+((srcWord bitShift: -16) bitAnd: 255))) bitShift: 10) +<br>
((dither8Lookup at: (addThreshold+((srcWord bitShift: -8) bitAnd: 255))) bitShift: 5) +<br>
(dither8Lookup at: (addThreshold+(srcWord bitAnd: 255))).<br>
!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>expensiveDither32To16:threshold: (in category 'pixel mapping') -----<br>
expensiveDither32To16: srcWord threshold: ditherValue<br>
"Dither the given 32bit word to 16 bit. Ignore alpha."<br>
| pv threshold value out |<br>
<inline: true> "You bet"<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #srcWord type: 'unsigned int'><br>
pv := srcWord bitAnd: 255.<br>
threshold := ditherThresholds16 at: (pv bitAnd: 7).<br>
value := ditherValues16 at: (pv bitShift: -3).<br>
ditherValue < threshold<br>
ifTrue:[out := value + 1]<br>
ifFalse:[out := value].<br>
pv := (srcWord bitShift: -8) bitAnd: 255.<br>
threshold := ditherThresholds16 at: (pv bitAnd: 7).<br>
value := ditherValues16 at: (pv bitShift: -3).<br>
ditherValue < threshold<br>
ifTrue:[out := out bitOr: (value+1 bitShift:5)]<br>
ifFalse:[out := out bitOr: (value bitShift: 5)].<br>
pv := (srcWord bitShift: -16) bitAnd: 255.<br>
threshold := ditherThresholds16 at: (pv bitAnd: 7).<br>
value := ditherValues16 at: (pv bitShift: -3).<br>
ditherValue < threshold<br>
ifTrue:[out := out bitOr: (value+1 bitShift:10)]<br>
ifFalse:[out := out bitOr: (value bitShift: 10)].<br>
^out!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>fixAlpha:with: (in category 'combination rules') -----<br>
fixAlpha: sourceWord with: destinationWord<br>
"For any non-zero pixel value in destinationWord with zero alpha channel take the alpha from sourceWord and fill it in. Intended for fixing alpha channels left at zero during 16->32 bpp conversions."<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
destDepth = 32 ifFalse:[^destinationWord]. "no-op for non 32bpp"<br>
destinationWord = 0 ifTrue:[^0].<br>
(destinationWord bitAnd: 16rFF000000) = 0 ifFalse:[^destinationWord].<br>
^destinationWord bitOr: (sourceWord bitAnd: 16rFF000000)<br>
!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>merge:with: (in category 'combination rules') -----<br>
merge: sourceWord with: destinationWord<br>
| mergeFnwith |<br>
"Sender warpLoop is too big to include this in-line"<br>
+ <var: #mergeFnwith declareC: 'unsigned int (*mergeFnwith)(unsigned int, unsigned int)'><br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
+ mergeFnwith := self cCoerce: (opTable at: combinationRule+1) to: 'unsigned int (*)(unsigned int, unsigned int)'.<br>
- <var: #mergeFnwith declareC: 'sqInt (*mergeFnwith)(sqInt, sqInt)'><br>
- mergeFnwith := self cCoerce: (opTable at: combinationRule+1) to: 'sqInt (*)(sqInt, sqInt)'.<br>
mergeFnwith. "null ref for compiler"<br>
<br>
^ self mergeFn: sourceWord with: destinationWord!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>partitionedAND:to:nBits:nPartitions: (in category 'combination rules') -----<br>
partitionedAND: word1 to: word2 nBits: nBits nPartitions: nParts<br>
"AND word1 to word2 as nParts partitions of nBits each.<br>
Any field of word1 not all-ones is treated as all-zeroes.<br>
Used for erasing, eg, brush shapes prior to ORing in a color"<br>
| mask result |<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #word1 type: 'unsigned int'><br>
+ <var: #word2 type: 'unsigned int'><br>
+ <var: #result type: 'unsigned int'><br>
mask := maskTable at: nBits. "partition mask starts at the right"<br>
result := 0.<br>
1 to: nParts do:<br>
[:i |<br>
(word1 bitAnd: mask) = mask<br>
ifTrue: [result := result bitOr: (word2 bitAnd: mask)].<br>
mask := mask << nBits "slide left to next partition"].<br>
^ result<br>
!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>partitionedAdd:to:nBits:componentMask:carryOverflowMask: (in category 'combination rules') -----<br>
partitionedAdd: word1 to: word2 nBits: nBits componentMask: componentMask carryOverflowMask: carryOverflowMask<br>
"Add word1 to word2 as nParts partitions of nBits each.<br>
This is useful for packed pixels, or packed colors"<br>
| carryOverflow sum w1 w2 |<br>
"Use unsigned int everywhere because it has a well known arithmetic model without undefined behavior w.r.t. overflow and shifts"<br>
+ <returnTypeC: 'unsigned int'><br>
<var: #word1 type: 'unsigned int'><br>
<var: #word2 type: 'unsigned int'><br>
<var: #w1 type: 'unsigned int'><br>
<var: #w2 type: 'unsigned int'><br>
<var: #componentMask type: 'unsigned int'><br>
<var: #carryOverflowMask type: 'unsigned int'><br>
<var: #carryOverflow type: 'unsigned int'><br>
<var: #sum type: 'unsigned int'><br>
w1 := word1 bitAnd: carryOverflowMask. "mask to remove high bit of each component"<br>
w2 := word2 bitAnd: carryOverflowMask.<br>
sum := (word1 bitXor: w1)+(word2 bitXor: w2). "sum without high bit to avoid overflowing over next component"<br>
carryOverflow := (w1 bitAnd: w2) bitOr: ((w1 bitOr: w2) bitAnd: sum). "detect overflow condition for saturating"<br>
^((sum bitXor: w1)bitXor:w2) "sum high bit without overflow"<br>
bitOr: carryOverflow>>(nBits-1) * componentMask "saturate in case of overflow"!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>partitionedMax:with:nBits:nPartitions: (in category 'combination rules') -----<br>
partitionedMax: word1 with: word2 nBits: nBits nPartitions: nParts<br>
"Max word1 to word2 as nParts partitions of nBits each"<br>
| mask result |<br>
"In C, most arithmetic operations answer the same bit pattern regardless of the operands being signed or unsigned ints<br>
(this is due to the way 2's complement numbers work). However, comparisions might fail. Add the proper declaration of<br>
words as unsigned int in those cases where comparisions are done (jmv)"<br>
+ <returnTypeC: 'unsigned int'><br>
<var: #word1 type: 'unsigned int'><br>
<var: #word2 type: 'unsigned int'><br>
<var: #mask type: 'unsigned int'><br>
<var: #result type: 'unsigned int'><br>
mask := maskTable at: nBits. "partition mask starts at the right"<br>
result := 0.<br>
1 to: nParts do:<br>
[:i |<br>
result := result bitOr: ((word2 bitAnd: mask) max: (word1 bitAnd: mask)).<br>
mask := mask << nBits "slide left to next partition"].<br>
^ result<br>
!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>partitionedMin:with:nBits:nPartitions: (in category 'combination rules') -----<br>
partitionedMin: word1 with: word2 nBits: nBits nPartitions: nParts<br>
"Min word1 to word2 as nParts partitions of nBits each"<br>
| mask result |<br>
"In C, most arithmetic operations answer the same bit pattern regardless of the operands being signed or unsigned ints<br>
(this is due to the way 2's complement numbers work). However, comparisions might fail. Add the proper declaration of<br>
words as unsigned int in those cases where comparisions are done (jmv)"<br>
+ <returnTypeC: 'unsigned int'><br>
<var: #word1 type: 'unsigned int'><br>
<var: #word2 type: 'unsigned int'><br>
<var: #mask type: 'unsigned int'><br>
<var: #result type: 'unsigned int'><br>
mask := maskTable at: nBits. "partition mask starts at the right"<br>
result := 0.<br>
1 to: nParts do:<br>
[:i |<br>
result := result bitOr: ((word2 bitAnd: mask) min: (word1 bitAnd: mask)).<br>
mask := mask << nBits "slide left to next partition"].<br>
^ result<br>
!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>partitionedMul:with:nBits:nPartitions: (in category 'combination rules') -----<br>
partitionedMul: word1 with: word2 nBits: nBits nPartitions: nParts<br>
"Multiply word1 with word2 as nParts partitions of nBits each.<br>
This is useful for packed pixels, or packed colors.<br>
Bug in loop version when non-white background"<br>
<br>
| sMask product result dMask |<br>
"In C, integer multiplication might answer a wrong value if the unsigned values are declared as signed.<br>
This problem does not affect this method, because the most significant bit (i.e. the sign bit) will<br>
always be zero (jmv)"<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #word1 type: 'unsigned int'><br>
+ <var: #word2 type: 'unsigned int'><br>
+ <var: #sMask type: 'unsigned int'><br>
+ <var: #dMask type: 'unsigned int'><br>
+ <var: #result type: 'unsigned int'><br>
+ <var: #product type: 'unsigned int'><br>
sMask := maskTable at: nBits. "partition mask starts at the right"<br>
dMask := sMask << nBits.<br>
result := (((word1 bitAnd: sMask)+1) * ((word2 bitAnd: sMask)+1) - 1<br>
bitAnd: dMask) >> nBits. "optimized first step"<br>
nParts = 1<br>
ifTrue: [ ^result ].<br>
product := (((word1>>nBits bitAnd: sMask)+1) * ((word2>>nBits bitAnd: sMask)+1) - 1 bitAnd: dMask).<br>
result := result bitOr: product.<br>
nParts = 2<br>
ifTrue: [ ^result ].<br>
product := (((word1>>(2*nBits) bitAnd: sMask)+1) * ((word2>>(2*nBits) bitAnd: sMask)+1) - 1 bitAnd: dMask).<br>
result := result bitOr: product << nBits.<br>
nParts = 3<br>
ifTrue: [ ^result ].<br>
product := (((word1>>(3*nBits) bitAnd: sMask)+1) * ((word2>>(3*nBits) bitAnd: sMask)+1) - 1 bitAnd: dMask).<br>
result := result bitOr: product << (2*nBits).<br>
^ result<br>
<br>
" | sMask product result dMask |<br>
sMask := maskTable at: nBits. 'partition mask starts at the right'<br>
dMask := sMask << nBits.<br>
result := (((word1 bitAnd: sMask)+1) * ((word2 bitAnd: sMask)+1) - 1<br>
bitAnd: dMask) >> nBits. 'optimized first step'<br>
nBits to: nBits * (nParts-1) by: nBits do: [:ofs |<br>
product := (((word1>>ofs bitAnd: sMask)+1) * ((word2>>ofs bitAnd: sMask)+1) - 1 bitAnd: dMask).<br>
result := result bitOr: (product bitAnd: dMask) << (ofs-nBits)].<br>
^ result"!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>partitionedRgbComponentAlpha:dest:nBits:nPartitions: (in category 'combination rules') -----<br>
partitionedRgbComponentAlpha: sourceWord dest: destWord nBits: nBits nPartitions: nParts<br>
| mask result p1 p2 v |<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destWord type: 'unsigned int'><br>
+ <var: #p1 type: 'unsigned int'><br>
+ <var: #p2 type: 'unsigned int'><br>
+ <var: #mask type: 'unsigned int'><br>
+ <var: #result type: 'unsigned int'><br>
mask := maskTable at: nBits. "partition mask starts at the right"<br>
result := 0.<br>
1 to: nParts do:<br>
[:i |<br>
p1 := (sourceWord bitAnd: mask) >> ((i - 1)*nBits).<br>
p2 := (destWord bitAnd: mask) >> ((i - 1)*nBits).<br>
nBits = 32<br>
ifFalse:[<br>
nBits = 16<br>
ifTrue:[<br>
p1 := (self rgbMap16To32: p1) bitOr: 16rFF000000.<br>
p2 := (self rgbMap16To32: p2) bitOr: 16rFF000000]<br>
ifFalse:[<br>
p1 := (self rgbMap: p1 from: nBits to: 32) bitOr: 16rFF000000.<br>
p2 := (self rgbMap: p2 from: nBits to: 32) bitOr: 16rFF000000.]].<br>
v := self rgbComponentAlpha32: p1 with: p2.<br>
nBits = 32<br>
ifFalse:[<br>
v := self rgbMap: v from: 32 to: nBits].<br>
result := result bitOr: (v << ((i - 1)*nBits)).<br>
mask := mask << nBits "slide left to next partition"].<br>
^ result<br>
!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>partitionedSub:from:nBits:nPartitions: (in category 'combination rules') -----<br>
partitionedSub: word1 from: word2 nBits: nBits nPartitions: nParts<br>
"Subtract word1 from word2 as nParts partitions of nBits each.<br>
This is useful for packed pixels, or packed colors"<br>
| mask result p1 p2 |<br>
"In C, most arithmetic operations answer the same bit pattern regardless of the operands being signed or unsigned ints<br>
(this is due to the way 2's complement numbers work). However, comparisions might fail. Add the proper declaration of<br>
words as unsigned int in those cases where comparisions are done (jmv)"<br>
+ <returnTypeC: 'unsigned int'><br>
<var: #word1 type: 'unsigned int'><br>
<var: #word2 type: 'unsigned int'><br>
<var: #p1 type: 'unsigned int'><br>
<var: #p2 type: 'unsigned int'><br>
<var: #mask type: 'unsigned int'><br>
<var: #result type: 'unsigned int'><br>
mask := maskTable at: nBits. "partition mask starts at the right"<br>
result := 0.<br>
1 to: nParts do:<br>
[:i |<br>
p1 := word1 bitAnd: mask.<br>
p2 := word2 bitAnd: mask.<br>
p1 < p2 "result is really abs value of thedifference"<br>
ifTrue: [result := result bitOr: p2 - p1]<br>
ifFalse: [result := result bitOr: p1 - p2].<br>
mask := mask << nBits "slide left to next partition"].<br>
^ result<br>
!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>pickSourcePixels:flags:srcMask:destMask:srcShiftInc:dstShiftInc: (in category 'combination rules') -----<br>
pickSourcePixels: nPixels flags: mapperFlags srcMask: srcMask destMask: dstMask srcShiftInc: srcShiftInc dstShiftInc: dstShiftInc<br>
"Pick nPix pixels starting at srcBitIndex from the source, map by the<br>
color map, and justify them according to dstBitIndex in the resulting destWord."<br>
| sourceWord destWord sourcePix destPix srcShift dstShift nPix |<br>
<inline: true> "oh please"<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: #'unsigned int'><br>
+ <var: #destWord type: #'unsigned int'><br>
sourceWord := self srcLongAt: sourceIndex.<br>
destWord := 0.<br>
srcShift := srcBitShift. "Hint: Keep in register"<br>
dstShift := dstBitShift. "Hint: Keep in register"<br>
nPix := nPixels. "always > 0 so we can use do { } while(--nPix);"<br>
(mapperFlags = (ColorMapPresent bitOr: ColorMapIndexedPart)) ifTrue:[<br>
"a little optimization for (pretty crucial) blits using indexed lookups only"<br>
[ "grab, colormap and mix in pixel"<br>
sourcePix := sourceWord >> srcShift bitAnd: srcMask.<br>
destPix := cmLookupTable at: (sourcePix bitAnd: cmMask).<br>
destWord := destWord bitOr: (destPix bitAnd: dstMask) << dstShift.<br>
"adjust dest pix index"<br>
dstShift := dstShift + dstShiftInc.<br>
"adjust source pix index"<br>
((srcShift := srcShift + srcShiftInc) bitAnd: 16rFFFFFFE0) = 0 ifFalse:[<br>
sourceMSB ifTrue:[srcShift := srcShift + 32] ifFalse:[srcShift := srcShift - 32].<br>
sourceWord := self srcLongAt: (self incSrcIndex: 4)].<br>
(nPix := nPix - 1) = 0] whileFalse.<br>
] ifFalse:[<br>
[ "grab, colormap and mix in pixel"<br>
sourcePix := sourceWord >> srcShift bitAnd: srcMask.<br>
destPix := self mapPixel: sourcePix flags: mapperFlags.<br>
destWord := destWord bitOr: (destPix bitAnd: dstMask) << dstShift.<br>
"adjust dest pix index"<br>
dstShift := dstShift + dstShiftInc.<br>
"adjust source pix index"<br>
((srcShift := srcShift + srcShiftInc) bitAnd: 16rFFFFFFE0) = 0 ifFalse:[<br>
sourceMSB ifTrue:[srcShift := srcShift + 32] ifFalse:[srcShift := srcShift - 32].<br>
sourceWord := self srcLongAt: (self incSrcIndex: 4)].<br>
(nPix := nPix - 1) = 0] whileFalse.<br>
].<br>
srcBitShift := srcShift. "Store back"<br>
^destWord<br>
!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>pickWarpPixelAtX:y: (in category 'pixel mapping') -----<br>
pickWarpPixelAtX: xx y: yy<br>
"Pick a single pixel from the source for WarpBlt.<br>
Note: This method is crucial for WarpBlt speed w/o smoothing<br>
and still relatively important when smoothing is used."<br>
| x y srcIndex sourceWord sourcePix |<br>
<inline: true> "*please*"<br>
+ <returnTypeC: #'unsigned int'><br>
+ <var: #sourceWord type: #'unsigned int'><br>
<br>
"note: it would be much faster if we could just<br>
avoid these stupid tests for being inside sourceForm."<br>
(xx < 0 or:[yy < 0 or:[<br>
(x := xx >> BinaryPoint) >= sourceWidth or:[<br>
(y := yy >> BinaryPoint) >= sourceHeight]]]) ifTrue:[^0]. "out of bounds"<br>
<br>
"Fetch source word.<br>
Note: We should really update srcIndex with sx and sy so that<br>
we don't have to do the computation below. We might even be<br>
able to simplify the out of bounds test from above."<br>
srcIndex := sourceBits + (y * sourcePitch) + (x >> warpAlignShift * 4).<br>
sourceWord := self srcLongAt: srcIndex.<br>
<br>
"Extract pixel from word"<br>
srcBitShift := warpBitShiftTable at: (x bitAnd: warpAlignMask).<br>
sourcePix := sourceWord >> srcBitShift bitAnd: warpSrcMask.<br>
^sourcePix!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>pixClear:with: (in category 'combination rules') -----<br>
pixClear: sourceWord with: destinationWord<br>
"Clear all pixels in destinationWord for which the pixels of sourceWord have the same values. Used to clear areas of some constant color to zero."<br>
| mask result nBits pv |<br>
<inline: false><br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
+ <var: #mask type: 'unsigned int'><br>
+ <var: #pv type: 'unsigned int'><br>
+ <var: #result type: 'unsigned int'><br>
destDepth = 32 ifTrue:[<br>
sourceWord = destinationWord ifTrue:[^0] ifFalse:[^destinationWord].<br>
].<br>
nBits := destDepth.<br>
mask := maskTable at: nBits. "partition mask starts at the right"<br>
result := 0.<br>
1 to: destPPW do:[:i |<br>
pv := destinationWord bitAnd: mask.<br>
(sourceWord bitAnd: mask) = pv ifTrue:[pv := 0].<br>
result := result bitOr: pv.<br>
mask := mask << nBits "slide left to next partition"].<br>
^ result!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>pixMask:with: (in category 'combination rules') -----<br>
pixMask: sourceWord with: destinationWord<br>
<inline: false><br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
^ self partitionedAND: sourceWord bitInvert32 to: destinationWord<br>
nBits: destDepth nPartitions: destPPW!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>pixPaint:with: (in category 'combination rules') -----<br>
pixPaint: sourceWord with: destinationWord<br>
<inline: false><br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
sourceWord = 0 ifTrue: [^ destinationWord].<br>
^ sourceWord bitOr:<br>
(self partitionedAND: sourceWord bitInvert32 to: destinationWord<br>
nBits: destDepth nPartitions: destPPW)!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>pixSwap:with: (in category 'combination rules') -----<br>
pixSwap: sourceWord with: destWord<br>
"Swap the pixels in destWord"<br>
| result shift lowMask highMask |<br>
<inline: false><br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destWord type: 'unsigned int'><br>
+ <var: #lowMask type: 'unsigned int'><br>
+ <var: #highMask type: 'unsigned int'><br>
+ <var: #result type: 'unsigned int'><br>
destPPW = 1 ifTrue:[^destWord]. "a single pixel per word"<br>
result := 0.<br>
lowMask := (1 << destDepth) - 1. "mask low pixel"<br>
highMask := lowMask << (destPPW-1 * destDepth). "mask high pixel"<br>
shift := 32 - destDepth.<br>
result := result bitOr: (<br>
(destWord bitAnd: lowMask) << shift bitOr:<br>
(destWord bitAnd: highMask) >> shift).<br>
destPPW <= 2 ifTrue:[^result].<br>
2 to: destPPW // 2 do:[:i|<br>
lowMask := lowMask << destDepth.<br>
highMask := highMask >> destDepth.<br>
shift := shift - (destDepth * 2).<br>
result := result bitOr: (<br>
(destWord bitAnd: lowMask) << shift bitOr:<br>
(destWord bitAnd: highMask) >> shift)].<br>
^result!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>rgbAdd:with: (in category 'combination rules') -----<br>
rgbAdd: sourceWord with: destinationWord<br>
<inline: false><br>
+ <returnTypeC: 'unsigned int'><br>
<var: #sourceWord type: 'unsigned int'><br>
<var: #destinationWord type: 'unsigned int'><br>
<var: #carryOverflowMask type: 'unsigned int'><br>
<var: #componentMask type: 'unsigned int'><br>
| componentMask carryOverflowMask |<br>
destDepth < 16 ifTrue:<br>
["Add each pixel separately"<br>
componentMask := 1<<destDepth-1.<br>
carryOverflowMask := 16rFFFFFFFF//componentMask<<(destDepth-1).<br>
^ self partitionedAdd: sourceWord to: destinationWord<br>
nBits: destDepth componentMask: componentMask carryOverflowMask: carryOverflowMask].<br>
destDepth = 16 ifTrue:<br>
["Add RGB components of each pixel separately"<br>
componentMask := 16r1F.<br>
carryOverflowMask := 16r42104210.<br>
^ (self partitionedAdd: (sourceWord bitAnd: 16r7FFF7FFF) to: (destinationWord bitAnd: 16r7FFF7FFF) "make sure that the unused bit is at 0"<br>
nBits: 5 componentMask: componentMask carryOverflowMask: carryOverflowMask)]<br>
ifFalse:<br>
["Add RGBA components of the pixel separately"<br>
componentMask := 16rFF.<br>
carryOverflowMask := 16r80808080.<br>
^ self partitionedAdd: sourceWord to: destinationWord<br>
nBits: 8 componentMask: componentMask carryOverflowMask: carryOverflowMask]!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>rgbComponentAlpha16 (in category 'combination rules') -----<br>
rgbComponentAlpha16<br>
"This version assumes<br>
combinationRule = 41<br>
sourcePixSize = 32<br>
destPixSize = 16<br>
sourceForm ~= destForm.<br>
"<br>
<inline: false> "This particular method should be optimized in itself"<br>
+ <var: #sourceWord type: #'unsigned int'><br>
+ <var: #destWord type: #'unsigned int'><br>
+ <var: #dstMask type: #'unsigned int'><br>
<br>
| srcIndex dstIndex sourceWord srcAlpha destWord deltaX deltaY<br>
srcY dstY dstMask srcShift ditherBase ditherIndex ditherThreshold |<br>
<br>
deltaY := bbH + 1. "So we can pre-decrement"<br>
srcY := sy.<br>
dstY := dy.<br>
srcShift := (dx bitAnd: 1) * 16.<br>
destMSB ifTrue:[srcShift := 16 - srcShift].<br>
mask1 := 16rFFFF << (16 - srcShift).<br>
"This is the outer loop"<br>
[(deltaY := deltaY - 1) ~= 0] whileTrue:[<br>
srcIndex := sourceBits + (srcY * sourcePitch) + (sx * 4).<br>
dstIndex := destBits + (dstY * destPitch) + (dx // 2 * 4).<br>
ditherBase := (dstY bitAnd: 3) * 4.<br>
ditherIndex := (sx bitAnd: 3) - 1. "For pre-increment"<br>
deltaX := bbW + 1. "So we can pre-decrement"<br>
dstMask := mask1.<br>
dstMask = 16rFFFF ifTrue:[srcShift := 16] ifFalse:[srcShift := 0].<br>
<br>
"This is the inner loop"<br>
[(deltaX := deltaX - 1) ~= 0] whileTrue:[<br>
ditherThreshold := ditherMatrix4x4 at: ditherBase + (ditherIndex := ditherIndex + 1 bitAnd: 3).<br>
sourceWord := self srcLongAt: srcIndex.<br>
srcAlpha := sourceWord bitAnd: 16rFFFFFF.<br>
srcAlpha = 0 ifFalse:[ "0 < srcAlpha"<br>
"If we have to mix colors then just copy a single word"<br>
destWord := self dstLongAt: dstIndex.<br>
destWord := destWord bitAnd: dstMask bitInvert32.<br>
destWord := destWord >> srcShift.<br>
"Expand from 16 to 32 bit by adding zero bits"<br>
destWord := (((destWord bitAnd: 16r7C00) bitShift: 9) bitOr:<br>
((destWord bitAnd: 16r3E0) bitShift: 6)) bitOr:<br>
(((destWord bitAnd: 16r1F) bitShift: 3) bitOr:<br>
16rFF000000).<br>
"Mix colors"<br>
sourceWord := self rgbComponentAlpha32: sourceWord with: destWord.<br>
"And dither"<br>
sourceWord := self dither32To16: sourceWord threshold: ditherThreshold.<br>
sourceWord = 0<br>
ifTrue:[sourceWord := 1 << srcShift]<br>
ifFalse:[sourceWord := sourceWord << srcShift].<br>
"Store back"<br>
self dstLongAt: dstIndex put: sourceWord mask: dstMask.<br>
].<br>
srcIndex := srcIndex + 4.<br>
destMSB<br>
ifTrue:[srcShift = 0 ifTrue:[dstIndex := dstIndex + 4]]<br>
ifFalse:[srcShift = 0 ifFalse:[dstIndex := dstIndex + 4]].<br>
srcShift := srcShift bitXor: 16. "Toggle between 0 and 16"<br>
dstMask := dstMask bitInvert32. "Mask other half word"<br>
].<br>
srcY := srcY + 1.<br>
dstY := dstY + 1.<br>
].<br>
!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>rgbComponentAlpha32 (in category 'combination rules') -----<br>
rgbComponentAlpha32<br>
"This version assumes<br>
combinationRule = 41<br>
sourcePixSize = destPixSize = 32<br>
sourceForm ~= destForm.<br>
Note: The inner loop has been optimized for dealing<br>
with the special case of aR = aG = aB = 0<br>
"<br>
| srcIndex dstIndex sourceWord srcAlpha destWord deltaX deltaY srcY dstY |<br>
<br>
<inline: false> "This particular method should be optimized in itself"<br>
<br>
"Give the compile a couple of hints"<br>
- <var: #sourceWord type: 'register long'><br>
<var: #deltaX type: 'register long'><br>
+ <var: #sourceWord type: #'unsigned int'><br>
+ <var: #destWord type: #'unsigned int'><br>
<br>
"The following should be declared as pointers so the compiler will<br>
notice that they're used for accessing memory locations<br>
(good to know on an Intel architecture) but then the increments<br>
would be different between ST code and C code so must hope the<br>
compiler notices what happens (MS Visual C does)"<br>
<var: #srcIndex type: 'register long'><br>
<var: #dstIndex type: 'register long'><br>
<br>
deltaY := bbH + 1. "So we can pre-decrement"<br>
srcY := sy.<br>
dstY := dy.<br>
<br>
"This is the outer loop"<br>
[(deltaY := deltaY - 1) ~= 0] whileTrue:[<br>
srcIndex := sourceBits + (srcY * sourcePitch) + (sx * 4).<br>
dstIndex := destBits + (dstY * destPitch) + (dx * 4).<br>
deltaX := bbW + 1. "So we can pre-decrement"<br>
<br>
"This is the inner loop"<br>
[(deltaX := deltaX - 1) ~= 0] whileTrue:[<br>
sourceWord := self srcLongAt: srcIndex.<br>
srcAlpha := sourceWord bitAnd:16rFFFFFF.<br>
srcAlpha = 0 ifTrue:[<br>
srcIndex := srcIndex + 4.<br>
dstIndex := dstIndex + 4.<br>
"Now skip as many words as possible,"<br>
[(deltaX := deltaX - 1) ~= 0 and:[<br>
((sourceWord := self srcLongAt: srcIndex) bitAnd:16rFFFFFF) = 0]]<br>
whileTrue:[<br>
srcIndex := srcIndex + 4.<br>
dstIndex := dstIndex + 4.<br>
].<br>
"Adjust deltaX"<br>
deltaX := deltaX + 1.<br>
] ifFalse:[ "0 < srcAlpha"<br>
"If we have to mix colors then just copy a single word"<br>
destWord := self dstLongAt: dstIndex.<br>
destWord := self rgbComponentAlpha32: sourceWord with: destWord.<br>
self dstLongAt: dstIndex put: destWord.<br>
srcIndex := srcIndex + 4.<br>
dstIndex := dstIndex + 4.<br>
].<br>
].<br>
srcY := srcY + 1.<br>
dstY := dstY + 1.<br>
].!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>rgbComponentAlpha8 (in category 'combination rules') -----<br>
rgbComponentAlpha8<br>
"This version assumes<br>
combinationRule = 41<br>
sourcePixSize = 32<br>
destPixSize = 8<br>
sourceForm ~= destForm.<br>
Note: This is not real blending since we don't have the source colors available.<br>
"<br>
<br>
| srcIndex dstIndex sourceWord srcAlpha destWord deltaX deltaY<br>
srcY dstY dstMask srcShift adjust mappingTable mapperFlags |<br>
<br>
<inline: false> "This particular method should be optimized in itself"<br>
<var: #mappingTable declareC:'unsigned int *mappingTable'><br>
+ <var: #sourceWord type: #'unsigned int'><br>
+ <var: #destWord type: #'unsigned int'><br>
+ <var: #dstMask type: #'unsigned int'><br>
<br>
mappingTable := self default8To32Table.<br>
mapperFlags := cmFlags bitAnd: ColorMapNewStyle bitInvert32.<br>
deltaY := bbH + 1. "So we can pre-decrement"<br>
srcY := sy.<br>
dstY := dy.<br>
mask1 := ((dx bitAnd: 3) * 8).<br>
destMSB ifTrue:[mask1 := 24 - mask1].<br>
mask2 := AllOnes bitXor:(16rFF << mask1).<br>
(dx bitAnd: 1) = 0<br>
ifTrue:[adjust := 0]<br>
ifFalse:[adjust := 16r1F1F1F1F].<br>
(dy bitAnd: 1) = 0<br>
ifTrue:[adjust := adjust bitXor: 16r1F1F1F1F].<br>
"This is the outer loop"<br>
[(deltaY := deltaY - 1) ~= 0] whileTrue:[<br>
adjust := adjust bitXor: 16r1F1F1F1F.<br>
srcIndex := sourceBits + (srcY * sourcePitch) + (sx * 4).<br>
dstIndex := destBits + (dstY * destPitch) + (dx // 4 * 4).<br>
deltaX := bbW + 1. "So we can pre-decrement"<br>
srcShift := mask1.<br>
dstMask := mask2.<br>
<br>
"This is the inner loop"<br>
[(deltaX := deltaX - 1) ~= 0] whileTrue:[<br>
sourceWord := ((self srcLongAt: srcIndex) bitAnd: (adjust bitInvert32)) + adjust.<br>
srcAlpha := sourceWord bitAnd: 16rFFFFFF.<br>
"set srcAlpha to the average of the 3 separate aR,Ag,AB values"<br>
srcAlpha := ((srcAlpha >> 16) + (srcAlpha >> 8 bitAnd: 16rFF) + (srcAlpha bitAnd: 16rFF)) // 3.<br>
srcAlpha > 31 ifTrue:["Everything below 31 is transparent"<br>
srcAlpha > 224<br>
ifTrue: ["treat everything above 224 as opaque"<br>
sourceWord := 16rFFFFFFFF].<br>
destWord := self dstLongAt: dstIndex.<br>
destWord := destWord bitAnd: dstMask bitInvert32.<br>
destWord := destWord >> srcShift.<br>
destWord := mappingTable at: destWord.<br>
sourceWord := self rgbComponentAlpha32: sourceWord with: destWord.<br>
sourceWord := self mapPixel: sourceWord flags: mapperFlags.<br>
sourceWord := sourceWord << srcShift.<br>
"Store back"<br>
self dstLongAt: dstIndex put: sourceWord mask: dstMask.<br>
].<br>
srcIndex := srcIndex + 4.<br>
destMSB ifTrue:[<br>
srcShift = 0<br>
ifTrue:[dstIndex := dstIndex + 4.<br>
srcShift := 24.<br>
dstMask := 16r00FFFFFF]<br>
ifFalse:[srcShift := srcShift - 8.<br>
dstMask := (dstMask >> 8) bitOr: 16rFF000000].<br>
] ifFalse:[<br>
srcShift = 32<br>
ifTrue:[dstIndex := dstIndex + 4.<br>
srcShift := 0.<br>
dstMask := 16rFFFFFF00]<br>
ifFalse:[srcShift := srcShift + 8.<br>
dstMask := dstMask << 8 bitOr: 255].<br>
].<br>
adjust := adjust bitXor: 16r1F1F1F1F.<br>
].<br>
srcY := srcY + 1.<br>
dstY := dstY + 1.<br>
].<br>
!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>rgbDiff:with: (in category 'combination rules') -----<br>
rgbDiff: sourceWord with: destinationWord<br>
"Subract the pixels in the source and destination, color by color,<br>
and return the sum of the absolute value of all the differences.<br>
For non-rgb, return the number of differing pixels."<br>
| pixMask destShifted sourceShifted destPixVal bitsPerColor rgbMask sourcePixVal diff maskShifted |<br>
<inline: false><br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
+ <var: #sourceShifted type: 'unsigned int'><br>
+ <var: #destShifted type: 'unsigned int'><br>
+ <var: #maskShifted type: 'unsigned int'><br>
+ <var: #pixMask type: 'unsigned int'><br>
+ <var: #rgbMask type: 'unsigned int'><br>
pixMask := maskTable at: destDepth.<br>
destDepth = 16<br>
ifTrue: [bitsPerColor := 5. rgbMask := 16r1F]<br>
ifFalse: [bitsPerColor := 8. rgbMask := 16rFF].<br>
maskShifted := destMask.<br>
destShifted := destinationWord.<br>
sourceShifted := sourceWord.<br>
1 to: destPPW do:<br>
[:i |<br>
(maskShifted bitAnd: pixMask) > 0 ifTrue:<br>
["Only tally pixels within the destination rectangle"<br>
destPixVal := destShifted bitAnd: pixMask.<br>
sourcePixVal := sourceShifted bitAnd: pixMask.<br>
destDepth < 16<br>
ifTrue: [sourcePixVal = destPixVal<br>
ifTrue: [diff := 0]<br>
ifFalse: [diff := 1]]<br>
ifFalse: [diff := (self partitionedSub: sourcePixVal from: destPixVal<br>
nBits: bitsPerColor nPartitions: 3).<br>
diff := (diff bitAnd: rgbMask)<br>
+ (diff>>bitsPerColor bitAnd: rgbMask)<br>
+ ((diff>>bitsPerColor)>>bitsPerColor bitAnd: rgbMask)].<br>
bitCount := bitCount + diff].<br>
maskShifted := maskShifted >> destDepth.<br>
sourceShifted := sourceShifted >> destDepth.<br>
destShifted := destShifted >> destDepth].<br>
^ destinationWord "For no effect on dest"<br>
!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>rgbMax:with: (in category 'combination rules') -----<br>
rgbMax: sourceWord with: destinationWord<br>
<inline: false><br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
destDepth < 16 ifTrue:<br>
["Max each pixel separately"<br>
^ self partitionedMax: sourceWord with: destinationWord<br>
nBits: destDepth nPartitions: destPPW].<br>
destDepth = 16 ifTrue:<br>
["Max RGB components of each pixel separately"<br>
^ (self partitionedMax: sourceWord with: destinationWord<br>
nBits: 5 nPartitions: 3)<br>
+ ((self partitionedMax: sourceWord>>16 with: destinationWord>>16<br>
nBits: 5 nPartitions: 3) << 16)]<br>
ifFalse:<br>
["Max RGBA components of the pixel separately"<br>
^ self partitionedMax: sourceWord with: destinationWord<br>
nBits: 8 nPartitions: 4]!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>rgbMin:with: (in category 'combination rules') -----<br>
rgbMin: sourceWord with: destinationWord<br>
<inline: false><br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
destDepth < 16 ifTrue:<br>
["Min each pixel separately"<br>
^ self partitionedMin: sourceWord with: destinationWord<br>
nBits: destDepth nPartitions: destPPW].<br>
destDepth = 16 ifTrue:<br>
["Min RGB components of each pixel separately"<br>
^ (self partitionedMin: sourceWord with: destinationWord<br>
nBits: 5 nPartitions: 3)<br>
+ ((self partitionedMin: sourceWord>>16 with: destinationWord>>16<br>
nBits: 5 nPartitions: 3) << 16)]<br>
ifFalse:<br>
["Min RGBA components of the pixel separately"<br>
^ self partitionedMin: sourceWord with: destinationWord<br>
nBits: 8 nPartitions: 4]!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>rgbMinInvert:with: (in category 'combination rules') -----<br>
rgbMinInvert: wordToInvert with: destinationWord<br>
| sourceWord |<br>
<inline: false><br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #wordToInvert type: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
sourceWord := wordToInvert bitInvert32.<br>
destDepth < 16 ifTrue:<br>
["Min each pixel separately"<br>
^ self partitionedMin: sourceWord with: destinationWord<br>
nBits: destDepth nPartitions: destPPW].<br>
destDepth = 16 ifTrue:<br>
["Min RGB components of each pixel separately"<br>
^ (self partitionedMin: sourceWord with: destinationWord<br>
nBits: 5 nPartitions: 3)<br>
+ ((self partitionedMin: sourceWord>>16 with: destinationWord>>16<br>
nBits: 5 nPartitions: 3) << 16)]<br>
ifFalse:<br>
["Min RGBA components of the pixel separately"<br>
^ self partitionedMin: sourceWord with: destinationWord<br>
nBits: 8 nPartitions: 4]!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>rgbMul:with: (in category 'combination rules') -----<br>
rgbMul: sourceWord with: destinationWord<br>
<inline: false><br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
destDepth < 16 ifTrue:<br>
["Mul each pixel separately"<br>
^ self partitionedMul: sourceWord with: destinationWord<br>
nBits: destDepth nPartitions: destPPW].<br>
destDepth = 16 ifTrue:<br>
["Mul RGB components of each pixel separately"<br>
^ (self partitionedMul: sourceWord with: destinationWord<br>
nBits: 5 nPartitions: 3)<br>
+ ((self partitionedMul: sourceWord>>16 with: destinationWord>>16<br>
nBits: 5 nPartitions: 3) << 16)]<br>
ifFalse:<br>
["Mul RGBA components of the pixel separately"<br>
^ self partitionedMul: sourceWord with: destinationWord<br>
nBits: 8 nPartitions: 4]<br>
<br>
" | scanner |<br>
Display repaintMorphicDisplay.<br>
scanner := DisplayScanner quickPrintOn: Display.<br>
MessageTally time: [0 to: 760 by: 4 do: [:y |scanner drawString: 'qwrepoiuasfd=)(/&()=#!!〕kjzxv.,mn124+09857907QROIYTOAFDJZXNBNB,M-.,Mqwrepoiuasfd=)(/&()=#!!〕kjzxv.,mn124+09857907QROIYTOAFDJZXNBNB,M-.,M1234124356785678' at: 0@y]]. "!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>rgbSub:with: (in category 'combination rules') -----<br>
rgbSub: sourceWord with: destinationWord<br>
<inline: false><br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
destDepth < 16 ifTrue:<br>
["Sub each pixel separately"<br>
^ self partitionedSub: sourceWord from: destinationWord<br>
nBits: destDepth nPartitions: destPPW].<br>
destDepth = 16 ifTrue:<br>
["Sub RGB components of each pixel separately"<br>
^ (self partitionedSub: sourceWord from: destinationWord<br>
nBits: 5 nPartitions: 3)<br>
+ ((self partitionedSub: sourceWord>>16 from: destinationWord>>16<br>
nBits: 5 nPartitions: 3) << 16)]<br>
ifFalse:<br>
["Sub RGBA components of the pixel separately"<br>
^ self partitionedSub: sourceWord from: destinationWord<br>
nBits: 8 nPartitions: 4]!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>sourceWord:with: (in category 'combination rules') -----<br>
sourceWord: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
^sourceWord!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>subWord:with: (in category 'combination rules') -----<br>
subWord: sourceWord with: destinationWord<br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
^sourceWord - destinationWord!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>tallyIntoMap:with: (in category 'combination rules') -----<br>
tallyIntoMap: sourceWord with: destinationWord<br>
"Tally pixels into the color map. Those tallied are exactly those<br>
in the destination rectangle. Note that the source should be<br>
specified == destination, in order for the proper color map checks<br>
to be performed at setup."<br>
| mapIndex pixMask destShifted maskShifted pixVal |<br>
<inline: false><br>
+ <returnTypeC: 'unsigned int'><br>
+ <var: #sourceWord type: 'unsigned int'><br>
+ <var: #destinationWord type: 'unsigned int'><br>
+ <var: #pixMask type: 'unsigned int'><br>
+ <var: #destShifted type: 'unsigned int'><br>
+ <var: #maskShifted type: 'unsigned int'><br>
(cmFlags bitAnd: (ColorMapPresent bitOr: ColorMapIndexedPart)) =<br>
(ColorMapPresent bitOr: ColorMapIndexedPart)<br>
ifFalse: [^ destinationWord "no op"].<br>
pixMask := maskTable at: destDepth.<br>
destShifted := destinationWord.<br>
maskShifted := destMask.<br>
1 to: destPPW do:<br>
[:i |<br>
(maskShifted bitAnd: pixMask) = 0 ifFalse:<br>
["Only tally pixels within the destination rectangle"<br>
pixVal := destShifted bitAnd: pixMask.<br>
destDepth < 16<br>
ifTrue: [mapIndex := pixVal]<br>
ifFalse: [destDepth = 16<br>
ifTrue: [mapIndex := self rgbMap: pixVal from: 5 to: cmBitsPerColor]<br>
ifFalse: [mapIndex := self rgbMap: pixVal from: 8 to: cmBitsPerColor]].<br>
self tallyMapAt: mapIndex put: (self tallyMapAt: mapIndex) + 1].<br>
maskShifted := maskShifted >> destDepth.<br>
destShifted := destShifted >> destDepth].<br>
^ destinationWord "For no effect on dest"!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>warpLoop (in category 'inner loop') -----<br>
warpLoop<br>
"This version of the inner loop traverses an arbirary quadrilateral<br>
source, thus producing a general affine transformation."<br>
| skewWord halftoneWord mergeWord startBits<br>
deltaP12x deltaP12y deltaP43x deltaP43y pAx pAy pBx pBy<br>
xDelta yDelta smoothingCount sourceMapOop<br>
nSteps nPix words destWord endBits mergeFnwith dstShiftInc dstShiftLeft mapperFlags |<br>
+ <inline: false><br>
+ <var: #mergeFnwith declareC: 'unsigned int (*mergeFnwith)(unsigned int, unsigned int)'><br>
+ <var: #skewWord type: #'unsigned int'><br>
+ <var: #halftoneWord type: #'unsigned int'><br>
+ <var: #mergeWord type: #'unsigned int'><br>
+ <var: #destWord type: #'unsigned int'><br>
+ mergeFnwith := self cCoerce: (opTable at: combinationRule+1) to: 'unsigned int (*)(unsigned int, unsigned int)'.<br>
- <inline: false><br>
- <var: #mergeFnwith declareC: 'sqInt (*mergeFnwith)(sqInt, sqInt)'><br>
- mergeFnwith := self cCoerce: (opTable at: combinationRule+1) to: 'sqInt (*)(sqInt, sqInt)'.<br>
mergeFnwith. "null ref for compiler"<br>
<br>
(interpreterProxy slotSizeOf: bitBltOop) >= (BBWarpBase+12)<br>
ifFalse: [^ interpreterProxy primitiveFail].<br>
nSteps := height-1. nSteps <= 0 ifTrue: [nSteps := 1].<br>
<br>
pAx := self fetchIntOrFloat: BBWarpBase ofObject: bitBltOop.<br>
words := self fetchIntOrFloat: BBWarpBase+3 ofObject: bitBltOop.<br>
deltaP12x := self deltaFrom: pAx to: words nSteps: nSteps.<br>
deltaP12x < 0 ifTrue: [pAx := words - (nSteps*deltaP12x)].<br>
<br>
pAy := self fetchIntOrFloat: BBWarpBase+1 ofObject: bitBltOop.<br>
words := self fetchIntOrFloat: BBWarpBase+4 ofObject: bitBltOop.<br>
deltaP12y := self deltaFrom: pAy to: words nSteps: nSteps.<br>
deltaP12y < 0 ifTrue: [pAy := words - (nSteps*deltaP12y)].<br>
<br>
pBx := self fetchIntOrFloat: BBWarpBase+9 ofObject: bitBltOop.<br>
words := self fetchIntOrFloat: BBWarpBase+6 ofObject: bitBltOop.<br>
deltaP43x := self deltaFrom: pBx to: words nSteps: nSteps.<br>
deltaP43x < 0 ifTrue: [pBx := words - (nSteps*deltaP43x)].<br>
<br>
pBy := self fetchIntOrFloat: BBWarpBase+10 ofObject: bitBltOop.<br>
words := self fetchIntOrFloat: BBWarpBase+7 ofObject: bitBltOop.<br>
deltaP43y := self deltaFrom: pBy to: words nSteps: nSteps.<br>
deltaP43y < 0 ifTrue: [pBy := words - (nSteps*deltaP43y)].<br>
<br>
interpreterProxy failed ifTrue: [^ false]. "ie if non-integers above"<br>
interpreterProxy methodArgumentCount = 2<br>
ifTrue: [smoothingCount := interpreterProxy stackIntegerValue: 1.<br>
sourceMapOop := interpreterProxy stackValue: 0.<br>
sourceMapOop = interpreterProxy nilObject<br>
ifTrue: [sourceDepth < 16 ifTrue:<br>
["color map is required to smooth non-RGB dest"<br>
^ interpreterProxy primitiveFail]]<br>
ifFalse: [(interpreterProxy slotSizeOf: sourceMapOop)<br>
< (1 << sourceDepth) ifTrue:<br>
["sourceMap must be long enough for sourceDepth"<br>
^ interpreterProxy primitiveFail].<br>
sourceMapOop := self oopForPointer: (interpreterProxy firstIndexableField: sourceMapOop)]]<br>
ifFalse: [smoothingCount := 1.<br>
sourceMapOop := interpreterProxy nilObject].<br>
nSteps := width-1. nSteps <= 0 ifTrue: [nSteps := 1].<br>
startBits := destPPW - (dx bitAnd: destPPW-1).<br>
endBits := ((dx + bbW - 1) bitAnd: destPPW-1) + 1.<br>
bbW < startBits ifTrue:[startBits := bbW].<br>
<br>
destY < clipY ifTrue:[<br>
"Advance increments if there was clipping in y"<br>
pAx := pAx + (clipY - destY * deltaP12x).<br>
pAy := pAy + (clipY - destY * deltaP12y).<br>
pBx := pBx + (clipY - destY * deltaP43x).<br>
pBy := pBy + (clipY - destY * deltaP43y)].<br>
<br>
"Setup values for faster pixel fetching."<br>
self warpLoopSetup.<br>
"Setup color mapping if not provided"<br>
(smoothingCount > 1 and:[(cmFlags bitAnd: ColorMapNewStyle) = 0]) ifTrue:[<br>
cmLookupTable == nil ifTrue:[<br>
destDepth = 16 ifTrue:[self setupColorMasksFrom: 8 to: 5].<br>
] ifFalse:[<br>
self setupColorMasksFrom: 8 to: cmBitsPerColor.<br>
].<br>
].<br>
mapperFlags := cmFlags bitAnd: ColorMapNewStyle bitInvert32.<br>
<br>
destMSB<br>
ifTrue:[ dstShiftInc := 0 - destDepth.<br>
dstShiftLeft := 32 - destDepth]<br>
ifFalse:[ dstShiftInc := destDepth.<br>
dstShiftLeft := 0].<br>
1 to: bbH do:<br>
[ :i | "here is the vertical loop..."<br>
xDelta := self deltaFrom: pAx to: pBx nSteps: nSteps.<br>
xDelta >= 0 ifTrue: [sx := pAx] ifFalse: [sx := pBx - (nSteps*xDelta)].<br>
yDelta := self deltaFrom: pAy to: pBy nSteps: nSteps.<br>
yDelta >= 0 ifTrue: [sy := pAy] ifFalse: [sy := pBy - (nSteps*yDelta)].<br>
<br>
destMSB<br>
ifTrue:[dstBitShift := 32 - ((dx bitAnd: destPPW - 1) + 1 * destDepth)]<br>
ifFalse:[dstBitShift := (dx bitAnd: destPPW - 1) * destDepth].<br>
<br>
(destX < clipX) ifTrue:[<br>
"Advance increments if there was clipping in x"<br>
sx := sx + (clipX - destX * xDelta).<br>
sy := sy + (clipX - destX * yDelta).<br>
].<br>
<br>
noHalftone<br>
ifTrue: [halftoneWord := AllOnes]<br>
ifFalse: [halftoneWord := self halftoneAt: dy+i-1].<br>
destMask := mask1.<br>
nPix := startBits.<br>
"Here is the inner loop..."<br>
words := nWords.<br>
["pick up word"<br>
smoothingCount = 1 ifTrue:["Faster if not smoothing"<br>
skewWord := self warpPickSourcePixels: nPix<br>
xDeltah: xDelta yDeltah: yDelta<br>
xDeltav: deltaP12x yDeltav: deltaP12y<br>
dstShiftInc: dstShiftInc flags: mapperFlags.<br>
] ifFalse:["more difficult with smoothing"<br>
skewWord := self warpPickSmoothPixels: nPix<br>
xDeltah: xDelta yDeltah: yDelta<br>
xDeltav: deltaP12x yDeltav: deltaP12y<br>
sourceMap: sourceMapOop<br>
smoothing: smoothingCount<br>
dstShiftInc: dstShiftInc.<br>
].<br>
"align next word access to left most pixel"<br>
dstBitShift := dstShiftLeft.<br>
destMask = AllOnes ifTrue:["avoid read-modify-write"<br>
mergeWord := self mergeFn: (skewWord bitAnd: halftoneWord)<br>
with: (self dstLongAt: destIndex).<br>
self dstLongAt: destIndex put: (destMask bitAnd: mergeWord).<br>
] ifFalse:[ "General version using dest masking"<br>
destWord := self dstLongAt: destIndex.<br>
mergeWord := self mergeFn: (skewWord bitAnd: halftoneWord)<br>
with: (destWord bitAnd: destMask).<br>
destWord := (destMask bitAnd: mergeWord) bitOr:<br>
(destWord bitAnd: destMask bitInvert32).<br>
self dstLongAt: destIndex put: destWord.<br>
].<br>
self incDestIndex: 4.<br>
words = 2 "e.g., is the next word the last word?"<br>
ifTrue:["set mask for last word in this row"<br>
destMask := mask2.<br>
nPix := endBits]<br>
ifFalse:["use fullword mask for inner loop"<br>
destMask := AllOnes.<br>
nPix := destPPW].<br>
(words := words - 1) = 0] whileFalse.<br>
"--- end of inner loop ---"<br>
pAx := pAx + deltaP12x.<br>
pAy := pAy + deltaP12y.<br>
pBx := pBx + deltaP43x.<br>
pBy := pBy + deltaP43y.<br>
self incDestIndex: destDelta]!<br>
<br>
Item was changed:<br>
----- Method: BitBltSimulation>>warpPickSmoothPixels:xDeltah:yDeltah:xDeltav:yDeltav:sourceMap:smoothing:dstShiftInc: (in category 'pixel mapping') -----<br>
warpPickSmoothPixels: nPixels<br>
xDeltah: xDeltah yDeltah: yDeltah<br>
xDeltav: xDeltav yDeltav: yDeltav<br>
sourceMap: sourceMap<br>
smoothing: n<br>
dstShiftInc: dstShiftInc<br>
"Pick n (sub-) pixels from the source form, mapped by sourceMap,<br>
average the RGB values, map by colorMap and return the new word.<br>
This version is only called from WarpBlt with smoothingCount > 1"<br>
| rgb x y a r g b xx yy xdh ydh xdv ydv dstMask destWord i j k nPix |<br>
<inline: false> "nope - too much stuff in here"<br>
+ <var: #rgb type: #'unsigned int'><br>
dstMask := maskTable at: destDepth.<br>
destWord := 0.<br>
n = 2 "Try avoiding divides for most common n (divide by 2 is generated as shift)"<br>
ifTrue:[xdh := xDeltah // 2. ydh := yDeltah // 2.<br>
xdv := xDeltav // 2. ydv := yDeltav // 2]<br>
ifFalse:[xdh := xDeltah // n. ydh := yDeltah // n.<br>
xdv := xDeltav // n. ydv := yDeltav // n].<br>
i := nPixels.<br>
[<br>
x := sx. y := sy.<br>
a := r := g := b := 0.<br>
"Pick and average n*n subpixels"<br>
nPix := 0. "actual number of pixels (not clipped and not transparent)"<br>
j := n.<br>
[<br>
xx := x. yy := y.<br>
k := n.<br>
[<br>
"get a single subpixel"<br>
rgb := self pickWarpPixelAtX: xx y: yy.<br>
(combinationRule=25 "PAINT" and: [rgb = 0]) ifFalse:[<br>
"If not clipped and not transparent, then tally rgb values"<br>
nPix := nPix + 1.<br>
sourceDepth < 16 ifTrue:[<br>
"Get RGBA values from sourcemap table"<br>
rgb := self long32At: sourceMap + (rgb << 2).<br>
] ifFalse:["Already in RGB format"<br>
sourceDepth = 16<br>
ifTrue:[rgb := self rgbMap16To32: rgb]<br>
ifFalse:[rgb := self rgbMap32To32: rgb]].<br>
b := b + (rgb bitAnd: 255).<br>
g := g + (rgb >> 8 bitAnd: 255).<br>
r := r + (rgb >> 16 bitAnd: 255).<br>
a := a + (rgb >> 24)].<br>
xx := xx + xdh.<br>
yy := yy + ydh.<br>
(k := k - 1) = 0] whileFalse.<br>
x := x + xdv.<br>
y := y + ydv.<br>
(j := j - 1) = 0] whileFalse.<br>
<br>
(nPix = 0 or: [combinationRule=25 "PAINT" and: [nPix < (n * n // 2)]]) ifTrue:[<br>
rgb := 0 "All pixels were 0, or most were transparent"<br>
] ifFalse:[<br>
"normalize rgba sums"<br>
nPix = 4 "Try to avoid divides for most common n"<br>
ifTrue:[r := r >> 2. g := g >> 2. b := b >> 2. a := a >> 2]<br>
ifFalse:[ r := r // nPix. g := g // nPix. b := b // nPix. a := a // nPix].<br>
rgb := (a << 24) + (r << 16) + (g << 8) + b.<br>
<br>
"map the pixel"<br>
rgb = 0 ifTrue: [<br>
"only generate zero if pixel is really transparent"<br>
(r + g + b + a) > 0 ifTrue: [rgb := 1]].<br>
rgb := self mapPixel: rgb flags: cmFlags.<br>
].<br>
"Mix it in"<br>
destWord := destWord bitOr: (rgb bitAnd: dstMask) << dstBitShift.<br>
dstBitShift := dstBitShift + dstShiftInc.<br>
sx := sx + xDeltah.<br>
sy := sy + yDeltah.<br>
(i := i - 1) = 0] whileFalse.<br>
<br>
^destWord<br>
!<br>
<br>
</blockquote></div><br></div>