fix(display): Fusszeile des Bildsatzes passt aufs Panel, auch die Fehlt-Warnung

Am Geraet kam die Zeile gekuerzt an ('... (ohne WLA...'), und mit dem Zusatz
' - SATZ FEHLT' war die Warnung in beiden Richtungen ausserhalb der Panelbreite -
also genau die Zeile, die sagt, dass die Station nichts ausliefern kann.

Unbemerkt blieb das, weil _load_font() auf dem Pi DejaVu nimmt und auf dem Mac bis
Arial durchfaellt: dieselbe Zeile misst dort 246,0 von 246 px, auf dem Pi 283,5 px.
Der neue Test misst deshalb mit 25 % Reserve gegen eine breitere Schrift.

Die Fehlt-Warnung ersetzt die Zeile jetzt, statt sie zu verlaengern.
This commit is contained in:
Michael Sauer
2026-09-15 10:37:30 +02:00
parent c482194503
commit f4dd1386ef
2 changed files with 63 additions and 4 deletions
+46
View File
@@ -2064,3 +2064,49 @@ def test_missing_pillow_logs_exactly_one_line_and_exits_zero(argv, monkeypatch,
assert len(caplog.records) == 1, \
f"erwartet genau eine Protokollzeile, bekommen: {[r.getMessage() for r in caplog.records]}"
assert "PIL" in caplog.records[0].getMessage()
# --- Fusszeile des Bildsatz-Umschalters (Geraetetermin 2026-09-15) ------------------
#
# Am Geraet kam die Zeile gekuerzt an: "Lampe -> Onboarding-AP (ohne WLA...". Ausgerechnet
# die Klammer, die den Zustand benennt, fiel weg - und mit dem Zusatz " - SATZ FEHLT" war
# die WARNUNG, dass der gewaehlte Satz gar nicht auf dem Pi liegt, in beiden Richtungen
# unsichtbar (367,5 px bzw. 306 px bei 246 px Platz).
#
# Warum die Testsuite das nie bemerkt hat: _load_font() nimmt den ersten Pfad, der sich
# oeffnen laesst. Auf dem Pi ist das DejaVu Sans Bold, auf dem Mac des Entwicklers faellt
# die Kette bis "Arial Bold.ttf" durch - und Arial baut schmaler. Dieselbe Zeile misst
# dort 246,0 von 246 px (haarscharf drin), auf dem Pi 283,5 px. Das Layout war damit auf
# die Schrift der ENTWICKLUNGSMASCHINE ausgelegt, nicht auf die des Zielgeraets.
#
# Dieser Test misst deshalb mit einer ausdruecklichen Marge: die Zusage lautet nicht "es
# passt mit der hier zufaellig installierten Schrift", sondern "es passt auch mit einer
# spuerbar breiteren". 25 % decken den gemessenen Abstand Arial -> DejaVu (+15 %) mit
# Reserve ab.
FOOTER_WIDTH_SAFETY = 1.25
def _footer_width_px(text: str) -> float:
from PIL import Image, ImageDraw, ImageFont
draw = ImageDraw.Draw(Image.new("1", (render.PANEL_WIDTH_PX,
render.PANEL_HEIGHT_PX), 255))
font = render._load_font(ImageFont, render.FOOTER_FONT_PX, bold=True)
return draw.textlength(text, font=font)
@pytest.mark.parametrize("name", sorted(render.IMAGESET_LABELS))
@pytest.mark.parametrize("missing", [False, True])
def test_imageset_footer_fits_the_panel_with_room_for_a_wider_font(name, missing):
"""Jede Fusszeile des Umschalters - beide Saetze, mit und ohne Fehlt-Warnung - muss
ungekuerzt auf das Panel passen, auch wenn die Schrift des Zielgeraets breiter baut
als die hier installierte. Der Fehlt-Fall ist der wichtigere der vier: er sagt, dass
der GEWAEHLTE Bildsatz nicht auf dem Pi liegt, und genau der war unsichtbar."""
text, = (t for t, role in render._imageset_blocks(
{"imageset": name, "imageset_ok": not missing}) if role == render.ROLE_FOOTER)
max_width_px = render.PANEL_WIDTH_PX - 2 * render.TEXT_MARGIN_PX
width_px = _footer_width_px(text)
assert width_px * FOOTER_WIDTH_SAFETY <= max_width_px, (
"Fusszeile {!r} misst {:.1f} px; mit {:.0f} %% Reserve fuer eine breitere "
"Schrift bleiben nur {:.1f} px Platz".format(
text, width_px, (FOOTER_WIDTH_SAFETY - 1) * 100, max_width_px))