fontdone¶
Latest release: 2.14.3-alpha.11.
fontdone is the JavaScript npm package for the pure-Rust fontdone engine. It
ships a prebuilt wasm32-unknown-unknown module and a zero-dependency ESM
wrapper for opening font bytes and rasterizing individual glyphs.
Different alpha releases are not API- or ABI-compatible by promise, and this package is not a text-shaping or layout engine.
Install¶
npm install fontdone@2.14.3-alpha.11
Node.js¶
Save as render.mjs. Run node render.mjs /path/to/your-font.ttf with a font
you are licensed to use. Requires Node.js 20 or newer.
import { readFile } from "node:fs/promises";
import createFontdone from "fontdone";
const fontBytes = await readFile(process.argv[2]);
const engine = await createFontdone();
try {
const face = engine.openFace(fontBytes, { pixelSize: 32 });
try {
const bitmap = face.render("A");
console.log(bitmap.width, bitmap.height, bitmap.pixels.length);
} finally {
face.close();
}
} finally {
engine.close();
}
Browser¶
Serve your licensed font at /fonts/example.ttf or change the URL to your
own asset. The package loads its bundled WASM module automatically.
import createFontdone from "fontdone";
const [engine, fontBytes] = await Promise.all([
createFontdone(),
fetch("/fonts/example.ttf").then((response) => response.arrayBuffer()),
]);
const face = engine.openFace(fontBytes, { pixelSize: 32 });
try {
const bitmap = face.render("A");
console.log(bitmap.width, bitmap.height, bitmap.pitch, bitmap.pixels);
} finally {
face.close();
engine.close();
}
In browsers, the default initializer fetches fontdone.wasm relative to the
ESM entry point. In Node.js, the package's conditional node export reads the
same bundled asset from disk, so createFontdone() works without a
fetch(file://…) call. Pass an explicit URL, Response, ArrayBuffer,
typed-array view, WebAssembly.Module, or WebAssembly.Instance when your
asset pipeline needs different loading behavior:
const engine = await createFontdone("/assets/fontdone.wasm");
The loader uses streaming instantiation when available and falls back to an
ArrayBuffer when the server does not send application/wasm.
Runtime contract¶
The maintained package requires ESM, WebAssembly, and WebAssembly JavaScript
BigInt integration. Browser initialization requires fetch; Node.js uses its
conditional entrypoint and the local bundled asset. The wrapper performs no
font or telemetry requests; the only implicit asset load is its own Wasm
module.
Each initializer call owns a separate WebAssembly instance. Faces and memory offsets are instance-local and cannot be transferred to another instance or Worker. Create one engine per Worker and close every face deterministically.
render maps one Unicode scalar, loads the glyph, renders it in normal
grayscale mode, and copies the result out of linear memory. Its result has:
glyphIndex: the mapped glyph index;widthandheight: bitmap dimensions in pixels;pitch: signed bytes per source row;pixels: an ownedUint8Arrayofabs(pitch) * heightbytes.
The package does not shape text, apply bidi ordering, choose fallback fonts, or retain the caller's font buffer. Use a shaping library before loading glyph indices when those behaviors are required.
API¶
createFontdone(source?)/init(source?): create an independent engine.engine.openFace(bytes, { faceIndex?, pixelSize? }): copy bytes, open a face, and select an integer pixels-per-EM size (16 by default).face.setPixelSize(size)orsetPixelSizes(width, height): select integer pixels per EM.face.getCharIndex(character): map one number or one Unicode scalar string.face.loadGlyph(index, loadFlags?): load an explicit glyph.face.renderGlyph(renderMode?): render and copy the current glyph bitmap.face.render(character, options?): map, load, and render in one call.face.close()/engine.close(): deterministic, idempotent wrapper cleanup.
Nonzero engine statuses throw FontdoneError, whose code is the preserved
FreeType-compatible FT_Error value and whose operation names the failed
wrapper call. Programmer errors such as an invalid size or use after close
throw standard JavaScript errors.
TypeScript declarations ship with the package. The complete low-level export
and record inventory is also distributed as
abi.json;
only the wrapper above is promoted as the JavaScript application API.
Security and license¶
Fonts are untrusted binary input and can demand substantial CPU or memory even inside WebAssembly. Apply application-level input-size and execution limits. Report vulnerabilities through the repository's private security-advisory route.
The package is distributed under the FreeType License (FTL). See
FTL.TXT and NOTICE.md for terms and attribution.