// Vereinfachte App-/Geraete-Symbole (eigene Zeichnungen, keine Original-Logos) in Einheitskoordinaten [-1, 1]. const TAU = Math.PI * 2; export const APP_GLYPHS = [ 'eye-off', 'lightbulb', 'pc-monitor', 'chrome', 'discord', 'steam', 'twitch', 'netflix', 'youtube', 'medal', 'nvidia', 'steelseries', 'aniworld', 'prismlens', ]; /** * @param {import('./raster.mjs').Canvas} canvas * @param {string} name - Eintrag aus APP_GLYPHS * @param {number} cx * @param {number} cy * @param {number} r - halbe Symbolgroesse in Pixeln * @param {string|Function} color * @param {string|Function} background - Farbe fuer "ausgeschnittene" Teile */ export function drawApp(canvas, name, cx, cy, r, color, background) { const p = (x, y) => [cx + x * r, cy + y * r]; const stroke = (x1, y1, x2, y2, w = 0.2, paint = color) => { canvas.line(...p(x1, y1), ...p(x2, y2), w * r, paint); }; const path = (points, w = 0.2, paint = color) => { points.slice(1).forEach((pt, i) => stroke(...points[i], ...pt, w, paint)); }; const poly = (points, paint = color) => canvas.polygon(points.map(([x, y]) => p(x, y)), paint); const disc = (x, y, radius, paint = color) => canvas.circle(...p(x, y), radius * r, paint); const ring = (x, y, outer, inner, from = 0, to = TAU) => canvas.ring(...p(x, y), outer * r, inner * r, color, from, to); const box = (x, y, w, h, radius, paint = color) => canvas.roundRect(...p(x, y), w * r, h * r, radius * r, paint); // Ellipse; thickness = Randstaerke relativ zum Radius, null = gefuellt. const ellipse = (x, y, rx, ry, thickness, paint = color) => { const [ex, ey] = p(x, y); canvas.fill((px, py) => { const d = Math.hypot((px - ex) / (rx * r), (py - ey) / (ry * r)); return d <= 1 && (thickness === null || d >= 1 - thickness); }, paint, [ex - rx * r, ey - ry * r, ex + rx * r, ey + ry * r]); }; switch (name) { case 'eye-off': ellipse(0, 0, 0.98, 0.58, 0.22); disc(0, 0, 0.3); stroke(-0.75, 0.8, 0.75, -0.8, 0.42, background); stroke(-0.75, 0.8, 0.75, -0.8, 0.2); break; case 'lightbulb': disc(0, -0.25, 0.62); poly([[-0.4, 0.1], [0.4, 0.1], [0.28, 0.45], [-0.28, 0.45]]); box(-0.3, 0.5, 0.6, 0.16, 0.06); box(-0.2, 0.72, 0.4, 0.14, 0.06); path([[-0.2, 0.05], [0, -0.3], [0.2, 0.05]], 0.1, background); break; case 'pc-monitor': box(-0.95, -0.8, 1.9, 1.35, 0.12); box(-0.8, -0.65, 1.6, 1.05, 0.05, background); path([[-0.6, -0.1], [-0.28, -0.1], [-0.12, -0.45], [0.08, 0.2], [0.24, -0.2], [0.6, -0.2]], 0.13); stroke(0, 0.55, 0, 0.82, 0.2); stroke(-0.5, 0.88, 0.5, 0.88, 0.2); break; case 'chrome': ring(0, 0, 0.95, 0.72); disc(0, 0, 0.36); for (let i = 0; i < 3; i += 1) { const a = (-90 + i * 120) * (Math.PI / 180); stroke(Math.cos(a) * 0.3, Math.sin(a) * 0.3, Math.cos(a) * 0.85, Math.sin(a) * 0.85, 0.2); } disc(0, 0, 0.2, background); break; case 'discord': ellipse(0, -0.05, 0.95, 0.7, null); poly([[-0.5, 0.45], [-0.75, 0.9], [-0.15, 0.62]]); poly([[0.5, 0.45], [0.75, 0.9], [0.15, 0.62]]); disc(-0.36, -0.05, 0.19, background); disc(0.36, -0.05, 0.19, background); break; case 'steam': ring(0, 0, 0.95, 0.72); disc(0.32, -0.28, 0.32); disc(0.32, -0.28, 0.14, background); disc(-0.36, 0.3, 0.2); stroke(-0.36, 0.3, 0.2, -0.05, 0.16); break; case 'twitch': poly([[-0.85, -0.85], [0.9, -0.85], [0.9, 0.4], [0.4, 0.4], [0.05, 0.8], [0.05, 0.4], [-0.85, 0.4]]); stroke(0.02, -0.5, 0.02, 0, 0.16, background); stroke(0.5, -0.5, 0.5, 0, 0.16, background); break; case 'netflix': box(-0.55, -0.85, 0.28, 1.7, 0.02); box(0.27, -0.85, 0.28, 1.7, 0.02); poly([[-0.55, -0.85], [-0.27, -0.85], [0.55, 0.85], [0.27, 0.85]]); break; case 'youtube': box(-0.95, -0.62, 1.9, 1.24, 0.34); poly([[-0.2, -0.32], [0.34, 0], [-0.2, 0.32]], background); break; case 'medal': poly([[0, -0.95], [0.85, -0.6], [0.85, 0.15], [0, 0.95], [-0.85, 0.15], [-0.85, -0.6]]); path([[-0.45, 0.32], [-0.45, -0.32], [0, 0.1], [0.45, -0.32], [0.45, 0.32]], 0.16, background); break; case 'nvidia': box(-0.95, -0.55, 1.9, 1.1, 0.12); disc(0, 0, 0.42, background); disc(0, 0, 0.17); for (let i = 0; i < 4; i += 1) { const a = i * (Math.PI / 2) + 0.4; stroke(Math.cos(a) * 0.14, Math.sin(a) * 0.14, Math.cos(a) * 0.36, Math.sin(a) * 0.36, 0.12); } break; case 'steelseries': ring(0, -0.42, 0.56, 0.34, Math.PI / 2, TAU); ring(0, 0.42, 0.56, 0.34, (3 * Math.PI) / 2, TAU); ring(0, 0.42, 0.56, 0.34, 0, Math.PI); break; case 'aniworld': ring(0, 0, 0.95, 0.72); poly([[-0.22, -0.42], [0.5, 0], [-0.22, 0.42]]); break; case 'prismlens': ring(0, 0, 0.95, 0.75); ring(0, 0, 0.58, 0.4); disc(0, 0, 0.2); break; default: throw new Error(`Unbekanntes Symbol: ${name}`); } }