Why build another PDF engine
Hi Folks, my name is Jasper. I spent the last year writing a PDF engine from scratch in Rust. Not wrapping an existing C++ library, not forking an open source project - 48 pure Rust crates with zero C or C++ dependencies. The SDK is now solid, and a new version of the free desktop editor ships next week. Here's what broke along the way.
The brutal parts
XFA forms were the first obstacle. Adobe deprecated XFA in PDF 2.0, but deprecated doesn't mean gone. XFA has its own layout model, scripting language, and data binding - all documented in a 756-page specification. Implementing it meant writing a JavaScript interpreter (QuickJS) for form calculations while ensuring scripts in documents never execute.
Rendering was another challenge. Existing Rust PDF crates only parsed files, so I had to build a rasterizer using vello_cpu. The first PDF/A conversions passed validation while quietly dropping content. The validator checked structure, not whether text was preserved. I caught it by counting words with mutool against the original - one escaped backslash cost an entire page.
What actually works now
After processing 50,000 real PDFs with zero crashes, I measured rendering performance on a 5,000-document test set and PDF/A compliance on a separate 1,000-document holdout set:
- 94% render at SSIM 0.95 or better against mutool (mean SSIM 0.9869)
- 0.16% crash rate (8 crashes), all on adversarial fuzzing input
- 98.9% PDF/A-2b conformance on a 1,000-document holdout set
- Text retention median 100.0%, 5th percentile 99.3%, none below 95%
These numbers are reproducible using veraPDF and mutool against the published benchmarks.
Testing traps I fell into
A binding in the WebAssembly build had been broken since May. A test for it existed but wasn't running in CI - like 198 other method tests sitting unused. Now nothing ships without its test running in the pipeline.
Three "passing" tests didn't actually test anything: one used ASCII fixtures that never hit Unicode paths, another counted uncompressed streams as zero, and a third positioned text where no blocks were detectable. The rule now: break the function on purpose and see if the suite notices.
Silent test skips hid problems too. A duplicated character-mapping table survived because missing fixtures failed quietly. Now any skip must log to stderr.
The privacy approach
The editor makes three outbound connections: update checks, opt-in crash reports, and opening links in your browser. Document content never leaves your machine. You can verify this:
- Monitor network traffic while using the tool
- Check that reqwest only appears in the updater (
cargo tree -i reqwest) - Compare against my published packet capture
The limitation: TLS obscures content, and unpublished source can't be verified. You can run this same check on any PDF tool you use to compare the results.
What's next
The new editor version removes non-functional e-signature controls and fixes save-state indicators. It stays free for all uses, no accounts or telemetry. The SDK licenses start at €699 with a 30-day evaluation. The SDK runs with all features enabled but adds a watermark to the output until you apply a license key.
Top comments (0)