graphitepdf 0.4.0

A Rust PDF rendering engine for layout, composition, and rendering pipelines.
Documentation
# GraphitePDF Architecture

## High-Level Overview

GraphitePDF is now a crate-centric Rust workspace. The primary architecture is no longer rooted in `src/`; it lives in the split crates under `crates/`.

The canonical crate-native pipeline is:

1. shared services such as `font`, `image`, `stylesheet`, `svg`, `math`, and `textkit` provide inputs and domain-specific processing
2. `layout` resolves pages, node geometry, inherited style, text layout, and asset sizing into a safe layout tree
3. `render` lowers that layout tree into typed render commands and provides the production PDF backend
4. `kit` emits PDF page content and serializes final PDF bytes

Supporting that pipeline are shared crates for errors, primitives, utilities, assets, and scene conversion:

- `errors`, `primitives`, `utils`
- `font`, `image`, `stylesheet`
- `svg`, `math`

Compatibility crates such as `document`, `style`, and `renderer`, along with the root crate and `src/`, still matter, but they sit above that canonical path as facade layers rather than as the place where the canonical architecture lives.

## Workspace Shape

```text
graphitepdf/
├── crates/
│   ├── errors/       # Shared Result/Error types
│   ├── primitives/   # Geometry, units, colors, common low-level types
│   ├── utils/        # Generic helpers
│   ├── font/         # Font descriptors, sources, registration, loading, fallback support
│   ├── image/        # Image sources, decoded assets, async resolution, caching
│   ├── stylesheet/   # CSS-like normalization, shorthands, media/unit resolution
│   ├── svg/          # SVG parser -> typed SvgNode tree
│   ├── math/         # LaTeX -> SVG scene conversion
│   ├── textkit/      # Attributed text, bidi, hyphenation, text layout
│   ├── style/        # Compatibility style facade over layout/style-system types
│   ├── document/     # Compatibility document facade over layout/render types
│   ├── layout/       # Canonical layout pipeline and safe layout tree
│   ├── render/       # Render commands + production PDF backend over kit
│   ├── renderer/     # Thin compatibility facade over render
│   └── kit/          # Low-level PDF content generation and file writing
└── src/
    ├── document/     # Root-crate compatibility wrappers
    ├── layout/       # Root-crate compatibility wrappers
    ├── render/       # Root-crate compatibility wrappers
    ├── renderer/     # Root-crate compatibility wrappers
    ├── style/        # Root-crate compatibility wrappers
    ├── textkit/      # Root-crate compatibility wrappers
    └── lib.rs        # Public facade and re-exports
```

## Architectural Layers

### 1. Foundation

- `crates/errors` defines the shared workspace error surface.
- `crates/primitives` defines reusable low-level data such as `Pt`, `Bounds`, `Point`, `Size`, and `Color`.
- `crates/utils` holds general helpers used by higher-level crates.

These crates sit at the bottom of the graph and should stay free of document, layout, render, or PDF policy.

### 2. Shared asset and style services

- `crates/font` owns `FontDescriptor`, `FontSource`, `FontStore`, standard fonts, loading, fallback lookup, and hyphenation hooks.
- `crates/image` owns image sources, decoded image assets, async resolution, and cache management.
- `crates/stylesheet` owns stylesheet flattening, shorthand expansion, unit resolution, media-query handling, and normalization.

These crates are shared domain services. They are not PDF-specific and they are not root-crate-only helpers.

### 3. Shared scene conversion

- `crates/svg` parses XML/SVG input into a typed `SvgNode` tree.
- `crates/math` renders LaTeX into SVG-shaped scene data using `graphitepdf-svg`.

`math` is therefore not a separate rendering backend. It is a scene producer that feeds the same downstream pipeline as SVG.

### 4. Canonical pipeline inputs

#### `textkit`

`crates/textkit` is the dedicated text subsystem. It owns:

- attributed text and text runs
- bidi and script heuristics
- font substitution
- hyphenation-aware breaking
- line and fragment layout

This crate is now the text engine that `layout` depends on rather than text behavior being embedded ad hoc in higher layers.

#### `layout`

`crates/layout` is the canonical layout layer. It integrates style, text, SVG, math, and image sizing into:

- `SafeLayoutDocument`
- `SafeLayoutPage`
- `SafeLayoutNode`

It also exposes the ordered layout pipeline steps, including style resolution, inheritance, text layout, SVG resolution, pagination, origin assignment, and z-index ordering.

This is now the authoritative geometric model for downstream rendering.

### 5. Render orchestration and PDF backend

#### `render`

`crates/render` is the main render layer. It lowers layout output into a typed `RenderDocument` made of `RenderCommand`s such as text, image, SVG, fill, border, transform, and debug operations.

Crucially, `render` also contains the production PDF path:

- `RenderEngine` builds render commands from `layout`
- `RendererSession` drives end-to-end document rendering
- `PdfRenderBackend` turns render commands into PDF bytes
- that backend uses `graphitepdf-kit` for page-content helpers and PDF writing

