forked from genewildish/Mainline
- Add _glyph_cache dict to PygameDisplay.__init__ - Cache font.render() results per (char, fg, bg) combination - Use blits() for batch rendering instead of individual blit calls - Add TestRenderBorder tests (8 new tests) for border rendering - Update NullDisplay.show() to support border=True for consistency - Add test_show_with_border_uses_render_border for TerminalDisplay Closes #28
82 lines
2.3 KiB
Python
82 lines
2.3 KiB
Python
"""
|
|
Null/headless display backend.
|
|
"""
|
|
|
|
import time
|
|
|
|
|
|
class NullDisplay:
|
|
"""Headless/null display - discards all output.
|
|
|
|
This display does nothing - useful for headless benchmarking
|
|
or when no display output is needed. Captures last buffer
|
|
for testing purposes.
|
|
"""
|
|
|
|
width: int = 80
|
|
height: int = 24
|
|
_last_buffer: list[str] | None = None
|
|
|
|
def __init__(self):
|
|
self._last_buffer = None
|
|
|
|
def init(self, width: int, height: int, reuse: bool = False) -> None:
|
|
"""Initialize display with dimensions.
|
|
|
|
Args:
|
|
width: Terminal width in characters
|
|
height: Terminal height in rows
|
|
reuse: Ignored for NullDisplay (no resources to reuse)
|
|
"""
|
|
self.width = width
|
|
self.height = height
|
|
self._last_buffer = None
|
|
|
|
def show(self, buffer: list[str], border: bool = False) -> None:
|
|
from engine.display import get_monitor, render_border
|
|
|
|
# Get FPS for border (if available)
|
|
fps = 0.0
|
|
frame_time = 0.0
|
|
monitor = get_monitor()
|
|
if monitor:
|
|
stats = monitor.get_stats()
|
|
avg_ms = stats.get("pipeline", {}).get("avg_ms", 0) if stats else 0
|
|
frame_count = stats.get("frame_count", 0) if stats else 0
|
|
if avg_ms and frame_count > 0:
|
|
fps = 1000.0 / avg_ms
|
|
frame_time = avg_ms
|
|
|
|
# Apply border if requested (same as terminal display)
|
|
if border:
|
|
buffer = render_border(buffer, self.width, self.height, fps, frame_time)
|
|
|
|
self._last_buffer = buffer
|
|
if monitor:
|
|
t0 = time.perf_counter()
|
|
chars_in = sum(len(line) for line in buffer)
|
|
elapsed_ms = (time.perf_counter() - t0) * 1000
|
|
monitor.record_effect("null_display", elapsed_ms, chars_in, chars_in)
|
|
|
|
def clear(self) -> None:
|
|
pass
|
|
|
|
def cleanup(self) -> None:
|
|
pass
|
|
|
|
def get_dimensions(self) -> tuple[int, int]:
|
|
"""Get current dimensions.
|
|
|
|
Returns:
|
|
(width, height) in character cells
|
|
"""
|
|
return (self.width, self.height)
|
|
|
|
def is_quit_requested(self) -> bool:
|
|
"""Check if quit was requested (optional protocol method)."""
|
|
return False
|
|
|
|
def clear_quit_request(self) -> None:
|
|
"""Clear quit request (optional protocol method)."""
|
|
pass
|