Add a PC renderer for the themed pages; fix overlapping layouts

tools/render_pages.py compiles the page code natively with g++ against
ESPHome's own display and font code and the font bitmaps of the last
`esphome compile`, and draws pages to PNG at chosen moments with sample
data (normal, empty, alert, busy), as a contact sheet, or as one example
per page in docs/images/pages (now shown in the README).

Fixes found with it: Cyber HUD zone names ran into the temperatures,
the breach header label hit the tag and the column marker the matrix
label; KonoSuba subtitle, guild weather icon, cabbage text and all-day
deadline, and hills through the party; Steins;Gate D-mail recipient, the
microwave display, the gadget card value and world line labels; LCARS
room rows, readout bars and data cascade, warp core readouts, and the
captain's log weather wording.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mangavalkandClaude Opus 5.5 committed 2026-10-19 16:46:31 +02:00
1 parent 13a499fd97
commit d2e81a5a36
27 files changed
+627 -38

No files matched your search

+7 -7
View File
@@ -173,16 +173,16 @@ void lcars_status(EL512Display &it, const Fonts &f, const HomeData &d, ESPTime n
for (int i = 0; i < 3; i++) {
const int y = 48 + i * 24;
block(it, f.small, 84, y, 66, 18, rows[i].name);
readout(it, 156, y + 4, 90, 10, rows[i].w / 5000.0f);
readout(it, 156, y + 4, 80, 10, rows[i].w / 5000.0f);
it.print(298, y + 18, f.small, TextAlign::BOTTOM_RIGHT, kw(rows[i].w).c_str());
}
// Environmental.
it.print(84, 128, f.small, TextAlign::TOP_LEFT, "ENVIRONMENTAL DECKS 1-4");
for (int i = 0; i < 4; i++) {
const int x = 84 + (i % 2) * 110, y = 150 + (i / 2) * 40;
const int x = 84 + (i % 2) * 110, y = 148 + (i / 2) * 44;
it.print(x, y, f.small, TextAlign::TOP_LEFT, fit(f.small, upper(d.rooms[i].name), 104).c_str());
it.print(x, y + 16, f.medium, TextAlign::TOP_LEFT, deg(d.rooms[i].value).c_str());
it.print(x, y + 14, f.medium, TextAlign::TOP_LEFT, deg(d.rooms[i].value).c_str());
}
// Clock, sensors, fabrication bay.
@@ -200,7 +200,7 @@ void lcars_status(EL512Display &it, const Fonts &f, const HomeData &d, ESPTime n
for (int col = 0; col < 2; col++) {
for (int row = 0; row < 9; row++) {
const uint32_t r = hash(col * 31 + row, (t / 180) + row * 3);
const int x = 446 + col * 32, y = 96 + row * 12;
const int x = 456 + col * 30, y = 96 + row * 12;
if (r % 5 == 0)
continue;
it.printf(x, y, f.pixel, TextAlign::TOP_LEFT, "%03u", (unsigned) (r % 1000));
@@ -325,8 +325,8 @@ void warp_core(EL512Display &it, const Fonts &f, const HomeData &d) {
for (int i = 0; i < 3; i++) {
const int y = 36 + i * 44;
it.print(0, y, f.small, TextAlign::TOP_LEFT, rows[i].name);
it.print(204, y, f.small, TextAlign::TOP_RIGHT, rows[i].value.c_str());
readout(it, 0, y + 22, 200, 10, rows[i].frac);
it.print(196, y, f.small, TextAlign::TOP_RIGHT, rows[i].value.c_str());
readout(it, 0, y + 22, 196, 10, rows[i].frac);
}
it.print(0, 172, f.small, TextAlign::TOP_LEFT, "MATTER / ANTIMATTER 1:1");
it.print(0, 192, f.small, TextAlign::TOP_LEFT, "DILITHIUM MATRIX STABLE");
@@ -409,7 +409,7 @@ void captains_log(EL512Display &it, const Fonts &f, const HomeData &d, ESPTime n
std::string entry = "We are holding position at home.";
if (!std::isnan(d.temp))
entry += str(" Outside it is %.0f degrees", d.temp) +
(d.weather.empty() ? std::string(".") : " and " + weather_text(d.weather) + ".");
(d.weather.empty() ? std::string(".") : " and " + lower(weather_text(d.weather)) + ".");
if (!std::isnan(d.solar))
entry += " The solar collectors deliver " + watts(d.solar) +
(std::isnan(d.house) ? std::string(".") : " while the replicators draw " + watts(d.house) + ".");