This means the workspace now does have a real crate-native `layout -> render -> kit -> PDF` path. That was previously a planned end state; it is now implemented.

### 6. Low-level PDF emission

`crates/kit` is the low-level PDF engine. It owns:

- PDF object and file serialization
- PDF page and document writing
- text, vector, image, and SVG page-content helpers
- font registration helpers for PDF emission

`kit` should stay focused on PDF mechanics. It is not the place for stylesheet resolution, document authoring policy, or high-level layout decisions.

### 7. Compatibility and facade crates

#### `style`

`crates/style` is currently a compatibility style facade, not a canonical pipeline layer. It projects stylesheet data into a legacy `Style` type, but it also depends on `graphitepdf-layout` for shared types such as `EdgeInsets` and for conversion into `graphitepdf_layout::LayoutStyle`.

So `style` does not sit below `layout` in the dependency graph. It sits above or beside the canonical layout crate as an adapter for legacy API shapes.

#### `document`

`crates/document` is also a compatibility-facing facade. It provides compatibility-friendly `Document`, `Node`, `TextNode`, and `ImageNode` types, lowers them into `graphitepdf-layout` types, and also implements rendering entry points by depending on `graphitepdf-render` and `graphitepdf-renderer`.

This crate is therefore a front door and adapter layer over the canonical pipeline, not the core pipeline itself.

#### `renderer`

`crates/renderer` is currently a thin facade over `graphitepdf-render`. It exists as an API tier and compatibility surface, but the substantive rendering logic lives in `crates/render`.

## Dependency Direction

The dependency direction is best understood like this:

```text
root crate
  -> document, renderer, render, layout, style, textkit, kit, font, image, stylesheet, svg, math, primitives, errors, utils

document
  -> style, image, layout, render, renderer, textkit, primitives

renderer
  -> render, layout, kit, font, primitives, errors

style
  -> layout, stylesheet, font, primitives

render
  -> layout, kit, font, image, svg, textkit, primitives, utils, errors

layout
  -> textkit, stylesheet, image, math, svg, font, primitives, errors

kit
  -> font, image, math, svg, errors

textkit
  -> font, primitives, errors

image
  -> svg, errors

math
  -> svg, primitives, errors

svg
  -> primitives, errors

stylesheet
  -> errors

font
  -> errors
```

Important practical consequences:

- `layout` is the canonical bridge between shared inputs and rendering.
- `render` is the canonical bridge between layout output and `kit`.
- `renderer` is an API shell over `render`, not a separate rendering engine.
- `style` and `document` are compatibility adapters, not canonical layers that everything else must flow through.
- `src/` and the root crate sit above the crate graph as a facade layer.

## Role Of `src/`

The role of `src/` is intentionally reduced.

Today `src/` primarily does three things:

1. re-exports the split crates through the root `graphitepdf` crate
2. preserves compatibility modules such as `src/document`, `src/layout`, `src/render`, `src/renderer`, `src/style`, and `src/textkit`
3. offers a convenient top-level facade for users who want one dependency instead of many

What `src/` is not anymore:

- the canonical home of the document model
- the canonical layout engine
- the canonical render engine
- the canonical PDF backend

Those responsibilities now belong to the crates under `crates/`.

## Current Mental Model

The cleanest current mental model is:

- `font`, `image`, and `stylesheet` provide shared domain services
- `svg` and `math` provide typed scene data
- `textkit` provides the canonical text subsystem that feeds layout
- `layout` produces the canonical positioned scene graph
- `render` turns that graph into backend-friendly render commands and a working PDF backend
- `kit` performs low-level PDF emission
- `style`, `document`, `renderer`, the root crate, and `src/` provide convenience and compatibility surfaces

## Remaining Post-Port Gaps

Most of the post-port architectural gaps are now closed, including the last PDF-boundary image seam.

- Concrete `Image` assets render all the way through `render` into `kit`.
- Unresolved `ImageSource` values now follow one canonical source-to-asset resolution step inside the PDF backend before final encoding.
- The remaining work is now mostly iterative polish, coverage expansion, and narrowing behavior differences between the compatibility facade and the crate-native surfaces.

So the missing seam is no longer "is there a real PDF backend?" There is. It is also no longer "where is the single canonical source-to-asset image resolution step?" That path now exists in the render-to-kit backend.

## Summary

GraphitePDF now has the intended crate-centric layering:

- shared foundations in `errors`, `primitives`, and `utils`
- shared asset/style services in `font`, `image`, and `stylesheet`
- shared scene conversion in `svg` and `math`
- canonical text and layout inputs in `textkit`
- canonical layout in `layout`
- canonical rendering and PDF backend integration in `render`
- low-level PDF emission in `kit`
- facade layers in `style`, `document`, `renderer`, the root crate, and `src/`

That is the architecture the workspace actually implements today.