From 76c1bbc737cb000753682c73899fe8f5b223f136 Mon Sep 17 00:00:00 2001 From: EMRG Evolution Date: Tue, 11 Aug 2026 18:47:01 +0800 Subject: [PATCH 1/3] =?UTF-8?q?emrg:=20app=20icon=20finalization=20?= =?UTF-8?q?=E2=80=94=20Branch=20Emergence=20SVG=20design=20source=20+=20ge?= =?UTF-8?q?n-assets=20pipeline=20(rant=202026-08-11T18:28:09)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-release.yml | 21 +++ .gitignore | 7 + packaging/assets/icon-256.png | Bin 2120 -> 0 bytes packaging/assets/icon-512.png | Bin 5397 -> 0 bytes packaging/assets/icon.icns | Bin 42070 -> 0 bytes packaging/assets/icon.ico | Bin 4596 -> 0 bytes packaging/assets/icon.png | Bin 14810 -> 0 bytes packaging/assets/icon.svg | 121 ++++++++++++++++ packaging/gen-assets.sh | 214 ++++++++++++++-------------- 9 files changed, 253 insertions(+), 110 deletions(-) delete mode 100644 packaging/assets/icon-256.png delete mode 100644 packaging/assets/icon-512.png delete mode 100644 packaging/assets/icon.icns delete mode 100644 packaging/assets/icon.ico delete mode 100644 packaging/assets/icon.png create mode 100644 packaging/assets/icon.svg diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index c014c856..7b2c4bae 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -153,6 +153,27 @@ jobs: shell: bash run: bash packaging/build-runtime.sh + # ── 图标资产生成(rant 2026-08-11T18:28:09:仓库只保留 icon.svg 设计源, + # png/icns/ico 由 CI 构建时现生成,必须先于 GUI 构建执行)── + - name: Generate icon assets (icon.svg → png/icns/ico) + shell: bash + run: | + set -euo pipefail + if command -v rsvg-convert >/dev/null 2>&1; then + echo "rsvg-convert already available" + elif [ "$RUNNER_OS" = "Linux" ]; then + sudo apt-get update -qq && sudo apt-get install -y -qq librsvg2-bin + elif [ "$RUNNER_OS" = "macOS" ]; then + brew install librsvg + else + echo "no rsvg-convert; gen-assets.sh will fall back to Chrome/Edge headless" + fi + bash packaging/gen-assets.sh + # 产物必须存在(GUI 构建引用 ../packaging/assets/*.png/icns/ico) + test -s packaging/assets/icon.png + test -s packaging/assets/icon.icns + test -s packaging/assets/icon.ico + # ── GUI dist(electron-builder;linux extraResources runtime §5 R64)── - name: Build GUI (electron-builder) working-directory: emrg/gui diff --git a/.gitignore b/.gitignore index df54b9f7..98bba0a6 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,10 @@ node_modules/ .pytest_cache/ /dist/ /emrg/gui/dist/ +# icon products generated at build time from packaging/assets/icon.svg (design source) +# (rant 2026-08-11T18:28:09: repo keeps only the SVG; png/icns/ico generated by gen-assets.sh) +packaging/assets/icon.png +packaging/assets/icon-512.png +packaging/assets/icon-256.png +packaging/assets/icon.icns +packaging/assets/icon.ico diff --git a/packaging/assets/icon-256.png b/packaging/assets/icon-256.png deleted file mode 100644 index 55902400241690faef5741215868bf756d08ddc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2120 zcmZuy3s6+o8UF8McQ3HG7kscjU@zhXlOk+_4x|Em!389#gi$IXQP_@JO=7_Z;r%$g zWL1hzlWAq5WMyc5V1(9`hc@oTEUq*fWKxSpkOf3Apzg{Lud?j+EF?1>+kfVqd(MBp z`~Uwr|Lb5{r*w^hMK!^3o3i= zm4<$EeR8`;+KE4noLGE-kVIZnuW!}^S$ zQdbs31qG$e;wA^39cxculGky?HVVigpD6f)KWh{TAZ&+?@pcvoZDPMHQ`St7pjSZ$ zqffU3LSm-^7~t)X>1r)+zarzqX<&`%RQ}FVvGYkDu#8mbdT@|G!{`SR9@HZC8ZC6~ zh&H?qL#^j@v?()nC#xrfgzeEfm}7x16-(IR8>3qViHkhQa@S50z!m3^@2z3ZVQkN{ z-x!L2anpwY{a2k&^RV{l4(gWDI-pp_~Jx7X!8Fl>{uII7grLotUH50E?~~U$t*y!LS&Hd>kJz-d=#L z(Ja}a1XGCpLuMljNc3kb_yX86Q#l|htJn%~Xvq0|y!F+(U z?~G#)pxLW58yaRlOV7Fhw+~_TW$XO@2x##KbR}~-Hf%oHzOim#HOdgIjL zj9~bTT`A+H;#561q(I`}#e_yPCKvV>LJP+^$_nhUtrYg2i}>ZxbbNLF_}|lJ7W!ku zG*h3X^-NKgh4ciuWrkqo2wNF7#VdNIXfDr(bF8ybhA?13P(lQGu6J7}G%rJqbtAH$ z1ulXi8PH{3v*M8w9OEWZ$e^KFjvCYN6L1NIV?BhL+>f zoq38`X+_XB#6|2^lVEzngi6xnGO$bdaxe8#^Olt*1!Jg-2l&KE5a4?gL;e z2;*G5|E7ij%%4Thaf4*s!vb`K15_=}Ob-MDoOjHfpsErn2tTU8b_t;Eg&BJVAjN4B zACX}BL4m5USFo>KV9s+k-#g|63jw}3!&I|Uo&o|esg{+z0nX)?4N;K;uO-g}M?u8| zscrQ@o}-g@A12(B=+CQMdczN(vHUOY;{t=p;z`Q9*#3E7QlL{T>k820*b+=hp-%=b zzp|XWc*mtC#Gkv^4!eJu{yrRS^I(19Y;Qphtc>BaLW$d1b)KpLsB)P}JI)hR!Q*sqd6 zu*sF5FVFzb*^xEgwLk8zSyK!_ak`~+j^C+@$=xe(3Uu_FUwN|_Xn(a^`6l!7k-jCK zK)<05pK%5k12V7`XPxFR_kSP(_Vm{I>wKK8ilV4(uwH9eN^eRT%A4%@3+^vAN+*Rb z2JvEwS>uheXsommXAo1Nng@7OXzRvx`3@`oBmIa9)NCX?AfZ&w6xKX58A)I!Ov32L zCH9X1359H--{`Om{kp7dSdP9S5bvw3`TDxpi;MZ&c8Wk~hs0d62H0kkOLmZr68;8i z+~MBcyvLq13mODo@OENv>ry*x1Nb_9ZpZve3V>5PTgjSF#P@O62-SG+>&x%dNU`$g zm4@L!M+@+l>)qwP<`<$F*J6SN-F`7(ScCt6TokS!PW5rV3mgtgnOT9uMib$1$6MrS zYa$HpMAM3A>YHZ!F&tZyG} zn>PCYYrOZs@m|Mc(g3LL~A9cf+l`y}|m01{#o KwdZ4WW&Z&qlIv;! diff --git a/packaging/assets/icon-512.png b/packaging/assets/icon-512.png deleted file mode 100644 index bc6179cfc97159e1d0320cdbc446b368dd4a6311..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5397 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 diff --git a/packaging/assets/icon.png b/packaging/assets/icon.png deleted file mode 100644 index 794c9bcad0bae4f294d022d8dca0ac59c0f8a01f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14810 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 diff --git a/packaging/assets/icon.svg b/packaging/assets/icon.svg new file mode 100644 index 00000000..ee62a043 --- /dev/null +++ b/packaging/assets/icon.svg @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packaging/gen-assets.sh b/packaging/gen-assets.sh index 3f489548..533b8dc3 100644 --- a/packaging/gen-assets.sh +++ b/packaging/gen-assets.sh @@ -1,102 +1,84 @@ #!/usr/bin/env bash -# EMRG Phase 4 — generate packaging assets (icons). +# EMRG Phase 4 — generate packaging assets (icons) from the SVG design source. # -# Pure-stdlib approach (no PIL/ImageMagick dependency): -# 1. Python stdlib draws a 1024x1024 PNG (EMRG glyph: dark bg + green "E" + circuit node) +# Design source: packaging/assets/icon.svg ("Branch Emergence" — rant 2026-08-11T18:28:09) +# Pipeline: +# 1. Render icon.svg → 1024x1024 icon.png +# renderer priority: rsvg-convert (librsvg) → Chrome/Chromium headless → sips +# (sips 对 feGaussianBlur 支持有限 → 辉光丢失,仅作最后兜底并告警) # 2. iconutil (macOS) → .icns -# 3. Python stdlib → multi-size .ico (win) +# 3. Python stdlib (area-average box filter) → multi-size .ico (win) # 4. 512/256 PNG copies (linux) # # Output in packaging/assets/: -# icon.png (1024) icon-512.png icon-256.png icon.icns icon.ico +# icon.svg (design source, committed) icon.png (1024) icon-512.png +# icon-256.png icon.icns icon.ico (generated, gitignored) # # Run from repo root: bash packaging/gen-assets.sh set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" OUT="$ROOT/packaging/assets" +SVG="$OUT/icon.svg" mkdir -p "$OUT" -echo "==> generating 1024x1024 icon.png (pure stdlib)" +if [ ! -f "$SVG" ]; then + echo "ERROR: $SVG not found — design source missing" >&2 + exit 1 +fi + +echo "==> rendering icon.svg → 1024x1024 icon.png" +render_svg_to_png() { + # 1) rsvg-convert (librsvg) — full SVG + filter support + if command -v rsvg-convert >/dev/null 2>&1; then + echo " renderer: rsvg-convert" + rsvg-convert -w 1024 -h 1024 "$SVG" -o "$OUT/icon.png" + return 0 + fi + # 2) Chrome/Chromium headless --screenshot (full filter support) + for chrome in \ + "${CHROME_BIN:-}" \ + "google-chrome" "google-chrome-stable" "chromium" "chromium-browser" \ + "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \ + "/Applications/Chromium.app/Contents/MacOS/Chromium" \ + "/c/Program Files/Google/Chrome/Application/chrome.exe" \ + "/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe"; do + if [ -n "$chrome" ] && command -v "$chrome" >/dev/null 2>&1 || [ -x "$chrome" ] 2>/dev/null; then + echo " renderer: $chrome (headless)" + "$chrome" --headless --disable-gpu --hide-scrollbars \ + --screenshot="$OUT/icon.png" --window-size=1024,1024 \ + --default-background-color=00000000 "file://$SVG" >/dev/null 2>&1 + return 0 + fi + done + # 3) sips (macOS last resort) — 辉光(feGaussianBlur)可能丢失 + if command -v sips >/dev/null 2>&1; then + echo " ⚠️ renderer: sips (last resort) — glow may be lost (feGaussianBlur unsupported)" >&2 + sips -s format png "$SVG" --out "$OUT/icon.png" >/dev/null 2>&1 + return 0 + fi + echo "ERROR: no SVG renderer found (rsvg-convert / chrome / sips)" >&2 + return 1 +} +render_svg_to_png || exit 1 +# sanity: non-empty 1024x1024 PNG python3 - "$OUT/icon.png" <<'PYEOF' -import sys, struct, zlib, math - -path = sys.argv[1] -S = 1024 -# RGBA buffer (transparent bg) -buf = bytearray([0, 0, 0, 0]) * (S * S) - -def put(x, y, r, g, b, a=255): - if 0 <= x < S and 0 <= y < S: - i = (y * S + x) * 4 - buf[i] = r; buf[i+1] = g; buf[i+2] = b; buf[i+3] = a - -def fill_circle(cx, cy, rad, r, g, b, a=255): - # bounding box fill - x0, x1 = max(0, int(cx-rad)), min(S, int(cx+rad)+1) - y0, y1 = max(0, int(cy-rad)), min(S, int(cy+rad)+1) - r2 = rad*rad - for yy in range(y0, y1): - for xx in range(x0, x1): - dx, dy = xx-cx, yy-cy - if dx*dx + dy*dy <= r2: - put(xx, yy, r, g, b, a) - -def fill_rect(x0, y0, x1, y1, r, g, b, a=255): - for yy in range(max(0,y0), min(S,y1)): - for xx in range(max(0,x0), min(S,x1)): - put(xx, yy, r, g, b, a) - -def fill_round_rect(x0, y0, x1, y1, rad, r, g, b, a=255): - fill_rect(x0+rad, y0, x1-rad, y1, r, g, b, a) - fill_rect(x0, y0+rad, x1, y1-rad, r, g, b, a) - fill_circle(x0+rad, y0+rad, rad, r, g, b, a) - fill_circle(x1-rad, y0+rad, rad, r, g, b, a) - fill_circle(x0+rad, y1-rad, rad, r, g, b, a) - fill_circle(x1-rad, y1-rad, rad, r, g, b, a) - -# background: rounded square (EMRG brand: dark navy #0f172a) -fill_round_rect(64, 64, S-64, S-64, 180, 0x0f, 0x17, 0x2a) -# subtle outer ring -for rad in range(460, 480): - fill_circle(S//2, S//2, rad, 0x1e, 0x29, 0x3b, 255) - -# circuit: ring + node (self-evolving motif) -fill_circle(S//2, S//2, 300, 0x10, 0xb9, 0x81, 255) # green ring body -fill_circle(S//2, S//2, 250, 0x0f, 0x17, 0x2a, 255) # punch hole → ring -# 4 orbit nodes -for ang in (0, 90, 180, 270): - ox = S//2 + int(380 * math.cos(math.radians(ang))) - oy = S//2 + int(380 * math.sin(math.radians(ang))) - fill_circle(ox, oy, 40, 0x10, 0xb9, 0x81, 255) - -# "E" glyph (three bars + spine) — simple block letter -bar = 70 -spine_x0, spine_x1 = S//2 - 200, S//2 - 130 -top_y, mid_y, bot_y = S//2 - 200, S//2 - 30, S//2 + 140 -fill_rect(spine_x0, top_y, spine_x1, bot_y+bar, 0xf8, 0xfa, 0xfc) # vertical spine -fill_rect(spine_x0, top_y, S//2 + 200, top_y+bar, 0xf8, 0xfa, 0xfc) # top bar -fill_rect(spine_x0, mid_y, S//2 + 140, mid_y+bar, 0xf8, 0xfa, 0xfc) # middle bar -fill_rect(spine_x0, bot_y, S//2 + 200, bot_y+bar, 0xf8, 0xfa, 0xfc) # bottom bar - -def write_png(path, w, h, rgba): - def chunk(tag, data): - c = struct.pack(">I", len(data)) + tag + data - c += struct.pack(">I", zlib.crc32(tag + data) & 0xffffffff) - return c - raw = b"".join(b"\x00" + bytes(rgba[y*w*4:(y+1)*w*4]) for y in range(h)) - png = b"\x89PNG\r\n\x1a\n" - png += chunk(b"IHDR", struct.pack(">IIBBBBB", w, h, 8, 6, 0, 0, 0)) - png += chunk(b"IDAT", zlib.compress(raw, 9)) - png += chunk(b"IEND", b"") - with open(path, "wb") as f: - f.write(png) - -write_png(path, S, S, buf) -print(" wrote", path) +import sys, struct +data = open(sys.argv[1], "rb").read() +assert data[:8] == b"\x89PNG\r\n\x1a\n", "not a PNG" +pos = 8 +while pos < len(data): + ln = struct.unpack(">I", data[pos:pos+4])[0] + tag = data[pos+4:pos+8] + if tag == b"IHDR": + w, h = struct.unpack(">II", data[pos+8:pos+16]) + assert (w, h) == (1024, 1024), f"expected 1024x1024, got {w}x{h}" + print(f" icon.png OK: {w}x{h}") + break + pos += 12 + ln PYEOF -echo "==> resizing to 512/256 (stdlib scale-down)" +echo "==> resizing to 512/256 (stdlib area-average box filter)" python3 - "$OUT/icon.png" "$OUT" <<'PYEOF' import sys, zlib, struct @@ -124,20 +106,24 @@ def read_png(path): w, h, raw = read_png(src) stride = w * 4 -def sample(x, y): - i = y * stride + x * 4 - return raw[i], raw[i+1], raw[i+2], raw[i+3] - -def resize(nw, nh): +def resize_area(nw, nh): + """Area-average (box filter) downscale — better antialiasing than nearest.""" out = bytearray([0, 0, 0, 0]) * (nw * nh) for yy in range(nh): - sy = min(int(yy * h / nh), h-1) + y0 = yy * h // nh + y1 = max(y0 + 1, (yy + 1) * h // nh) for xx in range(nw): - sx = min(int(xx * w / nw), w-1) - i = sy * stride + sx * 4 - r, g, b, a = raw[i], raw[i+1], raw[i+2], raw[i+3] + x0 = xx * w // nw + x1 = max(x0 + 1, (xx + 1) * w // nw) + r = g = b = a = 0 + n = 0 + for sy in range(y0, y1): + for sx in range(x0, x1): + i = sy * stride + sx * 4 + r += raw[i]; g += raw[i+1]; b += raw[i+2]; a += raw[i+3] + n += 1 o = (yy * nw + xx) * 4 - out[o] = r; out[o+1] = g; out[o+2] = b; out[o+3] = a + out[o] = r // n; out[o+1] = g // n; out[o+2] = b // n; out[o+3] = a // n return bytes(out) def write_png(path, nw, nh, rgba): @@ -151,7 +137,7 @@ def write_png(path, nw, nh, rgba): for size in (512, 256): p = f"{outdir}/icon-{size}.png" - write_png(p, size, size, resize(size, size)) + write_png(p, size, size, resize_area(size, size)) print(" wrote", p) PYEOF @@ -160,11 +146,9 @@ ICONSET="$OUT/icon.iconset" mkdir -p "$ICONSET" # iconutil wants specific sizes for s in 16 32 128 256 512; do - d=$((s*2)) python3 - "$OUT/icon.png" "$ICONSET/icon_${s}x${s}.png" "$s" <<'PYEOF' import sys, zlib, struct src, dst, size = sys.argv[1], sys.argv[2], int(sys.argv[3]) -# reuse resize from above by re-reading data = open(src, "rb").read(); pos, w, h, idat = 8, 0, 0, b"" while pos < len(data): ln = struct.unpack(">I", data[pos:pos+4])[0]; tag = data[pos+4:pos+8]; chunk = data[pos+8:pos+8+ln] @@ -175,17 +159,23 @@ raw = zlib.decompress(idat) stride0 = w*4 + 1 raw = b"".join(raw[y*stride0+1:(y+1)*stride0] for y in range(h)) stride = w*4 -out = bytearray([0,0,0,0])*(size*size) -for yy in range(size): - sy = yy*h//size - for xx in range(size): - sx = min(xx*w//size, w-1) - i = sy*stride + sx*4 - o = (yy*size+xx)*4 - out[o]=raw[i]; out[o+1]=raw[i+1]; out[o+2]=raw[i+2]; out[o+3]=raw[i+3] +def resize_area(nw, nh): + out = bytearray([0,0,0,0])*(nw*nh) + for yy in range(nh): + y0 = yy*h//nh; y1 = max(y0+1, (yy+1)*h//nh) + for xx in range(nw): + x0 = xx*w//nw; x1 = max(x0+1, (xx+1)*w//nw) + r = g = b = a = n = 0 + for sy in range(y0, y1): + for sx in range(x0, x1): + i = sy*stride + sx*4 + r += raw[i]; g += raw[i+1]; b += raw[i+2]; a += raw[i+3]; n += 1 + o = (yy*nw+xx)*4 + out[o] = r//n; out[o+1] = g//n; out[o+2] = b//n; out[o+3] = a//n + return bytes(out) def chunk(tag, data): c = struct.pack(">I", len(data))+tag+data; c += struct.pack(">I", zlib.crc32(tag+data)&0xffffffff); return c -rgba = bytes(out) +rgba = resize_area(size, size) raw2 = b"".join(b"\x00"+rgba[y*size*4:(y+1)*size*4] for y in range(size)) png = b"\x89PNG\r\n\x1a\n"+chunk(b"IHDR", struct.pack(">IIBBBBB", size, size, 8, 6, 0, 0, 0))+chunk(b"IDAT", zlib.compress(raw2,9))+chunk(b"IEND", b"") open(dst, "wb").write(png) @@ -212,15 +202,19 @@ stride0 = w*4 + 1 raw = b"".join(raw[y*stride0+1:(y+1)*stride0] for y in range(h)) stride = w*4 -def resize(nw, nh): +def resize_area(nw, nh): out = bytearray([0,0,0,0])*(nw*nh) for yy in range(nh): - sy = min(yy*h//nh, h-1) + y0 = yy*h//nh; y1 = max(y0+1, (yy+1)*h//nh) for xx in range(nw): - sx = min(xx*w//nw, w-1) - i = sy*stride + sx*4 + x0 = xx*w//nw; x1 = max(x0+1, (xx+1)*w//nw) + r = g = b = a = n = 0 + for sy in range(y0, y1): + for sx in range(x0, x1): + i = sy*stride + sx*4 + r += raw[i]; g += raw[i+1]; b += raw[i+2]; a += raw[i+3]; n += 1 o = (yy*nw+xx)*4 - out[o]=raw[i]; out[o+1]=raw[i+1]; out[o+2]=raw[i+2]; out[o+3]=raw[i+3] + out[o] = r//n; out[o+1] = g//n; out[o+2] = b//n; out[o+3] = a//n return bytes(out) def png_bytes(nw, nh, rgba): @@ -231,7 +225,7 @@ def png_bytes(nw, nh, rgba): # ICO: header + directory + PNG-embedded entries sizes = [16, 24, 32, 48, 64, 128, 256] -imgs = [(s, png_bytes(s, s, resize(s, s))) for s in sizes] +imgs = [(s, png_bytes(s, s, resize_area(s, s))) for s in sizes] header = struct.pack(" Date: Tue, 11 Aug 2026 18:50:37 +0800 Subject: [PATCH 2/3] =?UTF-8?q?emrg:=20gen-assets=20=E2=80=94=20cygpath=20?= =?UTF-8?q?file=20URL=20for=20Windows=20Chrome/Edge=20fallback=20renderer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packaging/gen-assets.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packaging/gen-assets.sh b/packaging/gen-assets.sh index 533b8dc3..9346a4f7 100644 --- a/packaging/gen-assets.sh +++ b/packaging/gen-assets.sh @@ -36,6 +36,11 @@ render_svg_to_png() { return 0 fi # 2) Chrome/Chromium headless --screenshot (full filter support) + # Windows (Git Bash): convert /c/... → file:///C:/... so Chrome resolves the URL. + SVG_URL="file://$SVG" + if command -v cygpath >/dev/null 2>&1; then + SVG_URL="file:///$(cygpath -m "$SVG")" + fi for chrome in \ "${CHROME_BIN:-}" \ "google-chrome" "google-chrome-stable" "chromium" "chromium-browser" \ @@ -47,7 +52,7 @@ render_svg_to_png() { echo " renderer: $chrome (headless)" "$chrome" --headless --disable-gpu --hide-scrollbars \ --screenshot="$OUT/icon.png" --window-size=1024,1024 \ - --default-background-color=00000000 "file://$SVG" >/dev/null 2>&1 + --default-background-color=00000000 "$SVG_URL" >/dev/null 2>&1 return 0 fi done From 72248905b7c0f9401c356717fcdacc4104adb60f Mon Sep 17 00:00:00 2001 From: EMRG Evolution Date: Tue, 11 Aug 2026 18:54:12 +0800 Subject: [PATCH 3/3] =?UTF-8?q?emrg:=20gen-assets=20+=20CI=20=E2=80=94=20g?= =?UTF-8?q?uard=20iconutil=20to=20macOS=20only=20(Linux/Windows=20skip=20i?= =?UTF-8?q?cns)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/build-release.yml | 4 +++- packaging/gen-assets.sh | 28 ++++++++++++++++------------ 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 7b2c4bae..e1280546 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -171,7 +171,9 @@ jobs: bash packaging/gen-assets.sh # 产物必须存在(GUI 构建引用 ../packaging/assets/*.png/icns/ico) test -s packaging/assets/icon.png - test -s packaging/assets/icon.icns + if [ "$RUNNER_OS" = "macOS" ]; then + test -s packaging/assets/icon.icns + fi test -s packaging/assets/icon.ico # ── GUI dist(electron-builder;linux extraResources runtime §5 R64)── diff --git a/packaging/gen-assets.sh b/packaging/gen-assets.sh index 9346a4f7..a09d3d25 100644 --- a/packaging/gen-assets.sh +++ b/packaging/gen-assets.sh @@ -146,12 +146,13 @@ for size in (512, 256): print(" wrote", p) PYEOF -echo "==> iconutil → icon.icns (macOS)" -ICONSET="$OUT/icon.iconset" -mkdir -p "$ICONSET" -# iconutil wants specific sizes -for s in 16 32 128 256 512; do - python3 - "$OUT/icon.png" "$ICONSET/icon_${s}x${s}.png" "$s" <<'PYEOF' +echo "==> iconutil → icon.icns (macOS only; skipped on Linux/Windows)" +if command -v iconutil >/dev/null 2>&1; then + ICONSET="$OUT/icon.iconset" + mkdir -p "$ICONSET" + # iconutil wants specific sizes + for s in 16 32 128 256 512; do + python3 - "$OUT/icon.png" "$ICONSET/icon_${s}x${s}.png" "$s" <<'PYEOF' import sys, zlib, struct src, dst, size = sys.argv[1], sys.argv[2], int(sys.argv[3]) data = open(src, "rb").read(); pos, w, h, idat = 8, 0, 0, b"" @@ -185,12 +186,15 @@ raw2 = b"".join(b"\x00"+rgba[y*size*4:(y+1)*size*4] for y in range(size)) png = b"\x89PNG\r\n\x1a\n"+chunk(b"IHDR", struct.pack(">IIBBBBB", size, size, 8, 6, 0, 0, 0))+chunk(b"IDAT", zlib.compress(raw2,9))+chunk(b"IEND", b"") open(dst, "wb").write(png) PYEOF - cp "$ICONSET/icon_${s}x${s}.png" "$ICONSET/icon_${s}x${s}@2x.png" 2>/dev/null || true -done -# icns needs exact 16/32/128/256/512 + @2x -iconutil -c icns "$ICONSET" -o "$OUT/icon.icns" -rm -rf "$ICONSET" -echo " wrote $OUT/icon.icns" + cp "$ICONSET/icon_${s}x${s}.png" "$ICONSET/icon_${s}x${s}@2x.png" 2>/dev/null || true + done + # icns needs exact 16/32/128/256/512 + @2x + iconutil -c icns "$ICONSET" -o "$OUT/icon.icns" + rm -rf "$ICONSET" + echo " wrote $OUT/icon.icns" +else + echo " skipping icon.icns (iconutil unavailable — macOS only)" +fi echo "==> icon.ico (multi-size, win)" python3 - "$OUT/icon.png" "$OUT/icon.ico" <<'PYEOF'