A high-performance, pure Rust reimplementation of Apache FOP (Formatting Objects Processor), translating XSL-FO documents to PDF, SVG, PostScript, raster images, and plain text.
170 Rust files Β· 72,872 lines of code Β· 3,010+ tests Β· Zero warnings Β· 10β1200Γ faster than Java FOP
Phase 5β6 Enhanced β Production ready with comprehensive features and testing.
| Phase | Status | Description |
|---|---|---|
| Phase 1: Foundation | β Complete | Core types, property system, FO tree parsing |
| Phase 2: Basic Layout | β Complete | Area tree, block/inline layout, PDF output |
| Phase 3: Advanced Layout | β Complete | Knuth-Plass line breaking, tables, lists, graphics, images |
| Phase 4: Integration | β Complete | Multi-page breaking, engine integration |
| Phase 5: Advanced Features | β Complete | Image rendering, links, bookmarks, font embedding, i18n, encryption |
| Phase 6: Optimization | π 85% Complete | Performance (β ), streaming (β ), testing (β ) |
Current stats: 3,010+ tests (all passing), 0 compiler warnings, 0 clippy warnings, 10β1200Γ faster than Java FOP
- 294 XSL-FO 1.1 properties with full inheritance and shorthand expansion
- 29 FO element types β blocks, inlines, tables, lists, graphics, links, page masters
- Knuth-Plass optimal line breaking β same algorithm as TeX for publication-quality typography
- Multi-page breaking with widow/orphan control and overflow detection
- PDF β valid, viewable, text-extractable, with font embedding and subsetting
- SVG β scalable vector graphics output
- PostScript β for print workflows
- PNG / JPEG β raster image output
- Plain text β text extraction mode
- PDF encryption β RC4-128 with owner/user passwords and permission control
- PDF/A compliance mode β for archival-quality output
- Bookmarks and outlines β document navigation
- Internal and external links β clickable hyperlinks
- Font embedding and subsetting β TrueType/OpenType with CIDFontType2 + Identity-H encoding
- 16+ languages supported β Japanese, Chinese, Korean, Arabic, Thai, Hindi, Hebrew, and more
- CJK support β Type 0 composite fonts with proper glyph rendering
- Right-to-left (RTL) β Arabic and Hebrew bidirectional text
- Emoji and full Unicode β complete Unicode coverage
- See docs/I18N_CAPABILITIES.md for the full guide
- Streaming mode for large documents (>1000 pages) with bounded memory
- Parallel rendering infrastructure for multi-core utilization
- 10β1200Γ faster than Java FOP across all benchmarks
- <10ms startup vs ~2000ms JVM cold start
The fop-pdf-renderer crate parses and rasterizes PDF output with no C dependencies (no poppler, no Ghostscript). Use it programmatically or from the CLI:
use fop_pdf_renderer::PdfRenderer;
let renderer = PdfRenderer::from_bytes(&pdf_bytes)?;
let page = renderer.render_page(0, 150.0)?; // 150 DPI β RasterPage
let text = renderer.extract_text(0)?; // user-visible text extractionCLI equivalents:
# Round-trip self-verification (generates PDF then rasterizes it internally)
fop input.fo output.pdf --render-verify
# Standalone PDF β PNG conversion
fop-render-pdf output.pdf page.png 150- CLI β Apache FOP-compatible command-line interface with progress bars and JSON stats
- WASM β browser and Node.js bindings via
wasm-bindgen - Python β bindings via PyO3 (published as
fop2on PyPI)
Real benchmark results against Java Apache FOP:
| Metric | Java FOP | Rust FOP | Speedup |
|---|---|---|---|
| Simple document render | ~50ms | ~0.04ms | ~1200Γ |
| Parse 1000-page doc | ~500ms | <50ms | ~10Γ |
| Memory per page | ~50KB | <5KB | ~10Γ |
| Binary size | 15MB+ JAR | <5MB stripped | ~3Γ |
| Startup time | ~2000ms (JVM) | <10ms | ~200Γ |
# Build
cargo build --release
# Run tests (zero warnings policy)
cargo nextest run --all-features
cargo clippy --all-targets -- -D warnings
# Run an example
cargo run --example hello_pdfuse fop_core::FoTreeBuilder;
use fop_layout::LayoutEngine;
use fop_render::PdfRenderer;
use std::io::Cursor;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let xml = r#"<?xml version="1.0"?>
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<fo:simple-page-master master-name="A4"
page-width="210mm" page-height="297mm">
<fo:region-body margin="1in"/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="A4">
<fo:flow flow-name="xsl-region-body">
<fo:block font-size="14pt">Hello, FOP!</fo:block>
</fo:flow>
</fo:page-sequence>
</fo:root>"#;
// Parse -> Layout -> Render
let fo_tree = FoTreeBuilder::new().parse(Cursor::new(xml))?;
let area_tree = LayoutEngine::new().layout(&fo_tree)?;
let pdf_doc = PdfRenderer::new().render(&area_tree)?;
let pdf_bytes = pdf_doc.to_bytes()?;
std::fs::write("output.pdf", &pdf_bytes)?;
println!("Wrote output.pdf ({} bytes)", pdf_bytes.len());
Ok(())
}# Convert XSL-FO to PDF
fop -fo input.fo -pdf output.pdf
# Convert to SVG
fop -fo input.fo -svg output.svg
# Convert to PostScript
fop -fo input.fo -ps output.ps
# With progress bar and JSON stats
fop -fo input.fo -pdf output.pdf --progress --stats
# See all options
fop --helpSee crates/fop-cli/USAGE.md for the full CLI reference.
The Python package is available on PyPI as fop2.
pip install fop2import fop
# One-shot conversion
pdf_bytes = fop.convert_to_pdf(fo_xml_string)
# Or use the converter class
converter = fop.FopConverter()
pdf = converter.convert_to_pdf(fo_xml)
svg = converter.convert_to_svg(fo_xml)
text = converter.convert_to_text(fo_xml)The WASM package is available on npm as @cooljapan/fop.
npm install @cooljapan/fopimport init, { FopConverter } from '@cooljapan/fop';
await init();
const converter = new FopConverter();
const pdfBytes = converter.convertToPdf(foXml);
const svgString = converter.convertToSvg(foXml);π Comprehensive documentation available in docs/
- docs/README.md β Complete documentation index
- docs/I18N_CAPABILITIES.md β Internationalization guide (Japanese, CJK, Arabic RTL, etc.)
- docs/LIMITATIONS.md β Current limitations and migration guide from Java FOP
fop/
βββ Cargo.toml # Workspace root + top-level fop crate
βββ crates/
β βββ fop-types/ # Core types (Length, Color, Rect, FontMetrics, errors)
β βββ fop-core/ # FO tree parsing & 294-property system
β βββ fop-layout/ # Layout engine (block, inline, table, list, page breaking)
β βββ fop-render/ # Rendering backends (PDF, SVG, PostScript, raster, text)
β βββ fop-pdf-renderer/ # Pure Rust PDF-to-image renderer (glyph outlines, text extraction, self-verification)
β βββ fop-cli/ # CLI tool (fop binary)
β βββ fop-wasm/ # WebAssembly bindings (browser / Node.js)
β βββ fop-python/ # Python bindings via PyO3
βββ examples/ # 23 runnable examples
βββ benches/ # Performance & comparison benchmarks
βββ tests/ # Integration tests
βββ fuzz/ # Fuzz testing targets
βββ docs/ # Documentation
fop-types (no internal deps)
β
βββ fop-core (+ quick-xml)
β β
β βββ fop-layout (+ image)
β β β
β β βββ fop-render (+ oxiarc-deflate, ttf-parser, png, aes, sha2, md-5,
β β β resvg, usvg, jpeg-encoder, tiny-skia)
β β β
β β βββ fop-cli (+ clap, anyhow, indicatif, console,
β β β humantime, bytesize, serde_json)
β β β
β β βββ fop-wasm (+ wasm-bindgen, js-sys, serde-wasm-bindgen)
β β β
β β βββ fop-python (+ pyo3)
β β
βββββββββ
fop-pdf-renderer (standalone: thiserror, oxiarc-deflate, ttf-parser, png,
jpeg-decoder, tiny-skia)
| Category | Elements |
|---|---|
| Root & Structure | fo:root, fo:layout-master-set, fo:simple-page-master |
| Regions | fo:region-body, fo:region-before, fo:region-after, fo:region-start, fo:region-end |
| Page Sequences | fo:page-sequence, fo:flow, fo:static-content |
| Block-level | fo:block, fo:block-container |
| Inline-level | fo:inline, fo:character, fo:page-number, fo:page-number-citation |
| Tables | fo:table, fo:table-column, fo:table-header, fo:table-body, fo:table-row, fo:table-cell |
| Lists | fo:list-block, fo:list-item, fo:list-item-label, fo:list-item-body |
| Graphics & Links | fo:external-graphic, fo:basic-link |
| Leaders | fo:leader |
All 23 examples can be run with cargo run --example <name>:
| Example | Description |
|---|---|
basic_types |
Length, Color, Geometry type usage |
border_background_demo |
Borders and background styling |
cli_production_example |
Production CLI workflow demonstration |
comprehensive_demo |
All Phase 3 features combined |
generate_japanese_pdfs |
Japanese PDF generation with CJK fonts |
hello_pdf |
Minimal PDF generation |
i18n_multi_font |
Multi-font internationalization |
i18n_showcase |
Full i18n showcase (16+ languages) |
layout_demo |
FO tree to area tree transformation |
manual_japanese_font |
Manual Japanese font configuration |
parse_fo_document |
Full XSL-FO document parsing |
pdf_encryption |
PDF encryption with RC4-128 |
phase5_complete_demo |
Phase 5 complete feature demonstration |
phase5_features |
Phase 5 individual features |
properties |
Property system and inheritance |
ps_output_demo |
PostScript output generation |
shorthand |
Shorthand property expansion (margin, padding, border) |
streaming_demo |
Streaming mode for large documents |
styled_pdf |
PDF with colors and fonts |
svg_output_demo |
SVG output generation |
tables_lists_demo |
Tables and lists end-to-end |
text_extraction_demo |
Text extraction from PDF |
validation |
Element nesting validation |
All dependencies are pure Rust β no C/Fortran/system libraries required.
| Crate | Version | Purpose |
|---|---|---|
quick-xml |
0.39 | XML parsing (zero-copy) |
thiserror |
2.0 | Error type derivation |
log |
0.4 | Logging facade |
oxiarc-deflate |
0.2.6 | PDF stream compression (deflate) β pure Rust |
ttf-parser |
0.25 | TrueType/OpenType font parsing |
png |
0.18 | PNG image encoding/decoding |
jpeg-decoder |
0.3 | JPEG image decoding |
jpeg-encoder |
0.7 | JPEG image encoding |
image |
0.25 | Image format detection and loading |
tiny-skia |
0.12 | 2D raster rendering |
resvg |
0.47 | SVG rendering |
usvg |
0.47 | SVG tree simplification |
aes |
0.8 | AES encryption (PDF security) |
cbc |
0.1 | CBC block cipher mode |
sha2 |
0.10 | SHA-256 hashing (PDF encryption) |
md-5 |
0.10 | MD5 hashing (PDF encryption) |
| Crate | Version | Purpose |
|---|---|---|
clap |
4.5 | Command-line argument parsing |
anyhow |
1.0 | Error handling |
indicatif |
0.18 | Progress bars |
console |
0.16 | Terminal formatting |
humantime |
2.3 | Human-readable durations |
bytesize |
2.3 | Human-readable byte sizes |
serde_json |
1.0 | JSON statistics output |
| Crate | Version | Purpose |
|---|---|---|
pyo3 |
0.28 | Python bindings (ABI3, Python 3.8+) |
wasm-bindgen |
0.2 | WebAssembly bindings |
js-sys |
0.3 | JavaScript interop |
XSL-FO XML βββ FO Tree βββ Area Tree βββ Output (PDF/SVG/PS/PNG/text)
(parse) (layout) (render)
- Zero-copy parsing β
Cow<'static, str>and arena allocation throughout - Arena allocation β index-based tree nodes (no
Rc<RefCell<>>overhead) - Static dispatch β enum dispatch over trait objects where possible
- Millipoint arithmetic β 1/1000 pt precision with integer math (no floating-point drift)
- Release profile β LTO + single codegen unit + opt-level 3 + stripped binaries
- 3,010+ tests β unit, integration, and fuzz targets
- Zero warnings β enforced via
cargo clippy --all-targets -- -D warnings - Fuzz testing β
fuzz_xml_parser,fuzz_property_parser,fuzz_layout - PDF self-verification β
fop-pdf-rendererrenders generated PDFs back to compare
.github/workflows/ci.yml runs fmt, clippy -D warnings, cargo nextest, and doc -D warnings on every push and PR across Linux, macOS, and Windows (stable Rust). No poppler or Ghostscript is installed on any runner β the auto-verify path is exercised end-to-end through the pure-Rust fop-pdf-renderer. Python (PyO3) and WASM bindings are built in a dedicated job that installs the required toolchains.
This project enforces zero compiler warnings and zero clippy warnings:
cargo clippy --all-targets -- -D warnings
cargo nextest run --all-features# Debug build
cargo build
# Optimized release build (LTO + stripped)
cargo build --release
# Build WASM bindings
cd crates/fop-wasm && wasm-pack build --target web
# Build Python bindings
cd crates/fop-python && maturin develop --releasecargo bench --bench fop_benchmarks
cargo bench --bench comparison_benchmarks
cargo bench --bench performance_benchmarksSee benches/README.md for benchmark details.
- Based on Apache FOP (Java, 1566+ files across 8 Maven modules)
- Implements XSL-FO 1.1 Specification
- CHANGELOG.md β Release history
FOP is developed and maintained by COOLJAPAN OU (Team Kitasan).
If you find FOP useful, please consider sponsoring the project to support continued development of the Pure Rust ecosystem.
https://github.com/sponsors/cool-japan
Your sponsorship helps us:
- Maintain and improve the COOLJAPAN ecosystem
- Keep the entire ecosystem (OxiBLAS, OxiFFT, SciRS2, etc.) 100% Pure Rust
- Provide long-term support and security updates
Licensed under the Apache License, Version 2.0. See LICENSE for details.
Copyright 2024β2026 COOLJAPAN OU (Team Kitasan)