pithos/scripts/make-icons.cjs

53 lines
2.5 KiB
JavaScript
Raw Normal View History

// Renders ui/icon.svg into the desktop app's icons: desktop/icons/icon.png (512 px,
// for Linux and the window) and desktop/icons/icon.ico (16-256 px, PNG-compressed
// entries, for Windows). Run with Electron, which brings its own renderer:
// npx electron scripts/make-icons.cjs
const { app, BrowserWindow } = require('electron');
const fs = require('node:fs');
const path = require('node:path');
const root = path.join(__dirname, '..');
const svg = fs.readFileSync(path.join(root, 'ui', 'icon.svg'), 'utf8');
const out = path.join(root, 'desktop', 'icons');
app.disableHardwareAcceleration();
app.on('window-all-closed', () => {});
app.whenReady().then(async () => {
// The page draws the SVG on a canvas at each size and hands back a PNG.
const win = new BrowserWindow({ show: false, webPreferences: { offscreen: true } });
await win.loadURL('data:text/html,<html><body></body></html>');
const src = `data:image/svg+xml;base64,${Buffer.from(svg).toString('base64')}`;
const render = async (size) => {
const url = await win.webContents.executeJavaScript(`new Promise((ok, fail) => {
const img = new Image(); img.onerror = () => fail(new Error('svg did not load'));
img.onload = () => { const c = document.createElement('canvas'); c.width = c.height = ${size};
const g = c.getContext('2d'); g.imageSmoothingQuality = 'high'; g.drawImage(img, 0, 0, ${size}, ${size}); ok(c.toDataURL('image/png')); };
img.src = ${JSON.stringify(src)};
})`);
return Buffer.from(url.split(',')[1], 'base64');
};
fs.mkdirSync(out, { recursive: true });
fs.writeFileSync(path.join(out, 'icon.png'), await render(512));
const sizes = [16, 24, 32, 48, 64, 128, 256];
const pngs = [];
for (const s of sizes) pngs.push(await render(s));
const header = Buffer.alloc(6);
header.writeUInt16LE(0, 0); header.writeUInt16LE(1, 2); header.writeUInt16LE(sizes.length, 4);
const dir = Buffer.alloc(16 * sizes.length);
let offset = 6 + dir.length;
sizes.forEach((s, i) => {
const e = i * 16;
dir.writeUInt8(s >= 256 ? 0 : s, e); dir.writeUInt8(s >= 256 ? 0 : s, e + 1);
dir.writeUInt8(0, e + 2); dir.writeUInt8(0, e + 3);
dir.writeUInt16LE(1, e + 4); dir.writeUInt16LE(32, e + 6);
dir.writeUInt32LE(pngs[i].length, e + 8); dir.writeUInt32LE(offset, e + 12);
offset += pngs[i].length;
});
fs.writeFileSync(path.join(out, 'icon.ico'), Buffer.concat([header, dir, ...pngs]));
win.destroy();
console.log('icons written to', out);
app.quit();
}).catch((e) => { console.error(e); app.exit(1); });