A fast, minimal PDF page renderer
Project description
rupdf
A fast, minimal PDF renderer in Rust with Python bindings. Takes pre-laid-out pages and renders them to PDF bytes.
Features
- Text with TTF/OTF fonts, alignment, and colors
- Rectangles with stroke and fill
- Lines with configurable width
- Images (PNG, JPEG, WebP, SVG)
- Barcodes (Code 128, with optional human-readable text)
- Font subsetting - embeds only used glyphs
- Compression - optional zlib compression
Installation
pip install rupdf
Usage
import rupdf
doc = {
"metadata": {
"title": "My Document",
"author": "Jane Doe"
},
"pages": [
{
"size": (612, 792), # Letter size in points
"background": (255, 255, 255, 255),
"elements": [
{
"type": "text",
"x": 72,
"y": 72,
"text": "Hello, World!",
"font": "main",
"size": 24,
"color": (0, 0, 0, 255)
},
{
"type": "rect",
"x": 72,
"y": 120,
"w": 200,
"h": 100,
"stroke": 1.0,
"stroke_color": (0, 0, 0, 255),
"fill_color": (240, 240, 240, 255)
}
]
}
],
"resources": {
"fonts": {
"main": {"path": "/path/to/font.ttf"}
# Or: "main": {"bytes": font_bytes}
},
"images": {
"logo": {"path": "/path/to/logo.png"}
# Or: "logo": {"bytes": image_bytes}
}
}
}
# Render to PDF bytes
pdf_bytes = rupdf.render_pdf(doc, compress=True)
# Write to file
with open("output.pdf", "wb") as f:
f.write(pdf_bytes)
Coordinate System
- Origin: top-left corner of the page
- Units: points (1 point = 1/72 inch)
- Y-axis: increases downward
Common page sizes:
- Letter: 612 x 792 points
- A4: 595 x 842 points
Element Types
Text
{
"type": "text",
"x": 72,
"y": 72,
"text": "Hello",
"font": "font_ref", # Reference to fonts in resources
"size": 12, # Font size in points
"color": (0, 0, 0, 255), # RGBA
"align": "left" # "left", "center", or "right"
}
Rectangle
{
"type": "rect",
"x": 72,
"y": 72,
"w": 100,
"h": 50,
"stroke": 1.0, # Stroke width (0 for no stroke)
"stroke_color": (0, 0, 0, 255), # Optional
"fill_color": (255, 255, 255, 255) # Optional
}
Line
{
"type": "line",
"x1": 72,
"y1": 72,
"x2": 200,
"y2": 72,
"stroke": 1.0,
"color": (0, 0, 0, 255)
}
Image
{
"type": "image",
"x": 72,
"y": 72,
"w": 200,
"h": 150,
"image_ref": "logo" # Reference to images in resources
}
Supported formats: PNG, JPEG, WebP (rasterized to 300 DPI), SVG (rendered as vectors).
Barcode (Code 128)
{
"type": "barcode",
"x": 72,
"y": 72,
"w": 200,
"h": 60,
"value": "ABC-123",
"human_readable": True, # Show text below barcode
"font": "font_ref", # Required if human_readable
"font_size": 10
}
QR Code
{
"type": "qrcode",
"x": 72,
"y": 72,
"size": 100, # QR codes are square
"value": "https://example.com",
"color": (0, 0, 0, 255), # Foreground (dark modules)
"background": (255, 255, 255, 255) # Background (light modules)
}
Error Handling
try:
pdf = rupdf.render_pdf(doc)
except rupdf.RupdfError as e:
print(f"Failed to render: {e}")
Common errors:
- Missing font or image reference
- Invalid page dimensions
- Missing required element fields
- Character not found in font
Performance
Benchmarks comparing rupdf to ReportLab (10 iterations each):
| Benchmark | rupdf | ReportLab | Speedup |
|---|---|---|---|
| Empty page | 0.02ms | 0.27ms | 13x |
| 50 text lines | 0.82ms | 0.82ms | 1x |
| 100 rectangles | 0.19ms | 1.02ms | 5x |
| 10 pages | 1.62ms | 3.80ms | 2x |
Development
# Build
maturin develop
# Run tests
cargo test # Rust unit tests
pytest python/tests/ -v # Python tests
# Generate test PDF with all element types
python scripts/generate_test_pdf.py # Without images
python scripts/generate_test_pdf.py --svg logo.svg --png photo.png # With images
# Benchmarks
python benchmarks/run_benchmark.py
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rupdf-0.1.1.tar.gz.
File metadata
- Download URL: rupdf-0.1.1.tar.gz
- Upload date:
- Size: 42.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aa275c321540ed473a3561184caacd7ea2b9a9cbe3d234d43d86efe19e6532de
|
|
| MD5 |
337508aafa7342359b821a1764c3c0e9
|
|
| BLAKE2b-256 |
e6ed69de47bcd824d6898e47d70420489f1d576decc024a7fb0040eefd328c8b
|
File details
Details for the file rupdf-0.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: rupdf-0.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 1.2 MB
- Tags: CPython 3.12, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1f1a304dd32dde33410571f049e114153fb428f9770d2bc60ef881162f4b754a
|
|
| MD5 |
4e3859fdf92e51f60880446ae39b75dc
|
|
| BLAKE2b-256 |
19398861da4ea5e548ed2328df5e35ce98525111f70acf48d0373c0d0deedf7b
|
File details
Details for the file rupdf-0.1.1-cp312-cp312-macosx_11_0_arm64.whl.
File metadata
- Download URL: rupdf-0.1.1-cp312-cp312-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.0 MB
- Tags: CPython 3.12, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2e0bf8790df8c15e51e10088538ae282f2224dc9662148984ecb1becbc1b6b2e
|
|
| MD5 |
bb1c8088d6c8b0c483d1ccf57bb84898
|
|
| BLAKE2b-256 |
296350a0a6c3fcf627a1c2dc0daced368dace2a98801a64246a4a6b5f8edd61c
|
File details
Details for the file rupdf-0.1.1-cp311-cp311-macosx_11_0_arm64.whl.
File metadata
- Download URL: rupdf-0.1.1-cp311-cp311-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.0 MB
- Tags: CPython 3.11, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eeb3513ea902b4f3a9e3e29d7e266a7d6a4c44a72e2352eefc5709aef7daf883
|
|
| MD5 |
95541962e9dda284b7d321cd60bbb1b0
|
|
| BLAKE2b-256 |
2063935cd06f8cc85d4e7be785e3edae670e43462253535d018d1df0517ca067
|