/** Runtime proof that this document can rasterize isolated SVG screen blend. */ type ProbeState = { promise: Promise; resolved?: boolean }; const documentProbes = new WeakMap(); export type Rgb = readonly [number, number, number]; /** CSS screen formula in 8-bit sRGB, rounded exactly like a pixel sample. */ export function screenRgb(a: Rgb, b: Rgb): [number, number, number] { return [0, 1, 2].map((index) => Math.round( 255 - ((255 - a[index]) * (255 - b[index])) / 255, )) as [number, number, number]; } const closePixel = (actual: Uint8ClampedArray, expected: Rgb, offset: number): boolean => ( actual[offset + 3] === 255 && expected.every((channel, index) => Math.abs(actual[offset + index] - channel) <= 2) ); async function renderProbe(doc: Document): Promise { const win = doc.defaultView; if (!win || !win.CSS?.supports?.('mix-blend-mode', 'screen')) return false; const sourceA: Rgb = [128, 32, 16]; const sourceB: Rgb = [16, 64, 128]; const background: Rgb = [9, 19, 29]; const svg = ` `; const url = win.URL.createObjectURL(new Blob([svg], { type: 'image/svg+xml' })); try { const image = await new Promise((resolve, reject) => { const node = new win.Image(); const timer = win.setTimeout(() => reject(new Error('SVG blend probe timeout')), 1000); node.onload = () => { win.clearTimeout(timer); resolve(node); }; node.onerror = () => { win.clearTimeout(timer); reject(new Error('SVG blend probe failed')); }; node.src = url; }); const canvas = doc.createElement('canvas'); canvas.width = 4; canvas.height = 1; const context = canvas.getContext('2d', { willReadFrequently: true }); if (!context) return false; context.drawImage(image, 0, 0, 4, 1); const pixels = context.getImageData(0, 0, 4, 1).data; return closePixel(pixels, sourceA, 0) && closePixel(pixels, screenRgb(sourceA, sourceB), 4) && closePixel(pixels, sourceB, 8) && closePixel(pixels, background, 12); } catch { return false; } finally { win.URL.revokeObjectURL(url); } } /** One cached Promise per real Document; errors are a normal false fallback. */ export function svgScreenBlendSupported(doc: Document): Promise { const cached = documentProbes.get(doc); if (cached) return cached.promise; const state: ProbeState = { promise: Promise.resolve(false) }; state.promise = renderProbe(doc).catch(() => false).then((resolved) => { state.resolved = resolved; return resolved; }); documentProbes.set(doc, state); return state.promise; } /** Synchronous warm-remount path: undefined means the first cold probe is pending. */ export function resolvedSvgScreenBlend(doc: Document): boolean | undefined { return documentProbes.get(doc)?.resolved; }