Move SSD review paint helpers to typed Kotlin

ober

e13f163b5ef6a5f1ffd88d93cdc238699140c8dd

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 097e7eb..99ed1ae 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -3699,8 +3699,17 @@
                 manualGroupLabel manualCellCount editedGroupCount
                 clampPageIndex shiftPageIndex displayGroupCanvasLabel
                 dropdownHeight dialogPageNumber nullableLowercaseOrEmpty
-                selectModeStatus selectionResultStatus groupStrokeColor)
+                selectModeStatus selectionResultStatus
+                reviewPrimaryColor reviewWhiteColor reviewLabelTextColor
+                reviewLabelBackgroundColor reviewCanvasBackgroundColor
+                groupStrokeColor selectedGroupFillColor
+                ssdAreaFillColor ssdAreaStrokeColor dragFillColor
+                cellStrokeWidth groupBaseStrokeWidth groupStrokeWidth
+                ssdAreaStrokeWidth dragStrokeWidth dragAnchorStrokeWidth
+                dragAnchorArmLength dragAnchorRadius touchPointerStrokeWidth
+                touchPointerOuterRadius touchPointerInnerRadius)
         (type Int32)
+        (type Float32)
         (extern (androidColorRgb (red : Int32)
                                  (green : Int32)
                                  (blue : Int32)) : Int32
@@ -3867,14 +3876,56 @@
                   (int32->string matchingCount)
                   " detected boxes"))
               "Shrank rough selection to SSD boxes")))
+        (def (reviewPrimaryColor) : Int32
+          (androidColorRgb (int32 37) (int32 99) (int32 235)))
+        (def (reviewWhiteColor) : Int32
+          (androidColorRgb (int32 255) (int32 255) (int32 255)))
+        (def (reviewLabelTextColor) : Int32
+          (androidColorRgb (int32 30) (int32 64) (int32 175)))
+        (def (reviewLabelBackgroundColor) : Int32
+          (androidColorArgb (int32 220) (int32 255) (int32 255) (int32 255)))
+        (def (reviewCanvasBackgroundColor) : Int32
+          (androidColorRgb (int32 248) (int32 250) (int32 252)))
         (def (groupStrokeColor (selected : Bool) (status : String)) : Int32
           (if selected
-            (androidColorRgb (int32 37) (int32 99) (int32 235))
+            (reviewPrimaryColor)
             (if (or (equal? status "approved") (equal? status "reviewed"))
               (androidColorRgb (int32 5) (int32 150) (int32 105))
               (if (equal? status "rejected")
                 (androidColorRgb (int32 185) (int32 28) (int32 28))
                 (androidColorArgb (int32 155) (int32 245) (int32 158) (int32 11))))))
