Files
arcrun-collector/cmd/arcrun-tray/assets/store/gen-store-assets.py
T
Leo 7ecd740f82 品牌 icon 落地:托盤/app/msix/landing favicon 用 leo 的 CIS
用戶從 rag.arcrun.dev → install.arcrun.dev → 自己的 portal → 托盤,
四個地方應該看到同一個 icon。此前最不一致的就是托盤(Fyne 內建的通用
「儲存」圖示,main.go:1016 留著 TODO)。

素材真身=InkStoneCo/arcrun-cis/(leo 用 Claude Design 做的 CIS)。

托盤(trayicon.go,新檔)
- macOS:template 單色(純黑+alpha),系統依選單列深淺自動反色。
  ⚠️ fyne v2.5.3 只有 *theme.ThemedResource 才會走 systray.SetTemplateIcon
  (driver_desktop.go:169);傳一般 StaticResource 會走 SetIcon=不反色。
- Windows:完整墨底 icon(template 是 mac 專有)。
- 兩份都用 go:embed 內嵌,不讀外部路徑——打包後工作目錄不是原始碼目錄。
- 選單列用雙 chevron 而非完整方形字符:CIS 規定 26px 以下降級成 chevron,
  方塊裡的字符只佔高度 ~28%,22pt 下只剩 ~4px 會糊掉。

app 圖示
- icon.png 換成 CIS 1024 原生;icns 重產含 16→1024 全套 Retina 階梯。

msix(Store)
- 圖示改成預先產好、隨 repo 版控的 assets/store/(含 gen-store-assets.py 可重跑)。
- 修掉一個實際的變形 bug:舊版 `sips -z 150 310 icon.png` 會把方形 icon
  **橫向拉扁**成寬磚(實測產出的字符明顯變形),違反 CIS「never skew or stretch」。
  寬磚改用橫式 lockup 等比置中於墨底。
- 補 71x71/310x310/targetsize-16/24/32/48/256,manifest 一併宣告;
  BackgroundColor 從 transparent 改成品牌 Ink #17181A。

landing favicon(rag.arcrun.dev)
- LOGO_SVG 從琥珀金圓圈暫代圖換成 CIS 正式 mark(單色,CIS:彩色 chevron
  在產品裡代表「這條關係是活的」,用在 logo 會是謊話)。
- 修掉名實不符:`/favicon.ico` 過去回的是 SVG 位元組卻標 image/svg+xml
  (線上實測 200 但 type=image/svg+xml),老瀏覽器與抓圖服務畫不出來。
  現在 .ico 回真 ICO(16/32/48 三尺寸)、apple-touch-icon.png 回真 PNG(180)。
- 三個頁面(首頁/privacy/support)補上 icon link 宣告(此前完全沒有)。

⚠️ installer 這次沒動:`install.arcrun.dev` 的真身是
`installer/oauth-prototype/worker.js`(不在本分支,見 wiki decisions-summary
「installer 有兩個 worker,改錯=白做」),另立一筆處理。

實測證據
- mac .app 執行檔內 grep 到 tray-template.png 位元組(sha f6af940d,位移 14001472);
  Windows exe 內 grep 到 tray-windows.png(sha 59f4f1ac);各自平台只嵌自己那份
  (另一份被 linker 消掉=runtime.GOOS 編譯期常數,正確)。
- msix 重打包過 makemsix unpack 回讀驗證,包內 11 張圖示齊全。
- 已部署 arcrun-landing(版本 b79d19df)。繞快取實測 rag.arcrun.dev:
  favicon.ico→image/x-icon 1573B(3 icons,sha 151e645b=與本機產出同一顆)、
  apple-touch-icon.png→image/png 180x180、首頁 head 三個 link 宣告都在。
  ⚠️ 舊版 max-age=86400 的邊緣快取未 purge(無 zone token),24h 內自然過期。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-31 20:43:55 +08:00

