Somewhere deep in Odoo’s infrastructure, a team has been methodically building a CSS rendering engine from scratch. It’s called paper-muncher, and its job is straightforward: take HTML and CSS, produce pixel-perfect PDF output. The project exists because wkhtmltopdf — the aging WebKit-based tool that Odoo and countless other web applications rely on for PDF generation — has become a bottleneck. It’s unmaintained, its rendering quirks are unfixable without forking an obsolete browser engine, and it can’t handle modern CSS.
The latest batch of changes to paper-muncher represents something genuinely interesting: the engine is now handling CSS float layout, improved table rendering, writing modes for right-to-left and vertical text, and initial support for cascade layers. These aren’t trivial features. Each one touches the most specification-dense parts of CSS, and getting them right is what separates a toy renderer from something that can handle real-world business documents.
Float Layout Lands, and Invoice Totals Stop Overlapping
The headline addition is CSS 2.2 float support in both block and inline layout contexts. If you’ve ever generated an Odoo invoice as a PDF and noticed that the total amount box overlaps the line items above it, you’ve been looking at a float rendering failure. The invoice template uses float: right to position the totals block, and without proper float handling, the rendering engine treated the floated element as if it occupied zero space, causing it to land on top of whatever came before it.
The implementation follows CSS 2.2 §9.5 — the section of the specification that defines how floated boxes are positioned relative to their containing block and to other floats. The engine now includes a dedicated float module that handles float side resolution (including RTL-aware logic where float: leftbecomes float: right in right-to-left contexts), band allocation for available space around floated elements, clearance calculations, and collision detection.
There’s a practical limitation documented alongside the implementation: line boxes are not yet shortened around floats. Content that doesn’t fit beside a float drops below it rather than wrapping tightly. For invoice PDFs and standard business documents this is adequate — the totals block lands in the correct position and the content flows around it at the block level. Tight inline wrapping around floated images, the kind you see in magazine-style layouts, will come later.
Table Width Distribution Gets Smarter About Colspans
Two separate improvements target table rendering, and they both address the same fundamental challenge: how to distribute horizontal space across table columns when cells span multiple columns.
The first change improves how the engine distributes assignable table width. Previous behavior could produce columns that were too narrow or too wide when the table’s content had uneven natural widths across columns. The new algorithm better respects the minimum and maximum content widths of each column while distributing remaining space proportionally.
The second change is more subtle but equally important: the engine now correctly accounts for colspan when measuring cell heights in the table formatting context. A cell that spans three columns has different height requirements than a single-column cell with the same content, because the wider available width means the text reflows differently. Getting this calculation wrong produces tables where rows have inconsistent heights or where content gets clipped.
DIN 5008 Invoices Stop Crashing the Engine
A specific bug in fragmentation handling — the process of splitting content across page boundaries — has been fixed. A table row taller than half the available page height, with cells that offer no internal breakpoint (empty cells, for instance), would cause a panic. The engine now returns a “no breakpoint” marker for these rows and treats them as atomic, unsplittable content. This directly fixes the crash that occurred when rendering the German DIN 5008 invoice layout, a standardized business letter format that uses specific table structures for sender and recipient address blocks.
Writing Modes Open the Door to RTL and Vertical Scripts
The addition of writing-mode anddirection properties from the CSS Writing Modes Level 4 specification is less immediately visible but architecturally significant. These properties control the fundamental flow direction of text: horizontal top-to-bottom (the Latin default), vertical right-to-left (used in traditional Chinese, Japanese, and Korean typography), and horizontal right-to-left (Arabic, Hebrew). Adding them at the style parsing level means the engine can now understand document intent for these scripts, even if full layout support for vertical text is still being built out.
For Odoo’s global user base, this is a prerequisite for correct Arabic and Hebrew invoice rendering. The float implementation already includes RTL-aware float side resolution, which means the pieces are falling into place for right-to-left document layout that actually works.
Cascade Layers and the Long Game
Initial support for CSS cascade layers (@layer) rounds out the batch. Cascade layers are a relatively modern CSS feature — they reached browsers in 2022 — that let stylesheet authors define explicit priority ordering between groups of styles. In a PDF rendering context, this matters because Odoo’s report templates layer base styles, theme styles, and user customizations on top of each other. Without proper cascade layer support, specificity conflicts between these layers produce unpredictable results.
What makes paper-muncher worth watching isn’t any individual feature. It’s the velocity. The engine is implementing CSS capabilities in a logical sequence that tracks the real-world needs of Odoo’s report templates: first basic block layout, then tables, then floats, then fragmentation for pagination, now writing modes and cascade layers. Each addition targets a specific class of report rendering failures. The engine isn’t trying to render every website on the internet. It’s trying to render business documents perfectly, and it’s getting there faster than most people realize.
Stacking Contexts Get a Spec-Compliance Fix
A separate correction ensures that the overflowproperty no longer creates a stacking context. CSS 2.2 Appendix E is explicit about this: overflow controls whether content is clipped, not how elements are layered in the z-axis. The engine had been incorrectly promoting elements withoverflow values other than visible into their own stacking context, which could cause elements to render in the wrong order. The test case for this fix is adapted from the Web Platform Tests suite, the cross-browser conformance test collection maintained by the W3C, which signals that the paper-muncher team is validating against the same standards that browser vendors use.