Author: Tim Felgentreff <[email protected]>
Branch: rbitblt
Changeset: r543:fb979403239a
Date: 2013-12-19 16:26 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/fb979403239a/

Log:    finish copying squeakjs bitblt

diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -649,7 +649,7 @@
     if (combinationRule == 22 or combinationRule == 32):
         s_frame.pop() # pops the next value under BitBlt
         s_frame.push(s_bitblt.bitCount())
-    else if w_dest_form.is_same_object(space.objtable['w_display']):
+    elif w_dest_form.is_same_object(space.objtable['w_display']):
         w_bitmap = w_dest_form.fetch(space, 0)
         assert isinstance(w_bitmap, model.W_DisplayBitmap)
         w_bitmap.flush_to_screen()
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -1178,19 +1178,19 @@
 
     def loadBitBlt(self):
         self.success = True
-        self.destForm = self.fetch(0)
-        self.dest = self.loadForm(self.destForm)
-        self.sourceForm = self.fetch(1)
-        if self.sourceForm is not self.space.w_nil:
-            self.source = self.loadForm(self.sourceForm)
+        self.w_destForm = self.fetch(0)
+        self.dest = self.loadForm(self.w_destForm)
+        self.w_sourceForm = self.fetch(1)
+        if self.w_sourceForm is not self.space.w_nil:
+            self.source = self.loadForm(self.w_sourceForm)
         else:
             self.source = None
         self.halftone = self.loadHalftone(self.fetch(2))
         self.combinationRule = self.space.unwrap_int(self.fetch(3))
         self.destX = self.intOrIfNil(self.fetch(4), 0)
         self.destY = self.intOrIfNil(self.fetch(5), 0)
-        self.width = self.intOrIfNil(self.fetch(6), self.dest_form.width)
-        self.height = self.intOrIfNil(self.fetch(7), self.dest_form.height)
+        self.width = self.intOrIfNil(self.fetch(6), self.dest.width)
+        self.height = self.intOrIfNil(self.fetch(7), self.dest.height)
         self.clipX = self.intOrIfNil(self.fetch(10), 0)
         self.clipY = self.intOrIfNil(self.fetch(11), 0)
         self.clipW = self.intOrIfNil(self.fetch(12), self.width)
@@ -1206,19 +1206,72 @@
     def copyBits(self):
         self.bitCount = 0
         self.clipRange()
-        if (self.bbW <= 0 ir self.bbH <= 0):
+        if (self.bbW <= 0 or self.bbH <= 0):
             return
         self.destMaskAndPointerInit()
         if not self.source:
             self.copyLoopNoSource()
         else:
             self.checkSourceOverlap()
-            if self.source.depth !== self.dest.depth:
+            if self.source.depth != self.dest.depth:
                 self.copyLoopPixMap()
             else:
                 self.sourceSkewAndPointerInit()
                 self.copyLoop()
 
