'use strict'; const fs = require('fs'); const path = require('path'); const zlib = require('zlib'); function crc32(buf) { let c = ~0; for (let i = 0; i < buf.length; i += 1) { c ^= buf[i]; for (let k = 0; k < 8; k += 1) c = (c >>> 1) ^ (0xedb88320 & -(c & 1)); } return ~c >>> 0; } function chunk(type, data) { const body = Buffer.concat([Buffer.from(type), data]); const out = Buffer.alloc(8 + body.length); out.writeUInt32BE(data.length, 0); body.copy(out, 4); out.writeUInt32BE(crc32(body), 8 + data.length); return out; } function png(size) { const raw = Buffer.alloc((size * 4 + 1) * size); for (let y = 0; y < size; y += 1) { const row = y * (size * 4 + 1); raw[row] = 0; for (let x = 0; x < size; x += 1) { const nx = x / (size - 1); const ny = y / (size - 1); const onX = Math.abs(nx - ny) < 0.16 || Math.abs(nx - (1 - ny)) < 0.16; const margin = size * 0.18; const inside = x > margin && y > margin && x < size - margin && y < size - margin; const i = row + 1 + x * 4; if (inside && onX) { raw[i] = 255; raw[i + 1] = 255; raw[i + 2] = 255; raw[i + 3] = 255; } else if (inside) { raw[i] = 32; raw[i + 1] = 122; raw[i + 2] = 214; raw[i + 3] = 255; } else { raw[i + 3] = 0; } } } const ihdr = Buffer.alloc(13); ihdr.writeUInt32BE(size, 0); ihdr.writeUInt32BE(size, 4); ihdr[8] = 8; ihdr[9] = 6; return Buffer.concat([ Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]), chunk('IHDR', ihdr), chunk('IDAT', zlib.deflateSync(raw)), chunk('IEND', Buffer.alloc(0)), ]); } function ico(images) { const count = images.length; const header = Buffer.alloc(6 + count * 16); header.writeUInt16LE(0, 0); header.writeUInt16LE(1, 2); header.writeUInt16LE(count, 4); let offset = 6 + count * 16; const parts = [header]; images.forEach((image, index) => { const entry = 6 + index * 16; header[entry] = image.size === 256 ? 0 : image.size; header[entry + 1] = image.size === 256 ? 0 : image.size; header.writeUInt16LE(1, entry + 4); header.writeUInt16LE(32, entry + 6); header.writeUInt32LE(image.data.length, entry + 8); header.writeUInt32LE(offset, entry + 12); offset += image.data.length; parts.push(image.data); }); return Buffer.concat(parts); } const root = path.join(__dirname, '..', 'assets'); fs.mkdirSync(root, { recursive: true }); const sizes = [16, 32, 48, 256]; const images = sizes.map((size) => ({ size, data: png(size) })); fs.writeFileSync(path.join(root, 'tray.png'), images[0].data); fs.writeFileSync(path.join(root, 'icon.png'), images[3].data); fs.writeFileSync(path.join(root, 'icon.ico'), ico(images)); console.log('wrote icons', images.map((image) => image.data.length).join(','));