Generate SSD PDF rendering from typed Jerboa

ober

32db0a41c36d71827f33ff5108e2234efbb95460

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index f22cff2..ad03588 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -4774,9 +4774,14 @@
                       (android content DialogInterface)
                       (android content pm PackageManager)
                       (android graphics Bitmap)
+                      (android graphics Bitmap Config)
                       (android content Intent)
                       (android database Cursor)
+                      (android graphics Matrix)
+                      (android graphics Rect)
                       (android graphics drawable GradientDrawable)
+                      (android graphics pdf PdfRenderer)
+                      (android graphics pdf PdfRenderer Page)
                       (android net Uri)
                       (android os Build)
                       (android os Environment)
@@ -4928,6 +4933,7 @@
                 mainActivityRestoreLastPdf mainActivityPersistCurrentPdfState
                 mainActivityRestoredViewportFor
                 mainActivityDisplayName mainActivityLoadPdf
+                mainActivityPdfPageCount mainActivityRenderPdfPage
                 mainActivityInitialPickerUri mainActivityOpenPdf
                 mainActivityOpenAnyPdf mainActivityChooseSsdPdfFolder
                 mainActivityRequestDownloadAccess
@@ -5043,8 +5049,13 @@
         (type FloatArray)
         (type Bitmap)
         (type Char)
+        (type Config)
         (type Exception)
         (type Environment)
+        (type Matrix)
+        (type Page)
+        (type PdfRenderer)
+        (type Rect)
         (type Runnable)
         (type Thread)
         (type AlertDialog)
@@ -5171,12 +5182,67 @@
                   (resolver : ContentResolver)
                   (uri : Uri)) : (Nullable OutputStream)
           (kotlin-member-call openOutputStream))
+        (extern (contentResolverOpenFileDescriptorRaw
+                  (resolver : ContentResolver)
+                  (uri : Uri)
+                  (mode : String)) : (Nullable ParcelFileDescriptor)
+          (kotlin-member-call openFileDescriptor))
         (extern (sha1HexRaw (input : InputStream)) : String
           (kotlin-call sha1Hex))
         (extern (uiInputStreamCloseRaw (input : InputStream)) : Unit
           (kotlin-member-call close))
         (extern (uiOutputStreamCloseRaw (output : OutputStream)) : Unit
           (kotlin-member-call close))
+        (extern (pdfRendererFromDescriptorRaw
+                  (descriptor : ParcelFileDescriptor)) : PdfRenderer
+          (kotlin-call PdfRenderer))
+        (extern (pdfRendererPageCountRaw
+                  (renderer : PdfRenderer)) : Int32
+          (kotlin-member-get pageCount))
+        (extern (pdfRendererOpenPageRaw
+                  (renderer : PdfRenderer)
+                  (index : Int32)) : Page
+          (kotlin-member-call openPage))
+        (extern (pdfRendererCloseRaw
+                  (renderer : PdfRenderer)) : Unit
+          (kotlin-member-call close))
+        (extern (pdfPageWidthRaw (page : Page)) : Int32
+          (kotlin-member-get width))
+        (extern (pdfPageHeightRaw (page : Page)) : Int32
+          (kotlin-member-get height))
+        (extern (pdfPageRenderRaw
+                  (page : Page)
+                  (bitmap : Bitmap)
+                  (destClip : (Nullable Rect))
+                  (transform : Matrix)
+                  (mode : Int32)) : Unit
+          (kotlin-member-call render))
+        (extern (pdfPageCloseRaw (page : Page)) : Unit
+          (kotlin-member-call close))
+        (extern (pdfPageRenderModeForDisplay) : Int32
+          (kotlin-value Page RENDER_MODE_FOR_DISPLAY))
+        (extern (bitmapConfigArgb8888) : Config
+          (kotlin-value Bitmap Config ARGB_8888))
+        (extern (bitmapCreateBitmapRaw
+                  (width : Int32)
+                  (height : Int32)
+                  (config : Config)) : Bitmap
+          (kotlin-call Bitmap createBitmap))
+        (extern (bitmapEraseColorRaw
+                  (bitmap : Bitmap)
+                  (color : Int32)) : Unit
+          (kotlin-member-call eraseColor))
+        (extern (matrixSetScaleRaw
+                  (matrix : Matrix)
+                  (scaleX : Float32)
+                  (scaleY : Float32)) : Unit
+          (kotlin-member-call setScale))
+        (extern (float32ToInt32Raw
+                  (value : Float32)) : Int32
+          (kotlin-member-call toInt))
+        (extern (mainActivityIllegalArgumentExceptionRaw
+                  (message : String)) : Exception
+          (kotlin-call IllegalArgumentException))
         (extern (uuidRandomRaw) : UUID
           (kotlin-call UUID randomUUID))
         (extern (uuidToStringRaw (uuid : UUID)) : String
@@ -5847,15 +5913,6 @@
         (extern (mainActivityReviewViewRaw
                   (activity : MainActivity)) : SsdReviewView
           (kotlin-member-get reviewView))
-        (extern (mainActivityRenderPdfPageRaw
-                  (activity : MainActivity)
-                  (uri : Uri)
-                  (page : Int32)) : Bitmap
-          (kotlin-member-call renderPdfPage))
-        (extern (mainActivityPdfPageCountRaw
-                  (activity : MainActivity)
-                  (uri : Uri)) : Int32
-          (kotlin-member-call pdfPageCount))
         (extern (mainActivityCurrentSessionRaw
                   (activity : MainActivity)) : (Nullable SsdSession)
           (kotlin-member-get currentSession))
@@ -8632,6 +8689,72 @@
               uri
               initialPageIndex
               restoring)))