+        (def (selectedGroupFillColor) : Int32
+          (androidColorArgb (int32 45) (int32 37) (int32 99) (int32 235)))
+        (def (ssdAreaFillColor) : Int32
+          (androidColorArgb (int32 18) (int32 14) (int32 165) (int32 233)))
+        (def (ssdAreaStrokeColor) : Int32
+          (androidColorRgb (int32 14) (int32 165) (int32 233)))
+        (def (dragFillColor) : Int32
+          (androidColorArgb (int32 38) (int32 37) (int32 99) (int32 235)))
+        (def (scaledPixels (pixels : Float32) (scale : Float32)) : Float32
+          (/ pixels scale))
+        (def (cellStrokeWidth (scale : Float32)) : Float32
+          (scaledPixels (float32 2.0) scale))
+        (def (groupBaseStrokeWidth (scale : Float32)) : Float32
+          (scaledPixels (float32 4.0) scale))
+        (def (groupStrokeWidth (selected : Bool) (scale : Float32)) : Float32
+          (scaledPixels (if selected (float32 7.0) (float32 3.0)) scale))
+        (def (ssdAreaStrokeWidth (scale : Float32)) : Float32
+          (scaledPixels (float32 6.0) scale))
+        (def (dragStrokeWidth (scale : Float32)) : Float32
+          (scaledPixels (float32 3.0) scale))
+        (def (dragAnchorStrokeWidth (scale : Float32)) : Float32
+          (scaledPixels (float32 4.0) scale))
+        (def (dragAnchorArmLength (scale : Float32)) : Float32
+          (scaledPixels (float32 14.0) scale))
+        (def (dragAnchorRadius (scale : Float32)) : Float32
+          (scaledPixels (float32 10.0) scale))
+        (def (touchPointerStrokeWidth) : Float32
+          (float32 3.0))
+        (def (touchPointerOuterRadius) : Float32
+          (float32 9.0))
+        (def (touchPointerInnerRadius) : Float32
+          (float32 4.0))
         (def (editedGroupCount (count : (Nullable Int32))
                                (fallback : Int32)) : Int32
           (if (nullable-null? count)
@@ -6664,13 +6715,13 @@
        "    private val inverse = Matrix()"
        "    private val paint = Paint(Paint.ANTI_ALIAS_FLAG)"
        "    private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {"
-       "        color = Color.rgb(30, 64, 175)"
+       "        color = reviewLabelTextColor()"
        "        textSize = 28f"
        "        style = Paint.Style.FILL"
        "        textAlign = Paint.Align.CENTER"
        "    }"
 	       "    private val labelBgPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {"
-	       "        color = Color.argb(220, 255, 255, 255)"
+	       "        color = reviewLabelBackgroundColor()"
 	       "        style = Paint.Style.FILL"
 	       "    }"
 	       "    private val density = context.resources.displayMetrics.density"
@@ -6708,7 +6759,7 @@
        ""
        "    override fun onDraw(canvas: Canvas) {"
        "        super.onDraw(canvas)"
-       "        canvas.drawColor(Color.rgb(248, 250, 252))"
+       "        canvas.drawColor(reviewCanvasBackgroundColor())"
        "        val img = bitmap ?: return"
        "        canvas.drawBitmap(img, matrix, null)"
        "        val saved = canvas.save()"
@@ -6878,10 +6929,10 @@
        "    private fun drawCells(canvas: Canvas) {"
        "        val sess = session ?: return"
        "        paint.style = Paint.Style.STROKE"
-       "        paint.strokeWidth = 2f / scale"
+       "        paint.strokeWidth = cellStrokeWidth(scale)"
        "        for (cell in sess.cells) {"
        "            if (ssdSessionGroupContainsCellId(sess, selectedGroupId, cell.id)) {"
-       "                paint.color = Color.rgb(37, 99, 235)"
+       "                paint.color = reviewPrimaryColor()"
        "                canvas.drawRect(cell.x, cell.y, cell.x + cell.w, cell.y + cell.h, paint)"
        "            }"
        "        }"
@@ -6890,15 +6941,15 @@
        "    private fun drawGroups(canvas: Canvas) {"
        "        val sess = session ?: return"
        "        paint.style = Paint.Style.STROKE"
-       "        paint.strokeWidth = 4f / scale"
+       "        paint.strokeWidth = groupBaseStrokeWidth(scale)"
        "        for (group in sess.groups) {"
        "            val selected = group.id == selectedGroupId"
        "            paint.color = groupStrokeColor(selected, group.status)"
-       "            paint.strokeWidth = if (selected) 7f / scale else 3f / scale"
+       "            paint.strokeWidth = groupStrokeWidth(selected, scale)"
        "            canvas.drawRect(group.bbox[0], group.bbox[1], group.bbox[2], group.bbox[3], paint)"
        "            if (selected) {"
        "                paint.style = Paint.Style.FILL"
-       "                paint.color = Color.argb(45, 37, 99, 235)"
+       "                paint.color = selectedGroupFillColor()"
        "                canvas.drawRect(group.bbox[0], group.bbox[1], group.bbox[2], group.bbox[3], paint)"
        "                paint.style = Paint.Style.STROKE"
        "            }"
@@ -6908,11 +6959,11 @@
 	       "    private fun drawSsdArea(canvas: Canvas) {"
 	       "        val area = ssdArea ?: return"
 	       "        paint.style = Paint.Style.FILL"
-	       "        paint.color = Color.argb(18, 14, 165, 233)"
+	       "        paint.color = ssdAreaFillColor()"
 	       "        canvas.drawRect(area[0], area[1], area[2], area[3], paint)"
 	       "        paint.style = Paint.Style.STROKE"
-	       "        paint.strokeWidth = 6f / scale"
-	       "        paint.color = Color.rgb(14, 165, 233)"
+	       "        paint.strokeWidth = ssdAreaStrokeWidth(scale)"
+	       "        paint.color = ssdAreaStrokeColor()"
 	       "        canvas.drawRect(area[0], area[1], area[2], area[3], paint)"
 	       "    }"
 	       ""
@@ -6952,16 +7003,17 @@
        "        val end = dragEnd ?: return"
        "        val rect = normalizeRect(floatArrayOf(start[0], start[1], end[0], end[1]))"
        "        paint.style = Paint.Style.FILL"
-       "        paint.color = Color.argb(38, 37, 99, 235)"
+       "        paint.color = dragFillColor()"
        "        canvas.drawRect(rect[0], rect[1], rect[2], rect[3], paint)"
        "        paint.style = Paint.Style.STROKE"
-	       "        paint.strokeWidth = 3f / scale"
-	       "        paint.color = Color.rgb(37, 99, 235)"
+	       "        paint.strokeWidth = dragStrokeWidth(scale)"
+	       "        paint.color = reviewPrimaryColor()"
 	       "        canvas.drawRect(rect[0], rect[1], rect[2], rect[3], paint)"
-	       "        paint.strokeWidth = 4f / scale"
-	       "        canvas.drawLine(start[0] - 14f / scale, start[1], start[0] + 14f / scale, start[1], paint)"
-	       "        canvas.drawLine(start[0], start[1] - 14f / scale, start[0], start[1] + 14f / scale, paint)"
-	       "        canvas.drawCircle(start[0], start[1], 10f / scale, paint)"
+	       "        paint.strokeWidth = dragAnchorStrokeWidth(scale)"
+	       "        val arm = dragAnchorArmLength(scale)"
+	       "        canvas.drawLine(start[0] - arm, start[1], start[0] + arm, start[1], paint)"
+	       "        canvas.drawLine(start[0], start[1] - arm, start[0], start[1] + arm, paint)"
+	       "        canvas.drawCircle(start[0], start[1], dragAnchorRadius(scale), paint)"
 	       "    }"
 	       ""
 	       "    private fun drawTouchPointer(canvas: Canvas) {"
@@ -6969,14 +7021,14 @@
 	       "        val anchor = dragEnd ?: dragStart ?: return"
 	       "        val viewAnchor = imageToView(anchor[0], anchor[1])"
 	       "        paint.style = Paint.Style.STROKE"
-	       "        paint.strokeWidth = 3f"
-	       "        paint.color = Color.rgb(37, 99, 235)"
+	       "        paint.strokeWidth = touchPointerStrokeWidth()"
+	       "        paint.color = reviewPrimaryColor()"
 	       "        canvas.drawLine(pointerX, pointerY, viewAnchor[0], viewAnchor[1], paint)"
 	       "        paint.style = Paint.Style.FILL"
-	       "        paint.color = Color.rgb(37, 99, 235)"
-	       "        canvas.drawCircle(viewAnchor[0], viewAnchor[1], 9f, paint)"
-	       "        paint.color = Color.WHITE"
-	       "        canvas.drawCircle(viewAnchor[0], viewAnchor[1], 4f, paint)"
+	       "        paint.color = reviewPrimaryColor()"
+	       "        canvas.drawCircle(viewAnchor[0], viewAnchor[1], touchPointerOuterRadius(), paint)"
+	       "        paint.color = reviewWhiteColor()"
+	       "        canvas.drawCircle(viewAnchor[0], viewAnchor[1], touchPointerInnerRadius(), paint)"
 	       "    }"
 	       ""
 	       "    private fun updateMatrix() {"