Skip to content

ConaMobileDev/PdfKmp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

118 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

PdfKmp

Maven Central License Kotlin Platforms Docs

Kotlin Multiplatform PDF generator for Android, iOS, Desktop (JVM) & Web (Wasm) β€” vector-first, type-safe, DSL-driven.

πŸ“– Full documentation: conamobiledev.github.io/PdfKmp β€” 20 hand-written guides, every sample, and the Dokka API reference.

Android Desktop β€” macOS Β· Windows Β· Linux (JVM)
PdfKmp brochure rendered on Android PdfKmp brochure rendered on Desktop (macOS / Windows / Linux)
iOS Web (Kotlin/Wasm)
PdfKmp brochure rendered on iOS The PdfKmp web sample running in the browser β€” every PDF generated in-page by Kotlin/Wasm

The same brochure document rendered on Android, iOS and Desktop β€” pixel-identical vector output β€” plus the browser sample generating it live on the Web.

PdfKmp lets you build PDF documents from a Compose-style DSL that runs identically on Android, iOS, Desktop (JVM β€” macOS, Windows, Linux), and the browser (Kotlin/Wasm). Text becomes glyph paths, shapes become path operators β€” every page stays sharp at any zoom level. The library ships the Inter font for cross-platform Latin parity and exposes opt-in references to system CJK / Arabic / Persian fonts so non-Latin scripts render natively on Android and iOS (on Desktop, supply a custom font β€” see i18n fonts).

What's in the box:

  • Rich text engine β€” full justification, automatic hyphenation, maxLines + ellipsis, soft-hyphen + mid-word breaking, super/subscript spans, right-to-left support with bidi reorder + Arabic shaping (incl. kashida justification), and orphan/widow control.
  • Layout & pagination β€” column / row / box / card, weighted children, recursive column slicing, table row slicing with repeating headers, keepTogether, multi-column (columns) and uniform grid, mixed page orientations.
  • Tables, lists, dividers, circles & ellipses, plus a free-form vector DSL (freeDraw).
  • Graphics β€” QR codes, Code 128 / EAN-13 / UPC-A barcodes, Data Matrix, and bar / stacked-bar / (multi-series) line / pie / donut charts β€” all pure vector, no external dependencies.
  • Decorations β€” backgrounds, per-corner radii, per-side borders, dashed / dotted borders, gradients, drop shadows, rotation, and group opacity.
  • Navigation & document features β€” bookmarks / outline, internal links + auto table of contents, hyperlinks, AcroForm fields, encryption, file attachments, best-effort PDF/A, and JVM digital signing.
  • Images & vectors β€” PNG / JPEG / WebP / HEIF, Android <vector> and W3C <svg> (kept vector inside the PDF).
  • Companion modules β€” a Compose Multiplatform PDF viewer, a Compose Resources bridge, and a Markdown renderer.

See the platform feature parity table for what each backend supports.

Under the hood β€” native / pure-Java PDF stacks per platform:

Platform Backend
Android android.graphics.pdf.PdfDocument + android.graphics.Canvas
iOS UIGraphicsBeginPDFContextToData + Core Graphics (CGContext)
Desktop (JVM) Apache PDFBox β€” pure-Java, runs on macOS / Windows / Linux with no native libraries
Web (Wasm) kmpwriter β€” PdfKmp's own pure-Kotlin PDF 1.7 writer (no browser PDF API exists), with TrueType subsetting + Flate compression

Every DSL node funnels into these PDF backends, so the resulting bytes are real, vector PDFs β€” readable in Preview, Adobe Reader, Chrome, and any spec-compliant viewer. On Desktop the embedded TrueType fonts are subsetted to only the glyphs you draw, so text stays vector and the file stays small.


Installation

