94 lines
2.8 KiB
Python
94 lines
2.8 KiB
Python
"""
|
||
Generate PassKeeper extension icons (16×16, 48×48, 128×128 PNG).
|
||
|
||
Requires Pillow (already a project dependency via qrcode[pil]):
|
||
python extension/make_icons.py
|
||
"""
|
||
import os
|
||
import math
|
||
from PIL import Image, ImageDraw
|
||
|
||
SIZES = [16, 48, 128]
|
||
OUT_DIR = os.path.join(os.path.dirname(__file__), 'icons')
|
||
BG_COLOR = '#1a73e8' # Google-blue background
|
||
FG_COLOR = '#ffffff' # White lock
|
||
|
||
|
||
def draw_icon(size: int) -> Image.Image:
|
||
img = Image.new('RGBA', (size, size), (0, 0, 0, 0))
|
||
draw = ImageDraw.Draw(img)
|
||
|
||
# Rounded-rectangle background
|
||
pad = max(1, size // 10)
|
||
draw.rounded_rectangle(
|
||
[pad, pad, size - pad - 1, size - pad - 1],
|
||
radius=max(2, size // 6),
|
||
fill=BG_COLOR,
|
||
)
|
||
|
||
# ── Lock body (rectangle with rounded bottom) ──────────────────────────
|
||
bx = size * 0.28
|
||
by = size * 0.50
|
||
bw = size * 0.44
|
||
bh = size * 0.36
|
||
draw.rounded_rectangle(
|
||
[bx, by, bx + bw, by + bh],
|
||
radius=max(1, int(size * 0.07)),
|
||
fill=FG_COLOR,
|
||
)
|
||
|
||
# Keyhole
|
||
kr = max(1, int(size * 0.07))
|
||
kx = size / 2
|
||
ky = by + bh * 0.40
|
||
draw.ellipse([kx - kr, ky - kr, kx + kr, ky + kr], fill=BG_COLOR)
|
||
# Small stem below the hole
|
||
stem_w = max(1, int(size * 0.06))
|
||
draw.rectangle(
|
||
[kx - stem_w, ky, kx + stem_w, ky + bh * 0.30],
|
||
fill=BG_COLOR,
|
||
)
|
||
|
||
# ── Shackle (arc) ──────────────────────────────────────────────────────
|
||
sw = max(1, int(size * 0.09)) # stroke width
|
||
slm = size * 0.28 # left margin of shackle oval
|
||
srm = size * 0.72 # right margin
|
||
st = size * 0.15 # top of shackle
|
||
sb = size * 0.58 # bottom of shackle (overlaps lock body top)
|
||
|
||
# Draw as thick arc by layering concentric arcs
|
||
for offset in range(sw):
|
||
f = offset / max(sw - 1, 1)
|
||
draw.arc(
|
||
[slm + offset, st + offset, srm - offset, sb - offset],
|
||
start=180, end=0,
|
||
fill=FG_COLOR,
|
||
width=1,
|
||
)
|
||
|
||
# Simpler approach: draw white arc with width parameter (Pillow 8+)
|
||
try:
|
||
draw.arc(
|
||
[slm, st, srm, sb],
|
||
start=180, end=0,
|
||
fill=FG_COLOR,
|
||
width=sw,
|
||
)
|
||
except TypeError:
|
||
pass # older Pillow — arcs from the loop above are sufficient
|
||
|
||
return img
|
||
|
||
|
||
def main():
|
||
os.makedirs(OUT_DIR, exist_ok=True)
|
||
for s in SIZES:
|
||
path = os.path.join(OUT_DIR, f'icon{s}.png')
|
||
draw_icon(s).save(path, 'PNG')
|
||
print(f' OK {path}')
|
||
print('Icons generated.')
|
||
|
||
|
||
if __name__ == '__main__':
|
||
main()
|