Rendering Pipeline
The source-defined PDF rendering pipeline moves from a stored DOM and stylesheet preparation to decorated frames, positioning and reflow, renderer dispatch, canvas operations, and adapter-produced output.
[!WARNING] Do not treat this bundled sequence as evidence that an application workflow constructs the renderer, calls
render(), or consumesoutput(). Those application-level handoffs and a successful runtime execution were not observed.
Source-defined order
flowchart TD
n0["Dompdf::__construct<br/>initial CanvasFactory selection"]
n1["Dompdf::loadDOM<br/>stored DOM"]
n2["Dompdf::processHtml<br/>FrameTree and stylesheets"]
n3["Stylesheet::apply_styles<br/>styled frames"]
n4{"CSS paper size or orientation differs?"}
n5["CanvasFactory::get_instance<br/>conditional canvas recreation"]
n6["Frame::Factory::decorate_frame<br/>decorated frames"]
n7["root setup and reflow<br/>containing block and position"]
n8["Renderer::render<br/>display dispatch"]
n9["Canvas interface<br/>drawing operations"]
n10["Dompdf::output<br/>adapter output"]
n0 --> n1 --> n2 --> n3 --> n4
n4 -- yes --> n5 --> n6
n4 -- no --> n6
n6 --> n7 --> n8 --> n9 --> n10
Dompdf::__construct obtains the initial canvas through CanvasFactory::get_instance before loadDOM. During Dompdf::render, the canvas is recreated through the same factory only when CSS page-size or orientation values differ from the current canvas; the root then receives canvas dimensions and a Renderer before reflow.
Stage handoffs
[
{
"title": "DOM to FrameTree and stylesheet preparation",
"body": "In `pdf/src/Dompdf.php`, **Dompdf::loadDOM** removes direct `#text` children from the selected html, head, table, tbody, thead, tfoot, and tr elements, stores the supplied DOM and quirks-mode flag, and constructs `new FrameTree($this->dom)`. The source-defined **processHtml** stage calls `$this->tree->build_tree()` before loading the user-agent stylesheet, linked author stylesheets in document order, and inline style content. **Dompdf::render** then calls **processHtml** followed by **apply_styles**."
},
{
"title": "Stylesheet handoff to decorated frames",
"body": "**Stylesheet::apply_styles** in `pdf/src/Css/Stylesheet.php` traverses the FrameTree, resolves frame styles, applies inheritance where required, and assigns the resulting style objects to frames. **Factory::decorate_frame** in `pdf/src/Frame/Factory.php` maps display types to positioner, decorator, and reflower classes, then binds those components to each decorated frame. CSS `absolute` and `fixed` positions replace the mapped positioner with **Absolute** or **Fixed**."
},
{
"title": "Frame classification and positioning",
"body": "In `pdf/src/Frame.php`, a frame is in-flow only when its float is `none` and it is not absolute-positioned. **Frame::is_absolute** treats both CSS `absolute` and `fixed` positions as absolute. During the position handoff, **Absolute::position** in `pdf/src/Positioner/Absolute.php` resolves coordinates against the relevant containing block or positioned parent, while **Fixed::position** in `pdf/src/Positioner/Fixed.php` derives coordinates from the root containing block and `@page` margins and propagates the position to each direct child."
},
{
"title": "Root reflow to renderer dispatch",
"body": "In `pdf/src/Dompdf.php`, **Dompdf::render** decorates the root and remaining frames, sets the root containing block to the canvas dimensions, attaches `new Renderer($this)`, and calls `$root->reflow()`. In `pdf/src/Renderer.php`, **Renderer::render** dispatches block-like displays to the block renderer, inline text to the text renderer, inline elements to the inline renderer, table cells and row groups to their table renderers, list bullets to the list-bullet renderer, and `-dompdf-image` to the image renderer."
},
{
"title": "Visibility, child traversal, and image handoff",
"body": "The renderer returns before drawing frames with `hidden` or `collapse` visibility. Its `none` branch handles embedded script types and returns without rendering that frame's children. After dispatch, it groups and sorts children by z-index before recursively rendering them. In `pdf/src/Renderer/Image.php`, the image renderer uses the canvas image operation for the normal path; when the image cache marks the source broken and an alt attribute is available, it emits the alt text through the canvas text operation instead."
},
{
"title": "Canvas operations to output data",
"body": "The `Canvas` contract in `pdf/src/Canvas.php` covers drawing text and images, page creation, clipping and graphics-state operations, and output or streaming. **Dompdf::output** in `pdf/src/Dompdf.php` returns `null` when no canvas is present; otherwise it calls `$canvas->output($options)`, restores PHP configuration, and returns the adapter-produced output data."
}
]
The declared completion boundary is therefore the return from Dompdf::output when a canvas exists.
Canvas backend selection and limits
| Selection condition | Adapter | Source-defined boundary |
|---|---|---|
| An explicitly supplied class is loaded | <class>_Adapter |
CanvasFactory::get_instance in pdf/src/CanvasFactory.php appends _Adapter and instantiates it with paper, orientation, and the Dompdf object. |
Backend is auto or pdflib, and PDFLib is already available |
Dompdf\Adapter\PDFLib | Selected when class_exists("PDFLib", false) is true. |
Backend is gd, and the GD extension is loaded |
Dompdf\Adapter\GD | Selected when extension_loaded('gd') is true. |
| No earlier selection applies | Dompdf\Adapter\CPDF | CPDF is the fallback adapter. |
Two adapter limitations affect the drawing handoff:
pdf/src/Adapter/GD.phpdeclaresclipping_rectangle,clipping_roundrectangle, andclipping_end, but their method bodies are// @todoplaceholders. Clipping behavior is therefore not implemented by the inspected GD adapter.pdf/src/Adapter/PDFLib.phpreturns before drawing when an image-load response is zero. The inspected source records no rendered fallback or successful image-load outcome for that branch.
Updated