Notes · Sep 10, 2026 · 1 min read
Designing a PDF engine you can trust
The preview is the product: how Invoice Maker renders vector PDFs with Core Graphics and keeps WYSIWYG honest.
In an invoicing app, the preview is the product. If the PDF that reaches your client differs from what you saw on screen by even one point of spacing, trust is gone. So Invoice Maker is built around a single rule: one renderer, one truth.
One renderer
UIGraphicsPDFRenderer draws the final document, and the on-screen preview renders the same document through PDFKit. There is no second code path to drift out of sync — what you see is what you export, by construction rather than by discipline.
The layout loop
Every invoice is a measurement problem:
- Measure each line item’s height with the real font metrics.
- Break pages only at row boundaries.
- Repeat headers and re-number footers on every page.
Multi-page invoices look typeset, not stapled together.
The math underneath
Amounts are computed by a pure-function engine — discounts cascade to rows, per-line tax overrides win, partial payments reduce the balance — and it’s covered by 111+ unit tests. Currency-in-words in English and Chinese (One Hundred Twenty / 壹佰贰拾元整) is generated from the same numbers, never typed twice.
What we deliberately didn’t do
No HTML-to-PDF. No web views. No server-side rendering. A vector PDF drawn natively with Core Graphics is sharp on screen and on paper, works offline, and leaks nothing — which is exactly what a private-first tool should ship.