109 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""重新產生 Microsoft Storemsix)的圖示素材。
素材真身=leo 的 CIS`InkStoneCo/arcrun-cis/`),本腳本只做「等比縮 + 置中合成」。
守 CIS 的 Don't:**不拉扁、不歪斜、不加第二個顏色**。
- 方形磚 → 用方形 icon`arcrun-icon-ink-1024.png`)等比縮。
- 寬磚 310×150 → 用**橫式 lockup**`arcrun-lockup-h-paper-on-ink.png`)置中於墨底。
不能拿方形 icon 硬拉成 310×150——舊版 `sips -z 150 310` 就是這樣把方形字符拉扁的。
- targetsize-16/24(工作列小圖)→ CIS 規定 26px 以下降級成 chevron
完整字符在這尺寸只剩約 4px 高,會糊掉。
用法(需要 Pillow):
python3 gen-store-assets.py
產物寫回本目錄、隨 repo 版控;`build-msix.sh` 只負責 cp 進包裡。
"""
import os
from pathlib import Path
from PIL import Image, ImageDraw
HERE = Path(__file__).resolve().parent
# CIS 住在 InkStoneCo 頂層。預設往上找,找不到時用 ARCRUN_CIS 指過去。
CIS = Path(os.environ["ARCRUN_CIS"]) if os.environ.get("ARCRUN_CIS") else None
if CIS is None:
for parent in HERE.parents:
cand = parent / "arcrun-cis"
if cand.is_dir():
CIS = cand
break
INK = (23, 24, 26, 255)
PAPER = (253, 252, 251, 255)
def load(name: str) -> Image.Image:
if CIS is None or not (CIS / name).exists():
raise SystemExit(
f"❌ 找不到 CIS 素材 {name}(找過 {CIS}\n"
f" 指過去:ARCRUN_CIS=/path/to/arcrun-cis python3 {Path(__file__).name}")
return Image.open(CIS / name).convert("RGBA")
def chevron_on_ink(size: int, inset: float = 0.20) -> Image.Image:
"""雙 chevronpaper)置中於墨底——給 26px 以下的小尺寸用。
幾何與 CIS `chevron-double.svg` 同一組座標(24-grid、stroke 2.8)。
先超取樣畫再縮,邊緣才不會鋸齒。
"""
ss = size * 16
unit = ss / 24.0
layer = Image.new("RGBA", (ss, ss), (0, 0, 0, 0))
d = ImageDraw.Draw(layer)
w = max(1, round(2.8 * unit))
for dx in (0, 7):
d.line([((5 + dx) * unit, 5 * unit),
((12 + dx) * unit, 12 * unit),
((5 + dx) * unit, 19 * unit)],
fill=PAPER, width=w, joint="curve")
art = layer.crop(layer.split()[3].getbbox())
target = ss * (1 - 2 * inset)
scale = target / max(art.size)
nw, nh = max(1, round(art.size[0] * scale)), max(1, round(art.size[1] * scale))
art = art.resize((nw, nh), Image.LANCZOS)
out = Image.new("RGBA", (ss, ss), INK)
out.paste(art, ((ss - nw) // 2, (ss - nh) // 2), art)
return out.resize((size, size), Image.LANCZOS)
def wide_tile(w: int, h: int, pad_ratio: float = 0.14) -> Image.Image:
"""寬磚:橫式 lockup 等比 fit 進墨底,四周留白(CIS clear space)。"""
lock = load("arcrun-lockup-h-paper-on-ink.png")
canvas = Image.new("RGBA", (w, h), INK)
lw, lh = lock.size
scale = min(w * (1 - 2 * pad_ratio) / lw, h * (1 - 2 * pad_ratio) / lh)
nw, nh = max(1, round(lw * scale)), max(1, round(lh * scale))
art = lock.resize((nw, nh), Image.LANCZOS)
canvas.paste(art, ((w - nw) // 2, (h - nh) // 2), art)
return canvas
def main() -> None:
square = load("arcrun-icon-ink-1024.png")
made = []
for name, s in [("Square44x44Logo", 44), ("StoreLogo", 50),
("Square71x71Logo", 71), ("Square150x150Logo", 150),
("Square310x310Logo", 310)]:
square.resize((s, s), Image.LANCZOS).save(HERE / f"{name}.png")
made.append((f"{name}.png", s, s))
# 工作列 / 開始功能表多尺寸:26px 以下用 chevronCIS 規定),其餘用方形 icon
for s in (16, 24, 32, 48, 256):
img = chevron_on_ink(s) if s <= 26 else square.resize((s, s), Image.LANCZOS)
img.save(HERE / f"Square44x44Logo.targetsize-{s}.png")
made.append((f"Square44x44Logo.targetsize-{s}.png", s, s))
wide_tile(310, 150).save(HERE / "Wide310x150Logo.png")
made.append(("Wide310x150Logo.png", 310, 150))
for n, w, h in made:
print(f"✅ {n}: {w}x{h}")
if __name__ == "__main__":
main()