+    def checkSourceOverlap(self):
+        if (self.w_sourceForm is self.w_destForm and self.dy >= self.sy):
+            if (self.dy > self.sy):
+                self.vDir = -1
+                self.sy = (self.sy + self.bbH) - 1
+                self.dy = (self.dy + self.bbH) - 1
+            else:
+                if (self.dy == self.sy and self.dx > self.sx):
+                    self.hDir = -1
+                    self.sx = (self.sx + self.bbW) - 1 # start at right
+                    self.dx = (self.dx + self.bbW) - 1
+                    if (self.nWords > 1):
+                        t = self.mask1 # and fix up masks
+                        self.mask1 = self.mask2
+                        self.mask2 = t
+            self.destIndex = (self.dy * self.dest.pitch) + (self.dx / 
self.dest.pixPerWord | 0) # recompute since dx, dy change
+            self.destDelta = (self.dest.pitch * self.vDir) - (self.nWords * 
self.hDir)
+
+    def sourceSkewAndPointerInit(self):
+        pixPerM1 = self.dest.pixPerWord - 1 # Pix per word is power of two, so 
self makes a mask
+        sxLowBits = self.sx & pixPerM1
+        dxLowBits = self.dx & pixPerM1
+        # check if need to preload buffer
+        # (i.e., two words of source needed for first word of destination)
+        dWid = -1
+        if (self.hDir > 0):
+            if self.bbW < (self.dest.pixPerWord - dxLowBits):
+                dWid = self.bbW
+            else:
+                dWid = self.dest.pixPerWord - dxLowBits
+            self.preload = (sxLowBits + dWid) > pixPerM1
+        else:
+            if self.bbW < (dxLowBits + 1):
+                dWid = self.bbW
+            else:
+                dWid = dxLowBits + 1
+            self.preload = ((sxLowBits - dWid) + 1) < 0
+
+        if self.source.msb:
+            self.skew = (sxLowBits - dxLowBits) * self.dest.depth
+        else:
+            self.skew = (dxLowBits - sxLowBits) * self.dest.depth
+        if (self.preload):
+            if (self.skew < 0):
+                self.skew += 32
+            else:
+                self.skew -= 32
+        # calculate increments from end of one line to start of next
+        self.sourceIndex = (self.sy * self.source.pitch) + (self.sx / (32 / 
self.source.depth) |0)
+        self.sourceDelta = (self.source.pitch * self.vDir) - (self.nWords * 
self.hDir)
+        if (self.preload):
+            self.sourceDelta -= self.hDir
+
     def clipRange(self):
         # intersect with destForm bounds
         if self.clipX < 0:
@@ -1231,174 +1284,399 @@
             self.clipW = self.dest.width - self.clipX
         if self.clipY + self.clipH > self.dest.height:
             self.clipH = self.dest.height - self.clipY
-
         # intersect with clipRect
-        leftOffset = max(self.clipY - self.destY, 0)
+        leftOffset = max(self.clipX - self.destX, 0)
         self.sx = self.sourceX + leftOffset
         self.dx = self.destX + leftOffset
         self.bbW = self.width - leftOffset
-        rightOffset =
+        rightOffset = (self.dx + self.bbW) - (self.clipX + self.clipW)
+        if rightOffset > 0:
+            self.bbW -= rightOffset
+        topOffset = max(self.clipY - self.destY, 0)
+        self.sy = self.sourceY + topOffset
+        self.dy = self.destY + topOffset
+        self.bbH = self.height - topOffset
+        bottomOffset = (self.dy + self.bbH) - (self.clipY + self.clipH)
+        if bottomOffset > 0:
+            self.bbH -= bottomOffset
+        # intersect with sourceForm bounds
+        if not self.source:
+            return
+        if self.sx < 0:
+            self.dx -= self.sx
+            self.bbW += self.sx
+            self.sx = 0
+        if (self.sx + self.bbW) > self.source.width:
+            self.bbW -= (self.sx + self.bbW) - self.source.width
+        if self.sy < 0:
+            self.dy -= self.sy
+            self.bbH += self.sy
+            self.sy = 0
+        if (self.sy + self.bbH) > self.source.height:
+            self.bbH -= (self.sy + self.bbH) - self.source.height
 
+    def rshift(self, val, n):
+        return rarithmetic.intmask(val >> n if val >= 0 else (val + 
0x100000000) >> n)
 
-    def compute_masks(self):
-        self.dest_bits = self.dest_form.w_bits
-        self.dest_raster = (self.dest_form.width - 1) // BitBltShadow.WordSize 
+ 1
-        if self.source_form is not None:
-            self.source_bits = self.source_form.w_bits
-            self.source_raster = (self.source_form.width - 1) // 
BitBltShadow.WordSize + 1
+    def destMaskAndPointerInit(self):
+        pixPerM1 = self.dest.pixPerWord - 1 # pixPerWord is power-of-two, so 
this makes a mask
+        startBits = self.dest.pixPerWord - (self.dx & pixPerM1) # how many px 
in 1st word
+        endBits = (((self.dx + self.bbW) - 1) & pixPerM1) + 1
+        if self.dest.msb:
+            self.mask1 = self.rshift(0xFFFFFFFF, (32 - (startBits * 
self.dest.depth)))
+            self.mask2 = 0xFFFFFFFF << (32 - (endBits * self.dest.depth))
         else:
