70 lines
2.4 KiB
Python
70 lines
2.4 KiB
Python
"""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("<HHH", 0, 1, len(images))
|
|
offset = 6 + 16 * len(images)
|
|
entries, blobs = b"", b""
|
|
for n, data in zip(sizes, images):
|
|
entries += struct.pack("<BBBBHHII", n % 256, n % 256, 0, 0, 1, 32, len(data), offset)
|
|
offset += len(data)
|
|
blobs += data
|
|
path.write_bytes(header + entries + blobs)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
app = QGuiApplication(sys.argv)
|
|
ASSETS.mkdir(exist_ok=True)
|
|
render(256).save(str(ASSETS / "icon.png"))
|
|
write_ico(ASSETS / "icon.ico")
|
|
print("wrote", ASSETS / "icon.png", ASSETS / "icon.ico")
|