8f841eac by 柴进

:art: DMG 背景图: PIL 生成箭头 + 中文提示, 布局对齐

之前只有两个图标并排, 用户看不出来要拖拽. 现在在 DMG 挂载打开时:
- 中间一根灰箭头从 .app 指向 Applications
- 底部中文提示 "将左侧应用拖到右侧 Applications 即完成安装"
- 窗口/图标/箭头三者坐标对齐

实现:
- 用 PIL 在 staging 阶段生成 600x400 PNG, 放 .background/bg.png
  (dot 前缀让 Finder 默认隐藏)
- AppleScript 里 set background picture 用 HFS path (冒号分隔)
- 图标位置 {150,200} / {450,200} 与背景图箭头两端对齐

PIL 字体查找: PingFang (默认中文) -> STHeiti -> Helvetica -> 兜底,
在打包机上都会命中至少一个.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 063d58aa
...@@ -92,12 +92,54 @@ TMP_DMG="dist/.tmp_rw.dmg" ...@@ -92,12 +92,54 @@ TMP_DMG="dist/.tmp_rw.dmg"
92 STAGE="dist/.dmg_stage" 92 STAGE="dist/.dmg_stage"
93 VOL_NAME="ZB100ImageGenerator" 93 VOL_NAME="ZB100ImageGenerator"
94 94
95 # 1. 准备 staging: .app + Applications 快捷方式 95 # 1. 准备 staging: .app + Applications 快捷方式 + 背景图
96 rm -rf "$STAGE" 96 rm -rf "$STAGE"
97 mkdir -p "$STAGE" 97 mkdir -p "$STAGE/.background"
98 cp -R "dist/ZB100ImageGenerator.app" "$STAGE/" 98 cp -R "dist/ZB100ImageGenerator.app" "$STAGE/"
99 ln -s /Applications "$STAGE/Applications" 99 ln -s /Applications "$STAGE/Applications"
100 100
101 # 用 PIL 生成带箭头+中文提示的背景图 (600x400, 跟 DMG 窗口尺寸匹配)
102 DMG_BG_PATH="$STAGE/.background/bg.png" python3 <<'PYEOF'
103 import os
104 from PIL import Image, ImageDraw, ImageFont
105
106 W, H = 600, 400
107 img = Image.new('RGB', (W, H), color=(248, 248, 250))
108 d = ImageDraw.Draw(img)
109
110 # 中间箭头 (从 .app 指向 Applications)
111 arrow_y = 200
112 arrow_color = (120, 120, 125)
113 d.line([(260, arrow_y), (425, arrow_y)], fill=arrow_color, width=5)
114 d.polygon(
115 [(425, arrow_y - 14), (455, arrow_y), (425, arrow_y + 14)],
116 fill=arrow_color,
117 )
118
119 # 底部提示文字
120 def load_font(size):
121 for path in (
122 "/System/Library/Fonts/PingFang.ttc",
123 "/System/Library/Fonts/STHeiti Medium.ttc",
124 "/System/Library/Fonts/Helvetica.ttc",
125 ):
126 if os.path.exists(path):
127 try:
128 return ImageFont.truetype(path, size)
129 except Exception:
130 continue
131 return ImageFont.load_default()
132
133 font = load_font(22)
134 text = "将左侧应用拖到右侧 Applications 即完成安装"
135 bbox = d.textbbox((0, 0), text, font=font)
136 tw = bbox[2] - bbox[0]
137 d.text(((W - tw) // 2, 320), text, fill=(90, 90, 95), font=font)
138
139 img.save(os.environ['DMG_BG_PATH'])
140 print(f"[dmg] 背景图已生成: {os.environ['DMG_BG_PATH']}")
141 PYEOF
142
101 # 2. 先卸载可能残留的同名卷, 防止上次失败留下的挂载 143 # 2. 先卸载可能残留的同名卷, 防止上次失败留下的挂载
102 hdiutil detach "/Volumes/$VOL_NAME" -force >/dev/null 2>&1 || true 144 hdiutil detach "/Volumes/$VOL_NAME" -force >/dev/null 2>&1 || true
103 145
...@@ -121,12 +163,16 @@ tell application "Finder" ...@@ -121,12 +163,16 @@ tell application "Finder"
121 set current view of container window to icon view 163 set current view of container window to icon view
122 set toolbar visible of container window to false 164 set toolbar visible of container window to false
123 set statusbar visible of container window to false 165 set statusbar visible of container window to false
124 set the bounds of container window to {200, 120, 800, 470} 166 -- 窗口尺寸匹配背景图 600x400, 坐标系从屏幕左上角算
167 set the bounds of container window to {200, 120, 800, 520}
125 set theViewOptions to the icon view options of container window 168 set theViewOptions to the icon view options of container window
126 set arrangement of theViewOptions to not arranged 169 set arrangement of theViewOptions to not arranged
127 set icon size of theViewOptions to 128 170 set icon size of theViewOptions to 128
128 set position of item "ZB100ImageGenerator.app" of container window to {160, 170} 171 -- 设置背景图 (HFS path, 冒号分隔)
129 set position of item "Applications" of container window to {440, 170} 172 set background picture of theViewOptions to file ".background:bg.png"
173 -- 图标位置要跟背景图里的箭头对齐
174 set position of item "ZB100ImageGenerator.app" of container window to {150, 200}
175 set position of item "Applications" of container window to {450, 200}
130 update without registering applications 176 update without registering applications
131 delay 1 177 delay 1
132 close 178 close
......