Author: Tim Felgentreff <[email protected]>
Branch: bitblt
Changeset: r165:b1dfe51b9b09
Date: 2013-03-11 13:30 +0100
http://bitbucket.org/pypy/lang-smalltalk/changeset/b1dfe51b9b09/

Log:    create python-bitblt branch

diff --git a/images/mini.image b/images/mini.image
index 
4e0739b0aa769798ae904fee0eff0b0eac8c8368..1bc58a0fd06c4079c4651f707226768f724e405e
GIT binary patch

[cut]

diff --git a/spyvm/interpreter.py b/spyvm/interpreter.py
--- a/spyvm/interpreter.py
+++ b/spyvm/interpreter.py
@@ -75,8 +75,8 @@
                 s_new_context = p.s_new_context
 
     def c_loop(self, s_context):
-        # padding = ' ' * (self.max_stack_depth - self.remaining_stack_depth)
-        # print padding + s_context.short_str()
+        padding = ' ' * (self.max_stack_depth - self.remaining_stack_depth)
+        print padding + s_context.short_str()
         old_pc = 0
         while True:
             pc = s_context._pc
diff --git a/spyvm/model.py b/spyvm/model.py
--- a/spyvm/model.py
+++ b/spyvm/model.py
@@ -369,6 +369,14 @@
         from spyvm.shadow import CachedObjectShadow
         return self.as_special_get_shadow(space, CachedObjectShadow)
 
+    def as_bitblt_get_shadow(self, space):
+        from spyvm.shadow import BitBltShadow
+        return self.as_special_get_shadow(space, BitBltShadow)
+
+    def as_form_get_shadow(self, space):
+        from spyvm.shadow import FormShadow
+        return self.as_special_get_shadow(space, FormShadow)
+
     def become(self, w_other):
         if not isinstance(w_other, W_PointersObject):
             return False
diff --git a/spyvm/primitives.py b/spyvm/primitives.py
--- a/spyvm/primitives.py
+++ b/spyvm/primitives.py
@@ -513,7 +513,7 @@
 INPUT_SEMAPHORE = 93
 GET_NEXT_EVENT = 94
 INPUT_WORD = 95
-OBSOLETE_INDEXED = 96
+BITBLT_COPY_BITS = 96 # OBSOLETE_INDEXED = 96
 SNAPSHOT = 97
 STORE_IMAGE_SEGMENT = 98
 LOAD_IMAGE_SEGMENT = 99
@@ -521,7 +521,7 @@
 BE_CURSOR = 101
 BE_DISPLAY = 102
 SCAN_CHARACTERS = 103
-# OBSOLETE_INDEXED = 104 # also 96
+OBSOLETE_INDEXED = 104 # also 96
 STRING_REPLACE = 105
 SCREEN_SIZE = 106
 MOUSE_BUTTONS = 107
@@ -533,6 +533,21 @@
 def func(interp, s_frame, w_rcvr):
     raise PrimitiveNotYetWrittenError()
 
+@expose_primitive(BITBLT_COPY_BITS, unwrap_spec=[object])
+def func(interp, s_frame, w_rcvr):
+    if not isinstance(w_rcvr, model.W_PointersObject) or w_rcvr.size() < 15:
+        raise PrimitiveFailedError
+    # See BlueBook p.356ff
+    s_bitblt = w_rcvr.as_bitblt_get_shadow(interp.space)
+    s_bitblt.clip_range()
+    if s_bitblt.w <= 0 or s_bitblt.h <= 0:
+        return w_rcvr # null range
+    s_bitblt.compute_masks()
+    s_bitblt.check_overlap()
+    s_bitblt.calculate_offsets()
+    s_bitblt.copy_loop()
+    return w_rcvr
+
 @expose_primitive(BE_CURSOR, unwrap_spec=[object])
 def func(interp, s_frame, w_rcvr):
     # TODO: Use info from cursor object.
@@ -671,6 +686,7 @@
 
 @expose_primitive(DRAW_RECTANGLE, unwrap_spec=[object, int, int, int, int])
 def func(interp, s_frame, w_rcvr, left, right, top, bottom):
+    import pdb; pdb.set_trace()
     raise PrimitiveNotYetWrittenError()
 
 
diff --git a/spyvm/shadow.py b/spyvm/shadow.py
--- a/spyvm/shadow.py
+++ b/spyvm/shadow.py
@@ -692,8 +692,11 @@
         return 0
 
     def short_str(self):
-        return 'BlockContext of %s (%i)' % 
(self.w_method().get_identifier_string(),
-                    self.pc() + 1)
+        return 'BlockContext of %s (%s) [%i]' % (
+            self.w_method().get_identifier_string(),
+            self.w_receiver(),
+            self.pc() + 1
+        )
 
 class MethodContextShadow(ContextPartShadow):
     _attr_ = ['w_closure_or_nil', '_w_receiver', '__w_method']
@@ -843,7 +846,12 @@
 
     def short_str(self):
         block = '[] of' if self.is_closure_context() else ''
