# Text geometry

The optional `@pibbl/text` package converts one text run into editable
[`PathGeometry`](/reference/functions/path-geometry/). HarfBuzz shapes the whole run,
including kerning, ligatures, and mark positioning, before Pibbl copies its outlines
into independent geometry. Importing the package does not initialize WASM.

```ts
import { loadOutlineFont, createTextGeometry } from "@pibbl/text";

async function label(bytes: Uint8Array) {
  using font = await loadOutlineFont(bytes);
  return createTextGeometry(font, "Hello Pibbl", {
    fontSize: 96,
    features: { kern: true, liga: true },
  });
}
```

The returned geometry remains usable after the font is disposed. Pass it to
`<Path style={{ d: result.geometry, fill: "teal" }} />`, inspect its segments,
or edit its control points. Geometry mutation does not schedule a repaint;
update a signal or state after editing, as in the
[editable text example](/playground/#/examples/drawing/text-geometry).

## Load and own a font

`loadOutlineFont(source, options?)` accepts a URL string, `URL`, `ArrayBuffer`,
or `Uint8Array`. Strings mean URLs; Node callers read filesystem bytes themselves.
An offset typed-array view is respected and copied before asynchronous work.
`OutlineFontOptions.signal` cancels a download. Failed or canceled acquisition
returns no font owner.

`OutlineFont` implements `dispose()` and `[Symbol.dispose]()` with the same
synchronous, idempotent cleanup. Use `using font = await loadOutlineFont(...)`
for a local conversion or retain one font across edits and call `dispose()` on
teardown. A retained font must outlive every conversion that uses it. Loading
belongs outside Pibbl's synchronous component evaluation.

`using` requires runtime `Symbol.dispose` support and a compatible syntax target
or compiler transform. TypeScript consumers include `ESNext.Disposable` (or
`ESNext`) in their configured libraries. Pibbl does not install a global polyfill. Explicit
`dispose()` works without `using` syntax. Generated paths and metrics hold no
borrowed WASM views. Disposing a font releases its native resources; the shared
WASM memory may retain its high-water capacity for later reuse.

Supported containers are outline TTF and OTF (quadratic TrueType and cubic CFF
outlines). WOFF, WOFF2, collections, and system-font/CSS lookup are not supported.
No font fallback is performed. Variable fonts use their default instance; there
is no axis or face-selection API in this release.

Fonts declaring COLR, SVG, sbix, CBDT, or EBDT presentation tables are rejected by
default. Set `monochromeFallback: true` to explicitly request their ordinary
outlines. This does not convert colors, bitmap images, or SVG artwork; a usable
outline is still required. The check is conservative for the entire font.

## Convert one run

`createTextGeometry(font, text, options)` is synchronous. `TextGeometryOptions`
requires a finite positive `fontSize` in logical units. Optional fields are:

| Option          | Meaning                                                                              |
| --------------- | ------------------------------------------------------------------------------------ |
| `features`      | Up to 64 four-character OpenType tags mapped to booleans, such as `{ liga: false }`. |
| `direction`     | `"ltr"` or `"rtl"`; otherwise inferred by HarfBuzz.                                  |
| `script`        | Four-character ISO 15924 script tag, such as `"Arab"`.                               |
| `language`      | ASCII language tag, such as `"ar"` or `"en-US"`, up to 63 characters.                |
| `missingGlyphs` | `"error"` (default) or explicit `"notdef"` substitution.                             |
| `maxSegments`   | Integer output limit from 1 to 1,000,000; default 1,000,000.                         |

The origin is baseline `(0, 0)`, with positive Y down. Negative bearings are
preserved. RTL glyphs remain in HarfBuzz's output order. There is no paragraph
bidi algorithm, line wrapping, vertical layout, rich text, caret mapping, or
font fallback. Tabs and line breaks are rejected.

## Results and editing

`TextGeometryResult` contains:

- `geometry`: a new mutable `PathGeometry`, preserving curves and closed contours.
- `advance`: readonly X/Y layout advance, including whitespace.
- `inkBounds`: readonly `InkBounds` (`x`, `y`, `width`, `height`) using curve
  extrema, or `null` for empty ink. This differs from the advance.
- `glyphs`: readonly `TextGlyph` records with `glyphId`, UTF-16 `cluster`,
  `segmentStart`, `segmentCount`, `x`, `y`, `xAdvance`, and `yAdvance`.

Clusters are source string indices, not character, grapheme, or caret indices.
Several glyphs may share a cluster, and RTL cluster indices can descend.
Whitespace may have advance and zero segments. Metadata describes the initial
conversion: later edits do not update its segment ranges, metrics, or bounds.
No per-glyph path copies are created eagerly.

Font inputs are limited to 32 MiB, text to 100,000 UTF-16 units, shaped output to
200,000 glyphs, and extraction to a shared 2²⁴ native work-unit budget. Malformed
inputs, missing glyphs, nonfinite results, and exceeded limits throw without
returning partial geometry. These bounds do not guarantee a shaping timeout.
Reuse fonts and generated paths; do not reshape static text every frame.

## Browser assets

The published package includes precompiled WASM; consumers need no native SDK.
Browser bundlers select browser-only loader code. Bundlers that process
`new URL(..., import.meta.url)` should emit the WASM asset. For a plain esbuild
pipeline, copy `dist/engine.wasm` from the installed package beside the emitted
engine chunk and serve it as `application/wasm`. Test the production output,
including any application base path. Node loading resolves the packaged binary
relative to the installed loader.

Build-time generation is a planned follow-up; the runtime package does not yet
provide a generator or compressed-webfont decoder.

HarfBuzz interns language tags for the shared engine lifetime. To bound that
memory, an engine accepts at most 256 distinct explicit language tags, compared
case-insensitively. Existing tags and inferred language remain usable after that
limit; disposing a font does not reset it.

## API details from source

<span id="api-InkBounds"></span>

### InkBounds

Axis-aligned bounds of visible glyph outlines in logical output coordinates.

```ts
interface InkBounds
```

Related API: [InkBounds](/reference/functions/text-geometry/).

#### See also

[TextGeometryResult](/reference/functions/text-geometry/)

[View source — packages/text/src/lib/bounds.ts:8](/source/packages/text/src/lib/bounds-ts/#L8)

#### Properties and methods

<span id="api-InkBounds-x"></span>
<details>
<summary>x</summary>


```ts
readonly x: number
```

Horizontal coordinate or displacement in the containing coordinate system. See
InkBounds.

[View source — packages/text/src/lib/bounds.ts:13](/source/packages/text/src/lib/bounds-ts/#L13)

</details>

<span id="api-InkBounds-y"></span>
<details>
<summary>y</summary>


```ts
readonly y: number
```

Vertical coordinate or displacement in the containing coordinate system. See InkBounds
.

[View source — packages/text/src/lib/bounds.ts:18](/source/packages/text/src/lib/bounds-ts/#L18)

</details>

<span id="api-InkBounds-width"></span>
<details>
<summary>width</summary>


```ts
readonly width: number
```

Horizontal extent in the units of the containing geometry or surface. See InkBounds.

[View source — packages/text/src/lib/bounds.ts:22](/source/packages/text/src/lib/bounds-ts/#L22)

</details>

<span id="api-InkBounds-height"></span>
<details>
<summary>height</summary>


```ts
readonly height: number
```

Vertical extent in the units of the containing geometry or surface. See InkBounds.

[View source — packages/text/src/lib/bounds.ts:24](/source/packages/text/src/lib/bounds-ts/#L24)

</details>

<span id="api-OutlineFont"></span>

### OutlineFont

An explicitly owned native font loaded for text shaping. Dispose it when no more geometry will be
created from it; disposal is idempotent.

```ts
interface OutlineFont extends Disposable
```

Related API: [OutlineFont](/reference/functions/text-geometry/).

#### See also

[loadOutlineFont](/reference/functions/text-geometry/)

[createTextGeometry](/reference/functions/text-geometry/)

[View source — packages/text/src/index.ts:16](/source/packages/text/src/index-ts/#L16)

#### Properties and methods

<span id="api-OutlineFont-dispose"></span>
<details>
<summary>dispose</summary>


```ts
dispose: () => void
```

Releases the native font owner; repeated calls are harmless and later shaping with this font
fails. See OutlineFont.

[View source — packages/text/src/index.ts:21](/source/packages/text/src/index-ts/#L21)

</details>

<span id="api-OutlineFontOptions"></span>

### OutlineFontOptions

Cancellation and monochrome-fallback policy used when loading an outline font.

```ts
interface OutlineFontOptions
```

Related API: [OutlineFontOptions](/reference/functions/text-geometry/).

#### See also

[loadOutlineFont](/reference/functions/text-geometry/)

[View source — packages/text/src/index.ts:28](/source/packages/text/src/index-ts/#L28)

#### Properties and methods

<span id="api-OutlineFontOptions-signal"></span>
<details>
<summary>signal (optional)</summary>


```ts
signal?: AbortSignal | undefined
```

Related API: [signal](/reference/functions/signal/).

Abort signal for font loading and validation. See OutlineFontOptions.

[View source — packages/text/src/index.ts:30](/source/packages/text/src/index-ts/#L30)

</details>

<span id="api-OutlineFontOptions-monochromeFallback"></span>
<details>
<summary>monochromeFallback (optional)</summary>


```ts
monochromeFallback?: boolean | undefined
```

Allows supported monochrome outlines when the font includes color glyph data. See
OutlineFontOptions.

[View source — packages/text/src/index.ts:35](/source/packages/text/src/index-ts/#L35)

</details>

<span id="api-TextGeometryOptions"></span>

### TextGeometryOptions

Font size, shaping direction, OpenType features, and work limits for one text run.

```ts
interface TextGeometryOptions
```

Related API: [TextGeometryOptions](/reference/functions/text-geometry/).

#### See also

[createTextGeometry](/reference/functions/text-geometry/)

[View source — packages/text/src/index.ts:42](/source/packages/text/src/index-ts/#L42)

#### Properties and methods

<span id="api-TextGeometryOptions-fontSize"></span>
<details>
<summary>fontSize</summary>


```ts
fontSize: number
```

Positive finite output font size in logical units. See TextGeometryOptions.

[View source — packages/text/src/index.ts:44](/source/packages/text/src/index-ts/#L44)

</details>

<span id="api-TextGeometryOptions-maxSegments"></span>
<details>
<summary>maxSegments (optional)</summary>


```ts
maxSegments?: number | undefined
```

Upper bound on the number of output path segments. See TextGeometryOptions.

[View source — packages/text/src/index.ts:46](/source/packages/text/src/index-ts/#L46)

</details>

<span id="api-TextGeometryOptions-missingGlyphs"></span>
<details>
<summary>missingGlyphs (optional)</summary>


```ts
missingGlyphs?: "error" | "notdef" | undefined
```

Whether an absent glyph fails shaping or uses the font's .notdef glyph. See
TextGeometryOptions.

[View source — packages/text/src/index.ts:51](/source/packages/text/src/index-ts/#L51)

</details>

<span id="api-TextGeometryOptions-direction"></span>
<details>
<summary>direction (optional)</summary>


```ts
direction?: "ltr" | "rtl" | undefined
```

Explicit left-to-right or right-to-left shaping direction; omitted direction is inferred. See
TextGeometryOptions.

[View source — packages/text/src/index.ts:56](/source/packages/text/src/index-ts/#L56)

</details>

<span id="api-TextGeometryOptions-script"></span>
<details>
<summary>script (optional)</summary>


```ts
script?: string | undefined
```

Four-character OpenType script tag overriding script inference. See
TextGeometryOptions.

[View source — packages/text/src/index.ts:61](/source/packages/text/src/index-ts/#L61)

</details>

<span id="api-TextGeometryOptions-language"></span>
<details>
<summary>language (optional)</summary>


```ts
language?: string | undefined
```

Language tag used for shaping; distinct interned tags are bounded by the engine. See
TextGeometryOptions.

[View source — packages/text/src/index.ts:66](/source/packages/text/src/index-ts/#L66)

</details>

<span id="api-TextGeometryOptions-features"></span>
<details>
<summary>features (optional)</summary>


```ts
features?: Readonly<Record<string, boolean>> | undefined
```

OpenType feature overrides keyed by four-character tags. See TextGeometryOptions.

[View source — packages/text/src/index.ts:68](/source/packages/text/src/index-ts/#L68)

</details>

<span id="api-TextGlyph"></span>

### TextGlyph

Shaped glyph identity, UTF-16 source cluster, outline segment range, and scaled placement metrics.

```ts
interface TextGlyph
```

Related API: [TextGlyph](/reference/functions/text-geometry/).

#### See also

[TextGeometryResult](/reference/functions/text-geometry/)

[View source — packages/text/src/index.ts:75](/source/packages/text/src/index-ts/#L75)

#### Properties and methods

<span id="api-TextGlyph-glyphId"></span>
<details>
<summary>glyphId</summary>


```ts
readonly glyphId: number
```

Font-specific identifier of the shaped glyph. See TextGlyph.

[View source — packages/text/src/index.ts:77](/source/packages/text/src/index-ts/#L77)

</details>

<span id="api-TextGlyph-cluster"></span>
<details>
<summary>cluster</summary>


```ts
readonly cluster: number
```

UTF-16 offset of the source cluster associated with this glyph. See TextGlyph.

[View source — packages/text/src/index.ts:79](/source/packages/text/src/index-ts/#L79)

</details>

<span id="api-TextGlyph-segmentStart"></span>
<details>
<summary>segmentStart</summary>


```ts
readonly segmentStart: number
```

Index of the glyph's first segment in the returned geometry. See TextGlyph.

[View source — packages/text/src/index.ts:81](/source/packages/text/src/index-ts/#L81)

</details>

<span id="api-TextGlyph-segmentCount"></span>
<details>
<summary>segmentCount</summary>


```ts
readonly segmentCount: number
```

Number of outline segments belonging to this glyph. See TextGlyph.

[View source — packages/text/src/index.ts:83](/source/packages/text/src/index-ts/#L83)

</details>

<span id="api-TextGlyph-x"></span>
<details>
<summary>x</summary>


```ts
readonly x: number
```

Horizontal coordinate or displacement in the containing coordinate system. See
TextGlyph.

[View source — packages/text/src/index.ts:88](/source/packages/text/src/index-ts/#L88)

</details>

<span id="api-TextGlyph-y"></span>
<details>
<summary>y</summary>


```ts
readonly y: number
```

Vertical coordinate or displacement in the containing coordinate system. See TextGlyph
.

[View source — packages/text/src/index.ts:93](/source/packages/text/src/index-ts/#L93)

</details>

<span id="api-TextGlyph-xAdvance"></span>
<details>
<summary>xAdvance</summary>


```ts
readonly xAdvance: number
```

Horizontal pen advance in scaled logical units. See TextGlyph.

[View source — packages/text/src/index.ts:95](/source/packages/text/src/index-ts/#L95)

</details>

<span id="api-TextGlyph-yAdvance"></span>
<details>
<summary>yAdvance</summary>


```ts
readonly yAdvance: number
```

Vertical pen advance in Canvas-oriented logical units. See TextGlyph.

[View source — packages/text/src/index.ts:97](/source/packages/text/src/index-ts/#L97)

</details>

<span id="api-TextGeometryResult"></span>

### TextGeometryResult

Independent path geometry, optional ink bounds, advances, and glyph metadata for a shaped text run.

```ts
interface TextGeometryResult
```

Related API: [TextGeometryResult](/reference/functions/text-geometry/).

#### See also

[PathGeometry](/reference/functions/path-geometry/)

[InkBounds](/reference/functions/text-geometry/)

[TextGlyph](/reference/functions/text-geometry/)

[createTextGeometry](/reference/functions/text-geometry/)

[View source — packages/text/src/index.ts:107](/source/packages/text/src/index-ts/#L107)

#### Properties and methods

<span id="api-TextGeometryResult-geometry"></span>
<details>
<summary>geometry</summary>


```ts
readonly geometry: PathGeometry
```

Related API: [PathGeometry](/reference/functions/path-geometry/).

Independent mutable outline geometry in Canvas-oriented output coordinates. See
PathGeometry.

[View source — packages/text/src/index.ts:112](/source/packages/text/src/index-ts/#L112)

</details>

<span id="api-TextGeometryResult-inkBounds"></span>
<details>
<summary>inkBounds</summary>


```ts
readonly inkBounds: Readonly<InkBounds> | null
```

Related API: [InkBounds](/reference/functions/text-geometry/).

Bounds of visible outlines, or null when the run has no ink. See InkBounds.

[View source — packages/text/src/index.ts:114](/source/packages/text/src/index-ts/#L114)

</details>

<span id="api-TextGeometryResult-advance"></span>
<details>
<summary>advance</summary>


```ts
readonly advance: Readonly<{ x: number; y: number; }>
```

Final pen displacement, including glyph advances even when no ink is drawn. See
TextGeometryResult.

[View source — packages/text/src/index.ts:119](/source/packages/text/src/index-ts/#L119)

</details>

<span id="api-TextGeometryResult-glyphs"></span>
<details>
<summary>glyphs</summary>


```ts
readonly glyphs: readonly TextGlyph[]
```

Related API: [TextGlyph](/reference/functions/text-geometry/).

Ordered shaped-glyph metadata corresponding to the returned outline segments. See
TextGlyph.

[View source — packages/text/src/index.ts:135](/source/packages/text/src/index-ts/#L135)

</details>

<span id="api-loadOutlineFont"></span>

### loadOutlineFont

Loads and validates font bytes from a URL or buffer and returns an explicitly disposable font.
Rejects on cancellation, unsupported font data, or allocation failure.

```ts
loadOutlineFont: (source: string | URL | ArrayBuffer | Uint8Array, options?: OutlineFontOptions) => Promise<OutlineFont>
```

Related API: [loadOutlineFont](/reference/functions/text-geometry/), [OutlineFontOptions](/reference/functions/text-geometry/), [OutlineFont](/reference/functions/text-geometry/).

#### Parameters

- **`source`** — Font URL to fetch, or in-memory font bytes to copy into the shaping engine.

- **`options`** — Cancellation signal and explicit monochrome fallback policy. See
[OutlineFontOptions](/reference/functions/text-geometry/) .

#### Returns

A promise for an owned font; dispose it when no further shaping will use it. See
[OutlineFont](/reference/functions/text-geometry/) .

#### See also

[OutlineFontOptions](/reference/functions/text-geometry/)

[OutlineFont](/reference/functions/text-geometry/)

[View source — packages/text/src/index.ts:157](/source/packages/text/src/index-ts/#L157)

<span id="api-createTextGeometry"></span>

### createTextGeometry

Synchronously shapes a single text run into independent Canvas-oriented outlines. The font must
be live, fontSize positive and finite, and text must not contain line breaks or tabs.

```ts
createTextGeometry: (font: OutlineFont, text: string, options: TextGeometryOptions) => TextGeometryResult
```

Related API: [createTextGeometry](/reference/functions/text-geometry/), [OutlineFont](/reference/functions/text-geometry/), [TextGeometryOptions](/reference/functions/text-geometry/), [TextGeometryResult](/reference/functions/text-geometry/).

#### Parameters

- **`font`** — Live font returned by loadOutlineFont; it must not have been disposed. See
[OutlineFont](/reference/functions/text-geometry/) .

- **`text`** — Text to shape as one run.

- **`options`** — Font size, shaping overrides, missing-glyph policy, and work limits. See
[TextGeometryOptions](/reference/functions/text-geometry/) .

#### Returns

Independent mutable path geometry plus glyph placements, ink bounds, and advances; the
result remains usable after font disposal. See [TextGeometryResult](/reference/functions/text-geometry/) .

#### See also

[OutlineFont](/reference/functions/text-geometry/)

[TextGeometryOptions](/reference/functions/text-geometry/)

[TextGeometryResult](/reference/functions/text-geometry/)

[View source — packages/text/src/index.ts:226](/source/packages/text/src/index-ts/#L226)

## Implementation guidance for agents

Read the [Text outlines and typography companion](/agents/topics/text/) for ownership, adaptation, failure modes, and verification. [Agent start](/agents/) provides the version-selection workflow.

## Complete minimal examples

- [Text outline](/minimal-examples/text/outline/): Load an outline font, shape a text run, and paint its editable path with glyph metrics. [Plain source](/minimal/text/outline.tsx)
## Interactive examples

- [Editable text outlines](/examples/text-geometry/) · [Full page](/experience/text-geometry/)
- [Text envelope playground](/examples/text-envelope/) · [Full page](/experience/text-envelope/)
## Documentation version

Documentation built with @pibbl/core 0.0.2, revision 272a94a. ALPHA — NOT FOR PRODUCTION USE.