-            self.source_bits = None
-            self.source_raster = 0
-        # Halftone form is set during synchronization
-        self.skew = (self.sx - self.dx) & (BitBltShadow.WordSize - 1)
-        start_bits = BitBltShadow.WordSize - (self.dx & (BitBltShadow.WordSize 
- 1))
-        self.mask1 = BitBltShadow.RightMasks[start_bits]
-        end_bits = (BitBltShadow.WordSize - 1) - ((self.dx + self.w - 1) & 
(BitBltShadow.WordSize - 1))
-        self.mask2 = ~BitBltShadow.RightMasks[end_bits]
-        if self.skew == 0:
-            self.skew_mask = rarithmetic.r_uint(0)
+            self.mask1 = 0xFFFFFFFF << (32 - (startBits * self.dest.depth))
+            self.mask2 = self.rshift(0xFFFFFFFF, (32 - (endBits * 
self.dest.depth)))
+        if self.bbW < startBits:
+            self.mask1 = self.mask1 & self.mask2
+            self.mask2 = 0
+            self.nWords = 1
         else:
-            self.skew_mask = BitBltShadow.RightMasks[BitBltShadow.WordSize - 
self.skew]
-        if self.w < start_bits:
-            self.mask1 = self.mask1 & self.mask2
-            self.mask2 = rarithmetic.r_uint(0)
-            self.n_words = 1
+            self.nWords = (((self.bbW - startBits) + pixPerM1) / 
self.dest.pixPerWord | 0) + 1
+        self.hDir = 1
+        self.vDir = 1
+        self.destIndex = (self.dy * self.dest.pitch) + (self.dx / 
self.dest.pixPerWord | 0)
+        self.destDelta = (self.dest.pitch * self.vDir) - (self.nWords * 
self.hDir)
+
+    def copyLoopNoSource(self):
+        halftoneWord = 0xFFFFFFFF
+        for i in range(self.bbH):
+            if self.halftone:
+                halftoneWord = self.halftone[(self.dy + i) % 
len(self.halftone)]
+            # first word in row is masked
+            destMask = self.mask1
+            destWord = self.dest.w_bits.getword(self.destIndex)
+            mergeWord = self.mergeFn(halftoneWord, destWord)
+            destWord = (destMask & mergeWord) | (destWord & (~destMask))
+            self.dest.w_bits.setword(self.destIndex, destWord)
+            self.destIndex += 1
+            destMask = 0xFFFFFFFF
+            # the central horizontal loop requires no store masking
+            if self.combinationRule == 3: # store rule requires no dest merging
+                for word in range(2, self.nWords):
+                    self.dest.w_bits.setword(self.destIndex, halftoneWord)
+                    self.destIndex += 1
+            else:
+                for word in range(2, self.nWords):
+                    destWord = self.dest.w_bits.getword(self.destIndex)
+                    mergeWord = self.mergeFn(halftoneWord, destWord)
+                    self.dest.w_bits.setword(self.destIndex, mergeWord)
+                    self.destIndex += 1
+            # last word in row is masked
+            if self.nWords > 1:
+                destMask = self.mask2
+                destWord = self.dest.w_bits.getword(self.destIndex)
+                mergeWord = self.mergeFn(halftoneWord, destWord)
+                destWord = (destMask & mergeWord) | (destWord & (~destMask))
+                self.dest.w_bits.setword(self.destIndex, destWord)
+                self.destIndex += 1
+            self.destIndex += self.destDelta
+
+    def copyLoopPixMap(self):
+        # This version of the inner loop maps source pixels
+        # to a destination form with different depth.  Because it is already
+        # unweildy, the loop is not unrolled as in the other versions.
+        # Preload, skew and skewMask are all overlooked, since pickSourcePixels
+        # delivers its destination word already properly aligned.
+        # Note that pickSourcePixels could be copied in-line at the top of
+        # the horizontal loop, and some of its inits moved out of the loop.
+        #
+        # The loop has been rewritten to use only one pickSourcePixels call.
+        # The idea is that the call itself could be inlined. If we decide not
+        # to inline pickSourcePixels we could optimize the loop instead.
+        sourcePixMask = BitBltShadow.MaskTable[this.source.depth]
+        destPixMask = BitBltShadow.MaskTable[this.dest.depth]
+        self.sourceIndex = (self.sy * self.source.pitch) + (self.sx / 
self.source.pixPerWord | 0)
+        scrStartBits = self.source.pixPerWord - (self.sx & 
(self.source.pixPerWord - 1))
+        if self.bbW < scrStartBits:
+            nSourceIncs = 0
         else:
