Skip to content

KitePDF

One pure-Kotlin document engine for Kotlin Multiplatform. Read, create, edit and render PDFs, and read EPUBs, from commonMain, with the exact same code on every target: Android, iOS, desktop, web and Kotlin/Native.

// commonMain. Nothing platform-specific. This runs everywhere Kotlin runs.
val doc = PdfDocument.open(bytes)

val text = doc.pages[0].extractText()       // read
doc.edit().apply {                          // edit
    redactRegion(doc.pages[0], Rectangle(72.0, 700.0, 320.0, 720.0))
}.saveRewritten()

val fresh = PdfBuilder()                     // create
    .page { text(StandardFont.Helvetica, 24.0, x = 72.0, y = 720.0, "Hello, world!") }
    .build()

Why KitePDF

Most "Kotlin PDF libraries" are thin expect/actual wrappers around the platform's own engine: PdfRenderer on Android, PDFKit on iOS, PDF.js in the browser, PDFBox on the JVM. You then depend on four engines. Each one has its own bugs and its own feature set.

KitePDF is a single standalone engine, written in Kotlin and almost entirely in common code. Parser, renderer, writer, editor, encryption and fonts are all included, and kitepdf-core carries just three expect declarations (a mutex, a thread id, and the deflate/inflate hook). Write your PDF code once in commonMain and the same implementation runs on every target.

Drawing to a screen is the only job that needs a platform. KitePDF keeps that job in separate artifacts, so the engine itself stays portable.

Install

The engine is a single dependency. Add it to commonMain and you have everything except drawing to a screen:

kotlin {
    sourceSets {
        commonMain.dependencies {
            implementation("io.github.yuroyami:kitepdf:0.5.0")
        }
    }
}

Its runtime dependencies are kotlin-stdlib and the pure-Kotlin KiteImage codec engine. It runs on every target listed under Platform support.

Drawing a page to the screen is the one job that needs a platform, so the rendering bindings are separate, opt-in artifacts. Add the one that matches how you draw:

Artifact Add it when you want
io.github.yuroyami:kitepdf The engine: read, write and edit PDFs, and read EPUBs. Pure Kotlin (stdlib plus KiteImage codecs).
io.github.yuroyami:kitepdf-compose-viewer A Compose PdfView / EpubView, drawn straight into a DrawScope.
io.github.yuroyami:kitepdf-native-renderer Headless page → image through the platform canvas (AWT, CoreGraphics, android.graphics, Canvas2D).
io.github.yuroyami:kitepdf-skia-renderer Headless page → image through Skia / Skiko: one API on JVM, Android, Apple, Linux and web.

Every artifact is at 0.5.0. For a single format, add kitepdf-pdf (the PDF handler alone) or kitepdf-epub (the EPUB reader alone). The kitepdf umbrella contains both. See Show it on screen for each binding in use.

Not using Kotlin Multiplatform?

The same artifact works in a plain Android or JVM project. Add io.github.yuroyami:kitepdf:0.5.0 to your normal dependencies { } block.

What you can do

Everything in this section is pure common code from the kitepdf engine.

Read

val doc = PdfDocument.open(bytes)

doc.pages[0].extractText()      // text, or structured layout with positions
doc.pageCount                   // metadata, outlines, annotations, form fields...

// Encrypted? Pass the password.
val locked = PdfDocument.open(bytes, password = "secret".encodeToByteArray())
require(locked.isAuthenticated)

Text extraction (plain and structured), document metadata and XMP, outlines and bookmarks, annotations, form fields, encryption and permissions, page labels, optional-content layers, attachments and more. See Reading PDFs.

Create and edit

// Fill a form field and save (append-only)
doc.edit().apply {
    setTextFieldValue(doc.formField("Name")!!, "Jane Doe")
}.saveIncremental()

// Truly redact a region (the underlying content is removed, not covered)
doc.edit().apply {
    redactRegion(doc.pages[0], Rectangle(72.0, 700.0, 320.0, 720.0))
}.saveRewritten()

// Build a new PDF from scratch
PdfBuilder()
    .page {
        text(StandardFont.HelveticaBold, 24.0, x = 72.0, y = 720.0, "Invoice")
        setFillRgb(0.9, 0.95, 1.0); rectangle(72.0, 600.0, 200.0, 80.0); fill()
    }
    .build()

Build from scratch with a content DSL, fill forms, stamp and watermark, and redact for real. See Creating PDFs and Editing & redaction.

Show it on screen

The engine is headless. Rendering is the one job that needs a platform, so it lives in separate, optional artifacts.

Compose Multiplatform: kitepdf-compose-viewer

A PDF page is just another composable, drawn straight into a Compose DrawScope.

implementation("io.github.yuroyami:kitepdf-compose-viewer:0.5.0")
val state = rememberPdfViewState(doc)

PdfView(
    state = state,
    layout = PdfLayout.Paged(Orientation.Horizontal),   // or Continuous / SinglePage
    zoomSpec = PdfZoomSpec(maxZoom = 6f),                // pinch, double-tap, pan
    renderSpec = PdfRenderSpec.Rasterized(),            // or Vectorized()
    overlay = { PdfNavigationControls(it, Modifier.align(Alignment.BottomCenter)) },
)
PdfPageIndicator(state)
PdfThumbnailStrip(state)

See the Compose viewer guide.

Headless: kitepdf-native-renderer and kitepdf-skia-renderer

For servers, CI and thumbnails, render a page straight to image bytes with no UI:

implementation("io.github.yuroyami:kitepdf-native-renderer:0.5.0")  // or kitepdf-skia-renderer
val png = AwtPdfRasterizer.encodeToPng(doc.pages[0], scale = 2.0)

See Headless rendering.

Guides

Getting started Open your first PDF and display it, step by step.
Compose viewer PdfView: layouts, zoom, render modes, navigation, export.
Reading PDFs Text, metadata, outlines, annotations, forms, encryption.
Reading EPUBs Reflowable EPUB 2/3: pagination, reader settings, search, typography.
Creating PDFs Build from scratch with the content DSL.
Editing & redaction Fill forms, stamp pages, redact, save.
Headless rendering Page to PNG / Bitmap without a UI.
Recipes Copy-paste patterns for common tasks.
Platform support What runs where, and why.

Status

KitePDF is pre-1.0 and actively developed. Reading, text extraction, metadata, outlines, annotations, forms, encrypted documents, the Compose viewer, headless rendering, editing, redaction, signing preparation, PDF creation, and the supported JBIG2/JPEG 2000 profiles all work today. Signature validation, less common form widgets, advanced color management, broader image-codec profiles, and more document handlers are on the way.

If a PDF renders incorrectly, open an issue with the file attached. Every rendering fix ships with a regression test.