icons: drawn by tools/icons.py (Pillow, supersampled), not screenshotted — the runner's Chrome cropped them
shots / shots (push) Canceled after 29s

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K6897PWcUEwHiqZMcVnNF6
This commit is contained in:
teahubxyzandClaude Fable 5.1 committed 2026-10-21 01:58:01 +00:00
1 parent fb1f816ebe
commit c488529e14
3 files changed
+66 -31

No files matched your search

+2 -3
View File
@@ -1,6 +1,5 @@
<!doctype html>
<meta charset="utf-8">
<title>icon</title>
<style>html,body{margin:0;background:#0b0b0e;overflow:hidden}img{position:absolute;left:0;top:0;display:block}</style>
<img id="i" src="icon.svg" alt="">
<script>const s=+new URLSearchParams(location.search).get("s")||512;const i=document.getElementById("i");i.width=s;i.height=s;i.style.width=i.style.height=s+"px";</script>
<style>html,body{margin:0;height:100%;background:#0b0b0e;display:grid;place-items:center}img{width:min(100vw,100vh);height:min(100vw,100vh)}</style>
<img src="icon.svg" alt="the gandora mark">
+42
View File
@@ -0,0 +1,42 @@
"""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)
+22 -28
View File
@@ -1,11 +1,13 @@
#!/bin/sh
# tools/shots.sh: shots/desktop.png, the first screen at 1440x900, and the app icons (icons/*.png from icons/icon.svg),
# rendered from this folder by headless Chrome.
# Needs python3 (for a local server) and Chrome or Chromium: set CHROME=/path/to/chrome if it isn't found, and
# CHROME_FLAGS=--no-sandbox when running as root.
# tools/shots.sh: shots/desktop.png, the first screen at 1440x900, rendered from this folder by headless Chrome, and
# the app icons, drawn by tools/icons.py.
# Needs python3 (for a local server; Pillow for the icons) and Chrome or Chromium: set CHROME=/path/to/chrome if it
# isn't found, and CHROME_FLAGS=--no-sandbox when running as root.
set -eu
cd "$(dirname "$0")/.."
python3 tools/icons.py
CHROME=${CHROME:-}
for c in "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" "$(command -v chromium || true)" \
"$(command -v chromium-browser || true)" "$(command -v google-chrome || true)" "$(command -v google-chrome-stable || true)"; do
@@ -22,27 +24,19 @@ until curl -fs -o /dev/null --max-time 2 "http://127.0.0.1:$PORT/"; do
n=$((n + 1)); [ "$n" -lt 40 ] || { echo "the local server on port $PORT never answered" >&2; exit 1; }; sleep 0.5
done
# shoot <url> <WxH> <out>: one headless screenshot, waited for. The icon page draws its own box at the top left,
# so the crop is exact whatever viewport the runner's Chromium decides on.
shoot() {
prof=$(mktemp -d)
rm -f "$3"
# shellcheck disable=SC2086
"$CHROME" --headless=new --hide-scrollbars --no-first-run --no-default-browser-check --disable-background-networking \
--disable-component-update --force-device-scale-factor=1 --user-data-dir="$prof" --virtual-time-budget=6000 \
--window-size="$2" --screenshot="$3" ${CHROME_FLAGS:-} "$1" >"$prof.log" 2>&1 &
pid=$!
n=0
while kill -0 "$pid" 2>/dev/null && [ ! -s "$3" ]; do n=$((n + 1)); [ "$n" -lt 120 ] || break; sleep 0.5; done
sleep 1
kill "$pid" 2>/dev/null || true; wait "$pid" 2>/dev/null || true
[ -s "$3" ] || { echo "Chrome made no screenshot for $1:" >&2; tail -5 "$prof.log" >&2; exit 1; }
rm -rf "$prof" "$prof.log"
echo "built: ${3#$PWD/}"
}
mkdir -p shots icons
shoot "http://127.0.0.1:$PORT/" 1440,900 "$PWD/shots/desktop.png"
shoot "http://127.0.0.1:$PORT/icons/icon.html?s=512" 512,512 "$PWD/icons/icon-512.png"
shoot "http://127.0.0.1:$PORT/icons/icon.html?s=192" 192,192 "$PWD/icons/icon-192.png"
shoot "http://127.0.0.1:$PORT/icons/icon.html?s=180" 180,180 "$PWD/icons/apple-touch-icon.png"
mkdir -p shots
out=$PWD/shots/desktop.png
prof=$(mktemp -d)
rm -f "$out"
# shellcheck disable=SC2086
"$CHROME" --headless=new --hide-scrollbars --no-first-run --no-default-browser-check --disable-background-networking \
--disable-component-update --user-data-dir="$prof" --virtual-time-budget=6000 --window-size=1440,900 \
--screenshot="$out" ${CHROME_FLAGS:-} "http://127.0.0.1:$PORT/" >"$prof.log" 2>&1 &
pid=$!
n=0
while kill -0 "$pid" 2>/dev/null && [ ! -s "$out" ]; do n=$((n + 1)); [ "$n" -lt 120 ] || break; sleep 0.5; done
sleep 1
kill "$pid" 2>/dev/null || true; wait "$pid" 2>/dev/null || true
[ -s "$out" ] || { echo "Chrome made no screenshot:" >&2; tail -5 "$prof.log" >&2; exit 1; }
rm -rf "$prof" "$prof.log"
echo "built: shots/desktop.png"