| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrRRectEffect.h" | 8 #include "GrRRectEffect.h" |
| 9 | 9 |
| 10 #include "gl/GrGLEffect.h" | 10 #include "gl/GrGLEffect.h" |
| 11 #include "gl/GrGLSL.h" | 11 #include "gl/GrGLSL.h" |
| 12 #include "GrTBackendEffectFactory.h" | 12 #include "GrTBackendEffectFactory.h" |
| 13 | 13 |
| 14 #include "SkRRect.h" | 14 #include "SkRRect.h" |
| 15 | 15 |
| 16 using namespace GrRRectEffect; | 16 using namespace GrRRectEffect; |
| 17 | 17 |
| 18 class GLRRectEffect; | 18 class GLRRectEffect; |
| 19 | 19 |
| 20 class RRectEffect : public GrEffect { | 20 class RRectEffect : public GrEffect { |
| 21 public: | 21 public: |
| 22 // This effect only supports circular corner rrects where the radius is >= k
RadiusMin. | 22 // This effect only supports circular corner rrects where the radius is >= k
RadiusMin. |
| 23 static const SkScalar kRadiusMin; | 23 static const SkScalar kRadiusMin; |
| 24 | 24 |
| 25 /// The types of circular corner rrects supported | 25 enum CornerFlags { |
| 26 enum RRectType { | 26 kTopLeft_CornerFlag = (1 << SkRRect::kUpperLeft_Corner), |
| 27 kCircleCorner_RRectType, //<! All four corners have the same circula
r radius. | 27 kTopRight_CornerFlag = (1 << SkRRect::kUpperRight_Corner), |
| 28 kLeftCircleTab_RRectType, //<! The left side has circular corners, th
e right is a rect. | 28 kBottomRight_CornerFlag = (1 << SkRRect::kLowerRight_Corner), |
| 29 kTopCircleTab_RRectType, //<! etc | 29 kBottomLeft_CornerFlag = (1 << SkRRect::kLowerLeft_Corner), |
| 30 kRightCircleTab_RRectType, | 30 |
| 31 kBottomCircleTab_RRectType, | 31 kLeft_CornerFlags = kTopLeft_CornerFlag | kBottomLeft_CornerFlag, |
| 32 kTop_CornerFlags = kTopLeft_CornerFlag | kTopRight_CornerFlag, |
| 33 kRight_CornerFlags = kTopRight_CornerFlag | kBottomRight_CornerFlag, |
| 34 kBottom_CornerFlags = kBottomLeft_CornerFlag | kBottomRight_CornerFlag, |
| 35 |
| 36 kAll_CornerFlags = kTopLeft_CornerFlag | kTopRight_CornerFlag | |
| 37 kBottomLeft_CornerFlag | kBottomRight_CornerFlag, |
| 38 |
| 32 }; | 39 }; |
| 33 | 40 |
| 34 static GrEffectRef* Create(GrEffectEdgeType, RRectType, const SkRRect&); | 41 // The flags are used to indicate which corners are circluar (unflagged corn
ers are assumed to |
| 42 // be square). |
| 43 static GrEffectRef* Create(GrEffectEdgeType, uint32_t circularCornerFlags, c
onst SkRRect&); |
| 35 | 44 |
| 36 virtual ~RRectEffect() {}; | 45 virtual ~RRectEffect() {}; |
| 37 static const char* Name() { return "RRect"; } | 46 static const char* Name() { return "RRect"; } |
| 38 | 47 |
| 39 const SkRRect& getRRect() const { return fRRect; } | 48 const SkRRect& getRRect() const { return fRRect; } |
| 40 | 49 |
| 41 RRectType getType() const { return fRRectType; } | 50 uint32_t getCircularCornerFlags() const { return fCircularCornerFlags; } |
| 42 | 51 |
| 43 GrEffectEdgeType getEdgeType() const { return fEdgeType; } | 52 GrEffectEdgeType getEdgeType() const { return fEdgeType; } |
| 44 | 53 |
| 45 typedef GLRRectEffect GLEffect; | 54 typedef GLRRectEffect GLEffect; |
| 46 | 55 |
| 47 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags
) const SK_OVERRIDE; | 56 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags
) const SK_OVERRIDE; |
| 48 | 57 |
| 49 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; | 58 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; |
| 50 | 59 |
| 51 private: | 60 private: |
| 52 RRectEffect(GrEffectEdgeType, RRectType, const SkRRect&); | 61 RRectEffect(GrEffectEdgeType, uint32_t circularCornerFlags, const SkRRect&); |
| 53 | 62 |
| 54 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; | 63 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; |
| 55 | 64 |
| 56 SkRRect fRRect; | 65 SkRRect fRRect; |
| 57 GrEffectEdgeType fEdgeType; | 66 GrEffectEdgeType fEdgeType; |
| 58 RRectType fRRectType; | 67 uint32_t fCircularCornerFlags; |
| 59 | 68 |
| 60 GR_DECLARE_EFFECT_TEST; | 69 GR_DECLARE_EFFECT_TEST; |
| 61 | 70 |
| 62 typedef GrEffect INHERITED; | 71 typedef GrEffect INHERITED; |
| 63 }; | 72 }; |
| 64 | 73 |
| 65 const SkScalar RRectEffect::kRadiusMin = 0.5f; | 74 const SkScalar RRectEffect::kRadiusMin = 0.5f; |
| 66 | 75 |
| 67 GrEffectRef* RRectEffect::Create(GrEffectEdgeType edgeType, | 76 GrEffectRef* RRectEffect::Create(GrEffectEdgeType edgeType, |
| 68 RRectType rrType, | 77 uint32_t circularCornerFlags, |
| 69 const SkRRect& rrect) { | 78 const SkRRect& rrect) { |
| 70 SkASSERT(kFillAA_GrEffectEdgeType == edgeType || kInverseFillAA_GrEffectEdge
Type == edgeType); | 79 SkASSERT(kFillAA_GrEffectEdgeType == edgeType || kInverseFillAA_GrEffectEdge
Type == edgeType); |
| 71 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(RRectEffect, (edgeType, rr
Type, rrect)))); | 80 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(RRectEffect, |
| 81 (edgeType, circularCornerF
lags, rrect)))); |
| 72 } | 82 } |
| 73 | 83 |
| 74 void RRectEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlag
s) const { | 84 void RRectEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlag
s) const { |
| 75 *validFlags = 0; | 85 *validFlags = 0; |
| 76 } | 86 } |
| 77 | 87 |
| 78 const GrBackendEffectFactory& RRectEffect::getFactory() const { | 88 const GrBackendEffectFactory& RRectEffect::getFactory() const { |
| 79 return GrTBackendEffectFactory<RRectEffect>::getInstance(); | 89 return GrTBackendEffectFactory<RRectEffect>::getInstance(); |
| 80 } | 90 } |
| 81 | 91 |
| 82 RRectEffect::RRectEffect(GrEffectEdgeType edgeType, RRectType rrType, const SkRR
ect& rrect) | 92 RRectEffect::RRectEffect(GrEffectEdgeType edgeType, uint32_t circularCornerFlags
, |
| 93 const SkRRect& rrect) |
| 83 : fRRect(rrect) | 94 : fRRect(rrect) |
| 84 , fEdgeType(edgeType) | 95 , fEdgeType(edgeType) |
| 85 , fRRectType(rrType) { | 96 , fCircularCornerFlags(circularCornerFlags) { |
| 86 this->setWillReadFragmentPosition(); | 97 this->setWillReadFragmentPosition(); |
| 87 } | 98 } |
| 88 | 99 |
| 89 bool RRectEffect::onIsEqual(const GrEffect& other) const { | 100 bool RRectEffect::onIsEqual(const GrEffect& other) const { |
| 90 const RRectEffect& rre = CastEffect<RRectEffect>(other); | 101 const RRectEffect& rre = CastEffect<RRectEffect>(other); |
| 91 // type is derived from fRRect, so no need to check it. | 102 // type is derived from fRRect, so no need to check it. |
| 92 return fEdgeType == rre.fEdgeType && fRRect == rre.fRRect; | 103 return fEdgeType == rre.fEdgeType && fRRect == rre.fRRect; |
| 93 } | 104 } |
| 94 | 105 |
| 95 ////////////////////////////////////////////////////////////////////////////// | 106 ////////////////////////////////////////////////////////////////////////////// |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 175 // fragments near the other three edges will get the correct AA. Fragments i
n the interior of | 186 // fragments near the other three edges will get the correct AA. Fragments i
n the interior of |
| 176 // the rrect will have a (0,0) vector at all four corners. So long as the ra
dius > 0.5 they will | 187 // the rrect will have a (0,0) vector at all four corners. So long as the ra
dius > 0.5 they will |
| 177 // correctly produce an alpha value of 1 at all four corners. We take the mi
n of all the alphas. | 188 // correctly produce an alpha value of 1 at all four corners. We take the mi
n of all the alphas. |
| 178 // The code below is a simplified version of the above that performs maxs on
the vector | 189 // The code below is a simplified version of the above that performs maxs on
the vector |
| 179 // components before computing distances and alpha values so that only one d
istance computation | 190 // components before computing distances and alpha values so that only one d
istance computation |
| 180 // need be computed to determine the min alpha. | 191 // need be computed to determine the min alpha. |
| 181 // | 192 // |
| 182 // For the cases where one half of the rrect is rectangular we drop one of t
he x or y | 193 // For the cases where one half of the rrect is rectangular we drop one of t
he x or y |
| 183 // computations, compute a separate rect edge alpha for the rect side, and m
ul the two computed | 194 // computations, compute a separate rect edge alpha for the rect side, and m
ul the two computed |
| 184 // alphas together. | 195 // alphas together. |
| 185 switch (rre.getType()) { | 196 switch (rre.getCircularCornerFlags()) { |
| 186 case RRectEffect::kCircleCorner_RRectType: | 197 case RRectEffect::kAll_CornerFlags: |
| 187 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); | 198 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); |
| 188 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); | 199 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); |
| 189 builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n")
; | 200 builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n")
; |
| 190 builder->fsCodeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0.
0, 1.0);\n", | 201 builder->fsCodeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0.
0, 1.0);\n", |
| 191 radiusPlusHalfName); | 202 radiusPlusHalfName); |
| 192 break; | 203 break; |
| 193 case RRectEffect::kLeftCircleTab_RRectType: | 204 case RRectEffect::kLeft_CornerFlags: |
| 194 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); | 205 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); |
| 195 builder->fsCodeAppendf("\t\tfloat dy1 = %s.y - %s.w;\n", fragmentPos
, rectName); | 206 builder->fsCodeAppendf("\t\tfloat dy1 = %s.y - %s.w;\n", fragmentPos
, rectName); |
| 196 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, d
y1)), 0.0);\n"); | 207 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, d
y1)), 0.0);\n"); |
| 197 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.
0, 1.0);\n", | 208 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.
0, 1.0);\n", |
| 198 rectName, fragmentPos); | 209 rectName, fragmentPos); |
| 199 builder->fsCodeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - le
ngth(dxy), 0.0, 1.0);\n", | 210 builder->fsCodeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - le
ngth(dxy), 0.0, 1.0);\n", |
| 200 radiusPlusHalfName); | 211 radiusPlusHalfName); |
| 201 break; | 212 break; |
| 202 case RRectEffect::kTopCircleTab_RRectType: | 213 case RRectEffect::kTop_CornerFlags: |
| 203 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); | 214 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); |
| 204 builder->fsCodeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentPos
, rectName); | 215 builder->fsCodeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentPos
, rectName); |
| 205 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), dxy
0.y), 0.0);\n"); | 216 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), dxy
0.y), 0.0);\n"); |
| 206 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0
.0, 1.0);\n", | 217 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0
.0, 1.0);\n", |
| 207 rectName, fragmentPos); | 218 rectName, fragmentPos); |
| 208 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - l
ength(dxy), 0.0, 1.0);\n", | 219 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - l
ength(dxy), 0.0, 1.0);\n", |
| 209 radiusPlusHalfName); | 220 radiusPlusHalfName); |
| 210 break; | 221 break; |
| 211 case RRectEffect::kRightCircleTab_RRectType: | 222 case RRectEffect::kRight_CornerFlags: |
| 212 builder->fsCodeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, f
ragmentPos); | 223 builder->fsCodeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, f
ragmentPos); |
| 213 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); | 224 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); |
| 214 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1
.y)), 0.0);\n"); | 225 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1
.y)), 0.0);\n"); |
| 215 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0
, 1.0);\n", | 226 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0
, 1.0);\n", |
| 216 fragmentPos, rectName); | 227 fragmentPos, rectName); |
| 217 builder->fsCodeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - len
gth(dxy), 0.0, 1.0);\n", | 228 builder->fsCodeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - len
gth(dxy), 0.0, 1.0);\n", |
| 218 radiusPlusHalfName); | 229 radiusPlusHalfName); |
| 219 break; | 230 break; |
| 220 case RRectEffect::kBottomCircleTab_RRectType: | 231 case RRectEffect::kBottom_CornerFlags: |
| 221 builder->fsCodeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, f
ragmentPos); | 232 builder->fsCodeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, f
ragmentPos); |
| 222 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); | 233 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); |
| 223 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), dxy
1.y), 0.0);\n"); | 234 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), dxy
1.y), 0.0);\n"); |
| 224 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0,
1.0);\n", | 235 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0,
1.0);\n", |
| 225 fragmentPos, rectName); | 236 fragmentPos, rectName); |
| 226 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - leng
th(dxy), 0.0, 1.0);\n", | 237 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - leng
th(dxy), 0.0, 1.0);\n", |
| 227 radiusPlusHalfName); | 238 radiusPlusHalfName); |
| 228 break; | 239 break; |
| 229 } | 240 } |
| 230 | 241 |
| 231 if (kInverseFillAA_GrEffectEdgeType == rre.getEdgeType()) { | 242 if (kInverseFillAA_GrEffectEdgeType == rre.getEdgeType()) { |
| 232 builder->fsCodeAppend("\t\talpha = 1.0 - alpha;\n"); | 243 builder->fsCodeAppend("\t\talpha = 1.0 - alpha;\n"); |
| 233 } | 244 } |
| 234 | 245 |
| 235 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, | 246 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, |
| 236 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st
r()); | 247 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st
r()); |
| 237 } | 248 } |
| 238 | 249 |
| 239 GrGLEffect::EffectKey GLRRectEffect::GenKey(const GrDrawEffect& drawEffect, cons
t GrGLCaps&) { | 250 GrGLEffect::EffectKey GLRRectEffect::GenKey(const GrDrawEffect& drawEffect, cons
t GrGLCaps&) { |
| 240 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); | 251 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); |
| 241 GR_STATIC_ASSERT(kGrEffectEdgeTypeCnt <= 8); | 252 GR_STATIC_ASSERT(kGrEffectEdgeTypeCnt <= 8); |
| 242 return (rre.getType() << 3) | rre.getEdgeType(); | 253 return (rre.getCircularCornerFlags() << 3) | rre.getEdgeType(); |
| 243 } | 254 } |
| 244 | 255 |
| 245 void GLRRectEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect&
drawEffect) { | 256 void GLRRectEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect&
drawEffect) { |
| 246 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); | 257 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); |
| 247 const SkRRect& rrect = rre.getRRect(); | 258 const SkRRect& rrect = rre.getRRect(); |
| 248 if (rrect != fPrevRRect) { | 259 if (rrect != fPrevRRect) { |
| 249 SkRect rect = rrect.getBounds(); | 260 SkRect rect = rrect.getBounds(); |
| 250 SkScalar radius = 0; | 261 SkScalar radius = 0; |
| 251 switch (rre.getType()) { | 262 switch (rre.getCircularCornerFlags()) { |
| 252 case RRectEffect::kCircleCorner_RRectType: | 263 case RRectEffect::kAll_CornerFlags: |
| 253 SkASSERT(rrect.isSimpleCircular()); | 264 SkASSERT(rrect.isSimpleCircular()); |
| 254 radius = rrect.getSimpleRadii().fX; | 265 radius = rrect.getSimpleRadii().fX; |
| 255 SkASSERT(radius >= RRectEffect::kRadiusMin); | 266 SkASSERT(radius >= RRectEffect::kRadiusMin); |
| 256 rect.inset(radius, radius); | 267 rect.inset(radius, radius); |
| 257 break; | 268 break; |
| 258 case RRectEffect::kLeftCircleTab_RRectType: | 269 case RRectEffect::kLeft_CornerFlags: |
| 259 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; | 270 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; |
| 260 rect.fLeft += radius; | 271 rect.fLeft += radius; |
| 261 rect.fTop += radius; | 272 rect.fTop += radius; |
| 262 rect.fRight += 0.5f; | 273 rect.fRight += 0.5f; |
| 263 rect.fBottom -= radius; | 274 rect.fBottom -= radius; |
| 264 break; | 275 break; |
| 265 case RRectEffect::kTopCircleTab_RRectType: | 276 case RRectEffect::kTop_CornerFlags: |
| 266 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; | 277 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; |
| 267 rect.fLeft += radius; | 278 rect.fLeft += radius; |
| 268 rect.fTop += radius; | 279 rect.fTop += radius; |
| 269 rect.fRight -= radius; | 280 rect.fRight -= radius; |
| 270 rect.fBottom += 0.5f; | 281 rect.fBottom += 0.5f; |
| 271 break; | 282 break; |
| 272 case RRectEffect::kRightCircleTab_RRectType: | 283 case RRectEffect::kRight_CornerFlags: |
| 273 radius = rrect.radii(SkRRect::kUpperRight_Corner).fX; | 284 radius = rrect.radii(SkRRect::kUpperRight_Corner).fX; |
| 274 rect.fLeft -= 0.5f; | 285 rect.fLeft -= 0.5f; |
| 275 rect.fTop += radius; | 286 rect.fTop += radius; |
| 276 rect.fRight -= radius; | 287 rect.fRight -= radius; |
| 277 rect.fBottom -= radius; | 288 rect.fBottom -= radius; |
| 278 break; | 289 break; |
| 279 case RRectEffect::kBottomCircleTab_RRectType: | 290 case RRectEffect::kBottom_CornerFlags: |
| 280 radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX; | 291 radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX; |
| 281 rect.fLeft += radius; | 292 rect.fLeft += radius; |
| 282 rect.fTop -= 0.5f; | 293 rect.fTop -= 0.5f; |
| 283 rect.fRight -= radius; | 294 rect.fRight -= radius; |
| 284 rect.fBottom -= radius; | 295 rect.fBottom -= radius; |
| 285 break; | 296 break; |
| 297 default: |
| 298 GrCrash("Should have been one of the above cases."); |
| 286 } | 299 } |
| 287 uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.f
Bottom); | 300 uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.f
Bottom); |
| 288 uman.set1f(fRadiusPlusHalfUniform, radius + 0.5f); | 301 uman.set1f(fRadiusPlusHalfUniform, radius + 0.5f); |
| 289 fPrevRRect = rrect; | 302 fPrevRRect = rrect; |
| 290 } | 303 } |
| 291 } | 304 } |
| 292 | 305 |
| 293 ////////////////////////////////////////////////////////////////////////////// | 306 ////////////////////////////////////////////////////////////////////////////// |
| 294 | 307 |
| 295 GrEffectRef* GrRRectEffect::Create(GrEffectEdgeType edgeType, const SkRRect& rre
ct) { | 308 GrEffectRef* GrRRectEffect::Create(GrEffectEdgeType edgeType, const SkRRect& rre
ct) { |
| 296 if (kFillAA_GrEffectEdgeType != edgeType && kInverseFillAA_GrEffectEdgeType
!= edgeType) { | 309 if (kFillAA_GrEffectEdgeType != edgeType && kInverseFillAA_GrEffectEdgeType
!= edgeType) { |
| 297 return NULL; | 310 return NULL; |
| 298 } | 311 } |
| 299 RRectEffect::RRectType rrtype; | 312 uint32_t cornerFlags; |
| 300 if (rrect.isSimpleCircular()) { | 313 if (rrect.isSimpleCircular()) { |
| 301 if (rrect.getSimpleRadii().fX < RRectEffect::kRadiusMin) { | 314 if (rrect.getSimpleRadii().fX < RRectEffect::kRadiusMin) { |
| 302 return NULL; | 315 return NULL; |
| 303 } | 316 } |
| 304 rrtype = RRectEffect::kCircleCorner_RRectType; | 317 cornerFlags = RRectEffect::kAll_CornerFlags; |
| 305 } else if (rrect.isComplex()) { | 318 } else if (rrect.isComplex()) { |
| 306 // Check for the "tab" cases - two adjacent circular corners and two squ
are corners. | 319 // Check for the "tab" cases - two adjacent circular corners and two squ
are corners. |
| 307 SkScalar radius = 0; | 320 SkScalar radius = 0; |
| 308 int circleCornerBitfield = 0; | 321 cornerFlags = 0; |
| 309 for (int c = 0; c < 4; ++c) { | 322 for (int c = 0; c < 4; ++c) { |
| 310 const SkVector& r = rrect.radii((SkRRect::Corner)c); | 323 const SkVector& r = rrect.radii((SkRRect::Corner)c); |
| 311 SkASSERT((0 == r.fX) == (0 == r.fY)); | 324 SkASSERT((0 == r.fX) == (0 == r.fY)); |
| 312 if (0 == r.fX) { | 325 if (0 == r.fX) { |
| 313 continue; | 326 continue; |
| 314 } | 327 } |
| 315 if (r.fX != r.fY) { | 328 if (r.fX != r.fY) { |
| 316 return NULL; | 329 return NULL; |
| 317 } | 330 } |
| 318 if (!circleCornerBitfield) { | 331 if (!cornerFlags) { |
| 319 radius = r.fX; | 332 radius = r.fX; |
| 320 if (radius < RRectEffect::kRadiusMin) { | 333 if (radius < RRectEffect::kRadiusMin) { |
| 321 return NULL; | 334 return NULL; |
| 322 } | 335 } |
| 323 circleCornerBitfield = 1 << c; | 336 cornerFlags = 1 << c; |
| 324 } else { | 337 } else { |
| 325 if (r.fX != radius) { | 338 if (r.fX != radius) { |
| 326 return NULL; | 339 return NULL; |
| 327 } | 340 } |
| 328 circleCornerBitfield |= 1 << c; | 341 cornerFlags |= 1 << c; |
| 329 } | 342 } |
| 330 } | 343 } |
| 331 | 344 |
| 332 GR_STATIC_ASSERT(SkRRect::kUpperLeft_Corner == 0); | 345 switch (cornerFlags) { |
| 333 GR_STATIC_ASSERT(SkRRect::kUpperRight_Corner == 1); | 346 case RRectEffect::kLeft_CornerFlags: |
| 334 GR_STATIC_ASSERT(SkRRect::kLowerRight_Corner == 2); | 347 case RRectEffect::kTop_CornerFlags: |
| 335 GR_STATIC_ASSERT(SkRRect::kLowerLeft_Corner == 3); | 348 case RRectEffect::kRight_CornerFlags: |
| 336 switch (circleCornerBitfield) { | 349 case RRectEffect::kBottom_CornerFlags: |
| 337 case 3: | 350 case RRectEffect::kAll_CornerFlags: |
| 338 rrtype = RRectEffect::kTopCircleTab_RRectType; | |
| 339 break; | |
| 340 case 6: | |
| 341 rrtype = RRectEffect::kRightCircleTab_RRectType; | |
| 342 break; | |
| 343 case 9: | |
| 344 rrtype = RRectEffect::kLeftCircleTab_RRectType; | |
| 345 break; | |
| 346 case 12: | |
| 347 rrtype = RRectEffect::kBottomCircleTab_RRectType; | |
| 348 break; | 351 break; |
| 349 default: | 352 default: |
| 350 return NULL; | 353 return NULL; |
| 351 } | 354 } |
| 352 } else { | 355 } else { |
| 353 return NULL; | 356 return NULL; |
| 354 } | 357 } |
| 355 return RRectEffect::Create(edgeType, rrtype, rrect); | 358 return RRectEffect::Create(edgeType, cornerFlags, rrect); |
| 356 } | 359 } |
| OLD | NEW |