Built specifically for Kotlin Multiplatform
PdfKmp is a KMP-first library. The DSL, the layout engine, and the document model all live in commonMain. Rendering dispatches to each OS's native PDF stack — android.graphics.pdf.PdfDocument on Android, UIGraphicsBeginPDFContextToData + Core Graphics on iOS. You write the document once and ship it to both stores.
If you only target Android, you can still use it as a plain Android library (pdfkmp-android artifact).
What's in the box
Document structure
- A Compose-style DSL:
pdf { … },page { … },column,row,box,card - Spacing, padding, weighted children, alignment
- Multi-page documents with automatic pagination
Text rendering
- Vector glyph paths — every character is a real PDF text operator, not a bitmap
- Single-style
text(...)blocks and multi-stylerichText { span(...) }runs - Font weights, italics, underline, strikethrough, letter spacing, line height, alignment
Tables
- Column weights and per-cell styling
- Header rows that repeat on every page
- Automatic page-break across long tables — no orphan rows
Decorations
- Backgrounds, rounded corners, borders, gradients
- Dividers, lines, circles, ellipses
- Bullet and numbered lists
Page-level features
- Headers and footers with access to current page number and total page count
- Watermarks
- Page numbers in any format you write
Hyperlinks
-
link(url) { … }emits real PDF link annotations — clickable in Adobe Reader, Preview, Chrome, and any spec-compliant viewer
Internationalisation
- Bundled Inter font, exposed as
PdfFont.Default, identical bytes on both platforms - Opt-in system fallbacks for non-Latin scripts:
PdfFont.SystemCJK,PdfFont.SystemArabic,PdfFont.SystemPersian - Custom fonts via
registerFont(PdfFont.Custom(name, bytes))for brand or licence-bound typefaces
Images and vector graphics
- Raster images (JPEG / PNG) embedded as-is for real photos
- Vector and SVG images stay vector — sharp at any zoom
Storage
-
StorageLocation.Documents/Downloads/Cache/AppFiles/Temp/Custom - MediaStore on Android Q+ (no runtime permission needed)
- Sandboxed paths on iOS
Opt-in companion modules
-
pdfkmp-viewer— a Compose Multiplatform PDF viewer composable with topbar, share sheet, zoom, search, and text selection. Works as a standalone viewer for any PDF, not just PdfKmp-generated ones. -
pdfkmp-compose-resources— bridges Compose MultiplatformDrawableResourcereferences into the PdfKmp DSL.
The core pdfkmp artifact stays Compose-free. If you don't use Compose, you don't pay for it.
Why vector matters
Most "save to PDF" flows on mobile rasterise — they snapshot a View and embed that bitmap. PdfKmp is vector-only for everything except real photos. That gives you three things:
- Small file size. A typical text-heavy invoice lands in the tens of kilobytes, not megabytes.
- Crisp output at any zoom. Path operators are resolution-independent.
- Searchable, accessible documents. Real text means Preview's ⌘F finds the order number, and screen readers can read the page.
Cross-platform parity is the contract
PdfKmp pins the bundled Inter font on both platforms so glyph metrics match exactly. Same DSL → same line breaks → same page splits → same final file. For non-Latin scripts that rely on system fonts, the fallback is named explicitly so any divergence is visible instead of silent.
If the output ever differs between Android and iOS on a document you care about, that's a bug — open an issue with the DSL snippet.
Stability signals
- 1.0 stable, follows SemVer — no breaking changes within the 1.x line
-
explicitApi()enforced — every public declaration is intentional - Apache 2.0 — drop-in for enterprise, no AGPL friction
- R8-clean — no keep rules required
- No third-party engines — output goes through the OS's native PDF stack

Top comments (0)