diff --git a/icons/fill_res_24_dark.png b/icons/fill_res_24_dark.png index e0ec6b1..f583c29 100644 Binary files a/icons/fill_res_24_dark.png and b/icons/fill_res_24_dark.png differ diff --git a/icons/fill_res_24_light.png b/icons/fill_res_24_light.png index 4f7c1d0..363e63f 100644 Binary files a/icons/fill_res_24_light.png and b/icons/fill_res_24_light.png differ diff --git a/tools/gen_icons.py b/tools/gen_icons.py new file mode 100644 index 0000000..169545f --- /dev/null +++ b/tools/gen_icons.py @@ -0,0 +1,56 @@ +"""Generate the plugin icons: a bold copper Ω filling the canvas. + + python tools/gen_icons.py + +Writes icons/fill_res_24_light.png (dark copper, for light toolbars), +icons/fill_res_24_dark.png (bright copper, for dark toolbars) and +resources/icon.png (64 px, for the PCM package listing). Rendered +supersampled with matplotlib's bundled DejaVu Sans Bold, then +downsampled for crisp antialiasing. +""" +from pathlib import Path + +import matplotlib +from PIL import Image, ImageDraw, ImageFont + +SS = 20 # supersampling factor +MARGIN = 1 # px kept clear per 24 px + +COLORS = { + "light": (158, 88, 28), # dark copper on light toolbar + "dark": (232, 162, 94), # bright copper on dark toolbar +} + + +def render(color: tuple[int, int, int], size: int) -> Image.Image: + canvas = size * SS + img = Image.new("RGBA", (canvas, canvas), (0, 0, 0, 0)) + draw = ImageDraw.Draw(img) + font_path = (Path(matplotlib.get_data_path()) + / "fonts" / "ttf" / "DejaVuSans-Bold.ttf") + # size the glyph so its ink box fills the canvas minus the margin + target = canvas - 2 * MARGIN * SS * size // 24 + font = ImageFont.truetype(str(font_path), target) + x0, y0, x1, y1 = font.getbbox("Ω") + scale = min(target / (x1 - x0), target / (y1 - y0)) + font = ImageFont.truetype(str(font_path), int(target * scale)) + x0, y0, x1, y1 = font.getbbox("Ω") + pos = ((canvas - (x1 - x0)) // 2 - x0, (canvas - (y1 - y0)) // 2 - y0) + draw.text(pos, "Ω", font=font, fill=color + (255,)) + return img.resize((size, size), Image.LANCZOS) + + +def main() -> None: + root = Path(__file__).resolve().parent.parent + for theme, color in COLORS.items(): + p = root / "icons" / f"fill_res_24_{theme}.png" + render(color, 24).save(p) + print(f"wrote {p}") + p = root / "resources" / "icon.png" + p.parent.mkdir(exist_ok=True) + render(COLORS["light"], 64).save(p) + print(f"wrote {p}") + + +if __name__ == "__main__": + main()