/** * Multi-channel Signed Distance Field (MSDF) rasterizer * * MSDF uses three channels (RGB) to encode distance information, * allowing sharp corners to be preserved when scaling. * * Algorithm: * 1. Decompose glyph outline into edges (lines, quadratics, cubics) * 2. Color edges so adjacent edges at sharp corners have different colors * 3. For each pixel, compute signed distance to nearest edge of each color * 4. Store R, G, B distances in output bitmap * 5. Shader reconstructs using: median(r, g, b) * * Reference: https://github.com/Chlumsky/msdfgen */ import type { Font } from "../font/font.ts"; import type { GlyphPath } from "../render/path.ts"; import { type Bitmap, type GlyphAtlas, type MsdfAtlasOptions } from "./types.ts"; /** * A 2D point */ export interface Point { x: number; y: number; } /** * Edge color channels for MSDF * 0 = red, 1 = green, 2 = blue */ export type EdgeColor = 0 | 1 | 2; /** * Bounding box for edge culling */ interface EdgeBounds { minX: number; maxX: number; minY: number; maxY: number; } /** * An edge with color assignment and bounding box */ export type MsdfEdge = ({ type: "line"; p0: Point; p1: Point; color: EdgeColor; } & EdgeBounds) | ({ type: "quadratic"; p0: Point; p1: Point; p2: Point; color: EdgeColor; } & EdgeBounds) | ({ type: "cubic"; p0: Point; p1: Point; p2: Point; p3: Point; color: EdgeColor; } & EdgeBounds); /** * Signed distance result with parameter t */ export interface SignedDistanceResult { distance: number; t: number; } /** * Options for MSDF rendering */ export interface MsdfOptions { /** Width in pixels */ width: number; /** Height in pixels */ height: number; /** Scale factor (font units to pixels) */ scale: number; /** X offset in pixels */ offsetX?: number; /** Y offset in pixels */ offsetY?: number; /** Flip Y axis (font coords are Y-up, bitmap is Y-down) */ flipY?: boolean; /** Spread/radius - how far the distance field extends in pixels (default: 8) */ spread?: number; } /** * Return the median of three numbers */ export declare function median(a: number, b: number, c: number): number; /** * Compute signed distance from point to line segment */ export declare function signedDistanceToLine(px: number, py: number, p0: Point, p1: Point): SignedDistanceResult; /** * Compute signed distance from point to quadratic bezier curve * Uses Newton-Raphson iteration to find closest point */ export declare function signedDistanceToQuadratic(px: number, py: number, p0: Point, p1: Point, p2: Point): SignedDistanceResult; /** * Compute signed distance from point to cubic bezier curve * Uses Newton-Raphson iteration with multiple starting points */ export declare function signedDistanceToCubic(px: number, py: number, p0: Point, p1: Point, p2: Point, p3: Point): SignedDistanceResult; /** * Assign colors to edges based on corner angles * At sharp corners, adjacent edges get different colors */ export declare function assignEdgeColors(contours: MsdfEdge[][]): void; /** * Compute signed distance from point to edge */ export declare function signedDistanceToEdge(px: number, py: number, edge: MsdfEdge): SignedDistanceResult; /** * Determine if a point is inside using ray casting (even-odd rule) */ export declare function isPointInside(px: number, py: number, contours: MsdfEdge[][]): boolean; /** * Flatten an edge to points for inside testing */ export declare function flattenEdge(edge: MsdfEdge): Point[]; /** * Render a glyph path as a multi-channel signed distance field */ export declare function renderMsdf(path: GlyphPath, options: MsdfOptions): Bitmap; /** * Build an MSDF texture atlas from a set of glyphs */ export declare function buildMsdfAtlas(font: Font, glyphIds: number[], options: MsdfAtlasOptions): GlyphAtlas; /** * Build MSDF atlas for ASCII printable characters (32-126) */ export declare function buildMsdfAsciiAtlas(font: Font, options: MsdfAtlasOptions): GlyphAtlas; /** * Build MSDF atlas for a specific string (including all unique glyphs) */ export declare function buildMsdfStringAtlas(font: Font, text: string, options: MsdfAtlasOptions): GlyphAtlas; /** * Export MSDF atlas as RGB texture data */ export declare function msdfAtlasToRGB(atlas: GlyphAtlas): Uint8Array; /** * Export MSDF atlas as RGBA texture data */ export declare function msdfAtlasToRGBA(atlas: GlyphAtlas): Uint8Array; export {};