#!/usr/bin/env python3 """Disegna le icone dei tre tasti delle opzioni rapide in Home. Stanno in qml/icons/ perche' il pulsante Silica vuole un'immagine, non un disegno QML. PNG e non SVG di proposito: il PNG si vede di sicuro, l'SVG dipende dal supporto SVG dentro il sandbox dell'app. Bianche su trasparente: sul tema Sailfish i tasti sono scuri e le icone di sistema sono cosi'. Tre concetti che il tema Sailfish non ha (nell'elenco ufficiale non c'e' nessuna fiamma, nessuna goccia): boost = fiamma, assenza = casa (la stessa casa dell'icona dell'app), comandi = tre righe con le manopole. Uso: python3 scripts/make_glyphs.py """ import math import pathlib from PIL import Image, ImageDraw BASE = 688 # si disegna grande e si riduce: bordi puliti a ogni taglia OUT = 64 # il riquadro vero lo decide il tema (iconSizeExtraSmall) DEST = pathlib.Path(__file__).resolve().parent.parent / "qml" / "icons" BIANCO = (255, 255, 255, 255) VUOTO = (0, 0, 0, 0) def nuova(): return Image.new("RGBA", (BASE, BASE), VUOTO) def fiamma(d, cx, cy, w, h): """Boost: fiamma — stretta, punta piegata a sinistra, fondo tondo.""" r = 0.26 * w alto = h - 0.55 * r fondo = cy + h / 2 destra, sinistra = [], [] passi = 160 for i in range(passi + 1): t = i / passi mezza = (w / 2) * math.sin(math.pi * (t ** 0.7)) piega = (w * 0.18) * (t ** 1.7) # la punta pende a sinistra y = fondo - alto * t destra.append((cx + mezza - piega, y)) sinistra.append((cx - mezza - piega, y)) d.polygon(destra + list(reversed(sinistra)), fill=BIANCO) # fondo arrotondato: copre la punta stretta in basso d.ellipse([cx - r, fondo - 0.55 * r, cx + r, fondo + 0.55 * r], fill=BIANCO) def casa(d, cx, cy, w, h): """Assenza: casa con la porta (senza la porta si legge come una freccia).""" cima = cy - h / 2 base = cy + h / 2 spalle = cima + h * 0.36 # dove il tetto incontra il muro d.polygon([(cx - w * 0.52, spalle), (cx, cima), (cx + w * 0.52, spalle)], fill=BIANCO) d.rectangle([cx - w * 0.33, spalle - 1, cx + w * 0.33, base], fill=BIANCO) # la porta: e' quello che la distingue da una freccia d.rectangle([cx - w * 0.20 / 2, base - h * 0.30, cx + w * 0.20 / 2, base], fill=VUOTO) def comandi(d, cx, cy, w, h): """Comandi: tre righe con la manopola in posizioni diverse.""" manopole = (-0.18, 0.20, -0.06) for i, posizione in enumerate(manopole): y = cy - h / 2 + h * (0.16 + 0.34 * i) spessore = h * 0.115 d.rounded_rectangle([cx - w / 2, y - spessore / 2, cx + w / 2, y + spessore / 2], radius=spessore / 2, fill=BIANCO) kx = cx + w * posizione r = h * 0.13 d.ellipse([kx - r * 1.5, y - r * 1.5, kx + r * 1.5, y + r * 1.5], fill=VUOTO) d.ellipse([kx - r, y - r, kx + r, y + r], fill=BIANCO) def stop(d, cx, cy, w, h): """Ferma il boost: quadrato pieno dentro un anello (il segno universale).""" r = min(w, h) / 2 d.ellipse([cx - r, cy - r, cx + r, cy + r], outline=BIANCO, width=max(2, int(h * 0.12))) q = r * 0.46 d.rectangle([cx - q, cy - q, cx + q, cy + q], fill=BIANCO) def main(): DEST.mkdir(parents=True, exist_ok=True) disegni = ( ("quick-boost.png", fiamma, 0.62), ("quick-away.png", casa, 0.80), ("quick-commands.png", comandi, 0.90), ("quick-boost-stop.png", stop, 0.90), ) # il glifo riempie il suo riquadro (un filo di margine): la misura sul # telefono la decide Theme.iconSizeExtraSmall nel pulsante, non il file lato = BASE * 0.80 for nome, disegno, strettezza in disegni: img = nuova() d = ImageDraw.Draw(img) disegno(d, BASE / 2, BASE / 2, lato * strettezza, lato) img = img.resize((OUT, OUT), Image.LANCZOS) img.save(DEST / nome) print("scritto", (DEST / nome).relative_to(DEST.parent.parent)) if __name__ == "__main__": main()