[canvaskit] expose all 8 radii for RRect

Change-Id: I537bda18a588c9db5b0f3ea17203bb1daab0feb5
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/240689
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Kevin Lubick <kjlubick@google.com>
diff --git a/modules/canvaskit/CHANGELOG.md b/modules/canvaskit/CHANGELOG.md
index 7047b14..31b3eef 100644
--- a/modules/canvaskit/CHANGELOG.md
+++ b/modules/canvaskit/CHANGELOG.md
@@ -9,7 +9,8 @@
 ### Added
  - `SkCanvas.drawCircle()`, `SkCanvas.getSaveCount()`
  - `SkPath.offset()`, `SkPath.drawOval`
- - `SkRRect` support (`SkCanvas.drawRRect`, `SkCanvas.drawDRRect`)
+ - `SkRRect` support (`SkCanvas.drawRRect`, `SkCanvas.drawDRRect`, `CanvasKit.RRectXY`).
+   Advanced users can specify the 8 individual radii, if needed.
 
 ### Changed
  - `MakeSkVertices` uses a builder to save a copy.
diff --git a/modules/canvaskit/canvaskit_bindings.cpp b/modules/canvaskit/canvaskit_bindings.cpp
index f610fc6..7e7d881 100644
--- a/modules/canvaskit/canvaskit_bindings.cpp
+++ b/modules/canvaskit/canvaskit_bindings.cpp
@@ -558,12 +558,23 @@
 // SimpleRRect is simpler than passing a (complex) SkRRect over the wire to JS.
 struct SimpleRRect {
     SkRect rect;
-    SkScalar rx;
-    SkScalar ry;
+
+    SkScalar rx1;
+    SkScalar ry1;
+    SkScalar rx2;
+    SkScalar ry2;
+    SkScalar rx3;
+    SkScalar ry3;
+    SkScalar rx4;
+    SkScalar ry4;
 };
 
 SkRRect toRRect(const SimpleRRect& r) {
-    return SkRRect::MakeRectXY(r.rect, r.rx, r.ry);
+    SkVector fRadii[4] = {{r.rx1, r.ry1}, {r.rx2, r.ry2},
+                          {r.rx3, r.ry3}, {r.rx4, r.ry4}};
+    SkRRect rr;
+    rr.setRectRadii(r.rect, fRadii);
+    return rr;
 }
 
 // These objects have private destructors / delete methods - I don't think
@@ -1310,8 +1321,14 @@
 
     value_object<SimpleRRect>("SkRRect")
         .field("rect", &SimpleRRect::rect)
-        .field("rx",   &SimpleRRect::rx)
-        .field("ry",   &SimpleRRect::ry);
+        .field("rx1",  &SimpleRRect::rx1)
+        .field("ry1",  &SimpleRRect::ry1)
+        .field("rx2",  &SimpleRRect::rx2)
+        .field("ry2",  &SimpleRRect::ry2)
+        .field("rx3",  &SimpleRRect::rx3)
+        .field("ry3",  &SimpleRRect::ry3)
+        .field("rx4",  &SimpleRRect::rx4)
+        .field("ry4",  &SimpleRRect::ry4);
 
     value_object<SkIRect>("SkIRect")
         .field("fLeft",   &SkIRect::fLeft)
diff --git a/modules/canvaskit/externs.js b/modules/canvaskit/externs.js
index 24ce99f..0ef36e7 100644
--- a/modules/canvaskit/externs.js
+++ b/modules/canvaskit/externs.js
@@ -29,6 +29,8 @@
 	LTRBRect: function() {},
 	/** @return {CanvasKit.SkRect} */
 	XYWHRect: function() {},
+	/** @return {CanvasKit.SkRRect} */
+	RRectXY: function() {},
 	/** @return {ImageData} */
 	ImageData: function() {},
 
@@ -285,8 +287,14 @@
 
 	SkRRect: {
 		rect: {},
-		rx: {},
-		ry: {},
+		rx1: {},
+		ry1: {},
+		rx2: {},
+		ry2: {},
+		rx3: {},
+		ry3: {},
+		rx4: {},
+		ry4: {},
 	},
 
 	SkSurface: {
diff --git a/modules/canvaskit/interface.js b/modules/canvaskit/interface.js
index 98db395..d0e8d19 100644
--- a/modules/canvaskit/interface.js
+++ b/modules/canvaskit/interface.js
@@ -793,6 +793,22 @@
   };
 }
 
