# PaperForge
> A comprehensive, pure-Rust PDF generation, editing, inspection, rendering, and document-processing engine.
[](https://github.com/Rohithdgrr/paperforge/actions)
[](https://crates.io/crates/paperforge)
[](https://docs.rs/paperforge)
[](LICENSE-MIT)
[](LICENSE-APACHE)
## Overview
PaperForge is a native Rust alternative to Python ReportLab and fragmented Rust PDF tooling. One coherent API for generating, editing, parsing, rendering, and extracting PDF documents.
## Quick Start
Add to your `Cargo.toml`:
```toml
[dependencies]
paperforge = "0.1"
```
Generate a PDF:
```rust
use paperforge::prelude::*;
fn main() -> Result<(), PdfError> {
let mut doc = Document::new();
let page = doc.add_page(PageSize::A4);
page.text()
.at(50.mm(), 250.mm())
.font_size(24.0)
.write("Hello, Rust!");
doc.save("hello.pdf")?;
Ok(())
}
```
## Features
| PDF Generation | โ
|
| PDF Parsing | โ
|
| PDF Editing | ๐ (merge/split via CLI + `paperforge-pdf` edit API) |
| Text + Unicode | โ
|
| Font Embedding | ๐ (loading scaffold; TTF parsing/subsetting planned) |
| JPEG/PNG Images | โ
(JPEG pass-through, PNG decode, `/SMask`) |
| Vector Graphics | โ
|
| Basic Layout | ๐ |
| Tables | ๐ |
| Forms | ๐ |
| Rendering | ๐ |
| Encryption | ๐ |
| PDF/A | ๐ |
## Architecture
```
paperforge/
โโโ paperforge/ # Main public crate
โโโ paperforge-core/ # PDF-independent abstractions
โโโ paperforge-pdf/ # PDF serialization/parsing
โโโ paperforge-layout/ # High-level document layout
โโโ paperforge-fonts/ # Font handling
โโโ paperforge-images/ # Image support
โโโ paperforge-render/ # PDF rendering
โโโ paperforge-forms/ # AcroForm support
โโโ paperforge-annotations/ # Annotations
โโโ paperforge-security/ # Encryption/security
โโโ paperforge-extract/ # Text/image extraction
โโโ paperforge-cli/ # CLI tool
```
## Benchmarks
Measured with [criterion](https://github.com/bheisler/criterion.rs) (30 samples, median) on an **AMD Ryzen 5 7235HS / Windows 11** (2026-08-13). Workload: a 100-page A4 text document โ one heading and one body line per page โ built with each library's high-level (or object-level, for lopdf) API and then parsed from the same in-memory bytes. Every library builds the identical workload. Reproduce with `cargo bench -p paperforge-bench`.
| Generate 100-page text doc | 1.77 ms | 482 ยตs | 6.45 ms |
| Generate, content compression off | 543 ยตs | 482 ยตs ยน | โ |
| Parse 100-page doc (~36 KB) | 423 ยตs | 467 ยตs | โ |
| Streaming open (no parse) | 129 ยตs | โ | โ |
| Output size (100 pages) | 35.9 KB | 27.4 KB | 60.9 KB |
ยน lopdf writes uncompressed streams by default; both columns use each library's default settings.
Notes:
- **Generation beats printpdf by ~3.6ร.** paperforge (default: flate-compressed content, level 6) generates the 100-page document in 1.77 ms โ 3.6ร faster than printpdf (6.45 ms). lopdf remains the fastest because its default output skips compression entirely and is object-level; with compression disabled paperforge (543 ยตs) is within ~13% of lopdf (482 ยตs) on the same uncompressed workload, down from ~20% in the previous release.
- **Parsing beats lopdf** โ 423 ยตs vs 467 ยตs on the same compressed 100-page document.
- **Streaming open is 3.6ร faster than lopdf's full parse** โ 129 ยตs to open a file and have random access to all 205 objects, vs 467 ยตs for lopdf's parse.
- **Output is 1.7ร smaller than printpdf** (35.9 KB vs 60.9 KB). paperforge's output is also 25% smaller than the previous release (47.7 KB) thanks to a single shared `/Resources` object referenced by every page. lopdf's 27.4 KB is uncompressed object-level output that omits required structure such as the `/Parent` link; paperforge keeps full spec compliance (ISO 32000-1).
- The speedups come from reusing zlib compressor state across content streams (4โ6ร faster flate on many small streams), building content streams into a reused buffer without per-command `format!` allocations, interning common dictionary keys (`/Type`, `/Parent`, โฆ) so dict inserts allocate nothing, `ryu` number formatting for content-stream coordinates, a fast hasher for dictionary keys, and manual integer/number parsing in the parser (no per-number UTF-8 validation or `str::parse`).
- The parse benchmark surfaced a real interop bug: xref table entries were 19 bytes instead of the spec-mandated 20 (ISO 32000-1 ยง7.5.4), which strict parsers such as lopdf reject. Entries are now spec-compliant, locked in by `serializer::tests::xref_entries_are_exactly_20_bytes`.
- Criterion also writes per-run reports and regression tracking to `target/criterion/`.
Full methodology and analysis are in [docs/benchmarks.md](docs/benchmarks.md).
## Feature Flags
```toml
[dependencies]
paperforge = { version = "0.1", features = ["generate", "parse", "layout", "fonts", "images"] }
```
Available features: `generate`, `parse`, `edit`, `layout`, `fonts`, `images`, `render`, `forms`, `annotations`, `security`, `extract`, `svg`.
## License
Dual-licensed under MIT OR Apache-2.0.