PdfKmp is published to Maven Central. The library exposes:

  • an Android aar (io.github.conamobiledev:pdfkmp-android),
  • an iOS framework named PdfKmp for arm64 (device) and simulator-arm64 (Apple-Silicon simulator),
  • a Desktop / JVM jar (io.github.conamobiledev:pdfkmp-jvm) for macOS, Windows, and Linux,
  • a Web / Kotlin-Wasm klib (io.github.conamobiledev:pdfkmp-wasm-js) β€” see Web (Kotlin/Wasm) for what the browser backend covers,
  • common Kotlin metadata (io.github.conamobiledev:pdfkmp),
  • an optional Compose Multiplatform Resources companion (io.github.conamobiledev:pdfkmp-compose-resources, with -android / -jvm / -wasm-js platform variants),
  • an optional Markdown renderer (io.github.conamobiledev:pdfkmp-markdown, same platform variants),
  • an optional Compose Multiplatform PDF viewer screen (io.github.conamobiledev:pdfkmp-viewer, with -android / -jvm platform variants β€” not on web; see below).

Web (Kotlin/Wasm)

The browser exposes no PDF engine to Wasm, so the web target renders through PdfKmp's own pure-Kotlin PDF writer β€” everything vector works exactly like the other platforms, custom TrueType fonts embed as subsets, and Cyrillic works out of the box via the bundled Inter. Current limits and font details: see the Web guide.

Viewing needs no library at all β€” browsers ship excellent PDF viewers, so hand them the bytes:

val doc = pdf { page { text("Hello, Wasm!") } }
doc.openInNewTab()                                  // browser's own viewer
doc.save(StorageLocation.Downloads, "hello.pdf")    // browser download

Make sure Maven Central is in your repository list:

// settings.gradle.kts
dependencyResolutionManagement {
    repositories {
        mavenCentral()
    }
}

Pick the section that matches your project. The paths are mutually exclusive β€” KMP projects depend on pdfkmp only (Gradle resolves the right platform variant automatically, including for Android and Desktop targets), while plain Android projects depend on pdfkmp-android and plain JVM/Desktop projects on pdfkmp-jvm. Inside each path, use whichever dependency style your project already uses; the libs.versions.toml form is recommended for new projects.

Kotlin Multiplatform project

Depend on pdfkmp from commonMain. Do not add pdfkmp-android separately β€” Gradle picks the Android variant of pdfkmp for your Android target on its own. (Version catalogs work as usual β€” map the same coordinates in libs.versions.toml.)

// build.gradle.kts
kotlin {
    sourceSets {
        commonMain.dependencies {
            implementation("io.github.conamobiledev:pdfkmp:1.2.0")
            implementation("io.github.conamobiledev:pdfkmp-compose-resources:1.2.0") // optional
            implementation("io.github.conamobiledev:pdfkmp-viewer:1.2.0")            // optional
        }
    }
}

Both companions are opt-in:

  • pdfkmp-compose-resources β€” add it only if your project uses Compose Multiplatform Resources (Res.drawable.*) and you want typed resource references inside the PdfKmp DSL. Full usage in the Compose Resources guide.
  • pdfkmp-viewer β€” Compose Multiplatform PDF viewer screen with topbar, search, share, save, hyperlinks, gesture-driven zoom & text selection. Skip it if you only need to generate PDFs and let users view them in their system default reader. Full usage in the viewer guide.

The core pdfkmp artifact itself stays Compose-free β€” non-Compose consumers don't pay for either companion.

Android-only project

For projects that don't use Kotlin Multiplatform (plain com.android.application or com.android.library), depend on pdfkmp-android. KMP consumers should use the section above instead β€” they should not add this artifact.

// app/build.gradle.kts
dependencies {
    implementation("io.github.conamobiledev:pdfkmp-android:1.2.0")
    implementation("io.github.conamobiledev:pdfkmp-viewer:1.2.0") // optional β€” Compose viewer screen
}

pdfkmp-viewer brings in Compose Multiplatform β€” skip it if your Android project still uses the legacy View system. The viewer assumes Compose hosting (a ComponentActivity with setContent { … } or an embedded ComposeView).

