@pptx-editor.dev/core/layout

Functions (42)

adjustForHandlefunction

The values of the guides that handle index moves, which put it nearest to point (shape-local EMU), each within its handle range. Undefined when the shape has no such handle. Values are whole guide units, as a:gd stores them.

declare function adjustForHandle(preset: string, w: number, h: number, adjust: ReadonlyMap<string, number>, index: number, point: {
    readonly x: number;
    readonly y: number;
}): Map<string, number> | undefined;

applyfunctionSource ↗

Apply a matrix to a point.

declare function apply(m: Matrix, x: number, y: number): {
    x: number;
    y: number;
};

autonumberTextfunctionSource ↗

The marker text for item n (1-based) of a scheme. A value that ST_TextAutonumberScheme does not list falls back to n..

declare function autonumberText(scheme: string, n: number): string;

baselineOffsetPtfunctionSource ↗

Distance from the line box top to the baseline (points), before rounding.

declare function baselineOffsetPt(sizePt: number, lineHeight: number, metrics: FaceMetrics): number;

baselineOffsetPtfunctionSource ↗

Deprecated. The spacing is ignored: the line height decides. Call without it.

Distance from the line box top to the baseline (points), before rounding.

declare function baselineOffsetPt(sizePt: number, lineHeight: number, metrics: FaceMetrics, spacing: {
    pct: number;
} | {
    pts: number;
}): number;

boxMatrixfunctionSource ↗

Box-local → parent: rotate and flip around the box center, then place at the offset.

declare function boxMatrix(x: Xfrm, withFlip?: boolean, extraRotation?: number): Matrix;

breakOpportunitiesfunctionSource ↗

Break opportunities in text. eaLineBreak applies the East Asian line breaking rules (a:pPr/@eaLnBrk, on by default); latinLineBreak allows a break between any two characters (a:pPr/@latinLnBrk). kinsoku replaces the built-in lists of those rules.

declare function breakOpportunities(text: string, eaLineBreak?: boolean, latinLineBreak?: boolean, kinsoku?: KinsokuLists): Uint8Array;

composeFontConfigurationfunctionSource ↗

Merge a base and any number of fragments into one frozen FontConfiguration.

A bare fragment IS a valid base, so the single-origin case is one argument: composeFontConfiguration(await loadDefaultFonts()). Pass extra fragments to layer origins, and set epoch/maxFontBytes/defaultFont on the base only when you need something other than the documented defaults.

- Sources dedupe first-wins by (family, weight, style), in argument order — base before fragments, earlier fragments before later ones. - Substitutions dedupe first-wins by their from face, in the same order, and every substitution whose from face has a direct source anywhere in the composition is dropped: a real face always beats a stand-in. - The result is frozen (arrays included); the byte arrays themselves are the callers' and are not copied here — the resource snapshot takes its own defensive copy.

declare function composeFontConfiguration(base: FontConfigurationBase, ...fragments: readonly FontConfigurationFragment[]): FontConfiguration;

composeFontOriginsfunctionSource ↗

Resolve a list of [FontOrigin](FontOrigin)s against one document's needs and merge them, first-wins in list order.

Origins resolve IN ORDER, one after another, and each is told which faces the ones before it can already paint ([FontResolutionRequest.resolvedFaces](FontResolutionRequest.resolvedFaces)). Sequential rather than a Promise.all, and that is a real cost — one extra origin's latency on the critical path — bought deliberately: composition is first-wins, so a later origin's copy of a face an earlier one supplied can never be used, and fetching it anyway spends the bytes twice and tells a font host which families the document uses for a result that gets thrown away. Order origins cheapest-first.

A resolver that ignores resolvedFaces still composes correctly; it just spends more.

ONE ORIGIN CANNOT SINK THE REST. An origin that throws, answers null, or answers something malformed is reported and skipped whole, and the origins around it still compose — an app that listed a flaky network origin behind a bundled one keeps the bundled faces. Skipped WHOLE: an answer is read completely before any of it is committed, so a half-ingested origin can never reach composition.

The result carries NO epoch: it is a fragment for the engine to stamp with the load sequence. A fixed epoch from here would label every document's byte set as the same one. undefined means no origin contributed anything, which is a normal answer — the document stays on the fixed measurer.

declare function composeFontOrigins(origins: readonly FontOrigin[], request: FontResolutionRequest, options?: ComposeFontOriginsOptions): Promise<FontConfigurationFragment | undefined>;

configuredDefaultFontFamilyfunctionSource ↗

The face a run with no authored font is measured and reported as: the configured default when it names a valid family, Calibri otherwise.

declare function configuredDefaultFontFamily(configuration?: FontCatalogConfiguration): string;

connectionSitesfunctionSource ↗

The connection sites of a geometry spec at a size (EMU), in a:cxnLst order. Evaluated paths have none.

declare function connectionSites(spec: GeometrySpec, w: number, h: number): ConnectionSite[];

createFixedMeasurerfunctionSource ↗

A deterministic measurer for tests and for hosts without fonts: every code unit is 0.5 em, spaces 0.25 em, and every glyph outline is a box. Never use it for fidelity work.

declare function createFixedMeasurer(): TextMeasurer;

createHarfBuzzMeasurerfunctionSource ↗

Create a measurer over a set of faces. Registration order matters only for ties: the first face registered for a family/style wins.

Face ids are unique for each measurer (pptx-f<measurer>-<face>), so the faces of two documents never share a name, for example in a rasterizer's font registry.

