93 lines
3.4 KiB
Python
93 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Generate simple PNG icons for tabBar using only stdlib"""
|
|
import struct, zlib, math, os
|
|
|
|
def save_png(img_data, w, h, filepath):
|
|
"""img_data: list of (r,g,b) tuples, row-major"""
|
|
def chunk(ctype, data):
|
|
c = ctype + data
|
|
return struct.pack('>I', len(data)) + c + struct.pack('>I', zlib.crc32(c) & 0xffffffff)
|
|
sig = b'\x89PNG\r\n\x1a\n'
|
|
ihdr = chunk(b'IHDR', struct.pack('>IIBBBBB', w, h, 8, 2, 0, 0, 0))
|
|
raw = b''
|
|
for row in img_data:
|
|
raw += b'\x00'
|
|
for r, g, b in row:
|
|
raw += bytes([r, g, b])
|
|
idat = chunk(b'IDAT', zlib.compress(raw, 9))
|
|
iend = chunk(b'IEND', b'')
|
|
with open(filepath, 'wb') as f:
|
|
f.write(sig + ihdr + idat + iend)
|
|
|
|
def draw_circle(img, w, h, cx, cy, radius, r, g, b, fill=True):
|
|
for y in range(h):
|
|
for x in range(w):
|
|
d = math.sqrt((x-cx)**2 + (y-cy)**2)
|
|
if fill and d <= radius:
|
|
img[y][x] = (r, g, b)
|
|
elif not fill and abs(d - radius) < 1.0:
|
|
img[y][x] = (r, g, b)
|
|
|
|
def solid_img(w, h, r, g, b):
|
|
return [[(r, g, b)] * w for _ in range(h)]
|
|
|
|
def home_icon(active):
|
|
img = solid_img(81, 81, 0, 0, 0)
|
|
base = (180, 180, 180) if not active else (7, 193, 96)
|
|
accent = (7, 193, 96) if active else (120, 120, 120)
|
|
# house shape: triangle roof + rectangle body
|
|
roof = [(40,15),(15,40),(66,40)] # simplified triangle roof points
|
|
for y in range(81):
|
|
for x in range(81):
|
|
# roof triangle
|
|
if y <= 40 and x >= 15 and x <= 66:
|
|
in_roof = (y - 15) >= abs(x - 40) * 0.8
|
|
else:
|
|
in_roof = False
|
|
# body rectangle
|
|
in_body = x >= 22 and x <= 60 and y >= 38 and y <= 66
|
|
if in_roof or in_body:
|
|
img[y][x] = accent
|
|
return img
|
|
|
|
def report_icon(active):
|
|
img = solid_img(81, 81, 0, 0, 0)
|
|
accent = (7, 193, 96) if active else (180, 180, 180)
|
|
for y in range(81):
|
|
for x in range(81):
|
|
# doc rectangle with folded corner
|
|
in_doc = x >= 20 and x <= 62 and y >= 12 and y <= 70
|
|
corner = x >= 46 and y <= 28 and (x - 46 + y - 28) <= 6
|
|
if in_doc and not corner:
|
|
img[y][x] = accent
|
|
if 28 <= y <= 50 and x >= 30 and x <= 52 and (y - 28) > abs(x - 41) * 0.7:
|
|
img[y][x] = (255,255,255) if active else (220,220,220)
|
|
return img
|
|
|
|
def mine_icon(active):
|
|
img = solid_img(81, 81, 0, 0, 0)
|
|
accent = (7, 193, 96) if active else (180, 180, 180)
|
|
cx, cy = 40, 36
|
|
r = 18
|
|
for y in range(81):
|
|
for x in range(81):
|
|
d = math.sqrt((x-cx)**2 + (y-cy)**2)
|
|
if d <= r:
|
|
img[y][x] = accent
|
|
# shoulders
|
|
for y in range(55, 75):
|
|
for x in range(15, 66):
|
|
d = math.sqrt((x-40)**2/900 + (y-62)**2/225)
|
|
if d <= 1:
|
|
img[y][x] = accent
|
|
return img
|
|
|
|
static = '/Users/wac/Desktop/www/_src/petstore/frontend/src/static'
|
|
save_png(home_icon(False), 81, 81, f'{static}/tab-home.png')
|
|
save_png(home_icon(True), 81, 81, f'{static}/tab-home-active.png')
|
|
save_png(report_icon(False), 81, 81, f'{static}/tab-report.png')
|
|
save_png(report_icon(True), 81, 81, f'{static}/tab-report-active.png')
|
|
save_png(mine_icon(False), 81, 81, f'{static}/tab-mine.png')
|
|
save_png(mine_icon(True), 81, 81, f'{static}/tab-mine-active.png')
|
|
print('done')
|