# -*- coding: utf-8 -*- """功能区 24 图标最终版:Lucide 开源图标库(ISC 可商用,专业设计)。 管线:jsdelivr 拉取 lucide-static SVG → 替换 currentColor 为语义色 → Edge 无头渲染 256px → 缩 64px。 文件名不变(bin\\Debug\\icons\\*.png),Designer.cs 的 FromFile 路径不用改。 404 的图标名会打印出来供换名重跑。""" import io import os import re import shutil import subprocess import tempfile from PIL import Image ROOT = r"C:\Users\099978\Documents\SharpDevelop Projects\成套报价软件" PNG_DIR = os.path.join(ROOT, "成套报价软件", "bin", "Debug", "icons") SVG_DIR = os.path.join(ROOT, "成套报价软件", "icons", "svg", "lucide") EDGE = r"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" VER = "0.525.0" URL = "https://cdn.jsdelivr.net/npm/lucide-static@%s/icons/%%s.svg" % VER INK = "#3D434A" # 墨青灰(默认) GRN = "#217346" # 强调绿(=功能区 AccentColor) COP = "#C8791E" # 铜橙 RED = "#D64541" # 警示红 BLU = "#2B579A" # 点缀蓝 # 按钮 → (lucide 图标名, 颜色) BIND = { "new-project": ("file-plus-2", INK), "edit-project": ("file-pen", INK), "delete-project": ("trash-2", RED), "open-project": ("folder-open", INK), "copy-project": ("files", INK), "import-project": ("import", GRN), "export-project": ("export", BLU), "open-quote": ("folder-open", INK), # button9 同款 "edit-quote": ("file-pen", INK), # button10 同款 "save": ("save", GRN), "import-quote": ("file-down", GRN), "report": ("table-cells", INK), "busbar": ("align-justify", COP), # 三横线=三根铜排 "factor": ("sliders-horizontal", INK), "sort-components": ("arrow-up-narrow-wide", INK), "template-cost": ("badge-japanese-yen", GRN), "cad-grab": ("drafting-compass", INK), "login": ("log-in", GRN), "password": ("key-round", INK), "member": ("id-card", INK), "company": ("building-2", INK), "save-layout": ("layout-template", INK), "backup": ("database-backup", GRN), "restore": ("archive-restore", INK), } def fetch(name): import urllib.request req = urllib.request.Request(URL % name, headers={"User-Agent": "Mozilla/5.0"}) with urllib.request.urlopen(req, timeout=30) as r: return r.read().decode("utf-8") def process(svg_text, color): # 去注释/class,currentColor→语义色,尺寸改 256(viewBox 24 不动) svg_text = re.sub(r"\s*", "", svg_text, flags=re.S) svg_text = svg_text.replace('class="lucide lucide-%s"' % "", "") svg_text = re.sub(r'\s+class="[^"]*"', "", svg_text) svg_text = svg_text.replace('stroke="currentColor"', 'stroke="%s"' % color) svg_text = svg_text.replace('width="24"', 'width="256"').replace('height="24"', 'height="256"') return svg_text def render_edge(name, svg_text): sp = os.path.join(SVG_DIR, name + ".svg") with io.open(sp, "w", encoding="utf-8") as f: f.write(svg_text) tmp = tempfile.mkdtemp(prefix="lucide_") try: tmp_svg = os.path.join(tmp, "i.svg") tmp_png = os.path.join(tmp, "i.png") shutil.copy(sp, tmp_svg) subprocess.run( [EDGE, "--headless", "--disable-gpu", "--no-sandbox", "--user-data-dir=" + os.path.join(tmp, "p"), "--screenshot=" + tmp_png, "--window-size=256,256", "--default-background-color=00000000", "file:///" + tmp_svg.replace("\\", "/")], capture_output=True, timeout=40) if not os.path.exists(tmp_png): raise RuntimeError("Edge 渲染失败") Image.open(tmp_png).convert("RGBA").resize((64, 64), Image.LANCZOS)\ .save(os.path.join(PNG_DIR, name + ".png")) finally: shutil.rmtree(tmp, ignore_errors=True) def main(): os.makedirs(SVG_DIR, exist_ok=True) os.makedirs(PNG_DIR, exist_ok=True) ok, missing = 0, [] for name, (icon, color) in BIND.items(): try: raw = fetch(icon) if "