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.