Warning: This project is under active development. The API is unstable and subject to breaking changes. Do not use in production environments.
A Rust library for creating and manipulating PDF documents with a focus on ease of use and comprehensive text layout support.
- Layout-based document creation - Cursor-based layout with automatic text flow, margins, and bounding boxes
- Rich text formatting - Bold, italic, colors, alignment (left/center/right/justify)
- Font support - 14 standard PDF fonts + TrueType/OpenType embedding with text shaping
- Font fallback - Automatic fallback for mixed-language text (CJK, emoji, etc.)
- Tables - Full-featured tables with borders, cell styles, column spans, and overflow handling
- Images - PNG and JPEG embedding with fit/fill modes
- SVG rendering - Embed SVG graphics directly
- Links and outlines - Hyperlinks, internal links, and document bookmarks
- Forms - Interactive form fields (text, checkbox, radio, dropdown)
- WASM support - Works in WebAssembly environments (tested with Cloudflare Workers)
- Python bindings - Use pdfcrate from Python via PyO3
Add to your Cargo.toml:
[dependencies]
pdfcrate = "0.1"use pdfcrate::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
Document::generate("hello.pdf", |doc| {
doc.title("Hello PDF").author("pdfcrate");
doc.font("Helvetica-Bold").size(24.0);
doc.text("Hello, World!");
doc.move_down(20.0);
doc.font("Helvetica").size(12.0);
doc.text_wrap("This is a simple PDF document created with pdfcrate. \
Text automatically wraps within the page margins.");
Ok(())
})?;
Ok(())
}use pdfcrate::prelude::*;
Document::generate("custom_font.pdf", |doc| {
// Embed a TrueType font
let font = doc.embed_font_file("fonts/MyFont.ttf")?;
doc.font(&font).size(16.0);
doc.text("Text with custom font!");
Ok(())
})?;use pdfcrate::prelude::*;
Document::generate("multilingual.pdf", |doc| {
let cjk_font = doc.embed_font_file("fonts/NotoSansCJK.ttf")?;
// Configure fallback fonts
doc.fallback_fonts(vec![cjk_font]);
doc.font("Helvetica").size(14.0);
doc.text_wrap("English text mixed with 中文 and 日本語");
Ok(())
})?;use pdfcrate::prelude::*;
Document::generate("table.pdf", |doc| {
let table = Table::new(&[100.0, 150.0, 100.0])
.header(&["Name", "Description", "Price"])
.row(&["Item 1", "First item", "$10.00"])
.row(&["Item 2", "Second item", "$20.00"])
.borders(BorderStyle::all(0.5, Color::BLACK));
doc.table(&table);
Ok(())
})?;use pdfcrate::prelude::*;
Document::generate("with_image.pdf", |doc| {
// Embed and draw image
doc.image_fit("photo.png", [0.0, 0.0], 200.0, 150.0)?;
Ok(())
})?;pdfcrate provides Python bindings via PyO3 and maturin.
# Install in development mode
uv run maturin develop --features python
# Run the showcase
uv run python examples/showcase.pyfrom pdfcrate import Document, Margin, Color, TextFragment
doc = Document(margin=Margin(36, 36, 36, 36))
doc.title("Hello from Python")
doc.font("Helvetica", 24)
doc.text("Hello, World!")
doc.move_down(20)
doc.font("Helvetica", 12)
doc.text("Created with pdfcrate Python bindings.")
doc.save("hello.pdf")All features are pure Rust and WASM-compatible.
| Feature | Default | Description |
|---|---|---|
std |
Yes | Standard library support (file I/O) |
png |
Yes | PNG image support (JPEG is always supported) |
fonts |
Yes | TrueType/OpenType font embedding |
text-shaping |
Yes | Complex text shaping via rustybuzz |
svg |
Yes | SVG rendering support |
barcode |
Yes | QR code and barcode generation |
python |
No | Python bindings (PyO3) |
To use minimal features:
[dependencies]
pdfcrate = { version = "0.1", default-features = false }Rust 1.87 or later.
This project is licensed under the MIT License - see the LICENSE file for details.