+
+${orbHtml(116, 'position:absolute;left:24px;top:26px;box-shadow:0 6px 18px rgba(0,0,0,.6)')}
+

+
EuerChat
+
IRC & LIVESTREAM
+
`;
// ---------------------------------------------------------------------------
// Rendering mit Edge (Chrome DevTools Protocol)
@@ -198,23 +181,21 @@ async function startEdge() {
await send('Page.enable');
await send('Emulation.setDefaultBackgroundColorOverride', { color: { r: 0, g: 0, b: 0, a: 0 } });
return {
- send,
- async html(markup, width, height) {
+ async render(markup, width, height) {
await send('Emulation.setDeviceMetricsOverride', { width, height, deviceScaleFactor: 1, mobile: false });
const doc = `${markup}`;
await send('Page.navigate', { url: 'data:text/html;base64,' + Buffer.from(doc).toString('base64') });
- await new Promise((r) => setTimeout(r, 500));
- await send('Runtime.evaluate', { expression: 'document.fonts.ready.then(()=>1)', awaitPromise: true });
- },
- async png() {
+ await new Promise((r) => setTimeout(r, 400));
+ await send('Runtime.evaluate', { expression: 'Promise.all([document.fonts.ready,...[...document.images].map(i=>i.decode())]).then(()=>1)', awaitPromise: true });
const r = await send('Page.captureScreenshot', { format: 'png', fromSurface: true });
return Buffer.from(r.data, 'base64');
},
- async eval(expression) {
- const r = await send('Runtime.evaluate', { expression, returnByValue: true, awaitPromise: true });
- return r.result?.value;
- },
close() { ws.close(); proc.kill(); },
+ async evaluate(expression) {
+ const r = await send('Runtime.evaluate', { expression, awaitPromise: true, returnByValue: true });
+ if (r.exceptionDetails) throw new Error(JSON.stringify(r.exceptionDetails));
+ return r.result.value;
+ },
};
}
@@ -243,45 +224,6 @@ function makeIco(frames) {
return Buffer.concat([header, ...entries, ...sorted.map((f) => f.png)]);
}
-function decodePng(buf) {
- let pos = 8;
- let width = 0, height = 0, colorType = 0;
- const idat = [];
- while (pos < buf.length) {
- const len = buf.readUInt32BE(pos);
- const type = buf.toString('ascii', pos + 4, pos + 8);
- const data = buf.subarray(pos + 8, pos + 8 + len);
- if (type === 'IHDR') { width = data.readUInt32BE(0); height = data.readUInt32BE(4); colorType = data[9]; }
- if (type === 'IDAT') idat.push(data);
- pos += 12 + len;
- }
- const bpp = colorType === 6 ? 4 : 3;
- const raw = zlib.inflateSync(Buffer.concat(idat));
- const stride = width * bpp;
- const px = Buffer.alloc(height * stride);
- for (let y = 0; y < height; y++) {
- const filter = raw[y * (stride + 1)];
- for (let x = 0; x < stride; x++) {
- const v = raw[y * (stride + 1) + 1 + x];
- const a = x >= bpp ? px[y * stride + x - bpp] : 0;
- const b = y > 0 ? px[(y - 1) * stride + x] : 0;
- const c = x >= bpp && y > 0 ? px[(y - 1) * stride + x - bpp] : 0;
- let out;
- if (filter === 0) out = v;
- else if (filter === 1) out = v + a;
- else if (filter === 2) out = v + b;
- else if (filter === 3) out = v + ((a + b) >> 1);
- else {
- const p = a + b - c;
- const pa = Math.abs(p - a), pb = Math.abs(p - b), pc = Math.abs(p - c);
- out = v + (pa <= pb && pa <= pc ? a : pb <= pc ? b : c);
- }
- px[y * stride + x] = out & 255;
- }
- }
- return { width, height, bpp, px };
-}
-
/** 24-Bit-BMP (NSIS kann nur BMP), Transparenz wird auf `bg` gemischt. */
function pngToBmp(png, bg = [255, 255, 255]) {
const { width, height, bpp, px } = decodePng(png);
@@ -309,42 +251,30 @@ function pngToBmp(png, bg = [255, 255, 255]) {
// ---------------------------------------------------------------------------
+console.log(`Logo ${logo.width}x${logo.height}, Ball: Mitte (${orb.cx}, ${orb.cy}), Radius ${orb.r}`);
const edge = await startEdge();
try {
- // Textbreiten der Wortmarke messen, damit nichts verzerrt wird
- await edge.html(`