Single Page PDFs
The simplest way to create a PDF – call renderToPdf with a composable lambda.
renderToPdf now auto-paginates by default. If your content overflows a single page, it automatically flows to additional pages. To force single-page behavior (clip overflow), pass pagination = PdfPagination.SINGLE_PAGE.
Basic usage
val pdfBytes = renderToPdf {
Column(Modifier.fillMaxSize().padding(32.dp)) {
Text("Hello, PDF!", fontSize = 28.sp)
}
}
File("output.pdf").writeBytes(pdfBytes)
This renders an A4 page in vector mode with the bundled Inter font. If the content fits on one page, you get a single-page PDF.
All parameters
val pdfBytes = renderToPdf(
config = PdfPageConfig.A4, // Page size and margins
density = Density(2f), // Pixel resolution for layout
mode = RenderMode.VECTOR, // Vector or raster rendering
defaultFontFamily = InterFontFamily, // Font family for text
pagination = PdfPagination.AUTO, // Auto-paginate or single page
) {
// Your composable content
}
| Parameter | Type | Default | Description |
|---|---|---|---|
config | PdfPageConfig | PdfPageConfig.A4 | Page dimensions and margins |
density | Density | Density(2f) | Pixel density for Compose layout. Higher = better anti-aliasing, more memory |
mode | RenderMode | RenderMode.VECTOR | VECTOR for selectable text, RASTER for pixel-perfect |
defaultFontFamily | FontFamily? | InterFontFamily | Default font. Pass null for system fonts |
pagination | PdfPagination | PdfPagination.AUTO | AUTO splits content across pages. SINGLE_PAGE clips to one page |
content | @Composable () -> Unit | – | The content to render |
Returns: ByteArray containing a valid PDF document.
Examples
With page configuration
val pdf = renderToPdf(config = PdfPageConfig.LetterWithMargins) {
Column(Modifier.fillMaxSize()) {
Text("US Letter with 1-inch margins", fontSize = 20.sp)
}
}
With system fonts
val pdf = renderToPdf(defaultFontFamily = null) {
Text("Using system fonts")
}
Raster mode with higher density
val pdf = renderToPdf(
mode = RenderMode.RASTER,
density = Density(3f),
) {
Text("Pixel-perfect rendering")
}
Saving and streaming
renderToPdf returns a ByteArray, or you can stream directly to an OutputStream:
// ByteArray -- simple, works everywhere
val pdfBytes = renderToPdf { MyContent() }
File("report.pdf").writeBytes(pdfBytes)
// OutputStream -- avoids extra copy for large PDFs
FileOutputStream("report.pdf").use { out ->
renderToPdf(out) { MyContent() }
}
// Ktor -- stream directly to the HTTP response
call.respondOutputStream(ContentType.Application.Pdf) {
renderToPdf(this) { MyContent() }
}
See Server-side & Ktor for more integration patterns.
renderToPdf is not thread-safe. If you need to generate PDFs concurrently, serialize calls with a mutex or single-threaded dispatcher.
See also
- API Reference: renderToPdf – Full function signature and documentation
- Page Configuration – All page sizes and margin options
- Vector vs Raster – Choosing a rendering mode