Why a renderer is a primitive
There is a whole class of document whose illustrations are not pictures at all. They are instructions: move here, curve to there, fill this shape. A design-led technical manual is often built entirely this way, and nothing in it can be extracted, because there is nothing to extract — the figure only becomes visible at the moment something executes the instructions. Ask a vision model to look at such a figure and you have nothing to hand it.
So the renderer is not a convenience wrapped around the interesting parts. It is the verb the system was missing. The inventory can say a figure occupies this rectangle on that page; only the renderer can produce the thing itself. And once it exists, the whole shape of the problem changes: parsing stays authoritative for anything written down, and the model becomes a bounded annotator asked one question — what is this? — about a picture it has actually been given.
That division is not a preference. Feed a page image to a vision model and ask it to transcribe, and it will quietly rewrite words into more plausible words — measured at half to two-thirds of perturbed words on general-purpose models, against zero for traditional optical recognition. Run the same chart through the same model twenty times and almost every chart yields at least one differing extraction. A parser is boring, exact and repeatable; a model is the only thing that can say what a picture depicts. Give each the job it is actually good at.
Resolution is not a dial you turn up
The received wisdom is three hundred dots per inch, and it is folklore. In one published comparison, three hundred was worse than a hundred and forty-four for three of five models. A study of optical recognition found error rate tracks the pixel height of a capital letter — and degrades above the optimum, not just below it. Practitioner defaults cluster around a hundred and fifty.
There is a harder ceiling above that anyway. A vision model does not see your pixels; it sees patches, and it caps how many it will look at. Past a certain density your image is quietly downscaled before the model ever reads it — which means a three-hundred and a two-hundred scan of the same page arrive as the same image and cost exactly the same. You paid twice for one picture. Choosing a hundred and fifty is not thrift. It is declining to pay for resolution nobody downstream will ever see.
What only pixels can answer
A detected figure's rectangle is the union of the strokes that were painted. But a document can paint something and then clip it away, or cover it with something opaque — and neither act leaves a trace any bounding box can carry. The result is a region that is geometrically correct and visibly two-fifths empty. One measured case: a figure eight hundred points wide whose ink stopped at four hundred and forty-three.
Two teams tried to close that gap upstream, in the geometry, and both attempts made correct figures worse. The answer is that visibility is a pixel question, and the renderer is the first thing in the chain that holds the answer — because it has just drawn it. So it trims the crop to the ink actually present, and reports that it did, keeping the detector's original rectangle alongside so the two can be compared.
The trap in that is the mirror image of the problem. Set the threshold for 'this pixel is ink' a shade too strict and a pale-tinted drawing with one dark mark on it trims down to the mark — ninety-seven per cent of the figure thrown away, under a label that reads 'blank margins removed'. The rule that survives is a definition rather than a guess: the canvas is filled with opaque white before drawing, so anything that is not exactly white is something the page drew.
Pixels we made are labelled as ours
A rendered figure did not come out of the document. We manufactured it, at a resolution we picked, with a renderer at a particular version. Leaving that implicit is how a picture the machine drew ends up being treated as a picture the author supplied — so every asset in the system states which it is, and a rendered one carries the renderer, the engine underneath it, the encoder that turned the bitmap into bytes, the effective resolution and the exact rectangle.
Three version numbers, not one, and they are not interchangeable: the wrapper, the engine that decided the pixels, and the encoder that decided the bytes. They move independently, and when the output changes you want to know which of the three moved.
A licence is an engineering constraint
Almost every PDF renderer in the world is one of two engines, and both are copyleft — one of them with no commercial licence available at all, because its copyright is held by dozens of people. Every convenient wrapper you might reach for turns out to be a permissive badge over one of those two. It is worth saying plainly, because the shape of the constraint is invisible from outside: the licence did not slow the work down, it decided which library the work was built on, and therefore which behaviours had to be re-derived.
The route that stays clean is a permissively licensed engine with no Python dependencies at all. It also has its own opinions — it renders a page's crop box rather than its media box, which shifts every coordinate with no error and no size mismatch to notice, and its crop parameter counts amounts cut from each side rather than describing a rectangle. Those are the kind of details that are invisible in a tutorial and decisive in production. The general lesson is one licence audits teach repeatedly: permissive code and restricted weights travel together far more often than anyone expects, and the two have to be read separately.
Engines that draw pages
PDFium
Chrome's engine, BSD-licensed, no Python dependencies. The route that stays commercially clean.
MuPDF
Fast and excellent, AGPL. Also the only library treating vector-figure detection as first-class — which is why the algorithm had to be re-derived rather than reused.
Ghostscript / poppler
The venerable pair behind most command-line PDF tools. GPL, and poppler has no commercial licence at all — its copyright is held by dozens of people.
pypdfium2
The Python binding we use. Apache-2.0 or BSD-3, prebuilt wheels, pure CPU.
Cairo / Skia
General 2D rasterisers rather than document engines — the layer below, if you are drawing rather than reproducing.
Browser print-to-PDF
The reverse direction, and a reminder that a PDF is a rendering target as often as it is a source.
Where to look
In Gateway, rendering is an op on a document already parsed:
{"op": "render", "dpi": 150, "trim": true}
# every rendered asset comes back marked origin:"rendered", with the
# renderer, engine, encoder, effective dpi and the exact box it drew —
# so pixels we made are never mistaken for pixels the author suppliedRendering one region costs a few milliseconds and no money. It is not the expensive part of anything — finding the region is far slower, and describing it is the only step that costs at all. Which is a good note to end on: the verb that unlocked a whole class of document turned out to be the cheapest thing in the pipeline. It was simply missing.