Move SSD native bridge checks to typed Kotlin

ober

185b9c7a097de0f56d506af36cf352e2dae24117

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index a45f041..fc5f788 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -4024,7 +4024,7 @@
       (kotlin-imports (org json JSONArray) (org json JSONObject))
       (typed-library (com sfb ssdreview)
         (export nativeDetectionCellsFromJson nativeDetectionGroupsFromJson
-                nativeDetectionRootOk nativeDetectionRootError
+                nativeDetectionRootOk nativeDetectionRootFailed nativeDetectionRootError
                 nativeDetectionFromJsonRoot)
         (type JSONArray)
         (type JSONObject)
@@ -4044,6 +4044,8 @@
             (string-pad-start (int32->string (+ index (int32 1))) (int32 4) #\0)))
         (def (nativeDetectionRootOk (root : JSONObject)) : Bool
           (json-object-opt-bool-default root "ok" #t))
+        (def (nativeDetectionRootFailed (root : JSONObject)) : Bool
+          (not (nativeDetectionRootOk root)))
         (def (nativeDetectionRootError (root : JSONObject)) : String
           (json-object-opt-string-default root "error" "native detector failed"))
         (def (nativeDetectionCellsFromJson (raw : (Nullable JSONArray))) : (MutableList SsdCell)
@@ -7392,6 +7394,7 @@
       (kotlin-imports (android graphics Bitmap))
       (typed-library (com sfb ssdreview)
         (export bitmapPixelWidth bitmapPixelHeight bitmapHasPixels
+                bitmapReadyForNativeDetection
                 bitmapPixels bitmapWindowPixels bitmapToRgba)
         (type Bitmap)
         (type Int32)
@@ -7417,6 +7420,8 @@
         (def (bitmapHasPixels (bitmap : Bitmap)) : Bool
           (and (> (bitmapPixelWidth bitmap) (int32 0))
                (> (bitmapPixelHeight bitmap) (int32 0))))
+        (def (bitmapReadyForNativeDetection (loaded : Bool) (bitmap : Bitmap)) : Bool
+          (and loaded (bitmapHasPixels bitmap)))
         (def (bitmapWindowPixels (bitmap : Bitmap)
                                  (x : Int32)
                                  (y : Int32)
@@ -7594,7 +7599,7 @@
        "    fun loadErrorMessage(): String = loadError?.message ?: \"\""
        ""
        "    fun detect(bitmap: Bitmap): NativeDetection? {"
-       "        if (!loaded || !bitmapHasPixels(bitmap)) return null"
+       "        if (!bitmapReadyForNativeDetection(loaded, bitmap)) return null"
        "        val rgba = bitmapToRgba(bitmap)"
        "        val jsonText = try {"
        "            nativeDetectRgbaJson(bitmapPixelWidth(bitmap), bitmapPixelHeight(bitmap), rgba)"
@@ -7603,7 +7608,7 @@
        "            return null"
        "        }"
        "        val root = try { jsonObjectFromText(jsonText) } catch (_: Exception) { return null }"
-       "        if (!nativeDetectionRootOk(root)) {"
+       "        if (nativeDetectionRootFailed(root)) {"
        "            loadError = IllegalStateException(nativeDetectionRootError(root))"
        "            return null"
        "        }"