jarvis/scripts/gen-icon.js
2026-04-13 22:01:33 +02:00

94 lines
3.1 KiB
JavaScript

'use strict';
const { app, BrowserWindow } = require('electron');
const fs = require('fs');
const path = require('path');
const OUT_DIR = path.join(__dirname, '..', 'build');
const OUT_PNG = path.join(OUT_DIR, 'icon.png');
const HTML = `<!DOCTYPE html><html><body style="margin:0;background:transparent">
<canvas id="c" width="1024" height="1024"></canvas>
<script>
const S = 1024;
const c = document.getElementById('c');
const g = c.getContext('2d');
const cx = S/2, cy = S/2;
const bg = g.createRadialGradient(cx, cy, 0, cx, cy, S/2);
bg.addColorStop(0, '#0a1826');
bg.addColorStop(0.6, '#030812');
bg.addColorStop(1, '#000000');
g.fillStyle = bg;
g.beginPath(); g.arc(cx, cy, S/2 - 8, 0, Math.PI * 2); g.fill();
g.strokeStyle = 'rgba(0,212,255,0.9)'; g.lineWidth = 12;
g.beginPath(); g.arc(cx, cy, S/2 - 36, 0, Math.PI * 2); g.stroke();
g.strokeStyle = 'rgba(0,212,255,0.95)'; g.lineWidth = 8;
for (let i = 0; i < 24; i++) {
const a = (i/24) * Math.PI * 2;
const r1 = S/2 - 60, r2 = S/2 - 88;
g.beginPath();
g.moveTo(cx + Math.cos(a)*r1, cy + Math.sin(a)*r1);
g.lineTo(cx + Math.cos(a)*r2, cy + Math.sin(a)*r2);
g.stroke();
}
g.shadowBlur = 40; g.shadowColor = 'rgba(0,212,255,1)';
g.strokeStyle = 'rgba(0,212,255,1)'; g.lineWidth = 16;
g.beginPath(); g.arc(cx, cy, 300, 0.3, 0.3 + Math.PI * 0.8); g.stroke();
g.beginPath(); g.arc(cx, cy, 300, 0.3 + Math.PI, 0.3 + Math.PI * 1.8); g.stroke();
g.lineWidth = 10;
g.beginPath(); g.arc(cx, cy, 216, -0.5, -0.5 + Math.PI * 0.7); g.stroke();
g.beginPath(); g.arc(cx, cy, 216, -0.5 + Math.PI, -0.5 + Math.PI * 1.7); g.stroke();
for (let i = 0; i < 6; i++) {
const a = (i/6) * Math.PI * 2;
const grad = g.createLinearGradient(
cx + Math.cos(a)*60, cy + Math.sin(a)*60,
cx + Math.cos(a)*190, cy + Math.sin(a)*190
);
grad.addColorStop(0, 'rgba(120,220,255,1)');
grad.addColorStop(1, 'rgba(0,180,255,0)');
g.strokeStyle = grad; g.lineWidth = 20;
g.beginPath();
g.moveTo(cx + Math.cos(a)*60, cy + Math.sin(a)*60);
g.lineTo(cx + Math.cos(a)*190, cy + Math.sin(a)*190);
g.stroke();
}
g.shadowBlur = 80;
const core = g.createRadialGradient(cx, cy, 0, cx, cy, 100);
core.addColorStop(0, 'rgba(255,255,255,1)');
core.addColorStop(0.3, 'rgba(180,240,255,1)');
core.addColorStop(1, 'rgba(0,212,255,0)');
g.fillStyle = core;
g.beginPath(); g.arc(cx, cy, 100, 0, Math.PI * 2); g.fill();
g.shadowBlur = 0;
g.fillStyle = '#ffffff';
g.beginPath(); g.arc(cx, cy, 32, 0, Math.PI * 2); g.fill();
window._png = c.toDataURL('image/png');
</script></body></html>`;
app.disableHardwareAcceleration();
app.whenReady().then(async () => {
fs.mkdirSync(OUT_DIR, { recursive: true });
const win = new BrowserWindow({
width: 1024, height: 1024, show: false,
webPreferences: { offscreen: true },
});
await win.loadURL('data:text/html;charset=utf-8,' + encodeURIComponent(HTML));
// Laisser le temps au canvas de rendre
await new Promise(r => setTimeout(r, 200));
const dataUrl = await win.webContents.executeJavaScript('window._png');
const b64 = dataUrl.replace(/^data:image\/png;base64,/, '');
fs.writeFileSync(OUT_PNG, Buffer.from(b64, 'base64'));
console.log('Icône générée →', OUT_PNG);
app.quit();
});