Strip unused glyphs from embedded fonts so the PDF only carries the characters that actually appear in the document.
use pdfluent::{Document, optimizer::FontSubsetOptions};
fn main() -> pdfluent::Result<()> {
let mut doc = Document::open("input.pdf")?;
let opts = FontSubsetOptions {
subset_type1: false, // Type1 subsetting is lossy; skip by default
subset_truetype: true,
subset_opentype: true,
};
doc.subset_fonts(opts)?;
doc.save("subsetted.pdf")?;
Ok(())
}Before subsetting, you can list embedded fonts and their sizes to understand what will change.
let doc = Document::open("input.pdf")?;
for font in doc.fonts() {
println!(
"{} ({:?}) embedded={} size={}B",
font.name(),
font.font_type(),
font.is_embedded(),
font.embedded_size_bytes().unwrap_or(0),
);
}FontSubsetOptions controls which font types are processed. Type 1 fonts often have limited glyph sets already; focus on TrueType and OpenType where gains are largest.
use pdfluent::optimizer::FontSubsetOptions;
let opts = FontSubsetOptions {
subset_type1: false,
subset_truetype: true,
subset_opentype: true,
};PDFluent scans every page content stream, collects the Unicode codepoints actually used, then rewrites each embedded font to contain only those glyphs.
let mut doc = Document::open("input.pdf")?;
doc.subset_fonts(opts)?;Check the font sizes again after subsetting to measure the reduction.
for font in doc.fonts() {
println!(
"{} size after={}B",
font.name(),
font.embedded_size_bytes().unwrap_or(0),
);
}Write the subsetted file. Combine with compress_streams() for maximum size reduction.
doc.compress_streams()?;
doc.save("subsetted.pdf")?;No JVM, no runtime, no DLL dependencies. Ships as a single native binary or WASM module.
Rust's ownership model prevents buffer overflows and use-after-free. No segfaults in PDF parsing.
Same code runs server-side, in Docker, on AWS Lambda, on Cloudflare Workers, or in the browser via WASM.