import { GpuFragmentParams } from '../../contract'; export interface CanvasRasterTargetOptions { /** Hard cap per axis, in texels. WebGPU's floor is 8192; the fleet's convention is 4096. */ maxAxis?: number; /** * Supersample factor applied ON TOP of the device pixel ratio. The headroom is what survives * MAGNIFICATION: a distortion that scales rastered content past the atlas's density resamples * texels, and past ~2× that reads as soft edges. Default 1 (no supersampling). */ supersample?: number; /** Passed through to `getContext('2d')` — Ascii and ObjectTracker want `willReadFrequently`. */ contextAttributes?: CanvasRenderingContext2DSettings; } export interface RasterSize { /** Device-pixels per CSS pixel actually used, after the max-axis clamp. */ scale: number; /** Texture width, `max(2, round(cssWidth · scale))`. */ texW: number; /** Texture height, `max(2, round(cssHeight · scale))`. */ texH: number; } export interface CanvasRasterTarget { /** * The 2D context, creating the canvas on first call. Null when the host has no 2D context (or * after cleanup) — every caller must handle that, as a rasterizing shader with no context can * only render transparent. */ context(): CanvasRenderingContext2D | null; /** The backing canvas — pass it to `mediaTexture.write`. Null before the first `context()`. */ canvas(): HTMLCanvasElement | null; /** * Resolve the raster resolution for a CSS-pixel box: device pixel ratio × supersample, clamped so * NEITHER axis exceeds `maxAxis`, then rounded with a 2-texel floor. Degrading the density is the * correct failure mode for a long text run — an over-cap texture allocation would throw. */ rasterSize(cssWidth: number, cssHeight: number): RasterSize; /** Resize the canvas to `w`×`h` and clear it. Returns the context, or null when unavailable. */ resize(w: number, h: number): CanvasRenderingContext2D | null; /** The host's real device-pixel ratio, derived from the canvas vs the logical dimensions. */ devicePixelRatio(): number; /** True once the shader has been cleaned up. */ readonly disposed: boolean; } /** * An offscreen 2D canvas sized in device pixels, with the scale invariant and the teardown wired up. * * The canvas is created LAZILY: an atlas shader that never rasters (empty `characters`, labels off) * must not allocate a multi-megabyte backing store at composition time. Cleanup sets both axes to 0, * which is what actually releases that store — dropping the reference alone leaves it to the GC. */ export declare function createCanvasRasterTarget(params: GpuFragmentParams, opts?: CanvasRasterTargetOptions): CanvasRasterTarget; export interface RasterInvalidatorOptions { /** * Everything the raster depends on, as one string. Include the canvas size for anything measured * in device pixels — a resize changes the raster even when no prop did. */ key(): string; /** * Minimum ms between key CHECKS, not between rasters. The check reads live prop handles, so it is * not free; 16 ms (one frame at 60fps) is the fleet default, and an atlas whose props change * rarely can afford 100 ms. */ minIntervalMs?: number; /** Re-raster. Called only when the key actually changed. */ run(): void; /** * Key value to treat as already-rendered. Pass the key matching a raster the shader performed * eagerly at composition, so the first frame does not immediately redo it. Default `''` — no key * matches, so the first check after the interval triggers a run. */ initialKey?: string; } /** A throttled key-diff over `onBeforeRender`. */ export declare function createRasterInvalidator(params: GpuFragmentParams, opts: RasterInvalidatorOptions): void; export interface FontDependentRasterOptions { /** Font identity (family | weight | italic). A change re-triggers the load. */ key(): string; /** Load the font for the CURRENT key. Rejection is expected and means "keep the fallback". */ load(): Promise; /** * Re-raster now that the real font is available. Anything that must invalidate a MEASURE cache * belongs at the top of this callback — `measureText` keys on font availability, so a cache * populated with the fallback's metrics has to be dropped before re-measuring. */ onLoaded(): void; } export interface FontDependentRaster { /** * Load the current font if it changed, then re-raster. Cheap and idempotent per key — call it * next to every raster, including the invalidator's. */ ensure(): void; } /** * The two-pass webfont raster: draw immediately with whatever font is resolvable (so text appears on * the first frame), then re-draw once the real font has loaded. * * Skipping the first pass and waiting for the font is the tempting simplification and it is wrong — * a font load is a network round trip, and a text layer that renders nothing until it completes * flashes empty on every cold load. */ export declare function createFontDependentRaster(opts: FontDependentRasterOptions): FontDependentRaster; //# sourceMappingURL=canvasRaster.d.ts.map