From 99a06d533b513b075beefcc32e58a340a610fe6f Mon Sep 17 00:00:00 2001 From: janik Date: Wed, 15 Jul 2026 14:55:09 +0700 Subject: [PATCH] Redraw toolbar icons: full-canvas copper ohm glyph, add generator The previous 24 px icons were a copper square with a tiny knocked-out ohm that was unreadable in the toolbar. tools/gen_icons.py renders the glyph supersampled from DejaVu Sans Bold in theme-specific copper shades (plus the 64 px PCM listing icon). Co-Authored-By: Claude Fable 5 --- icons/fill_res_24_dark.png | Bin 435 -> 1286 bytes icons/fill_res_24_light.png | Bin 435 -> 1197 bytes tools/gen_icons.py | 56 ++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 tools/gen_icons.py diff --git a/icons/fill_res_24_dark.png b/icons/fill_res_24_dark.png index e0ec6b1cc91e9e744d1c8d5d88ec15378839ab87..f583c2995d401dbed2d158a0255cd2fda3d184ca 100644 GIT binary patch delta 1267 zcmV>ZiA(@X$C0Wy|6TQ$Pu6cg->ynW3tSWhL%$*(H zyVMD0rIFH34A`@w|D*5dz933vo4bpSUTDV0dxytfS&j^|W5cJr3eLehjW{bw(X&)N zOn$m}`O4#!V>N?_tg_M|@b$pkQ}XQoX3ID_meTbgo+Y58(maVM^D3+Qj3s+fJ$Bu2q5Q- zBj?f@)YPU|Ke}yF{;cF#VnebZ&(W+AE1AW0+fmhOwVY2|h!}-}AWI61IN2JuHfD)b zDiwjCQaG8DQFMtV26(uIs)4HPSl=QyU`c418Gq!AF_04cE#-sx9McgAtThgFTWBgV z<$P!6QVRp1YCq4lkGLs;h>|R63@9pOz(vf`400Y~p`CDNvJjg&MoFselPRr`B^p^u zAy|xC^K$%KT6@T_Eh{Uu^`yDXQ#nS#{DsW7M*Jd9sg(nQiV`DT+b3reZOjrur~nC* z2!CL25T~-EL^q66R7!oBq2@1e#ts4YJTU!DJ%}e)l^nT6sSzgB=> z9JX`o=T98A5JzZc)8zwQ1$$c<86!Gt%C2sN>DRqeo4=RKug$!U%#9B9TaNw~0egZt zHLk4{FwEYHf?a(te|$B28zlUZ5&GlAOMhF+W&b+{SQ{sXeb>@N{8tq5QyUMBPIpoT zfZtCY^wxLTJ%5LdFpaF;WzRZphPQQ5KO0@Ej0d)Tuq~TKGYjq+M-}>qeNQ-G4== zj}7dS>CC8U@agW7vpI;;L@>mFL1b3jN}p9$I_)}iarNq+-HQ(nB5MHj8Neunq5>pC z)asl<6DEcVKp>uRag8o$fR;CyWi!rTCJ*MEB(qW d;zx`S;vY@Oijc9=vVQ;o002ovPDHLkV1k@gV(9V>bE-^7K zFf1TwbaZfYIxjD6VRUe8Z***FVlHoTXD^k6l7D&>4}x!>pausDcdmwz zAP_Z>3J7V*1xmTxE}7=8xtcO5d#<0FY%>2pJK4=&u-1|%D{1j?b-D^Pfg0c~sAqr| zptX0=3FV+5H%P>9fI~-v2f(qIq?0xsij!!aOOYDLT3oZ8HCS}#^YHQ#o?&UA|7d^V zm8z`oHz<~U-hc0J`5E?geOiO9qcbXNbxbs3r*Wxm(;E~^K7+?Q-n!S5TR2}4ST+t$ zsBZ2Ok3zh%j~RcuGZ;PvU}B=L55|K&HjY$%YJ;%Xoz~y4J#E|aqv@ZiB#~=O)<9y; zHP2atRuXfr2!OT}lS~$pT$Y%VB>GS2%jE5u(9e@!EfX(NN8mT76aWAK07*qoM6N<$ Ef>s2tt^fc4 diff --git a/icons/fill_res_24_light.png b/icons/fill_res_24_light.png index 4f7c1d060eae288ae1120523c8128c2cc7be569d..363e63f64f6e6f667ea185ce5e4bb4902ef3b30b 100644 GIT binary patch delta 1178 zcmV;L1ZDfP1FZ>=BYy;RNklnqfsQ7a<_}2}VPxn~ zHwj)u;I0uUi3rt&1QG?owikiWO_$1M7Fo1<(M4TU5bRPBv|aUMntQS3u5O9BwK_B3 zeBXKBc+bo?PP$?Qy%)oobDs0Ozt5Q=+{A{4z|}D@ssP5?n}5}y#5 z-vOrp-3+G+GVG1cqZ^SAoPf9WyHBrJFVF|o>uLoS2LRDUCi+=4ogg}Y3V`pv(`~d+ zNi6M=ot4LX9KGm8x0GUb2Gp)gwoXz>i7?*ua&YhHxzF>vH*#R9vPE%p=d#y(Vt2q; z8ks;<6A(p?T7RVwMW#?8P@x!es8b`;*YOP|@0DT>7zKE~;nThze(A{IvVU#Hl{em;8vrMEtdHm2U*GpQ zTAgGz8_?dEU9BmH_KZ$HyU;KkeX89}M5QIpW2-vIRORBir_Kcf1+|e3u1^QIm0Dx>{ zpqR5%b4<6HQ#&KYrJTIW`tn8eBLRV_jaNb|wnNWWZDbzHqV~vFfK@f@X*moQ4|Fc00RpeTm3k zQkx_|x1~OaA;gq=C06|`+&c*k(_z4svol}TGnwcuu)U&^q$;JD?|XBg@`PayKY%!A zKYzRrk-a&UQ+BD9)(&+jotgJ7f4G1Amnbg$N%p(aMHb9}zJVX6jz{MdH6L6kN|A z7fToRe=?bbhGjr_a10zxG5B=Lhzu_e0S9WQQTLsCkc^#8gKs6iX!SSFd9uMbw*!N?(cC06H2(%kwn0|-k6a1 z)=&fo1Em0#&Q=PaW|veK()@k$N*s&$YkDVtzH_PNV-<3kik?Z3wRO sx8z!@0@dNx`)*&uUm45vU*P`+8xzql>5_GXIsgCw07*qoM6N<$f_N`V7ytkO delta 410 zcmV;L0cHNJ39|!`BYyxobVXQnQ*UN;cVTj608L?ZaBOdMY-wU3c4cyNX>V>bE-^7K zFf1TwbaZfYIxjD6VRUe8Z***FVlHoTXD^kwKF)%PZVPIgG<3IKK zXOI9R$Ollvw=*y>SX0U2M;RCxJVBPgT$(~f!x^AvC4(3+3qZj_Z6J$m0l8t04=~Zn zU=%QF0r44)ph6BF1{LQ-239UUhWiJXGJJXUfVy#@6;RB;C#A;l=jT@jv-By%Y9rnP zR!%;KhsW14+<)FR8_cG95HbA!$Drz(%pj?{KtN;K2 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()