95 lines
2.8 KiB
JavaScript
95 lines
2.8 KiB
JavaScript
'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(','));
|