PRA-only-demo/scripts/generate-icon.mjs

79 lines
2.4 KiB
JavaScript
Raw Normal View History

import fs from "node:fs";
import path from "node:path";
import process from "node:process";
import { PNG } from "pngjs";
const root = process.cwd();
const output = path.join(root, "build", "icon.ico");
const size = 256;
const png = new PNG({ width: size, height: size });
const glyph = [
"0111000000",
"1000100000",
"1000100000",
"1000100000",
"1111100000",
"1000100000",
"1000100000",
"1000100000",
"1000100000",
"1000100000"
];
function insideRoundedSquare(x, y, radius) {
const clampX = Math.min(Math.max(x, radius), size - 1 - radius);
const clampY = Math.min(Math.max(y, radius), size - 1 - radius);
return (x - clampX) ** 2 + (y - clampY) ** 2 <= radius ** 2;
}
for (let y = 0; y < size; y += 1) {
for (let x = 0; x < size; x += 1) {
const index = (size * y + x) << 2;
const visible = insideRoundedSquare(x, y, 34);
const gradient = (x + y) / (2 * (size - 1));
png.data[index] = visible ? Math.round(37 + (30 - 37) * gradient) : 0;
png.data[index + 1] = visible ? Math.round(99 + (58 - 99) * gradient) : 0;
png.data[index + 2] = visible ? Math.round(235 + (138 - 235) * gradient) : 0;
png.data[index + 3] = visible ? 255 : 0;
if (visible) {
const glyphX = Math.round((x - 78) / 10);
const glyphY = Math.round((y - 68) / 12);
if (glyphY >= 0 && glyphY < glyph.length && glyphX >= 0 && glyphX < glyph[glyphY].length && glyph[glyphY][glyphX] === "1") {
png.data[index] = 255;
png.data[index + 1] = 255;
png.data[index + 2] = 255;
png.data[index + 3] = 255;
}
}
}
}
const chunks = [];
png.pack()
.on("data", (chunk) => chunks.push(chunk))
.on("end", () => {
const image = Buffer.concat(chunks);
const directory = Buffer.alloc(6);
directory.writeUInt16LE(0, 0);
directory.writeUInt16LE(1, 2);
directory.writeUInt16LE(1, 4);
const entry = Buffer.alloc(16);
entry[0] = 0;
entry[1] = 0;
entry[2] = 0;
entry[3] = 0;
entry.writeUInt16LE(1, 4);
entry.writeUInt16LE(32, 6);
entry.writeUInt32LE(image.length, 8);
entry.writeUInt32LE(22, 12);
fs.mkdirSync(path.dirname(output), { recursive: true });
fs.writeFileSync(output, Buffer.concat([directory, entry, image]));
console.log(`[icon] generated ${output} (${image.length + 22} bytes)`);
})
.on("error", (error) => {
console.error(error);
process.exitCode = 1;
});