<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jasper | PDFluent</title>
    <description>The latest articles on DEV Community by Jasper | PDFluent (@jasper_de_winter).</description>
    <link>https://dev.to/jasper_de_winter</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3781039%2Fe00e35a5-cffc-44f5-b077-2154a7d01a00.jpg</url>
      <title>DEV Community: Jasper | PDFluent</title>
      <link>https://dev.to/jasper_de_winter</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jasper_de_winter"/>
    <language>en</language>
    <item>
      <title>Building a PDF engine from scratch in Rust</title>
      <dc:creator>Jasper | PDFluent</dc:creator>
      <pubDate>Sat, 22 Aug 2026 20:30:11 +0000</pubDate>
      <link>https://dev.to/jasper_de_winter/building-a-pdf-engine-from-scratch-in-rust-4opk</link>
      <guid>https://dev.to/jasper_de_winter/building-a-pdf-engine-from-scratch-in-rust-4opk</guid>
      <description>&lt;h2&gt;
  
  
  Why build another PDF engine
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  The brutal parts
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually works now
&lt;/h2&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;94% render at SSIM 0.95 or better against mutool (mean SSIM 0.9869)&lt;/li&gt;
&lt;li&gt;0.16% crash rate (8 crashes), all on adversarial fuzzing input&lt;/li&gt;
&lt;li&gt;98.9% PDF/A-2b conformance on a 1,000-document holdout set&lt;/li&gt;
&lt;li&gt;Text retention median 100.0%, 5th percentile 99.3%, none below 95%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These numbers are reproducible using veraPDF and mutool against the published benchmarks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing traps I fell into
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Silent test skips hid problems too. A duplicated character-mapping table survived because missing fixtures failed quietly. Now any skip must log to stderr.&lt;/p&gt;

&lt;h2&gt;
  
  
  The privacy approach
&lt;/h2&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Monitor network traffic while using the tool&lt;/li&gt;
&lt;li&gt;Check that reqwest only appears in the updater (&lt;code&gt;cargo tree -i reqwest&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Compare against my published packet capture&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>rust</category>
      <category>software</category>
    </item>
  </channel>
</rss>
