import type { Font, Measure } from "./types.js"; export const fontString = (font: Font) => `${font.italic ? "italic " : ""}${font.weight === "bold" ? "bold " : ""}${font.size}px ${font.family}`; // A bounded per-surface cache replaces the original global memoizee cache. // Font loading creates a new measure/layout so fallback metrics cannot persist. export function canvasMeasure(context: CanvasRenderingContext2D, maximum = 12000): Measure { const cache = new Map>(); return (text, font) => { const key = `${fontString(font)}/${text}`; const cached = cache.get(key); if (cached) return cached; context.font = fontString(font); const metrics = context.measureText(text); const value = { width: Math.max(0, metrics.width), ascent: Math.max(metrics.actualBoundingBoxAscent || 0, font.size * 0.85), descent: Math.max(metrics.actualBoundingBoxDescent || 0, font.size * 0.22), }; if (cache.size >= maximum) cache.clear(); cache.set(key, value); return value; }; }