New way to scale RRect

- far simpler
- matches the float behavior of transforming the path-equivalent

This shows a few tiny diffs, due to the different way we apply
the matrix itself:

Old way: transform distances (radii width and height)

New way: transform centers (positions, not distances)

The new way is aligned with out paths, even paths that represent
round-rects, are transformed. Hence this CL brings rrect::transform
inline with its path counterpart.

Triggered by SK_SUPPORT_LEGACY_RRECT_TRANSFORM

Clients should define this (or not) while they transition to the
(slighly) different behavior.

Change-Id: I5976bf5b7b7f943afa14a7f426e14ff29086d350
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1029976
Reviewed-by: Eric Boren <borenet@google.com>
Reviewed-by: Florin Malita <fmalita@google.com>
Commit-Queue: Mike Reed <mike@reedtribe.org>
Reviewed-by: Daniel Dilan <danieldilan@google.com>
diff --git a/include/core/SkRRect.h b/include/core/SkRRect.h
index fddd130..43ee170 100644
--- a/include/core/SkRRect.h
+++ b/include/core/SkRRect.h
@@ -455,13 +455,7 @@
      *  If the matrix does not preserve axis-alignment (e.g. rotates, skews, etc.)
      *  then this returns {}.
      */
-    std::optional<SkRRect> transform(const SkMatrix& matrix) const {
-        SkRRect rr;
-        if (this->transform(matrix, &rr)) {
-            return rr;
-        }
-        return {};
-    }
+    std::optional<SkRRect> transform(const SkMatrix&) const;
 
     // Deprecated: use optional form
     bool transform(const SkMatrix& matrix, SkRRect* dst) const;
diff --git a/src/core/SkRRect.cpp b/src/core/SkRRect.cpp
index 24a13da..72e818a 100644
--- a/src/core/SkRRect.cpp
+++ b/src/core/SkRRect.cpp
@@ -16,6 +16,8 @@
 #include "include/private/base/SkDebug.h"
 #include "include/private/base/SkFloatingPoint.h"
 #include "src/base/SkBuffer.h"
+#include "src/core/SkPathPriv.h"
+#include "src/core/SkPathRawShapes.h"
 #include "src/core/SkRRectPriv.h"
 #include "src/core/SkRectPriv.h"
 #include "src/core/SkScaleToSides.h"
@@ -25,6 +27,11 @@
 #include <cstring>
 #include <iterator>
 
+// TODO: when this flag is present in clients, remove these 3 lines
+#ifndef SK_SUPPORT_LEGACY_RRECT_TRANSFORM
+    #define SK_SUPPORT_LEGACY_RRECT_TRANSFORM
+#endif
+
 ///////////////////////////////////////////////////////////////////////////////
 
 void SkRRect::setOval(const SkRect& oval) {
@@ -433,7 +440,35 @@
     }
 }
 
+std::optional<SkRRect> SkRRect::transform(const SkMatrix& matrix) const {
+    if (matrix.isIdentity()) {
+        return *this;
+    }
+
+    if (!matrix.preservesAxisAlignment()) {
+        return {};
+    }
+
+    const SkRect newRect = matrix.mapRect(fRect);
+    if (!newRect.isFinite()) {
+        return {};
+    }
+
+    switch (this->getType()) {
+        case kEmpty_Type: return MakeEmpty();
+        case kRect_Type:  return MakeRect(newRect);
+        case kOval_Type:  return MakeOval(newRect);
+        default:
+            break;
+    }
+
+    SkPathRawShapes::RRect raw(*this);
+    matrix.mapPoints(raw.fStorage);
+    return SkPathPriv::DeduceRRectFromContour(newRect, raw.fPoints, raw.fVerbs);
+}
+
 bool SkRRect::transform(const SkMatrix& matrix, SkRRect* dst) const {
+#ifdef SK_SUPPORT_LEGACY_RRECT_TRANSFORM
     if (nullptr == dst) {
         return false;
     }
@@ -562,6 +597,15 @@
 
     SkASSERT(dst->isValid());
     return true;
+#else
+    if (auto rr = this->transform(matrix)) {
+        if (dst) {
+            *dst = *rr;
+        }
+        return true;
+    }
+    return false;
+#endif
 }
 
 ///////////////////////////////////////////////////////////////////////////////