diff android/DWindows.kt @ 2727:bf585f375286

Android: Initial print implementation for Android.... Currently crashes shortly after displaying printer selection dialog. Fixes coming but I wanted to get the bulk of it committed.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Sat, 11 Dec 2021 14:14:26 +0000
parents cacde852e2db
children 34e34d5d56e8
line wrap: on
line diff
--- a/android/DWindows.kt	Sat Dec 11 00:54:01 2021 +0000
+++ b/android/DWindows.kt	Sat Dec 11 14:14:26 2021 +0000
@@ -67,9 +67,9 @@
 import android.content.ContentUris
 import androidx.appcompat.widget.AppCompatSeekBar
 import android.content.DialogInterface
-
-
-
+import android.graphics.pdf.PdfDocument
+import android.print.*
+import android.print.pdf.PrintedPdfDocument
 
 
 // Color Wheel section
@@ -946,6 +946,106 @@
     external fun eventHandlerHTMLChanged(obj1: View, message: Int, URI: String, status: Int)
 }
 
+class DWPrintDocumentAdapter : PrintDocumentAdapter()
+{
+    var context: Context? = null
+    var pages: Int = 0
+    var pdfDocument: PrintedPdfDocument? = null
+    var print: Long = 0
+
+    override fun onLayout(
+        oldAttributes: PrintAttributes?,
+        newAttributes: PrintAttributes,
+        cancellationSignal: CancellationSignal?,
+        callback: LayoutResultCallback,
+        extras: Bundle?
+    ) {
+        // Create a new PdfDocument with the requested page attributes
+        pdfDocument = context?.let { PrintedPdfDocument(it, newAttributes) }
+
+        // Respond to cancellation request
+        if (cancellationSignal?.isCanceled == true) {
+            callback.onLayoutCancelled()
+            return
+        }
+
+        if (pages > 0) {
+            // Return print information to print framework
+            PrintDocumentInfo.Builder("print_output.pdf")
+                .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
+                .setPageCount(pages)
+                .build()
+                .also { info ->
+                    // Content layout reflow is complete
+                    callback.onLayoutFinished(info, true)
+                }
+        } else {
+            // Otherwise report an error to the print framework
+            callback.onLayoutFailed("No pages to print.")
+        }
+    }
+
+    override fun onWrite(
+        pageRanges: Array<out PageRange>,
+        destination: ParcelFileDescriptor,
+        cancellationSignal: CancellationSignal?,
+        callback: WriteResultCallback
+    ) {
+        var writtenPagesArray: Array<PdfDocument.Page> = emptyArray()
+
+        // Iterate over each page of the document,
+        // check if it's in the output range.
+        for (i in 0 until pages) {
+            pdfDocument?.startPage(i)?.also { page ->
+
+                // check for cancellation
+                if (cancellationSignal?.isCanceled == true) {
+                    callback.onWriteCancelled()
+                    pdfDocument?.close()
+                    pdfDocument = null
+                    return
+                }
+
+                // Draw page content for printing
+                var bitmap = Bitmap.createBitmap(page.canvas.width, page.canvas.height, Bitmap.Config.ARGB_8888)
+                // Actual drawing is done in the JNI C code callback to the bitmap
+                eventHandlerPrintDraw(print, bitmap, i, page.canvas.width, page.canvas.height)
+                // Copy from the bitmap canvas our C code drew on to the PDF page canvas
+                val rect = Rect(0, 0, page.canvas.width, page.canvas.height)
+                page.canvas.drawBitmap(bitmap, rect, rect, null)
+
+                // Rendering is complete, so page can be finalized.
+                pdfDocument?.finishPage(page)
+
+                // Add the new page to the array
+                writtenPagesArray += page
+            }
+        }
+
+        // Write PDF document to file
+        try {
+            pdfDocument?.writeTo(FileOutputStream(destination.fileDescriptor))
+        } catch (e: IOException) {
+            callback.onWriteFailed(e.toString())
+            return
+        } finally {
+            pdfDocument?.close()
+            pdfDocument = null
+        }
+        // Signal the print framework the document is complete
+        callback.onWriteFinished(pageRanges)
+    }
+
+    override fun onFinish() {
+        // Notify our C code so it can cleanup
+        eventHandlerPrintFinish(print)
+        super.onFinish()
+    }
+
+    external fun eventHandlerPrintDraw(print: Long, bitmap: Bitmap, page: Int, width: Int, height: Int)
+    external fun eventHandlerPrintFinish(print: Long)
+}
+
 class DWSlider
 @JvmOverloads constructor(context: Context): FrameLayout(context) {
     val slider: SeekBar = SeekBar(context)
@@ -4658,6 +4758,35 @@
         return pixmap
     }
 
+    fun printRun(print: Long, flags: Int, jobname: String, pages: Int, runflags: Int): PrintJob?
+    {
+        var retval: PrintJob? = null
+
+        waitOnUiThread {
+            // Get a PrintManager instance
+            val printManager = this.getSystemService(Context.PRINT_SERVICE) as PrintManager
+            // Setup our print adapter
+            val printAdapter = DWPrintDocumentAdapter()
+            printAdapter.context = this
+            printAdapter.pages = pages
+            printAdapter.print = print
+            // Start a print job, passing in a PrintDocumentAdapter implementation
+            // to handle the generation of a print document
+            retval = printManager.print(jobname, printAdapter, null)
+        }
+        return retval
+    }
+
+    fun printCancel(printjob: PrintJob)
+    {
+        waitOnUiThread {
+            // Get a PrintManager instance
+            val printManager = this.getSystemService(Context.PRINT_SERVICE) as PrintManager
+            // Remove the job we earlier added from the queue
+            printManager.printJobs.remove(printjob)
+        }
+    }
+
     fun pixmapGetDimensions(pixmap: Bitmap): Long
     {
         var dimensions: Long = 0