-        return '%s %s (%i)' % (block, self.w_method().get_identifier_string(), 
self.pc() + 1)
+        return '%s %s (%s) [%i]' % (
+            block,
+            self.w_method().get_identifier_string(),
+            self.w_receiver(),
+            self.pc() + 1
+        )
 
 class CompiledMethodShadow(object):
     _immutable_fields_ = ["_w_self", "bytecode",
@@ -919,4 +927,240 @@
         return self._w_self._store(n0, w_value)
 
     def update_shadow(self):
-        self.version = Version()
\ No newline at end of file
+        self.version = Version()
+
+
+class BitBltShadow(AbstractCachingShadow):
+    _attrs_ = [# From BitBlt
+               "dest_form", "source_form", "halftone_bits",
+               "combination_rule", "dest_x", "dest_y", "width",
+               "height", "source_x", "source_y", "clip_x", "clip_y",
+               "clip_width", "clip_height", "color_map",
+               # From BitBltSimulation
+               "w", "h", "sx", "sy", "dx", "dy",
+               "dest_bits", "dest_raster", "source_bits", "source_raster",
+               "halftone_bits", "skew", "mask1", "mask2", "skew_mask",
+               "n_words", "h_dir", "v_dir", "preload", "source_index",
+               "dest_index", "source_delta", "dest_delta"]
+
+    RightMasks = [0, 1, 3, 7, 15, 31, 63, 127, 255, 511,
+                  1023, 2047, 4095, 8191, 16383, 32767, 65535]
+    AllOnes = 65535
+
+    def sync_cache(self):
+        self.dest_form = self.fetch(0).as_form_get_shadow(self.space)
+        w_source_form = self.fetch(1)
+        if w_source_form is self.space.w_nil:
+            self.source_form = None
+        else:
+            self.source_form = w_source_form.as_form_get_shadow(self.space)
+        w_halftone_form = self.fetch(2)
+        if w_halftone_form is self.space.w_nil:
+            self.halftone_bits = None
+        elif isinstance(w_halftone_form, model.W_PointersObject):
+            self.halftone_bits = 
w_halftone_form.as_form_get_shadow(self.space).bits
+        elif isinstance(w_halftone_form, model.W_WordsObject):
+            self.halftone_bits = w_halftone_form.words
+        elif isinstance(w_halftone_form, model.W_BytesObject):
+            self.halftone_bits = [ord(byte) for byte in w_halftone_form.bytes]
+        self.combination_rule = self.space.unwrap_int(self.fetch(3))
+        self.dest_x = self.space.unwrap_int(self.fetch(4))
+        self.dest_y = self.space.unwrap_int(self.fetch(5))
+        self.width = self.space.unwrap_int(self.fetch(6))
+        self.height = self.space.unwrap_int(self.fetch(7))
+        self.source_x = self.space.unwrap_int(self.fetch(8))
+        self.source_y = self.space.unwrap_int(self.fetch(9))
+        self.clip_x = self.space.unwrap_int(self.fetch(10))
+        self.clip_y = self.space.unwrap_int(self.fetch(11))
+        self.clip_width = self.space.unwrap_int(self.fetch(12))
+        self.clip_height = self.space.unwrap_int(self.fetch(13))
+        self.color_map = self.fetch(14)
+
+    def clip_range(self):
+        if self.dest_x >= self.clip_x:
+            self.sx = self.source_x
+            self.dx = self.dest_x
+            self.w = self.width
+        else:
+            self.sx = self.source_x + (self.clip_x - self.dest_x)
+            self.w = self.width - (self.clip_x - self.dest_x)
+            self.dx = self.clip_x
+        if self.dx + self.w > self.clip_x + self.clip_width:
+            self.w = self.w - (self.dx + self.w - (self.clip_x + 
self.clip_width))
+        if self.dest_x >= self.clip_y:
+            self.sy = self.source_y
+            self.dy = self.dest_y
+            self.h = self.height
+        else:
+            self.sy = self.source_y + self.clip_y - self.dest_y
+            self.h = self.height - (self.clip_y - self.dest_y)
+            self.dy = self.clip_y
+        if self.dy + self.h > self.clip_y + self.clip_height:
+            self.h = self.h - (self.dy + self.h - (self.clip_y + 
self.clip_height))
+        if self.sx < 0:
+            self.dx = self.dx - self.sx
+            self.w = self.w + self.sx
+            self.sx = 0
+        if self.source_form and self.sx + self.w > self.source_form.width:
+            self.w = self.w - (self.sx + self.w - self.source_form.width)
+        if self.sy < 0:
+            self.dy = self.dy - self.su
+            self.h = self.h + self.sy
+            self.sy = 0
+        if self.source_form and self.sy + self.h > self.source_form.height:
+            self.h = self.h - (self.sy + self.h - self.source_form.height)
+
+    def compute_masks(self):
+        self.dest_bits = self.dest_form.bits
+        self.dest_raster = (self.dest_form.width - 1) / 16 + 1
+        if self.source_form:
+            self.source_bits = self.source_form.bits
+            self.source_raster = (self.source_form.width - 1) / 16 + 1
+        self.skew = (self.sx - self.dx) & 15
+        start_bits = 16 - (self.dx & 15)
+        self.mask1 = BitBltShadow.RightMasks[start_bits]
+        end_bits = 15 - ((self.dx + self.w - 1) & 15)
+        self.mask2 = ~BitBltShadow.RightMasks[end_bits]
+        if self.skew == 0:
+            self.skew_mask = 0
+        else:
+            self.skew_mask = BitBltShadow.RightMasks[16 - self.skew]
+        if self.w < start_bits:
+            self.mask1 = self.mask1 & self.mask2
+            self.mask2 = 0
+            self.n_words = 1
+        else:
+            self.n_words = (self.w - start_bits - 1) / 16 + 2
+
+    def check_overlap(self):
+        self.h_dir = 1
+        self.v_dir = 1
+        if (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
+
+    def calculate_offsets(self):
+        self.preload = self.source_form and self.skew_mask != 0 and self.skew 
<= (self.sx & 15)
+        if self.h_dir < 0:
+            self.preload = not self.preload
+        self.source_index = self.sy * self.source_raster + self.sx / 16
+        self.dest_index = self.dy * self.dest_raster + self.dx / 16
+        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
+
+    def copy_loop(self):
+        for i in xrange(self.h):
+            if self.halftone_bits:
+                halftone_word = self.halftone_bits[self.dy & 15]
+                self.dy = self.dy + self.v_dir
+            else:
+                halftone_word = BitBltShadow.AllOnes
+            skew_word = halftone_word
+            if self.preload:
+                prev_word = self.source_bits[self.source_index]
+                self.source_index = self.source_index + self.h_dir
+            else:
+                prev_word = 0
+            merge_mask = self.mask1
+            for word in xrange(self.n_words):
+                if self.source_form:
+                    prev_word = prev_word & self.skew_mask
+                    this_word = self.source_bits[self.source_index]
+                    skew_word = prev_word | (this_word & ~self.skew_mask)
+                    prev_word = this_word
+                    skew_word = (self.bit_shift(skew_word, self.skew) |
+                                 self.bit_shift(skew_word, self.skew - 16))
+                merge_word = self.merge(
+                    skew_word & halftone_word,
+                    self.dest_bits[self.dest_index]
+                )
+                self.dest_bits[self.dest_index] = (
+                    (merge_mask & merge_word) |
+                    (~merge_mask & self.dest_bits[self.dest_index])
+                )
+                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
+                else:
+                    merge_mask = BitBltShadow.AllOnes
+            self.source_index = self.source_index + self.source_delta
+            self.dest_index = self.dest_index + self.dest_delta
+        self.dest_form.replace_bits(self.dest_bits)
+
+    def bit_shift(self, target, amount):
+        if amount > 0:
+            return target << amount
+        else:
+            return target >> -amount
+
+    def merge(self, source_word, dest_word):
+        if self.combination_rule == 0:
+            return 0
+        elif self.combination_rule == 1:
+            return source_word & dest_word
+        elif self.combination_rule == 2:
+            return source_word & ~dest_word
+        elif self.combination_rule == 3:
+            return source_word
+        elif self.combination_rule == 4:
+            return ~source_word & dest_word
+        elif self.combination_rule == 5:
+            return dest_word
+        elif self.combination_rule == 6:
+            return source_word ^ dest_word
+        elif self.combination_rule == 7:
+            return source_word | dest_word
+        elif self.combination_rule == 8:
+            return ~source_word & ~dest_word
+        elif self.combination_rule == 9:
+            return ~source_word ^ dest_word
+        elif self.combination_rule == 10:
+            return ~dest_word
+        elif self.combination_rule == 11:
+            return source_word | ~dest_word
+        elif self.combination_rule == 12:
+            return ~source_word
+        elif self.combination_rule == 13:
+            return ~source_word | dest_word
+        elif self.combination_rule == 14:
+            return ~source_word | ~dest_word
+        elif self.combination_rule == 15:
+            return BitBltShadow.AllOnes
+
+
+class FormShadow(AbstractCachingShadow):
+    _attrs_ = ["bits", "width", "height", "depth", "offset_x", "offset_y"]
+
+    def sync_cache(self):
+        w_bits = self.fetch(0)
+        if isinstance(w_bits, model.W_WordsObject):
+            self.bits = w_bits.words
+        else:
+            self.bits = [ord(byte) for byte in w_bits.bytes]
+        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))
+        w_offset = self.fetch(4)
+        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))
+
+    def replace_bits(self, bits):
+        w_bits = self.fetch(0)
+        if isinstance(bits, model.W_WordsObject):
+            w_bits.words[:] = bits
+        else:
+            w_bits.bytes[:] = [chr(byte) for byte in bits]
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to