declare function createHarfBuzzMeasurer(sources: readonly FontSource[]): TextMeasurer & {
    readonly faces: readonly RegisteredFace[];
};

deferFontsfunctionSource ↗

Load an origin's faces after the document first paints, instead of before.

The editor opens the document with the faces the other origins supply, then lays it out again when these arrive. Use it for faces that are large or slow to fetch. Leave an origin unwrapped to install its faces with the document's other waiting fonts: a large document (over about 512 KB of uncompressed content) waits up to 2 seconds for them before its first paint.

ts const fonts = [packagedFonts(), deferFonts(myBrandFonts())];

A document export that receives this origin waits for its faces, so exported pages use them. The faces never change the configuration settings, such as defaultFont or maxFontBytes: those come from the origins that answer at once, so the document does not change its default font after it paints.

declare function deferFonts(origin: FontOrigin): MarkedFontResolver;

defineFontResolverfunctionSource ↗

Mark a function as an on-demand [FontResolver](FontResolver).

Wrap every resolver you put in a fonts list — useFonts(...), useDocxSource's fonts option, composeFontOrigins. The fonts PROP needs no marking, because a function there is always a resolver; a list also accepts the older zero-argument loader form ({ fonts: defaultFonts }), and this is what keeps the two apart.

Returns the same function object, mutated, so the mark survives being passed around and a marked resolver stays === to itself. It does NOT survive .bind() or being wrapped: both make a new function object. Re-mark the result.

ts const brandFonts = defineFontResolver(async ({ families }) => ({ sources: await loadMine(families), }));

Throws a TypeError on a frozen or sealed function, which cannot take the mark. That is deliberate: returning it unmarked would compile — the return TYPE says marked — and then lose every font at runtime.

declare function defineFontResolver<T extends FontResolver>(resolve: T): MarkedFontResolver<T>;

drawingCapabilitiesfunctionSource ↗

What the installed drawing renderers paint, read at the time of the call. The chrome reads it when it renders, to offer only the controls whose result paints. Unlike a paint, this query does not count as a use, so an install after it logs no warning.

declare function drawingCapabilities(): DrawingCapabilities;

drawingRenderersVersionfunctionSource ↗

A number that each installDrawingRenderers call increases. An adapter reads it with [subscribeDrawingRenderers](subscribeDrawingRenderers) (for example through useSyncExternalStore), so the choices it shows refresh after an install.

declare function drawingRenderersVersion(): number;

eastAsianFallbackFamiliesfunctionSource ↗

The East Asian fallback faces in the order for a language (a BCP 47 tag): the faces of its script first (Simplified Chinese for Hans, Traditional Chinese for Hant, Korean for Hang), so the text draws with its own glyph forms. Japanese and no language: EAST_ASIAN_FALLBACK_FAMILIES.

declare function eastAsianFallbackFamilies(lang?: string): readonly string[];

evaluateFormulafunction

Evaluate one guide formula against the variables defined so far.

declare function evaluateFormula(fmla: string, vars: ReadonlyMap<string, number>): number;

evaluateGeometryfunctionSource ↗

Evaluate a geometry spec at a size (EMU).

declare function evaluateGeometry(spec: GeometrySpec, w: number, h: number): EvaluatedGeometry;

fontSubstitutesfunctionSource ↗

The substitutes of family. A deck names any family, so only own keys count: a family named constructor has none.

declare function fontSubstitutes(family: string): readonly string[];

hasCharactersfunctionSource ↗

Whether a text layout holds a character. An empty text body still lays out one line, so the caret of a press in it has a position and a height; that line shows nothing, so diagnostics, effect silhouettes, and paint bounds treat the body as no text.

declare function hasCharacters(layout: TextLayout): boolean;

initializeHarfBuzzfunctionSource ↗

Load and verify the HarfBuzz runtime. Idempotent.

declare function initializeHarfBuzz(): Promise<void>;

invertfunctionSource ↗

Invert an affine matrix.

declare function invert(m: Matrix): Matrix;

isFontResolverfunctionSource ↗

Whether a value is a function marked by [defineFontResolver](defineFontResolver).

False for an unmarked function, which callers read as a zero-argument loader. Calling a resolver that way reads request.defaultFamily off undefined and throws, so the callers that make this choice say so rather than swallowing it — and the type-level mark on [MarkedFontResolver](MarkedFontResolver) is there to stop it reaching runtime at all.

declare function isFontResolver(value: unknown): value is MarkedFontResolver;

isHarfBuzzReadyfunctionSource ↗

Whether initializeHarfBuzz() has completed.

declare function isHarfBuzzReady(): boolean;

isIdeographicfunctionSource ↗

Whether a code point is an East Asian character that breaks per character.

declare function isIdeographic(cp: number): boolean;

isMetricCompatiblefunctionSource ↗

Whether measuring family with substitute keeps the original's advance widths.

declare function isMetricCompatible(family: string, substitute: string): boolean;

layoutSlidefunctionSource ↗

Lay out a resolved slide.

declare function layoutSlide(slide: ResolvedSlide, measurer: TextMeasurer): SlideLayout;

layoutTablefunctionSource ↗

Lay out a table. substitutions collects font substitutions for the report.

declare function layoutTable(table: ResolvedTable, measurer: TextMeasurer, substitutions?: Set<string>): TableLayout;

layoutTextfunctionSource ↗

Lay out one text body inside a box (shape-local EMU).

