Skip to content

Document raster geometry

Document cards and the raster modal read source-page dimensions through web/src/lib/documentPageGeometry.ts. Silver's build_pages_meta produces pages.meta.json. The raster modal reads its compact geometry summary from the document index's pages_meta, including for local-only documents without gold regions. HTTP, MCP, and CLI index responses carry the same summary from the selected document generation. The card reads pages_meta from gold-map:

{
  "bbox_origin": "top-left",
  "pages": {
    "1": { "page_size": [600, 800] },
    "2": { "page_size": [800, 600] }
  }
}

page_size is width and height in source PDF points. It is independent of the raster's DPI and pixel dimensions. Each page has its own dimensions. The compatibility parser also accepts the previous flat consumer shape, { "1": { "width": 600, "height": 800 } }. It requires positive finite numeric dimensions. Malformed canonical metadata does not fall through to legacy fields. Explicit non-top-left metadata is unsupported.

The parser returns page-keyed DocumentPageGeometry values. A missing page means unknown geometry. The page image remains visible, precise overlays are omitted, and a text status explains that page dimensions are unknown. Image dimensions alone cannot establish source dimensions, so there is no assumed DPI fallback.

Both raster consumers use bboxToImageRect. The card requests a 100-by-100 target to obtain percentages; the modal requests the loaded image's natural pixel dimensions for its SVG overlay. For an unrotated page of size W by H, the percentages are x/W, y/H, width/W and height/H, multiplied by 100. Card resizing and canvas zoom scale the image and percentages together. Stored bboxes and coord_origin are unchanged.

Ingest also writes silver/<slug>/pages/<n>.candidates.png next to the page PNG and candidate JSON. This debug image highlights each candidate by type, with its ID, label, and explicit reading order when available. Keyed, text, and harness ingestion all produce it. Boxes use the same top-left point-to-pixel mapping as the raster viewer, including at non-default DPI. Missing page dimensions and unusable boxes are shown as diagnostics. The original page image and candidate JSON remain the source of truth.

The frontend contract fixture is generated by tests/fixtures/document_page_geometry.py using the real renderer, silver producer and gold-map store reader. The backend contract test regenerates and compares that payload with the frontend fixture. To regenerate it:

uv run python -m tests.fixtures.document_page_geometry web/src/lib/fixtures/documentPageGeometry.json

Rotation, crop-box and UserUnit transforms belong to the separate PDF viewport contract. This adapter performs no such transformations.