forked from s444420/AL-2020
2539 lines
98 KiB
Python
2539 lines
98 KiB
Python
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()
|
|
|
|
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, 0, 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), '<Surface(70x70x32 SW)>')
|
|
|
|
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_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_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_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."""
|
|
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)
|
|
|
|
########################################################################
|
|
|
|
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)
|
|
|
|
########################################################################
|
|
|
|
def test_get_parent(self):
|
|
"""Ensure a surface's parent can be retrieved."""
|
|
parent = pygame.Surface((16, 16))
|
|
child = parent.subsurface((0,0,5,5))
|
|
|
|
self.assertIs(child.get_parent(), parent)
|
|
|
|
########################################################################
|
|
|
|
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), "<BufferProxy(" + str(length) + ")>")
|
|
|
|
# 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()
|
|
s.set_masks((b,g,r,a))
|
|
r2,g2,b2,a2 = s.get_masks()
|
|
self.assertEqual((r,g,b,a), (b2,g2,r2,a2))
|
|
|
|
|
|
def test_set_shifts(self):
|
|
s = pygame.Surface((32,32))
|
|
r,g,b,a = s.get_shifts()
|
|
s.set_shifts((b,g,r,a))
|
|
r2,g2,b2,a2 = s.get_shifts()
|
|
self.assertEqual((r,g,b,a), (b2,g2,r2,a2))
|
|
|
|
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)
|
|
|
|
def todo_test_blit(self):
|
|
# __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.
|
|
|
|
self.fail()
|
|
|
|
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 todo_test_blit__blit_to_self(self): #TODO
|
|
src = pygame.Surface( (256,256), SRCALPHA, 32)
|
|
rect = src.get_rect()
|
|
|
|
for pt, color in test_utils.gradient(rect.width, rect.height):
|
|
src.set_at(pt, color)
|
|
|
|
src.blit(src, (0, 0))
|
|
|
|
def todo_test_blit__SRCALPHA_to_SRCALPHA_non_zero(self): #TODO
|
|
# " There is no unit test for blitting a SRCALPHA source with non-zero
|
|
# alpha to a SRCALPHA destination with non-zero alpha " LL
|
|
|
|
w,h = size = 32,32
|
|
|
|
s = pygame.Surface(size, pygame.SRCALPHA, 32)
|
|
s2 = s.copy()
|
|
|
|
s.fill((32,32,32,111))
|
|
s2.fill((32,32,32,31))
|
|
|
|
s.blit(s2, (0,0))
|
|
|
|
# TODO:
|
|
# what is the correct behaviour ?? should it blend? what algorithm?
|
|
|
|
self.assertEqual(s.get_at((0,0)), (32,32,32,31))
|
|
|
|
def test_blit__SRCALPHA32_to_8(self):
|
|
# Bug: fatal
|
|
# SDL_DisplayConvert segfaults when video is uninitialized.
|
|
target = pygame.Surface((11, 8), 0, 8)
|
|
color = target.get_palette_at(2)
|
|
source = pygame.Surface((1, 1), pygame.SRCALPHA, 32)
|
|
source.set_at((0, 0), color)
|
|
target.blit(source, (0, 0))
|
|
|
|
@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)), '<Surface(24x24x32 SW)>')
|
|
self.assertEqual(repr(im2.convert(32)), '<Surface(469x137x32 SW)>')
|
|
|
|
# Ensure a palette format to palette format works.
|
|
im3 = im.convert(8)
|
|
self.assertEqual(repr(im3), '<Surface(24x24x8 SW)>')
|
|
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 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 todo_test_convert_alpha(self):
|
|
|
|
# __doc__ (as of 2008-08-02) for pygame.surface.Surface.convert_alpha:
|
|
|
|
# Surface.convert_alpha(Surface): return Surface
|
|
# Surface.convert_alpha(): return Surface
|
|
# change the pixel format of an image including per pixel alphas
|
|
#
|
|
# Creates a new copy of the surface with the desired pixel format. The
|
|
# new surface will be in a format suited for quick blitting to the
|
|
# given format with per pixel alpha. If no surface is given, the new
|
|
# surface will be optimized for blitting to the current display.
|
|
#
|
|
# Unlike the Surface.convert() method, the pixel format for the new
|
|
# image will not be exactly the same as the requested source, but it
|
|
# will be optimized for fast alpha blitting to the destination.
|
|
#
|
|
|
|
self.fail()
|
|
|
|
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 todo_test_get_abs_offset(self):
|
|
|
|
# __doc__ (as of 2008-08-02) for pygame.surface.Surface.get_abs_offset:
|
|
|
|
# Surface.get_abs_offset(): return (x, y)
|
|
# find the absolute position of a child subsurface inside its top level parent
|
|
#
|
|
# Get the offset position of a child subsurface inside of its top
|
|
# level parent Surface. If the Surface is not a subsurface this will
|
|
# return (0, 0).
|
|
#
|
|
|
|
self.fail()
|
|
|
|
def todo_test_get_abs_parent(self):
|
|
|
|
# __doc__ (as of 2008-08-02) for pygame.surface.Surface.get_abs_parent:
|
|
|
|
# Surface.get_abs_parent(): return Surface
|
|
# find the top level parent of a subsurface
|
|
#
|
|
# Returns the parent Surface of a subsurface. If this is not a
|
|
# subsurface then this surface will be returned.
|
|
#
|
|
|
|
self.fail()
|
|
|
|
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 todo_test_get_bitsize(self):
|
|
|
|
# __doc__ (as of 2008-08-02) for pygame.surface.Surface.get_bitsize:
|
|
|
|
# Surface.get_bitsize(): return int
|
|
# get the bit depth of the Surface pixel format
|
|
#
|
|
# Returns the number of bits used to represent each pixel. This value
|
|
# may not exactly fill the number of bytes used per pixel. For example
|
|
# a 15 bit Surface still requires a full 2 bytes.
|
|
#
|
|
|
|
self.fail()
|
|
|
|
def todo_test_get_clip(self):
|
|
|
|
# __doc__ (as of 2008-08-02) for pygame.surface.Surface.get_clip:
|
|
|
|
# Surface.get_clip(): return Rect
|
|
# get the current clipping area of the Surface
|
|
#
|
|
# Return a rectangle of the current clipping area. The Surface will
|
|
# always return a valid rectangle that will never be outside the
|
|
# bounds of the image. If the Surface has had None set for the
|
|
# clipping area, the Surface will return a rectangle with the full
|
|
# area of the Surface.
|
|
#
|
|
|
|
self.fail()
|
|
|
|
def todo_test_get_colorkey(self):
|
|
surf = pygame.surface((2, 2), 0, 24)
|
|
self.assertIsNone(surf.get_colorykey())
|
|
colorkey = pygame.Color(20, 40, 60)
|
|
surf.set_colorkey(colorkey)
|
|
ck = surf.get_colorkey()
|
|
self.assertIsInstance(ck, pygame.Color)
|
|
self.assertEqual(ck, colorkey)
|
|
|
|
def todo_test_get_height(self):
|
|
|
|
# __doc__ (as of 2008-08-02) for pygame.surface.Surface.get_height:
|
|
|
|
# Surface.get_height(): return height
|
|
# get the height of the Surface
|
|
#
|
|
# Return the height of the Surface in pixels.
|
|
|
|
self.fail()
|
|
|
|
def todo_test_get_locked(self):
|
|
|
|
# __doc__ (as of 2008-08-02) for pygame.surface.Surface.get_locked:
|
|
|
|
# Surface.get_locked(): return bool
|
|
# test if the Surface is current locked
|
|
#
|
|
# Returns True when the Surface is locked. It doesn't matter how many
|
|
# times the Surface is locked.
|
|
#
|
|
|
|
self.fail()
|
|
|
|
def todo_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.
|
|
|
|
self.fail()
|
|
|
|
def todo_test_get_losses(self):
|
|
|
|
# __doc__ (as of 2008-08-02) for pygame.surface.Surface.get_losses:
|
|
|
|
# Surface.get_losses(): return (R, G, B, A)
|
|
# the significant bits used to convert between a color and a mapped integer
|
|
#
|
|
# Return the least significant number of bits stripped from each color
|
|
# in a mapped integer.
|
|
#
|
|
# This value is not needed for normal Pygame usage.
|
|
|
|
self.fail()
|
|
|
|
def todo_test_get_masks(self):
|
|
|
|
# __doc__ (as of 2008-08-02) for pygame.surface.Surface.get_masks:
|
|
|
|
# Surface.get_masks(): return (R, G, B, A)
|
|
# the bitmasks needed to convert between a color and a mapped integer
|
|
#
|
|
# Returns the bitmasks used to isolate each color in a mapped integer.
|
|
# This value is not needed for normal Pygame usage.
|
|
|
|
self.fail()
|
|
|
|
def todo_test_get_offset(self):
|
|
|
|
# __doc__ (as of 2008-08-02) for pygame.surface.Surface.get_offset:
|
|
|
|
# Surface.get_offset(): return (x, y)
|
|
# find the position of a child subsurface inside a parent
|
|
#
|
|
# Get the offset position of a child subsurface inside of a parent. If
|
|
# the Surface is not a subsurface this will return (0, 0).
|
|
#
|
|
|
|
self.fail()
|
|
|
|
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 todo_test_get_pitch(self):
|
|
|
|
# __doc__ (as of 2008-08-02) for pygame.surface.Surface.get_pitch:
|
|
|
|
# Surface.get_pitch(): return int
|
|
# get the number of bytes used per Surface row
|
|
#
|
|
# Return the number of bytes separating each row in the Surface.
|
|
# Surfaces in video memory are not always linearly packed. Subsurfaces
|
|
# will also have a larger pitch than their real width.
|
|
#
|
|
# This value is not needed for normal Pygame usage.
|
|
|
|
self.fail()
|
|
|
|
def todo_test_get_shifts(self):
|
|
|
|
# __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.
|
|
|
|
self.fail()
|
|
|
|
def todo_test_get_size(self):
|
|
|
|
# __doc__ (as of 2008-08-02) for pygame.surface.Surface.get_size:
|
|
|
|
# Surface.get_size(): return (width, height)
|
|
# get the dimensions of the Surface
|
|
#
|
|
# Return the width and height of the Surface in pixels.
|
|
|
|
self.fail()
|
|
|
|
def todo_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.
|
|
#
|
|
|
|
self.fail()
|
|
|
|
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 todo_test_mustlock(self):
|
|
|
|
# __doc__ (as of 2008-08-02) for pygame.surface.Surface.mustlock:
|
|
|
|
# Surface.mustlock(): return bool
|
|
# test if the Surface requires locking
|
|
#
|
|
# Returns True if the Surface is required to be locked to access pixel
|
|
# data. Usually pure software Surfaces do not require locking. This
|
|
# method is rarely needed, since it is safe and quickest to just lock
|
|
# all Surfaces as needed.
|
|
#
|
|
# 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.
|
|
#
|
|
|
|
self.fail()
|
|
|
|
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 todo_test_unlock(self):
|
|
|
|
# __doc__ (as of 2008-08-02) for pygame.surface.Surface.unlock:
|
|
|
|
# Surface.unlock(): return None
|
|
# unlock the Surface memory from pixel access
|
|
#
|
|
# Unlock the Surface pixel data after it has been locked. The unlocked
|
|
# Surface can once again be drawn and managed by Pygame. See the
|
|
# Surface.lock() documentation for more details.
|
|
#
|
|
# 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.
|
|
#
|
|
|
|
self.fail()
|
|
|
|
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):
|
|
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_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 opperations.
|
|
screen.set_clip((0, 0, 320, 480))
|
|
|
|
# Test fills with each special flag, and additionaly 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()
|