PrawnX
A rewrite of Prawn, prawn-table and prawn-svg in one gem: lighter files, faster renders, and PDF/A-3 and Factur-X on top.
gem "prawnx"
In numbers
Loading the latest numbers…
Why
Prawn draws good pages, slowly. Profiling an invoice with a table shows where the time goes: line breaking rebuilds its regular expressions for every line, every number is formatted then patched, and TrueType fonts are read again for each document.
PrawnX keeps Prawn’s Ruby API and its pages, and rewrites what sits underneath. Your code does not change; the PDF it produces looks the same, weighs less, and comes out faster.
What changes
One gem instead of three
pdf.table and pdf.svg work without prawn-table or prawn-svg; require "prawn/table" and require "prawn-svg" keep working.
Lighter files, same pixels
Every PDF is written as PDF 1.5: compressed streams, the other objects packed in one compressed object stream, a cross-reference stream. Identical images are embedded once.
Fonts parsed once per process
A TrueType or OpenType font is read once, frozen and shared by every document and thread, until its file changes. PrawnX.eager_load! loads it all before a server forks.
PDF/A-3 and Factur-X
pdf_a: true writes a PDF/A-3b document; factur_x embeds the invoice XML your invoicing system produced.
Prawn’s bugs, fixed and declared
Each fix is proven by a specification and listed with the exact differences the oracle reports. Everything else matches Prawn.
Safer SVG by default
SVG images fetch nothing from the web unless asked to: a submitted SVG cannot make the server request a URL.
Same pages
An oracle renders every example of Prawn’s and prawn-table’s manuals and every sample SVG of prawn-svg with Prawn 2.5, prawn-table 0.2.2 and prawn-svg 0.40.4, and with PrawnX, each in its own process. It compares their pages, their text and its positions to 0.01 pt, their pixels at 150 dpi in MuPDF and in Poppler, their validity and their weight. A seeded fuzzer writes random documents and compares them the same way.
Quick start
Gemfile
gem "prawnx" # instead of prawn, prawn-table and prawn-svg
Your code, unchanged
Prawn::Document.generate("hello.pdf") do
text "Hello, World!"
table [%w[SKU Qty], %w[A-1 2]]
end