Shaping API
shape()
The main text shaping function. Converts text to positioned glyphs using OpenType and AAT features.
function shape(
fontLike: Font | Face,
buffer: UnicodeBuffer,
options?: ShapeOptions
): GlyphBufferParameters
fontLike- Either aFontorFaceinstance. UseFacefor variable fonts.buffer-UnicodeBuffercontaining the text to shapeoptions- Optional shaping options
ShapeOptions
interface ShapeOptions {
/** Script tag (e.g., "arab", "latn") */
script?: string;
/** Language tag (BCP 47, e.g., "en", "ar") */
language?: string | null;
/** Text direction: "ltr" or "rtl" */
direction?: "ltr" | "rtl";
/** OpenType features to enable/disable */
features?: ShapeFeature[];
}ShapeFeature
interface ShapeFeature {
tag: Tag; // Feature tag (e.g., Tags.liga)
enabled: boolean; // true to enable, false to disable
}Basic Usage
import { Font, UnicodeBuffer, shape } from "typeshaper";
const font = await Font.fromFile("font.ttf");
const buffer = new UnicodeBuffer();
buffer.addStr("Hello World");
const shaped = shape(font, buffer);
for (const { info, position } of shaped) {
console.log(`Glyph ${info.glyphId}: advance ${position.xAdvance}`);
}With Options
const shaped = shape(font, buffer, {
script: "arab",
language: "ar",
direction: "rtl",
features: [
{ tag: Tags.liga, enabled: false }, // Disable ligatures
{ tag: Tags.calt, enabled: true } // Enable contextual alternates
]
});Variable Fonts
Use Face for variable font instances:
import { Font, Face, UnicodeBuffer, shape } from "typeshaper";
const font = await Font.fromFile("variable.ttf");
const face = new Face(font, { wght: 700, wdth: 100 });
const buffer = new UnicodeBuffer();
buffer.addStr("Variable");
const shaped = shape(face, buffer);Complex Scripts
The shaper automatically detects and handles complex scripts:
Arabic
buffer.addStr("مرحبا");
buffer.setScript("arab");
buffer.setDirection(Direction.RTL);
const shaped = shape(font, buffer, { direction: "rtl" });Indic (Devanagari)
buffer.addStr("नमस्ते");
buffer.setScript("deva");
const shaped = shape(font, buffer, { script: "deva" });Thai
buffer.addStr("สวัสดี");
buffer.setScript("thai");
const shaped = shape(font, buffer, { script: "thai" });Korean (Hangul)
buffer.addStr("안녕하세요");
buffer.setScript("hang");
const shaped = shape(font, buffer, { script: "hang" });Shape Plan
The shape plan determines which lookups to apply during shaping. Plans are cached for performance.
ShapePlan Interface
interface ShapePlan {
script: Tag;
language: Tag | null;
direction: "ltr" | "rtl";
gsubLookups: Array<{ index: number; lookup: AnyGsubLookup }>;
gposLookups: Array<{ index: number; lookup: AnyGposLookup }>;
}createShapePlan()
Manually create a shape plan (usually not needed, as shape() handles this).
function createShapePlan(
font: Font,
script: string,
language: string | null,
direction: "ltr" | "rtl",
features: ShapeFeature[],
axisCoords: number[] | null
): ShapePlangetOrCreateShapePlan()
Get or create a cached shape plan.
function getOrCreateShapePlan(
font: Font,
script: string,
language: string | null,
direction: "ltr" | "rtl",
userFeatures?: ShapeFeature[],
axisCoords?: number[] | null
): ShapePlanFeature Helpers
Convenient functions for common OpenType features.
Ligatures
import { standardLigatures, discretionaryLigatures } from "typeshaper";
const shaped = shape(font, buffer, {
features: standardLigatures(true) // Enable standard ligatures
});Small Caps
import { smallCaps } from "typeshaper";
const shaped = shape(font, buffer, {
features: smallCaps(true)
});Kerning
import { kerning } from "typeshaper";
const shaped = shape(font, buffer, {
features: kerning(false) // Disable kerning
});Number Styles
import { oldstyleFigures, tabularFigures } from "typeshaper";
const shaped = shape(font, buffer, {
features: [...oldstyleFigures(true), ...tabularFigures(true)]
});Stylistic Sets
import { stylisticSet } from "typeshaper";
const shaped = shape(font, buffer, {
features: stylisticSet(1, true) // Enable stylistic set 1
});Combining Features
import { combineFeatures, smallCaps, kerning, standardLigatures } from "typeshaper";
const shaped = shape(font, buffer, {
features: combineFeatures(
smallCaps(true),
kerning(true),
standardLigatures(true)
)
});Default Features
The shaper applies these features by default:
GSUB (Substitution)
ccmp- Glyph composition/decompositionlocl- Localized formsrlig- Required ligaturesrclt- Required contextual alternatescalt- Contextual alternatesliga- Standard ligatures
GPOS (Positioning)
kern- Kerningmark- Mark positioningmkmk- Mark-to-mark positioning
AAT Morphing
For fonts with Apple Advanced Typography (AAT) tables, the shaper automatically falls back to morx if no OpenType layout is present.
// Automatically uses morx if available and GSUB/GPOS not present
const shaped = shape(font, buffer);Fallback Positioning
When GPOS is not available, the shaper applies fallback positioning:
- Fallback Kerning - Uses legacy
kerntable if present - Fallback Mark Positioning - Uses Unicode combining classes for basic mark attachment
import { applyFallbackKerning, applyFallbackMarkPositioning } from "typeshaper";
// These are called automatically when GPOS is not available
// Can also be called manually for custom workflows
applyFallbackKerning(font, infos, positions);
applyFallbackMarkPositioning(font, infos, positions);