Text
insomni ships two text paths that share one rendering shader and one
authoring surface (Layer.pushText and friends). They
differ only in how glyphs are rasterized into the atlas:
- Raster (default) — system fonts via Canvas 2D + a CPU-computed SDF.
Zero font bytes, no
opentype.js. This is whatinsomnigives you out of the box. - MSDF / TTF (opt-in) — true multi-channel SDF from TTF/OTF outlines, with
kerning and cross-platform-consistent shapes. Imported from
insomni/text-ttf, which pulls ininsomni-msdf-text.
Both produce a GlyphAtlas you attach to a layer; the layer’s text methods
shape strings against that atlas.
RasterFont + SdfGlyphAtlas. Choosing a path
Section titled “Choosing a path”| | Raster (default) | MSDF / TTF (insomni/text-ttf) |
| -------------------- | ------------------------------------ | ------------------------------------------------------ |
| Import | insomni | insomni/text-ttf (+ insomni-msdf-text) |
| Font source | Any CSS family the browser resolves | A specific .ttf / .otf you load |
| Bundle cost | Zero font bytes | opentype.js + MSDF generator |
| Kerning | No (always 0) | Yes |
| Extreme-zoom corners | SDF rounds sharp corners | Stays crisp (MSDF) |
| Best for | UI / dataviz labels at typical sizes | Display typography, brand fonts, exact cross-OS layout |
The shared font/atlas interfaces
Section titled “The shared font/atlas interfaces”Both paths satisfy two interfaces so the shaper and renderer don’t care which kind you use:
TextFont—family,unitsPerEm,ascender,descender,lineGap, andgetKerning(left, right). Metrics are em-relative and normalized.GlyphAtlas— owns the GPU atlas texture and lazily rasterizes glyphs on first request. Key members:texture,font,pxRange,atlasFontSize,atlasSize,getGlyph(codepoint),measureText(text, options),preload(text), andversion(bumped on each new glyph allocation).
GlyphAtlasOptions configures an atlas: atlasSize (default 2048),
atlasFontSize (em size in atlas texels, default 64), pxRange (SDF distance
range in texels, default 8), and label.
measureText(text, options) takes MeasureTextOptions (fontSize, optional
maxWidth, lineHeight, fontFamily, fontWeight, fontStyle, simple) and
returns TextMetrics (width, height). The simple flag mirrors the same
flag on the shape so a measured width matches what the layout will produce.
Raster path (default)
Section titled “Raster path (default)”Build a RasterFont from a CSS family, then an SdfGlyphAtlas over it:
import { createLayer, loadSystemFont, SdfGlyphAtlas, rgba } from "insomni";
const font = await loadSystemFont("system-ui");const atlas = new SdfGlyphAtlas(renderer, font, { atlasFontSize: 64 });
const labels = createLayer({ space: "ui", atlas });labels.pushText({ text: "Hello, insomni", x: 24, y: 24, fontSize: 16, color: rgba(0.1, 0.1, 0.1, 1),});
renderer.render([labels]);RasterFontimplementsTextFontover a system font.loadSystemFont(family, options?)returns one (resolves immediately — Canvas metrics are synchronous).familyis any CSS font-family ("sans-serif","system-ui","monospace", …).RasterFontOptions:family(label override),samplePx(metric sampling size, default 64),weight,style. Kerning always returns 0.SdfGlyphAtlasis theGlyphAtlasfor raster fonts: it renders each glyph onto anOffscreenCanvas, runs a CPU distance transform, and splats the single-channel SDF into all four atlas channels so the MSDF shader works unchanged. Construct withnew SdfGlyphAtlas(owner, rasterFont, options?).
MSDF / TTF path (opt-in)
Section titled “MSDF / TTF path (opt-in)”Import the loaders from insomni/text-ttf. This entry point re-exports
insomni-msdf-text’s Font / loadFont plus insomni’s MsdfGlyphAtlas
adapter, and pulls opentype.js + the MSDF generator into your bundle:
import { createLayer } from "insomni";import { loadFont, MsdfGlyphAtlas } from "insomni/text-ttf";
const inter = await loadFont("/fonts/inter.ttf");const atlas = new MsdfGlyphAtlas(renderer, inter);
const labels = createLayer({ space: "ui", atlas });labels.pushText({ text: "Crisp at any zoom", x: 24, y: 24, fontSize: 18 });loadFont accepts a URL or an ArrayBuffer (FontSource) and takes
FontOptions. The resulting Font is a TextFont with real kerning;
MsdfGlyphAtlas is its GlyphAtlas.
Standalone MSDF shaping
Section titled “Standalone MSDF shaping”For non-layer consumers (custom pipelines, SVG export, measurement), the MSDF shaper is exported from the core barrel under prefixed names:
shapeMsdfText(text, font, atlas, x, y, options)→ anMsdfShapedBlock(glyphs,bbox,height,lineCount,maxLineWidth).MsdfShapeOptions—fontSize,align,maxWidth,lineHeight,simple.MsdfShapedGlyph— one positioned glyph (glyph,worldX/Y,worldW/H).MsdfGlyph— an atlas glyph entry.
The TextPack class (with TextBlockMetrics and the MsdfTextShape alias of
its TextShape) is the GPU-backed per-layer text buffer used internally; it owns
the glyph instance buffer and a style table. Most callers never touch it
directly — Layer.pushText manages packing for you.
Pushing text onto a layer
Section titled “Pushing text onto a layer”A layer created with { atlas } exposes the text methods (they throw without an
atlas):
pushText(shape, flags?)— full shaper: kerning, multi-line (\n), and word wrap (maxWidth). Returns layout metrics (glyph count + world bbox).pushString(shape)— fast single-line, no-kerning append (equivalent topushTextwith shaping off).pushAnchoredString(shape, flags?)— world-anchored, screen-sized text: the anchor stays in world coordinates and the shader projects it per-frame, so panning never repacks the glyphs. Em size and offsets are CSS px.pushStringsBulkInto(batch)— structure-of-arrays fast path for many short single-line labels with no per-string allocation.
pushText / pushString consume a text shape with these fields:
| Field | Type | Default | Notes |
| ------------ | ------- | -------------- | ------------------------------------------------ |
| text | string | — | The string. |
| x, y | number | — | Anchor; y is the top of the first line (Y-up). |
| fontSize | number | 16 | World units per em. |
| color | Color | black | Fill color. |
| align | string | "left" | "left" | "center" | "right". |
| maxWidth | number | — (no wrap) | Hard wrap width in world units. |
| lineHeight | number | fontSize*1.2 | Line spacing. |
| simple | boolean | false | Skip kerning / multi-line / wrap for speed. |
Text styling
Section titled “Text styling”Outline, shadow, and gradient are described per-block by these exported types (stored per text block, looked up per-glyph in the fragment shader):
TextStyle—{ fill, outline?, shadow?, gradient? }.TextOutline—{ color, width, softness? }(width/softness in screen px).TextShadow—{ color, dx, dy, softness? }(offset/softness in screen px).TextGradient—{ from, to, angle? }(angleradians; 0 = left→right).BlockGeometry—{ originX, originY, width, height }, the block’s world-space content box that a gradient samples within.
See also
Section titled “See also”- Drawing primitives — shapes and sprites.
- Layers & groups — attaching an atlas and the text methods.
- insomni-msdf-text — the standalone TTF/MSDF package behind
insomni/text-ttf.