-            self.n_words = (self.w - start_bits - 1) // BitBltShadow.WordSize 
+ 2
+            nSourceIncs = ((self.bbW - scrStartBits) / self.source.pixPerWord 
| 0) + 1
+        # Note following two items were already calculated in destmask setup!
+        self.sourceDelta = self.source.pitch - nSourceIncs
+        startBits = self.dest.pixPerWord - (self.dx & (self.dest.pixPerWord - 
1))
+        endBits = (((self.dx + self.bbW) - 1) & (self.dest.pixPerWord - 1)) + 1
+        if self.bbW < startBits:
+            startBits = self.bbW # ?!
+        srcShift = (self.sx & (self.source.pixPerWord - 1)) * self.source.depth
+        dstShift = (self.dx & (self.dest.pixPerWord - 1)) * self.dest.depth
+        srcShiftInc = self.source.depth
+        dstShiftInc = self.dest.depth
+        dstShiftLeft = 0
+        if (self.source.msb):
+            srcShift = (32 - self.source.depth) - srcShift
+            srcShiftInc = -srcShiftInc
 
-    def check_overlap(self):
-        self.h_dir = 1
-        self.v_dir = 1
-        if (self.source_form is not None and
-            self.source_form.w_self().is_same_object(self.dest_form.w_self()) 
and
-            self.dy >= self.sy):
-            if self.dy > self.sy:
-                self.v_dir = -1
-                self.sy = self.sy + self.h - 1
-                self.dy = self.dy + self.h - 1
-            elif self.dx > self.sx:
-                self.h_dir = -1
-                self.sx = self.sx + self.w - 1
-                self.dx = self.dx + self.w - 1
-                self.skew_mask = ~self.skew_mask
-                self.mask1, self.mask2 = self.mask2, self.mask1
+        if (self.dest.msb):
+            dstShift = (32 - self.dest.depth) - dstShift
+            dstShiftInc = -dstShiftInc
+            dstShiftLeft = 32 - self.dest.depth
 
-    def calculate_offsets(self):
-        self.preload = (self.source_form is not None and (
-                        self.skew != 0 and
-                        self.skew <= (self.sx & (BitBltShadow.WordSize - 1))))
-        if self.h_dir < 0:
-            self.preload = not self.preload
-        self.source_index = self.sy * self.source_raster + (self.sx // 
BitBltShadow.WordSize)
-        self.dest_index = self.dy * self.dest_raster + (self.dx // 
BitBltShadow.WordSize)
-        self.source_delta = (self.source_raster *
-                             self.v_dir -
-                             ((self.n_words + (1 if self.preload else 0)) *
-                             self.h_dir))
-        self.dest_delta = self.dest_raster * self.v_dir - self.n_words * 
self.h_dir
+        for i in range(self.bbH):
+            if self.halftone:
+                halftoneWord = self.halftone[(self.dy + i) % 
self.halftone.length]
+            else:
+                halftoneWord = 0xFFFFFFFF
+            self.srcBitShift = srcShift
+            self.dstBitShift = dstShift
+            self.destMask = self.mask1
+            nPix = startBits
+            words = self.nWords
+            # Here is the horizontal loop...
+            for word in range(words + 1):
+                skewWord = self.pickSourcePixels(nPix, sourcePixMask, 
destPixMask, srcShiftInc, dstShiftInc)
+                # align next word to leftmost pixel
+                self.dstBitShift = dstShiftLeft
+                if self.destMask == 0xFFFFFFFF: # avoid read-modify-write
+                    self.dest.w_bits.setword(
+                        self.destIndex,
+                        self.mergeFn(skewWord & halftoneWord, 
self.dest.w_bits.getword(self.destIndex))
+                    )
+                else: # General version using dest masking
+                    destWord = self.dest.w_bits.getword(self.destIndex)
+                    mergeWord = self.mergeFn(skewWord & halftoneWord, destWord 
& self.destMask)
+                    destWord = (self.destMask & mergeWord) | (destWord & 
(~self.destMask))
+                    self.dest.w_bits.setword(self.destIndex, destWord)
 