+        (def (mainActivityOpenPdfRenderer
+               (activity : MainActivity)
+               (uri : Uri)) : PdfRenderer
+          (let ((descriptor
+                  (contentResolverOpenFileDescriptorRaw
+                    (mainActivityContentResolverRaw activity)
+                    uri
+                    "r")))
+            (if (parcelFileDescriptorPresent descriptor)
+              (pdfRendererFromDescriptorRaw (nullable-get descriptor))
+              (throw
+                (mainActivityIllegalArgumentExceptionRaw
+                  "Unable to open PDF")
+                PdfRenderer))))
+        (def (mainActivityPdfPageCount
+               (activity : MainActivity)
+               (uri : Uri)) : Int32
+          (let ((renderer
+                  (mainActivityOpenPdfRenderer activity uri)))
+            (try-finally
+              (pdfRendererPageCountRaw renderer)
+              (pdfRendererCloseRaw renderer))))
+        (def (mainActivityRenderPageWithRenderer
+               (renderer : PdfRenderer)
+               (index : Int32)
+               (dpi : Int32)) : Bitmap
+          (let ((page
+                  (pdfRendererOpenPageRaw renderer index)))
+            (try-finally
+              (let ((scale
+                      (/ (float32 dpi) (float32 72.0)))
+                    (matrix (new Matrix)))
+                (let ((bitmap
+                        (bitmapCreateBitmapRaw
+                          (float32ToInt32Raw
+                            (* (float32 (pdfPageWidthRaw page))
+                               scale))
+                          (float32ToInt32Raw
+                            (* (float32 (pdfPageHeightRaw page))
+                               scale))
+                          (bitmapConfigArgb8888))))
+                  (begin
+                    (bitmapEraseColorRaw
+                      bitmap
+                      (reviewWhiteColor))
+                    (matrixSetScaleRaw matrix scale scale)
+                    (pdfPageRenderRaw
+                      page
+                      bitmap
+                      (nullable-none Rect)
+                      matrix
+                      (pdfPageRenderModeForDisplay))
+                    bitmap)))
+              (pdfPageCloseRaw page))))
+        (def (mainActivityRenderPdfPage
+               (activity : MainActivity)
+               (uri : Uri)
+               (index : Int32)) : Bitmap
+          (let ((renderer
+                  (mainActivityOpenPdfRenderer activity uri)))
+            (try-finally
+              (mainActivityRenderPageWithRenderer
+                renderer
+                index
+                (mainActivityDpiValue))
+              (pdfRendererCloseRaw renderer))))
         (def (mainActivityRestoreLastPdf
                (activity : MainActivity)) : Bool
           (let ((preferences
@@ -9598,7 +9721,7 @@
             (lambda ()
               (try
                 (let ((bitmap
-                        (mainActivityRenderPdfPageRaw
+                        (mainActivityRenderPdfPage
                           activity
                           uri
                           renderPageIndex)))
@@ -9710,7 +9833,7 @@
                             (contentResolverOpenInputStreamRaw
                               (mainActivityContentResolverRaw activity)
                               uri))))
-                    (let ((count (mainActivityPdfPageCountRaw activity uri)))
+                    (let ((count (mainActivityPdfPageCount activity uri)))
                       (mainActivityRunOnUiThreadRaw
                         activity
                         (lambda ()
@@ -12328,33 +12451,6 @@
        "            }"
        "            }"
        "    }"
-	       ""
-	       "    internal fun pdfPageCount(uri: Uri): Int {"
-       "        openPdfRenderer(uri).use { renderer -> return renderer.pageCount }"
-       "    }"
-       ""
-       "    internal fun renderPdfPage(uri: Uri, index: Int): Bitmap {"
-       "        openPdfRenderer(uri).use { renderer ->"
-       "            renderer.openPage(index).use { page ->"
-       "                val scale = DPI / 72f"
-       "                val bitmap = Bitmap.createBitmap("
-       "                    (page.width * scale).toInt(),"
-       "                    (page.height * scale).toInt(),"
-       "                    Bitmap.Config.ARGB_8888"
-       "                )"
-       "                bitmap.eraseColor(reviewWhiteColor())"
-       "                page.render(bitmap, null, Matrix().apply { setScale(scale, scale) }, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)"
-       "                return bitmap"
-       "            }"
-       "        }"
-       "    }"
-       ""
-       "    private fun openPdfRenderer(uri: Uri): PdfRenderer {"
-       "        val descriptor = contentResolver.openFileDescriptor(uri, \"r\")"
-       "        if (!parcelFileDescriptorPresent(descriptor)) throw IllegalArgumentException(\"Unable to open PDF\")"
-       "        val pfd: ParcelFileDescriptor = checkNotNull(descriptor)"
-       "        return PdfRenderer(pfd)"
-       "    }"
        ""
        "    private fun installClientCrashLogger() {"
        "        if (clientCrashLoggerInstalled) return"