draw_test.py 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294
  1. import unittest
  2. import sys
  3. import pygame
  4. from pygame import draw
  5. from pygame import draw_py
  6. from pygame.locals import SRCALPHA
  7. from pygame.tests import test_utils
  8. PY3 = sys.version_info >= (3, 0, 0)
  9. RED = BG_RED = pygame.Color('red')
  10. GREEN = FG_GREEN = pygame.Color('green')
  11. def get_border_values(surface, width, height):
  12. """Returns a list containing lists with the values of the surface's
  13. borders.
  14. """
  15. border_top = [surface.get_at((x, 0)) for x in range(width)]
  16. border_left = [surface.get_at((0, y)) for y in range(height)]
  17. border_right = [
  18. surface.get_at((width - 1, y)) for y in range(height)]
  19. border_bottom = [
  20. surface.get_at((x, height - 1)) for x in range(width)]
  21. return [border_top, border_left, border_right, border_bottom]
  22. def corners(surface):
  23. """Returns a tuple with the corner positions of the given surface.
  24. Clockwise from the top left corner.
  25. """
  26. width, height = surface.get_size()
  27. return ((0, 0), (width - 1, 0), (width - 1, height - 1), (0, height - 1))
  28. def border_pos_and_color(surface):
  29. """Yields each border position and its color for a given surface.
  30. Clockwise from the top left corner.
  31. """
  32. width, height = surface.get_size()
  33. right, bottom = width - 1, height - 1
  34. # Top edge.
  35. for x in range(width):
  36. pos = (x, 0)
  37. yield pos, surface.get_at(pos)
  38. # Right edge.
  39. # Top right done in top edge loop.
  40. for y in range(1, height):
  41. pos = (right, y)
  42. yield pos, surface.get_at(pos)
  43. # Bottom edge.
  44. # Bottom right done in right edge loop.
  45. for x in range(right - 1, -1, -1):
  46. pos = (x, bottom)
  47. yield pos, surface.get_at(pos)
  48. # Left edge.
  49. # Bottom left done in bottom edge loop. Top left done in top edge loop.
  50. for y in range(bottom - 1, 0, -1):
  51. pos = (0, y)
  52. yield pos, surface.get_at(pos)
  53. class DrawTestCase(unittest.TestCase):
  54. """Base class to test draw module functions."""
  55. draw_rect = staticmethod(draw.rect)
  56. draw_polygon = staticmethod(draw.polygon)
  57. draw_circle = staticmethod(draw.circle)
  58. draw_ellipse = staticmethod(draw.ellipse)
  59. draw_arc = staticmethod(draw.arc)
  60. draw_line = staticmethod(draw.line)
  61. draw_lines = staticmethod(draw.lines)
  62. draw_aaline = staticmethod(draw.aaline)
  63. draw_aalines = staticmethod(draw.aalines)
  64. class PythonDrawTestCase(unittest.TestCase):
  65. """Base class to test draw_py module functions."""
  66. # draw_py is currently missing some functions.
  67. #draw_rect = staticmethod(draw_py.draw_rect)
  68. draw_polygon = staticmethod(draw_py.draw_polygon)
  69. #draw_circle = staticmethod(draw_py.draw_circle)
  70. #draw_ellipse = staticmethod(draw_py.draw_ellipse)
  71. #draw_arc = staticmethod(draw_py.draw_arc)
  72. draw_line = staticmethod(draw_py.draw_line)
  73. draw_lines = staticmethod(draw_py.draw_lines)
  74. draw_aaline = staticmethod(draw_py.draw_aaline)
  75. draw_aalines = staticmethod(draw_py.draw_aalines)
  76. ### Ellipse Testing ###########################################################
  77. class DrawEllipseMixin(object):
  78. """Mixin tests for drawing ellipses.
  79. This class contains all the general ellipse drawing tests.
  80. """
  81. def test_ellipse(self):
  82. """Tests ellipses of differing sizes on surfaces of differing sizes.
  83. Checks if the number of sides touching the border of the surface is
  84. correct.
  85. """
  86. left_top = [(0, 0), (1, 0), (0, 1), (1, 1)]
  87. sizes = [(4, 4), (5, 4), (4, 5), (5, 5)]
  88. color = (1, 13, 24, 255)
  89. def same_size(width, height, border_width):
  90. """Test for ellipses with the same size as the surface."""
  91. surface = pygame.Surface((width, height))
  92. self.draw_ellipse(surface, color, (0, 0, width, height),
  93. border_width)
  94. # For each of the four borders check if it contains the color
  95. borders = get_border_values(surface, width, height)
  96. for border in borders:
  97. self.assertTrue(color in border)
  98. def not_same_size(width, height, border_width, left, top):
  99. """Test for ellipses that aren't the same size as the surface."""
  100. surface = pygame.Surface((width, height))
  101. self.draw_ellipse(surface, color,
  102. (left, top, width - 1, height - 1), border_width)
  103. borders = get_border_values(surface, width, height)
  104. # Check if two sides of the ellipse are touching the border
  105. sides_touching = [
  106. color in border for border in borders].count(True)
  107. self.assertEqual(sides_touching, 2)
  108. for width, height in sizes:
  109. for border_width in (0, 1):
  110. same_size(width, height, border_width)
  111. for left, top in left_top:
  112. not_same_size(width, height, border_width, left, top)
  113. def _check_1_pixel_sized_ellipse(self, surface, collide_rect,
  114. surface_color, ellipse_color):
  115. # Helper method to check the surface for 1 pixel wide and/or high
  116. # ellipses.
  117. surf_w, surf_h = surface.get_size()
  118. surface.lock() # For possible speed up.
  119. for pos in ((x, y) for y in range(surf_h) for x in range(surf_w)):
  120. # Since the ellipse is just a line we can use a rect to help find
  121. # where it is expected to be drawn.
  122. if collide_rect.collidepoint(pos):
  123. expected_color = ellipse_color
  124. else:
  125. expected_color = surface_color
  126. self.assertEqual(surface.get_at(pos), expected_color,
  127. 'collide_rect={}, pos={}'.format(collide_rect, pos))
  128. surface.unlock()
  129. def test_ellipse__1_pixel_width(self):
  130. """Ensures an ellipse with a width of 1 is drawn correctly.
  131. An ellipse with a width of 1 pixel is a vertical line.
  132. """
  133. ellipse_color = pygame.Color('red')
  134. surface_color = pygame.Color('black')
  135. surf_w, surf_h = 10, 20
  136. surface = pygame.Surface((surf_w, surf_h))
  137. rect = pygame.Rect((0, 0), (1, 0))
  138. collide_rect = rect.copy()
  139. # Calculate some positions.
  140. off_left = -1
  141. off_right = surf_w
  142. off_bottom = surf_h
  143. center_x = surf_w // 2
  144. center_y = surf_h // 2
  145. # Test some even and odd heights.
  146. for ellipse_h in range(6, 10):
  147. # The ellipse is drawn on the edge of the rect so collide_rect
  148. # needs +1 height to track where it's drawn.
  149. collide_rect.h = ellipse_h + 1
  150. rect.h = ellipse_h
  151. # Calculate some variable positions.
  152. off_top = -(ellipse_h + 1)
  153. half_off_top = -(ellipse_h // 2)
  154. half_off_bottom = surf_h - (ellipse_h // 2)
  155. # Draw the ellipse in different positions: fully on-surface,
  156. # partially off-surface, and fully off-surface.
  157. positions = ((off_left, off_top),
  158. (off_left, half_off_top),
  159. (off_left, center_y),
  160. (off_left, half_off_bottom),
  161. (off_left, off_bottom),
  162. (center_x, off_top),
  163. (center_x, half_off_top),
  164. (center_x, center_y),
  165. (center_x, half_off_bottom),
  166. (center_x, off_bottom),
  167. (off_right, off_top),
  168. (off_right, half_off_top),
  169. (off_right, center_y),
  170. (off_right, half_off_bottom),
  171. (off_right, off_bottom))
  172. for rect_pos in positions:
  173. surface.fill(surface_color) # Clear before each draw.
  174. rect.topleft = rect_pos
  175. collide_rect.topleft = rect_pos
  176. self.draw_ellipse(surface, ellipse_color, rect)
  177. self._check_1_pixel_sized_ellipse(surface, collide_rect,
  178. surface_color, ellipse_color)
  179. def test_ellipse__1_pixel_width_spanning_surface(self):
  180. """Ensures an ellipse with a width of 1 is drawn correctly
  181. when spanning the height of the surface.
  182. An ellipse with a width of 1 pixel is a vertical line.
  183. """
  184. ellipse_color = pygame.Color('red')
  185. surface_color = pygame.Color('black')
  186. surf_w, surf_h = 10, 20
  187. surface = pygame.Surface((surf_w, surf_h))
  188. rect = pygame.Rect((0, 0), (1, surf_h + 2)) # Longer than the surface.
  189. # Draw the ellipse in different positions: on-surface and off-surface.
  190. positions = ((-1, -1), # (off_left, off_top)
  191. (0, -1), # (left_edge, off_top)
  192. (surf_w // 2, -1), # (center_x, off_top)
  193. (surf_w - 1, -1), # (right_edge, off_top)
  194. (surf_w, -1)) # (off_right, off_top)
  195. for rect_pos in positions:
  196. surface.fill(surface_color) # Clear before each draw.
  197. rect.topleft = rect_pos
  198. self.draw_ellipse(surface, ellipse_color, rect)
  199. self._check_1_pixel_sized_ellipse(surface, rect, surface_color,
  200. ellipse_color)
  201. def test_ellipse__1_pixel_height(self):
  202. """Ensures an ellipse with a height of 1 is drawn correctly.
  203. An ellipse with a height of 1 pixel is a horizontal line.
  204. """
  205. ellipse_color = pygame.Color('red')
  206. surface_color = pygame.Color('black')
  207. surf_w, surf_h = 20, 10
  208. surface = pygame.Surface((surf_w, surf_h))
  209. rect = pygame.Rect((0, 0), (0, 1))
  210. collide_rect = rect.copy()
  211. # Calculate some positions.
  212. off_right = surf_w
  213. off_top = -1
  214. off_bottom = surf_h
  215. center_x = surf_w // 2
  216. center_y = surf_h // 2
  217. # Test some even and odd widths.
  218. for ellipse_w in range(6, 10):
  219. # The ellipse is drawn on the edge of the rect so collide_rect
  220. # needs +1 width to track where it's drawn.
  221. collide_rect.w = ellipse_w + 1
  222. rect.w = ellipse_w
  223. # Calculate some variable positions.
  224. off_left = -(ellipse_w + 1)
  225. half_off_left = -(ellipse_w // 2)
  226. half_off_right = surf_w - (ellipse_w // 2)
  227. # Draw the ellipse in different positions: fully on-surface,
  228. # partially off-surface, and fully off-surface.
  229. positions = ((off_left, off_top),
  230. (half_off_left, off_top),
  231. (center_x, off_top),
  232. (half_off_right, off_top),
  233. (off_right, off_top),
  234. (off_left, center_y),
  235. (half_off_left, center_y),
  236. (center_x, center_y),
  237. (half_off_right, center_y),
  238. (off_right, center_y),
  239. (off_left, off_bottom),
  240. (half_off_left, off_bottom),
  241. (center_x, off_bottom),
  242. (half_off_right, off_bottom),
  243. (off_right, off_bottom))
  244. for rect_pos in positions:
  245. surface.fill(surface_color) # Clear before each draw.
  246. rect.topleft = rect_pos
  247. collide_rect.topleft = rect_pos
  248. self.draw_ellipse(surface, ellipse_color, rect)
  249. self._check_1_pixel_sized_ellipse(surface, collide_rect,
  250. surface_color, ellipse_color)
  251. def test_ellipse__1_pixel_height_spanning_surface(self):
  252. """Ensures an ellipse with a height of 1 is drawn correctly
  253. when spanning the width of the surface.
  254. An ellipse with a height of 1 pixel is a horizontal line.
  255. """
  256. ellipse_color = pygame.Color('red')
  257. surface_color = pygame.Color('black')
  258. surf_w, surf_h = 20, 10
  259. surface = pygame.Surface((surf_w, surf_h))
  260. rect = pygame.Rect((0, 0), (surf_w + 2, 1)) # Wider than the surface.
  261. # Draw the ellipse in different positions: on-surface and off-surface.
  262. positions = ((-1, -1), # (off_left, off_top)
  263. (-1, 0), # (off_left, top_edge)
  264. (-1, surf_h // 2), # (off_left, center_y)
  265. (-1, surf_h - 1), # (off_left, bottom_edge)
  266. (-1, surf_h)) # (off_left, off_bottom)
  267. for rect_pos in positions:
  268. surface.fill(surface_color) # Clear before each draw.
  269. rect.topleft = rect_pos
  270. self.draw_ellipse(surface, ellipse_color, rect)
  271. self._check_1_pixel_sized_ellipse(surface, rect, surface_color,
  272. ellipse_color)
  273. def test_ellipse__1_pixel_width_and_height(self):
  274. """Ensures an ellipse with a width and height of 1 is drawn correctly.
  275. An ellipse with a width and height of 1 pixel is a single pixel.
  276. """
  277. ellipse_color = pygame.Color('red')
  278. surface_color = pygame.Color('black')
  279. surf_w, surf_h = 10, 10
  280. surface = pygame.Surface((surf_w, surf_h))
  281. rect = pygame.Rect((0, 0), (1, 1))
  282. # Calculate some positions.
  283. off_left = -1
  284. off_right = surf_w
  285. off_top = -1
  286. off_bottom = surf_h
  287. left_edge = 0
  288. right_edge = surf_w - 1
  289. top_edge = 0
  290. bottom_edge = surf_h - 1
  291. center_x = surf_w // 2
  292. center_y = surf_h // 2
  293. # Draw the ellipse in different positions: center surface,
  294. # top/bottom/left/right edges, and off-surface.
  295. positions = ((off_left, off_top),
  296. (off_left, top_edge),
  297. (off_left, center_y),
  298. (off_left, bottom_edge),
  299. (off_left, off_bottom),
  300. (left_edge, off_top),
  301. (left_edge, top_edge),
  302. (left_edge, center_y),
  303. (left_edge, bottom_edge),
  304. (left_edge, off_bottom),
  305. (center_x, off_top),
  306. (center_x, top_edge),
  307. (center_x, center_y),
  308. (center_x, bottom_edge),
  309. (center_x, off_bottom),
  310. (right_edge, off_top),
  311. (right_edge, top_edge),
  312. (right_edge, center_y),
  313. (right_edge, bottom_edge),
  314. (right_edge, off_bottom),
  315. (off_right, off_top),
  316. (off_right, top_edge),
  317. (off_right, center_y),
  318. (off_right, bottom_edge),
  319. (off_right, off_bottom))
  320. for rect_pos in positions:
  321. surface.fill(surface_color) # Clear before each draw.
  322. rect.topleft = rect_pos
  323. self.draw_ellipse(surface, ellipse_color, rect)
  324. self._check_1_pixel_sized_ellipse(surface, rect, surface_color,
  325. ellipse_color)
  326. class DrawEllipseTest(DrawEllipseMixin, DrawTestCase):
  327. """Test draw module function ellipse.
  328. This class inherits the general tests from DrawEllipseMixin. It is also
  329. the class to add any draw.ellipse specific tests to.
  330. """
  331. @unittest.skip('draw_py.draw_ellipse not supported yet')
  332. class PythonDrawEllipseTest(DrawEllipseMixin, PythonDrawTestCase):
  333. """Test draw_py module function draw_ellipse.
  334. This class inherits the general tests from DrawEllipseMixin. It is also
  335. the class to add any draw_py.draw_ellipse specific tests to.
  336. """
  337. ### Line Testing ##############################################################
  338. class LineMixin(object):
  339. """Mixin test for drawing lines and aalines.
  340. This class contains all the general line/lines/aaline/aalines drawing
  341. tests.
  342. """
  343. def setUp(self):
  344. self._colors = ((0, 0, 0), (255, 0, 0), (0, 255, 0), (0, 0, 255),
  345. (255, 255, 0), (255, 0, 255), (0, 255, 255),
  346. (255, 255, 255))
  347. # Create some surfaces with different sizes, depths, and flags.
  348. self._surfaces = []
  349. for size in ((49, 49), (50, 50)):
  350. for depth in (8, 16, 24, 32):
  351. for flags in (0, SRCALPHA):
  352. surface = pygame.display.set_mode(size, flags, depth)
  353. self._surfaces.append(surface)
  354. self._surfaces.append(surface.convert_alpha())
  355. def test_line__color(self):
  356. """Tests if the line drawn is the correct color."""
  357. pos = (0, 0)
  358. for surface in self._surfaces:
  359. for expected_color in self._colors:
  360. self.draw_line(surface, expected_color, pos, (1, 0))
  361. self.assertEqual(surface.get_at(pos), expected_color,
  362. 'pos={}'.format(pos))
  363. def test_aaline__color(self):
  364. """Tests if the aaline drawn is the correct color."""
  365. pos = (0, 0)
  366. for surface in self._surfaces:
  367. for expected_color in self._colors:
  368. self.draw_aaline(surface, expected_color, pos, (1, 0))
  369. self.assertEqual(surface.get_at(pos), expected_color,
  370. 'pos={}'.format(pos))
  371. def test_line__gaps(self):
  372. """Tests if the line drawn contains any gaps."""
  373. expected_color = (255, 255, 255)
  374. for surface in self._surfaces:
  375. width = surface.get_width()
  376. self.draw_line(surface, expected_color, (0, 0), (width - 1, 0))
  377. for x in range(width):
  378. pos = (x, 0)
  379. self.assertEqual(surface.get_at(pos), expected_color,
  380. 'pos={}'.format(pos))
  381. def test_aaline__gaps(self):
  382. """Tests if the aaline drawn contains any gaps.
  383. See: #512
  384. """
  385. expected_color = (255, 255, 255)
  386. for surface in self._surfaces:
  387. width = surface.get_width()
  388. self.draw_aaline(surface, expected_color, (0, 0), (width - 1, 0))
  389. for x in range(width):
  390. pos = (x, 0)
  391. self.assertEqual(surface.get_at(pos), expected_color,
  392. 'pos={}'.format(pos))
  393. def test_lines__color(self):
  394. """Tests if the lines drawn are the correct color.
  395. Draws lines around the border of the given surface and checks if all
  396. borders of the surface only contain the given color.
  397. """
  398. for surface in self._surfaces:
  399. for expected_color in self._colors:
  400. self.draw_lines(surface, expected_color, True,
  401. corners(surface))
  402. for pos, color in border_pos_and_color(surface):
  403. self.assertEqual(color, expected_color,
  404. 'pos={}'.format(pos))
  405. def test_aalines__color(self):
  406. """Tests if the aalines drawn are the correct color.
  407. Draws aalines around the border of the given surface and checks if all
  408. borders of the surface only contain the given color.
  409. """
  410. for surface in self._surfaces:
  411. for expected_color in self._colors:
  412. self.draw_aalines(surface, expected_color, True,
  413. corners(surface))
  414. for pos, color in border_pos_and_color(surface):
  415. self.assertEqual(color, expected_color,
  416. 'pos={}'.format(pos))
  417. def test_lines__gaps(self):
  418. """Tests if the lines drawn contain any gaps.
  419. Draws lines around the border of the given surface and checks if
  420. all borders of the surface contain any gaps.
  421. """
  422. expected_color = (255, 255, 255)
  423. for surface in self._surfaces:
  424. self.draw_lines(surface, expected_color, True, corners(surface))
  425. for pos, color in border_pos_and_color(surface):
  426. self.assertEqual(color, expected_color, 'pos={}'.format(pos))
  427. def test_aalines__gaps(self):
  428. """Tests if the aalines drawn contain any gaps.
  429. Draws aalines around the border of the given surface and checks if
  430. all borders of the surface contain any gaps.
  431. See: #512
  432. """
  433. expected_color = (255, 255, 255)
  434. for surface in self._surfaces:
  435. self.draw_aalines(surface, expected_color, True, corners(surface))
  436. for pos, color in border_pos_and_color(surface):
  437. self.assertEqual(color, expected_color, 'pos={}'.format(pos))
  438. class PythonDrawLineTest(LineMixin, DrawTestCase):
  439. """Test draw_py module functions: line, lines, aaline, and aalines.
  440. This class inherits the general tests from LineMixin. It is also the class
  441. to add any draw_py.draw_line/lines/aaline/aalines specific tests to.
  442. """
  443. class DrawLineTest(LineMixin, PythonDrawTestCase):
  444. """Test draw module functions: line, lines, aaline, and aalines.
  445. This class inherits the general tests from LineMixin. It is also the class
  446. to add any draw.line/lines/aaline/aalines specific tests to.
  447. """
  448. def test_path_data_validation(self):
  449. """Test validation of multi-point drawing methods.
  450. See bug #521
  451. """
  452. surf = pygame.Surface((5, 5))
  453. rect = pygame.Rect(0, 0, 5, 5)
  454. bad_values = ('text', b'bytes', 1 + 1j, # string, bytes, complex,
  455. object(), (lambda x: x)) # object, function
  456. bad_points = list(bad_values) + [(1,) , (1, 2, 3)] # wrong tuple length
  457. bad_points.extend((1, v) for v in bad_values) # one wrong value
  458. good_path = [(1, 1), (1, 3), (3, 3), (3, 1)]
  459. # A) draw.lines
  460. check_pts = [(x, y) for x in range(5) for y in range(5)]
  461. for method, is_polgon in ((draw.lines, 0), (draw.aalines, 0),
  462. (draw.polygon, 1)):
  463. for val in bad_values:
  464. # 1. at the beginning
  465. draw.rect(surf, RED, rect, 0)
  466. with self.assertRaises(TypeError):
  467. if is_polgon:
  468. method(surf, GREEN, [val] + good_path, 0)
  469. else:
  470. method(surf, GREEN, True, [val] + good_path)
  471. # make sure, nothing was drawn :
  472. self.assertTrue(all(surf.get_at(pt) == RED for pt in check_pts))
  473. # 2. not at the beginning (was not checked)
  474. draw.rect(surf, RED, rect, 0)
  475. with self.assertRaises(TypeError):
  476. path = good_path[:2] + [val] + good_path[2:]
  477. if is_polgon:
  478. method(surf, GREEN, path, 0)
  479. else:
  480. method(surf, GREEN, True, path)
  481. # make sure, nothing was drawn :
  482. self.assertTrue(all(surf.get_at(pt) == RED for pt in check_pts))
  483. def _test_endianness(self, draw_func):
  484. """ test color component order
  485. """
  486. depths = 24, 32
  487. for depth in depths:
  488. surface = pygame.Surface((5, 3), 0, depth)
  489. surface.fill(pygame.Color(0,0,0))
  490. draw_func(surface, pygame.Color(255, 0, 0), (0, 1), (2, 1), 1)
  491. self.assertGreater(surface.get_at((1, 1)).r, 0, 'there should be red here')
  492. surface.fill(pygame.Color(0,0,0))
  493. draw_func(surface, pygame.Color(0, 0, 255), (0, 1), (2, 1), 1)
  494. self.assertGreater(surface.get_at((1, 1)).b, 0, 'there should be blue here')
  495. def test_line_endianness(self):
  496. """ test color component order
  497. """
  498. self._test_endianness(draw.line)
  499. def test_aaline_endianness(self):
  500. """ test color component order
  501. """
  502. self._test_endianness(draw.aaline)
  503. def test_color_validation(self):
  504. surf = pygame.Surface((10, 10))
  505. colors = 123456, (1, 10, 100), RED # but not '#ab12df' or 'red' ...
  506. points = ((0, 0), (1, 1), (1, 0))
  507. # 1. valid colors
  508. for col in colors:
  509. draw.line(surf, col, (0, 0), (1, 1))
  510. draw.aaline(surf, col, (0, 0), (1, 1))
  511. draw.aalines(surf, col, True, points)
  512. draw.lines(surf, col, True, points)
  513. draw.arc(surf, col, pygame.Rect(0, 0, 3, 3), 15, 150)
  514. draw.ellipse(surf, col, pygame.Rect(0, 0, 3, 6), 1)
  515. draw.circle(surf, col, (7, 3), 2)
  516. draw.polygon(surf, col, points, 0)
  517. # 2. invalid colors
  518. for col in ('invalid', 1.256, object(), None, '#ab12df', 'red'):
  519. with self.assertRaises(TypeError):
  520. draw.line(surf, col, (0, 0), (1, 1))
  521. with self.assertRaises(TypeError):
  522. draw.aaline(surf, col, (0, 0), (1, 1))
  523. with self.assertRaises(TypeError):
  524. draw.aalines(surf, col, True, points)
  525. with self.assertRaises(TypeError):
  526. draw.lines(surf, col, True, points)
  527. with self.assertRaises(TypeError):
  528. draw.arc(surf, col, pygame.Rect(0, 0, 3, 3), 15, 150)
  529. with self.assertRaises(TypeError):
  530. draw.ellipse(surf, col, pygame.Rect(0, 0, 3, 6), 1)
  531. with self.assertRaises(TypeError):
  532. draw.circle(surf, col, (7, 3), 2)
  533. with self.assertRaises(TypeError):
  534. draw.polygon(surf, col, points, 0)
  535. # Using a separate class to test line anti-aliasing.
  536. class AntiAliasedLineMixin(object):
  537. """Mixin tests for line anti-aliasing.
  538. This class contains all the general anti-aliasing line drawing tests.
  539. """
  540. def setUp(self):
  541. self.surface = pygame.Surface((10, 10))
  542. draw.rect(self.surface, BG_RED, (0, 0, 10, 10), 0)
  543. def _check_antialiasing(self, from_point, to_point, should, check_points,
  544. set_endpoints=True):
  545. """Draw a line between two points and check colors of check_points."""
  546. if set_endpoints:
  547. should[from_point] = should[to_point] = FG_GREEN
  548. def check_one_direction(from_point, to_point, should):
  549. self.draw_aaline(self.surface, FG_GREEN, from_point, to_point,
  550. True)
  551. for pt in check_points:
  552. color = should.get(pt, BG_RED)
  553. if PY3: # "subTest" is sooo helpful, but does not exist in PY2
  554. with self.subTest(from_pt=from_point, pt=pt, to=to_point):
  555. self.assertEqual(self.surface.get_at(pt), color)
  556. else:
  557. self.assertEqual(self.surface.get_at(pt), color)
  558. # reset
  559. draw.rect(self.surface, BG_RED, (0, 0, 10, 10), 0)
  560. # it is important to test also opposite direction, the algorithm
  561. # is (#512) or was not symmetric
  562. check_one_direction(from_point, to_point, should)
  563. if from_point != to_point:
  564. check_one_direction(to_point, from_point, should)
  565. def test_short_non_antialiased_lines(self):
  566. """test very short not anti aliased lines in all directions."""
  567. # Horizontal, vertical and diagonal lines should not be anti-aliased,
  568. # even with draw.aaline ...
  569. check_points = [(i, j) for i in range(3, 8) for j in range(3, 8)]
  570. def check_both_directions(from_pt, to_pt, other_points):
  571. should = {pt: FG_GREEN for pt in other_points}
  572. self._check_antialiasing(from_pt, to_pt, should, check_points)
  573. # 0. one point
  574. check_both_directions((5, 5), (5, 5), [])
  575. # 1. horizontal
  576. check_both_directions((4, 7), (5, 7), [])
  577. check_both_directions((5, 4), (7, 4), [(6, 4)])
  578. # 2. vertical
  579. check_both_directions((5, 5), (5, 6), [])
  580. check_both_directions((6, 4), (6, 6), [(6, 5)])
  581. # 3. diagonals
  582. check_both_directions((5, 5), (6, 6), [])
  583. check_both_directions((5, 5), (7, 7), [(6, 6)])
  584. check_both_directions((5, 6), (6, 5), [])
  585. check_both_directions((6, 4), (4, 6), [(5, 5)])
  586. def test_short_line_anti_aliasing(self):
  587. check_points = [(i, j) for i in range(3, 8) for j in range(3, 8)]
  588. def check_both_directions(from_pt, to_pt, should):
  589. self._check_antialiasing(from_pt, to_pt, should, check_points)
  590. # lets say dx = abs(x0 - x1) ; dy = abs(y0 - y1)
  591. brown = (127, 127, 0)
  592. # dy / dx = 0.5
  593. check_both_directions((4, 4), (6, 5), {(5, 4): brown, (5, 5): brown})
  594. check_both_directions((4, 5), (6, 4), {(5, 4): brown, (5, 5): brown})
  595. # dy / dx = 2
  596. check_both_directions((4, 4), (5, 6), {(4, 5): brown, (5, 5): brown})
  597. check_both_directions((5, 4), (4, 6), {(4, 5): brown, (5, 5): brown})
  598. # some little longer lines; so we need to check more points:
  599. check_points = [(i, j) for i in range(2, 9) for j in range(2, 9)]
  600. # dy / dx = 0.25
  601. reddish = (191, 63, 0)
  602. greenish = (63, 191, 0)
  603. should = {(4, 3): greenish, (5, 3): brown, (6, 3): reddish,
  604. (4, 4): reddish, (5, 4): brown, (6, 4): greenish}
  605. check_both_directions((3, 3), (7, 4), should)
  606. should = {(4, 3): reddish, (5, 3): brown, (6, 3): greenish,
  607. (4, 4): greenish, (5, 4): brown, (6, 4): reddish}
  608. check_both_directions((3, 4), (7, 3), should)
  609. # dy / dx = 4
  610. should = {(4, 4): greenish, (4, 5): brown, (4, 6): reddish,
  611. (5, 4): reddish, (5, 5): brown, (5, 6): greenish,
  612. }
  613. check_both_directions((4, 3), (5, 7), should)
  614. should = {(4, 4): reddish, (4, 5): brown, (4, 6): greenish,
  615. (5, 4): greenish, (5, 5): brown, (5, 6): reddish}
  616. check_both_directions((5, 3), (4, 7), should)
  617. def test_anti_aliasing_float_coordinates(self):
  618. """Float coordinates should be blended smoothly."""
  619. check_points = [(i, j) for i in range(5) for j in range(5)]
  620. brown = (127, 127, 0)
  621. # 0. identical point : current implementation does no smoothing...
  622. expected = {(1, 2): FG_GREEN}
  623. self._check_antialiasing((1.5, 2), (1.5, 2), expected,
  624. check_points, set_endpoints=False)
  625. expected = {(2, 2): FG_GREEN}
  626. self._check_antialiasing((2.5, 2.7), (2.5, 2.7), expected,
  627. check_points, set_endpoints=False)
  628. # 1. horizontal lines
  629. # a) blend endpoints
  630. expected = {(1, 2): brown, (2, 2): FG_GREEN}
  631. self._check_antialiasing((1.5, 2), (2, 2), expected,
  632. check_points, set_endpoints=False)
  633. expected = {(1, 2): brown, (2, 2): FG_GREEN, (3, 2): brown}
  634. self._check_antialiasing((1.5, 2), (2.5, 2), expected,
  635. check_points, set_endpoints=False)
  636. expected = {(2, 2): brown, (1, 2): FG_GREEN, }
  637. self._check_antialiasing((1, 2), (1.5, 2), expected,
  638. check_points, set_endpoints=False)
  639. expected = {(1, 2): brown, (2, 2): (63, 191, 0)}
  640. self._check_antialiasing((1.5, 2), (1.75, 2), expected,
  641. check_points, set_endpoints=False)
  642. # b) blend y-coordinate
  643. expected = {(x, y): brown for x in range(2, 5) for y in (1, 2)}
  644. self._check_antialiasing((2, 1.5), (4, 1.5), expected,
  645. check_points, set_endpoints=False)
  646. # 2. vertical lines
  647. # a) blend endpoints
  648. expected = {(2, 1): brown, (2, 2): FG_GREEN, (2, 3): brown}
  649. self._check_antialiasing((2, 1.5), (2, 2.5), expected,
  650. check_points, set_endpoints=False)
  651. expected = {(2, 1): brown, (2, 2): (63, 191, 0)}
  652. self._check_antialiasing((2, 1.5), (2, 1.75), expected,
  653. check_points, set_endpoints=False)
  654. # b) blend x-coordinate
  655. expected = {(x, y): brown for x in (1, 2) for y in range(2, 5)}
  656. self._check_antialiasing((1.5, 2), (1.5, 4), expected,
  657. check_points, set_endpoints=False)
  658. # 3. diagonal lines
  659. # a) blend endpoints
  660. expected = {(1, 1): brown, (2, 2): FG_GREEN, (3, 3): brown}
  661. self._check_antialiasing((1.5, 1.5), (2.5, 2.5), expected,
  662. check_points, set_endpoints=False)
  663. expected = {(3, 1): brown, (2, 2): FG_GREEN, (1, 3): brown}
  664. self._check_antialiasing((2.5, 1.5), (1.5, 2.5), expected,
  665. check_points, set_endpoints=False)
  666. # b) blend sidewards
  667. expected = {(2, 1): brown, (2, 2): brown, (3, 2): brown, (3, 3): brown}
  668. self._check_antialiasing((2, 1.5), (3, 2.5), expected,
  669. check_points, set_endpoints=False)
  670. reddish = (191, 63, 0)
  671. greenish = (63, 191, 0)
  672. expected = {(2, 1): greenish, (2, 2): reddish,
  673. (3, 2): greenish, (3, 3): reddish,
  674. (4, 3): greenish, (4, 4): reddish}
  675. self._check_antialiasing((2, 1.25), (4, 3.25), expected,
  676. check_points, set_endpoints=False)
  677. def test_anti_aliasing_at_and_outside_the_border(self):
  678. check_points = [(i, j) for i in range(10) for j in range(10)]
  679. reddish = (191, 63, 0)
  680. brown = (127, 127, 0)
  681. greenish = (63, 191, 0)
  682. from_point, to_point = (3, 3), (7, 4)
  683. should = {(4, 3): greenish, (5, 3): brown, (6, 3): reddish,
  684. (4, 4): reddish, (5, 4): brown, (6, 4): greenish}
  685. for dx, dy in ((-4, 0), (4, 0), # moved to left and right borders
  686. (0, -5), (0, -4), (0, -3), # upper border
  687. (0, 5), (0, 6), (0, 7), # lower border
  688. (-4, -4), (-4, -3), (-3, -4)): # upper left corner
  689. first = from_point[0] + dx, from_point[1] + dy
  690. second = to_point[0] + dx, to_point[1] + dy
  691. expected = {(x + dx, y + dy): color
  692. for (x, y), color in should.items()}
  693. self._check_antialiasing(first, second, expected, check_points)
  694. @unittest.expectedFailure
  695. class AntiAliasingLineTest(AntiAliasedLineMixin, DrawTestCase):
  696. """Test anti-aliasing for draw.
  697. This class inherits the general tests from AntiAliasedLineMixin. It is
  698. also the class to add any anti-aliasing draw specific tests to.
  699. """
  700. class PythonAntiAliasingLineTest(AntiAliasedLineMixin, PythonDrawTestCase):
  701. """Test anti-aliasing for draw_py.
  702. This class inherits the general tests from AntiAliasedLineMixin. It is
  703. also the class to add any anti-aliasing draw_py specific tests to.
  704. """
  705. ### Draw Module Testing #######################################################
  706. # These tests should eventually be moved to their appropriate mixin/class.
  707. class DrawModuleTest(unittest.TestCase):
  708. def setUp(self):
  709. (self.surf_w, self.surf_h) = self.surf_size = (320, 200)
  710. self.surf = pygame.Surface(self.surf_size, pygame.SRCALPHA)
  711. self.color = (1, 13, 24, 205)
  712. def test_rect__fill(self):
  713. # __doc__ (as of 2008-06-25) for pygame.draw.rect:
  714. # pygame.draw.rect(Surface, color, Rect, width=0): return Rect
  715. # draw a rectangle shape
  716. rect = pygame.Rect(10, 10, 25, 20)
  717. drawn = draw.rect(self.surf, self.color, rect, 0)
  718. self.assertEqual(drawn, rect)
  719. # Should be colored where it's supposed to be
  720. for pt in test_utils.rect_area_pts(rect):
  721. color_at_pt = self.surf.get_at(pt)
  722. self.assertEqual(color_at_pt, self.color)
  723. # And not where it shouldn't
  724. for pt in test_utils.rect_outer_bounds(rect):
  725. color_at_pt = self.surf.get_at(pt)
  726. self.assertNotEqual(color_at_pt, self.color)
  727. # Issue #310: Cannot draw rectangles that are 1 pixel high
  728. bgcolor = pygame.Color('black')
  729. self.surf.fill(bgcolor)
  730. hrect = pygame.Rect(1, 1, self.surf_w - 2, 1)
  731. vrect = pygame.Rect(1, 3, 1, self.surf_h - 4)
  732. drawn = draw.rect(self.surf, self.color, hrect, 0)
  733. self.assertEqual(drawn, hrect)
  734. x, y = hrect.topleft
  735. w, h = hrect.size
  736. self.assertEqual(self.surf.get_at((x - 1, y)), bgcolor)
  737. self.assertEqual(self.surf.get_at((x + w, y)), bgcolor)
  738. for i in range(x, x + w):
  739. self.assertEqual(self.surf.get_at((i, y)), self.color)
  740. drawn = draw.rect(self.surf, self.color, vrect, 0)
  741. self.assertEqual(drawn, vrect)
  742. x, y = vrect.topleft
  743. w, h = vrect.size
  744. self.assertEqual(self.surf.get_at((x, y - 1)), bgcolor)
  745. self.assertEqual(self.surf.get_at((x, y + h)), bgcolor)
  746. for i in range(y, y + h):
  747. self.assertEqual(self.surf.get_at((x, i)), self.color)
  748. def test_rect__one_pixel_lines(self):
  749. rect = pygame.Rect(10, 10, 56, 20)
  750. drawn = draw.rect(self.surf, self.color, rect, 1)
  751. self.assertEqual(drawn, rect)
  752. # Should be colored where it's supposed to be
  753. for pt in test_utils.rect_perimeter_pts(drawn):
  754. color_at_pt = self.surf.get_at(pt)
  755. self.assertEqual(color_at_pt, self.color)
  756. # And not where it shouldn't
  757. for pt in test_utils.rect_outer_bounds(drawn):
  758. color_at_pt = self.surf.get_at(pt)
  759. self.assertNotEqual(color_at_pt, self.color)
  760. # See DrawLineTest class for additional draw.line() and draw.aaline()
  761. # tests.
  762. def test_line(self):
  763. # (l, t), (l, t)
  764. drawn = draw.line(self.surf, self.color, (1, 0), (200, 0))
  765. self.assertEqual(drawn.right, 201,
  766. "end point arg should be (or at least was) inclusive")
  767. # Should be colored where it's supposed to be
  768. for pt in test_utils.rect_area_pts(drawn):
  769. self.assertEqual(self.surf.get_at(pt), self.color)
  770. # And not where it shouldn't
  771. for pt in test_utils.rect_outer_bounds(drawn):
  772. self.assertNotEqual(self.surf.get_at(pt), self.color)
  773. # Line width greater that 1
  774. line_width = 2
  775. offset = 5
  776. a = (offset, offset)
  777. b = (self.surf_size[0] - offset, a[1])
  778. c = (a[0], self.surf_size[1] - offset)
  779. d = (b[0], c[1])
  780. e = (a[0] + offset, c[1])
  781. f = (b[0], c[0] + 5)
  782. lines = [(a, d), (b, c), (c, b), (d, a),
  783. (a, b), (b, a), (a, c), (c, a),
  784. (a, e), (e, a), (a, f), (f, a),
  785. (a, a),]
  786. for p1, p2 in lines:
  787. msg = "%s - %s" % (p1, p2)
  788. if p1[0] <= p2[0]:
  789. plow = p1
  790. phigh = p2
  791. else:
  792. plow = p2
  793. phigh = p1
  794. self.surf.fill((0, 0, 0))
  795. rec = draw.line(self.surf, (255, 255, 255), p1, p2, line_width)
  796. xinc = yinc = 0
  797. if abs(p1[0] - p2[0]) > abs(p1[1] - p2[1]):
  798. yinc = 1
  799. else:
  800. xinc = 1
  801. for i in range(line_width):
  802. p = (p1[0] + xinc * i, p1[1] + yinc * i)
  803. self.assertEqual(self.surf.get_at(p), (255, 255, 255), msg)
  804. p = (p2[0] + xinc * i, p2[1] + yinc * i)
  805. self.assertEqual(self.surf.get_at(p), (255, 255, 255), msg)
  806. p = (plow[0] - 1, plow[1])
  807. self.assertEqual(self.surf.get_at(p), (0, 0, 0), msg)
  808. p = (plow[0] + xinc * line_width, plow[1] + yinc * line_width)
  809. self.assertEqual(self.surf.get_at(p), (0, 0, 0), msg)
  810. p = (phigh[0] + xinc * line_width, phigh[1] + yinc * line_width)
  811. self.assertEqual(self.surf.get_at(p), (0, 0, 0), msg)
  812. if p1[0] < p2[0]:
  813. rx = p1[0]
  814. else:
  815. rx = p2[0]
  816. if p1[1] < p2[1]:
  817. ry = p1[1]
  818. else:
  819. ry = p2[1]
  820. w = abs(p2[0] - p1[0]) + 1 + xinc * (line_width - 1)
  821. h = abs(p2[1] - p1[1]) + 1 + yinc * (line_width - 1)
  822. msg += ", %s" % (rec,)
  823. self.assertEqual(rec, (rx, ry, w, h), msg)
  824. @unittest.expectedFailure
  825. def test_line_for_gaps(self):
  826. """ |tags: ignore|
  827. """
  828. # __doc__ (as of 2008-06-25) for pygame.draw.line:
  829. # pygame.draw.line(Surface, color, start_pos, end_pos, width=1): return Rect
  830. # draw a straight line segment
  831. # This checks bug Thick Line Bug #448
  832. width = 200
  833. height = 200
  834. surf = pygame.Surface((width, height), pygame.SRCALPHA)
  835. def white_surrounded_pixels(x, y):
  836. offsets = [(1, 0), (0, 1), (-1, 0), (0, -1)]
  837. WHITE = (255, 255, 255, 255)
  838. return len([1 for dx, dy in offsets
  839. if surf.get_at((x+dx, y+dy)) == WHITE])
  840. def check_white_line(start, end):
  841. surf.fill((0, 0, 0))
  842. pygame.draw.line(surf, (255, 255, 255), start, end, 30)
  843. BLACK = (0, 0, 0, 255)
  844. for x in range(1, width-1):
  845. for y in range(1, height-1):
  846. if surf.get_at((x, y)) == BLACK:
  847. self.assertTrue(white_surrounded_pixels(x, y) < 3)
  848. check_white_line((50, 50), (140, 0))
  849. check_white_line((50, 50), (0, 120))
  850. check_white_line((50, 50), (199, 198))
  851. ### Polygon Testing ###########################################################
  852. SQUARE = ([0, 0], [3, 0], [3, 3], [0, 3])
  853. DIAMOND = [(1, 3), (3, 5), (5, 3), (3, 1)]
  854. CROSS = ([2, 0], [4, 0], [4, 2], [6, 2],
  855. [6, 4], [4, 4], [4, 6], [2, 6],
  856. [2, 4], [0, 4], [0, 2], [2, 2])
  857. class DrawPolygonMixin(object):
  858. """Mixin tests for drawing polygons.
  859. This class contains all the general polygon drawing tests.
  860. """
  861. def setUp(self):
  862. self.surface = pygame.Surface((20, 20))
  863. def test_draw_square(self):
  864. self.draw_polygon(self.surface, RED, SQUARE, 0)
  865. # note : there is a discussion (#234) if draw.polygon should include or
  866. # not the right or lower border; here we stick with current behavior,
  867. # eg include those borders ...
  868. for x in range(4):
  869. for y in range(4):
  870. self.assertEqual(self.surface.get_at((x, y)), RED)
  871. def test_draw_diamond(self):
  872. pygame.draw.rect(self.surface, RED, (0, 0, 10, 10), 0)
  873. self.draw_polygon(self.surface, GREEN, DIAMOND, 0)
  874. # this diamond shape is equivalent to its four corners, plus inner square
  875. for x, y in DIAMOND:
  876. self.assertEqual(self.surface.get_at((x, y)), GREEN, msg=str((x, y)))
  877. for x in range(2, 5):
  878. for y in range(2, 5):
  879. self.assertEqual(self.surface.get_at((x, y)), GREEN)
  880. def test_1_pixel_high_or_wide_shapes(self):
  881. # 1. one-pixel-high, filled
  882. pygame.draw.rect(self.surface, RED, (0, 0, 10, 10), 0)
  883. self.draw_polygon(self.surface, GREEN, [(x, 2) for x, _y in CROSS], 0)
  884. cross_size = 6 # the maximum x or y coordinate of the cross
  885. for x in range(cross_size + 1):
  886. self.assertEqual(self.surface.get_at((x, 1)), RED)
  887. self.assertEqual(self.surface.get_at((x, 2)), GREEN)
  888. self.assertEqual(self.surface.get_at((x, 3)), RED)
  889. pygame.draw.rect(self.surface, RED, (0, 0, 10, 10), 0)
  890. # 2. one-pixel-high, not filled
  891. self.draw_polygon(self.surface, GREEN, [(x, 5) for x, _y in CROSS], 1)
  892. for x in range(cross_size + 1):
  893. self.assertEqual(self.surface.get_at((x, 4)), RED)
  894. self.assertEqual(self.surface.get_at((x, 5)), GREEN)
  895. self.assertEqual(self.surface.get_at((x, 6)), RED)
  896. pygame.draw.rect(self.surface, RED, (0, 0, 10, 10), 0)
  897. # 3. one-pixel-wide, filled
  898. self.draw_polygon(self.surface, GREEN, [(3, y) for _x, y in CROSS], 0)
  899. for y in range(cross_size + 1):
  900. self.assertEqual(self.surface.get_at((2, y)), RED)
  901. self.assertEqual(self.surface.get_at((3, y)), GREEN)
  902. self.assertEqual(self.surface.get_at((4, y)), RED)
  903. pygame.draw.rect(self.surface, RED, (0, 0, 10, 10), 0)
  904. # 4. one-pixel-wide, not filled
  905. self.draw_polygon(self.surface, GREEN, [(4, y) for _x, y in CROSS], 1)
  906. for y in range(cross_size + 1):
  907. self.assertEqual(self.surface.get_at((3, y)), RED)
  908. self.assertEqual(self.surface.get_at((4, y)), GREEN)
  909. self.assertEqual(self.surface.get_at((5, y)), RED)
  910. def test_draw_symetric_cross(self):
  911. """non-regression on issue #234 : x and y where handled inconsistently.
  912. Also, the result is/was different whether we fill or not the polygon.
  913. """
  914. # 1. case width = 1 (not filled: `polygon` calls internally the `lines` function)
  915. pygame.draw.rect(self.surface, RED, (0, 0, 10, 10), 0)
  916. self.draw_polygon(self.surface, GREEN, CROSS, 1)
  917. inside = [(x, 3) for x in range(1, 6)] + [(3, y) for y in range(1, 6)]
  918. for x in range(10):
  919. for y in range(10):
  920. if (x, y) in inside:
  921. self.assertEqual(self.surface.get_at((x, y)), RED)
  922. elif (x in range(2, 5) and y <7) or (y in range(2, 5) and x < 7):
  923. # we are on the border of the cross:
  924. self.assertEqual(self.surface.get_at((x, y)), GREEN)
  925. else:
  926. # we are outside
  927. self.assertEqual(self.surface.get_at((x, y)), RED)
  928. # 2. case width = 0 (filled; this is the example from #234)
  929. pygame.draw.rect(self.surface, RED, (0, 0, 10, 10), 0)
  930. self.draw_polygon(self.surface, GREEN, CROSS, 0)
  931. inside = [(x, 3) for x in range(1, 6)] + [(3, y) for y in range(1, 6)]
  932. for x in range(10):
  933. for y in range(10):
  934. if (x in range(2, 5) and y <7) or (y in range(2, 5) and x < 7):
  935. # we are on the border of the cross:
  936. self.assertEqual(self.surface.get_at((x, y)), GREEN, msg=str((x, y)))
  937. else:
  938. # we are outside
  939. self.assertEqual(self.surface.get_at((x, y)), RED)
  940. def test_illumine_shape(self):
  941. """non-regression on issue #313"""
  942. rect = pygame.Rect((0, 0, 20, 20))
  943. path_data = [(0, 0), (rect.width-1, 0), # upper border
  944. (rect.width-5, 5-1), (5-1, 5-1), # upper inner
  945. (5- 1, rect.height-5), (0, rect.height-1)] # lower diagonal
  946. # The shape looks like this (the numbers are the indices of path_data)
  947. # 0**********************1 <-- upper border
  948. # ***********************
  949. # **********************
  950. # *********************
  951. # ****3**************2 <-- upper inner border
  952. # *****
  953. # ***** (more lines here)
  954. # *****
  955. # ****4
  956. # ****
  957. # ***
  958. # **
  959. # 5
  960. #
  961. # the current bug is that the "upper inner" line is not drawn, but only
  962. # if 4 or some lower corner exists
  963. pygame.draw.rect(self.surface, RED, (0, 0, 20, 20), 0)
  964. # 1. First without the corners 4 & 5
  965. self.draw_polygon(self.surface, GREEN, path_data[:4], 0)
  966. for x in range(20):
  967. self.assertEqual(self.surface.get_at((x, 0)), GREEN) # upper border
  968. for x in range(4, rect.width-5 +1):
  969. self.assertEqual(self.surface.get_at((x, 4)), GREEN) # upper inner
  970. # 2. with the corners 4 & 5
  971. pygame.draw.rect(self.surface, RED, (0, 0, 20, 20), 0)
  972. self.draw_polygon(self.surface, GREEN, path_data, 0)
  973. for x in range(4, rect.width-5 +1):
  974. self.assertEqual(self.surface.get_at((x, 4)), GREEN) # upper inner
  975. def test_invalid_points(self):
  976. self.assertRaises(TypeError, lambda: self.draw_polygon(self.surface,
  977. RED, ((0, 0), (0, 20), (20, 20), 20), 0))
  978. class DrawPolygonTest(DrawPolygonMixin, DrawTestCase):
  979. """Test draw module function polygon.
  980. This class inherits the general tests from DrawPolygonMixin. It is also
  981. the class to add any draw.polygon specific tests to.
  982. """
  983. class PythonDrawPolygonTest(DrawPolygonMixin, PythonDrawTestCase):
  984. """Test draw_py module function draw_polygon.
  985. This class inherits the general tests from DrawPolygonMixin. It is also
  986. the class to add any draw_py.draw_polygon specific tests to.
  987. """
  988. ### Rect Testing ##############################################################
  989. class DrawRectMixin(object):
  990. """Mixin tests for drawing rects.
  991. This class contains all the general rect drawing tests.
  992. """
  993. def todo_test_circle(self):
  994. self.fail()
  995. class DrawRectTest(DrawRectMixin, DrawTestCase):
  996. """Test draw module function rect.
  997. This class inherits the general tests from DrawRectMixin. It is also the
  998. class to add any draw.rect specific tests to.
  999. """
  1000. class PythonDrawRectTest(DrawRectMixin, PythonDrawTestCase):
  1001. """Test draw_py module function draw_rect.
  1002. This class inherits the general tests from DrawRectMixin. It is also the
  1003. class to add any draw_py.draw_rect specific tests to.
  1004. """
  1005. ### Circle Testing ############################################################
  1006. class DrawCircleMixin(object):
  1007. """Mixin tests for drawing circles.
  1008. This class contains all the general circle drawing tests.
  1009. """
  1010. def todo_test_circle(self):
  1011. self.fail()
  1012. class DrawCircleTest(DrawCircleMixin, DrawTestCase):
  1013. """Test draw module function circle.
  1014. This class inherits the general tests from DrawCircleMixin. It is also
  1015. the class to add any draw.circle specific tests to.
  1016. """
  1017. class PythonDrawCircleTest(DrawCircleMixin, PythonDrawTestCase):
  1018. """Test draw_py module function draw_circle."
  1019. This class inherits the general tests from DrawCircleMixin. It is also
  1020. the class to add any draw_py.draw_circle specific tests to.
  1021. """
  1022. ### Arc Testing ###############################################################
  1023. class DrawArcMixin(object):
  1024. """Mixin tests for drawing arcs.
  1025. This class contains all the general arc drawing tests.
  1026. """
  1027. def todo_test_arc(self):
  1028. self.fail()
  1029. class DrawArcTest(DrawArcMixin, DrawTestCase):
  1030. """Test draw module function arc.
  1031. This class inherits the general tests from DrawArcMixin. It is also the
  1032. class to add any draw.arc specific tests to.
  1033. """
  1034. class PythonDrawArcTest(DrawArcMixin, PythonDrawTestCase):
  1035. """Test draw_py module function draw_arc.
  1036. This class inherits the general tests from DrawArcMixin. It is also the
  1037. class to add any draw_py.draw_arc specific tests to.
  1038. """
  1039. ###############################################################################
  1040. if __name__ == '__main__':
  1041. unittest.main()