aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-03-24 19:24:59 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-03-24 19:24:59 +0000
commit2a8be900db664bb26dca1adcb3a524a1bb1f45e6 (patch)
tree3f660fe022223f798d6a7f2e0d222983f44d8164
parent1ba62629f4d8300eb5ff82a83807119032eb0c02 (diff)
When clipping treat rrect corners where either the x or y radius is < 0.5 as square.
BUG=skia:2181 R=robertphillips@google.com, jvanverth@google.com Author: bsalomon@google.com Review URL: https://codereview.chromium.org/200723011 git-svn-id: http://skia.googlecode.com/svn/trunk@13918 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--src/gpu/effects/GrRRectEffect.cpp119
1 files changed, 68 insertions, 51 deletions
diff --git a/src/gpu/effects/GrRRectEffect.cpp b/src/gpu/effects/GrRRectEffect.cpp
index e4120c956a..1e8613b5bc 100644
--- a/src/gpu/effects/GrRRectEffect.cpp
+++ b/src/gpu/effects/GrRRectEffect.cpp
@@ -9,16 +9,20 @@
#include "gl/GrGLEffect.h"
#include "gl/GrGLSL.h"
+#include "GrConvexPolyEffect.h"
#include "GrTBackendEffectFactory.h"
#include "SkRRect.h"
+// The effects defined here only handle rrect radii >= kRadiusMin.
+static const SkScalar kRadiusMin = SK_ScalarHalf;
+
+//////////////////////////////////////////////////////////////////////////////
+
class GLCircularRRectEffect;
class CircularRRectEffect : public GrEffect {
public:
- // This effect only supports circular corner rrects where the radius is >= kRadiusMin.
- static const SkScalar kRadiusMin;
enum CornerFlags {
kTopLeft_CornerFlag = (1 << SkRRect::kUpperLeft_Corner),
@@ -34,6 +38,7 @@ public:
kAll_CornerFlags = kTopLeft_CornerFlag | kTopRight_CornerFlag |
kBottomLeft_CornerFlag | kBottomRight_CornerFlag,
+ kNone_CornerFlags = 0
};
// The flags are used to indicate which corners are circluar (unflagged corners are assumed to
@@ -69,8 +74,6 @@ private:
typedef GrEffect INHERITED;
};
-const SkScalar CircularRRectEffect::kRadiusMin = 0.5f;
-
GrEffectRef* CircularRRectEffect::Create(GrEffectEdgeType edgeType,
uint32_t circularCornerFlags,
const SkRRect& rrect) {
@@ -303,7 +306,7 @@ void GLCircularRRectEffect::setData(const GrGLUniformManager& uman,
case CircularRRectEffect::kAll_CornerFlags:
SkASSERT(rrect.isSimpleCircular());
radius = rrect.getSimpleRadii().fX;
- SkASSERT(radius >= CircularRRectEffect::kRadiusMin);
+ SkASSERT(radius >= kRadiusMin);
rect.inset(radius, radius);
break;
case CircularRRectEffect::kTopLeft_CornerFlag:
@@ -377,9 +380,6 @@ class GLEllipticalRRectEffect;
class EllipticalRRectEffect : public GrEffect {
public:
- // This effect only supports rrects where the radii are >= kRadiusMin.
- static const SkScalar kRadiusMin;
-
static GrEffectRef* Create(GrEffectEdgeType, const SkRRect&);
virtual ~EllipticalRRectEffect() {};
@@ -409,8 +409,6 @@ private:
typedef GrEffect INHERITED;
};
-const SkScalar EllipticalRRectEffect::kRadiusMin = 0.5f;
-
GrEffectRef* EllipticalRRectEffect::Create(GrEffectEdgeType edgeType, const SkRRect& rrect) {
SkASSERT(kFillAA_GrEffectEdgeType == edgeType || kInverseFillAA_GrEffectEdgeType == edgeType);
return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipticalRRectEffect, (edgeType, rrect))));
@@ -596,8 +594,8 @@ void GLEllipticalRRectEffect::setData(const GrGLUniformManager& uman,
if (rrect != fPrevRRect) {
SkRect rect = rrect.getBounds();
const SkVector& r0 = rrect.radii(SkRRect::kUpperLeft_Corner);
- SkASSERT(r0.fX >= EllipticalRRectEffect::kRadiusMin);
- SkASSERT(r0.fY >= EllipticalRRectEffect::kRadiusMin);
+ SkASSERT(r0.fX >= kRadiusMin);
+ SkASSERT(r0.fY >= kRadiusMin);
switch (erre.getRRect().getType()) {
case SkRRect::kSimple_Type:
rect.inset(r0.fX, r0.fY);
@@ -606,8 +604,8 @@ void GLEllipticalRRectEffect::setData(const GrGLUniformManager& uman,
break;
case SkRRect::kNinePatch_Type: {
const SkVector& r1 = rrect.radii(SkRRect::kLowerRight_Corner);
- SkASSERT(r1.fX >= EllipticalRRectEffect::kRadiusMin);
- SkASSERT(r1.fY >= EllipticalRRectEffect::kRadiusMin);
+ SkASSERT(r1.fX >= kRadiusMin);
+ SkASSERT(r1.fY >= kRadiusMin);
rect.fLeft += r0.fX;
rect.fTop += r0.fY;
rect.fRight -= r1.fX;
@@ -632,43 +630,53 @@ GrEffectRef* GrRRectEffect::Create(GrEffectEdgeType edgeType, const SkRRect& rre
if (kFillAA_GrEffectEdgeType != edgeType && kInverseFillAA_GrEffectEdgeType != edgeType) {
return NULL;
}
- uint32_t cornerFlags;
+
+ if (rrect.isRect()) {
+ return GrConvexPolyEffect::Create(edgeType, rrect.getBounds());
+ }
+
if (rrect.isSimple()) {
+ if (rrect.getSimpleRadii().fX < kRadiusMin || rrect.getSimpleRadii().fY < kRadiusMin) {
+ // In this case the corners are extremely close to rectangular and we collapse the
+ // clip to a rectangular clip.
+ return GrConvexPolyEffect::Create(edgeType, rrect.getBounds());
+ }
if (rrect.getSimpleRadii().fX == rrect.getSimpleRadii().fY) {
- if (rrect.getSimpleRadii().fX < CircularRRectEffect::kRadiusMin) {
- return NULL;
- }
- cornerFlags = CircularRRectEffect::kAll_CornerFlags;
+ return CircularRRectEffect::Create(edgeType, CircularRRectEffect::kAll_CornerFlags,
+ rrect);
} else {
- if (rrect.getSimpleRadii().fX < EllipticalRRectEffect::kRadiusMin ||
- rrect.getSimpleRadii().fY < EllipticalRRectEffect::kRadiusMin) {
- return NULL;
- }
return EllipticalRRectEffect::Create(edgeType, rrect);
}
- } else if (rrect.isComplex() || rrect.isNinePatch()) {
+ }
+
+ if (rrect.isComplex() || rrect.isNinePatch()) {
// Check for the "tab" cases - two adjacent circular corners and two square corners.
- SkScalar radius = 0;
- cornerFlags = 0;
+ SkScalar circularRadius = 0;
+ uint32_t cornerFlags = 0;
+
+ SkVector radii[4];
+ bool squashedRadii = false;
for (int c = 0; c < 4; ++c) {
- const SkVector& r = rrect.radii((SkRRect::Corner)c);
- SkASSERT((0 == r.fX) == (0 == r.fY));
- if (0 == r.fX) {
+ radii[c] = rrect.radii((SkRRect::Corner)c);
+ SkASSERT((0 == radii[c].fX) == (0 == radii[c].fY));
+ if (0 == radii[c].fX) {
+ // The corner is square, so no need to squash or flag as circular.
+ continue;
+ }
+ if (radii[c].fX < kRadiusMin || radii[c].fY < kRadiusMin) {
+ radii[c].set(0, 0);
+ squashedRadii = true;
continue;
}
- if (r.fX != r.fY) {
+ if (radii[c].fX != radii[c].fY) {
cornerFlags = ~0U;
break;
}
if (!cornerFlags) {
- radius = r.fX;
- if (radius < CircularRRectEffect::kRadiusMin) {
- cornerFlags = ~0U;
- break;
- }
+ circularRadius = radii[c].fX;
cornerFlags = 1 << c;
} else {
- if (r.fX != radius) {
+ if (radii[c].fX != circularRadius) {
cornerFlags = ~0U;
break;
}
@@ -677,6 +685,10 @@ GrEffectRef* GrRRectEffect::Create(GrEffectEdgeType edgeType, const SkRRect& rre
}
switch (cornerFlags) {
+ case CircularRRectEffect::kAll_CornerFlags:
+ // This rrect should have been caught in the simple case above. Though, it would
+ // be correctly handled in the fallthrough code.
+ SkASSERT(false);
case CircularRRectEffect::kTopLeft_CornerFlag:
case CircularRRectEffect::kTopRight_CornerFlag:
case CircularRRectEffect::kBottomRight_CornerFlag:
@@ -684,24 +696,29 @@ GrEffectRef* GrRRectEffect::Create(GrEffectEdgeType edgeType, const SkRRect& rre
case CircularRRectEffect::kLeft_CornerFlags:
case CircularRRectEffect::kTop_CornerFlags:
case CircularRRectEffect::kRight_CornerFlags:
- case CircularRRectEffect::kBottom_CornerFlags:
- case CircularRRectEffect::kAll_CornerFlags:
- break;
- default:
+ case CircularRRectEffect::kBottom_CornerFlags: {
+ SkTCopyOnFirstWrite<SkRRect> rr(rrect);
+ if (squashedRadii) {
+ rr.writable()->setRectRadii(rrect.getBounds(), radii);
+ }
+ return CircularRRectEffect::Create(edgeType, cornerFlags, *rr);
+ }
+ case CircularRRectEffect::kNone_CornerFlags:
+ return GrConvexPolyEffect::Create(edgeType, rrect.getBounds());
+ default: {
+ if (squashedRadii) {
+ // If we got here then we squashed some but not all the radii to zero. (If all
+ // had been squashed cornerFlags would be 0.) The elliptical effect doesn't
+ // support some rounded and some square corners.
+ return NULL;
+ }
if (rrect.isNinePatch()) {
- const SkVector& r0 = rrect.radii(SkRRect::kUpperLeft_Corner);
- const SkVector& r1 = rrect.radii(SkRRect::kLowerRight_Corner);
- if (r0.fX >= EllipticalRRectEffect::kRadiusMin &&
- r0.fY >= EllipticalRRectEffect::kRadiusMin &&
- r1.fX >= EllipticalRRectEffect::kRadiusMin &&
- r1.fY >= EllipticalRRectEffect::kRadiusMin) {
- return EllipticalRRectEffect::Create(edgeType, rrect);
- }
+ return EllipticalRRectEffect::Create(edgeType, rrect);
}
return NULL;
+ }
}
- } else {
- return NULL;
}
- return CircularRRectEffect::Create(edgeType, cornerFlags, rrect);
+
+ return NULL;
}