Desktop / JVM project

KMP projects with a jvm() target need no extra setup β€” Gradle resolves the Desktop variant of pdfkmp for the JVM target automatically, exactly like it does for Android. For a plain JVM project (a standalone Compose for Desktop app or any non-KMP Gradle JVM module), depend on pdfkmp-jvm directly:

// build.gradle.kts
dependencies {
    implementation("io.github.conamobiledev:pdfkmp-jvm:1.2.0")
    implementation("io.github.conamobiledev:pdfkmp-viewer-jvm:1.2.0") // optional β€” Compose for Desktop viewer
}

The Desktop backend is built on Apache PDFBox (pulled in transitively) and is pure-Java, so the same artifact runs on macOS, Windows, and Linux with no native libraries to bundle. The generation API (pdf { … }, document.save(...), toByteArray()) is identical across all platforms. pdfkmp-viewer on Desktop hosts the viewer in a Compose for Desktop window and rasterises pages with PDFBox's PDFRenderer.

Requirements

  • JDK 17+
  • Android Gradle Plugin 8.x, compileSdk 34+ (Android targets)
  • Xcode 16+ when targeting iOS via Kotlin Multiplatform
  • A desktop JRE 17+ when targeting Desktop / JVM (macOS, Windows, Linux)

R8 / ProGuard

R8 is fully supported β€” no additional keep rules required.


Hello world

import com.conamobile.pdfkmp.pdf
import com.conamobile.pdfkmp.storage.StorageLocation
import com.conamobile.pdfkmp.storage.save
import com.conamobile.pdfkmp.style.PdfColor
import com.conamobile.pdfkmp.unit.sp

// 1. Build the document
//    Use `pdf { }` for a synchronous build, or `pdfAsync { }` (suspend) when
//    the tree contains typed `Res.drawable.*` references β€” see Compose
//    Multiplatform Resources below.
val document = pdf {
    metadata { title = "Hello, PdfKmp" }
    page {
        text("Hello, world!") {
            fontSize = 24.sp
            bold = true
            color = PdfColor.Blue
        }
    }
}

// 2. Pick what to do with it:
val bytes: ByteArray = document.toByteArray()              // raw bytes
// or
val saved = document.save(StorageLocation.Cache, "hello.pdf")  // returns SavedPdf (synchronous)
println(saved.path)  // absolute filesystem path you can hand to a viewer / share intent

After save(...) you get a SavedPdf with a real filesystem path you can hand to a PDF viewer or a share sheet β€” the Getting started guide has ready-made view / share / open snippets for every platform.


Documentation

This README covers installation and your first document only β€” everything else lives on the documentation site:

πŸ“– conamobiledev.github.io/PdfKmp

  • Getting started β€” every feature guide: text & typography, layout, tables, decorations, images & SVG, QR / barcodes / charts, navigation & TOC, pages / headers / watermarks, forms & security, fonts & i18n, the Compose viewer, Markdown-to-PDF, and the Web (Wasm) target.
  • Samples β€” every bundled showcase document, with the code that builds it.
  • Internals β€” how the layout engine and the per-platform renderers work.
  • API Reference β€” generated KDoc for every public declaration.

For repo conventions and AI-agent guidance see CLAUDE.md (working on this codebase) and AGENTS.md / .claude/skills/pdfkmp/SKILL.md (using the library).


License

Apache License 2.0 β€” see LICENSE.

The bundled Inter font is licensed separately under the SIL Open Font License 1.1 β€” see pdfkmp/fonts/Inter-LICENSE.txt.


If PdfKmp saved you some time, don't forget to click ⭐ β€” it helps others find the project :)

About

Kotlin Multiplatform PDF generator - Android, iOS, Desktop (JVM), Web (Wasm). Vector-first Compose-style DSL, viewer, markdown.

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages