Files
StarPilot/openpilot/starpilot/ui/preview_typography.py
T
firestar5683 a82935f326 User interfaces and Android Auto
Integrate onroad views, configurable widgets, local settings, steering-profile contracts, Bluetooth and Android Auto with their device and runtime services.

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
Co-authored-by: Daniel Koepping <elkoled@gmail.com>
Co-authored-by: Danny <dannyirwin31@yahoo.com>
Co-authored-by: DimitriChrysafis <Dimitri.chrysafis@gmail.com>
Co-authored-by: Dom <168790843+firestar5683@users.noreply.github.com>
Co-authored-by: Harald Schäfer <harald.the.engineer@gmail.com>
Co-authored-by: Prabhaav Pillai <prabhaav@msu.edu>
Co-authored-by: Shane Smiskol <shane@smiskol.com>
Co-authored-by: dirwin31 <83434411+dirwin31@users.noreply.github.com>
Co-authored-by: firestarsdog <229254897+firestarsdog@users.noreply.github.com>
Co-authored-by: stef <19478336+stefpi@users.noreply.github.com>
Co-authored-by: whoisdomi <dcantu83@gmail.com>

Co-authored-by: Intelli <contact@intelli.software>
Co-authored-by: pharmacomaniac <blittle65@gmail.com>

Co-authored-by: prabhaavp <prabhaav@msu.edu>
2026-10-14 20:02:39 -05:00

80 lines
3.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Explicit desktop typography preview; no manager, Params or device service access."""
import argparse
import hashlib
import json
from pathlib import Path
import pyray as rl
from openpilot.starpilot.ui.presentation import BitmapFonts, FontRole, Profile
def samples(profile: Profile) -> list[dict]:
if profile == Profile.LARGE:
return [
{"text": "StarPilot", "role": "brand", "size": 96, "x": 40, "y": 25},
{"text": "StarPilot - Baseline model", "role": "normal", "size": 48, "x": 40, "y": 180},
{"text": "CONDITIONAL EXPERIMENTAL", "role": "normal", "size": 45, "x": 40, "y": 290},
{"text": "ALL TIME PAST WEEK PERSONAL RECORDS", "role": "semi_bold", "size": 40, "x": 40, "y": 390},
{"text": "TAKE CONTROL IMMEDIATELY", "role": "bold", "size": 76, "x": 40, "y": 500},
{"text": "45 mph 120 kilometers 0.0 miles", "role": "medium", "size": 58, "x": 40, "y": 650},
{"text": "ABC xyz 0123456789 – ° ✓", "role": "roman", "size": 44, "x": 40, "y": 790},
{"text": "ABC xyz 0123456789", "role": "fallback", "size": 36, "x": 40, "y": 900},
]
return [
{"text": "StarPilot", "role": "brand", "size": 96, "x": 6, "y": -16},
{"text": "6.7.7 Sep 15 Baseline model", "role": "roman", "size": 36, "x": 6, "y": 96},
{"text": "678af78", "role": "normal", "size": 36, "x": 6, "y": 138},
{"text": "45 mph 50 MAX", "role": "bold", "size": 32, "x": 6, "y": 185},
]
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--profile", choices=list(Profile), required=True)
parser.add_argument("--output", type=Path, required=True)
parser.add_argument("--font-directory", type=Path, required=True)
args = parser.parse_args()
profile = Profile(args.profile)
args.output.mkdir(parents=True, exist_ok=True)
width, height = profile.size
rl.set_config_flags(rl.ConfigFlags.FLAG_WINDOW_HIDDEN | rl.ConfigFlags.FLAG_MSAA_4X_HINT)
# The framebuffer is independent of the desktop window; a small hidden context
# also works when the logical device resolution exceeds the desktop monitor.
context_size = min(width, 960), min(height, 540)
rl.init_window(*context_size, "Typography preview")
if not rl.is_window_ready():
raise RuntimeError("Unable to create native graphics context")
texture = rl.load_render_texture(width, height)
try:
with BitmapFonts(profile, args.font_directory) as fonts:
measured = []
rl.begin_texture_mode(texture)
rl.clear_background(rl.BLACK)
for sample in samples(profile):
size = fonts.measure(sample["text"], FontRole(sample["role"]), sample["size"])
measured.append({**sample, "width": size.width, "height": size.height})
fonts.draw(sample["text"], FontRole(sample["role"]), sample["size"], sample["x"], sample["y"])
rl.end_texture_mode()
pixels = rl.load_image_from_texture(texture.texture)
try:
rl.image_format(pixels, rl.PixelFormat.PIXELFORMAT_UNCOMPRESSED_R8G8B8A8)
rl.image_flip_vertical(pixels)
image_path = args.output / f"{profile}.png"
if not rl.export_image(pixels, str(image_path)):
raise RuntimeError("Unable to export native framebuffer")
pixel_hash = hashlib.sha256(bytes(rl.ffi.buffer(pixels.data, width * height * 4))).hexdigest()
finally:
rl.unload_image(pixels)
report = {"profile": profile, "dimensions": [width, height], "context_dimensions": list(context_size), "rgba_sha256": pixel_hash,
"measurements": measured, "scope": "native desktop typography only; device rendering and full UI not qualified"}
(args.output / f"{profile}.json").write_text(json.dumps(report, indent=2) + "\n")
finally:
rl.unload_render_texture(texture)
rl.close_window()
if __name__ == "__main__":
main()