#!/usr/bin/env python3 """ Generate icons/app.ico (Windows) and icons/app.icns (macOS) from the rounded PNG source files in icons/twin-gears/rounded/. Run from the repo root: python scripts/build_icons.py Requirements: pip install pillow # for .ico iconutil # built into macOS; for .icns """ from __future__ import annotations import os import platform import shutil import subprocess import sys import tempfile from pathlib import Path ROOT = Path(__file__).parent.parent SRC = ROOT / "icons" / "twin-gears" / "rounded" OUT = ROOT / "icons" def build_ico(): try: from PIL import Image except ImportError: print("Pillow not installed — skipping .ico generation (pip install pillow)") return sizes = [16, 32, 48, 64, 128, 256] imgs = [] for s in sizes: p = SRC / f"icon-{s}.png" if not p.exists(): print(f" Missing {p.name}, skipping") continue imgs.append(Image.open(p).convert("RGBA")) if not imgs: print(" No source PNGs found — cannot build .ico") return dest = OUT / "app.ico" imgs[-1].save(dest, format="ICO", append_images=imgs[:-1]) print(f" Generated {dest.relative_to(ROOT)} ({dest.stat().st_size // 1024 + 1} KB)") def build_icns(): if shutil.which("iconutil") is None: print(" iconutil not found (macOS-only) — skipping .icns generation") return iconset = Path(tempfile.mkdtemp()) / "app.iconset" iconset.mkdir() mapping = { "icon_16x16.png": "icon-16.png", "icon_16x16@2x.png": "icon-32.png", "icon_32x32.png": "icon-32.png", "icon_32x32@2x.png": "icon-64.png", "icon_128x128.png": "icon-128.png", "icon_128x128@2x.png": "icon-256.png", "icon_256x256.png": "icon-256.png", "icon_256x256@2x.png": "icon-512.png", "icon_512x512.png": "icon-512.png", "icon_512x512@2x.png": "icon-1024.png", } for dst_name, src_name in mapping.items(): src = SRC / src_name if src.exists(): shutil.copy2(src, iconset / dst_name) else: print(f" Missing {src_name}, skipping {dst_name}") dest = OUT / "app.icns" subprocess.run( ["iconutil", "-c", "icns", str(iconset), "-o", str(dest)], check=True, ) shutil.rmtree(iconset.parent) print(f" Generated {dest.relative_to(ROOT)} ({dest.stat().st_size // 1024} KB)") if __name__ == "__main__": print("Building icons/app.ico ...") build_ico() print("Building icons/app.icns ...") build_icns() print("Done.")