declare function layoutText(body: ResolvedTextBody, rect: {
    x: number;
    y: number;
    width: number;
    height: number;
}, measurer: TextMeasurer): TextLayout;

lineHeightPtfunctionSource ↗

Line box height (points) for a line whose largest font is sizePt. Exact spacing rounds to a whole point; reduction (lnSpcReduction) is subtracted from a percentage.

declare function lineHeightPt(sizePt: number, spacing: {
    pct: number;
} | {
    pts: number;
}, reduction: number): number;

multiplyfunctionSource ↗

m × n: apply n first, then m.

declare function multiply(m: Matrix, n: Matrix): Matrix;

normalizeFontResolverResultfunctionSource ↗

Normalize an on-demand resolver answer that covers none of the requested families.

declare function normalizeFontResolverResult(result: FontConfigurationBase | null | undefined): FontConfigurationBase | undefined;

paragraphSpacingPtfunctionSource ↗

Paragraph spacing (spcBef/spcAft) in points. Points round to a whole point, as exact line spacing does. Percent is of 1.2 × the first run size and does not round.

declare function paragraphSpacingPt(spacing: {
    pct: number;
} | {
    pts: number;
}, sizePt: number): number;

presetAdjustmentsfunction

The adjust values of a preset in a:avLst order, each with the range of its adjust handle (ECMA-376 Part 1, 20.1.9.1 ahLst), evaluated at the size w by h (EMU) with the shape's own values. A range that names a guide needs a size: at zero size only literal ranges apply. Undefined for a preset that the engine does not know.

declare function presetAdjustments(preset: string, w: number, h: number, adjust: ReadonlyMap<string, number>): PresetAdjustment[] | undefined;

presetHandlesfunction

The adjust handles of a preset at the size w by h (EMU) with the shape's own adjust values, in a:ahLst order. Empty for a preset with no handles or one the engine does not know, and for a shape of no size.

declare function presetHandles(preset: string, w: number, h: number, adjust: ReadonlyMap<string, number>): PresetHandle[];

presetNamesfunction

Every preset name the evaluator can draw.

declare function presetNames(): string[];

runGlyphsfunctionSource ↗

