in printing/src/main/java/com/zachklipp/richtext/ui/printing/ComposePrintAdapter.kt [71:121]
override suspend fun onWrite(
pages: Array<out PageRange>,
destination: ParcelFileDescriptor
): Array<out PageRange> {
var currentPageIndex by mutableStateOf(0)
val pageCountDeferred = CompletableDeferred<Int>()
// Initialize the composition, and reuse the same composition to render all the pages.
composeToPdf(activity, pdfDocument, pageDpi, content = {
// This is the actual composable that will be rendered to the PDF.
// Paged tries to ensure that we don't cut off leaf composables in the middle.
Paged(
pageIndex = currentPageIndex,
pageModifier = pageModifier,
drawBreakpoints = printBreakpoints,
onPageLayout = { pageCountDeferred.complete(it) },
content = content
)
}) {
// We need to know the total page count before we can start iterating. This waits for the
// first composition and frame to commit.
val pageCount = pageCountDeferred.await()
(0 until pageCount).asSequence()
.filter { page -> pages.any { page in it.start..it.end } }
.forEach { pageNumber ->
val page = pdfDocument.startPage(pageNumber)
// Update the Paged to "flip" to the page.
currentPageIndex = pageNumber
// Render the page to the PDF. This function will automatically wait for the next frame to
// finish drawing. It also does not do any IO, so we don't need to switch dispatchers.
composePage(page)
pdfDocument.finishPage(page)
// We're on the main thread, so be a good citizen.
// Also ensures we handle cancellation in a timely fashion.
yield()
}
}
// The PDF currently only exists in memory, so to dump it to the printing system we use a
// background thread.
withContext(ioDispatcher) {
@Suppress("BlockingMethodInNonBlockingContext")
pdfDocument.writeTo(FileOutputStream(destination.fileDescriptor))
}
pdfDocument.close()
return pages
}