-    def copy_loop(self):
-        space = self.space
-        no_skew_mask = ~self.skew_mask
-        for i in xrange(1, self.h + 1):
-            if self.halftone_bits:
-                halftone_word = self.halftone_bits[self.dy % 
len(self.halftone_bits)]
-                self.dy = self.dy + self.v_dir
+                self.destIndex += 1
+                if (words == 2): # is the next word the last word?
+                    self.destMask = self.mask2
+                    nPix = endBits
+                else: # use fullword mask for inner loop
+                    self.destMask = 0xFFFFFFFF
+                    nPix = self.dest.pixPerWord
+            self.sourceIndex += self.sourceDelta
+            self.destIndex += self.destDelta
+
+    def pickSourcePixels(self, nPixels, srcMask, dstMask, srcShiftInc, 
dstShiftInc):
+        # Pick nPix pixels starting at srcBitIndex from the source, map by the
+        # color map, and justify them according to dstBitIndex in the 
resulting destWord.
+        sourceWord = self.source.w_bits.getword(self.sourceIndex)
+        destWord = 0
+        srcShift = self.srcBitShift # put into temp for speed
+        dstShift = self.dstBitShift
+        nPix = nPixels
+        # always > 0 so we can use do { } while(--nPix);
+        if (self.cmLookupTable): # a little optimization for (pretty crucial) 
blits using indexed lookups only
+            for px in range(nPix + 1):
+                sourcePix = self.rshift(sourceWord, srcShift) & srcMask
+                destPix = self.cmLookupTable[sourcePix & self.cmMask]
+                # adjust dest pix index
+                destWord = destWord | ((destPix & dstMask) << dstShift)
+                # adjust source pix index
+                dstShift += dstShiftInc
+                srcShift += srcShiftInc
+                if srcShift & 0xFFFFFFE0:
+                    if (self.source.msb):
+                        srcShift += 32
+                    else:
+                        srcShift -= 32
+                    self.sourceIndex += 1
+                    sourceWord = self.source.w_bits.getword(self.sourceIndex)
+        else:
+            raise PrimitiveFailedError()
+        self.srcBitShift = srcShift # Store back
+        return destWord
+
+    def rotate32bit(self, thisWord, prevWord, skewMask, notSkewMask, unskew):
+        if unskew < 0:
+            rotated = self.rshift(prevWord & notSkewMask, -unskew)
+        else:
+            rotated = (prevWord & notSkewMask) << unskew
+        if self.skew < 0:
+            rotated = rotated | self.rshift(thisWord & skewMask, -self.skew)
+        else:
+            rotated = rotated | (thisWord & skewMask) << self.skew
+        return rotated
+
+    def copyLoop(self):
+        # self version of the inner loop assumes we do have a source
+        sourceLimit = self.source.w_bits.size()
+        hInc = self.hDir
+        # init skew (the difference in word alignment of source and dest)
+        unskew = 0
+        skewMask = 0
+        if (self.skew == -32):
+            self.skew = unskew = skewMask = 0
+        else:
+            if (self.skew < 0):
+                unskew = self.skew + 32
+                skewMask = 0xFFFFFFFF << -self.skew
             else:
-                halftone_word = BitBltShadow.AllOnes
-            skew_word = halftone_word
-            if self.preload:
-                prev_word = self.source_bits.getword(self.source_index)
-                self.source_index = self.source_index + self.h_dir
+                if (self.skew == 0):
+                    unskew = 0
+                    skewMask = 0xFFFFFFFF
+                else:
+                    unskew = self.skew - 32
+                    skewMask = self.rshift(0xFFFFFFFF, self.skew)
+        notSkewMask = ~skewMask
+
+        # init halftones
+        halftoneWord = 0
+        halftoneHeight = 0
+        if (self.halftone):
+            halftoneWord = self.halftone[0]
+            halftoneHeight = len(self.halftone)
+        else:
+            halftoneWord = 0xFFFFFFFF
+            halftoneHeight = 0
+
+        # now loop over all lines
+        y = self.dy
+        for i in range(1, self.bbH + 1):
+            if (halftoneHeight > 1):
+                halftoneWord = self.halftone[y % halftoneHeight]
+                y += self.vDir
+
+            if (self.preload):
+                prevWord = self.source.w_bits.getword(self.sourceIndex)
+                self.sourceIndex += hInc
             else:
-                prev_word = 0
-            merge_mask = self.mask1
-            for word in xrange(1, self.n_words + 1):
-                if self.source_form is not None:
-                    prev_word = prev_word & self.skew_mask
-                    if (self.source_index < 0
-                        or self.source_index >= self.source_bits.size()):
-                        this_word = self.source_bits.getword(0)
+                prevWord = 0
+
+            destMask = self.mask1
+            # pick up next word
+            thisWord = self.source.w_bits.getword(self.sourceIndex)
+            self.sourceIndex += hInc
+            skewWord = self.rotate32bit(thisWord, prevWord, skewMask, 
notSkewMask, unskew)
+            prevWord = thisWord
+            destWord = self.dest.w_bits.getword(self.destIndex)
+            mergeWord = self.mergeFn(skewWord & halftoneWord, destWord)
+            destWord = (destMask & mergeWord) | (destWord & (~destMask))
+            self.dest.w_bits.setword(self.destIndex, destWord)
+            # The central horizontal loop requires no store masking
+            self.destIndex += hInc
+            destMask = 0xFFFFFFFF
+            if (self.combinationRule == 3): # Store mode avoids dest merge 
function
+                if ((self.skew == 0) and (halftoneWord == 0xFFFFFFFF)):
+                    # Non-skewed with no halftone
+                    if (self.hDir == -1):
+                        for word in range(2, self.nWords):
+                            thisWord = 
self.source.w_bits.getword(self.sourceIndex)
+                            self.dest.w_bits.setword(self.destIndex, thisWord)
+                            self.sourceIndex += hInc
+                            self.destIndex += hInc
                     else:
-                        this_word = self.source_bits.getword(self.source_index)
-                    skew_word = prev_word | (this_word & no_skew_mask)
-                    prev_word = this_word
-                    skew_word = (self.bit_shift(skew_word, self.skew) |
-                                 self.bit_shift(skew_word, self.skew - 
BitBltShadow.WordSize))
-                merge_word = rarithmetic.r_uint(self.merge(
-                    skew_word & halftone_word,
-                    self.dest_bits.getword(self.dest_index)
-                ))
-                __new = (
-                    (merge_mask & merge_word) |
-                    (~merge_mask & self.dest_bits.getword(self.dest_index))
-                )
-                self.dest_bits.setword(self.dest_index, __new)
-                self.source_index = self.source_index + self.h_dir
-                self.dest_index = self.dest_index + self.h_dir
-                if word == (self.n_words - 1):
-                    merge_mask = self.mask2
+                        for word in range(2, self.nWords):
+                            self.dest.w_bits.setword(self.destIndex, prevWord)
+                            prevWord = 
self.source.w_bits.getword(self.sourceIndex)
+                            self.destIndex += hInc
+                            self.sourceIndex += hInc
                 else:
-                    merge_mask = BitBltShadow.AllOnes
-            self.source_index = self.source_index + self.source_delta
-            self.dest_index = self.dest_index + self.dest_delta
+                    # skewed and/or halftoned
+                    for word in range(2, self.nWords):
+                        thisWord = self.source.w_bits.getword(self.sourceIndex)
+                        self.sourceIndex += hInc
+                        skewWord = self.rotate32bit(thisWord, prevWord, 
skewMask, notSkewMask, unskew)
+                        prevWord = thisWord
+                        self.dest.w_bits.setword(self.destIndex, skewWord & 
halftoneWord)
+                        self.destIndex += hInc
+            else: # Dest merging here...
+                for word in range(2, self.nWords):
+                    thisWord = self.source.w_bits.getword(self.sourceIndex) # 
pick up next word
+                    self.sourceIndex += hInc
+                    skewWord = self.rotate32bit(thisWord, prevWord, skewMask, 
notSkewMask, unskew)
+                    prevWord = thisWord
+                    mergeWord = self.mergeFn(skewWord & halftoneWord, 
self.dest.w_bits.getword(self.destIndex))
+                    self.dest.w_bits.setword(self.destIndex, mergeWord)
+                    self.destIndex += hInc
+            # last word with masking and all
+            if (self.nWords > 1):
+                destMask = self.mask2
+                if (self.sourceIndex >= 0 and self.sourceIndex < sourceLimit):
+                    # NOTE: we are currently overrunning source bits in some 
cases
+                    # self test makes up for it.
+                    thisWord = self.source.w_bits.getword(self.sourceIndex) # 
pick up next word
+                self.sourceIndex += hInc
+                skewWord = self.rotate32bit(thisWord, prevWord, skewMask, 
notSkewMask, unskew)
+                destWord = self.dest.w_bits.getword(self.destIndex)
+                mergeWord = self.mergeFn(skewWord & halftoneWord, destWord)
+                destWord = (destMask & mergeWord) | (destWord & (~destMask))
+                self.dest.w_bits.setword(self.destIndex, destWord)
+                self.destIndex += hInc
+            self.sourceIndex += self.sourceDelta
+            self.destIndex += self.destDelta
 
-    def bit_shift(self, target, amount):
-        if amount > 31 or amount < -31:
-            return 0
-        elif amount > 0:
-            return (rarithmetic.r_uint(target) << amount) & 
BitBltShadow.AllOnes
-        elif amount == 0:
-            return target
-        else:
-            return (rarithmetic.r_uint(target) >> -amount)
+    def mergeFn(self, src, dest):
+        return rarithmetic.r_uint(self.merge(
+            rarithmetic.r_uint(src),
+            rarithmetic.r_uint(dest)
+        ))
 
     def merge(self, source_word, dest_word):
         assert isinstance(source_word, rarithmetic.r_uint) and 
isinstance(dest_word, rarithmetic.r_uint)
-        if self.combination_rule == 0:
+        if self.combinationRule == 0:
             return 0
-        elif self.combination_rule == 1:
+        elif self.combinationRule == 1:
             return source_word & dest_word
-        elif self.combination_rule == 2:
+        elif self.combinationRule == 2:
             return source_word & ~dest_word
-        elif self.combination_rule == 3:
+        elif self.combinationRule == 3:
             return source_word
-        elif self.combination_rule == 4:
+        elif self.combinationRule == 4:
             return ~source_word & dest_word
-        elif self.combination_rule == 5:
+        elif self.combinationRule == 5:
             return dest_word
-        elif self.combination_rule == 6:
+        elif self.combinationRule == 6:
             return source_word ^ dest_word
-        elif self.combination_rule == 7:
+        elif self.combinationRule == 7:
             return source_word | dest_word
-        elif self.combination_rule == 8:
+        elif self.combinationRule == 8:
             return ~source_word & ~dest_word
-        elif self.combination_rule == 9:
+        elif self.combinationRule == 9:
             return ~source_word ^ dest_word
-        elif self.combination_rule == 10:
+        elif self.combinationRule == 10:
             return ~dest_word
