zpdf 0.12.1

Pure Rust PDF parsing library with wgpu GPU rendering
Documentation

zpdf

CI Release Publish (crates.io) crates.io docs.rs

Pure-Rust PDF parsing and rendering, with interchangeable CPU (tiny-skia) and GPU (wgpu) renderers whose output matches within <1% of pixels.

Features

  • Pure Rust — zero C/C++ dependencies, fully safe.
  • PDF parsing — header, traditional xref + xref/object streams + hybrid /XRefStm, trailer chains, lazy xref repair, object model, stream filters (Flate / LZW / ASCII85 / ASCIIHex / RunLength / DCT / CCITT G3-G4 + predictors) with corrupt-stream salvage.
  • Malformed-input robustness — opens corrupt, headerless, or garbage-tail files via full-file object-scan recovery (catalog inside an /ObjStm, page-tree synthesis from /Type /Page scan, byte-flipped /Type tolerance, lenient header/dict parsing). Never panics or hangs on adversarial input: path/raster/clip budgets plus interpret/render time backstops degrade to a partial render instead. Recent hardening: predictor overflow protection, safe ObjStm parsing, mesh shading NaN validation, font cache LRU eviction (256-font limit) to prevent memory exhaustion attacks.
  • Performance — CMYK/ColorSpace caching, zero-copy knockout rendering, in-place dash pattern optimization, and zero-copy PNG saving deliver 2–3× faster rendering on typical workloads (layered PDFs, technical drawings, repeated colors).
  • Encryption — RC4 (40/128-bit) and AES-128 / AES-256 (V5 R5/R6) standard security handler with crypt filters; opens with the user, owner, or empty password (open_with_password, CLI --password).
  • Content interpretation — graphics state, paths, clipping, text (incl. render modes and rise), inline & XObject images, Form XObjects (full resources, /BBox clip), axial/radial shadings, shading patterns, all 16 blend modes, dash patterns.
  • Color — DeviceGray/RGB/CMYK, ICCBased (/N), Indexed, Lab, Separation/DeviceN via a full PDF function evaluator (types 0/2/3/4).
  • Fonts — embedded TrueType, Type1, Type1C/CFF, CID/Type0 (Identity-H, /W, /CIDToGIDMap streams), Type3, the standard-14 fonts; encodings + /Differences; Quartz-subset recovery; /ToUnicode text extraction.
  • TXT, Markdown & HTML conversion — text-only conversion skips image decoding entirely; rich Markdown/HTML exports decoded images as PNG assets and includes document/page metadata. Unsupported or malformed images are discarded without interrupting text extraction (convert_pdf, CLI convert).
  • PowerPoint (PPTX) export — converts PDF pages to editable PowerPoint presentations preserving text (with font/size/color/style), shapes (rectangles, ellipses, lines with fill/stroke), and embedded images as native PowerPoint elements rather than rasterizing to images (zpdf-pptx-export, CLI export-pptx).
  • SVG export — vector-faithful page → SVG conversion (zpdf-svg-export, CLI export-svg). Paths, glyphs, and strokes stay vectors; images embed as base64 PNG; clips/soft masks/blend modes map to SVG equivalents. Verified against the CPU backend via resvg rasterization (zero systematic drift).
  • WebAssembly — the full read pipeline (parse + CPU render + text + SVG) compiles to wasm32-unknown-unknown (zpdf-wasm). Pure Rust with zero C dependencies makes this feasible where native PDF libraries fail. Includes a fully client-side browser demo (www/) with drag-drop, page navigation, text extraction, and SVG export — nothing uploads.
  • Images — 1/2/4/8/16-bpc, /Decode, soft masks, stencil & color-key masks, Indexed palettes, CMYK JPEG; bilinear sampling with box-filter minification.
  • Page geometry — CropBox-aware rendering, page-tree attribute inheritance (/Rotate, /Resources, boxes), page rotation.
  • Annotations & forms/AP appearance streams (/AS states, Hidden/NoView); an AcroForm field model (acro_form(), CLI forms) that generates text/choice field appearances when the producer left none.
  • Navigation & metadata — the document outline / bookmarks (outline(), CLI outline), named & explicit destinations resolved to a page + view (both /Names /Dests and the legacy /Root /Dests), page labels (/PageLabelspage_labels(), decimal/roman/letters + prefix/offset), link annotations resolved to their target page or URI (page_annotations()dest/uri, CLI links), XMP /Metadata via a hardened, entity-expansion-safe scrape (xmp_metadata()), and the /Info dictionary (info()). zpdf info surfaces the /Info, XMP, outline, and page-label data.
  • Digital signatures — parses /Sig signature fields from AcroForm, verifies byte-range integrity (recomputes SHA-1/256/384/512 digest of /ByteRange spans vs. CMS messageDigest) and cryptographic signatures (RSA PKCS#1 v1.5 / ECDSA P-256/P-384 over signed attributes using embedded certificate public keys). signatures() API + CLI zpdf signatures. Optional certificate-chain verification against caller-provided trust anchors (trust::verify_certificate_chain, CLI --trust roots.pem) with validity-period checks; revocation (CRL/OCSP) remains out of scope.
  • Writing & editing — a full authoring/editing toolkit (zpdf-writer):
    • Document creation from scratch (DocumentBuilder): pages, text (standard-14 or embedded TrueType with automatic font subsetting), JPEG/RGB/RGBA images (alpha → SMask), and vector paths.
    • Incremental updates (ISO 32000-1 §7.5.6): annotations (with baked /AP appearance streams), form filling, page rotate/delete/reorder, metadata, text & image stamps, digital signature creation (adbe.pkcs7.detached, RSA / ECDSA P-256) — including updates to encrypted documents (new objects encrypted with the document key).
    • Document merge (append_document): pages plus outlines, AcroForm fields (collision renaming), and optional-content (layer) configuration; page extraction / split.
    • Full rewrite (rewrite_pdf): garbage-collect, renumber, decrypt, Flate-compress, optional image downsampling — and encrypt on save (AES-256 R6 or RC4-128 with user/owner passwords and permissions).
    • True redaction (redact_page): removes text/image/path operators intersecting a region from the content stream itself (not a cosmetic box) and drops overlapping annotations.
    • Linearization (linearize_pdf): "fast web view" output per ISO 32000-1 Annex F.
  • PDF/A validation — a best-effort conformance rule engine for PDF/A-1b and PDF/A-2b (pdfa::validate, CLI zpdf validate): encryption/ID/header checks, XMP pdfaid identification, GTS_PDFA1 output intent, font embedding, forbidden features (JavaScript, embedded files, transparency for A-1).
  • Text extraction quality — geometric XY-cut reading order with dehyphenation (line-break hyphen joining) and RTL repair (Hebrew / Arabic visual→logical reordering).
  • Logical structure / Tagged PDF — the /StructTreeRoot structure tree (struct_tree(), CLI struct) read into a navigable model of structure elements with their roles (/S resolved through /RoleMap to standard types like H1/Table/Figure), accessibility text (/Alt//ActualText), language, titles, page associations, and marked-content (MCID) / object (/OBJR) kids; plus tagged-ness detection (is_tagged(), /MarkInfo). Text extraction can follow the structure tree's logical reading order with /ActualText / /Alt substitution (struct_ordered_text(), CLI text --struct) — the interpreter binds each text run to its /MCID — instead of the geometric XY-cut default.
  • CPU rendering — tiny-skia backend, PNG output at any DPI.
  • GPU rendering — wgpu backend (fills, strokes, clips, text, images, blend groups); matches the CPU renderer within <1% pixels.
  • Tooling — CLI with read commands (info/render/text/search/convert/export-pptx/export-svg/tables/forms/outline/links/struct/attachments/signatures/validate/compare/dump/debug-stream) and write commands (fill/merge/split/optimize/annotate/redact/sign/pages/set-meta/stamp), an interactive winit viewer example, and a native GPUI desktop reader (zpdf-viewer-gpui).

Documentation

Install

Command-line toolcargo install builds the zpdf binary:

cargo install zpdf-cli                  # CPU rendering (default)
cargo install zpdf-cli --features gpu   # + the wgpu GPU backend
zpdf info document.pdf
zpdf render document.pdf -p 1 -o out.png --dpi 150

Library — add the zpdf facade crate to your project:

cargo add zpdf                          # CPU rendering (default)
cargo add zpdf --features gpu-render    # + the wgpu GPU backend

Published on crates.io · API docs on docs.rs.

Quick start

Run from a checkout with cargo run (or drop the cargo run -p zpdf-cli -- prefix once the CLI is installed):

# Inspect a document
cargo run -p zpdf-cli -- info document.pdf

# Render page 1 at 150 DPI (CPU)
cargo run -p zpdf-cli -- render document.pdf -p 1 -o out.png --dpi 150

# Render on the GPU (requires the `gpu` feature)
cargo run -p zpdf-cli --features gpu -- render document.pdf -p 1 -o gpu.png --backend wgpu

# Extract text, and compare two renders
cargo run -p zpdf-cli -- text document.pdf -p 1
cargo run -p zpdf-cli -- compare out.png gpu.png --out diff.png

# Convert the whole document to TXT, rich Markdown, or rich HTML + PNG assets
cargo run -p zpdf-cli -- convert document.pdf -o document.txt --mode text
cargo run -p zpdf-cli -- convert document.pdf -o document.md --mode rich
cargo run -p zpdf-cli -- convert document.pdf -o document.html --mode rich

# Export pages as editable PowerPoint or vector SVG
cargo run -p zpdf-cli -- export-pptx document.pdf -o presentation.pptx
cargo run -p zpdf-cli -- export-svg document.pdf -p 1-5 -o page-%d.svg

# Create, edit, and secure PDFs
cargo run -p zpdf-cli -- merge a.pdf b.pdf -o merged.pdf        # pages + outlines + forms + layers
cargo run -p zpdf-cli -- annotate document.pdf -p 1 --kind highlight --rect 70,690,340,725 -o annotated.pdf
cargo run -p zpdf-cli -- redact document.pdf -p 1 --rect 60,690,400,730 -o redacted.pdf
cargo run -p zpdf-cli -- optimize document.pdf -o smaller.pdf --max-image-dim 1500
cargo run -p zpdf-cli -- optimize document.pdf -o encrypted.pdf --encrypt aes256 --user-password s3cret
cargo run -p zpdf-cli -- optimize document.pdf -o linear.pdf --linearize
cargo run -p zpdf-cli -- sign document.pdf --key key.p8.der --cert cert.der -o signed.pdf
cargo run -p zpdf-cli -- signatures signed.pdf --trust roots.pem
cargo run -p zpdf-cli -- validate document.pdf --profile pdfa-2b

# Interactive viewer (pan/zoom/page-flip)
cargo run -p zpdf-render-wgpu --example viewer -- document.pdf

# Native desktop reader (GPUI: page list, zoom, fit-width, keyboard nav)
cargo run -p zpdf-viewer-gpui -- document.pdf

Library usage

use zpdf::{ContentInterpreter, ImageCache, PdfDocument, RenderBackend};

let data = std::fs::read("document.pdf").map_err(zpdf::Error::Io)?;
let doc = PdfDocument::open(data)?;

let page = doc.page(0)?;                        // 0-based
let mut fonts = doc.load_page_fonts(&page);
let mut images = ImageCache::new();
let content = doc.page_content_bytes(&page)?;

let display_list = ContentInterpreter::new(page.effective_box()) // CropBox ∩ MediaBox
    .with_page_rotation(page.rotate)
    .with_fonts(&mut fonts)
    .with_document(doc.file(), &page.resources)
    .with_images(&mut images)
    .interpret(&content);

let mut renderer = zpdf::cpu::CpuRenderer::new()
    .with_fonts(&fonts)
    .with_images(&images);
let page_img = renderer.render_display_list(&display_list, 150.0 / 72.0)?; // 150 DPI
page_img.save_png("out.png")?;

Switch zpdf::cpu::CpuRenderer for zpdf::gpu::WgpuRenderer (with features = ["gpu-render"]) to render on the GPU — everything upstream is identical. See docs/library.md.

Exporting to SVG

use zpdf::svg::display_list_to_svg;

let svg = display_list_to_svg(&display_list, &fonts, &images, &Default::default());
std::fs::write("page.svg", svg)?;

WebAssembly

cd crates/zpdf-wasm
bash build-web.sh
python -m http.server -d www 8080
import init, { Pdf } from "./pkg/zpdf_wasm.js";
await init();

const pdf = Pdf.open(pdfBytes);
const bitmap = pdf.render_page(0, 150.0 / 72.0);  // page 0, 150 DPI
const text = pdf.page_text(0);
const svg = pdf.page_svg(0);

Creating a PDF from scratch

use zpdf::DocumentBuilder;

let mut builder = DocumentBuilder::new();
let page = builder.add_page(612.0, 792.0);                       // US Letter, points
builder.add_text(page, "Hello, PDF!", 72.0, 700.0, "Helvetica", 24.0, (0.0, 0.0, 0.0))?;

// Embedded fonts are automatically subset to the glyphs actually used.
let font = builder.embed_font(std::fs::read("DejaVuSans.ttf")?)?;
builder.add_text_embedded(page, "Embedded text", 72.0, 650.0, font, 14.0, (0.0, 0.3, 0.7))?;

std::fs::write("hello.pdf", builder.build()?)?;

Architecture

18-crate workspace with a strict one-direction dependency flow. Render backends depend only on zpdf-display-list, never on the parser — parsing and rendering stay fully decoupled.

zpdf-core            Shared types: ObjectId, PdfObject, Matrix, Rect, Error, ParseLimits
  ├─ zpdf-parser     Lexer, xref/trailer, object & stream decoding, filters
  │   └─ zpdf-document   Catalog, page tree, resource inheritance, font loading
  │       └─ zpdf-content   Content-stream interpreter → DisplayList
  ├─ zpdf-font       Type1 / TrueType / CID / Type3 fonts, CMap, encodings
  ├─ zpdf-image      JPEG / Flate / CCITT / masks / palettes → RGBA
  ├─ zpdf-color      Device / Indexed / Lab color + PDF function evaluator
  ├─ zpdf-display-list   Flat RenderCommand sequence (the backend contract)
  ├─ zpdf-render          RenderBackend trait
  │   ├─ zpdf-render-cpu   tiny-skia backend
  │   └─ zpdf-render-wgpu  wgpu backend (+ winit viewer example)
  ├─ zpdf-writer     PDF authoring & editing: DocumentBuilder, incremental updates,
  │                  merge, redaction, encryption, subsetting, linearization
  ├─ zpdf-pptx-export  DisplayList → editable PowerPoint
  ├─ zpdf-svg-export   DisplayList → vector-faithful SVG
  ├─ zpdf-wasm       WebAssembly bindings (parse + render + text + SVG in browser/Node)
  ├─ zpdf-cli        CLI tool
  ├─ zpdf-viewer-gpui  Native desktop reader (GPUI; depends on the facade)
  └─ zpdf            Facade crate (re-exports; feature-gates cpu / gpu)

Supported PDF features

Feature Status
PDF 1.0–2.0 header
Traditional xref + xref/object streams + hybrid /XRefStm
Incremental update (/Prev) chains, lazy xref repair
Corrupt/headerless recovery (object scan, catalog-in-/ObjStm, page-tree synthesis)
Adversarial-input safety (no panics, no hangs; budget-bounded partial render)
Flate / LZW / ASCII85 / ASCIIHex / RunLength + predictors ✅ with corrupt-stream salvage
DCTDecode (JPEG, incl. CMYK) / CCITTFaxDecode (G3/G4)
Encryption: RC4 40/128, AES-128, AES-256 (R5/R6), crypt filters ✅ user / owner / empty password
Page tree + attribute inheritance (/Rotate, /Resources, boxes)
CropBox-aware rendering + page rotation
Graphics state, paths, painting, clipping, dash patterns
DeviceGray / DeviceRGB / DeviceCMYK / ICCBased (/N)
Indexed / Lab / Separation / DeviceN (tint transforms)
PDF functions (sampled / exponential / stitching / PostScript)
Axial & radial shadings (sh + shading patterns)
Mesh shadings: free-form/lattice Gouraud (type 4/5), Coons/tensor patches (type 6/7)
Tiling patterns (PatternType 1, colored/uncolored cell replication)
16 blend modes (/BM) ✅ both backends
Text + text state operators, render modes, rise ✅ (text-as-clip approximated)
Type3 / TrueType / Type1 / Type1C / CID-Type0 / standard-14 fonts
Encodings + /Differences, /ToUnicode extraction
/CIDToGIDMap streams, OpenType-wrapped CID CFF
Inline & XObject images: 1–16 bpc, /Decode, SMask, /Mask, palettes
Form XObjects (full resources, /BBox clip, recursion guards)
CPU rendering (PNG)
GPU rendering (wgpu)
ExtGState soft masks (/SMask), transparency groups ✅ (knockout + non-isolated)
ICC color profiles (real color management, moxcms)
Annotation appearance streams (/AP, /AS, Hidden/NoView)
Interactive forms (AcroForm): field model + generated text/choice appearances
Non-embedded font fallback (incl. CJK via system fonts)
JBIG2 / JPX (JPEG 2000) filters
Optional content groups / layers (/OCG, /OCMD, /VE)
Predefined + embedded CMaps, vertical writing (WMode 1)
Digital signatures: byte-range integrity + RSA/ECDSA cryptographic verification ✅ (+ opt-in cert-chain trust; no revocation)
PDF creation from scratch (pages, text, images, paths, font embedding + subsetting)
Incremental update writing (annotations, forms, stamps, signing; encrypted docs too)
Encryption on save (AES-256 R6, RC4-128; permissions)
True redaction (content-stream excision + annotation removal)
Document merge incl. outlines, AcroForm fields, OCG configs
Linearization ("fast web view", Annex F)
PDF/A-1b / PDF/A-2b validation (best-effort rule engine)
PowerPoint (PPTX) export (editable text/shapes/images)
SVG export (vector-faithful paths/glyphs/clips/masks)
WebAssembly (parse + render + text + SVG in browser/Node)

Dependencies

All pure Rust:

Crate Purpose
ttf-parser TrueType / OpenType / CFF font parsing
tiny-skia CPU 2D rasterization
flate2 (rust_backend) FlateDecode
zune-jpeg JPEG (DCTDecode)
aes + cbc + sha2 AES encryption/decryption (RustCrypto)
rsa + p256 + p384 RSA/ECDSA signing & verification (RustCrypto)
getrandom Key/salt/IV generation for encryption on save
image PNG I/O
winnow Parsing helpers
wgpu + lyon + pollster GPU rendering (gpu-render feature)
wasm-bindgen WebAssembly bindings (zpdf-wasm)
resvg SVG rasterizer (test dependency for SVG export fidelity)
winit Viewer example only (dev-dependency)

Development

Contributions are welcome. Read CONTRIBUTING.md for project scope, development setup, test expectations, and the pull request process. For usage help, see SUPPORT.md. Report vulnerabilities privately as described in SECURITY.md.

cargo build                                   # CPU-only (default)
cargo build --features gpu-render             # include the wgpu backend
cargo test                                    # all tests
cargo test -p zpdf --features gpu-render      # + the GPU↔CPU acceptance harness
cargo clippy --workspace

Roadmap

See ROADMAP.md.

  • Phase 1 — PDF parsing — done
  • Phase 2 — Content interpretation + CPU rendering — done
  • Phase 3 — wgpu GPU rendering — done
  • Phase 4 — Advanced features — done (encryption incl. AES + user/owner passwords, shadings + mesh shadings, blend modes, spot color, CropBox/rotation, tiling-pattern cells, soft masks & transparency groups, annotation appearance streams, interactive forms (AcroForm), optional content, ICC color management, JBIG2 + JPEG 2000, system-font fallback, composite-font CMaps + vertical writing)
  • Writer toolkit — done (document creation from scratch, incremental updates incl. encrypted documents, encryption on save, true redaction, full document merge, font subsetting + image downsampling, signature creation + trust-chain verification, linearization, PDF/A validation)
  • Robustness — corrupt/adversarial-corpus pass: opens 426/618 of a malformed-PDF corpus (from 166), zero render panics, zero timeouts/hangs

License

MIT