The characters of a glyph run in source order, each with the left edge of its cell. In a run that reads right to left (GlyphRun.rtl), unit i draws in cell n - 1 - i, and a character with a mirror image (UAX #9 L4, such as a bracket) draws as that mirror. A surrogate pair is one character. For readers that place each glyph at its own position.

declare function runGlyphs(run: Pick<GlyphRun, 'text' | 'x' | 'rtl'>): RunGlyph[];

setHarfBuzzWasmUrlfunctionSource ↗

Point the text shaper at an externally hosted copy of harfbuzz.wasm.

Needed only under bundlers that do not emit new URL(..., import.meta.url) assets. esbuild and Bun are the common ones, and so is any build that inlines dynamic imports, such as a library bundle. There, the build succeeds and the shaper fails at runtime with an error that names this function; this function is the fix. Webpack, Turbopack and Vite emit the binary on their own, and passing a URL there simply overrides theirs.

ts import { setHarfBuzzWasmUrl } from '@pptx-editor.dev/core/layout'; setHarfBuzzWasmUrl('/static/harfbuzz.wasm');

Pass a URL your application controls. It is fetched and instantiated as WebAssembly, so never derive it from user input, a query parameter, or remote configuration. Serving it cross-origin needs that origin in your connect-src CSP directive, and WebAssembly needs wasm-unsafe-eval in script-src either way.

Call it before the first editor is created. The runtime reads the location once and caches the result, so a call afterwards warns and does nothing: fix the call site and reload. The file to serve is exported as @pptx-editor.dev/core/harfbuzz.wasm, and it must be the copy from the installed package version, because the runtime refuses a version mismatch at load rather than shaping with unverified metrics.

declare function setHarfBuzzWasmUrl(url: string | URL): void;

sha256FontBytesfunctionSource ↗

Synchronous platform-neutral SHA-256 used before font bytes cross into a shaping implementation.

sha256FontBytes: (bytes: Uint8Array) => string

subscribeDrawingRenderersfunctionSource ↗

Call listener after each installDrawingRenderers call. Returns the function that stops the calls. Like [drawingCapabilities](drawingCapabilities), a subscription does not count as a use, so it logs no warning.

declare function subscribeDrawingRenderers(listener: () => void): () => void;

Classes (1)

FontResolutionErrorclassSource ↗

A face that could not be admitted, carrying whatever evidence the refusal produced.

RETURNED rather than thrown by FontResourceSnapshot.resolve, because a missing face is an ordinary condition — layout falls back and carries on. It extends Error so a caller that would rather throw can.

declare class FontResolutionError extends Error
MemberTypeSummary
(constructor)Constructs a new instance of the `FontResolutionError` class
actual?number
actualHash?string
codeFontResolutionErrorCode
diagnostic?string
expectedHash?string
limit?number
name
requestFontRequest

Interfaces (33)

BulletPictureinterfaceSource ↗

The picture of a picture bullet, as paint draws it.

interface BulletPicture
MemberTypeSummary
heightnumberThe picture's height, EMU.
partstringThe part whose relationships resolve `rId` and `svgRId`.
rIdstringThe relationship of the raster picture (`a:blip/@r:embed`).
svgRId?stringThe relationship of an `asvg:svgBlip` alternative, when present.

CellLayoutinterfaceSource ↗

One drawn cell: its box in the frame and its text.

interface CellLayout
MemberTypeSummary
cellResolvedTableCell
heightnumber
paintBorders?CellBordersBorder paint overrides when native dash expansion exceeds the resource limit.
textTextLayout
widthnumber
xnumber
ynumber

ComposeFontOriginsOptionsinterfaceSource ↗

Diagnostics hook for ordered font-origin composition.

interface ComposeFontOriginsOptions
MemberTypeSummary
onOriginFailure?(failure: FontOriginFailure) => voidFire-and-forget diagnostics; returned promises are observed but do not delay resolution.

ConnectionSiteinterface

One connection site of a geometry, in shape-local EMU.

interface ConnectionSite
MemberTypeSummary
anglenumberThe angle a connector leaves the site at, in degrees clockwise from the +x axis.
xnumberThe site's x, shape-local EMU.
ynumberThe site's y, shape-local EMU.

DrawingCapabilitiesinterfaceSource ↗

What the installed drawing renderers paint in this process.

interface DrawingCapabilities
MemberTypeSummary
chartbooleanCharts draw from their cached values (`@pptx-editor.dev/pro/drawing`). Without it, a chart frame keeps its labeled placeholder.
effectsbooleanGlow, inner shadow, reflection, soft edge, blur, and 3-D paint (`@pptx-editor.dev/pro/drawing`).

EvaluatedGeometryinterface

Evaluated geometry: paths and the text rectangle (shape-local EMU).

interface EvaluatedGeometry
MemberTypeSummary
pathsreadonly GeometryPath[]
textRect{ readonly l: number; readonly t: number; readonly r: number; readonly b: number; }
unknownPreset?stringTrue when the preset name is unknown and a rectangle was substituted.

FaceMetricsinterfaceSource ↗

Face metrics in em units (font size = 1). Ascent and descent are positive.

interface FaceMetrics
MemberTypeSummary
ascentnumber
descentnumber
lineGapnumber
strikeoutPosition?numberThe face's `OS/2` `yStrikeoutPosition`, above the baseline, when the face has usable strikeout values. Paint centers the strikethrough on it.
strikeoutThickness?numberThe face's `OS/2` `yStrikeoutSize`: the strikethrough thickness.
underlinePositionnumber
underlineThicknessnumber

FontConfigurationBaseinterfaceSource ↗

The base of a composition: everything a FontConfiguration carries, all optional. Omitted fields take the documented defaults (epoch 0, maxFontBytes at the engine hard maximum, defaultFont Calibri at 11pt — the default face and size).

interface FontConfigurationBase extends FontConfigurationFragment
MemberTypeSummary
defaultFont?FontConfiguration['defaultFont']The face used when a run names no font. Defaults to Calibri at 11pt.
epoch?numberIdentity of this configuration's byte set. The engine uses it to tell one resolved font set from another; leave it unset and the editor supplies the load sequence.
language?stringBCP-47 tag passed to the shaper for language-sensitive shaping.
maxFontBytes?numberPer-face byte ceiling. Defaults to the engine hard maximum; lower it to tighten intake.

FontConfigurationFragmentinterfaceSource ↗

A partial font configuration one origin contributes: sources, substitutions, or both. loadDefaultFonts() (the substitute package) and loadFonts() (the fetch helper) both return this shape, so every origin composes through composeFontConfiguration the same way.

interface FontConfigurationFragment
MemberTypeSummary
deferred?Promise<FontConfigurationFragment | undefined>Faces that arrive after the document first paints. The editor lays the document out with `sources` and `substitutions`, then lays it out again once this settles. Use it for large faces, such as CJK fonts, that would otherwise hold back the first paint.
sources?readonly FontSource[]
substitutions?readonly FontSourceSubstitution[]
supportedFamilies?readonly string[]Selectable provider families, independent of loaded bytes. Listing them performs no fetch.

FontOriginFailureinterfaceSource ↗

A failed font origin or a partial failure in an otherwise usable fragment.

interface FontOriginFailure
MemberTypeSummary
causeunknown
originIndexnumberZero-based position in the first-wins origin list.
originName?stringResolver function name when one is safely available.

FontRequestinterfaceSource ↗

A font request from a run.

interface FontRequest
MemberTypeSummary
boldboolean
familystring
italicboolean
lang?stringThe language of East Asian text (a BCP 47 tag, `lang` or `altLang`): it orders the East Asian fallback faces, so Chinese and Korean text draw with their own glyph forms.
script?'eastAsian'The script of the text the face draws. `eastAsian` text (the `a:ea` slot) whose family is missing falls back to an East Asian face (`eastAsianFallbackFamilies`) before `DEFAULT_FALLBACK_FAMILY`. Absent for Latin text.

FontResolutionRequestinterfaceSource ↗

What the document turned out to need, handed to an on-demand resolver.

The families are the ones the file actually names — already name-validated and capped, so a resolver may treat them as a list to look up, never as URLs or paths to build.

interface FontResolutionRequest
MemberTypeSummary
defaultFamilystringThe face a run naming no font resolves to, so a resolver can cover it too.
familiesreadonly string[]Families needed by the document, deduped and capped at [MAX_RESOLVER_FAMILIES](MAX_RESOLVER_FAMILIES). Order is deterministic but may express host priority; do not sort it before resolving.
resolvedFaces?readonly FontFaceRequest[]Faces an EARLIER origin in the same composition can already PAINT — either because it supplied the bytes, or because it mapped that face onto one it did supply.
signal?AbortSignalCancels document-scoped resolution; network-backed resolvers should pass it to fetch.

FontResolverMarkinterfaceSource ↗

The type-level half of the mark: what [defineFontResolver](defineFontResolver) adds to a function's type so a FontOrigin list can REQUIRE it.

Declared with a string key so @docx-editor.dev/fonts can declare an identical interface and have the two unify without importing anything from the engine. Set at runtime as well as in the type — non-enumerable, so it stays out of Object.keys and out of a host's own spread.

interface FontResolverMark
MemberTypeSummary
"docx-editor.dev/font-resolver"trueAlways `true`. Set non-enumerably by [defineFontResolver](defineFontResolver).

FontSourceinterfaceSource ↗

One font face the host makes available: family name, style, and sfnt bytes.

interface FontSource
MemberTypeSummary
boldboolean
bytesUint8Array
familystring
italicboolean
originstringWhere the bytes came from, for the report: `embedded`, `substitute`, `system`, or `HOST_SUBSTITUTE_ORIGIN`.

GeometryPathinterface

One evaluated path with its fill mode and stroke flag.

interface GeometryPath
MemberTypeSummary
commandsreadonly PathCommand[]
fill'none' | 'norm' | 'lighten' | 'lightenLess' | 'darken' | 'darkenLess'
strokeboolean

GlyphRuninterfaceSource ↗

One positioned glyph run on a line.

interface GlyphRun
MemberTypeSummary
faceResolvedFace
kind'text' | 'bullet'
picture?BulletPictureThe picture of a picture bullet (`a:buBlip`). Such a run has no text, and `x` holds its left and right edge. The picture stands on the baseline.
propsRunProps
risenumberBaseline shift in EMU (positive raises).
rtl?trueThe run reads right to left: its units stand in visual order from right to left.
runIndexnumberIndex into the paragraph's runs (-1 for bullets).
sizePtnumberRendered size in points (after autofit and script scaling).
startnumberSource offset of `text[0]` within the paragraph.
textstringDisplay text (after caps).
xreadonly number[]Left edge of each UTF-16 unit, EMU from the text box left. Length = text.length + 1. In a run that reads right to left (`rtl`), the values are the cell edges from left to right, and unit `i` draws in cell `text.length - 1 - i`.

ItemPlacementinterfaceSource ↗

Where an item sits: its parent space → slide, and its box → the file's coordinates.

interface ItemPlacement
MemberTypeSummary
parentMatrixMatrix
toSourceSourceMap | null

KinsokuListsinterfaceSource ↗

Kinsoku lists: characters that may not start a line, and characters that may not end one.

interface KinsokuLists
MemberTypeSummary
notEndstringCharacters that may not end a line.
notStartstringCharacters that may not start a line.

LineinterfaceSource ↗

One laid-out line.

interface Line
MemberTypeSummary
baselinenumber
bidi?LineBidiThe units in visual order (UAX #9), absent where they read in source order.
caretXreadonly number[]x of each source offset from start to end inclusive, for caret placement.
columnnumberColumn index (multi-column bodies).
endnumber
fontHeightnumberHeight of the tallest font, for the caret.
heightnumber
marks?readonly LineMark[]The marks of the line's equations (`a14:m`). The glyphs of an equation are text runs of the line, each at its own size and rise; the equation is one object character in the source.
paragraphnumber
pendingBullet?GlyphRunThe bullet or number of an empty list item. An empty item shows none, so paint ignores it; the editor draws it dimmed while the caret is in the paragraph.
runsreadonly GlyphRun[]
startnumberSource offsets covered: [start, end).
topnumberTop of the line box and its baseline, EMU from the text box top.

LineBidiinterfaceSource ↗

The visual order of a line's units (Line.bidi).

interface LineBidi
MemberTypeSummary
paragraphRtlbooleanThe paragraph reads right to left (`a:pPr/@rtl`).
rtlreadonly boolean[]Whether each unit, `end - start` values from `start`, reads right to left.
trailingXreadonly number[]The trailing edge of each unit: its right edge, or its left edge when it reads right to left. `Line.caretX` holds the leading edges.

LineMarkinterfaceSource ↗

A shape that an equation draws itself: a fraction rule, a radical sign, a stretched delimiter, a brace, or an arrow. Paint fills it (nonzero) with the run's fill.

interface LineMark
MemberTypeSummary
commandsreadonly PathCommand[]The outline: x in EMU from the text box left, y in EMU up from the line's baseline.
propsRunProps
runIndexnumberIndex into the paragraph's runs: the math run.

PresetAdjustmentinterface

One adjust value of a preset (a:avLst/a:gd), with the range of the handle that moves it.

interface PresetAdjustment
MemberTypeSummary
anglebooleanAn angle (`a:ahPolar/@gdRefAng`).
maxnumber | null
minnumber | nullThe handle range at this size, or null when the preset gives none.
namestring
valuenumberThe value in guide units: 1/100 000 for a length, 1/60 000 of a degree for an angle.

PresetHandleinterface

One adjust handle of a shape, in shape-local EMU, with the guides it moves.

interface PresetHandle
MemberTypeSummary
guidesreadonly string[]The adjust guides this handle moves (`a:avLst` names): x and y, or radius and angle.
kind'xy' | 'polar'
xnumber
ynumber

PresetShapeDefinitioninterface

One preset shape: adjust defaults, guides, text rectangle, and paths.

interface PresetShapeDefinition
MemberTypeSummary
ah?readonly (readonly [ string, 'x' | 'y' | 'r' | 'ang', string | null, string | null ])[]Adjust handles (`a:ahLst`): the guide each handle moves, its axis (`x`, `y`, `r`, or `ang` for an angle), and its minimum and maximum as a guide name or a literal, or null.
avreadonly (readonly [string, string])[]
cxn?readonly (readonly [string, string, string])[]Connection sites (`a:cxnLst`, ECMA-376 Part 1, 20.1.9.10): the angle a connector leaves the site at, and the site's position, each as a guide name or a literal.
gdreadonly (readonly [string, string])[]
hp?readonly (readonly [ 'xy' | 'polar', string, string, string | null, string | null ])[]Adjust handle places (`a:ahXY` and `a:ahPolar` with their `a:pos`), in `a:ahLst` order: the kind, the position as guide names or literals, and the guides the handle moves (x and y, or radius and angle), each null when the handle does not move it.
pathsreadonly PresetPath[]
rect?readonly [string, string, string, string]Text rectangle as guide names: l, t, r, b.

RegisteredFaceinterfaceSource ↗

A registered face: the source plus the internal id paint uses.

interface RegisteredFace extends FontSource
MemberTypeSummary
idstring

ResolvedFaceinterfaceSource ↗

The face that measures and paints a request.

interface ResolvedFace
MemberTypeSummary
boldboolean
familystringThe family the face actually is (for diagnostics and the fidelity report).
idstringThe internal family name paint must use, so paint draws exactly the measured bytes.
italicboolean
metricsFaceMetrics
substitutedbooleanTrue when the requested family was not available and a substitute answered.
synthBoldbooleanThe request asked for bold/italic the face does not have: paint synthesizes it.
synthItalicboolean

RunGlyphinterfaceSource ↗

One character of a glyph run, at its place on the line.

interface RunGlyph
MemberTypeSummary
charstringThe character to draw: in a right-to-left run, the mirror of a mirrored character (L4).
indexnumberUTF-16 offset of the character in the run's text.
xnumberThe left edge of its cell, EMU from the text box left.

SlideLayoutinterfaceSource ↗

A laid-out slide.

interface SlideLayout
MemberTypeSummary
diagnosticsreadonly string[]For the fidelity report: unknown presets, substituted fonts, unrendered effects and frames, and `approximation: <id>` for each known approximation the slide uses.
itemsreadonly LayoutItem[]
slideResolvedSlide

SourceMapinterfaceSource ↗

Maps a group child's laid-out box back to the file: x_file = x / sx + ox, cx_file = cx / sx. Null for top-level elements, whose boxes are the file's.

interface SourceMap
MemberTypeSummary
oxnumber
oynumber
sxnumber
synumber

TableLayoutinterfaceSource ↗

A laid-out table. columnX and rowY hold every grid line, first to last.

interface TableLayout
MemberTypeSummary
cellsreadonly CellLayout[]Drawn cells only (merge anchors), in row-major order.
columnXreadonly number[]Column lines from the frame's left edge, in visual order (mirrored for `rtl`).
heightnumber
rowYreadonly number[]
rtlbooleanThe table runs right to left (`a:tblPr/@rtl`): grid column 0 is drawn at the right.
widthnumber

TextLayoutinterfaceSource ↗

Text layout result, in the text box's own frame.

interface TextLayout
MemberTypeSummary
box{ readonly x: number; readonly y: number; readonly width: number; readonly height: number; }The inner text box (after insets) in shape-local EMU, before rotation.
contentHeightnumberHeight the text needs in its own frame, EMU, insets included (for autofit). With columns, the box height, or more when the last column runs below the box.
linesreadonly Line[]
paragraphLengthsreadonly number[]Paragraph source lengths, for caret navigation.
rotationnumberRotation applied around the box center: 0, 90, or 270 plus `bodyPr/@rot`.
substitutionsreadonly string[]Families that were not available and were substituted.
upright'none' | 'eastAsian' | 'all'Characters paint draws upright inside a rotated line: East Asian characters for `eaVert`, every character for `wordArtVert`, none otherwise.
warped?readonly WarpedRun[]The glyphs of a warped text body (`a:prstTxWarp`) as paths in this frame, one entry for each run that draws. Paint fills these instead of drawing the runs as text; the lines keep the flat layout, for the caret and the selection.

TextMeasurerinterfaceSource ↗

The measurer port.

interface TextMeasurer
MemberTypeSummary
advancesAdvances in em per UTF-16 code unit. A cluster's whole advance sits on its first unit and the rest of the cluster's units are 0, so offsets map to positions without a cluster table.
fallbackFaceAnother face that draws a character `face` lacks: the East Asian fallback faces first for East Asian characters (in the order of `lang`), then each other face in registration order. Undefined when `face` has the character or no face has it. Optional: a measurer without it measures a missing character with an estimated width (the "Missing glyphs" approximation).
glyphOutlineThe outline of the glyph that the face's character map gives a character, in em with y up and the origin on the baseline at the glyph's start. Undefined when the face lacks the character or its outline, and when the outline has more than 2,000 commands. Optional: without it, warped text (`a:prstTxWarp`) draws flat.
resolve

WarpedRuninterfaceSource ↗

The warped paths of one glyph run: its glyphs, its bars, and its highlight.

interface WarpedRun
MemberTypeSummary
glyphsreadonly PathCommand[]The glyph outlines and the strikethrough, in the text frame (EMU, y down). Fill nonzero.
highlightreadonly PathCommand[]The highlight behind the run.
linenumberThe index of the line in `TextLayout.lines`, and of the run in that line.
picture?{ readonly origin: readonly [number, number]; readonly across: readonly [number, number]; readonly down: readonly [number, number]; }The picture of a picture bullet, as a parallelogram in the text frame (EMU): the warped place of its top-left corner, and the vectors to its top-right and bottom-left corners. The picture does not bend; it turns and stretches with the warp at its corners.
runnumber
underlinereadonly PathCommand[]The underline bars, filled with the underline fill.

Type aliases (10)

FontByteValidatortypeSource ↗

The injected check that bytes really are a font.

Injected because it is the shaper that knows — HarfBuzz can open a face and read its tables, and this layer must not duplicate that judgement. Every byte reaching it is file input.

type FontByteValidator = (bytes: Uint8Array, faceIndex: number) => FontValidationResult;

FontCatalogConfigurationtypeSource ↗

A configuration in either public spelling — full or fragment-with-defaults.

type FontCatalogConfiguration = FontConfiguration | FontConfigurationBase;

FontOrigintypeSource ↗

ONE font origin, in the one shape every origin takes: a finished configuration, a fragment, a promise for either, or a marked resolver that answers per document.

The point of the union is that packagedFonts(), googleFonts(), await defaultFonts() and a hand-built { sources } are all the same kind of thing, so a list of them needs no ordering rule beyond "first wins".

The resolver arm is [MarkedFontResolver](MarkedFontResolver), not bare FontResolver: a list may also hold a zero-argument loader, and only the mark separates the two.

type FontOrigin = FontConfiguration | FontConfigurationFragment | MarkedFontResolver | Promise<FontConfiguration | FontConfigurationFragment | undefined> | undefined;

FontResolutionErrorCodetypeSource ↗

Why a face was not admitted.

forbidden and hashMismatch are adversarial signals rather than ordinary failures: the first is a face the host declared off-limits, the second is bytes that are not what their source claimed.

type FontResolutionErrorCode = 'missing' | 'forbidden' | 'overLimit' | 'malformed' | 'hashMismatch';

FontResolvertypeSource ↗

Resolve fonts once the document's needs are known, instead of ahead of them.

Called after the file is mounted and again when editing requests a new family. Results compose with previously supplied faces; resolvedFaces identifies that coverage. Returning nothing is a valid answer — it means "I cover none of this", and the document stays on the fixed measurer.

A resolver that fetches makes opening a document perform network requests. That is a real change in posture and it must stay the APP's decision: the engine never supplies one, and the families here are file-derived, so a resolver must look them up in a set it shipped rather than interpolate them into a URL.

type FontResolver = (request: FontResolutionRequest) => FontConfiguration | FontConfigurationFragment | undefined | Promise<FontConfiguration | FontConfigurationFragment | undefined>;

FontValidationResulttypeSource ↗

Whether bytes parse as a usable font, with a diagnostic when they do not.

type FontValidationResult = {
    readonly valid: true;
} | {
    readonly valid: false;
    readonly diagnostic: string;
};

LayoutItemtypeSource ↗

One positioned element. matrix maps the element's local box to slide EMU.

type LayoutItem = ItemPlacement & ({
    readonly kind: 'shape';
    readonly element: ResolvedShape;
    readonly matrix: Matrix;
    readonly geometry: EvaluatedGeometry;
    readonly paintLine?: ResolvedLine;
    readonly text?: TextLayout;
    readonly textMatrix?: Matrix;
} | {
    readonly kind: 'picture';
    readonly element: ResolvedPicture;
    readonly matrix: Matrix;
    readonly geometry: EvaluatedGeometry;
    readonly paintLine?: ResolvedLine;
} | {
    readonly kind: 'group';
    readonly element: ResolvedGroup;
    readonly matrix: Matrix;
    readonly children: readonly LayoutItem[];
} | {
    readonly kind: 'frame';
    readonly element: ResolvedGraphicFrame;
    readonly matrix: Matrix;
    readonly table?: TableLayout;
    readonly poster?: Extract<LayoutItem, {
        kind: 'picture';
    }>;
    readonly drawing?: readonly LayoutItem[];
    readonly chart?: readonly LayoutItem[];
});

MarkedFontResolvertypeSource ↗

A [FontResolver](FontResolver) that has been through [defineFontResolver](defineFontResolver).

This, not bare FontResolver, is what a FontOrigin list accepts. The mark is the only thing separating a resolver from a zero-argument loader, and getting that wrong loses every font silently, so the type asks for it up front.

type MarkedFontResolver<T extends FontResolver = FontResolver> = T & FontResolverMark;

MatrixtypeSource ↗

An affine matrix [a, b, c, d, e, f] (SVG convention). EMU units.

type Matrix = readonly [number, number, number, number, number, number];

PathCommandtype

One evaluated path command, absolute shape-local EMU. Arcs are already cubic Béziers.

type PathCommand = {
    readonly op: 'M' | 'L';
    readonly x: number;
    readonly y: number;
} | {
    readonly op: 'C';
    readonly x1: number;
    readonly y1: number;
    readonly x2: number;
    readonly y2: number;
    readonly x: number;
    readonly y: number;
} | {
    readonly op: 'Q';
    readonly x1: number;
    readonly y1: number;
    readonly x: number;
    readonly y: number;
} | {
    readonly op: 'Z';
};

Variables (20)

boundedStructuralFontValidatorconstSource ↗

Bounded minimum sfnt/TTC check; Task 4 supplies full parser-backed validation.

boundedStructuralFontValidator: FontByteValidator

DEFAULT_FALLBACK_FAMILYconstSource ↗

The face used when nothing else matches.

DEFAULT_FALLBACK_FAMILY = "Liberation Sans"

DEFAULT_FONTconstSource ↗

The document default font when nothing else says otherwise: Calibri at 11pt.

DEFAULT_FONT: FontConfiguration['defaultFont']

EAST_ASIAN_FALLBACK_FAMILIESconstSource ↗

The faces that draw East Asian text whose own family is missing, in order, when the host supplies one, for Japanese text or text with no language: the pan-CJK face of @docx-editor.dev/fonts-cjk (Noto Sans CJK JP), the regional Noto Sans faces of googleFonts({ cjk: true }), and the Noto Sans CJK faces a system may have. They cover the text, not the original's metrics. eastAsianFallbackFamilies gives the order for a language.

EAST_ASIAN_FALLBACK_FAMILIES: readonly string[]

FONT_RESOLVER_BRANDconstSource ↗

The runtime marker defineFontResolver sets and [isFontResolver](isFontResolver) reads.

Exported because a package mirroring the font contract structurally still has to mark the resolvers it builds. A package in that position sets Symbol.for('docx-editor.dev/font-resolver') itself; this constant is the same symbol, named, for everyone who can import it.

FONT_RESOLVER_BRAND: unique symbol

FONT_RESOLVER_MARK_KEYconstSource ↗

The namespaced key carrying the type-level half of the mark, and the runtime property name that backs it.

A plain string rather than a symbol on purpose: @docx-editor.dev/fonts has no runtime or type dependency on the engine, so it declares the same mark itself, and two unique symbols in two packages would not unify. Two identical string keys do.

FONT_RESOLVER_MARK_KEY = "docx-editor.dev/font-resolver"

FONT_SUBSTITUTESconstSource ↗

Metric-compatible substitutes for faces that cannot ship (from @docx-editor.dev/fonts), and close open alternatives for common presentation faces. Keys are lower case.

FONT_SUBSTITUTES: Readonly<Record<string, readonly string[]>>

HARD_MAX_AGGREGATE_FONT_BYTESconstSource ↗

Most bytes all admitted faces may total, whatever a caller configures.

HARD_MAX_AGGREGATE_FONT_BYTES: number

HARD_MAX_FONT_BYTESconstSource ↗

Largest single face this engine will ever admit, whatever a caller configures.

A CEILING, not a default: a host may set a smaller maxFontBytes, but nothing can raise it past this. Font bytes come from files, and an unbounded face is a memory-exhaustion vector.

HARD_MAX_FONT_BYTES: number

HARD_MAX_FONT_SOURCESconstSource ↗

Most faces one snapshot may hold, whatever a caller configures.

HARD_MAX_FONT_SOURCES = 256

HARFBUZZ_VERSIONconstSource ↗

The HarfBuzz build the engine measures with. A different runtime is refused.

HARFBUZZ_VERSION = "15.0.0"

HOST_SUBSTITUTE_ORIGINconstSource ↗

The origin of a host substitution's face: the face of another family, registered under the family that the deck names.

HOST_SUBSTITUTE_ORIGIN = "host-substitute"

IDENTITYconstSource ↗

IDENTITY: Matrix

MAX_RESOLVER_FAMILIESconstSource ↗

Ceiling on the families one document can put in front of a resolver.

A resolver typically turns each family into up to four faces, and the resource snapshot refuses more than HARD_MAX_FONT_SOURCES (256) sources — so 64 families is the point past which a document could no longer be served anyway. Capping here means a file declaring thousands of distinct w:rFonts cannot fan a resolver out across thousands of lookups (or fetches) before that limit is ever reached.

MAX_RESOLVER_FAMILIES = 64

METRIC_COMPATIBLEconstSource ↗

Substitutes built to match the original's advance widths (@docx-editor.dev/fonts): line breaks match the original font, only glyph shapes differ. Every other substitution can change line breaks. Keys are lower case.

METRIC_COMPATIBLE: Readonly<Record<string, string>>

PICTURE_BULLET_SCALEconstSource ↗

The height of a picture bullet over its bullet size: measured on reference PDFs, where the picture is 0.7 times the bullet size high, whatever the text's face, and keeps its aspect.

PICTURE_BULLET_SCALE = 0.7

SCRIPT_SIZE_SCALEconstSource ↗

Superscript/subscript (baseline ≠ 0) shrink runs to this fraction (measured).

SCRIPT_SIZE_SCALE: number

SINGLE_LINE_FACTORconstSource ↗

Line pitch multiplier for 100% spacing.

SINGLE_LINE_FACTOR = 1.2

SMALL_CAPS_SCALEconstSource ↗

Small caps render lowercase letters at this fraction of the size.

SMALL_CAPS_SCALE = 0.8

WORD_DEFAULT_FONTconstSource ↗

Deprecated. Use [DEFAULT_FONT](DEFAULT_FONT).

The DOCX Editor default font, under the name DOCX Editor's font-composition.ts exports. This module keeps the copied API equal to DOCX Editor's, so the name stays; it is the same value as [DEFAULT_FONT](DEFAULT_FONT).

WORD_DEFAULT_FONT: FontConfiguration['defaultFont']