AL-2020/venv/Lib/site-packages/pygame/tests/font_test.py

547 lines
19 KiB
Python

# -*- coding: utf8 -*-
import sys
import os
import unittest
import platform
import pygame
from pygame import font as pygame_font # So font can be replaced with ftfont
from pygame.compat import as_unicode, unicode_, as_bytes, xrange_, filesystem_errors
from pygame.compat import PY_MAJOR_VERSION
FONTDIR = os.path.join(os.path.dirname (os.path.abspath (__file__)),
'fixtures', 'fonts')
UCS_4 = sys.maxunicode > 0xFFFF
def equal_images(s1, s2):
size = s1.get_size()
if s2.get_size() != size:
return False
w, h = size
for x in xrange_(w):
for y in xrange_(h):
if s1.get_at((x, y)) != s2.get_at((x, y)):
return False
return True
IS_PYPY = 'PyPy' == platform.python_implementation()
@unittest.skipIf(IS_PYPY, 'pypy skip known failure') # TODO
class FontModuleTest( unittest.TestCase ):
def setUp(self):
pygame_font.init()
def tearDown(self):
pygame_font.quit()
def test_SysFont(self):
# Can only check that a font object is returned.
fonts = pygame_font.get_fonts()
if 'arial' in fonts:
# Try to use arial font if it is there, rather than a random font
# which can be different depending on installed fonts on the system.
font_name = 'arial'
else:
font_name = sorted(fonts)[0]
o = pygame_font.SysFont(font_name, 20)
self.assertTrue(isinstance(o, pygame_font.FontType))
o = pygame_font.SysFont(font_name, 20, italic=True)
self.assertTrue(isinstance(o, pygame_font.FontType))
o = pygame_font.SysFont(font_name, 20, bold=True)
self.assertTrue(isinstance(o, pygame_font.FontType))
o = pygame_font.SysFont('thisisnotafont', 20)
self.assertTrue(isinstance(o, pygame_font.FontType))
def test_get_default_font(self):
self.assertEqual(pygame_font.get_default_font(), 'freesansbold.ttf')
def test_get_fonts_returns_something(self):
fnts = pygame_font.get_fonts()
self.assertTrue(fnts)
# to test if some files exist...
#def XXtest_has_file_osx_10_5_sdk(self):
# import os
# f = "/Developer/SDKs/MacOSX10.5.sdk/usr/X11/include/ft2build.h"
# self.assertEqual(os.path.exists(f), True)
#def XXtest_has_file_osx_10_4_sdk(self):
# import os
# f = "/Developer/SDKs/MacOSX10.4u.sdk/usr/X11R6/include/ft2build.h"
# self.assertEqual(os.path.exists(f), True)
def test_get_fonts(self):
fnts = pygame_font.get_fonts()
self.assertTrue(fnts, msg=repr(fnts))
if (PY_MAJOR_VERSION >= 3):
# For Python 3.x, names will always be unicode strings.
name_types = (str,)
else:
# For Python 2.x, names may be either unicode or ascii strings.
name_types = (str, unicode)
for name in fnts:
# note, on ubuntu 2.6 they are all unicode strings.
self.assertTrue(isinstance(name, name_types), name)
# Font names can be comprised of only numeric characters, so
# just checking name.islower() will not work as expected here.
self.assertFalse(any(c.isupper() for c in name))
self.assertTrue(name.isalnum(), name)
def test_get_init(self):
self.assertTrue(pygame_font.get_init())
pygame_font.quit()
self.assertFalse(pygame_font.get_init())
def test_init(self):
pygame_font.init()
def test_match_font_all_exist(self):
fonts = pygame_font.get_fonts()
# Ensure all listed fonts are in fact available, and the returned file
# name is a full path.
for font in fonts:
path = pygame_font.match_font(font)
self.assertFalse(path is None)
self.assertTrue(os.path.isabs(path))
def test_match_font_bold(self):
fonts = pygame_font.get_fonts()
# Look for a bold font.
self.assertTrue(any(pygame_font.match_font(font, bold=True)
for font in fonts))
def test_match_font_italic(self):
fonts = pygame_font.get_fonts()
# Look for an italic font.
self.assertTrue(any(pygame_font.match_font(font, italic=True)
for font in fonts))
def test_match_font_comma_separated(self):
fonts = pygame_font.get_fonts()
# Check for not found.
self.assertTrue(pygame_font.match_font('thisisnotafont') is None)
# Check comma separated list.
names = ','.join(['thisisnotafont', fonts[-1], 'anothernonfont'])
self.assertFalse(pygame_font.match_font(names) is None)
names = ','.join(['thisisnotafont1', 'thisisnotafont2', 'thisisnotafont3'])
self.assertTrue(pygame_font.match_font(names) is None)
def test_quit(self):
pygame_font.quit()
@unittest.skipIf(IS_PYPY, 'pypy skip known failure') # TODO
class FontTest(unittest.TestCase):
def setUp(self):
pygame_font.init()
def tearDown(self):
pygame_font.quit()
def test_render_args(self):
screen = pygame.display.set_mode((600, 400))
rect = screen.get_rect()
f = pygame_font.Font(None, 20)
screen.fill((10, 10, 10))
font_surface = f.render(" bar", True, (0, 0, 0), (255, 255, 255))
font_rect = font_surface.get_rect()
font_rect.topleft = rect.topleft
self.assertTrue(font_surface)
screen.blit(font_surface, font_rect, font_rect)
pygame.display.update()
self.assertEqual(tuple(screen.get_at((0,0)))[:3], (255, 255, 255))
self.assertEqual(tuple(screen.get_at(font_rect.topleft))[:3], (255, 255, 255))
# If we don't have a real display, don't do this test.
# Transparent background doesn't seem to work without a read video card.
if os.environ.get('SDL_VIDEODRIVER') != 'dummy':
screen.fill((10, 10, 10))
font_surface = f.render(" bar", True, (0, 0, 0), None)
font_rect = font_surface.get_rect()
font_rect.topleft = rect.topleft
self.assertTrue(font_surface)
screen.blit(font_surface, font_rect, font_rect)
pygame.display.update()
self.assertEqual(tuple(screen.get_at((0,0)))[:3], (10, 10, 10))
self.assertEqual(tuple(screen.get_at(font_rect.topleft))[:3], (10, 10, 10))
screen.fill((10, 10, 10))
font_surface = f.render(" bar", True, (0, 0, 0))
font_rect = font_surface.get_rect()
font_rect.topleft = rect.topleft
self.assertTrue(font_surface)
screen.blit(font_surface, font_rect, font_rect)
pygame.display.update(rect)
self.assertEqual(tuple(screen.get_at((0,0)))[:3], (10, 10, 10))
self.assertEqual(tuple(screen.get_at(font_rect.topleft))[:3], (10, 10, 10))
@unittest.skipIf(IS_PYPY, 'pypy skip known failure') # TODO
class FontTypeTest( unittest.TestCase ):
def setUp(self):
pygame_font.init()
def tearDown(self):
pygame_font.quit()
def test_get_ascent(self):
# Ckecking ascent would need a custom test font to do properly.
f = pygame_font.Font(None, 20)
ascent = f.get_ascent()
self.assertTrue(isinstance(ascent, int))
self.assertTrue(ascent > 0)
s = f.render("X", False, (255, 255, 255))
self.assertTrue(s.get_size()[1] > ascent)
def test_get_descent(self):
# Ckecking descent would need a custom test font to do properly.
f = pygame_font.Font(None, 20)
descent = f.get_descent()
self.assertTrue(isinstance(descent, int))
self.assertTrue(descent < 0)
def test_get_height(self):
# Ckecking height would need a custom test font to do properly.
f = pygame_font.Font(None, 20)
height = f.get_height()
self.assertTrue(isinstance(height, int))
self.assertTrue(height > 0)
s = f.render("X", False, (255, 255, 255))
self.assertTrue(s.get_size()[1] == height)
def test_get_linesize(self):
# Ckecking linesize would need a custom test font to do properly.
# Questions: How do linesize, height and descent relate?
f = pygame_font.Font(None, 20)
linesize = f.get_linesize()
self.assertTrue(isinstance(linesize, int))
self.assertTrue(linesize > 0)
def test_metrics(self):
# Ensure bytes decoding works correctly. Can only compare results
# with unicode for now.
f = pygame_font.Font(None, 20)
um = f.metrics(as_unicode("."))
bm = f.metrics(as_bytes("."))
self.assertEqual(len(um), 1)
self.assertEqual(len(bm), 1)
self.assertIsNotNone(um[0])
self.assertEqual(um, bm)
u = u"\u212A"
b = u.encode("UTF-16")[2:] # Keep byte order consistent. [2:] skips BOM
bm = f.metrics(b)
self.assertEqual(len(bm), 2)
try: # FIXME why do we do this try/except ?
um = f.metrics(u)
except pygame.error:
pass
else:
self.assertEqual(len(um), 1)
self.assertNotEqual(bm[0], um[0])
self.assertNotEqual(bm[1], um[0])
if UCS_4:
u = u"\U00013000"
bm = f.metrics(u)
self.assertEqual(len(bm), 1)
self.assertIsNone(bm[0])
return # unfinished
# The documentation is useless here. How large a list?
# How do list positions relate to character codes?
# What about unicode characters?
# __doc__ (as of 2008-08-02) for pygame_font.Font.metrics:
# Font.metrics(text): return list
# Gets the metrics for each character in the pased string.
#
# The list contains tuples for each character, which contain the
# minimum X offset, the maximum X offset, the minimum Y offset, the
# maximum Y offset and the advance offset (bearing plus width) of the
# character. [(minx, maxx, miny, maxy, advance), (minx, maxx, miny,
# maxy, advance), ...]
self.fail()
def test_render(self):
f = pygame_font.Font(None, 20)
s = f.render("foo", True, [0, 0, 0], [255, 255, 255])
s = f.render("xxx", True, [0, 0, 0], [255, 255, 255])
s = f.render("", True, [0, 0, 0], [255, 255, 255])
s = f.render("foo", False, [0, 0, 0], [255, 255, 255])
s = f.render("xxx", False, [0, 0, 0], [255, 255, 255])
s = f.render("xxx", False, [0, 0, 0])
s = f.render(" ", False, [0, 0, 0])
s = f.render(" ", False, [0, 0, 0], [255, 255, 255])
# null text should be 1 pixel wide.
s = f.render("", False, [0, 0, 0], [255, 255, 255])
self.assertEqual(s.get_size()[0], 1)
# None text should be 1 pixel wide.
s = f.render(None, False, [0, 0, 0], [255, 255, 255])
self.assertEqual(s.get_size()[0], 1)
# Non-text should raise a TypeError.
self.assertRaises(TypeError, f.render,
[], False, [0, 0, 0], [255, 255, 255])
self.assertRaises(TypeError, f.render,
1, False, [0, 0, 0], [255, 255, 255])
# is background transparent for antialiasing?
s = f.render(".", True, [255, 255, 255])
self.assertEqual(s.get_at((0, 0))[3], 0)
# is Unicode and bytes encoding correct?
# Cannot really test if the correct characters are rendered, but
# at least can assert the encodings differ.
su = f.render(as_unicode("."), False, [0, 0, 0], [255, 255, 255])
sb = f.render(as_bytes("."), False, [0, 0, 0], [255, 255, 255])
self.assertTrue(equal_images(su, sb))
u = as_unicode(r"\u212A")
b = u.encode("UTF-16")[2:] # Keep byte order consistent. [2:] skips BOM
sb = f.render(b, False, [0, 0, 0], [255, 255, 255])
try: # FIXME why do we do this try/except ?
su = f.render(u, False, [0, 0, 0], [255, 255, 255])
except pygame.error:
pass
else:
self.assertFalse(equal_images(su, sb))
# If the font module is SDL_ttf based, then it can only supports UCS-2;
# it will raise an exception for an out-of-range UCS-4 code point.
if UCS_4 and not hasattr(f, 'ucs4'):
ucs_2 = as_unicode(r"\uFFEE")
s = f.render(ucs_2, False, [0, 0, 0], [255, 255, 255])
ucs_4 = as_unicode(r"\U00010000")
self.assertRaises(UnicodeError, f.render,
ucs_4, False, [0, 0, 0], [255, 255, 255])
b = as_bytes("ab\x00cd")
self.assertRaises(ValueError, f.render, b, 0, [0, 0, 0])
u = as_unicode("ab\x00cd")
self.assertRaises(ValueError, f.render, b, 0, [0, 0, 0])
def test_set_bold(self):
f = pygame_font.Font(None, 20)
self.assertFalse(f.get_bold())
f.set_bold(True)
self.assertTrue(f.get_bold())
f.set_bold(False)
self.assertFalse(f.get_bold())
def test_set_italic(self):
f = pygame_font.Font(None, 20)
self.assertFalse(f.get_italic())
f.set_italic(True)
self.assertTrue(f.get_italic())
f.set_italic(False)
self.assertFalse(f.get_italic())
def test_set_underline(self):
f = pygame_font.Font(None, 20)
self.assertFalse(f.get_underline())
f.set_underline(True)
self.assertTrue(f.get_underline())
f.set_underline(False)
self.assertFalse(f.get_underline())
def test_size(self):
f = pygame_font.Font(None, 20)
text = as_unicode("Xg")
size = f.size(text)
w, h = size
s = f.render(text, False, (255, 255, 255))
btext = text.encode("ascii")
self.assertIsInstance(w, int)
self.assertIsInstance(h, int)
self.assertEqual(s.get_size(), size)
self.assertEqual(f.size(btext), size)
text = as_unicode(r"\u212A")
btext = text.encode("UTF-16")[2:] # Keep the byte order consistent.
bsize = f.size(btext)
try: # FIXME why do we do this try/except ?
size = f.size(text)
except pygame.error:
pass
else:
self.assertNotEqual(size, bsize)
def test_font_file_not_found(self):
# A per BUG reported by Bo Jangeborg on pygame-user mailing list,
# http://www.mail-archive.com/pygame-users@seul.org/msg11675.html
pygame_font.init()
self.assertRaises(IOError,
pygame_font.Font,
unicode_('some-fictional-font.ttf'), 20)
def test_load_from_file(self):
font_name = pygame_font.get_default_font()
font_path = os.path.join(os.path.split(pygame.__file__)[0],
pygame_font.get_default_font())
f = pygame_font.Font(font_path, 20)
def test_load_from_file_obj(self):
font_name = pygame_font.get_default_font()
font_path = os.path.join(os.path.split(pygame.__file__)[0],
pygame_font.get_default_font())
with open(font_path, "rb") as f:
font = pygame_font.Font(f, 20)
def test_load_default_font_filename(self):
# In font_init, a special case is when the filename argument is
# identical to the default font file name.
f = pygame_font.Font(pygame_font.get_default_font(), 20)
def _load_unicode(self, path):
import shutil
fdir = unicode_(FONTDIR)
temp = os.path.join(fdir, path)
pgfont = os.path.join(fdir, u'test_sans.ttf')
shutil.copy(pgfont, temp)
try:
with open(temp, 'rb') as f:
pass
except IOError:
raise unittest.SkipTest('the path cannot be opened')
try:
pygame_font.Font(temp, 20)
finally:
os.remove(temp)
def test_load_from_file_unicode_0(self):
"""ASCII string as a unicode object"""
self._load_unicode(u'temp_file.ttf')
def test_load_from_file_unicode_1(self):
self._load_unicode(u'你好.ttf')
def test_load_from_file_bytes(self):
font_path = os.path.join(os.path.split(pygame.__file__)[0],
pygame_font.get_default_font())
filesystem_encoding = sys.getfilesystemencoding()
try: # FIXME why do we do this try/except ?
font_path = font_path.decode(filesystem_encoding,
filesystem_errors)
except AttributeError:
pass
bfont_path = font_path.encode(filesystem_encoding,
filesystem_errors)
f = pygame_font.Font(bfont_path, 20)
@unittest.skipIf(IS_PYPY, 'pypy skip known failure') # TODO
class VisualTests( unittest.TestCase ):
__tags__ = ['interactive']
screen = None
aborted = False
def setUp(self):
if self.screen is None:
pygame.init()
self.screen = pygame.display.set_mode((600, 200))
self.screen.fill((255, 255, 255))
pygame.display.flip()
self.f = pygame_font.Font(None, 32)
def abort(self):
if self.screen is not None:
pygame.quit()
self.aborted = True
def query(self,
bold=False, italic=False, underline=False, antialiase=False):
if self.aborted:
return False
spacing = 10
offset = 20
y = spacing
f = self.f
screen = self.screen
screen.fill((255, 255, 255))
pygame.display.flip()
if not (bold or italic or underline or antialiase):
text = "normal"
else:
modes = []
if bold:
modes.append("bold")
if italic:
modes.append("italic")
if underline:
modes.append("underlined")
if antialiase:
modes.append("antialiased")
text = "%s (y/n):" % ('-'.join(modes),)
f.set_bold(bold)
f.set_italic(italic)
f.set_underline(underline)
s = f.render(text, antialiase, (0, 0, 0))
screen.blit(s, (offset, y))
y += s.get_size()[1] + spacing
f.set_bold(False)
f.set_italic(False)
f.set_underline(False)
s = f.render("(some comparison text)", False, (0, 0, 0))
screen.blit(s, (offset, y))
pygame.display.flip()
while 1:
for evt in pygame.event.get():
if evt.type == pygame.KEYDOWN:
if evt.key == pygame.K_ESCAPE:
self.abort()
return False
if evt.key == pygame.K_y:
return True
if evt.key == pygame.K_n:
return False
if evt.type == pygame.QUIT:
self.abort()
return False
def test_bold(self):
self.assertTrue(self.query(bold=True))
def test_italic(self):
self.assertTrue(self.query(italic=True))
def test_underline(self):
self.assertTrue(self.query(underline=True))
def test_antialiase(self):
self.assertTrue(self.query(antialiase=True))
def test_bold_antialiase(self):
self.assertTrue(self.query(bold=True, antialiase=True))
def test_italic_underline(self):
self.assertTrue(self.query(italic=True, underline=True))
if __name__ == '__main__':
unittest.main()