# Functions V–W

Import these from `@grafloria/renderer`.

## Functions

### `viewBoxTransform`

The transform that maps a `viewBox` onto a rect the way `preserveAspectRatio` says
— the fit an inline `<svg>` gets from the browser for free, resolved into an
ordinary affine transform so every target can honour it.

Supports the two forms that actually occur: `none` (stretch each axis
independently) and `x??Y?? meet` (uniform scale, then align). `slice` is treated as
`meet`: over-filling the widget box would paint a chart over its neighbours, and a
chart that is slightly small is a far smaller lie than one that overlaps.

```ts
function viewBoxTransform(
  viewBox: Rectangle,
  rect: { width: number; height: number },
  preserveAspectRatio = 'xMidYMid meet'
): string
```

### `vnodeBounds`

The union box of everything a VNode tree paints, in the tree's own user space.

Returns `null` for a tree that paints nothing (an empty diagram) — the caller
decides what an empty document should be, because "nothing" is not a rectangle.

```ts
function vnodeBounds(root: VNode, options: BoundsOptions = {}): Rectangle | null
```

### `withInlinedImages`

EXTERNAL-URL IMAGES → embedded bytes, for the async export only.

A widget's `<img src="https://…">` captures as `<image href="https://…">`, which an
SVG renders online and a PDF cannot draw at all. The export runs in a browser, which
can usually fetch that URL itself — so every external reference is fetched and swapped
for a `data:` URI, three tiers (see `fetchAssetsTiered`): environment fetch, then
`ExportOptions.assetFetcher`, then the accurate warning.

TWO KINDS OF IMAGE, ONE PASS. Widget captures (`exportOptions.customNodes`) are
substituted here directly. A panel image painted by the RENDERER'S OWN tree is built
inside the synchronous export, so the renderer enumerates those URLs up front
(`collectExportImageUrls`), the fetch covers the UNION (one fetch per URL), and the
resolved map rides down `ExportOptions.resolvedAssets`. A URL the caller pre-resolved
is trusted, never fetched.

THE WARNING LEDGER IS RECONCILED, both ways: a capture whose images were all embedded
loses its capture-time "EXTERNAL URL" caveat; a URL every tier failed on keeps the
reference and gains a warning naming the URL and the reason — a tree image's failure
goes to `onWarnings`.

Run it AFTER the custom-node capture, so the captured images are in the options.

```ts
async function withInlinedImages(
  renderer: ExportImageUrlSource,
  exportOptions: ExportOptions
): Promise<ExportOptions>
```
