diff --git a/lib/pygraphics/_blit_hooks.py b/lib/pygraphics/_blit_hooks.py index 1a7af2a..0461dcf 100644 --- a/lib/pygraphics/_blit_hooks.py +++ b/lib/pygraphics/_blit_hooks.py @@ -43,22 +43,23 @@ def key_to_bytes(key, bpp): def clip_blit_bounds(canvas, source, x, y): """Return clipped destination/source origin as ``(x0, y0, w, h, src_x, src_y)``. - Returns ``None`` when the blit is fully outside the canvas. + Returns ``None`` when the blit is fully outside the canvas. ``source`` may + be a FrameBuffer or MicroPython's tuple form ``(buffer, width, height, + format[, stride])``, which ``framebuf.blit`` accepts too. """ - if ( - (-x >= source.width) - or (-y >= source.height) - or (x >= canvas.width) - or (y >= canvas.height) - ): + if isinstance(source, tuple): + src_w, src_h = source[1], source[2] + else: + src_w, src_h = source.width, source.height + if (-x >= src_w) or (-y >= src_h) or (x >= canvas.width) or (y >= canvas.height): return None x0 = max(0, x) y0 = max(0, y) src_x = max(0, -x) src_y = max(0, -y) - w = min(canvas.width, x + source.width) - x0 - h = min(canvas.height, y + source.height) - y0 + w = min(canvas.width, x + src_w) - x0 + h = min(canvas.height, y + src_h) - y0 return x0, y0, w, h, src_x, src_y diff --git a/tests/test_framebuf_plus.py b/tests/test_framebuf_plus.py index d53245c..fd77e95 100644 --- a/tests/test_framebuf_plus.py +++ b/tests/test_framebuf_plus.py @@ -93,6 +93,13 @@ def test_blit_returns_area(self): self.assertEqual(self.fb.blit(src, 2, 2), Area(2, 2, 4, 4)) self.assertEqual(self.fb.pixel(2, 2), 0xABCD) + def test_blit_tuple_source_returns_area(self): + # MicroPython's framebuf.blit takes (buffer, width, height, format). + buf = bytearray(b"\xcd\xab" * 12) + self.assertEqual(self.fb.blit((buf, 4, 3, RGB565), 2, 2), Area(2, 2, 4, 3)) + self.assertEqual(self.fb.pixel(2, 2), 0xABCD) + self.assertIsNone(self.fb.blit((buf, 4, 3, RGB565), -4, 0)) + def test_scroll_returns_area(self): self.fb.fill_rect(0, 0, 4, 4, 0xFFFF) self.assertEqual(self.fb.scroll(1, 0), Area(0, 0, 16, 16))