+// RRectXY returns an RRect with the given rect and a radiusX and radiusY for
+// all 4 corners.
+CanvasKit.RRectXY = function(rect, rx, ry) {
+  return {
+    rect: rect,
+    rx1: rx,
+    ry1: ry,
+    rx2: rx,
+    ry2: ry,
+    rx3: rx,
+    ry3: ry,
+    rx4: rx,
+    ry4: ry,
+  };
+}
+
 CanvasKit.MakePathFromCmds = function(cmds) {
   var ptrLen = loadCmdsTypedArray(cmds);
   var path = CanvasKit._MakePathFromCmds(ptrLen[0], ptrLen[1]);
diff --git a/modules/canvaskit/tests/canvas.spec.js b/modules/canvaskit/tests/canvas.spec.js
index e7054c0..b4f4cc9 100644
--- a/modules/canvaskit/tests/canvas.spec.js
+++ b/modules/canvaskit/tests/canvas.spec.js
@@ -162,7 +162,47 @@
         }));
     });
 
-    it('draws rrects', function(done) {
+    it('draws simple rrects', function(done) {
+        LoadCanvasKit.then(catchException(done, () => {
+            const surface = CanvasKit.MakeCanvasSurface('test');
+            expect(surface).toBeTruthy('Could not make surface')
+            if (!surface) {
+                done();
+                return;
+            }
+            const canvas = surface.getCanvas();
+            const path = starPath(CanvasKit);
+
+            const paint = new CanvasKit.SkPaint();
+
+            paint.setStyle(CanvasKit.PaintStyle.Stroke);
+            paint.setStrokeWidth(3.0);
+            paint.setAntiAlias(true);
+            paint.setColor(CanvasKit.BLACK);
+
+            canvas.clear(CanvasKit.WHITE);
+
+            canvas.drawRRect(CanvasKit.RRectXY(
+                CanvasKit.LTRBRect(10, 10, 50, 50), 5, 10), paint);
+
+            canvas.drawRRect(CanvasKit.RRectXY(
+                CanvasKit.LTRBRect(60, 10, 110, 50), 10, 5), paint);
+
+            canvas.drawRRect(CanvasKit.RRectXY(
+                CanvasKit.LTRBRect(10, 60, 210, 260), 0, 30), paint);
+
+            canvas.drawRRect(CanvasKit.RRectXY(
+                CanvasKit.LTRBRect(50, 90, 160, 210), 30, 30), paint);
+
+            surface.flush();
+            path.delete();
+            paint.delete();
+
+            reportSurface(surface, 'rrect_canvas', done);
+        }));
+    });
+
+    it('draws complex rrects', function(done) {
         LoadCanvasKit.then(catchException(done, () => {
             const surface = CanvasKit.MakeCanvasSurface('test');
             expect(surface).toBeTruthy('Could not make surface')
@@ -183,34 +223,22 @@
             canvas.clear(CanvasKit.WHITE);
 
             canvas.drawRRect({
-                rect: CanvasKit.LTRBRect(10, 10, 50, 50),
-                rx: 5,
-                ry: 10,
-            }, paint);
-
-            canvas.drawRRect({
-                rect: CanvasKit.LTRBRect(60, 10, 110, 50),
-                rx: 10,
-                ry: 5,
-            }, paint);
-
-            canvas.drawRRect({
-                rect: CanvasKit.LTRBRect(10, 60, 210, 260),
-                rx: 0,
-                ry: 30,
-            }, paint);
-
-            canvas.drawRRect({
-                rect: CanvasKit.LTRBRect(50, 90, 160, 210),
-                rx: 30,
-                ry: 30,
+              rect: CanvasKit.LTRBRect(10, 10, 210, 210),
+              rx1: 10, // top left corner, going clockwise
+              ry1: 30,
+              rx2: 30,
+              ry2: 10,
+              rx3: 50,
+              ry3: 75,
+              rx4: 120,
+              ry4: 120,
             }, paint);
 
             surface.flush();
             path.delete();
             paint.delete();
 
-            reportSurface(surface, 'rrect_canvas', done);
+            reportSurface(surface, 'rrect_8corners_canvas', done);
         }));
     });
 
@@ -234,18 +262,8 @@
 
             canvas.clear(CanvasKit.WHITE);
 
-
-            const outer = {
-                rect: CanvasKit.LTRBRect(10, 60, 210, 260),
-                rx: 10,
-                ry: 5,
-            };
-
-            const inner = {
-                rect: CanvasKit.LTRBRect(50, 90, 160, 210),
-                rx: 30,
-                ry: 30,
-            };
+            const outer = CanvasKit.RRectXY(CanvasKit.LTRBRect(10, 60, 210, 260), 10, 5);
+            const inner = CanvasKit.RRectXY(CanvasKit.LTRBRect(50, 90, 160, 210), 30, 30);
 
             canvas.drawDRRect(outer, inner, paint);