#!/usr/bin/env python3
"""Render static/logo.svg into the home-screen icons.
python3 tools/make_icons.py
Writes static/icon-180.png (what iOS uses on the home screen) and
static/icon-512.png (Android / the web manifest): the white mark on
the app's dark background color. iOS flattens a transparent PNG onto
white rather than black, which made the white-on-transparent mark
invisible on the home screen -- so the background needs to be baked
into the PNG itself.
The PNGs are committed, so this only needs running if the logo changes.
It rasterises with headless Chromium, which is a heavy thing to install
for one job -- if you have librsvg to hand, this does the same:
rsvg-convert -w 512 -h 512 --background-color '#0a0d14' static/logo.svg -o static/icon-512.png
Otherwise: pip install playwright && playwright install chromium
"""
import sys
from pathlib import Path
STATIC = Path(__file__).resolve().parent.parent / "static"
LOGO = STATIC / "logo.svg"
SIZES = (180, 512)
MARGIN = 0.14 # breathing room, so iOS's rounded mask never clips it
BACKGROUND = "#0a0d14" # matches theme_color/background_color in the manifest
PAGE = """
"""
def main():
try:
from playwright.sync_api import sync_playwright
except ImportError:
sys.exit("needs playwright: pip install playwright && playwright install chromium")
if not LOGO.exists():
sys.exit(f"no logo at {LOGO}")
scratch = STATIC / "_icon.html"
try:
with sync_playwright() as p:
browser = p.chromium.launch(args=["--no-sandbox"])
for size in SIZES:
inner = round(size * (1 - 2 * MARGIN))
scratch.write_text(PAGE.format(size=size, inner=inner, background=BACKGROUND))
page = browser.new_page(viewport={"width": size, "height": size})
page.goto(scratch.as_uri())
page.wait_for_timeout(120) # let the SVG paint
target = STATIC / f"icon-{size}.png"
page.screenshot(path=target)
page.close()
print(f"wrote {target} ({target.stat().st_size} bytes)")
browser.close()
finally:
scratch.unlink(missing_ok=True)
if __name__ == "__main__":
main()