Skip to content

Commit 2b3d6fd

Browse files
committed
Rewrite SDL renderer primitive drawing methods and add test coverage
Fixes #159
1 parent 1ba890c commit 2b3d6fd

File tree

3 files changed

+48
-32
lines changed

3 files changed

+48
-32
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ This project adheres to [Semantic Versioning](https://semver.org/) since version
1717
### Fixed
1818

1919
- Suppressed internal `mouse.tile_motion` deprecation warning.
20+
- Fixed SDL renderer primitive drawing methods. #159
2021

2122
## [16.2.3] - 2024-07-16
2223

tcod/sdl/render.py

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -581,62 +581,63 @@ def draw_point(self, xy: tuple[float, float]) -> None:
581581
582582
.. versionadded:: 13.5
583583
"""
584-
_check(lib.SDL_RenderDrawPointF(self.p, (xy,)))
584+
x, y = xy
585+
_check(lib.SDL_RenderDrawPointF(self.p, x, y))
585586

586587
def draw_line(self, start: tuple[float, float], end: tuple[float, float]) -> None:
587588
"""Draw a single line.
588589
589590
.. versionadded:: 13.5
590591
"""
591-
_check(lib.SDL_RenderDrawLineF(self.p, *start, *end))
592-
593-
def fill_rects(self, rects: NDArray[np.intc | np.float32]) -> None:
592+
x1, y1 = start
593+
x2, y2 = end
594+
_check(lib.SDL_RenderDrawLineF(self.p, x1, y1, x2, y2))
595+
596+
@staticmethod
597+
def _convert_array(array: NDArray[np.number]) -> NDArray[np.intc] | NDArray[np.float32]:
598+
"""Convert ndarray for a SDL function expecting a C contiguous array of either intc or float32."""
599+
if array.dtype in (np.intc, np.int8, np.int16, np.int32, np.uint8, np.uint16):
600+
return np.ascontiguousarray(array, np.intc)
601+
return np.ascontiguousarray(array, np.float32)
602+
603+
def fill_rects(self, rects: NDArray[np.number]) -> None:
594604
"""Fill multiple rectangles from an array.
595605
596606
.. versionadded:: 13.5
597607
"""
598608
assert len(rects.shape) == 2 # noqa: PLR2004
599609
assert rects.shape[1] == 4 # noqa: PLR2004
600-
rects = np.ascontiguousarray(rects)
610+
rects = self._convert_array(rects)
601611
if rects.dtype == np.intc:
602612
_check(lib.SDL_RenderFillRects(self.p, tcod.ffi.from_buffer("SDL_Rect*", rects), rects.shape[0]))
603-
elif rects.dtype == np.float32:
604-
_check(lib.SDL_RenderFillRectsF(self.p, tcod.ffi.from_buffer("SDL_FRect*", rects), rects.shape[0]))
605-
else:
606-
msg = f"Array must be an np.intc or np.float32 type, got {rects.dtype}."
607-
raise TypeError(msg)
613+
return
614+
_check(lib.SDL_RenderFillRectsF(self.p, tcod.ffi.from_buffer("SDL_FRect*", rects), rects.shape[0]))
608615

609-
def draw_rects(self, rects: NDArray[np.intc | np.float32]) -> None:
616+
def draw_rects(self, rects: NDArray[np.number]) -> None:
610617
"""Draw multiple outlined rectangles from an array.
611618
612619
.. versionadded:: 13.5
613620
"""
614621
assert len(rects.shape) == 2 # noqa: PLR2004
615622
assert rects.shape[1] == 4 # noqa: PLR2004
616-
rects = np.ascontiguousarray(rects)
623+
rects = self._convert_array(rects)
617624
if rects.dtype == np.intc:
618625
_check(lib.SDL_RenderDrawRects(self.p, tcod.ffi.from_buffer("SDL_Rect*", rects), rects.shape[0]))
619-
elif rects.dtype == np.float32:
620-
_check(lib.SDL_RenderDrawRectsF(self.p, tcod.ffi.from_buffer("SDL_FRect*", rects), rects.shape[0]))
621-
else:
622-
msg = f"Array must be an np.intc or np.float32 type, got {rects.dtype}."
623-
raise TypeError(msg)
626+
return
627+
_check(lib.SDL_RenderDrawRectsF(self.p, tcod.ffi.from_buffer("SDL_FRect*", rects), rects.shape[0]))
624628

625-
def draw_points(self, points: NDArray[np.intc | np.float32]) -> None:
629+
def draw_points(self, points: NDArray[np.number]) -> None:
626630
"""Draw an array of points.
627631
628632
.. versionadded:: 13.5
629633
"""
630634
assert len(points.shape) == 2 # noqa: PLR2004
631635
assert points.shape[1] == 2 # noqa: PLR2004
632-
points = np.ascontiguousarray(points)
636+
points = self._convert_array(points)
633637
if points.dtype == np.intc:
634-
_check(lib.SDL_RenderDrawRects(self.p, tcod.ffi.from_buffer("SDL_Point*", points), points.shape[0]))
635-
elif points.dtype == np.float32:
636-
_check(lib.SDL_RenderDrawRectsF(self.p, tcod.ffi.from_buffer("SDL_FPoint*", points), points.shape[0]))
637-
else:
638-
msg = f"Array must be an np.intc or np.float32 type, got {points.dtype}."
639-
raise TypeError(msg)
638+
_check(lib.SDL_RenderDrawPoints(self.p, tcod.ffi.from_buffer("SDL_Point*", points), points.shape[0]))
639+
return
640+
_check(lib.SDL_RenderDrawPointsF(self.p, tcod.ffi.from_buffer("SDL_FPoint*", points), points.shape[0]))
640641

641642
def draw_lines(self, points: NDArray[np.intc | np.float32]) -> None:
642643
"""Draw a connected series of lines from an array.
@@ -645,14 +646,11 @@ def draw_lines(self, points: NDArray[np.intc | np.float32]) -> None:
645646
"""
646647
assert len(points.shape) == 2 # noqa: PLR2004
647648
assert points.shape[1] == 2 # noqa: PLR2004
648-
points = np.ascontiguousarray(points)
649+
points = self._convert_array(points)
649650
if points.dtype == np.intc:
650-
_check(lib.SDL_RenderDrawRects(self.p, tcod.ffi.from_buffer("SDL_Point*", points), points.shape[0] - 1))
651-
elif points.dtype == np.float32:
652-
_check(lib.SDL_RenderDrawRectsF(self.p, tcod.ffi.from_buffer("SDL_FPoint*", points), points.shape[0] - 1))
653-
else:
654-
msg = f"Array must be an np.intc or np.float32 type, got {points.dtype}."
655-
raise TypeError(msg)
651+
_check(lib.SDL_RenderDrawLines(self.p, tcod.ffi.from_buffer("SDL_Point*", points), points.shape[0] - 1))
652+
return
653+
_check(lib.SDL_RenderDrawLinesF(self.p, tcod.ffi.from_buffer("SDL_FPoint*", points), points.shape[0] - 1))
656654

657655
@_required_version((2, 0, 18))
658656
def geometry(

tests/test_sdl.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,23 @@ def test_sdl_render(uses_window: None) -> None:
7676
assert (render.read_pixels(format="RGB") == (0, 0, 0)).all()
7777
assert render.read_pixels(rect=(1, 2, 3, 4)).shape == (4, 3, 4)
7878

79+
render.clear()
80+
81+
render.draw_point((0, 0))
82+
render.draw_points(np.ones((3, 2), dtype=np.float32))
83+
render.draw_points(np.ones((3, 2), dtype=np.intc))
84+
render.draw_points(np.ones((3, 2), dtype=np.float16))
85+
render.draw_points(np.ones((3, 2), dtype=np.int8))
86+
render.draw_line((0, 0), (1, 1))
87+
render.draw_lines(np.ones((3, 2), dtype=np.float32))
88+
render.draw_lines(np.ones((3, 2), dtype=np.intc))
89+
render.draw_rect((0, 0, 1, 1))
90+
render.draw_rects(np.ones((3, 4), dtype=np.float32))
91+
render.draw_rects(np.ones((3, 4), dtype=np.intc))
92+
render.fill_rect((0, 0, 1, 1))
93+
render.fill_rects(np.ones((3, 4), dtype=np.float32))
94+
render.fill_rects(np.ones((3, 4), dtype=np.intc))
95+
7996

8097
def test_sdl_render_bad_types() -> None:
8198
with pytest.raises(TypeError):

0 commit comments

Comments
 (0)