shots / shots (push) Canceled after 29s
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01K6897PWcUEwHiqZMcVnNF6
43 lines
1.5 KiB
Python
43 lines
1.5 KiB
Python
"""The app icons: the asterisk, white with square ends, on the ground colour. Same geometry as icons/icon.svg.
|
|
|
|
python3 tools/icons.py -> icons/icon-512.png, icons/icon-192.png, icons/apple-touch-icon.png
|
|
|
|
Needs Pillow (pip install pillow). Drawn at 4x and downsampled so the edges are clean.
|
|
"""
|
|
import math
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
try:
|
|
from PIL import Image, ImageDraw
|
|
except ImportError: # pragma: no cover
|
|
sys.exit("pip install pillow")
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
GROUND, INK = (11, 11, 14, 255), (237, 240, 240, 255)
|
|
|
|
|
|
def asterisk(size: int) -> Image.Image:
|
|
ss = 4
|
|
W = size * ss
|
|
im = Image.new("RGBA", (W, W), GROUND)
|
|
d = ImageDraw.Draw(im)
|
|
c = W / 2
|
|
half, width = 150 / 512 * W, 58 / 512 * W # arm half-length and stroke width, as in icon.svg
|
|
for k in range(3):
|
|
a = math.radians(90 + 60 * k)
|
|
dx, dy = math.cos(a), math.sin(a)
|
|
nx, ny = -dy * width / 2, dx * width / 2
|
|
p1 = (c - dx * half, c - dy * half)
|
|
p2 = (c + dx * half, c + dy * half)
|
|
d.polygon([(p1[0] + nx, p1[1] + ny), (p2[0] + nx, p2[1] + ny), (p2[0] - nx, p2[1] - ny), (p1[0] - nx, p1[1] - ny)], fill=INK)
|
|
return im.resize((size, size), Image.LANCZOS)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
out = ROOT / "icons"
|
|
out.mkdir(exist_ok=True)
|
|
for name, size in (("icon-512.png", 512), ("icon-192.png", 192), ("apple-touch-icon.png", 180)):
|
|
asterisk(size).convert("RGB").save(out / name, optimize=True)
|
|
print("built: icons/" + name)
|