// Aufzeichnender Canvas-Kontext für die Engine-Tests (Muster: Proxy aus entwuerfe/smoke.js). // fillRect/fillText werden mit dem aktuellen fillStyle/font notiert, alles Übrige ist ein No-op. /** * makeCtx({ width, height }) → { ctx, rects, texts, strokes, counts, alphas } * rects: [{ x, y, w, h, fill }] jedes fillRect * texts: [{ text, x, y, font }] jedes fillText (Nicht-String wirft wie im Smoke-Test) * strokes: [{ text, x, y, style, width, rects, texts }] jedes strokeText (style/width = strokeStyle/lineWidth, rects/texts = * Anzahl der bis dahin gezeichneten fillRect/fillText: so ist die Reihenfolge prüfbar) * counts: { save, restore } Aufrufe von ctx.save()/ctx.restore() * alphas: [] jede Zuweisung an ctx.globalAlpha */ export function makeCtx({ width = 960, height = 768 } = {}) { const rects = [] const texts = [] const strokes = [] const counts = { save: 0, restore: 0 } const alphas = [] const target = { canvas: { width, height }, fillStyle: '#000000', font: '10px sans-serif', globalAlpha: 1 } const ctx = new Proxy(target, { get(t, prop) { if (typeof prop === 'symbol') return undefined if (prop === 'save') return () => { counts.save++ } if (prop === 'restore') return () => { counts.restore++ } if (prop === 'measureText') return (text) => ({ width: String(text).length * 7 }) if (prop === 'fillRect') return (x, y, w, h) => { rects.push({ x, y, w, h, fill: t.fillStyle }) } if (prop === 'fillText') { return (text, x, y) => { if (typeof text !== 'string') throw new Error('fillText mit Nicht-String: ' + text) texts.push({ text, x, y, font: t.font }) } } if (prop === 'strokeText') { return (text, x, y) => { if (typeof text !== 'string') throw new Error('strokeText mit Nicht-String: ' + text) strokes.push({ text, x, y, style: t.strokeStyle, width: t.lineWidth, rects: rects.length, texts: texts.length }) } } if (prop === 'createLinearGradient' || prop === 'createRadialGradient') return () => ({ addColorStop() {} }) if (prop === 'getImageData') return () => ({ data: new Uint8ClampedArray(4) }) if (prop in t) return t[prop] return () => {} }, set(t, prop, value) { if (prop === 'globalAlpha') alphas.push(value) t[prop] = value return true }, }) return { ctx, rects, texts, strokes, counts, alphas } }