Initial Commit
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
# render-pipeline
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Internal pipeline helpers that the top-level `renderDocument`
|
||||
orchestrator delegates to. Splitting placement and slot-rendering out
|
||||
of the orchestrator keeps each file under the 300-line hard limit
|
||||
and lets callers test the per-node placement protocol in isolation
|
||||
from the page-emit loop. The pipeline is stateless across calls — every
|
||||
operation receives a `PipelineState` bundle (writer, layout engine,
|
||||
style resolver, image registry, abort signal, page counter) and
|
||||
mutates only the writer and the page counter.
|
||||
|
||||
## Features
|
||||
|
||||
- `placeNode` dispatches on the discriminated `DocumentNode` union
|
||||
and returns either a content-stream snippet or the `"page-break"`
|
||||
sentinel that signals the orchestrator to flush + restart.
|
||||
- Tables emit a `continuation` descriptor (`{ table, rowStart }`)
|
||||
when they partially fit, so the orchestrator can resume on the
|
||||
next page without re-measuring the full table.
|
||||
- `renderTableSlice` swallows `PDF.LAYOUT_OVERFLOW` from
|
||||
`TableElement.renderPage` and surfaces it as a `rowEnd === rowStart`
|
||||
no-progress result.
|
||||
- `renderSlot` flows header / footer nodes top-to-bottom inside the
|
||||
reserved slot rectangle.
|
||||
- `pickFontResource` re-uses the writer's idempotent font registry so
|
||||
one `F<id>` survives the whole render.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
import { placeNode, renderSlot, type PipelineState } from "@suaveplan/pdf";
|
||||
|
||||
const state: PipelineState = { writer, layout, styles, images, signal: undefined, pageCount: 0 };
|
||||
const result = placeNode(state, node, cursor, undefined, new Map());
|
||||
if (result === "page-break") {
|
||||
// orchestrator: flush and retry
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
import { placeNode, renderTableSlice, renderSlot } from "@suaveplan/pdf";
|
||||
|
||||
// Slice rendering protocol — orchestrator advances rowStart between calls.
|
||||
let rowStart = 0;
|
||||
while (rowStart < tableElement.options.rows.length) {
|
||||
const slice = renderTableSlice(state, tableElement, rowStart, cursor, config);
|
||||
if (slice.rowEnd === rowStart) {
|
||||
// No progress — caller must flush + create a fresh cursor.
|
||||
break;
|
||||
}
|
||||
rowStart = slice.rowEnd;
|
||||
// ... write slice.stream into the per-page buffer ...
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `placeNode(state, node, cursor, config?, pageXObjects)` →
|
||||
`PlacementResult`.
|
||||
- `renderTableSlice(state, table, rowStart, cursor, config?)` →
|
||||
`{ stream, rowEnd }`.
|
||||
- `renderSlot(state, nodes?, height?, slot, config?, pageXObjects)` →
|
||||
`string[]`.
|
||||
- `pickFontResource(state, style)` → `"F<id>"`.
|
||||
- Types: `PipelineState`, `PlacementResult`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
`placeNode` always measures first, then conditionally advances the
|
||||
cursor. Text and divider elements pass the pre-advance `cursor.y` as
|
||||
the render `y` (PDF's bottom-up coordinate system means the top of
|
||||
the element lives at the larger `y`, and the element's `.render()`
|
||||
contract places baselines at `y - i·lineHeight`). Images measure
|
||||
once and ignore `maxWidth` because their bounds are fixed at
|
||||
construction. Tables short-circuit through `TableElement.render`
|
||||
when the whole element fits and only fall back to the slice
|
||||
protocol when pagination is required. The slot renderer flows
|
||||
nodes downward inside the reserved rectangle, which means a footer
|
||||
slot with two stacked text lines places the first line at the slot
|
||||
top and the second below — matching the visual expectation that
|
||||
flow content reads top-to-bottom regardless of PDF's bottom-up
|
||||
geometry.
|
||||
Reference in New Issue
Block a user