50 lines
2.1 KiB
JavaScript
50 lines
2.1 KiB
JavaScript
#!/usr/bin/env node
|
|
// 生成托盘深浅色单色图标 (W-THE-01):
|
|
// src-tauri/icons/tray-light.png 深色字形 —— 浅色任务栏用
|
|
// src-tauri/icons/tray-dark.png 白色字形 —— 深色任务栏用
|
|
//
|
|
// 做法: 不能只用 alpha 通道做剪影 —— 源图标是「深色圆角方块 + 白色 i」,
|
|
// 整个方块都是不透明的, 只取 alpha 会得到一块纯色方块, i 字母细节全丢。
|
|
// 这里按**亮度**映射, 保留字母结构:
|
|
// 深色字形: alpha = (255-L)/255 → 方块保留深色, 白色 i 镂空透出任务栏
|
|
// 浅色字形: alpha = max(L,40)/255 → i 白色高亮, 方块留一点淡淡衬底
|
|
// 产物已提交进仓库, 仅图标变更时需要重跑: node scripts/gen-tray-icons.mjs
|
|
import sharp from 'sharp'
|
|
import { fileURLToPath } from 'node:url'
|
|
import path from 'node:path'
|
|
|
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
|
|
const src = path.join(root, 'src-tauri', 'icons', '128x128.png')
|
|
const outDir = path.join(root, 'src-tauri', 'icons')
|
|
|
|
const targets = [
|
|
{ file: 'tray-light.png', rgb: [31, 31, 31], mode: 'dark-glyph' }, // 深色字形 (浅色任务栏)
|
|
{ file: 'tray-dark.png', rgb: [250, 250, 250], mode: 'light-glyph' }, // 白色字形 (深色任务栏)
|
|
]
|
|
|
|
for (const t of targets) {
|
|
const { data, info } = await sharp(src)
|
|
.resize(32, 32, { fit: 'contain', background: { r: 0, g: 0, b: 0, alpha: 0 } })
|
|
.ensureAlpha()
|
|
.raw()
|
|
.toBuffer({ resolveWithObject: true })
|
|
const out = Buffer.alloc(info.width * info.height * 4)
|
|
for (let i = 0; i < info.width * info.height; i++) {
|
|
const r = data[i * 4]
|
|
const g = data[i * 4 + 1]
|
|
const b = data[i * 4 + 2]
|
|
const a = data[i * 4 + 3]
|
|
const lumi = 0.2126 * r + 0.7152 * g + 0.0722 * b
|
|
const alpha =
|
|
t.mode === 'dark-glyph' ? (a * (255 - lumi)) / 255 : (a * Math.max(lumi, 40)) / 255
|
|
out[i * 4] = t.rgb[0]
|
|
out[i * 4 + 1] = t.rgb[1]
|
|
out[i * 4 + 2] = t.rgb[2]
|
|
out[i * 4 + 3] = Math.round(alpha)
|
|
}
|
|
await sharp(out, { raw: { width: info.width, height: info.height, channels: 4 } })
|
|
.png()
|
|
.toFile(path.join(outDir, t.file))
|
|
console.log('generated', t.file)
|
|
}
|