Seeing the Page: Rendering Without Chromium

For Obscura, rendering is the point where a stateful document must become geometry and pixels without being handed to Chromium’s compositor. This chapter traces that render pipeline from styles and retained invalidation through layout, resource preparation, text and image handling, and CPU-backed paint. The practical judgment is not whether Obscura can produce a screenshot in the abstract, but whether its shared, feature-gated renderer gives a workload the visual and interaction fidelity it actually requires.

A page can be perfectly useful as a DOM and still be wrong as an image. An element may have a different size, text may wrap at another point, an image may lack its intrinsic dimensions, or a fixed element may be painted in the wrong place. Conversely, a screenshot can look plausible while the geometry exposed to page scripts or automation is inconsistent with the pixels. Obscura’s render design starts from the premise that those representations should be connected.

Layout is the contract between a document and a picture

Rendering begins with the live DOM and the styles that apply to it. Obscura computes CSS state, turns the document into a layout tree, and resolves boxes in a viewport measured in CSS pixels. The renderer uses Taffy as a layout foundation, then adds browser-oriented behavior around formatting, intrinsic sizes, text, transforms, overflow, and scrolling. The result is not just a bitmap: it is a set of geometry records that other browser APIs can consume.

That shared geometry matters for interaction. Suppose a page script asks for an element’s bounding rectangle and an automation caller then clicks at a coordinate derived from it. If the geometry API uses one model while the screenshot uses another, the page can report a button in one place and paint it somewhere else. A visual test may pass while a click misses, or a crawler may select a node whose apparent location does not match the captured evidence. Obscura’s architecture instead lets layout geometry feed both browser-facing measurements and paint, so the renderer has one source of spatial truth.

The relationship is especially important for responsive pages. The CSS viewport controls layout and page behavior, while physical capture scale can be handled separately. Scrolling, transforms, fixed positioning, and sticky geometry change how a box is observed without changing the underlying document identity. Treating these as renderer-owned state allows the same page to be measured, scrolled, and captured without rebuilding an unrelated screenshot-only interpretation each time.

Layout and paint are related but not identical. Layout answers where boxes and text runs belong and how large they are. Paint answers which colors, borders, images, glyphs, clips, and backgrounds should be placed into a raster surface. Keeping the stages separate lets a no-paint build still provide geometry, and it lets capture code validate a surface before allocating memory for it. It also makes a failure more diagnosable: a missing image resource, a text-shaping difference, and an incorrect flex calculation are not the same defect.

Consider a responsive dashboard captured twice. At a narrow viewport, a navigation rail may collapse, the table may wrap its headings, and a fixed control may remain attached to the viewport rather than the document.