-        elif self.combination_rule == 11:
+        elif self.combinationRule == 11:
             return source_word | ~dest_word
-        elif self.combination_rule == 12:
+        elif self.combinationRule == 12:
             return ~source_word
-        elif self.combination_rule == 13:
+        elif self.combinationRule == 13:
             return ~source_word | dest_word
-        elif self.combination_rule == 14:
+        elif self.combinationRule == 14:
             return ~source_word | ~dest_word
-        elif self.combination_rule == 15:
-            return dest_word & BitBltShadow.AllOnes
-        elif self.combination_rule >= 16 and self.combination_rule <= 24:
+        elif self.combinationRule >= 15 and self.combinationRule <= 17:
             return dest_word
-        elif self.combination_rule == 25:
+        elif self.combinationRule == 18:
+            return source_word + dest_word
+        elif self.combinationRule == 19:
+            return source_word - dest_word
+        elif self.combinationRule >= 20 and self.combinationRule <= 24:
+            return source_word
+        elif self.combinationRule == 25:
             if source_word == 0:
                 return dest_word
             else:
-                return source_word | (dest_word & ~source_word)
-        elif 26 <= self.combination_rule <= 41:
+                return self.partitionedANDtonBitsnPartitions(
+                    ~source_word,
+                    dest_word,
+                    self.dest.depth,
+                    self.dest.pixPerWord
+                )
+        elif self.combinationRule == 26:
+            return self.partitionedANDtonBitsnPartitions(
+                ~source_word,
+                dest_word,
+                self.dest.depth,
+                self.dest.pixPerWord
+            )
+        elif 26 < self.combinationRule <= 41:
             return dest_word
         else:
             raise error.PrimitiveFailedError()
 
+    def partitionedANDtonBitsnPartitions(self, word1, word2, nBits, nParts):
+        # partition mask starts at the right
+        mask = BitBltShadow.MaskTable[nBits]
+        result = 0
+        for i in range(1, nParts + 1):
+            if ((word1 & mask) == mask):
+                result = result | (word2 & mask)
+            # slide left to next partition
+            mask = mask << nBits
+        return result
+
     def as_string(bb):
         return 'aBitBlt (destX: %d, destY: %d, sx: %d, sy: %d, dx: %d, dy: %d, 
w: %d, h: %d, hDir: %d, vDir: %d, sDelta: %d, dDelta: %d, skew: %d, sI: %d, dI: 
%d)' % (
             bb.dest_x, bb.dest_y, bb.sx, bb.sy, bb.dx, bb.dy, bb.w, bb.h, 
bb.h_dir, bb.v_dir, bb.source_delta, bb.dest_delta, bb.skew, bb.source_index, 
bb.dest_index)
@@ -1424,11 +1702,22 @@
         self.width = self.space.unwrap_int(self.fetch(1))
         self.height = self.space.unwrap_int(self.fetch(2))
         self.depth = self.space.unwrap_int(self.fetch(3))
+        if self.width < 0 or self.height < 0:
+            raise PrimitiveFailedError()
+        self.msb = self.depth > 0
+        if self.depth < 0:
+            self.depth = -self.depth
+        if self.depth == 0:
+            raise PrimitiveFailedError()
         w_offset = self.fetch(4)
         assert isinstance(w_offset, model.W_PointersObject)
         if not w_offset is self.space.w_nil:
-            self.offset_x = self.space.unwrap_int(w_offset._fetch(0))
-            self.offset_y = self.space.unwrap_int(w_offset._fetch(1))
+            self.offsetX = self.space.unwrap_int(w_offset._fetch(0))
+            self.offsetY = self.space.unwrap_int(w_offset._fetch(1))
+        self.pixPerWord = 32 / self.depth
+        self.pitch = (self.width + (self.pixPerWord - 1)) / self.pixPerWord | 0
+        if self.w_bits.size() != (self.pitch * self.height):
+            raise PrimitiveFailedError()
 
     # def replace_bits(self):
     #     w_bits = self.w_bits
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to