Fix pill shape size and orientation

The pill() function was using vertices which were oriented
differently than most other shapes. Also, the final shape was
twice the size it should have been, given the width/height
parameters.

Also, this caused a crash bug due to a floating point error
during morph matching/cutting. The fix was to bound the cut
points to make sure they never go out of range.

Bug: 324057528
Test: unit tests pass, manual tests pass
Change-Id: I5b92b96e5f9fa037ef4f0165c3666e4f4b2d8ecd
diff --git a/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/PolygonMeasure.kt b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/PolygonMeasure.kt
index d8636f1..4af009d 100644
--- a/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/PolygonMeasure.kt
+++ b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/PolygonMeasure.kt
@@ -114,34 +114,33 @@
          * Cut this MeasuredCubic into two MeasuredCubics at the given outline progress value.
          */
         fun cutAtProgress(cutOutlineProgress: Float): Pair<MeasuredCubic, MeasuredCubic> {
+            // Floating point errors further up can cause cutOutlineProgress to land just
+            // slightly outside of the start/end progress for this cubic, so we limit it
+            // to those bounds to avoid further errors later
+            val boundedCutOutlineProgress =
+                cutOutlineProgress.coerceIn(startOutlineProgress, endOutlineProgress)
             val outlineProgressSize = endOutlineProgress - startOutlineProgress
-            val progressFromStart = positiveModulo(cutOutlineProgress - startOutlineProgress, 1f)
-            // progressFromStart should be in the [0 .. outlineProgressSize] range.
-            // If it's not, cap to that range.
-            val mid = if (progressFromStart > (1 + outlineProgressSize) / 2)
-                0f
-            else
-                progressFromStart.coerceAtMost(outlineProgressSize)
+            val progressFromStart = boundedCutOutlineProgress - startOutlineProgress
 
             // Note that in earlier parts of the computation, we have empty MeasuredCubics (cubics
             // with progressSize == 0f), but those cubics are filtered out before this method is
             // called.
-            val relativeMidProgress = mid / outlineProgressSize
-            val t = measurer.findCubicCutPoint(cubic, relativeMidProgress * measuredSize)
+            val relativeProgress = progressFromStart / outlineProgressSize
+            val t = measurer.findCubicCutPoint(cubic, relativeProgress * measuredSize)
             require(t in 0f..1f) {
                 "Cubic cut point is expected to be between 0 and 1"
             }
 
             debugLog(LOG_TAG) {
-                "cutAtProgress: progress = $cutOutlineProgress / " +
+                "cutAtProgress: progress = $boundedCutOutlineProgress / " +
                     "this = [$startOutlineProgress .. $endOutlineProgress] / " +
-                    "pp = $mid / rp = $relativeMidProgress / t = $t"
+                    "ps = $progressFromStart / rp = $relativeProgress / t = $t"
             }
 
             // c1/c2 are the two new cubics, then we return MeasuredCubics created from them
             val (c1, c2) = cubic.split(t)
-            return MeasuredCubic(c1, startOutlineProgress, cutOutlineProgress) to
-                MeasuredCubic(c2, cutOutlineProgress, endOutlineProgress)
+            return MeasuredCubic(c1, startOutlineProgress, boundedCutOutlineProgress) to
+                MeasuredCubic(c2, boundedCutOutlineProgress, endOutlineProgress)
         }
 
         override fun toString(): String {
diff --git a/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Shapes.kt b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Shapes.kt
index 44eebdc..a7ebd90 100644
--- a/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Shapes.kt
+++ b/graphics/graphics-shapes/src/commonMain/kotlin/androidx/graphics/shapes/Shapes.kt
@@ -189,14 +189,16 @@
         throw IllegalArgumentException("Pill shapes must have positive width and height")
     }
 
+    val wHalf = width / 2
+    val hHalf = height / 2
     return RoundedPolygon(
         vertices = floatArrayOf(
-            -width + centerX, -height + centerY,
-            width + centerX, -height + centerY,
-            width + centerX, height + centerY,
-            -width + centerX, height + centerY,
+            wHalf + centerX, hHalf + centerY,
+            -wHalf + centerX, hHalf + centerY,
+            -wHalf + centerX, -hHalf + centerY,
+            wHalf + centerX, -hHalf + centerY,
         ),
-        rounding = CornerRounding(min(width, height), smoothing),
+        rounding = CornerRounding(min(wHalf, hHalf), smoothing),
         centerX = centerX, centerY = centerY
     )
 }