@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) => stringsubscribeDrawingRenderersfunctionSource ↗
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| Member | Type | Summary |
|---|---|---|
| (constructor) | | Constructs a new instance of the `FontResolutionError` class |
| actual? | number | |
| actualHash? | string | |
| code | FontResolutionErrorCode | |
| diagnostic? | string | |
| expectedHash? | string | |
| limit? | number | |
| name | | |
| request | FontRequest |
Interfaces (33)
BulletPictureinterfaceSource ↗
The picture of a picture bullet, as paint draws it.
interface BulletPicture| Member | Type | Summary |
|---|---|---|
| height | number | The picture's height, EMU. |
| part | string | The part whose relationships resolve `rId` and `svgRId`. |
| rId | string | The relationship of the raster picture (`a:blip/@r:embed`). |
| svgRId? | string | The relationship of an `asvg:svgBlip` alternative, when present. |
CellLayoutinterfaceSource ↗
One drawn cell: its box in the frame and its text.
interface CellLayout| Member | Type | Summary |
|---|---|---|
| cell | ResolvedTableCell | |
| height | number | |
| paintBorders? | CellBorders | Border paint overrides when native dash expansion exceeds the resource limit. |
| text | TextLayout | |
| width | number | |
| x | number | |
| y | number |
ComposeFontOriginsOptionsinterfaceSource ↗
Diagnostics hook for ordered font-origin composition.
interface ComposeFontOriginsOptions| Member | Type | Summary |
|---|---|---|
| onOriginFailure? | (failure: FontOriginFailure) => void | Fire-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| Member | Type | Summary |
|---|---|---|
| angle | number | The angle a connector leaves the site at, in degrees clockwise from the +x axis. |
| x | number | The site's x, shape-local EMU. |
| y | number | The site's y, shape-local EMU. |
DrawingCapabilitiesinterfaceSource ↗
What the installed drawing renderers paint in this process.
interface DrawingCapabilities| Member | Type | Summary |
|---|---|---|
| chart | boolean | Charts draw from their cached values (`@pptx-editor.dev/pro/drawing`). Without it, a chart frame keeps its labeled placeholder. |
| effects | boolean | Glow, 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| Member | Type | Summary |
|---|---|---|
| paths | readonly GeometryPath[] | |
| textRect | {
readonly l: number;
readonly t: number;
readonly r: number;
readonly b: number;
} | |
| unknownPreset? | string | True 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| Member | Type | Summary |
|---|---|---|
| ascent | number | |
| descent | number | |
| lineGap | number | |
| strikeoutPosition? | number | The face's `OS/2` `yStrikeoutPosition`, above the baseline, when the face has usable strikeout values. Paint centers the strikethrough on it. |
| strikeoutThickness? | number | The face's `OS/2` `yStrikeoutSize`: the strikethrough thickness. |
| underlinePosition | number | |
| underlineThickness | number |
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| Member | Type | Summary |
|---|---|---|
| defaultFont? | FontConfiguration['defaultFont'] | The face used when a run names no font. Defaults to Calibri at 11pt. |
| epoch? | number | Identity 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? | string | BCP-47 tag passed to the shaper for language-sensitive shaping. |
| maxFontBytes? | number | Per-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| Member | Type | Summary |
|---|---|---|
| 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| Member | Type | Summary |
|---|---|---|
| cause | unknown | |
| originIndex | number | Zero-based position in the first-wins origin list. |
| originName? | string | Resolver function name when one is safely available. |
FontRequestinterfaceSource ↗
A font request from a run.
interface FontRequest| Member | Type | Summary |
|---|---|---|
| bold | boolean | |
| family | string | |
| italic | boolean | |
| lang? | string | The 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| Member | Type | Summary |
|---|---|---|
| defaultFamily | string | The face a run naming no font resolves to, so a resolver can cover it too. |
| families | readonly 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? | AbortSignal | Cancels 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| Member | Type | Summary |
|---|---|---|
| "docx-editor.dev/font-resolver" | true | Always `true`. Set non-enumerably by [defineFontResolver](defineFontResolver). |
FontSourceinterfaceSource ↗
One font face the host makes available: family name, style, and sfnt bytes.
interface FontSource| Member | Type | Summary |
|---|---|---|
| bold | boolean | |
| bytes | Uint8Array | |
| family | string | |
| italic | boolean | |
| origin | string | Where 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| Member | Type | Summary |
|---|---|---|
| commands | readonly PathCommand[] | |
| fill | 'none' | 'norm' | 'lighten' | 'lightenLess' | 'darken' | 'darkenLess' | |
| stroke | boolean |
GlyphRuninterfaceSource ↗
One positioned glyph run on a line.
interface GlyphRun| Member | Type | Summary |
|---|---|---|
| face | ResolvedFace | |
| kind | 'text' | 'bullet' | |
| picture? | BulletPicture | The 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. |
| props | RunProps | |
| rise | number | Baseline shift in EMU (positive raises). |
| rtl? | true | The run reads right to left: its units stand in visual order from right to left. |
| runIndex | number | Index into the paragraph's runs (-1 for bullets). |
| sizePt | number | Rendered size in points (after autofit and script scaling). |
| start | number | Source offset of `text[0]` within the paragraph. |
| text | string | Display text (after caps). |
| x | readonly 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| Member | Type | Summary |
|---|---|---|
| parentMatrix | Matrix | |
| toSource | SourceMap | null |
KinsokuListsinterfaceSource ↗
Kinsoku lists: characters that may not start a line, and characters that may not end one.
interface KinsokuLists| Member | Type | Summary |
|---|---|---|
| notEnd | string | Characters that may not end a line. |
| notStart | string | Characters that may not start a line. |
LineinterfaceSource ↗
One laid-out line.
interface Line| Member | Type | Summary |
|---|---|---|
| baseline | number | |
| bidi? | LineBidi | The units in visual order (UAX #9), absent where they read in source order. |
| caretX | readonly number[] | x of each source offset from start to end inclusive, for caret placement. |
| column | number | Column index (multi-column bodies). |
| end | number | |
| fontHeight | number | Height of the tallest font, for the caret. |
| height | number | |
| 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. |
| paragraph | number | |
| pendingBullet? | GlyphRun | The 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. |
| runs | readonly GlyphRun[] | |
| start | number | Source offsets covered: [start, end). |
| top | number | Top 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| Member | Type | Summary |
|---|---|---|
| paragraphRtl | boolean | The paragraph reads right to left (`a:pPr/@rtl`). |
| rtl | readonly boolean[] | Whether each unit, `end - start` values from `start`, reads right to left. |
| trailingX | readonly 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| Member | Type | Summary |
|---|---|---|
| commands | readonly PathCommand[] | The outline: x in EMU from the text box left, y in EMU up from the line's baseline. |
| props | RunProps | |
| runIndex | number | Index 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| Member | Type | Summary |
|---|---|---|
| angle | boolean | An angle (`a:ahPolar/@gdRefAng`). |
| max | number | null | |
| min | number | null | The handle range at this size, or null when the preset gives none. |
| name | string | |
| value | number | The 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| Member | Type | Summary |
|---|---|---|
| guides | readonly string[] | The adjust guides this handle moves (`a:avLst` names): x and y, or radius and angle. |
| kind | 'xy' | 'polar' | |
| x | number | |
| y | number |
PresetShapeDefinitioninterface
One preset shape: adjust defaults, guides, text rectangle, and paths.
interface PresetShapeDefinition| Member | Type | Summary |
|---|---|---|
| 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. |
| av | readonly (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. |
| gd | readonly (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. |
| paths | readonly 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| Member | Type | Summary |
|---|---|---|
| id | string |
ResolvedFaceinterfaceSource ↗
The face that measures and paints a request.
interface ResolvedFace| Member | Type | Summary |
|---|---|---|
| bold | boolean | |
| family | string | The family the face actually is (for diagnostics and the fidelity report). |
| id | string | The internal family name paint must use, so paint draws exactly the measured bytes. |
| italic | boolean | |
| metrics | FaceMetrics | |
| substituted | boolean | True when the requested family was not available and a substitute answered. |
| synthBold | boolean | The request asked for bold/italic the face does not have: paint synthesizes it. |
| synthItalic | boolean |
RunGlyphinterfaceSource ↗
One character of a glyph run, at its place on the line.
interface RunGlyph| Member | Type | Summary |
|---|---|---|
| char | string | The character to draw: in a right-to-left run, the mirror of a mirrored character (L4). |
| index | number | UTF-16 offset of the character in the run's text. |
| x | number | The left edge of its cell, EMU from the text box left. |
SlideLayoutinterfaceSource ↗
A laid-out slide.
interface SlideLayout| Member | Type | Summary |
|---|---|---|
| diagnostics | readonly string[] | For the fidelity report: unknown presets, substituted fonts, unrendered effects and frames, and `approximation: <id>` for each known approximation the slide uses. |
| items | readonly LayoutItem[] | |
| slide | ResolvedSlide |
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| Member | Type | Summary |
|---|---|---|
| ox | number | |
| oy | number | |
| sx | number | |
| sy | number |
TableLayoutinterfaceSource ↗
A laid-out table. columnX and rowY hold every grid line, first to last.
interface TableLayout| Member | Type | Summary |
|---|---|---|
| cells | readonly CellLayout[] | Drawn cells only (merge anchors), in row-major order. |
| columnX | readonly number[] | Column lines from the frame's left edge, in visual order (mirrored for `rtl`). |
| height | number | |
| rowY | readonly number[] | |
| rtl | boolean | The table runs right to left (`a:tblPr/@rtl`): grid column 0 is drawn at the right. |
| width | number |
TextLayoutinterfaceSource ↗
Text layout result, in the text box's own frame.
interface TextLayout| Member | Type | Summary |
|---|---|---|
| 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. |
| contentHeight | number | Height 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. |
| lines | readonly Line[] | |
| paragraphLengths | readonly number[] | Paragraph source lengths, for caret navigation. |
| rotation | number | Rotation applied around the box center: 0, 90, or 270 plus `bodyPr/@rot`. |
| substitutions | readonly 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| Member | Type | Summary |
|---|---|---|
| advances | | Advances 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. |
| fallbackFace | | Another 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). |
| glyphOutline | | The 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| Member | Type | Summary |
|---|---|---|
| glyphs | readonly PathCommand[] | The glyph outlines and the strikethrough, in the text frame (EMU, y down). Fill nonzero. |
| highlight | readonly PathCommand[] | The highlight behind the run. |
| line | number | The 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. |
| run | number | |
| underline | readonly 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: FontByteValidatorDEFAULT_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 symbolFONT_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: numberHARD_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: numberHARD_MAX_FONT_SOURCESconstSource ↗
Most faces one snapshot may hold, whatever a caller configures.
HARD_MAX_FONT_SOURCES = 256HARFBUZZ_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: MatrixMAX_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 = 64METRIC_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.7SCRIPT_SIZE_SCALEconstSource ↗
Superscript/subscript (baseline ≠ 0) shrink runs to this fraction (measured).
SCRIPT_SIZE_SCALE: numberSINGLE_LINE_FACTORconstSource ↗
Line pitch multiplier for 100% spacing.
SINGLE_LINE_FACTOR = 1.2SMALL_CAPS_SCALEconstSource ↗
Small caps render lowercase letters at this fraction of the size.
SMALL_CAPS_SCALE = 0.8WORD_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']