"""Render assets/icon.png and a multi-size assets/icon.ico. Run once; outputs are committed.""" import os import struct import sys from pathlib import Path os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") from PySide6.QtCore import QBuffer, QPointF, QRectF, Qt from PySide6.QtGui import QColor, QGuiApplication, QImage, QLinearGradient, QPainter, QPainterPath, QPolygonF ASSETS = Path(__file__).resolve().parent.parent / "assets" def render(size: int) -> QImage: img = QImage(size, size, QImage.Format_ARGB32) img.fill(Qt.transparent) p = QPainter(img) p.setRenderHint(QPainter.Antialiasing) s = size / 256 grad = QLinearGradient(0, 0, 0, size) grad.setColorAt(0, QColor("#2f80ed")) grad.setColorAt(1, QColor("#1b4f9c")) path = QPainterPath() path.addRoundedRect(QRectF(8 * s, 8 * s, 240 * s, 240 * s), 52 * s, 52 * s) p.fillPath(path, grad) # Film strip holes along the top and bottom edges. p.setBrush(QColor(255, 255, 255, 70)) p.setPen(Qt.NoPen) for i in range(6): x = (38 + i * 34) * s p.drawRoundedRect(QRectF(x, 22 * s, 18 * s, 14 * s), 3 * s, 3 * s) p.drawRoundedRect(QRectF(x, 220 * s, 18 * s, 14 * s), 3 * s, 3 * s) # Two chevrons: "convert from -> to". p.setBrush(QColor("white")) for dx in (0, 62): p.drawPolygon(QPolygonF([QPointF((70 + dx) * s, 72 * s), QPointF((136 + dx) * s, 128 * s), QPointF((70 + dx) * s, 184 * s), QPointF((70 + dx) * s, 152 * s), QPointF((100 + dx) * s, 128 * s), QPointF((70 + dx) * s, 104 * s)])) p.end() return img def png_bytes(img: QImage) -> bytes: buf = QBuffer() buf.open(QBuffer.WriteOnly) img.save(buf, "PNG") return bytes(buf.data()) def write_ico(path: Path, sizes=(16, 24, 32, 48, 64, 128, 256)) -> None: images = [png_bytes(render(n)) for n in sizes] header = struct.pack("