Accept near-simple, near-circular rrects for shadow fast path.
SkRRectPriv::IsSimpleCircular does a tolerance-based check for the
rrect radii but not for determining if the rrect is simple. This adds
IsNearlySimpleCircular as a looser check, since we don't care in this
case that the rrect is perfectly simple.
Bug: skia:11717
Change-Id: Ibbd53ff8c120287339fa29f87f064e6fb633ee7c
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/382703
Reviewed-by: Leon Scroggins <scroggo@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
diff --git a/src/core/SkRRect.cpp b/src/core/SkRRect.cpp
index f2f6ab3..060e956 100644
--- a/src/core/SkRRect.cpp
+++ b/src/core/SkRRect.cpp
@@ -317,6 +317,17 @@
return dist <= SkScalarSquare(fRadii[index].fX * fRadii[index].fY);
}
+bool SkRRectPriv::IsNearlySimpleCircular(const SkRRect& rr, SkScalar tolerance) {
+ SkScalar simpleRadius = rr.fRadii[0].fX;
+ return SkScalarNearlyEqual(simpleRadius, rr.fRadii[0].fY, tolerance) &&
+ SkScalarNearlyEqual(simpleRadius, rr.fRadii[1].fX, tolerance) &&
+ SkScalarNearlyEqual(simpleRadius, rr.fRadii[1].fY, tolerance) &&
+ SkScalarNearlyEqual(simpleRadius, rr.fRadii[2].fX, tolerance) &&
+ SkScalarNearlyEqual(simpleRadius, rr.fRadii[2].fY, tolerance) &&
+ SkScalarNearlyEqual(simpleRadius, rr.fRadii[3].fX, tolerance) &&
+ SkScalarNearlyEqual(simpleRadius, rr.fRadii[3].fY, tolerance);
+}
+
bool SkRRectPriv::AllCornersCircular(const SkRRect& rr, SkScalar tolerance) {
return SkScalarNearlyEqual(rr.fRadii[0].fX, rr.fRadii[0].fY, tolerance) &&
SkScalarNearlyEqual(rr.fRadii[1].fX, rr.fRadii[1].fY, tolerance) &&
diff --git a/src/core/SkRRectPriv.h b/src/core/SkRRectPriv.h
index 03fa8a2..cea579c 100644
--- a/src/core/SkRRectPriv.h
+++ b/src/core/SkRRectPriv.h
@@ -28,6 +28,10 @@
return rr.isSimple() && SkScalarNearlyEqual(rr.fRadii[0].fX, rr.fRadii[0].fY);
}
+ // Looser version of IsSimpleCircular, where the x & y values of the radii
+ // only have to be nearly equal instead of strictly equal.
+ static bool IsNearlySimpleCircular(const SkRRect& rr, SkScalar tolerance = SK_ScalarNearlyZero);
+
static bool EqualRadii(const SkRRect& rr) {
return rr.isRect() || SkRRectPriv::IsCircle(rr) || SkRRectPriv::IsSimpleCircular(rr);
}
diff --git a/src/gpu/GrSurfaceDrawContext.cpp b/src/gpu/GrSurfaceDrawContext.cpp
index 57a252b..7556d15 100644
--- a/src/gpu/GrSurfaceDrawContext.cpp
+++ b/src/gpu/GrSurfaceDrawContext.cpp
@@ -977,9 +977,9 @@
SkRRect rrect;
SkRect rect;
- // we can only handle rects, circles, and rrects with circular corners
- bool isRRect = path.isRRect(&rrect) && SkRRectPriv::IsSimpleCircular(rrect) &&
- rrect.radii(SkRRect::kUpperLeft_Corner).fX > SK_ScalarNearlyZero;
+ // we can only handle rects, circles, and simple rrects with circular corners
+ bool isRRect = path.isRRect(&rrect) && SkRRectPriv::IsNearlySimpleCircular(rrect) &&
+ rrect.getSimpleRadii().fX > SK_ScalarNearlyZero;
if (!isRRect &&
path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height()) &&
rect.width() > SK_ScalarNearlyZero) {
@@ -1089,7 +1089,7 @@
SkMatrix shadowTransform;
shadowTransform.setScaleTranslate(spotScale, spotScale, spotOffset.fX, spotOffset.fY);
rrect.transform(shadowTransform, &spotShadowRRect);
- SkScalar spotRadius = SkRRectPriv::GetSimpleRadii(spotShadowRRect).fX;
+ SkScalar spotRadius = spotShadowRRect.getSimpleRadii().fX;
// Compute the insetWidth
SkScalar blurOutset = srcSpaceSpotBlur;
@@ -1132,7 +1132,7 @@
spotShadowRRect.rect().fBottom -
rrect.rect().fBottom - dr);
maxOffset = SkScalarSqrt(std::max(SkPointPriv::LengthSqd(upperLeftOffset),
- SkPointPriv::LengthSqd(lowerRightOffset))) + dr;
+ SkPointPriv::LengthSqd(lowerRightOffset))) + dr;
}
insetWidth += std::max(blurOutset, maxOffset);
}