# -*- coding: utf-8 -*- """Generate Ai-DOP tabBar icons: 81x81 PNG, transparent bg, two states (gray / navy).""" import math from PIL import Image, ImageDraw S = 4 # supersample SIZE = 81 * S OUT = r"d:\Projects\Ai-DOP\SourceCode\ZZYDOP\App\src\static\tab" GRAY = (144, 147, 153, 255) # #909399 NAVY = (47, 58, 82, 255) # #2F3A52 def canvas(): img = Image.new("RGBA", (SIZE, SIZE), (0, 0, 0, 0)) return img, ImageDraw.Draw(img) def save(img, name): import os os.makedirs(OUT, exist_ok=True) img = img.resize((81, 81), Image.LANCZOS) img.save(os.path.join(OUT, name)) def lw(w): return int(w * S) # ---------- home: house ---------- def draw_home(color): img, d = canvas() c = SIZE / 2 roof_top = 14 * S roof_half = 30 * S roof_y = 40 * S # roof (triangle outline via polygon) d.polygon([(c, roof_top), (c - roof_half, roof_y), (c + roof_half, roof_y)], fill=color) # body bx0, by0 = c - 22 * S, 42 * S bx1, by1 = c + 22 * S, 68 * S d.rectangle([bx0, by0, bx1, by1], fill=color) # door cutout dw = 9 * S d.rectangle([c - dw, 52 * S, c + dw, by1], fill=(0, 0, 0, 0)) return img # ---------- todo: clipboard with check ---------- def draw_todo(color): img, d = canvas() x0, y0, x1, y1 = 18 * S, 14 * S, 63 * S, 70 * S w = lw(4) # board outline (rounded approximated by rectangle) d.rectangle([x0, y0 + 4 * S, x1, y1], outline=color, width=w) # clip d.rectangle([30 * S, 10 * S, 51 * S, 20 * S], fill=color) # check mark pts = [(26 * S, 44 * S), (37 * S, 56 * S), (57 * S, 30 * S)] d.line(pts, fill=color, width=lw(5), joint="curve") return img # ---------- message: chat bubble ---------- def draw_message(color): img, d = canvas() x0, y0, x1, y1 = 13 * S, 16 * S, 68 * S, 56 * S r = 10 * S d.rounded_rectangle([x0, y0, x1, y1], radius=r, fill=color) # tail d.polygon([(26 * S, y1 - 2 * S), (26 * S, 72 * S), (42 * S, y1 - 2 * S)], fill=color) # dots for i in range(3): cx = (27 + i * 13.5) * S cy = (y0 + y1) / 2 rr = 3.2 * S d.ellipse([cx - rr, cy - rr, cx + rr, cy + rr], fill=(0, 0, 0, 0)) return img # ---------- mine: person ---------- def draw_mine(color): img, d = canvas() c = SIZE / 2 # head hr = 12 * S hy = 28 * S d.ellipse([c - hr, hy - hr, c + hr, hy + hr], fill=color) # shoulders (half ellipse) sw = 26 * S sy0 = 46 * S sy1 = 88 * S d.pieslice([c - sw, sy0, c + sw, sy1], start=180, end=360, fill=color) d.rectangle([c - sw, (sy0 + sy1) / 2, c + sw, sy1], fill=(0, 0, 0, 0)) # re-draw shoulders as chord + body rect to horizon d.pieslice([c - sw, sy0, c + sw, sy1], start=180, end=360, fill=color) return img def main(): variants = {"": GRAY, "-active": NAVY} drawers = {"home": draw_home, "todo": draw_todo, "message": draw_message, "mine": draw_mine} for name, fn in drawers.items(): for suffix, color in variants.items(): save(fn(color), f"{name}{suffix}.png") print("done") if __name__ == "__main__": main()