import os import unittest from pygame.tests import test_utils from pygame.tests.test_utils import ( example_path, AssertRaisesRegexMixin, SurfaceSubclass, ) try: from pygame.tests.test_utils.arrinter import * except (ImportError, NameError): pass import pygame from pygame.locals import * from pygame.compat import xrange_, as_bytes, as_unicode from pygame.bufferproxy import BufferProxy import platform import gc import weakref import ctypes IS_PYPY = "PyPy" == platform.python_implementation() SDL1 = pygame.get_sdl_version()[0] < 2 def intify(i): """If i is a long, cast to an int while preserving the bits""" if 0x80000000 & i: return int((0xFFFFFFFF & i)) return i def longify(i): """If i is an int, cast to a long while preserving the bits""" if i < 0: return 0xFFFFFFFF & i return long(i) class SurfaceTypeTest(AssertRaisesRegexMixin, unittest.TestCase): def test_surface__pixel_format_as_surface_subclass(self): """Ensure a subclassed surface can be used for pixel format when creating a new surface.""" expected_depth = 16 expected_flags = SRCALPHA expected_size = (13, 37) depth_surface = SurfaceSubclass((11, 21), expected_flags, expected_depth) surface = pygame.Surface(expected_size, expected_flags, depth_surface) self.assertIsNot(surface, depth_surface) self.assertIsInstance(surface, pygame.Surface) self.assertNotIsInstance(surface, SurfaceSubclass) self.assertEqual(surface.get_size(), expected_size) self.assertEqual(surface.get_flags(), expected_flags) self.assertEqual(surface.get_bitsize(), expected_depth) def test_set_clip(self): """see if surface.set_clip(None) works correctly.""" s = pygame.Surface((800, 600)) r = pygame.Rect(10, 10, 10, 10) s.set_clip(r) r.move_ip(10, 0) s.set_clip(None) res = s.get_clip() # this was garbled before. self.assertEqual(res[0], 0) self.assertEqual(res[2], 800) def test_print(self): surf = pygame.Surface((70, 70), 0, 32) self.assertEqual(repr(surf), "") def test_keyword_arguments(self): surf = pygame.Surface((70, 70), flags=SRCALPHA, depth=32) self.assertEqual(surf.get_flags() & SRCALPHA, SRCALPHA) self.assertEqual(surf.get_bitsize(), 32) # sanity check to make sure the check below is valid surf_16 = pygame.Surface((70, 70), 0, 16) self.assertEqual(surf_16.get_bytesize(), 2) # try again with an argument list surf_16 = pygame.Surface((70, 70), depth=16) self.assertEqual(surf_16.get_bytesize(), 2) def test_set_at(self): # 24bit surfaces s = pygame.Surface((100, 100), 0, 24) s.fill((0, 0, 0)) # set it with a tuple. s.set_at((0, 0), (10, 10, 10, 255)) r = s.get_at((0, 0)) self.assertIsInstance(r, pygame.Color) self.assertEqual(r, (10, 10, 10, 255)) # try setting a color with a single integer. s.fill((0, 0, 0, 255)) s.set_at((10, 1), 0x0000FF) r = s.get_at((10, 1)) self.assertEqual(r, (0, 0, 255, 255)) def test_set_at__big_endian(self): """ png files are loaded in big endian format (BGR rather than RGB)""" pygame.display.init() try: image = pygame.image.load(example_path(os.path.join("data", "BGR.png"))) # Check they start red, green and blue self.assertEqual(image.get_at((10, 10)), pygame.Color(255, 0, 0)) self.assertEqual(image.get_at((10, 20)), pygame.Color(0, 255, 0)) self.assertEqual(image.get_at((10, 40)), pygame.Color(0, 0, 255)) # Set three pixels that are already red, green, blue # to red, green and, blue with set_at: image.set_at((10, 10), pygame.Color(255, 0, 0)) image.set_at((10, 20), pygame.Color(0, 255, 0)) image.set_at((10, 40), pygame.Color(0, 0, 255)) # Check they still are self.assertEqual(image.get_at((10, 10)), pygame.Color(255, 0, 0)) self.assertEqual(image.get_at((10, 20)), pygame.Color(0, 255, 0)) self.assertEqual(image.get_at((10, 40)), pygame.Color(0, 0, 255)) finally: pygame.display.quit() def test_SRCALPHA(self): # has the flag been passed in ok? surf = pygame.Surface((70, 70), SRCALPHA, 32) self.assertEqual(surf.get_flags() & SRCALPHA, SRCALPHA) # 24bit surfaces can not have SRCALPHA. self.assertRaises(ValueError, pygame.Surface, (100, 100), pygame.SRCALPHA, 24) # if we have a 32 bit surface, the SRCALPHA should have worked too. surf2 = pygame.Surface((70, 70), SRCALPHA) if surf2.get_bitsize() == 32: self.assertEqual(surf2.get_flags() & SRCALPHA, SRCALPHA) def test_flags_default0_nodisplay(self): """ is set to zero, and SRCALPH is not set by default with no display initialized. """ pygame.display.quit() surf = pygame.Surface((70, 70)) self.assertEqual(surf.get_flags() & SRCALPHA, 0) def test_flags_default0_display(self): """ is set to zero, and SRCALPH is not set by default even when the display is initialized. """ pygame.display.set_mode((320, 200)) try: surf = pygame.Surface((70, 70)) self.assertEqual(surf.get_flags() & SRCALPHA, 0) finally: pygame.display.quit() def test_masks(self): def make_surf(bpp, flags, masks): pygame.Surface((10, 10), flags, bpp, masks) # With some masks SDL_CreateRGBSurface does not work properly. masks = (0xFF000000, 0xFF0000, 0xFF00, 0) self.assertEqual(make_surf(32, 0, masks), None) # For 24 and 32 bit surfaces Pygame assumes no losses. masks = (0x7F0000, 0xFF00, 0xFF, 0) self.assertRaises(ValueError, make_surf, 24, 0, masks) self.assertRaises(ValueError, make_surf, 32, 0, masks) # What contiguous bits in a mask. masks = (0x6F0000, 0xFF00, 0xFF, 0) self.assertRaises(ValueError, make_surf, 32, 0, masks) def test_get_bounding_rect(self): surf = pygame.Surface((70, 70), SRCALPHA, 32) surf.fill((0, 0, 0, 0)) bound_rect = surf.get_bounding_rect() self.assertEqual(bound_rect.width, 0) self.assertEqual(bound_rect.height, 0) surf.set_at((30, 30), (255, 255, 255, 1)) bound_rect = surf.get_bounding_rect() self.assertEqual(bound_rect.left, 30) self.assertEqual(bound_rect.top, 30) self.assertEqual(bound_rect.width, 1) self.assertEqual(bound_rect.height, 1) surf.set_at((29, 29), (255, 255, 255, 1)) bound_rect = surf.get_bounding_rect() self.assertEqual(bound_rect.left, 29) self.assertEqual(bound_rect.top, 29) self.assertEqual(bound_rect.width, 2) self.assertEqual(bound_rect.height, 2) surf = pygame.Surface((70, 70), 0, 24) surf.fill((0, 0, 0)) bound_rect = surf.get_bounding_rect() self.assertEqual(bound_rect.width, surf.get_width()) self.assertEqual(bound_rect.height, surf.get_height()) surf.set_colorkey((0, 0, 0)) bound_rect = surf.get_bounding_rect() self.assertEqual(bound_rect.width, 0) self.assertEqual(bound_rect.height, 0) surf.set_at((30, 30), (255, 255, 255)) bound_rect = surf.get_bounding_rect() self.assertEqual(bound_rect.left, 30) self.assertEqual(bound_rect.top, 30) self.assertEqual(bound_rect.width, 1) self.assertEqual(bound_rect.height, 1) surf.set_at((60, 60), (255, 255, 255)) bound_rect = surf.get_bounding_rect() self.assertEqual(bound_rect.left, 30) self.assertEqual(bound_rect.top, 30) self.assertEqual(bound_rect.width, 31) self.assertEqual(bound_rect.height, 31) # Issue #180 pygame.display.init() try: surf = pygame.Surface((4, 1), 0, 8) surf.fill((255, 255, 255)) surf.get_bounding_rect() # Segfault. finally: pygame.display.quit() def test_copy(self): """Ensure a surface can be copied.""" color = (25, 25, 25, 25) s1 = pygame.Surface((32, 32), pygame.SRCALPHA, 32) s1.fill(color) s2 = s1.copy() s1rect = s1.get_rect() s2rect = s2.get_rect() self.assertEqual(s1rect.size, s2rect.size) self.assertEqual(s2.get_at((10, 10)), color) def test_fill(self): """Ensure a surface can be filled.""" color = (25, 25, 25, 25) fill_rect = pygame.Rect(0, 0, 16, 16) s1 = pygame.Surface((32, 32), pygame.SRCALPHA, 32) s1.fill(color, fill_rect) for pt in test_utils.rect_area_pts(fill_rect): self.assertEqual(s1.get_at(pt), color) for pt in test_utils.rect_outer_bounds(fill_rect): self.assertNotEqual(s1.get_at(pt), color) def test_fill_rle(self): """Test RLEACCEL flag with fill()""" color = (250, 25, 25, 255) surf = pygame.Surface((32, 32)) blit_surf = pygame.Surface((32, 32)) blit_surf.set_colorkey((255, 0, 255), pygame.RLEACCEL) self.assertTrue(blit_surf.get_flags() & pygame.RLEACCELOK) surf.blit(blit_surf, (0, 0)) blit_surf.fill(color) self.assertEqual( blit_surf.mustlock(), (blit_surf.get_flags() & pygame.RLEACCEL) != 0 ) self.assertTrue(blit_surf.get_flags() & pygame.RLEACCEL) def test_mustlock_rle(self): """Test RLEACCEL flag with mustlock()""" surf = pygame.Surface((100, 100)) blit_surf = pygame.Surface((100, 100)) blit_surf.set_colorkey((0, 0, 255), pygame.RLEACCEL) self.assertTrue(blit_surf.get_flags() & pygame.RLEACCELOK) surf.blit(blit_surf, (0, 0)) self.assertTrue(blit_surf.get_flags() & pygame.RLEACCEL) self.assertTrue(blit_surf.mustlock()) @unittest.skipIf(pygame.get_sdl_version()[0] == 1, "only works in SDL2") def test_mustlock_surf_alpha_rle(self): """Test RLEACCEL flag with mustlock() on a surface with per pixel alpha - new feature in SDL2""" surf = pygame.Surface((100, 100)) blit_surf = pygame.Surface((100, 100), depth=32, flags=pygame.SRCALPHA) blit_surf.set_colorkey((192, 191, 192, 255), pygame.RLEACCEL) self.assertTrue(blit_surf.get_flags() & pygame.RLEACCELOK) surf.blit(blit_surf, (0, 0)) self.assertTrue(blit_surf.get_flags() & pygame.RLEACCEL) self.assertTrue(blit_surf.get_flags() & pygame.SRCALPHA) self.assertTrue(blit_surf.mustlock()) def test_copy_rle(self): """ Test copying a surface set to use run length encoding""" s1 = pygame.Surface((32, 32), 24) s1.set_colorkey((255, 0, 255), pygame.RLEACCEL) self.assertTrue(s1.get_flags() & pygame.RLEACCELOK) newsurf = s1.copy() self.assertTrue(s1.get_flags() & pygame.RLEACCELOK) self.assertTrue(newsurf.get_flags() & pygame.RLEACCELOK) def test_subsurface_rle(self): """Ensure an RLE sub-surface works independently of its parent.""" color = (250, 25, 25, 255) color2 = (200, 200, 250, 255) sub_rect = pygame.Rect(16, 16, 16, 16) s0 = pygame.Surface((32, 32), 24) s1 = pygame.Surface((32, 32), 24) s1.set_colorkey((255, 0, 255), pygame.RLEACCEL) s1.fill(color) s2 = s1.subsurface(sub_rect) s2.fill(color2) s0.blit(s1, (0, 0)) self.assertTrue(s1.get_flags() & pygame.RLEACCEL) self.assertTrue(not s2.get_flags() & pygame.RLEACCEL) def test_subsurface_rle2(self): """Ensure an RLE sub-surface works independently of its parent.""" color = (250, 25, 25, 255) color2 = (200, 200, 250, 255) sub_rect = pygame.Rect(16, 16, 16, 16) s0 = pygame.Surface((32, 32), 24) s1 = pygame.Surface((32, 32), 24) s1.set_colorkey((255, 0, 255), pygame.RLEACCEL) s1.fill(color) s2 = s1.subsurface(sub_rect) s2.fill(color2) s0.blit(s2, (0, 0)) self.assertTrue(s1.get_flags() & pygame.RLEACCELOK) self.assertTrue(not s2.get_flags() & pygame.RLEACCELOK) def test_solarwolf_rle_usage(self): """ Test for error/crash when calling set_colorkey() followed by convert twice in succession. Code originally taken from solarwolf. """ def optimize(img): clear = img.get_colorkey() img.set_colorkey(clear, RLEACCEL) self.assertEqual(img.get_colorkey(), clear) return img.convert() pygame.display.init() try: pygame.display.set_mode((640, 480)) image = pygame.image.load(example_path(os.path.join("data", "alien1.png"))) image = image.convert() orig_colorkey = image.get_colorkey() image = optimize(image) image = optimize(image) self.assertTrue(image.get_flags() & pygame.RLEACCELOK) self.assertTrue(not image.get_flags() & pygame.RLEACCEL) self.assertEqual(image.get_colorkey(), orig_colorkey) self.assertTrue(isinstance(image, pygame.Surface)) finally: pygame.display.quit() def test_solarwolf_rle_usage_2(self): """ Test for RLE status after setting alpha """ pygame.display.init() try: pygame.display.set_mode((640, 480), depth=32) blit_to_surf = pygame.Surface((100, 100)) image = pygame.image.load(example_path(os.path.join("data", "alien1.png"))) image = image.convert() orig_colorkey = image.get_colorkey() # set the colorkey with RLEACCEL, should add the RLEACCELOK flag image.set_colorkey(orig_colorkey, RLEACCEL) self.assertTrue(image.get_flags() & pygame.RLEACCELOK) self.assertTrue(not image.get_flags() & pygame.RLEACCEL) # now blit the surface - should add the RLEACCEL flag blit_to_surf.blit(image, (0, 0)) self.assertTrue(image.get_flags() & pygame.RLEACCELOK) self.assertTrue(image.get_flags() & pygame.RLEACCEL) # Now set the alpha, without RLE acceleration - should strip all # RLE flags image.set_alpha(90) self.assertTrue(not image.get_flags() & pygame.RLEACCELOK) self.assertTrue(not image.get_flags() & pygame.RLEACCEL) finally: pygame.display.quit() @unittest.skipIf(pygame.get_sdl_version()[0] == 2, "only works in SDL 1") def test_set_alpha__rle_state_change(self): """ Likely related to: https://bugzilla.libsdl.org/show_bug.cgi?id=5321 """ pygame.display.init() try: pygame.display.set_mode((640, 480)) blit_to_surf = pygame.Surface((80, 71)) blit_to_surf.fill((255, 255, 255)) image = pygame.image.load(example_path(os.path.join("data", "alien1.png"))) image = image.convert() # Add the RLE flag while setting alpha for the whole surface image.set_alpha(90, RLEACCEL) blit_to_surf.blit(image, (0, 0)) sample_pixel_rle = blit_to_surf.get_at((50, 50)) # Now set the alpha again to the same value - but without RLE # acceleration image.set_alpha(90) blit_to_surf.fill((255, 255, 255)) blit_to_surf.blit(image, (0, 0)) sample_pixel_no_rle = blit_to_surf.get_at((50, 50)) self.assertAlmostEqual(sample_pixel_rle.r, sample_pixel_no_rle.r, delta=2) self.assertAlmostEqual(sample_pixel_rle.g, sample_pixel_no_rle.g, delta=2) self.assertAlmostEqual(sample_pixel_rle.b, sample_pixel_no_rle.b, delta=2) finally: pygame.display.quit() def test_set_alpha__set_colorkey_rle(self): pygame.display.init() try: pygame.display.set_mode((640, 480)) blit_to_surf = pygame.Surface((80, 71)) blit_to_surf.fill((255, 255, 255)) image = pygame.image.load(example_path(os.path.join("data", "alien1.png"))) image = image.convert() orig_colorkey = image.get_colorkey() # Add the RLE flag while setting alpha for the whole surface image.set_alpha(90, RLEACCEL) blit_to_surf.blit(image, (0, 0)) sample_pixel_rle = blit_to_surf.get_at((50, 50)) # Now reset the colorkey to the original value with RLE self.assertEqual(image.get_colorkey(), orig_colorkey) image.set_colorkey(orig_colorkey, RLEACCEL) blit_to_surf.fill((255, 255, 255)) blit_to_surf.blit(image, (0, 0)) sample_pixel_no_rle = blit_to_surf.get_at((50, 50)) self.assertAlmostEqual(sample_pixel_rle.r, sample_pixel_no_rle.r, delta=2) self.assertAlmostEqual(sample_pixel_rle.g, sample_pixel_no_rle.g, delta=2) self.assertAlmostEqual(sample_pixel_rle.b, sample_pixel_no_rle.b, delta=2) finally: pygame.display.quit() def test_fill_negative_coordinates(self): # negative coordinates should be clipped by fill, and not draw outside the surface. color = (25, 25, 25, 25) color2 = (20, 20, 20, 25) fill_rect = pygame.Rect(-10, -10, 16, 16) s1 = pygame.Surface((32, 32), pygame.SRCALPHA, 32) r1 = s1.fill(color, fill_rect) c = s1.get_at((0, 0)) self.assertEqual(c, color) # make subsurface in the middle to test it doesn't over write. s2 = s1.subsurface((5, 5, 5, 5)) r2 = s2.fill(color2, (-3, -3, 5, 5)) c2 = s1.get_at((4, 4)) self.assertEqual(c, color) # rect returns the area we actually fill. r3 = s2.fill(color2, (-30, -30, 5, 5)) # since we are using negative coords, it should be an zero sized rect. self.assertEqual(tuple(r3), (0, 0, 0, 0)) def test_fill_keyword_args(self): """Ensure fill() accepts keyword arguments.""" color = (1, 2, 3, 255) area = (1, 1, 2, 2) s1 = pygame.Surface((4, 4), 0, 32) s1.fill(special_flags=pygame.BLEND_ADD, color=color, rect=area) self.assertEqual(s1.get_at((0, 0)), (0, 0, 0, 255)) self.assertEqual(s1.get_at((1, 1)), color) ######################################################################## def test_get_alpha(self): """Ensure a surface's alpha value can be retrieved.""" s1 = pygame.Surface((32, 32), pygame.SRCALPHA, 32) self.assertEqual(s1.get_alpha(), 255) for alpha in (0, 32, 127, 255): s1.set_alpha(alpha) for t in range(4): s1.set_alpha(s1.get_alpha()) self.assertEqual(s1.get_alpha(), alpha) ######################################################################## def test_get_bytesize(self): """Ensure a surface's bit and byte sizes can be retrieved.""" pygame.display.init() try: depth = 32 depth_bytes = 4 s1 = pygame.Surface((32, 32), pygame.SRCALPHA, depth) self.assertEqual(s1.get_bytesize(), depth_bytes) self.assertEqual(s1.get_bitsize(), depth) depth = 15 depth_bytes = 2 s1 = pygame.Surface((32, 32), 0, depth) self.assertEqual(s1.get_bytesize(), depth_bytes) self.assertEqual(s1.get_bitsize(), depth) depth = 12 depth_bytes = 2 s1 = pygame.Surface((32, 32), 0, depth) self.assertEqual(s1.get_bytesize(), depth_bytes) self.assertEqual(s1.get_bitsize(), depth) with self.assertRaises(pygame.error): surface = pygame.display.set_mode() pygame.display.quit() surface.get_bytesize() finally: pygame.display.quit() ######################################################################## def test_get_flags(self): """Ensure a surface's flags can be retrieved.""" s1 = pygame.Surface((32, 32), pygame.SRCALPHA, 32) self.assertEqual(s1.get_flags(), pygame.SRCALPHA) @unittest.skipIf( os.environ.get("SDL_VIDEODRIVER") == "dummy", 'requires a non-"dummy" SDL_VIDEODRIVER', ) def test_get_flags__display_surf(self): pygame.display.init() try: # FULLSCREEN screen_surf = pygame.display.set_mode((600, 400), flags=0) self.assertFalse(screen_surf.get_flags() & pygame.FULLSCREEN) screen_surf = pygame.display.set_mode((600, 400), flags=pygame.FULLSCREEN) self.assertTrue(screen_surf.get_flags() & pygame.FULLSCREEN) # NOFRAME screen_surf = pygame.display.set_mode((600, 400),flags=0) self.assertFalse(screen_surf.get_flags() & pygame.NOFRAME) screen_surf = pygame.display.set_mode((600, 400), flags=pygame.NOFRAME) self.assertTrue(screen_surf.get_flags() & pygame.NOFRAME) # RESIZABLE screen_surf = pygame.display.set_mode((600, 400),flags=0) self.assertFalse(screen_surf.get_flags() & pygame.RESIZABLE) screen_surf = pygame.display.set_mode((600, 400), flags=pygame.RESIZABLE) self.assertTrue(screen_surf.get_flags() & pygame.RESIZABLE) # OPENGL screen_surf = pygame.display.set_mode((600, 400), flags=0) # it can have an OPENGL flag by default on Macos? if not (screen_surf.get_flags() & pygame.OPENGL): self.assertFalse(screen_surf.get_flags() & pygame.OPENGL) try: pygame.display.set_mode((200, 200), pygame.OPENGL, 32) except pygame.error: pass # If we can't create OPENGL surface don't try this test else: self.assertTrue(screen_surf.get_flags() & pygame.OPENGL) finally: pygame.display.quit() ######################################################################## def test_get_parent(self): """Ensure a surface's parent can be retrieved.""" pygame.display.init() try: parent = pygame.Surface((16, 16)) child = parent.subsurface((0, 0, 5, 5)) self.assertIs(child.get_parent(), parent) with self.assertRaises(pygame.error): surface = pygame.display.set_mode() pygame.display.quit() surface.get_parent() finally: pygame.display.quit() ######################################################################## def test_get_rect(self): """Ensure a surface's rect can be retrieved.""" size = (16, 16) surf = pygame.Surface(size) rect = surf.get_rect() self.assertEqual(rect.size, size) ######################################################################## def test_get_width__size_and_height(self): """Ensure a surface's size, width and height can be retrieved.""" for w in xrange_(0, 255, 32): for h in xrange_(0, 127, 15): s = pygame.Surface((w, h)) self.assertEqual(s.get_width(), w) self.assertEqual(s.get_height(), h) self.assertEqual(s.get_size(), (w, h)) def test_get_view(self): """Ensure a buffer view of the surface's pixels can be retrieved.""" # Check that BufferProxys are returned when array depth is supported, # ValueErrors returned otherwise. Error = ValueError s = pygame.Surface((5, 7), 0, 8) v2 = s.get_view("2") self.assertRaises(Error, s.get_view, "0") self.assertRaises(Error, s.get_view, "1") self.assertIsInstance(v2, BufferProxy) self.assertRaises(Error, s.get_view, "3") s = pygame.Surface((8, 7), 0, 8) length = s.get_bytesize() * s.get_width() * s.get_height() v0 = s.get_view("0") v1 = s.get_view("1") self.assertIsInstance(v0, BufferProxy) self.assertEqual(v0.length, length) self.assertIsInstance(v1, BufferProxy) self.assertEqual(v1.length, length) s = pygame.Surface((5, 7), 0, 16) v2 = s.get_view("2") self.assertRaises(Error, s.get_view, "0") self.assertRaises(Error, s.get_view, "1") self.assertIsInstance(v2, BufferProxy) self.assertRaises(Error, s.get_view, "3") s = pygame.Surface((8, 7), 0, 16) length = s.get_bytesize() * s.get_width() * s.get_height() v0 = s.get_view("0") v1 = s.get_view("1") self.assertIsInstance(v0, BufferProxy) self.assertEqual(v0.length, length) self.assertIsInstance(v1, BufferProxy) self.assertEqual(v1.length, length) s = pygame.Surface((5, 7), pygame.SRCALPHA, 16) v2 = s.get_view("2") self.assertIsInstance(v2, BufferProxy) self.assertRaises(Error, s.get_view, "3") s = pygame.Surface((5, 7), 0, 24) v2 = s.get_view("2") v3 = s.get_view("3") self.assertRaises(Error, s.get_view, "0") self.assertRaises(Error, s.get_view, "1") self.assertIsInstance(v2, BufferProxy) self.assertIsInstance(v3, BufferProxy) s = pygame.Surface((8, 7), 0, 24) length = s.get_bytesize() * s.get_width() * s.get_height() v0 = s.get_view("0") v1 = s.get_view("1") self.assertIsInstance(v0, BufferProxy) self.assertEqual(v0.length, length) self.assertIsInstance(v1, BufferProxy) self.assertEqual(v1.length, length) s = pygame.Surface((5, 7), 0, 32) length = s.get_bytesize() * s.get_width() * s.get_height() v0 = s.get_view("0") v1 = s.get_view("1") v2 = s.get_view("2") v3 = s.get_view("3") self.assertIsInstance(v0, BufferProxy) self.assertEqual(v0.length, length) self.assertIsInstance(v1, BufferProxy) self.assertEqual(v1.length, length) self.assertIsInstance(v2, BufferProxy) self.assertIsInstance(v3, BufferProxy) s2 = s.subsurface((0, 0, 4, 7)) self.assertRaises(Error, s2.get_view, "0") self.assertRaises(Error, s2.get_view, "1") s2 = None s = pygame.Surface((5, 7), pygame.SRCALPHA, 32) for kind in ("2", "3", "a", "A", "r", "R", "g", "G", "b", "B"): self.assertIsInstance(s.get_view(kind), BufferProxy) # Check default argument value: '2' s = pygame.Surface((2, 4), 0, 32) v = s.get_view() if not IS_PYPY: ai = ArrayInterface(v) self.assertEqual(ai.nd, 2) # Check locking. s = pygame.Surface((2, 4), 0, 32) self.assertFalse(s.get_locked()) v = s.get_view("2") self.assertFalse(s.get_locked()) c = v.__array_interface__ self.assertTrue(s.get_locked()) c = None gc.collect() self.assertTrue(s.get_locked()) v = None gc.collect() self.assertFalse(s.get_locked()) # Check invalid view kind values. s = pygame.Surface((2, 4), pygame.SRCALPHA, 32) self.assertRaises(TypeError, s.get_view, "") self.assertRaises(TypeError, s.get_view, "9") self.assertRaises(TypeError, s.get_view, "RGBA") self.assertRaises(TypeError, s.get_view, 2) # Both unicode and bytes strings are allowed for kind. s = pygame.Surface((2, 4), 0, 32) s.get_view(as_unicode("2")) s.get_view(as_bytes("2")) # Garbage collection s = pygame.Surface((2, 4), 0, 32) weak_s = weakref.ref(s) v = s.get_view("3") weak_v = weakref.ref(v) gc.collect() self.assertTrue(weak_s() is s) self.assertTrue(weak_v() is v) del v gc.collect() self.assertTrue(weak_s() is s) self.assertTrue(weak_v() is None) del s gc.collect() self.assertTrue(weak_s() is None) def test_get_buffer(self): # Check that get_buffer works for all pixel sizes and for a subsurface. # Check for all pixel sizes for bitsize in [8, 16, 24, 32]: s = pygame.Surface((5, 7), 0, bitsize) length = s.get_pitch() * s.get_height() v = s.get_buffer() self.assertIsInstance(v, BufferProxy) self.assertEqual(v.length, length) self.assertEqual(repr(v), "") # Check for a subsurface (not contiguous) s = pygame.Surface((7, 10), 0, 32) s2 = s.subsurface((1, 2, 5, 7)) length = s2.get_pitch() * s2.get_height() v = s2.get_buffer() self.assertIsInstance(v, BufferProxy) self.assertEqual(v.length, length) # Check locking. s = pygame.Surface((2, 4), 0, 32) v = s.get_buffer() self.assertTrue(s.get_locked()) v = None gc.collect() self.assertFalse(s.get_locked()) OLDBUF = hasattr(pygame.bufferproxy, "get_segcount") @unittest.skipIf(not OLDBUF, "old buffer not available") def test_get_buffer_oldbuf(self): from pygame.bufferproxy import get_segcount, get_write_buffer s = pygame.Surface((2, 4), pygame.SRCALPHA, 32) v = s.get_buffer() segcount, buflen = get_segcount(v) self.assertEqual(segcount, 1) self.assertEqual(buflen, s.get_pitch() * s.get_height()) seglen, segaddr = get_write_buffer(v, 0) self.assertEqual(segaddr, s._pixels_address) self.assertEqual(seglen, buflen) @unittest.skipIf(not OLDBUF, "old buffer not available") def test_get_view_oldbuf(self): from pygame.bufferproxy import get_segcount, get_write_buffer s = pygame.Surface((2, 4), pygame.SRCALPHA, 32) v = s.get_view("1") segcount, buflen = get_segcount(v) self.assertEqual(segcount, 8) self.assertEqual(buflen, s.get_pitch() * s.get_height()) seglen, segaddr = get_write_buffer(v, 7) self.assertEqual(segaddr, s._pixels_address + s.get_bytesize() * 7) self.assertEqual(seglen, s.get_bytesize()) def test_set_colorkey(self): # __doc__ (as of 2008-06-25) for pygame.surface.Surface.set_colorkey: # Surface.set_colorkey(Color, flags=0): return None # Surface.set_colorkey(None): return None # Set the transparent colorkey s = pygame.Surface((16, 16), pygame.SRCALPHA, 32) colorkeys = ((20, 189, 20, 255), (128, 50, 50, 255), (23, 21, 255, 255)) for colorkey in colorkeys: s.set_colorkey(colorkey) for t in range(4): s.set_colorkey(s.get_colorkey()) self.assertEqual(s.get_colorkey(), colorkey) def test_set_masks(self): s = pygame.Surface((32, 32)) r, g, b, a = s.get_masks() if pygame.get_sdl_version()[0] == 1: s.set_masks((b, g, r, a)) r2, g2, b2, a2 = s.get_masks() self.assertEqual((r, g, b, a), (b2, g2, r2, a2)) else: self.assertRaises(TypeError, s.set_masks, (b, g, r, a)) def test_set_shifts(self): s = pygame.Surface((32, 32)) r, g, b, a = s.get_shifts() if pygame.get_sdl_version()[0] == 1: s.set_shifts((b, g, r, a)) r2, g2, b2, a2 = s.get_shifts() self.assertEqual((r, g, b, a), (b2, g2, r2, a2)) else: self.assertRaises(TypeError, s.set_shifts, (b, g, r, a)) def test_blit_keyword_args(self): color = (1, 2, 3, 255) s1 = pygame.Surface((4, 4), 0, 32) s2 = pygame.Surface((2, 2), 0, 32) s2.fill((1, 2, 3)) s1.blit(special_flags=BLEND_ADD, source=s2, dest=(1, 1), area=s2.get_rect()) self.assertEqual(s1.get_at((0, 0)), (0, 0, 0, 255)) self.assertEqual(s1.get_at((1, 1)), color) @unittest.skipIf(pygame.get_sdl_version()[0] == 1, "only works in SDL2") def test_blit_big_rects(self): """SDL2 can have more than 16 bits for x, y, width, height.""" big_surf = pygame.Surface((100, 68000), 0, 32) big_surf_color = (255, 0, 0) big_surf.fill(big_surf_color) background = pygame.Surface((500, 500), 0, 32) background_color = (0, 255, 0) background.fill(background_color) # copy parts of the big_surf using more than 16bit parts. background.blit(big_surf, (100, 100), area=(0, 16000, 100, 100)) background.blit(big_surf, (200, 200), area=(0, 32000, 100, 100)) background.blit(big_surf, (300, 300), area=(0, 66000, 100, 100)) # check that all three areas are drawn. self.assertEqual(background.get_at((101, 101)), big_surf_color) self.assertEqual(background.get_at((201, 201)), big_surf_color) self.assertEqual(background.get_at((301, 301)), big_surf_color) # areas outside the 3 blitted areas not covered by those blits. self.assertEqual(background.get_at((400, 301)), background_color) self.assertEqual(background.get_at((400, 201)), background_color) self.assertEqual(background.get_at((100, 201)), background_color) self.assertEqual(background.get_at((99, 99)), background_color) self.assertEqual(background.get_at((450, 450)), background_color) class TestSurfaceBlit(unittest.TestCase): """Tests basic blitting functionality and options.""" # __doc__ (as of 2008-08-02) for pygame.surface.Surface.blit: # Surface.blit(source, dest, area=None, special_flags = 0): return Rect # draw one image onto another # # Draws a source Surface onto this Surface. The draw can be positioned # with the dest argument. Dest can either be pair of coordinates # representing the upper left corner of the source. A Rect can also be # passed as the destination and the topleft corner of the rectangle # will be used as the position for the blit. The size of the # destination rectangle does not effect the blit. # # An optional area rectangle can be passed as well. This represents a # smaller portion of the source Surface to draw. # # An optional special flags is for passing in new in 1.8.0: BLEND_ADD, # BLEND_SUB, BLEND_MULT, BLEND_MIN, BLEND_MAX new in 1.8.1: # BLEND_RGBA_ADD, BLEND_RGBA_SUB, BLEND_RGBA_MULT, BLEND_RGBA_MIN, # BLEND_RGBA_MAX BLEND_RGB_ADD, BLEND_RGB_SUB, BLEND_RGB_MULT, # BLEND_RGB_MIN, BLEND_RGB_MAX With other special blitting flags # perhaps added in the future. # # The return rectangle is the area of the affected pixels, excluding # any pixels outside the destination Surface, or outside the clipping # area. # # Pixel alphas will be ignored when blitting to an 8 bit Surface. # special_flags new in pygame 1.8. def setUp(self): """Resets starting surfaces.""" self.src_surface = pygame.Surface((256, 256), 32) self.src_surface.fill(pygame.Color(255, 255, 255)) self.dst_surface = pygame.Surface((64, 64), 32) self.dst_surface.fill(pygame.Color(0, 0, 0)) def test_blit_overflow_coord(self): """Full coverage w/ overflow, specified with Coordinate""" result = self.dst_surface.blit(self.src_surface, (0, 0)) self.assertIsInstance(result, pygame.Rect) self.assertEqual(result.size, (64, 64)) for k in [(x, x) for x in range(64)]: self.assertEqual(self.dst_surface.get_at(k), (255, 255, 255)) def test_blit_overflow_rect(self): """Full coverage w/ overflow, specified with a Rect""" result = self.dst_surface.blit(self.src_surface, pygame.Rect(-1, -1, 300, 300)) self.assertIsInstance(result, pygame.Rect) self.assertEqual(result.size, (64, 64)) for k in [(x, x) for x in range(64)]: self.assertEqual(self.dst_surface.get_at(k), (255, 255, 255)) def test_blit_overflow_nonorigin(self): """Test Rectange Dest, with overflow but with starting rect with top-left at (1,1)""" result = self.dst_surface.blit(self.src_surface, dest=pygame.Rect((1, 1, 1, 1))) self.assertIsInstance(result, pygame.Rect) self.assertEqual(result.size, (63, 63)) self.assertEqual(self.dst_surface.get_at((0, 0)), (0, 0, 0)) self.assertEqual(self.dst_surface.get_at((63, 0)), (0, 0, 0)) self.assertEqual(self.dst_surface.get_at((0, 63)), (0, 0, 0)) self.assertEqual(self.dst_surface.get_at((1, 1)), (255, 255, 255)) self.assertEqual(self.dst_surface.get_at((63, 63)), (255, 255, 255)) def test_blit_area_contraint(self): """Testing area constraint""" result = self.dst_surface.blit(self.src_surface, dest=pygame.Rect((1, 1, 1, 1)), area=pygame.Rect((2, 2, 2, 2))) self.assertIsInstance(result, pygame.Rect) self.assertEqual(result.size, (2, 2)) self.assertEqual(self.dst_surface.get_at((0, 0)), (0, 0, 0)) # Corners self.assertEqual(self.dst_surface.get_at((63, 0)), (0, 0, 0)) self.assertEqual(self.dst_surface.get_at((0, 63)), (0, 0, 0)) self.assertEqual(self.dst_surface.get_at((63, 63)), (0, 0, 0)) self.assertEqual(self.dst_surface.get_at((1, 1)), (255, 255, 255)) # Blitted Area self.assertEqual(self.dst_surface.get_at((2, 2)), (255, 255, 255)) self.assertEqual(self.dst_surface.get_at((3, 3)), (0, 0, 0)) # Should stop short of filling in (3,3) def test_blit_zero_overlap(self): """Testing zero-overlap condition.""" result = self.dst_surface.blit(self.src_surface, dest=pygame.Rect((-256, -256, 1, 1)), area=pygame.Rect((2, 2, 256, 256))) self.assertIsInstance(result, pygame.Rect) self.assertEqual(result.size, (0, 0)) # No blitting expected for k in [(x, x) for x in range(64)]: self.assertEqual(self.dst_surface.get_at(k), (0, 0, 0)) # Diagonal self.assertEqual(self.dst_surface.get_at((63, 0)), (0, 0, 0)) # Remaining corners self.assertEqual(self.dst_surface.get_at((0, 63)), (0, 0, 0)) def test_blit__SRCALPHA_opaque_source(self): src = pygame.Surface((256, 256), SRCALPHA, 32) dst = src.copy() for i, j in test_utils.rect_area_pts(src.get_rect()): dst.set_at((i, j), (i, 0, 0, j)) src.set_at((i, j), (0, i, 0, 255)) dst.blit(src, (0, 0)) for pt in test_utils.rect_area_pts(src.get_rect()): self.assertEqual(dst.get_at(pt)[1], src.get_at(pt)[1]) def test_blit__blit_to_self(self): """Test that blit operation works on self, alpha value is correct, and that no RGB distortion occurs.""" test_surface = pygame.Surface((128, 128), SRCALPHA, 32) area = test_surface.get_rect() for pt, test_color in test_utils.gradient(area.width, area.height): test_surface.set_at(pt, test_color) reference_surface = test_surface.copy() test_surface.blit(test_surface, (0, 0)) for x in range(area.width): for y in range(area.height): (r, g, b, a) = reference_color = reference_surface.get_at((x,y)) expected_color = (r, g, b, (a+(a*((256-a)//256)))) self.assertEqual(reference_color, expected_color) self.assertEqual(reference_surface.get_rect(), test_surface.get_rect()) def test_blit__SRCALPHA_to_SRCALPHA_non_zero(self): """Tests blitting a nonzero alpha surface to another nonzero alpha surface both straight alpha compositing method. Test is fuzzy (+/- 1/256) to account for different implementations in SDL1 and SDL2. """ size = (32, 32) def check_color_diff(color1, color2): """Returns True if two colors are within (1, 1, 1, 1) of each other.""" for val in color1 - color2: if abs(val) > 1: return False return True def high_a_onto_low(high, low): """Tests straight alpha case. Source is low alpha, destination is high alpha""" high_alpha_surface = pygame.Surface(size, pygame.SRCALPHA, 32) low_alpha_surface = high_alpha_surface.copy() high_alpha_color = Color((high, high, low, high)) # Injecting some RGB variance. low_alpha_color = Color((high, low, low, low)) high_alpha_surface.fill(high_alpha_color) low_alpha_surface.fill(low_alpha_color) high_alpha_surface.blit(low_alpha_surface, (0, 0)) expected_color = low_alpha_color + Color(tuple(((x*(255-low_alpha_color.a))//255) for x in high_alpha_color)) self.assertTrue(check_color_diff(high_alpha_surface.get_at((0, 0)), expected_color)) def low_a_onto_high(high, low): """Tests straight alpha case. Source is high alpha, destination is low alpha""" high_alpha_surface = pygame.Surface(size, pygame.SRCALPHA, 32) low_alpha_surface = high_alpha_surface.copy() high_alpha_color = Color((high, high, low, high)) # Injecting some RGB variance. low_alpha_color = Color((high, low, low, low)) high_alpha_surface.fill(high_alpha_color) low_alpha_surface.fill(low_alpha_color) low_alpha_surface.blit(high_alpha_surface, (0, 0)) expected_color = high_alpha_color + Color(tuple(((x*(255-high_alpha_color.a))//255) for x in low_alpha_color)) self.assertTrue(check_color_diff(low_alpha_surface.get_at((0, 0)), expected_color)) for low_a in range(0, 128): for high_a in range(128, 256): high_a_onto_low(high_a, low_a) low_a_onto_high(high_a, low_a) def test_blit__SRCALPHA32_to_8(self): # Bug: fatal # SDL_DisplayConvert segfaults when video is uninitialized. target = pygame.Surface((11, 8), 0, 8) test_color = target.get_palette_at(2) source = pygame.Surface((1, 1), pygame.SRCALPHA, 32) source.set_at((0, 0), test_color) target.blit(source, (0, 0)) class GeneralSurfaceTests(AssertRaisesRegexMixin, unittest.TestCase): @unittest.skipIf( os.environ.get("SDL_VIDEODRIVER") == "dummy", 'requires a non-"dummy" SDL_VIDEODRIVER', ) def test_image_convert_bug_131(self): # Bitbucket bug #131: Unable to Surface.convert(32) some 1-bit images. # https://bitbucket.org/pygame/pygame/issue/131/unable-to-surfaceconvert-32-some-1-bit pygame.display.init() try: pygame.display.set_mode((640, 480)) im = pygame.image.load(example_path(os.path.join("data", "city.png"))) im2 = pygame.image.load(example_path(os.path.join("data", "brick.png"))) self.assertEqual(im.get_palette(), ((0, 0, 0, 255), (255, 255, 255, 255))) self.assertEqual(im2.get_palette(), ((0, 0, 0, 255), (0, 0, 0, 255))) self.assertEqual(repr(im.convert(32)), "") self.assertEqual(repr(im2.convert(32)), "") # Ensure a palette format to palette format works. im3 = im.convert(8) self.assertEqual(repr(im3), "") self.assertEqual(im3.get_palette(), im.get_palette()) finally: pygame.display.quit() def test_convert_init(self): """Ensure initialization exceptions are raised for surf.convert().""" pygame.display.quit() surf = pygame.Surface((1, 1)) self.assertRaisesRegex(pygame.error, "display initialized", surf.convert) pygame.display.init() try: if os.environ.get("SDL_VIDEODRIVER") != "dummy": try: surf.convert(32) surf.convert(pygame.Surface((1, 1))) except pygame.error: self.fail("convert() should not raise an exception here.") self.assertRaisesRegex(pygame.error, "No video mode", surf.convert) pygame.display.set_mode((640, 480)) try: surf.convert() except pygame.error: self.fail("convert() should not raise an exception here.") finally: pygame.display.quit() def test_convert_alpha_init(self): """Ensure initialization exceptions are raised for surf.convert_alpha().""" pygame.display.quit() surf = pygame.Surface((1, 1)) self.assertRaisesRegex(pygame.error, "display initialized", surf.convert_alpha) pygame.display.init() try: self.assertRaisesRegex(pygame.error, "No video mode", surf.convert_alpha) pygame.display.set_mode((640, 480)) try: surf.convert_alpha() except pygame.error: self.fail("convert_alpha() should not raise an exception here.") finally: pygame.display.quit() def test_convert_alpha_SRCALPHA(self): """Ensure that the surface returned by surf.convert_alpha() has alpha blending enabled""" pygame.display.init() try: pygame.display.set_mode((640, 480)) s1 = pygame.Surface((100, 100), 0, 32) # s2=pygame.Surface((100,100), pygame.SRCALPHA, 32) s1_alpha = s1.convert_alpha() self.assertEqual(s1_alpha.get_flags() & SRCALPHA, SRCALPHA) self.assertEqual(s1_alpha.get_alpha(), 255) finally: pygame.display.quit() def test_src_alpha_issue_1289(self): """blit should be white.""" surf1 = pygame.Surface((1, 1), pygame.SRCALPHA, 32) surf1.fill((255, 255, 255, 100)) surf2 = pygame.Surface((1, 1), pygame.SRCALPHA, 32) self.assertEqual(surf2.get_at((0, 0)), (0, 0, 0, 0)) surf2.blit(surf1, (0, 0)) self.assertEqual(surf1.get_at((0, 0)), (255, 255, 255, 100)) self.assertEqual(surf2.get_at((0, 0)), (255, 255, 255, 100)) def test_src_alpha_compatible(self): """ "What pygame 1.9.x did". Is the alpha blitter as before? """ # The table below was generated with the SDL1 blit. # def print_table(): # nums = [0, 1, 65, 126, 127, 199, 254, 255] # results = {} # for dest_r, dest_b, dest_a in zip(nums, reversed(nums), reversed(nums)): # for src_r, src_b, src_a in zip(nums, reversed(nums), nums): # src_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 32) # src_surf.fill((src_r, 255, src_b, src_a)) # dest_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 32) # dest_surf.fill((dest_r, 255, dest_b, dest_a)) # dest_surf.blit(src_surf, (0, 0)) # key = ((dest_r, dest_b, dest_a), (src_r, src_b, src_a)) # results[key] = dest_surf.get_at((65, 33)) # print("(dest_r, dest_b, dest_a), (src_r, src_b, src_a): color") # pprint(results) results_expected = { ((0, 255, 255), (0, 255, 0)): (0, 255, 255, 255), ((0, 255, 255), (1, 254, 1)): (0, 255, 255, 255), ((0, 255, 255), (65, 199, 65)): (16, 255, 241, 255), ((0, 255, 255), (126, 127, 126)): (62, 255, 192, 255), ((0, 255, 255), (127, 126, 127)): (63, 255, 191, 255), ((0, 255, 255), (199, 65, 199)): (155, 255, 107, 255), ((0, 255, 255), (254, 1, 254)): (253, 255, 2, 255), ((0, 255, 255), (255, 0, 255)): (255, 255, 0, 255), ((1, 254, 254), (0, 255, 0)): (1, 255, 254, 254), ((1, 254, 254), (1, 254, 1)): (1, 255, 254, 255), ((1, 254, 254), (65, 199, 65)): (17, 255, 240, 255), ((1, 254, 254), (126, 127, 126)): (63, 255, 191, 255), ((1, 254, 254), (127, 126, 127)): (64, 255, 190, 255), ((1, 254, 254), (199, 65, 199)): (155, 255, 107, 255), ((1, 254, 254), (254, 1, 254)): (253, 255, 2, 255), ((1, 254, 254), (255, 0, 255)): (255, 255, 0, 255), ((65, 199, 199), (0, 255, 0)): (65, 255, 199, 199), ((65, 199, 199), (1, 254, 1)): (64, 255, 200, 200), ((65, 199, 199), (65, 199, 65)): (65, 255, 199, 214), ((65, 199, 199), (126, 127, 126)): (95, 255, 164, 227), ((65, 199, 199), (127, 126, 127)): (96, 255, 163, 227), ((65, 199, 199), (199, 65, 199)): (169, 255, 95, 243), ((65, 199, 199), (254, 1, 254)): (253, 255, 2, 255), ((65, 199, 199), (255, 0, 255)): (255, 255, 0, 255), ((126, 127, 127), (0, 255, 0)): (126, 255, 127, 127), ((126, 127, 127), (1, 254, 1)): (125, 255, 128, 128), ((126, 127, 127), (65, 199, 65)): (110, 255, 146, 160), ((126, 127, 127), (126, 127, 126)): (126, 255, 127, 191), ((126, 127, 127), (127, 126, 127)): (126, 255, 126, 191), ((126, 127, 127), (199, 65, 199)): (183, 255, 79, 227), ((126, 127, 127), (254, 1, 254)): (253, 255, 1, 255), ((126, 127, 127), (255, 0, 255)): (255, 255, 0, 255), ((127, 126, 126), (0, 255, 0)): (127, 255, 126, 126), ((127, 126, 126), (1, 254, 1)): (126, 255, 127, 127), ((127, 126, 126), (65, 199, 65)): (111, 255, 145, 159), ((127, 126, 126), (126, 127, 126)): (127, 255, 126, 190), ((127, 126, 126), (127, 126, 127)): (127, 255, 126, 191), ((127, 126, 126), (199, 65, 199)): (183, 255, 78, 227), ((127, 126, 126), (254, 1, 254)): (254, 255, 1, 255), ((127, 126, 126), (255, 0, 255)): (255, 255, 0, 255), ((199, 65, 65), (0, 255, 0)): (199, 255, 65, 65), ((199, 65, 65), (1, 254, 1)): (198, 255, 66, 66), ((199, 65, 65), (65, 199, 65)): (165, 255, 99, 114), ((199, 65, 65), (126, 127, 126)): (163, 255, 96, 159), ((199, 65, 65), (127, 126, 127)): (163, 255, 95, 160), ((199, 65, 65), (199, 65, 199)): (199, 255, 65, 214), ((199, 65, 65), (254, 1, 254)): (254, 255, 1, 255), ((199, 65, 65), (255, 0, 255)): (255, 255, 0, 255), ((254, 1, 1), (0, 255, 0)): (254, 255, 1, 1), ((254, 1, 1), (1, 254, 1)): (253, 255, 2, 2), ((254, 1, 1), (65, 199, 65)): (206, 255, 52, 66), ((254, 1, 1), (126, 127, 126)): (191, 255, 63, 127), ((254, 1, 1), (127, 126, 127)): (191, 255, 63, 128), ((254, 1, 1), (199, 65, 199)): (212, 255, 51, 200), ((254, 1, 1), (254, 1, 254)): (254, 255, 1, 255), ((254, 1, 1), (255, 0, 255)): (255, 255, 0, 255), ((255, 0, 0), (0, 255, 0)): (0, 255, 255, 0), ((255, 0, 0), (1, 254, 1)): (1, 255, 254, 1), ((255, 0, 0), (65, 199, 65)): (65, 255, 199, 65), ((255, 0, 0), (126, 127, 126)): (126, 255, 127, 126), ((255, 0, 0), (127, 126, 127)): (127, 255, 126, 127), ((255, 0, 0), (199, 65, 199)): (199, 255, 65, 199), ((255, 0, 0), (254, 1, 254)): (254, 255, 1, 254), ((255, 0, 0), (255, 0, 255)): (255, 255, 0, 255), } # chosen because they contain edge cases. nums = [0, 1, 65, 126, 127, 199, 254, 255] results = {} for dst_r, dst_b, dst_a in zip(nums, reversed(nums), reversed(nums)): for src_r, src_b, src_a in zip(nums, reversed(nums), nums): with self.subTest(src_r=src_r, src_b=src_b, src_a=src_a, dest_r=dst_r, dest_b=dst_b, dest_a=dst_a): src_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 32) src_surf.fill((src_r, 255, src_b, src_a)) dest_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 32) dest_surf.fill((dst_r, 255, dst_b, dst_a)) dest_surf.blit(src_surf, (0, 0)) key = ((dst_r, dst_b, dst_a), (src_r, src_b, src_a)) results[key] = dest_surf.get_at((65, 33)) self.assertEqual(results[key], results_expected[key]) # print("(dest_r, dest_b, dest_a), (src_r, src_b, src_a): color") # pprint(results) self.assertEqual(results, results_expected) def test_src_alpha_compatible_16bit(self): """ "What pygame 1.9.x did". Is the alpha blitter as before? """ # The table below was generated with the SDL1 blit. # def print_table(): # nums = [0, 1, 65, 126, 127, 199, 254, 255] # results = {} # for dest_r, dest_b, dest_a in zip(nums, reversed(nums), reversed(nums)): # for src_r, src_b, src_a in zip(nums, reversed(nums), nums): # src_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 16) # src_surf.fill((src_r, 255, src_b, src_a)) # dest_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 16) # dest_surf.fill((dest_r, 255, dest_b, dest_a)) # dest_surf.blit(src_surf, (0, 0)) # key = ((dest_r, dest_b, dest_a), (src_r, src_b, src_a)) # results[key] = dest_surf.get_at((65, 33)) # print("(dest_r, dest_b, dest_a), (src_r, src_b, src_a): color") # pprint(results) results_expected = { ((0, 255, 255), (0, 255, 0)): (0, 255, 255, 255), ((0, 255, 255), (1, 254, 1)): (0, 255, 255, 255), ((0, 255, 255), (65, 199, 65)): (17, 255, 255, 255), ((0, 255, 255), (126, 127, 126)): (51, 255, 204, 255), ((0, 255, 255), (127, 126, 127)): (51, 255, 204, 255), ((0, 255, 255), (199, 65, 199)): (170, 255, 102, 255), ((0, 255, 255), (254, 1, 254)): (255, 255, 0, 255), ((0, 255, 255), (255, 0, 255)): (255, 255, 0, 255), ((1, 254, 254), (0, 255, 0)): (0, 255, 255, 255), ((1, 254, 254), (1, 254, 1)): (0, 255, 255, 255), ((1, 254, 254), (65, 199, 65)): (17, 255, 255, 255), ((1, 254, 254), (126, 127, 126)): (51, 255, 204, 255), ((1, 254, 254), (127, 126, 127)): (51, 255, 204, 255), ((1, 254, 254), (199, 65, 199)): (170, 255, 102, 255), ((1, 254, 254), (254, 1, 254)): (255, 255, 0, 255), ((1, 254, 254), (255, 0, 255)): (255, 255, 0, 255), ((65, 199, 199), (0, 255, 0)): (68, 255, 204, 204), ((65, 199, 199), (1, 254, 1)): (68, 255, 204, 204), ((65, 199, 199), (65, 199, 65)): (68, 255, 204, 221), ((65, 199, 199), (126, 127, 126)): (85, 255, 170, 238), ((65, 199, 199), (127, 126, 127)): (85, 255, 170, 238), ((65, 199, 199), (199, 65, 199)): (187, 255, 85, 255), ((65, 199, 199), (254, 1, 254)): (255, 255, 0, 255), ((65, 199, 199), (255, 0, 255)): (255, 255, 0, 255), ((126, 127, 127), (0, 255, 0)): (119, 255, 119, 119), ((126, 127, 127), (1, 254, 1)): (119, 255, 119, 119), ((126, 127, 127), (65, 199, 65)): (102, 255, 136, 153), ((126, 127, 127), (126, 127, 126)): (119, 255, 119, 187), ((126, 127, 127), (127, 126, 127)): (119, 255, 119, 187), ((126, 127, 127), (199, 65, 199)): (187, 255, 68, 238), ((126, 127, 127), (254, 1, 254)): (255, 255, 0, 255), ((126, 127, 127), (255, 0, 255)): (255, 255, 0, 255), ((127, 126, 126), (0, 255, 0)): (119, 255, 119, 119), ((127, 126, 126), (1, 254, 1)): (119, 255, 119, 119), ((127, 126, 126), (65, 199, 65)): (102, 255, 136, 153), ((127, 126, 126), (126, 127, 126)): (119, 255, 119, 187), ((127, 126, 126), (127, 126, 127)): (119, 255, 119, 187), ((127, 126, 126), (199, 65, 199)): (187, 255, 68, 238), ((127, 126, 126), (254, 1, 254)): (255, 255, 0, 255), ((127, 126, 126), (255, 0, 255)): (255, 255, 0, 255), ((199, 65, 65), (0, 255, 0)): (204, 255, 68, 68), ((199, 65, 65), (1, 254, 1)): (204, 255, 68, 68), ((199, 65, 65), (65, 199, 65)): (170, 255, 102, 119), ((199, 65, 65), (126, 127, 126)): (170, 255, 85, 153), ((199, 65, 65), (127, 126, 127)): (170, 255, 85, 153), ((199, 65, 65), (199, 65, 199)): (204, 255, 68, 221), ((199, 65, 65), (254, 1, 254)): (255, 255, 0, 255), ((199, 65, 65), (255, 0, 255)): (255, 255, 0, 255), ((254, 1, 1), (0, 255, 0)): (0, 255, 255, 0), ((254, 1, 1), (1, 254, 1)): (0, 255, 255, 0), ((254, 1, 1), (65, 199, 65)): (68, 255, 204, 68), ((254, 1, 1), (126, 127, 126)): (119, 255, 119, 119), ((254, 1, 1), (127, 126, 127)): (119, 255, 119, 119), ((254, 1, 1), (199, 65, 199)): (204, 255, 68, 204), ((254, 1, 1), (254, 1, 254)): (255, 255, 0, 255), ((254, 1, 1), (255, 0, 255)): (255, 255, 0, 255), ((255, 0, 0), (0, 255, 0)): (0, 255, 255, 0), ((255, 0, 0), (1, 254, 1)): (0, 255, 255, 0), ((255, 0, 0), (65, 199, 65)): (68, 255, 204, 68), ((255, 0, 0), (126, 127, 126)): (119, 255, 119, 119), ((255, 0, 0), (127, 126, 127)): (119, 255, 119, 119), ((255, 0, 0), (199, 65, 199)): (204, 255, 68, 204), ((255, 0, 0), (254, 1, 254)): (255, 255, 0, 255), ((255, 0, 0), (255, 0, 255)): (255, 255, 0, 255) } # chosen because they contain edge cases. nums = [0, 1, 65, 126, 127, 199, 254, 255] results = {} for dst_r, dst_b, dst_a in zip(nums, reversed(nums), reversed(nums)): for src_r, src_b, src_a in zip(nums, reversed(nums), nums): with self.subTest(src_r=src_r, src_b=src_b, src_a=src_a, dest_r=dst_r, dest_b=dst_b, dest_a=dst_a): src_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 16) src_surf.fill((src_r, 255, src_b, src_a)) dest_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 16) dest_surf.fill((dst_r, 255, dst_b, dst_a)) dest_surf.blit(src_surf, (0, 0)) key = ((dst_r, dst_b, dst_a), (src_r, src_b, src_a)) results[key] = dest_surf.get_at((65, 33)) self.assertEqual(results[key], results_expected[key]) # print("(dest_r, dest_b, dest_a), (src_r, src_b, src_a): color") # pprint(results) self.assertEqual(results, results_expected) @unittest.skipIf(pygame.get_sdl_version()[0] == 2, "only works in SDL1") def test_src_alpha_compatible_opaque_dest(self): """ "What pygame 1.9.x did". Is the alpha blitter as before? """ results_expected = { ((0, 255), (0, 255, 0)): (0, 255, 255, 255), ((0, 255), (1, 254, 1)): (0, 255, 254, 255), ((0, 255), (65, 199, 65)): (16, 255, 240, 255), ((0, 255), (126, 127, 126)): (62, 255, 192, 255), ((0, 255), (127, 126, 127)): (63, 255, 191, 255), ((0, 255), (199, 65, 199)): (154, 255, 107, 255), ((0, 255), (254, 1, 254)): (252, 255, 2, 255), ((0, 255), (255, 0, 255)): (255, 255, 0, 255), ((1, 254), (0, 255, 0)): (1, 255, 254, 255), ((1, 254), (1, 254, 1)): (1, 255, 254, 255), ((1, 254), (65, 199, 65)): (17, 255, 240, 255), ((1, 254), (126, 127, 126)): (62, 255, 191, 255), ((1, 254), (127, 126, 127)): (63, 255, 190, 255), ((1, 254), (199, 65, 199)): (154, 255, 107, 255), ((1, 254), (254, 1, 254)): (252, 255, 2, 255), ((1, 254), (255, 0, 255)): (255, 255, 0, 255), ((65, 199), (0, 255, 0)): (65, 255, 199, 255), ((65, 199), (1, 254, 1)): (64, 255, 199, 255), ((65, 199), (65, 199, 65)): (65, 255, 199, 255), ((65, 199), (126, 127, 126)): (95, 255, 163, 255), ((65, 199), (127, 126, 127)): (95, 255, 162, 255), ((65, 199), (199, 65, 199)): (169, 255, 94, 255), ((65, 199), (254, 1, 254)): (252, 255, 2, 255), ((65, 199), (255, 0, 255)): (255, 255, 0, 255), ((126, 127), (0, 255, 0)): (126, 255, 127, 255), ((126, 127), (1, 254, 1)): (125, 255, 127, 255), ((126, 127), (65, 199, 65)): (110, 255, 145, 255), ((126, 127), (126, 127, 126)): (126, 255, 127, 255), ((126, 127), (127, 126, 127)): (126, 255, 126, 255), ((126, 127), (199, 65, 199)): (182, 255, 78, 255), ((126, 127), (254, 1, 254)): (253, 255, 1, 255), ((126, 127), (255, 0, 255)): (255, 255, 0, 255), ((127, 126), (0, 255, 0)): (127, 255, 126, 255), ((127, 126), (1, 254, 1)): (126, 255, 126, 255), ((127, 126), (65, 199, 65)): (111, 255, 144, 255), ((127, 126), (126, 127, 126)): (126, 255, 126, 255), ((127, 126), (127, 126, 127)): (127, 255, 126, 255), ((127, 126), (199, 65, 199)): (182, 255, 78, 255), ((127, 126), (254, 1, 254)): (253, 255, 1, 255), ((127, 126), (255, 0, 255)): (255, 255, 0, 255), ((199, 65), (0, 255, 0)): (199, 255, 65, 255), ((199, 65), (1, 254, 1)): (198, 255, 65, 255), ((199, 65), (65, 199, 65)): (164, 255, 99, 255), ((199, 65), (126, 127, 126)): (163, 255, 95, 255), ((199, 65), (127, 126, 127)): (163, 255, 95, 255), ((199, 65), (199, 65, 199)): (199, 255, 65, 255), ((199, 65), (254, 1, 254)): (253, 255, 1, 255), ((199, 65), (255, 0, 255)): (255, 255, 0, 255), ((254, 1), (0, 255, 0)): (254, 255, 1, 255), ((254, 1), (1, 254, 1)): (253, 255, 1, 255), ((254, 1), (65, 199, 65)): (206, 255, 51, 255), ((254, 1), (126, 127, 126)): (191, 255, 63, 255), ((254, 1), (127, 126, 127)): (190, 255, 63, 255), ((254, 1), (199, 65, 199)): (211, 255, 50, 255), ((254, 1), (254, 1, 254)): (254, 255, 1, 255), ((254, 1), (255, 0, 255)): (255, 255, 0, 255), ((255, 0), (0, 255, 0)): (255, 255, 0, 255), ((255, 0), (1, 254, 1)): (254, 255, 0, 255), ((255, 0), (65, 199, 65)): (206, 255, 50, 255), ((255, 0), (126, 127, 126)): (191, 255, 62, 255), ((255, 0), (127, 126, 127)): (191, 255, 62, 255), ((255, 0), (199, 65, 199)): (211, 255, 50, 255), ((255, 0), (254, 1, 254)): (254, 255, 0, 255), ((255, 0), (255, 0, 255)): (255, 255, 0, 255) } # chosen because they contain edge cases. nums = [0, 1, 65, 126, 127, 199, 254, 255] results = {} for dst_r, dst_b in zip(nums, reversed(nums)): for src_r, src_b, src_a in zip(nums, reversed(nums), nums): with self.subTest(src_r=src_r, src_b=src_b, src_a=src_a, dest_r=dst_r, dest_b=dst_b): src_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 32) src_surf.fill((src_r, 255, src_b, src_a)) dest_surf = pygame.Surface((66, 66), 0, 32) dest_surf.fill((dst_r, 255, dst_b)) dest_surf.blit(src_surf, (0, 0)) key = ((dst_r, dst_b), (src_r, src_b, src_a)) results[key] = dest_surf.get_at((65, 33)) self.assertEqual(results[key], results_expected[key]) # print("(dest_r, dest_b, dest_a), (src_r, src_b, src_a): color") # pprint(results) self.assertEqual(results, results_expected) @unittest.skipIf(pygame.get_sdl_version()[0] == 1, "only works in SDL2") def test_sdl1_mimic_blitter_with_set_alpha(self): """ does the SDL 1 style blitter in pygame 2 work with set_alpha(), this feature only exists in pygame 2/SDL2 SDL1 did not support combining surface and pixel alpha""" results_expected = { ((0, 255, 255), (0, 255, 0)): (0, 255, 255, 255), ((0, 255, 255), (1, 254, 1)): (0, 255, 255, 255), ((0, 255, 255), (65, 199, 65)): (16, 255, 241, 255), ((0, 255, 255), (126, 127, 126)): (62, 255, 192, 255), ((0, 255, 255), (127, 126, 127)): (63, 255, 191, 255), ((0, 255, 255), (199, 65, 199)): (155, 255, 107, 255), ((0, 255, 255), (254, 1, 254)): (253, 255, 2, 255), ((0, 255, 255), (255, 0, 255)): (255, 255, 0, 255), ((1, 254, 254), (0, 255, 0)): (1, 255, 254, 254), ((1, 254, 254), (1, 254, 1)): (1, 255, 254, 255), ((1, 254, 254), (65, 199, 65)): (17, 255, 240, 255), ((1, 254, 254), (126, 127, 126)): (63, 255, 191, 255), ((1, 254, 254), (127, 126, 127)): (64, 255, 190, 255), ((1, 254, 254), (199, 65, 199)): (155, 255, 107, 255), ((1, 254, 254), (254, 1, 254)): (253, 255, 2, 255), ((1, 254, 254), (255, 0, 255)): (255, 255, 0, 255), ((65, 199, 199), (0, 255, 0)): (65, 255, 199, 199), ((65, 199, 199), (1, 254, 1)): (64, 255, 200, 200), ((65, 199, 199), (65, 199, 65)): (65, 255, 199, 214), ((65, 199, 199), (126, 127, 126)): (95, 255, 164, 227), ((65, 199, 199), (127, 126, 127)): (96, 255, 163, 227), ((65, 199, 199), (199, 65, 199)): (169, 255, 95, 243), ((65, 199, 199), (254, 1, 254)): (253, 255, 2, 255), ((65, 199, 199), (255, 0, 255)): (255, 255, 0, 255), ((126, 127, 127), (0, 255, 0)): (126, 255, 127, 127), ((126, 127, 127), (1, 254, 1)): (125, 255, 128, 128), ((126, 127, 127), (65, 199, 65)): (110, 255, 146, 160), ((126, 127, 127), (126, 127, 126)): (126, 255, 127, 191), ((126, 127, 127), (127, 126, 127)): (126, 255, 126, 191), ((126, 127, 127), (199, 65, 199)): (183, 255, 79, 227), ((126, 127, 127), (254, 1, 254)): (253, 255, 1, 255), ((126, 127, 127), (255, 0, 255)): (255, 255, 0, 255), ((127, 126, 126), (0, 255, 0)): (127, 255, 126, 126), ((127, 126, 126), (1, 254, 1)): (126, 255, 127, 127), ((127, 126, 126), (65, 199, 65)): (111, 255, 145, 159), ((127, 126, 126), (126, 127, 126)): (127, 255, 126, 190), ((127, 126, 126), (127, 126, 127)): (127, 255, 126, 191), ((127, 126, 126), (199, 65, 199)): (183, 255, 78, 227), ((127, 126, 126), (254, 1, 254)): (254, 255, 1, 255), ((127, 126, 126), (255, 0, 255)): (255, 255, 0, 255), ((199, 65, 65), (0, 255, 0)): (199, 255, 65, 65), ((199, 65, 65), (1, 254, 1)): (198, 255, 66, 66), ((199, 65, 65), (65, 199, 65)): (165, 255, 99, 114), ((199, 65, 65), (126, 127, 126)): (163, 255, 96, 159), ((199, 65, 65), (127, 126, 127)): (163, 255, 95, 160), ((199, 65, 65), (199, 65, 199)): (199, 255, 65, 214), ((199, 65, 65), (254, 1, 254)): (254, 255, 1, 255), ((199, 65, 65), (255, 0, 255)): (255, 255, 0, 255), ((254, 1, 1), (0, 255, 0)): (254, 255, 1, 1), ((254, 1, 1), (1, 254, 1)): (253, 255, 2, 2), ((254, 1, 1), (65, 199, 65)): (206, 255, 52, 66), ((254, 1, 1), (126, 127, 126)): (191, 255, 63, 127), ((254, 1, 1), (127, 126, 127)): (191, 255, 63, 128), ((254, 1, 1), (199, 65, 199)): (212, 255, 51, 200), ((254, 1, 1), (254, 1, 254)): (254, 255, 1, 255), ((254, 1, 1), (255, 0, 255)): (255, 255, 0, 255), ((255, 0, 0), (0, 255, 0)): (0, 255, 255, 0), ((255, 0, 0), (1, 254, 1)): (1, 255, 254, 1), ((255, 0, 0), (65, 199, 65)): (65, 255, 199, 65), ((255, 0, 0), (126, 127, 126)): (126, 255, 127, 126), ((255, 0, 0), (127, 126, 127)): (127, 255, 126, 127), ((255, 0, 0), (199, 65, 199)): (199, 255, 65, 199), ((255, 0, 0), (254, 1, 254)): (254, 255, 1, 254), ((255, 0, 0), (255, 0, 255)): (255, 255, 0, 255), } # chosen because they contain edge cases. nums = [0, 1, 65, 126, 127, 199, 254, 255] results = {} for dst_r, dst_b, dst_a in zip(nums, reversed(nums), reversed(nums)): for src_r, src_b, src_a in zip(nums, reversed(nums), nums): with self.subTest(src_r=src_r, src_b=src_b, src_a=src_a, dest_r=dst_r, dest_b=dst_b, dest_a=dst_a): src_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 32) src_surf.fill((src_r, 255, src_b, 255)) src_surf.set_alpha(src_a) dest_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 32) dest_surf.fill((dst_r, 255, dst_b, dst_a)) dest_surf.blit(src_surf, (0, 0)) key = ((dst_r, dst_b, dst_a), (src_r, src_b, src_a)) results[key] = dest_surf.get_at((65, 33)) self.assertEqual(results[key], results_expected[key]) self.assertEqual(results, results_expected) @unittest.skipIf(pygame.get_sdl_version()[0] == 1, "only works in SDL2") @unittest.skipIf('arm' in platform.machine() or 'aarch64' in platform.machine(), "sdl2 blitter produces different results on arm") def test_src_alpha_sdl2_blitter(self): """ Checking that the BLEND_ALPHA_SDL2 flag works - this feature only exists when using SDL2""" results_expected = { ((0, 255, 255), (0, 255, 0)): (0, 255, 255, 255), ((0, 255, 255), (1, 254, 1)): (0, 253, 253, 253), ((0, 255, 255), (65, 199, 65)): (16, 253, 239, 253), ((0, 255, 255), (126, 127, 126)): (62, 253, 190, 253), ((0, 255, 255), (127, 126, 127)): (63, 253, 189, 253), ((0, 255, 255), (199, 65, 199)): (154, 253, 105, 253), ((0, 255, 255), (254, 1, 254)): (252, 253, 0, 253), ((0, 255, 255), (255, 0, 255)): (255, 255, 0, 255), ((1, 254, 254), (0, 255, 0)): (1, 255, 254, 254), ((1, 254, 254), (1, 254, 1)): (0, 253, 252, 252), ((1, 254, 254), (65, 199, 65)): (16, 253, 238, 252), ((1, 254, 254), (126, 127, 126)): (62, 253, 189, 252), ((1, 254, 254), (127, 126, 127)): (63, 253, 189, 253), ((1, 254, 254), (199, 65, 199)): (154, 253, 105, 253), ((1, 254, 254), (254, 1, 254)): (252, 253, 0, 253), ((1, 254, 254), (255, 0, 255)): (255, 255, 0, 255), ((65, 199, 199), (0, 255, 0)): (65, 255, 199, 199), ((65, 199, 199), (1, 254, 1)): (64, 253, 197, 197), ((65, 199, 199), (65, 199, 65)): (64, 253, 197, 211), ((65, 199, 199), (126, 127, 126)): (94, 253, 162, 225), ((65, 199, 199), (127, 126, 127)): (95, 253, 161, 225), ((65, 199, 199), (199, 65, 199)): (168, 253, 93, 241), ((65, 199, 199), (254, 1, 254)): (252, 253, 0, 253), ((65, 199, 199), (255, 0, 255)): (255, 255, 0, 255), ((126, 127, 127), (0, 255, 0)): (126, 255, 127, 127), ((126, 127, 127), (1, 254, 1)): (125, 253, 126, 126), ((126, 127, 127), (65, 199, 65)): (109, 253, 144, 158), ((126, 127, 127), (126, 127, 126)): (125, 253, 125, 188), ((126, 127, 127), (127, 126, 127)): (126, 253, 125, 189), ((126, 127, 127), (199, 65, 199)): (181, 253, 77, 225), ((126, 127, 127), (254, 1, 254)): (252, 253, 0, 253), ((126, 127, 127), (255, 0, 255)): (255, 255, 0, 255), ((127, 126, 126), (0, 255, 0)): (127, 255, 126, 126), ((127, 126, 126), (1, 254, 1)): (126, 253, 125, 125), ((127, 126, 126), (65, 199, 65)): (110, 253, 143, 157), ((127, 126, 126), (126, 127, 126)): (125, 253, 125, 188), ((127, 126, 126), (127, 126, 127)): (126, 253, 125, 189), ((127, 126, 126), (199, 65, 199)): (181, 253, 77, 225), ((127, 126, 126), (254, 1, 254)): (252, 253, 0, 253), ((127, 126, 126), (255, 0, 255)): (255, 255, 0, 255), ((199, 65, 65), (0, 255, 0)): (199, 255, 65, 65), ((199, 65, 65), (1, 254, 1)): (197, 253, 64, 64), ((199, 65, 65), (65, 199, 65)): (163, 253, 98, 112), ((199, 65, 65), (126, 127, 126)): (162, 253, 94, 157), ((199, 65, 65), (127, 126, 127)): (162, 253, 94, 158), ((199, 65, 65), (199, 65, 199)): (197, 253, 64, 212), ((199, 65, 65), (254, 1, 254)): (252, 253, 0, 253), ((199, 65, 65), (255, 0, 255)): (255, 255, 0, 255), ((254, 1, 1), (0, 255, 0)): (254, 255, 1, 1), ((254, 1, 1), (1, 254, 1)): (252, 253, 0, 0), ((254, 1, 1), (65, 199, 65)): (204, 253, 50, 64), ((254, 1, 1), (126, 127, 126)): (189, 253, 62, 125), ((254, 1, 1), (127, 126, 127)): (190, 253, 62, 126), ((254, 1, 1), (199, 65, 199)): (209, 253, 50, 198), ((254, 1, 1), (254, 1, 254)): (252, 253, 0, 253), ((254, 1, 1), (255, 0, 255)): (255, 255, 0, 255), ((255, 0, 0), (0, 255, 0)): (255, 255, 0, 0), ((255, 0, 0), (1, 254, 1)): (253, 253, 0, 0), ((255, 0, 0), (65, 199, 65)): (205, 253, 50, 64), ((255, 0, 0), (126, 127, 126)): (190, 253, 62, 125), ((255, 0, 0), (127, 126, 127)): (190, 253, 62, 126), ((255, 0, 0), (199, 65, 199)): (209, 253, 50, 198), ((255, 0, 0), (254, 1, 254)): (252, 253, 0, 253), ((255, 0, 0), (255, 0, 255)): (255, 255, 0, 255), } # chosen because they contain edge cases. nums = [0, 1, 65, 126, 127, 199, 254, 255] results = {} for dst_r, dst_b, dst_a in zip(nums, reversed(nums), reversed(nums)): for src_r, src_b, src_a in zip(nums, reversed(nums), nums): with self.subTest(src_r=src_r, src_b=src_b, src_a=src_a, dest_r=dst_r, dest_b=dst_b, dest_a=dst_a): src_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 32) src_surf.fill((src_r, 255, src_b, src_a)) dest_surf = pygame.Surface((66, 66), pygame.SRCALPHA, 32) dest_surf.fill((dst_r, 255, dst_b, dst_a)) dest_surf.blit(src_surf, (0, 0), special_flags=pygame.BLEND_ALPHA_SDL2) key = ((dst_r, dst_b, dst_a), (src_r, src_b, src_a)) results[key] = dest_surf.get_at((65, 33)) self.assertEqual(results[key], results_expected[key]) # print("(dest_r, dest_b, dest_a), (src_r, src_b, src_a): color") # pprint(results) self.assertEqual(results, results_expected) def test_opaque_destination_blit_with_set_alpha(self): # no set_alpha() src_surf = pygame.Surface((32, 32), pygame.SRCALPHA, 32) src_surf.fill((255, 255, 255, 200)) dest_surf = pygame.Surface((32, 32)) dest_surf.fill((100, 100, 100)) dest_surf.blit(src_surf, (0, 0)) no_surf_alpha_col = dest_surf.get_at((0,0)) dest_surf.fill((100, 100, 100)) dest_surf.set_alpha(200) dest_surf.blit(src_surf, (0, 0)) surf_alpha_col = dest_surf.get_at((0, 0)) self.assertEqual(no_surf_alpha_col, surf_alpha_col) def todo_test_convert(self): # __doc__ (as of 2008-08-02) for pygame.surface.Surface.convert: # Surface.convert(Surface): return Surface # Surface.convert(depth, flags=0): return Surface # Surface.convert(masks, flags=0): return Surface # Surface.convert(): return Surface # change the pixel format of an image # # Creates a new copy of the Surface with the pixel format changed. The # new pixel format can be determined from another existing Surface. # Otherwise depth, flags, and masks arguments can be used, similar to # the pygame.Surface() call. # # If no arguments are passed the new Surface will have the same pixel # format as the display Surface. This is always the fastest format for # blitting. It is a good idea to convert all Surfaces before they are # blitted many times. # # The converted Surface will have no pixel alphas. They will be # stripped if the original had them. See Surface.convert_alpha() for # preserving or creating per-pixel alphas. # self.fail() def test_convert__pixel_format_as_surface_subclass(self): """Ensure convert accepts a Surface subclass argument.""" expected_size = (23, 17) convert_surface = SurfaceSubclass(expected_size, 0, 32) depth_surface = SurfaceSubclass((31, 61), 0, 32) pygame.display.init() try: surface = convert_surface.convert(depth_surface) self.assertIsNot(surface, depth_surface) self.assertIsNot(surface, convert_surface) self.assertIsInstance(surface, pygame.Surface) self.assertIsInstance(surface, SurfaceSubclass) self.assertEqual(surface.get_size(), expected_size) finally: pygame.display.quit() def test_convert_alpha(self): """Ensure the surface returned by surf.convert_alpha has alpha values added""" pygame.display.init() try: pygame.display.set_mode((640, 480)) s1 = pygame.Surface((100, 100), 0, 32) s1_alpha = pygame.Surface.convert_alpha(s1) s2 = pygame.Surface((100, 100), 0, 32) s2_alpha = s2.convert_alpha() s3 = pygame.Surface((100, 100), 0, 8) s3_alpha = s3.convert_alpha() s4 = pygame.Surface((100, 100), 0, 12) s4_alpha = s4.convert_alpha() s5 = pygame.Surface((100, 100), 0, 15) s5_alpha = s5.convert_alpha() s6 = pygame.Surface((100, 100), 0, 16) s6_alpha = s6.convert_alpha() s7 = pygame.Surface((100, 100), 0, 24) s7_alpha = s7.convert_alpha() self.assertEqual(s1_alpha.get_alpha(), 255) self.assertEqual(s2_alpha.get_alpha(), 255) self.assertEqual(s3_alpha.get_alpha(), 255) self.assertEqual(s4_alpha.get_alpha(), 255) self.assertEqual(s5_alpha.get_alpha(), 255) self.assertEqual(s6_alpha.get_alpha(), 255) self.assertEqual(s7_alpha.get_alpha(), 255) self.assertEqual(s1_alpha.get_bitsize(), 32) self.assertEqual(s2_alpha.get_bitsize(), 32) self.assertEqual(s3_alpha.get_bitsize(), 32) self.assertEqual(s4_alpha.get_bitsize(), 32) self.assertEqual(s5_alpha.get_bitsize(), 32) self.assertEqual(s6_alpha.get_bitsize(), 32) self.assertEqual(s6_alpha.get_bitsize(), 32) with self.assertRaises(pygame.error): surface = pygame.display.set_mode() pygame.display.quit() surface.convert_alpha() finally: pygame.display.quit() def test_convert_alpha__pixel_format_as_surface_subclass(self): """Ensure convert_alpha accepts a Surface subclass argument.""" expected_size = (23, 17) convert_surface = SurfaceSubclass(expected_size, SRCALPHA, 32) depth_surface = SurfaceSubclass((31, 57), SRCALPHA, 32) pygame.display.init() try: pygame.display.set_mode((60, 60)) # This is accepted as an argument, but its values are ignored. # See issue #599. surface = convert_surface.convert_alpha(depth_surface) self.assertIsNot(surface, depth_surface) self.assertIsNot(surface, convert_surface) self.assertIsInstance(surface, pygame.Surface) self.assertIsInstance(surface, SurfaceSubclass) self.assertEqual(surface.get_size(), expected_size) finally: pygame.display.quit() def test_get_abs_offset(self): pygame.display.init() try: parent = pygame.Surface((64, 64), SRCALPHA, 32) # Stack bunch of subsurfaces sub_level_1 = parent.subsurface((2, 2), (34, 37)) sub_level_2 = sub_level_1.subsurface((0, 0), (30, 29)) sub_level_3 = sub_level_2.subsurface((3, 7), (20, 21)) sub_level_4 = sub_level_3.subsurface((6, 1), (14, 14)) sub_level_5 = sub_level_4.subsurface((5, 6), (3, 4)) # Parent is always (0, 0) self.assertEqual(parent.get_abs_offset(), (0, 0)) # Total offset: (0+2, 0+2) = (2, 2) self.assertEqual(sub_level_1.get_abs_offset(), (2, 2)) # Total offset: (0+2+0, 0+2+0) = (2, 2) self.assertEqual(sub_level_2.get_abs_offset(), (2, 2)) # Total offset: (0+2+0+3, 0+2+0+7) = (5, 9) self.assertEqual(sub_level_3.get_abs_offset(), (5, 9)) # Total offset: (0+2+0+3+6, 0+2+0+7+1) = (11, 10) self.assertEqual(sub_level_4.get_abs_offset(), (11, 10)) # Total offset: (0+2+0+3+6+5, 0+2+0+7+1+6) = (16, 16) self.assertEqual(sub_level_5.get_abs_offset(), (16, 16)) with self.assertRaises(pygame.error): surface = pygame.display.set_mode() pygame.display.quit() surface.get_abs_offset() finally: pygame.display.quit() def test_get_abs_parent(self): pygame.display.init() try: parent = pygame.Surface((32, 32), SRCALPHA, 32) # Stack bunch of subsurfaces sub_level_1 = parent.subsurface((1, 1), (15, 15)) sub_level_2 = sub_level_1.subsurface((1, 1), (12, 12)) sub_level_3 = sub_level_2.subsurface((1, 1), (9, 9)) sub_level_4 = sub_level_3.subsurface((1, 1), (8, 8)) sub_level_5 = sub_level_4.subsurface((2, 2), (3, 4)) sub_level_6 = sub_level_5.subsurface((0, 0), (2, 1)) # Can't have subsurfaces bigger than parents self.assertRaises(ValueError, parent.subsurface, (5, 5), (100, 100)) self.assertRaises(ValueError, sub_level_3.subsurface, (0, 0), (11, 5)) self.assertRaises(ValueError, sub_level_6.subsurface, (0, 0), (5, 5)) # Calling get_abs_parent on parent should return itself self.assertEqual(parent.get_abs_parent(), parent) # On subclass "depth" of 1, get_abs_parent and get_parent should return the same self.assertEqual(sub_level_1.get_abs_parent(), sub_level_1.get_parent()) self.assertEqual(sub_level_2.get_abs_parent(), parent) self.assertEqual(sub_level_3.get_abs_parent(), parent) self.assertEqual(sub_level_4.get_abs_parent(), parent) self.assertEqual(sub_level_5.get_abs_parent(), parent) self.assertEqual( sub_level_6.get_abs_parent(), sub_level_6.get_parent().get_abs_parent() ) with self.assertRaises(pygame.error): surface = pygame.display.set_mode() pygame.display.quit() surface.get_abs_parent() finally: pygame.display.quit() def test_get_at(self): surf = pygame.Surface((2, 2), 0, 24) c00 = pygame.Color(1, 2, 3) c01 = pygame.Color(5, 10, 15) c10 = pygame.Color(100, 50, 0) c11 = pygame.Color(4, 5, 6) surf.set_at((0, 0), c00) surf.set_at((0, 1), c01) surf.set_at((1, 0), c10) surf.set_at((1, 1), c11) c = surf.get_at((0, 0)) self.assertIsInstance(c, pygame.Color) self.assertEqual(c, c00) self.assertEqual(surf.get_at((0, 1)), c01) self.assertEqual(surf.get_at((1, 0)), c10) self.assertEqual(surf.get_at((1, 1)), c11) for p in [(-1, 0), (0, -1), (2, 0), (0, 2)]: self.assertRaises(IndexError, surf.get_at, p) def test_get_at_mapped(self): color = pygame.Color(10, 20, 30) for bitsize in [8, 16, 24, 32]: surf = pygame.Surface((2, 2), 0, bitsize) surf.fill(color) pixel = surf.get_at_mapped((0, 0)) self.assertEqual( pixel, surf.map_rgb(color), "%i != %i, bitsize: %i" % (pixel, surf.map_rgb(color), bitsize), ) def test_get_bitsize(self): pygame.display.init() try: expected_size = (11, 21) # Check that get_bitsize returns passed depth expected_depth = 32 surface = pygame.Surface(expected_size, pygame.SRCALPHA, expected_depth) self.assertEqual(surface.get_size(), expected_size) self.assertEqual(surface.get_bitsize(), expected_depth) expected_depth = 16 surface = pygame.Surface(expected_size, pygame.SRCALPHA, expected_depth) self.assertEqual(surface.get_size(), expected_size) self.assertEqual(surface.get_bitsize(), expected_depth) expected_depth = 15 surface = pygame.Surface(expected_size, 0, expected_depth) self.assertEqual(surface.get_size(), expected_size) self.assertEqual(surface.get_bitsize(), expected_depth) # Check for invalid depths expected_depth = -1 self.assertRaises( ValueError, pygame.Surface, expected_size, 0, expected_depth ) expected_depth = 11 self.assertRaises( ValueError, pygame.Surface, expected_size, 0, expected_depth ) expected_depth = 1024 self.assertRaises( ValueError, pygame.Surface, expected_size, 0, expected_depth ) with self.assertRaises(pygame.error): surface = pygame.display.set_mode() pygame.display.quit() surface.get_bitsize() finally: pygame.display.quit() def test_get_clip(self): s = pygame.Surface((800, 600)) rectangle = s.get_clip() self.assertEqual(rectangle, (0, 0, 800, 600)) def test_get_colorkey(self): pygame.display.init() try: # if set_colorkey is not used s = pygame.Surface((800, 600), 0, 32) self.assertIsNone(s.get_colorkey()) # if set_colorkey is used s.set_colorkey(None) self.assertIsNone(s.get_colorkey()) # setting up remainder of tests... r, g, b, a = 20, 40, 60, 12 colorkey = pygame.Color(r, g, b) s.set_colorkey(colorkey) # test for ideal case self.assertEqual(s.get_colorkey(), (r, g, b, 255)) # test for if the color_key is set using pygame.RLEACCEL s.set_colorkey(colorkey, pygame.RLEACCEL) self.assertEqual(s.get_colorkey(), (r, g, b, 255)) # test for if the color key is not what's expected s.set_colorkey(pygame.Color(r + 1, g + 1, b + 1)) self.assertNotEqual(s.get_colorkey(), (r, g, b, 255)) s.set_colorkey( pygame.Color(r, g, b, a) ) # regardless of whether alpha is not 255, colorkey returned from surface is always 255 self.assertEqual(s.get_colorkey(), (r, g, b, 255)) # test for using method when display is created with OpenGL and the SDL version is 1 # Open GL is not available on the dummy video driver if SDL1: # SLD1 is a bool defined at the top... try: s = pygame.display.set_mode((200, 200), pygame.OPENGL, 32) except pygame.error: pass # If we can't create OPENGL surface don't try this test else: with self.assertRaises(pygame.error): s.get_colorkey() finally: # test for using method after display.quit() is called... s = pygame.display.set_mode((200, 200), 0, 32) pygame.display.quit() with self.assertRaises(pygame.error): s.get_colorkey() def test_get_height(self): sizes = ((1, 1), (119, 10), (10, 119), (1, 1000), (1000, 1), (1000, 1000)) for width, height in sizes: surf = pygame.Surface((width, height)) found_height = surf.get_height() self.assertEqual(height, found_height) def test_get_locked(self): def blit_locked_test(surface): newSurf = pygame.Surface((10, 10)) try: newSurf.blit(surface, (0, 0)) except pygame.error: return True else: return False surf = pygame.Surface((100, 100)) self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Unlocked # Surface should lock surf.lock() self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Locked # Surface should unlock surf.unlock() self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Unlocked # Check multiple locks surf = pygame.Surface((100, 100)) surf.lock() surf.lock() self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Locked surf.unlock() self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Locked surf.unlock() self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Unlocked # Check many locks surf = pygame.Surface((100, 100)) for i in range(1000): surf.lock() self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Locked for i in range(1000): surf.unlock() self.assertFalse(surf.get_locked()) # Unlocked # Unlocking an unlocked surface surf = pygame.Surface((100, 100)) surf.unlock() self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Unlocked surf.unlock() self.assertIs(surf.get_locked(), blit_locked_test(surf)) # Unlocked def test_get_locks(self): # __doc__ (as of 2008-08-02) for pygame.surface.Surface.get_locks: # Surface.get_locks(): return tuple # Gets the locks for the Surface # # Returns the currently existing locks for the Surface. # test on a surface that is not initially locked surface = pygame.Surface((100, 100)) self.assertEqual(surface.get_locks(), ()) # test on the same surface after it has been locked surface.lock() self.assertEqual(surface.get_locks(), (surface,)) # test on the same surface after it has been unlocked surface.unlock() self.assertEqual(surface.get_locks(), ()) # test with PixelArray initialization: locks surface pxarray = pygame.PixelArray(surface) self.assertNotEqual(surface.get_locks(), ()) # closing the PixelArray releases the surface lock pxarray.close() self.assertEqual(surface.get_locks(), ()) # AttributeError raised when called on invalid object type (i.e. not a pygame.Surface object) with self.assertRaises(AttributeError): "DUMMY".get_locks() # test multiple locks and unlocks on the same surface surface.lock() surface.lock() surface.lock() self.assertEqual(surface.get_locks(), (surface, surface, surface)) surface.unlock() surface.unlock() self.assertEqual(surface.get_locks(), (surface,)) surface.unlock() self.assertEqual(surface.get_locks(), ()) def test_get_losses(self): """Ensure a surface's losses can be retrieved""" pygame.display.init() try: # Masks for different color component configurations mask8 = (224, 28, 3, 0) mask15 = (31744, 992, 31, 0) mask16 = (63488, 2016, 31, 0) mask24 = (4278190080, 16711680, 65280, 0) mask32 = (4278190080, 16711680, 65280, 255) # Surfaces with standard depths and masks display_surf = pygame.display.set_mode((100, 100)) surf = pygame.Surface((100, 100)) surf_8bit = pygame.Surface((100, 100), depth=8, masks=mask8) surf_15bit = pygame.Surface((100, 100), depth=15, masks=mask15) surf_16bit = pygame.Surface((100, 100), depth=16, masks=mask16) surf_24bit = pygame.Surface((100, 100), depth=24, masks=mask24) surf_32bit = pygame.Surface((100, 100), depth=32, masks=mask32) # Test output is correct type, length, and value range losses = surf.get_losses() self.assertIsInstance(losses, tuple) self.assertEqual(len(losses), 4) for loss in losses: self.assertIsInstance(loss, int) self.assertGreaterEqual(loss, 0) self.assertLessEqual(loss, 8) # Test each surface for correct losses # Display surface losses gives idea of default surface losses if display_surf.get_losses() == (0, 0, 0, 8): self.assertEqual(losses, (0, 0, 0, 8)) elif display_surf.get_losses() == (8, 8, 8, 8): self.assertEqual(losses, (8, 8, 8, 8)) self.assertEqual(surf_8bit.get_losses(), (5, 5, 6, 8)) self.assertEqual(surf_15bit.get_losses(), (3, 3, 3, 8)) self.assertEqual(surf_16bit.get_losses(), (3, 2, 3, 8)) self.assertEqual(surf_24bit.get_losses(), (0, 0, 0, 8)) self.assertEqual(surf_32bit.get_losses(), (0, 0, 0, 0)) # Method should fail when display is not initialized with self.assertRaises(pygame.error): surface = pygame.display.set_mode((100, 100)) pygame.display.quit() surface.get_losses() finally: pygame.display.quit() def test_get_masks__rgba(self): """ Ensure that get_mask can return RGBA mask. """ masks = [ (0x0f00, 0x00f0, 0x000f, 0xf000), (0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000) ] depths = [16, 32] for expected, depth in list(zip(masks, depths)): surface = pygame.Surface((10, 10), pygame.SRCALPHA, depth) self.assertEqual(expected, surface.get_masks()) def test_get_masks__rgb(self): """ Ensure that get_mask can return RGB mask. """ masks = [ (0x60, 0x1c, 0x03, 0x00), (0xf00, 0x0f0, 0x00f, 0x000), (0x7c00, 0x03e0, 0x001f, 0x0000), (0xf800, 0x07e0, 0x001f, 0x0000), (0xff0000, 0x00ff00, 0x0000ff, 0x000000), (0xff0000, 0x00ff00, 0x0000ff, 0x000000) ] depths = [8, 12, 15, 16, 24, 32] for expected, depth in list(zip(masks, depths)): surface = pygame.Surface((10, 10), 0, depth) if depth == 8 and pygame.get_sdl_version()[0] == 2: expected = (0x00, 0x00, 0x00, 0x00) self.assertEqual(expected, surface.get_masks()) def test_get_masks__no_surface(self): """ Ensure that after display.quit, calling get_masks raises pygame.error. """ with self.assertRaises(pygame.error): surface = pygame.display.set_mode((10, 10)) pygame.display.quit() surface.get_masks() def test_get_offset(self): """get_offset returns the (0,0) if surface is not a child returns the position of child subsurface inside of parent """ pygame.display.init() try: surf = pygame.Surface((100, 100)) self.assertEqual(surf.get_offset(), (0, 0)) # subsurface offset test subsurf = surf.subsurface(1, 1, 10, 10) self.assertEqual(subsurf.get_offset(), (1, 1)) with self.assertRaises(pygame.error): surface = pygame.display.set_mode() pygame.display.quit() surface.get_offset() finally: pygame.display.quit() def test_get_palette(self): pygame.display.init() try: palette = [Color(i, i, i) for i in range(256)] pygame.display.set_mode((100, 50)) surf = pygame.Surface((2, 2), 0, 8) surf.set_palette(palette) palette2 = surf.get_palette() r, g, b = palette2[0] self.assertEqual(len(palette2), len(palette)) for c2, c in zip(palette2, palette): self.assertEqual(c2, c) for c in palette2: self.assertIsInstance(c, pygame.Color) finally: pygame.display.quit() def test_get_palette_at(self): # See also test_get_palette pygame.display.init() try: pygame.display.set_mode((100, 50)) surf = pygame.Surface((2, 2), 0, 8) color = pygame.Color(1, 2, 3, 255) surf.set_palette_at(0, color) color2 = surf.get_palette_at(0) self.assertIsInstance(color2, pygame.Color) self.assertEqual(color2, color) self.assertRaises(IndexError, surf.get_palette_at, -1) self.assertRaises(IndexError, surf.get_palette_at, 256) finally: pygame.display.quit() def test_get_pitch(self): # Test get_pitch() on several surfaces of varying size/depth sizes = ((2, 2), (7, 33), (33, 7), (2, 734), (734, 2), (734, 734)) depths = [8, 24, 32] for width, height in sizes: for depth in depths: # Test get_pitch() on parent surface surf = pygame.Surface((width, height), depth=depth) buff = surf.get_buffer() pitch = buff.length / surf.get_height() test_pitch = surf.get_pitch() self.assertEqual(pitch, test_pitch) # Test get_pitch() on subsurface with same rect as parent rect1 = surf.get_rect() subsurf1 = surf.subsurface(rect1) sub_buff1 = subsurf1.get_buffer() sub_pitch1 = sub_buff1.length / subsurf1.get_height() test_sub_pitch1 = subsurf1.get_pitch() self.assertEqual(sub_pitch1, test_sub_pitch1) # Test get_pitch on subsurface with modified rect rect2 = rect1.inflate(-width / 2, -height / 2) subsurf2 = surf.subsurface(rect2) sub_buff2 = subsurf2.get_buffer() sub_pitch2 = sub_buff2.length / float(subsurf2.get_height()) test_sub_pitch2 = subsurf2.get_pitch() self.assertEqual(sub_pitch2, test_sub_pitch2) def test_get_shifts(self): """Tests whether Surface.get_shifts returns proper RGBA shifts under various conditions.""" # __doc__ (as of 2008-08-02) for pygame.surface.Surface.get_shifts: # Surface.get_shifts(): return (R, G, B, A) # the bit shifts needed to convert between a color and a mapped integer # # Returns the pixel shifts need to convert between each color and a # mapped integer. # # This value is not needed for normal Pygame usage. # Test for SDL1 -> set_shifts() raises AttributeError in SDL2 if SDL1: surface = pygame.Surface((32, 32)) surface.set_shifts((2, 4, 8, 16)) r, g, b, a = surface.get_shifts() self.assertEqual((r, g, b, a), (2, 4, 8, 16)) # Test for SDL2 on surfaces with various depths and alpha on/off else: depths = [8, 24, 32] alpha = 128 off = None for bit_depth in depths: surface = pygame.Surface((32, 32), depth=bit_depth) surface.set_alpha(alpha) r1, g1, b1, a1 = surface.get_shifts() surface.set_alpha(off) r2, g2, b2, a2 = surface.get_shifts() self.assertEqual((r1, g1, b1, a1), (r2, g2, b2, a2)) def test_get_size(self): sizes = ((1, 1), (119, 10), (1000, 1000), (1, 5000), (1221, 1), (99, 999)) for width, height in sizes: surf = pygame.Surface((width, height)) found_size = surf.get_size() self.assertEqual((width, height), found_size) def test_lock(self): # __doc__ (as of 2008-08-02) for pygame.surface.Surface.lock: # Surface.lock(): return None # lock the Surface memory for pixel access # # Lock the pixel data of a Surface for access. On accelerated # Surfaces, the pixel data may be stored in volatile video memory or # nonlinear compressed forms. When a Surface is locked the pixel # memory becomes available to access by regular software. Code that # reads or writes pixel values will need the Surface to be locked. # # Surfaces should not remain locked for more than necessary. A locked # Surface can often not be displayed or managed by Pygame. # # Not all Surfaces require locking. The Surface.mustlock() method can # determine if it is actually required. There is no performance # penalty for locking and unlocking a Surface that does not need it. # # All pygame functions will automatically lock and unlock the Surface # data as needed. If a section of code is going to make calls that # will repeatedly lock and unlock the Surface many times, it can be # helpful to wrap the block inside a lock and unlock pair. # # It is safe to nest locking and unlocking calls. The surface will # only be unlocked after the final lock is released. # # Basic surf = pygame.Surface((100, 100)) surf.lock() self.assertTrue(surf.get_locked()) # Nested surf = pygame.Surface((100, 100)) surf.lock() surf.lock() surf.unlock() self.assertTrue(surf.get_locked()) surf.unlock() surf.lock() surf.lock() self.assertTrue(surf.get_locked()) surf.unlock() self.assertTrue(surf.get_locked()) surf.unlock() self.assertFalse(surf.get_locked()) # Already Locked surf = pygame.Surface((100, 100)) surf.lock() surf.lock() self.assertTrue(surf.get_locked()) surf.unlock() self.assertTrue(surf.get_locked()) surf.unlock() self.assertFalse(surf.get_locked()) def test_map_rgb(self): color = Color(0, 128, 255, 64) surf = pygame.Surface((5, 5), SRCALPHA, 32) c = surf.map_rgb(color) self.assertEqual(surf.unmap_rgb(c), color) self.assertEqual(surf.get_at((0, 0)), (0, 0, 0, 0)) surf.fill(c) self.assertEqual(surf.get_at((0, 0)), color) surf.fill((0, 0, 0, 0)) self.assertEqual(surf.get_at((0, 0)), (0, 0, 0, 0)) surf.set_at((0, 0), c) self.assertEqual(surf.get_at((0, 0)), color) def test_mustlock(self): # Test that subsurfaces mustlock surf = pygame.Surface((1024, 1024)) subsurf = surf.subsurface((0, 0, 1024, 1024)) self.assertTrue(subsurf.mustlock()) self.assertFalse(surf.mustlock()) # Tests nested subsurfaces rects = ((0, 0, 512, 512), (0, 0, 256, 256), (0, 0, 128, 128)) surf_stack = [] surf_stack.append(surf) surf_stack.append(subsurf) for rect in rects: surf_stack.append(surf_stack[-1].subsurface(rect)) self.assertTrue(surf_stack[-1].mustlock()) self.assertTrue(surf_stack[-2].mustlock()) def test_set_alpha_none(self): """surf.set_alpha(None) disables blending""" s = pygame.Surface((1, 1), SRCALPHA, 32) s.fill((0, 255, 0, 128)) s.set_alpha(None) self.assertEqual(None, s.get_alpha()) s2 = pygame.Surface((1, 1), SRCALPHA, 32) s2.fill((255, 0, 0, 255)) s2.blit(s, (0, 0)) self.assertEqual(s2.get_at((0, 0))[0], 0, "the red component should be 0") def test_set_alpha_value(self): """surf.set_alpha(x), where x != None, enables blending""" s = pygame.Surface((1, 1), SRCALPHA, 32) s.fill((0, 255, 0, 128)) s.set_alpha(255) s2 = pygame.Surface((1, 1), SRCALPHA, 32) s2.fill((255, 0, 0, 255)) s2.blit(s, (0, 0)) self.assertGreater( s2.get_at((0, 0))[0], 0, "the red component should be above 0" ) def test_palette_colorkey(self): """test bug discovered by robertpfeiffer https://github.com/pygame/pygame/issues/721 """ surf = pygame.image.load(example_path(os.path.join("data", "alien2.png"))) key = surf.get_colorkey() self.assertEqual(surf.get_palette()[surf.map_rgb(key)], key) def test_palette_colorkey_set_px(self): surf = pygame.image.load(example_path(os.path.join("data", "alien2.png"))) key = surf.get_colorkey() surf.set_at((0, 0), key) self.assertEqual(surf.get_at((0, 0)), key) def test_palette_colorkey_fill(self): surf = pygame.image.load(example_path(os.path.join("data", "alien2.png"))) key = surf.get_colorkey() surf.fill(key) self.assertEqual(surf.get_at((0, 0)), key) def test_set_palette(self): palette = [pygame.Color(i, i, i) for i in range(256)] palette[10] = tuple(palette[10]) # 4 element tuple palette[11] = tuple(palette[11])[0:3] # 3 element tuple surf = pygame.Surface((2, 2), 0, 8) pygame.display.init() try: pygame.display.set_mode((100, 50)) surf.set_palette(palette) for i in range(256): self.assertEqual(surf.map_rgb(palette[i]), i, "palette color %i" % (i,)) c = palette[i] surf.fill(c) self.assertEqual(surf.get_at((0, 0)), c, "palette color %i" % (i,)) for i in range(10): palette[i] = pygame.Color(255 - i, 0, 0) surf.set_palette(palette[0:10]) for i in range(256): self.assertEqual(surf.map_rgb(palette[i]), i, "palette color %i" % (i,)) c = palette[i] surf.fill(c) self.assertEqual(surf.get_at((0, 0)), c, "palette color %i" % (i,)) self.assertRaises(ValueError, surf.set_palette, [Color(1, 2, 3, 254)]) self.assertRaises(ValueError, surf.set_palette, (1, 2, 3, 254)) finally: pygame.display.quit() def test_set_palette__fail(self): pygame.init() palette = 256 * [(10, 20, 30)] surf = pygame.Surface((2, 2), 0, 32) self.assertRaises(pygame.error, surf.set_palette, palette) pygame.quit() def test_set_palette_at(self): pygame.display.init() try: pygame.display.set_mode((100, 50)) surf = pygame.Surface((2, 2), 0, 8) original = surf.get_palette_at(10) replacement = Color(1, 1, 1, 255) if replacement == original: replacement = Color(2, 2, 2, 255) surf.set_palette_at(10, replacement) self.assertEqual(surf.get_palette_at(10), replacement) next = tuple(original) surf.set_palette_at(10, next) self.assertEqual(surf.get_palette_at(10), next) next = tuple(original)[0:3] surf.set_palette_at(10, next) self.assertEqual(surf.get_palette_at(10), next) self.assertRaises(IndexError, surf.set_palette_at, 256, replacement) self.assertRaises(IndexError, surf.set_palette_at, -1, replacement) finally: pygame.display.quit() def test_subsurface(self): # __doc__ (as of 2008-08-02) for pygame.surface.Surface.subsurface: # Surface.subsurface(Rect): return Surface # create a new surface that references its parent # # Returns a new Surface that shares its pixels with its new parent. # The new Surface is considered a child of the original. Modifications # to either Surface pixels will effect each other. Surface information # like clipping area and color keys are unique to each Surface. # # The new Surface will inherit the palette, color key, and alpha # settings from its parent. # # It is possible to have any number of subsurfaces and subsubsurfaces # on the parent. It is also possible to subsurface the display Surface # if the display mode is not hardware accelerated. # # See the Surface.get_offset(), Surface.get_parent() to learn more # about the state of a subsurface. # surf = pygame.Surface((16, 16)) s = surf.subsurface(0, 0, 1, 1) s = surf.subsurface((0, 0, 1, 1)) # s = surf.subsurface((0,0,1,1), 1) # This form is not acceptable. # s = surf.subsurface(0,0,10,10, 1) self.assertRaises(ValueError, surf.subsurface, (0, 0, 1, 1, 666)) self.assertEqual(s.get_shifts(), surf.get_shifts()) self.assertEqual(s.get_masks(), surf.get_masks()) self.assertEqual(s.get_losses(), surf.get_losses()) # Issue 2 at Bitbucket.org/pygame/pygame surf = pygame.Surface.__new__(pygame.Surface) self.assertRaises(pygame.error, surf.subsurface, (0, 0, 0, 0)) def test_unlock(self): # Basic surf = pygame.Surface((100, 100)) surf.lock() surf.unlock() self.assertFalse(surf.get_locked()) # Nested surf = pygame.Surface((100, 100)) surf.lock() surf.lock() surf.unlock() self.assertTrue(surf.get_locked()) surf.unlock() self.assertFalse(surf.get_locked()) # Already Unlocked surf = pygame.Surface((100, 100)) surf.unlock() self.assertFalse(surf.get_locked()) surf.unlock() self.assertFalse(surf.get_locked()) # Surface can be relocked surf = pygame.Surface((100, 100)) surf.lock() surf.unlock() self.assertFalse(surf.get_locked()) surf.lock() surf.unlock() self.assertFalse(surf.get_locked()) def test_unmap_rgb(self): # Special case, 8 bit-per-pixel surface (has a palette). surf = pygame.Surface((2, 2), 0, 8) c = (1, 1, 1) # Unlikely to be in a default palette. i = 67 pygame.display.init() try: pygame.display.set_mode((100, 50)) surf.set_palette_at(i, c) unmapped_c = surf.unmap_rgb(i) self.assertEqual(unmapped_c, c) # Confirm it is a Color instance self.assertIsInstance(unmapped_c, pygame.Color) finally: pygame.display.quit() # Remaining, non-pallete, cases. c = (128, 64, 12, 255) formats = [(0, 16), (0, 24), (0, 32), (SRCALPHA, 16), (SRCALPHA, 32)] for flags, bitsize in formats: surf = pygame.Surface((2, 2), flags, bitsize) unmapped_c = surf.unmap_rgb(surf.map_rgb(c)) surf.fill(c) comparison_c = surf.get_at((0, 0)) self.assertEqual( unmapped_c, comparison_c, "%s != %s, flags: %i, bitsize: %i" % (unmapped_c, comparison_c, flags, bitsize), ) # Confirm it is a Color instance self.assertIsInstance(unmapped_c, pygame.Color) def test_scroll(self): scrolls = [ (8, 2, 3), (16, 2, 3), (24, 2, 3), (32, 2, 3), (32, -1, -3), (32, 0, 0), (32, 11, 0), (32, 0, 11), (32, -11, 0), (32, 0, -11), (32, -11, 2), (32, 2, -11), ] for bitsize, dx, dy in scrolls: surf = pygame.Surface((10, 10), 0, bitsize) surf.fill((255, 0, 0)) surf.fill((0, 255, 0), (2, 2, 2, 2)) comp = surf.copy() comp.blit(surf, (dx, dy)) surf.scroll(dx, dy) w, h = surf.get_size() for x in range(w): for y in range(h): with self.subTest(x=x, y=y): self.assertEqual( surf.get_at((x, y)), comp.get_at((x, y)), "%s != %s, bpp:, %i, x: %i, y: %i" % ( surf.get_at((x, y)), comp.get_at((x, y)), bitsize, dx, dy, ), ) # Confirm clip rect containment surf = pygame.Surface((20, 13), 0, 32) surf.fill((255, 0, 0)) surf.fill((0, 255, 0), (7, 1, 6, 6)) comp = surf.copy() clip = Rect(3, 1, 8, 14) surf.set_clip(clip) comp.set_clip(clip) comp.blit(surf, (clip.x + 2, clip.y + 3), surf.get_clip()) surf.scroll(2, 3) w, h = surf.get_size() for x in range(w): for y in range(h): self.assertEqual(surf.get_at((x, y)), comp.get_at((x, y))) # Confirm keyword arguments and per-pixel alpha spot_color = (0, 255, 0, 128) surf = pygame.Surface((4, 4), pygame.SRCALPHA, 32) surf.fill((255, 0, 0, 255)) surf.set_at((1, 1), spot_color) surf.scroll(dx=1) self.assertEqual(surf.get_at((2, 1)), spot_color) surf.scroll(dy=1) self.assertEqual(surf.get_at((2, 2)), spot_color) surf.scroll(dy=1, dx=1) self.assertEqual(surf.get_at((3, 3)), spot_color) surf.scroll(dx=-3, dy=-3) self.assertEqual(surf.get_at((0, 0)), spot_color) class SurfaceSubtypeTest(unittest.TestCase): """Issue #280: Methods that return a new Surface preserve subclasses""" def setUp(self): pygame.display.init() def tearDown(self): pygame.display.quit() def test_copy(self): """Ensure method copy() preserves the surface's class When Surface is subclassed, the inherited copy() method will return instances of the subclass. Non Surface fields are uncopied, however. This includes instance attributes. """ expected_size = (32, 32) ms1 = SurfaceSubclass(expected_size, SRCALPHA, 32) ms2 = ms1.copy() self.assertIsNot(ms1, ms2) self.assertIsInstance(ms1, pygame.Surface) self.assertIsInstance(ms2, pygame.Surface) self.assertIsInstance(ms1, SurfaceSubclass) self.assertIsInstance(ms2, SurfaceSubclass) self.assertTrue(ms1.test_attribute) self.assertRaises(AttributeError, getattr, ms2, "test_attribute") self.assertEqual(ms2.get_size(), expected_size) def test_convert(self): """Ensure method convert() preserves the surface's class When Surface is subclassed, the inherited convert() method will return instances of the subclass. Non Surface fields are omitted, however. This includes instance attributes. """ expected_size = (32, 32) ms1 = SurfaceSubclass(expected_size, 0, 24) ms2 = ms1.convert(24) self.assertIsNot(ms1, ms2) self.assertIsInstance(ms1, pygame.Surface) self.assertIsInstance(ms2, pygame.Surface) self.assertIsInstance(ms1, SurfaceSubclass) self.assertIsInstance(ms2, SurfaceSubclass) self.assertTrue(ms1.test_attribute) self.assertRaises(AttributeError, getattr, ms2, "test_attribute") self.assertEqual(ms2.get_size(), expected_size) def test_convert_alpha(self): """Ensure method convert_alpha() preserves the surface's class When Surface is subclassed, the inherited convert_alpha() method will return instances of the subclass. Non Surface fields are omitted, however. This includes instance attributes. """ pygame.display.set_mode((40, 40)) expected_size = (32, 32) s = pygame.Surface(expected_size, SRCALPHA, 16) ms1 = SurfaceSubclass(expected_size, SRCALPHA, 32) ms2 = ms1.convert_alpha(s) self.assertIsNot(ms1, ms2) self.assertIsInstance(ms1, pygame.Surface) self.assertIsInstance(ms2, pygame.Surface) self.assertIsInstance(ms1, SurfaceSubclass) self.assertIsInstance(ms2, SurfaceSubclass) self.assertTrue(ms1.test_attribute) self.assertRaises(AttributeError, getattr, ms2, "test_attribute") self.assertEqual(ms2.get_size(), expected_size) def test_subsurface(self): """Ensure method subsurface() preserves the surface's class When Surface is subclassed, the inherited subsurface() method will return instances of the subclass. Non Surface fields are uncopied, however. This includes instance attributes. """ expected_size = (10, 12) ms1 = SurfaceSubclass((32, 32), SRCALPHA, 32) ms2 = ms1.subsurface((4, 5), expected_size) self.assertIsNot(ms1, ms2) self.assertIsInstance(ms1, pygame.Surface) self.assertIsInstance(ms2, pygame.Surface) self.assertIsInstance(ms1, SurfaceSubclass) self.assertIsInstance(ms2, SurfaceSubclass) self.assertTrue(ms1.test_attribute) self.assertRaises(AttributeError, getattr, ms2, "test_attribute") self.assertEqual(ms2.get_size(), expected_size) class SurfaceGetBufferTest(unittest.TestCase): # These tests requires ctypes. They are disabled if ctypes # is not installed. # try: ArrayInterface except NameError: __tags__ = ("ignore", "subprocess_ignore") lilendian = pygame.get_sdl_byteorder() == pygame.LIL_ENDIAN def _check_interface_2D(self, s): s_w, s_h = s.get_size() s_bytesize = s.get_bytesize() s_pitch = s.get_pitch() s_pixels = s._pixels_address # check the array interface structure fields. v = s.get_view("2") if not IS_PYPY: flags = PAI_ALIGNED | PAI_NOTSWAPPED | PAI_WRITEABLE if s.get_pitch() == s_w * s_bytesize: flags |= PAI_FORTRAN inter = ArrayInterface(v) self.assertEqual(inter.two, 2) self.assertEqual(inter.nd, 2) self.assertEqual(inter.typekind, "u") self.assertEqual(inter.itemsize, s_bytesize) self.assertEqual(inter.shape[0], s_w) self.assertEqual(inter.shape[1], s_h) self.assertEqual(inter.strides[0], s_bytesize) self.assertEqual(inter.strides[1], s_pitch) self.assertEqual(inter.flags, flags) self.assertEqual(inter.data, s_pixels) def _check_interface_3D(self, s): s_w, s_h = s.get_size() s_bytesize = s.get_bytesize() s_pitch = s.get_pitch() s_pixels = s._pixels_address s_shifts = list(s.get_shifts()) # Check for RGB or BGR surface. if s_shifts[0:3] == [0, 8, 16]: if self.lilendian: # RGB offset = 0 step = 1 else: # BGR offset = s_bytesize - 1 step = -1 elif s_shifts[0:3] == [8, 16, 24]: if self.lilendian: # xRGB offset = 1 step = 1 else: # BGRx offset = s_bytesize - 2 step = -1 elif s_shifts[0:3] == [16, 8, 0]: if self.lilendian: # BGR offset = 2 step = -1 else: # RGB offset = s_bytesize - 3 step = 1 elif s_shifts[0:3] == [24, 16, 8]: if self.lilendian: # BGRx offset = 2 step = -1 else: # RGBx offset = s_bytesize - 4 step = -1 else: return # check the array interface structure fields. v = s.get_view("3") if not IS_PYPY: inter = ArrayInterface(v) flags = PAI_ALIGNED | PAI_NOTSWAPPED | PAI_WRITEABLE self.assertEqual(inter.two, 2) self.assertEqual(inter.nd, 3) self.assertEqual(inter.typekind, "u") self.assertEqual(inter.itemsize, 1) self.assertEqual(inter.shape[0], s_w) self.assertEqual(inter.shape[1], s_h) self.assertEqual(inter.shape[2], 3) self.assertEqual(inter.strides[0], s_bytesize) self.assertEqual(inter.strides[1], s_pitch) self.assertEqual(inter.strides[2], step) self.assertEqual(inter.flags, flags) self.assertEqual(inter.data, s_pixels + offset) def _check_interface_rgba(self, s, plane): s_w, s_h = s.get_size() s_bytesize = s.get_bytesize() s_pitch = s.get_pitch() s_pixels = s._pixels_address s_shifts = s.get_shifts() s_masks = s.get_masks() # Find the color plane position within the pixel. if not s_masks[plane]: return alpha_shift = s_shifts[plane] offset = alpha_shift // 8 if not self.lilendian: offset = s_bytesize - offset - 1 # check the array interface structure fields. v = s.get_view("rgba"[plane]) if not IS_PYPY: inter = ArrayInterface(v) flags = PAI_ALIGNED | PAI_NOTSWAPPED | PAI_WRITEABLE self.assertEqual(inter.two, 2) self.assertEqual(inter.nd, 2) self.assertEqual(inter.typekind, "u") self.assertEqual(inter.itemsize, 1) self.assertEqual(inter.shape[0], s_w) self.assertEqual(inter.shape[1], s_h) self.assertEqual(inter.strides[0], s_bytesize) self.assertEqual(inter.strides[1], s_pitch) self.assertEqual(inter.flags, flags) self.assertEqual(inter.data, s_pixels + offset) def test_array_interface(self): self._check_interface_2D(pygame.Surface((5, 7), 0, 8)) self._check_interface_2D(pygame.Surface((5, 7), 0, 16)) self._check_interface_2D(pygame.Surface((5, 7), pygame.SRCALPHA, 16)) self._check_interface_3D(pygame.Surface((5, 7), 0, 24)) self._check_interface_3D(pygame.Surface((8, 4), 0, 24)) # No gaps self._check_interface_2D(pygame.Surface((5, 7), 0, 32)) self._check_interface_3D(pygame.Surface((5, 7), 0, 32)) self._check_interface_2D(pygame.Surface((5, 7), pygame.SRCALPHA, 32)) self._check_interface_3D(pygame.Surface((5, 7), pygame.SRCALPHA, 32)) def test_array_interface_masks(self): """Test non-default color byte orders on 3D views""" sz = (5, 7) # Reversed RGB byte order s = pygame.Surface(sz, 0, 32) s_masks = list(s.get_masks()) masks = [0xFF, 0xFF00, 0xFF0000] if s_masks[0:3] == masks or s_masks[0:3] == masks[::-1]: masks = s_masks[2::-1] + s_masks[3:4] self._check_interface_3D(pygame.Surface(sz, 0, 32, masks)) s = pygame.Surface(sz, 0, 24) s_masks = list(s.get_masks()) masks = [0xFF, 0xFF00, 0xFF0000] if s_masks[0:3] == masks or s_masks[0:3] == masks[::-1]: masks = s_masks[2::-1] + s_masks[3:4] self._check_interface_3D(pygame.Surface(sz, 0, 24, masks)) masks = [0xFF00, 0xFF0000, 0xFF000000, 0] self._check_interface_3D(pygame.Surface(sz, 0, 32, masks)) # Unsupported RGB byte orders if pygame.get_sdl_version()[0] == 1: # Invalid mask values with SDL2 masks = [0xFF00, 0xFF, 0xFF0000, 0] self.assertRaises( ValueError, pygame.Surface(sz, 0, 24, masks).get_view, "3" ) def test_array_interface_alpha(self): for shifts in [[0, 8, 16, 24], [8, 16, 24, 0], [24, 16, 8, 0], [16, 8, 0, 24]]: masks = [0xFF << s for s in shifts] s = pygame.Surface((4, 2), pygame.SRCALPHA, 32, masks) self._check_interface_rgba(s, 3) def test_array_interface_rgb(self): for shifts in [[0, 8, 16, 24], [8, 16, 24, 0], [24, 16, 8, 0], [16, 8, 0, 24]]: masks = [0xFF << s for s in shifts] masks[3] = 0 for plane in range(3): s = pygame.Surface((4, 2), 0, 24) self._check_interface_rgba(s, plane) s = pygame.Surface((4, 2), 0, 32) self._check_interface_rgba(s, plane) @unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented") def test_newbuf_PyBUF_flags_bytes(self): from pygame.tests.test_utils import buftools Importer = buftools.Importer s = pygame.Surface((10, 6), 0, 32) a = s.get_buffer() b = Importer(a, buftools.PyBUF_SIMPLE) self.assertEqual(b.ndim, 0) self.assertTrue(b.format is None) self.assertEqual(b.len, a.length) self.assertEqual(b.itemsize, 1) self.assertTrue(b.shape is None) self.assertTrue(b.strides is None) self.assertTrue(b.suboffsets is None) self.assertFalse(b.readonly) self.assertEqual(b.buf, s._pixels_address) b = Importer(a, buftools.PyBUF_WRITABLE) self.assertEqual(b.ndim, 0) self.assertTrue(b.format is None) self.assertFalse(b.readonly) b = Importer(a, buftools.PyBUF_FORMAT) self.assertEqual(b.ndim, 0) self.assertEqual(b.format, "B") b = Importer(a, buftools.PyBUF_ND) self.assertEqual(b.ndim, 1) self.assertTrue(b.format is None) self.assertEqual(b.len, a.length) self.assertEqual(b.itemsize, 1) self.assertEqual(b.shape, (a.length,)) self.assertTrue(b.strides is None) self.assertTrue(b.suboffsets is None) self.assertFalse(b.readonly) self.assertEqual(b.buf, s._pixels_address) b = Importer(a, buftools.PyBUF_STRIDES) self.assertEqual(b.ndim, 1) self.assertTrue(b.format is None) self.assertEqual(b.strides, (1,)) s2 = s.subsurface((1, 1, 7, 4)) # Not contiguous a = s2.get_buffer() b = Importer(a, buftools.PyBUF_SIMPLE) self.assertEqual(b.ndim, 0) self.assertTrue(b.format is None) self.assertEqual(b.len, a.length) self.assertEqual(b.itemsize, 1) self.assertTrue(b.shape is None) self.assertTrue(b.strides is None) self.assertTrue(b.suboffsets is None) self.assertFalse(b.readonly) self.assertEqual(b.buf, s2._pixels_address) b = Importer(a, buftools.PyBUF_C_CONTIGUOUS) self.assertEqual(b.ndim, 1) self.assertEqual(b.strides, (1,)) b = Importer(a, buftools.PyBUF_F_CONTIGUOUS) self.assertEqual(b.ndim, 1) self.assertEqual(b.strides, (1,)) b = Importer(a, buftools.PyBUF_ANY_CONTIGUOUS) self.assertEqual(b.ndim, 1) self.assertEqual(b.strides, (1,)) @unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented") def test_newbuf_PyBUF_flags_0D(self): # This is the same handler as used by get_buffer(), so just # confirm that it succeeds for one case. from pygame.tests.test_utils import buftools Importer = buftools.Importer s = pygame.Surface((10, 6), 0, 32) a = s.get_view("0") b = Importer(a, buftools.PyBUF_SIMPLE) self.assertEqual(b.ndim, 0) self.assertTrue(b.format is None) self.assertEqual(b.len, a.length) self.assertEqual(b.itemsize, 1) self.assertTrue(b.shape is None) self.assertTrue(b.strides is None) self.assertTrue(b.suboffsets is None) self.assertFalse(b.readonly) self.assertEqual(b.buf, s._pixels_address) @unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented") def test_newbuf_PyBUF_flags_1D(self): from pygame.tests.test_utils import buftools Importer = buftools.Importer s = pygame.Surface((10, 6), 0, 32) a = s.get_view("1") b = Importer(a, buftools.PyBUF_SIMPLE) self.assertEqual(b.ndim, 0) self.assertTrue(b.format is None) self.assertEqual(b.len, a.length) self.assertEqual(b.itemsize, s.get_bytesize()) self.assertTrue(b.shape is None) self.assertTrue(b.strides is None) self.assertTrue(b.suboffsets is None) self.assertFalse(b.readonly) self.assertEqual(b.buf, s._pixels_address) b = Importer(a, buftools.PyBUF_WRITABLE) self.assertEqual(b.ndim, 0) self.assertTrue(b.format is None) self.assertFalse(b.readonly) b = Importer(a, buftools.PyBUF_FORMAT) self.assertEqual(b.ndim, 0) self.assertEqual(b.format, "=I") b = Importer(a, buftools.PyBUF_ND) self.assertEqual(b.ndim, 1) self.assertTrue(b.format is None) self.assertEqual(b.len, a.length) self.assertEqual(b.itemsize, s.get_bytesize()) self.assertEqual(b.shape, (s.get_width() * s.get_height(),)) self.assertTrue(b.strides is None) self.assertTrue(b.suboffsets is None) self.assertFalse(b.readonly) self.assertEqual(b.buf, s._pixels_address) b = Importer(a, buftools.PyBUF_STRIDES) self.assertEqual(b.ndim, 1) self.assertTrue(b.format is None) self.assertEqual(b.strides, (s.get_bytesize(),)) @unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented") def test_newbuf_PyBUF_flags_2D(self): from pygame.tests.test_utils import buftools Importer = buftools.Importer s = pygame.Surface((10, 6), 0, 32) a = s.get_view("2") # Non dimensional requests, no PyDEF_ND, are handled by the # 1D surface buffer code, so only need to confirm a success. b = Importer(a, buftools.PyBUF_SIMPLE) self.assertEqual(b.ndim, 0) self.assertTrue(b.format is None) self.assertEqual(b.len, a.length) self.assertEqual(b.itemsize, s.get_bytesize()) self.assertTrue(b.shape is None) self.assertTrue(b.strides is None) self.assertTrue(b.suboffsets is None) self.assertFalse(b.readonly) self.assertEqual(b.buf, s._pixels_address) # Uniquely 2D b = Importer(a, buftools.PyBUF_STRIDES) self.assertEqual(b.ndim, 2) self.assertTrue(b.format is None) self.assertEqual(b.len, a.length) self.assertEqual(b.itemsize, s.get_bytesize()) self.assertEqual(b.shape, s.get_size()) self.assertEqual(b.strides, (s.get_bytesize(), s.get_pitch())) self.assertTrue(b.suboffsets is None) self.assertFalse(b.readonly) self.assertEqual(b.buf, s._pixels_address) b = Importer(a, buftools.PyBUF_RECORDS_RO) self.assertEqual(b.ndim, 2) self.assertEqual(b.format, "=I") self.assertEqual(b.strides, (s.get_bytesize(), s.get_pitch())) b = Importer(a, buftools.PyBUF_RECORDS) self.assertEqual(b.ndim, 2) self.assertEqual(b.format, "=I") self.assertEqual(b.strides, (s.get_bytesize(), s.get_pitch())) b = Importer(a, buftools.PyBUF_F_CONTIGUOUS) self.assertEqual(b.ndim, 2) self.assertEqual(b.format, None) self.assertEqual(b.strides, (s.get_bytesize(), s.get_pitch())) b = Importer(a, buftools.PyBUF_ANY_CONTIGUOUS) self.assertEqual(b.ndim, 2) self.assertEqual(b.format, None) self.assertEqual(b.strides, (s.get_bytesize(), s.get_pitch())) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ND) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_C_CONTIGUOUS) s2 = s.subsurface((1, 1, 7, 4)) # Not contiguous a = s2.get_view("2") b = Importer(a, buftools.PyBUF_STRIDES) self.assertEqual(b.ndim, 2) self.assertTrue(b.format is None) self.assertEqual(b.len, a.length) self.assertEqual(b.itemsize, s2.get_bytesize()) self.assertEqual(b.shape, s2.get_size()) self.assertEqual(b.strides, (s2.get_bytesize(), s.get_pitch())) self.assertTrue(b.suboffsets is None) self.assertFalse(b.readonly) self.assertEqual(b.buf, s2._pixels_address) b = Importer(a, buftools.PyBUF_RECORDS) self.assertEqual(b.ndim, 2) self.assertEqual(b.format, "=I") self.assertRaises(BufferError, Importer, a, buftools.PyBUF_SIMPLE) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_FORMAT) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_WRITABLE) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ND) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_C_CONTIGUOUS) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_F_CONTIGUOUS) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ANY_CONTIGUOUS) @unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented") def test_newbuf_PyBUF_flags_3D(self): from pygame.tests.test_utils import buftools Importer = buftools.Importer s = pygame.Surface((12, 6), 0, 24) rmask, gmask, bmask, amask = s.get_masks() if self.lilendian: if rmask == 0x0000FF: color_step = 1 addr_offset = 0 else: color_step = -1 addr_offset = 2 else: if rmask == 0xFF0000: color_step = 1 addr_offset = 0 else: color_step = -1 addr_offset = 2 a = s.get_view("3") b = Importer(a, buftools.PyBUF_STRIDES) w, h = s.get_size() shape = w, h, 3 strides = 3, s.get_pitch(), color_step self.assertEqual(b.ndim, 3) self.assertTrue(b.format is None) self.assertEqual(b.len, a.length) self.assertEqual(b.itemsize, 1) self.assertEqual(b.shape, shape) self.assertEqual(b.strides, strides) self.assertTrue(b.suboffsets is None) self.assertFalse(b.readonly) self.assertEqual(b.buf, s._pixels_address + addr_offset) b = Importer(a, buftools.PyBUF_RECORDS_RO) self.assertEqual(b.ndim, 3) self.assertEqual(b.format, "B") self.assertEqual(b.strides, strides) b = Importer(a, buftools.PyBUF_RECORDS) self.assertEqual(b.ndim, 3) self.assertEqual(b.format, "B") self.assertEqual(b.strides, strides) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_SIMPLE) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_FORMAT) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_WRITABLE) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ND) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_C_CONTIGUOUS) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_F_CONTIGUOUS) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ANY_CONTIGUOUS) @unittest.skipIf(not pygame.HAVE_NEWBUF, "newbuf not implemented") def test_newbuf_PyBUF_flags_rgba(self): # All color plane views are handled by the same routine, # so only one plane need be checked. from pygame.tests.test_utils import buftools Importer = buftools.Importer s = pygame.Surface((12, 6), 0, 24) rmask, gmask, bmask, amask = s.get_masks() if self.lilendian: if rmask == 0x0000FF: addr_offset = 0 else: addr_offset = 2 else: if rmask == 0xFF0000: addr_offset = 0 else: addr_offset = 2 a = s.get_view("R") b = Importer(a, buftools.PyBUF_STRIDES) w, h = s.get_size() shape = w, h strides = s.get_bytesize(), s.get_pitch() self.assertEqual(b.ndim, 2) self.assertTrue(b.format is None) self.assertEqual(b.len, a.length) self.assertEqual(b.itemsize, 1) self.assertEqual(b.shape, shape) self.assertEqual(b.strides, strides) self.assertTrue(b.suboffsets is None) self.assertFalse(b.readonly) self.assertEqual(b.buf, s._pixels_address + addr_offset) b = Importer(a, buftools.PyBUF_RECORDS_RO) self.assertEqual(b.ndim, 2) self.assertEqual(b.format, "B") self.assertEqual(b.strides, strides) b = Importer(a, buftools.PyBUF_RECORDS) self.assertEqual(b.ndim, 2) self.assertEqual(b.format, "B") self.assertEqual(b.strides, strides) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_SIMPLE) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_FORMAT) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_WRITABLE) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ND) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_C_CONTIGUOUS) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_F_CONTIGUOUS) self.assertRaises(BufferError, Importer, a, buftools.PyBUF_ANY_CONTIGUOUS) class SurfaceBlendTest(unittest.TestCase): def setUp(self): # Needed for 8 bits-per-pixel color palette surface tests. pygame.display.init() def tearDown(self): pygame.display.quit() _test_palette = [ (0, 0, 0, 255), (10, 30, 60, 0), (25, 75, 100, 128), (200, 150, 100, 200), (0, 100, 200, 255), ] surf_size = (10, 12) _test_points = [ ((0, 0), 1), ((4, 5), 1), ((9, 0), 2), ((5, 5), 2), ((0, 11), 3), ((4, 6), 3), ((9, 11), 4), ((5, 6), 4), ] def _make_surface(self, bitsize, srcalpha=False, palette=None): if palette is None: palette = self._test_palette flags = 0 if srcalpha: flags |= SRCALPHA surf = pygame.Surface(self.surf_size, flags, bitsize) if bitsize == 8: surf.set_palette([c[:3] for c in palette]) return surf def _fill_surface(self, surf, palette=None): if palette is None: palette = self._test_palette surf.fill(palette[1], (0, 0, 5, 6)) surf.fill(palette[2], (5, 0, 5, 6)) surf.fill(palette[3], (0, 6, 5, 6)) surf.fill(palette[4], (5, 6, 5, 6)) def _make_src_surface(self, bitsize, srcalpha=False, palette=None): surf = self._make_surface(bitsize, srcalpha, palette) self._fill_surface(surf, palette) return surf def _assert_surface(self, surf, palette=None, msg=""): if palette is None: palette = self._test_palette if surf.get_bitsize() == 16: palette = [surf.unmap_rgb(surf.map_rgb(c)) for c in palette] for posn, i in self._test_points: self.assertEqual( surf.get_at(posn), palette[i], "%s != %s: flags: %i, bpp: %i, posn: %s%s" % ( surf.get_at(posn), palette[i], surf.get_flags(), surf.get_bitsize(), posn, msg, ), ) def test_blit_blend(self): sources = [ self._make_src_surface(8), self._make_src_surface(16), self._make_src_surface(16, srcalpha=True), self._make_src_surface(24), self._make_src_surface(32), self._make_src_surface(32, srcalpha=True), ] destinations = [ self._make_surface(8), self._make_surface(16), self._make_surface(16, srcalpha=True), self._make_surface(24), self._make_surface(32), self._make_surface(32, srcalpha=True), ] blend = [ ("BLEND_ADD", (0, 25, 100, 255), lambda a, b: min(a + b, 255)), ("BLEND_SUB", (100, 25, 0, 100), lambda a, b: max(a - b, 0)), ("BLEND_MULT", (100, 200, 0, 0), lambda a, b: (a * b) // 256), ("BLEND_MIN", (255, 0, 0, 255), min), ("BLEND_MAX", (0, 255, 0, 255), max), ] for src in sources: src_palette = [src.unmap_rgb(src.map_rgb(c)) for c in self._test_palette] for dst in destinations: for blend_name, dst_color, op in blend: dc = dst.unmap_rgb(dst.map_rgb(dst_color)) p = [] for sc in src_palette: c = [op(dc[i], sc[i]) for i in range(3)] if dst.get_masks()[3]: c.append(dc[3]) else: c.append(255) c = dst.unmap_rgb(dst.map_rgb(c)) p.append(c) dst.fill(dst_color) dst.blit(src, (0, 0), special_flags=getattr(pygame, blend_name)) self._assert_surface( dst, p, ( ", op: %s, src bpp: %i" ", src flags: %i" % (blend_name, src.get_bitsize(), src.get_flags()) ), ) src = self._make_src_surface(32) masks = src.get_masks() dst = pygame.Surface( src.get_size(), 0, 32, [masks[2], masks[1], masks[0], masks[3]] ) for blend_name, dst_color, op in blend: p = [] for src_color in self._test_palette: c = [op(dst_color[i], src_color[i]) for i in range(3)] c.append(255) p.append(tuple(c)) dst.fill(dst_color) dst.blit(src, (0, 0), special_flags=getattr(pygame, blend_name)) self._assert_surface(dst, p, ", %s" % blend_name) # Blend blits are special cased for 32 to 32 bit surfaces. # # Confirm that it works when the rgb bytes are not the # least significant bytes. pat = self._make_src_surface(32) masks = pat.get_masks() if min(masks) == intify(0xFF000000): masks = [longify(m) >> 8 for m in masks] else: masks = [intify(m << 8) for m in masks] src = pygame.Surface(pat.get_size(), 0, 32, masks) self._fill_surface(src) dst = pygame.Surface(src.get_size(), 0, 32, masks) for blend_name, dst_color, op in blend: p = [] for src_color in self._test_palette: c = [op(dst_color[i], src_color[i]) for i in range(3)] c.append(255) p.append(tuple(c)) dst.fill(dst_color) dst.blit(src, (0, 0), special_flags=getattr(pygame, blend_name)) self._assert_surface(dst, p, ", %s" % blend_name) def test_blit_blend_rgba(self): sources = [ self._make_src_surface(8), self._make_src_surface(16), self._make_src_surface(16, srcalpha=True), self._make_src_surface(24), self._make_src_surface(32), self._make_src_surface(32, srcalpha=True), ] destinations = [ self._make_surface(8), self._make_surface(16), self._make_surface(16, srcalpha=True), self._make_surface(24), self._make_surface(32), self._make_surface(32, srcalpha=True), ] blend = [ ("BLEND_RGBA_ADD", (0, 25, 100, 255), lambda a, b: min(a + b, 255)), ("BLEND_RGBA_SUB", (0, 25, 100, 255), lambda a, b: max(a - b, 0)), ("BLEND_RGBA_MULT", (0, 7, 100, 255), lambda a, b: (a * b) // 256), ("BLEND_RGBA_MIN", (0, 255, 0, 255), min), ("BLEND_RGBA_MAX", (0, 255, 0, 255), max), ] for src in sources: src_palette = [src.unmap_rgb(src.map_rgb(c)) for c in self._test_palette] for dst in destinations: for blend_name, dst_color, op in blend: dc = dst.unmap_rgb(dst.map_rgb(dst_color)) p = [] for sc in src_palette: c = [op(dc[i], sc[i]) for i in range(4)] if not dst.get_masks()[3]: c[3] = 255 c = dst.unmap_rgb(dst.map_rgb(c)) p.append(c) dst.fill(dst_color) dst.blit(src, (0, 0), special_flags=getattr(pygame, blend_name)) self._assert_surface( dst, p, ( ", op: %s, src bpp: %i" ", src flags: %i" % (blend_name, src.get_bitsize(), src.get_flags()) ), ) # Blend blits are special cased for 32 to 32 bit surfaces # with per-pixel alpha. # # Confirm the general case is used instead when the formats differ. src = self._make_src_surface(32, srcalpha=True) masks = src.get_masks() dst = pygame.Surface( src.get_size(), SRCALPHA, 32, (masks[2], masks[1], masks[0], masks[3]) ) for blend_name, dst_color, op in blend: p = [ tuple([op(dst_color[i], src_color[i]) for i in range(4)]) for src_color in self._test_palette ] dst.fill(dst_color) dst.blit(src, (0, 0), special_flags=getattr(pygame, blend_name)) self._assert_surface(dst, p, ", %s" % blend_name) # Confirm this special case handles subsurfaces. src = pygame.Surface((8, 10), SRCALPHA, 32) dst = pygame.Surface((8, 10), SRCALPHA, 32) tst = pygame.Surface((8, 10), SRCALPHA, 32) src.fill((1, 2, 3, 4)) dst.fill((40, 30, 20, 10)) subsrc = src.subsurface((2, 3, 4, 4)) subdst = dst.subsurface((2, 3, 4, 4)) subdst.blit(subsrc, (0, 0), special_flags=BLEND_RGBA_ADD) tst.fill((40, 30, 20, 10)) tst.fill((41, 32, 23, 14), (2, 3, 4, 4)) for x in range(8): for y in range(10): self.assertEqual( dst.get_at((x, y)), tst.get_at((x, y)), "%s != %s at (%i, %i)" % (dst.get_at((x, y)), tst.get_at((x, y)), x, y), ) def test_blit_blend_premultiplied(self): def test_premul_surf( src_col, dst_col, src_size=(16, 16), dst_size=(16, 16), src_bit_depth=32, dst_bit_depth=32, src_has_alpha=True, dst_has_alpha=True, ): if src_bit_depth == 8: src = pygame.Surface(src_size, 0, src_bit_depth) palette = [src_col, dst_col] src.set_palette(palette) src.fill(palette[0]) elif src_has_alpha: src = pygame.Surface(src_size, SRCALPHA, src_bit_depth) src.fill(src_col) else: src = pygame.Surface(src_size, 0, src_bit_depth) src.fill(src_col) if dst_bit_depth == 8: dst = pygame.Surface(dst_size, 0, dst_bit_depth) palette = [src_col, dst_col] dst.set_palette(palette) dst.fill(palette[1]) elif dst_has_alpha: dst = pygame.Surface(dst_size, SRCALPHA, dst_bit_depth) dst.fill(dst_col) else: dst = pygame.Surface(dst_size, 0, dst_bit_depth) dst.fill(dst_col) dst.blit(src, (0, 0), special_flags=BLEND_PREMULTIPLIED) actual_col = dst.get_at( (int(float(src_size[0] / 2.0)), int(float(src_size[0] / 2.0))) ) # This is the blend pre-multiplied formula if src_col.a == 0: expected_col = dst_col elif src_col.a == 255: expected_col = src_col else: # sC + dC - (((dC + 1) * sA >> 8) expected_col = pygame.Color( (src_col.r + dst_col.r - ((dst_col.r + 1) * src_col.a >> 8)), (src_col.g + dst_col.g - ((dst_col.g + 1) * src_col.a >> 8)), (src_col.b + dst_col.b - ((dst_col.b + 1) * src_col.a >> 8)), (src_col.a + dst_col.a - ((dst_col.a + 1) * src_col.a >> 8)), ) if not dst_has_alpha: expected_col.a = 255 return (expected_col, actual_col) # # Colour Tests self.assertEqual( *test_premul_surf(pygame.Color(40, 20, 0, 51), pygame.Color(40, 20, 0, 51)) ) self.assertEqual( *test_premul_surf(pygame.Color(0, 0, 0, 0), pygame.Color(40, 20, 0, 51)) ) self.assertEqual( *test_premul_surf(pygame.Color(40, 20, 0, 51), pygame.Color(0, 0, 0, 0)) ) self.assertEqual( *test_premul_surf(pygame.Color(0, 0, 0, 0), pygame.Color(0, 0, 0, 0)) ) self.assertEqual( *test_premul_surf(pygame.Color(2, 2, 2, 2), pygame.Color(40, 20, 0, 51)) ) self.assertEqual( *test_premul_surf(pygame.Color(40, 20, 0, 51), pygame.Color(2, 2, 2, 2)) ) self.assertEqual( *test_premul_surf(pygame.Color(2, 2, 2, 2), pygame.Color(2, 2, 2, 2)) ) self.assertEqual( *test_premul_surf(pygame.Color(9, 9, 9, 9), pygame.Color(40, 20, 0, 51)) ) self.assertEqual( *test_premul_surf(pygame.Color(40, 20, 0, 51), pygame.Color(9, 9, 9, 9)) ) self.assertEqual( *test_premul_surf(pygame.Color(9, 9, 9, 9), pygame.Color(9, 9, 9, 9)) ) self.assertEqual( *test_premul_surf( pygame.Color(127, 127, 127, 127), pygame.Color(40, 20, 0, 51) ) ) self.assertEqual( *test_premul_surf( pygame.Color(40, 20, 0, 51), pygame.Color(127, 127, 127, 127) ) ) self.assertEqual( *test_premul_surf( pygame.Color(127, 127, 127, 127), pygame.Color(127, 127, 127, 127) ) ) self.assertEqual( *test_premul_surf( pygame.Color(200, 200, 200, 200), pygame.Color(40, 20, 0, 51) ) ) self.assertEqual( *test_premul_surf( pygame.Color(40, 20, 0, 51), pygame.Color(200, 200, 200, 200) ) ) self.assertEqual( *test_premul_surf( pygame.Color(200, 200, 200, 200), pygame.Color(200, 200, 200, 200) ) ) self.assertEqual( *test_premul_surf( pygame.Color(255, 255, 255, 255), pygame.Color(40, 20, 0, 51) ) ) self.assertEqual( *test_premul_surf( pygame.Color(40, 20, 0, 51), pygame.Color(255, 255, 255, 255) ) ) self.assertEqual( *test_premul_surf( pygame.Color(255, 255, 255, 255), pygame.Color(255, 255, 255, 255) ) ) # Surface format tests self.assertRaises( IndexError, test_premul_surf, pygame.Color(255, 255, 255, 255), pygame.Color(255, 255, 255, 255), src_size=(0, 0), dst_size=(0, 0), ) self.assertEqual( *test_premul_surf( pygame.Color(40, 20, 0, 51), pygame.Color(30, 20, 0, 51), src_size=(4, 4), dst_size=(9, 9), ) ) self.assertEqual( *test_premul_surf( pygame.Color(30, 20, 0, 51), pygame.Color(40, 20, 0, 51), src_size=(17, 67), dst_size=(69, 69), ) ) self.assertEqual( *test_premul_surf( pygame.Color(30, 20, 0, 255), pygame.Color(40, 20, 0, 51), src_size=(17, 67), dst_size=(69, 69), src_has_alpha=True, ) ) self.assertEqual( *test_premul_surf( pygame.Color(30, 20, 0, 51), pygame.Color(40, 20, 0, 255), src_size=(17, 67), dst_size=(69, 69), dst_has_alpha=False, ) ) self.assertEqual( *test_premul_surf( pygame.Color(30, 20, 0, 255), pygame.Color(40, 20, 0, 255), src_size=(17, 67), dst_size=(69, 69), src_has_alpha=False, dst_has_alpha=False, ) ) self.assertEqual( *test_premul_surf( pygame.Color(30, 20, 0, 255), pygame.Color(40, 20, 0, 255), src_size=(17, 67), dst_size=(69, 69), dst_bit_depth=24, src_has_alpha=True, dst_has_alpha=False, ) ) self.assertEqual( *test_premul_surf( pygame.Color(30, 20, 0, 255), pygame.Color(40, 20, 0, 255), src_size=(17, 67), dst_size=(69, 69), src_bit_depth=24, src_has_alpha=False, dst_has_alpha=True, ) ) self.assertEqual( *test_premul_surf( pygame.Color(30, 20, 0, 255), pygame.Color(40, 20, 0, 255), src_size=(17, 67), dst_size=(69, 69), src_bit_depth=24, dst_bit_depth=24, src_has_alpha=False, dst_has_alpha=False, ) ) self.assertEqual( *test_premul_surf( pygame.Color(30, 20, 0, 255), pygame.Color(40, 20, 0, 255), src_size=(17, 67), dst_size=(69, 69), src_bit_depth=8, ) ) self.assertEqual( *test_premul_surf( pygame.Color(30, 20, 0, 255), pygame.Color(40, 20, 0, 255), src_size=(17, 67), dst_size=(69, 69), dst_bit_depth=8, ) ) self.assertEqual( *test_premul_surf( pygame.Color(30, 20, 0, 255), pygame.Color(40, 20, 0, 255), src_size=(17, 67), dst_size=(69, 69), src_bit_depth=8, dst_bit_depth=8, ) ) def test_blit_blend_big_rect(self): """test that an oversized rect works ok.""" color = (1, 2, 3, 255) area = (1, 1, 30, 30) s1 = pygame.Surface((4, 4), 0, 32) r = s1.fill(special_flags=pygame.BLEND_ADD, color=color, rect=area) self.assertEqual(pygame.Rect((1, 1, 3, 3)), r) self.assertEqual(s1.get_at((0, 0)), (0, 0, 0, 255)) self.assertEqual(s1.get_at((1, 1)), color) black = pygame.Color("black") red = pygame.Color("red") self.assertNotEqual(black, red) surf = pygame.Surface((10, 10), 0, 32) surf.fill(black) subsurf = surf.subsurface(pygame.Rect(0, 1, 10, 8)) self.assertEqual(surf.get_at((0, 0)), black) self.assertEqual(surf.get_at((0, 9)), black) subsurf.fill(red, (0, -1, 10, 1), pygame.BLEND_RGB_ADD) self.assertEqual(surf.get_at((0, 0)), black) self.assertEqual(surf.get_at((0, 9)), black) subsurf.fill(red, (0, 8, 10, 1), pygame.BLEND_RGB_ADD) self.assertEqual(surf.get_at((0, 0)), black) self.assertEqual(surf.get_at((0, 9)), black) def test_GET_PIXELVALS(self): # surface.h GET_PIXELVALS bug regarding whether of not # a surface has per-pixel alpha. Looking at the Amask # is not enough. The surface's SRCALPHA flag must also # be considered. Fix rev. 1923. src = self._make_surface(32, srcalpha=True) src.fill((0, 0, 0, 128)) src.set_alpha(None) # Clear SRCALPHA flag. dst = self._make_surface(32, srcalpha=True) dst.blit(src, (0, 0), special_flags=BLEND_RGBA_ADD) self.assertEqual(dst.get_at((0, 0)), (0, 0, 0, 255)) def test_fill_blend(self): destinations = [ self._make_surface(8), self._make_surface(16), self._make_surface(16, srcalpha=True), self._make_surface(24), self._make_surface(32), self._make_surface(32, srcalpha=True), ] blend = [ ("BLEND_ADD", (0, 25, 100, 255), lambda a, b: min(a + b, 255)), ("BLEND_SUB", (0, 25, 100, 255), lambda a, b: max(a - b, 0)), ("BLEND_MULT", (0, 7, 100, 255), lambda a, b: (a * b) // 256), ("BLEND_MIN", (0, 255, 0, 255), min), ("BLEND_MAX", (0, 255, 0, 255), max), ] for dst in destinations: dst_palette = [dst.unmap_rgb(dst.map_rgb(c)) for c in self._test_palette] for blend_name, fill_color, op in blend: fc = dst.unmap_rgb(dst.map_rgb(fill_color)) self._fill_surface(dst) p = [] for dc in dst_palette: c = [op(dc[i], fc[i]) for i in range(3)] if dst.get_masks()[3]: c.append(dc[3]) else: c.append(255) c = dst.unmap_rgb(dst.map_rgb(c)) p.append(c) dst.fill(fill_color, special_flags=getattr(pygame, blend_name)) self._assert_surface(dst, p, ", %s" % blend_name) def test_fill_blend_rgba(self): destinations = [ self._make_surface(8), self._make_surface(16), self._make_surface(16, srcalpha=True), self._make_surface(24), self._make_surface(32), self._make_surface(32, srcalpha=True), ] blend = [ ("BLEND_RGBA_ADD", (0, 25, 100, 255), lambda a, b: min(a + b, 255)), ("BLEND_RGBA_SUB", (0, 25, 100, 255), lambda a, b: max(a - b, 0)), ("BLEND_RGBA_MULT", (0, 7, 100, 255), lambda a, b: (a * b) // 256), ("BLEND_RGBA_MIN", (0, 255, 0, 255), min), ("BLEND_RGBA_MAX", (0, 255, 0, 255), max), ] for dst in destinations: dst_palette = [dst.unmap_rgb(dst.map_rgb(c)) for c in self._test_palette] for blend_name, fill_color, op in blend: fc = dst.unmap_rgb(dst.map_rgb(fill_color)) self._fill_surface(dst) p = [] for dc in dst_palette: c = [op(dc[i], fc[i]) for i in range(4)] if not dst.get_masks()[3]: c[3] = 255 c = dst.unmap_rgb(dst.map_rgb(c)) p.append(c) dst.fill(fill_color, special_flags=getattr(pygame, blend_name)) self._assert_surface(dst, p, ", %s" % blend_name) class SurfaceSelfBlitTest(unittest.TestCase): """Blit to self tests. This test case is in response to MotherHamster Bugzilla Bug 19. """ def setUp(self): # Needed for 8 bits-per-pixel color palette surface tests. pygame.display.init() def tearDown(self): pygame.display.quit() _test_palette = [(0, 0, 0, 255), (255, 0, 0, 0), (0, 255, 0, 255)] surf_size = (9, 6) def _fill_surface(self, surf, palette=None): if palette is None: palette = self._test_palette surf.fill(palette[1]) surf.fill(palette[2], (1, 2, 1, 2)) def _make_surface(self, bitsize, srcalpha=False, palette=None): if palette is None: palette = self._test_palette flags = 0 if srcalpha: flags |= SRCALPHA surf = pygame.Surface(self.surf_size, flags, bitsize) if bitsize == 8: surf.set_palette([c[:3] for c in palette]) self._fill_surface(surf, palette) return surf def _assert_same(self, a, b): w, h = a.get_size() for x in range(w): for y in range(h): self.assertEqual( a.get_at((x, y)), b.get_at((x, y)), ( "%s != %s, bpp: %i" % (a.get_at((x, y)), b.get_at((x, y)), a.get_bitsize()) ), ) def test_overlap_check(self): # Ensure overlapping blits are properly detected. There are two # places where this is done, within SoftBlitPyGame() in alphablit.c # and PySurface_Blit() in surface.c. SoftBlitPyGame should catch the # per-pixel alpha surface, PySurface_Blit the colorkey and blanket # alpha surface. per-pixel alpha and blanket alpha self blits are # not properly handled by SDL 1.2.13, so Pygame does them. bgc = (0, 0, 0, 255) rectc_left = (128, 64, 32, 255) rectc_right = (255, 255, 255, 255) colors = [(255, 255, 255, 255), (128, 64, 32, 255)] overlaps = [ (0, 0, 1, 0, (50, 0)), (0, 0, 49, 1, (98, 2)), (0, 0, 49, 49, (98, 98)), (49, 0, 0, 1, (0, 2)), (49, 0, 0, 49, (0, 98)), ] surfs = [pygame.Surface((100, 100), SRCALPHA, 32)] surf = pygame.Surface((100, 100), 0, 32) surf.set_alpha(255) surfs.append(surf) surf = pygame.Surface((100, 100), 0, 32) surf.set_colorkey((0, 1, 0)) surfs.append(surf) for surf in surfs: for s_x, s_y, d_x, d_y, test_posn in overlaps: surf.fill(bgc) surf.fill(rectc_right, (25, 0, 25, 50)) surf.fill(rectc_left, (0, 0, 25, 50)) surf.blit(surf, (d_x, d_y), (s_x, s_y, 50, 50)) self.assertEqual(surf.get_at(test_posn), rectc_right) # https://github.com/pygame/pygame/issues/370#issuecomment-364625291 @unittest.skipIf("ppc64le" in platform.uname(), "known ppc64le issue") def test_colorkey(self): # Check a workaround for an SDL 1.2.13 surface self-blit problem # (MotherHamster Bugzilla bug 19). pygame.display.set_mode((100, 50)) # Needed for 8bit surface bitsizes = [8, 16, 24, 32] for bitsize in bitsizes: surf = self._make_surface(bitsize) surf.set_colorkey(self._test_palette[1]) surf.blit(surf, (3, 0)) p = [] for c in self._test_palette: c = surf.unmap_rgb(surf.map_rgb(c)) p.append(c) p[1] = (p[1][0], p[1][1], p[1][2], 0) tmp = self._make_surface(32, srcalpha=True, palette=p) tmp.blit(tmp, (3, 0)) tmp.set_alpha(None) comp = self._make_surface(bitsize) comp.blit(tmp, (0, 0)) self._assert_same(surf, comp) # https://github.com/pygame/pygame/issues/370#issuecomment-364625291 @unittest.skipIf("ppc64le" in platform.uname(), "known ppc64le issue") def test_blanket_alpha(self): # Check a workaround for an SDL 1.2.13 surface self-blit problem # (MotherHamster Bugzilla bug 19). pygame.display.set_mode((100, 50)) # Needed for 8bit surface bitsizes = [8, 16, 24, 32] for bitsize in bitsizes: surf = self._make_surface(bitsize) surf.set_alpha(128) surf.blit(surf, (3, 0)) p = [] for c in self._test_palette: c = surf.unmap_rgb(surf.map_rgb(c)) p.append((c[0], c[1], c[2], 128)) tmp = self._make_surface(32, srcalpha=True, palette=p) tmp.blit(tmp, (3, 0)) tmp.set_alpha(None) comp = self._make_surface(bitsize) comp.blit(tmp, (0, 0)) self._assert_same(surf, comp) def test_pixel_alpha(self): bitsizes = [16, 32] for bitsize in bitsizes: surf = self._make_surface(bitsize, srcalpha=True) comp = self._make_surface(bitsize, srcalpha=True) comp.blit(surf, (3, 0)) surf.blit(surf, (3, 0)) self._assert_same(surf, comp) def test_blend(self): bitsizes = [8, 16, 24, 32] blends = ["BLEND_ADD", "BLEND_SUB", "BLEND_MULT", "BLEND_MIN", "BLEND_MAX"] for bitsize in bitsizes: surf = self._make_surface(bitsize) comp = self._make_surface(bitsize) for blend in blends: self._fill_surface(surf) self._fill_surface(comp) comp.blit(surf, (3, 0), special_flags=getattr(pygame, blend)) surf.blit(surf, (3, 0), special_flags=getattr(pygame, blend)) self._assert_same(surf, comp) def test_blend_rgba(self): bitsizes = [16, 32] blends = [ "BLEND_RGBA_ADD", "BLEND_RGBA_SUB", "BLEND_RGBA_MULT", "BLEND_RGBA_MIN", "BLEND_RGBA_MAX", ] for bitsize in bitsizes: surf = self._make_surface(bitsize, srcalpha=True) comp = self._make_surface(bitsize, srcalpha=True) for blend in blends: self._fill_surface(surf) self._fill_surface(comp) comp.blit(surf, (3, 0), special_flags=getattr(pygame, blend)) surf.blit(surf, (3, 0), special_flags=getattr(pygame, blend)) self._assert_same(surf, comp) def test_subsurface(self): # Blitting a surface to its subsurface is allowed. surf = self._make_surface(32, srcalpha=True) comp = surf.copy() comp.blit(surf, (3, 0)) sub = surf.subsurface((3, 0, 6, 6)) sub.blit(surf, (0, 0)) del sub self._assert_same(surf, comp) # Blitting a subsurface to its owner is forbidden because of # lock conficts. This limitation allows the overlap check # in PySurface_Blit of alphablit.c to be simplified. def do_blit(d, s): d.blit(s, (0, 0)) sub = surf.subsurface((1, 1, 2, 2)) self.assertRaises(pygame.error, do_blit, surf, sub) def test_copy_alpha(self): """issue 581: alpha of surface copy with SRCALPHA is set to 0.""" surf = pygame.Surface((16, 16), pygame.SRCALPHA, 32) self.assertEqual(surf.get_alpha(), 255) surf2 = surf.copy() self.assertEqual(surf2.get_alpha(), 255) class SurfaceFillTest(unittest.TestCase): def setUp(self): pygame.display.init() def tearDown(self): pygame.display.quit() def test_fill(self): screen = pygame.display.set_mode((640, 480)) # Green and blue test pattern screen.fill((0, 255, 0), (0, 0, 320, 240)) screen.fill((0, 255, 0), (320, 240, 320, 240)) screen.fill((0, 0, 255), (320, 0, 320, 240)) screen.fill((0, 0, 255), (0, 240, 320, 240)) # Now apply a clip rect, such that only the left side of the # screen should be effected by blit operations. screen.set_clip((0, 0, 320, 480)) # Test fills with each special flag, and additionally without any. screen.fill((255, 0, 0, 127), (160, 0, 320, 30), 0) screen.fill((255, 0, 0, 127), (160, 30, 320, 30), pygame.BLEND_ADD) screen.fill((0, 127, 127, 127), (160, 60, 320, 30), pygame.BLEND_SUB) screen.fill((0, 63, 63, 127), (160, 90, 320, 30), pygame.BLEND_MULT) screen.fill((0, 127, 127, 127), (160, 120, 320, 30), pygame.BLEND_MIN) screen.fill((127, 0, 0, 127), (160, 150, 320, 30), pygame.BLEND_MAX) screen.fill((255, 0, 0, 127), (160, 180, 320, 30), pygame.BLEND_RGBA_ADD) screen.fill((0, 127, 127, 127), (160, 210, 320, 30), pygame.BLEND_RGBA_SUB) screen.fill((0, 63, 63, 127), (160, 240, 320, 30), pygame.BLEND_RGBA_MULT) screen.fill((0, 127, 127, 127), (160, 270, 320, 30), pygame.BLEND_RGBA_MIN) screen.fill((127, 0, 0, 127), (160, 300, 320, 30), pygame.BLEND_RGBA_MAX) screen.fill((255, 0, 0, 127), (160, 330, 320, 30), pygame.BLEND_RGB_ADD) screen.fill((0, 127, 127, 127), (160, 360, 320, 30), pygame.BLEND_RGB_SUB) screen.fill((0, 63, 63, 127), (160, 390, 320, 30), pygame.BLEND_RGB_MULT) screen.fill((0, 127, 127, 127), (160, 420, 320, 30), pygame.BLEND_RGB_MIN) screen.fill((255, 0, 0, 127), (160, 450, 320, 30), pygame.BLEND_RGB_MAX) # Update the display so we can see the results pygame.display.flip() # Compare colors on both sides of window for y in range(5, 480, 10): self.assertEqual(screen.get_at((10, y)), screen.get_at((330, 480 - y))) if __name__ == "__main__": unittest.main()