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
}
///////////////////////////////////////////////////////////////////////////////