| 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; |
| 17 |
| 16 class GLRRectEffect; | 18 class GLRRectEffect; |
| 17 | 19 |
| 18 class RRectEffect : public GrEffect { | 20 class RRectEffect : public GrEffect { |
| 19 public: | 21 public: |
| 20 // 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. |
| 21 static const SkScalar kRadiusMin; | 23 static const SkScalar kRadiusMin; |
| 22 | 24 |
| 23 /// The types of circular corner rrects supported | 25 /// The types of circular corner rrects supported |
| 24 enum Type { | 26 enum RRectType { |
| 25 kCircleCorner_Type, //<! All four corners have the same circular rad
ius. | 27 kCircleCorner_RRectType, //<! All four corners have the same circula
r radius. |
| 26 kLeftCircleTab_Type, //<! The left side has circular corners and the
right is a rect. | 28 kLeftCircleTab_RRectType, //<! The left side has circular corners, th
e right is a rect. |
| 27 kTopCircleTab_Type, //<! etc | 29 kTopCircleTab_RRectType, //<! etc |
| 28 kRightCircleTab_Type, | 30 kRightCircleTab_RRectType, |
| 29 kBottomCircleTab_Type, | 31 kBottomCircleTab_RRectType, |
| 30 }; | 32 }; |
| 31 | 33 |
| 32 static GrEffectRef* Create(const SkRRect&, Type); | 34 static GrEffectRef* Create(EdgeType, const SkRRect&, RRectType); |
| 33 | 35 |
| 34 virtual ~RRectEffect() {}; | 36 virtual ~RRectEffect() {}; |
| 35 static const char* Name() { return "RRect"; } | 37 static const char* Name() { return "RRect"; } |
| 36 | 38 |
| 37 const SkRRect& getRRect() const { return fRRect; } | 39 const SkRRect& getRRect() const { return fRRect; } |
| 38 | 40 |
| 39 Type getType() const { return fType; } | 41 RRectType getType() const { return fRRectType; } |
| 42 |
| 43 EdgeType getEdgeType() const { return fEdgeType; } |
| 40 | 44 |
| 41 typedef GLRRectEffect GLEffect; | 45 typedef GLRRectEffect GLEffect; |
| 42 | 46 |
| 43 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags
) const SK_OVERRIDE; | 47 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags
) const SK_OVERRIDE; |
| 44 | 48 |
| 45 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; | 49 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; |
| 46 | 50 |
| 47 private: | 51 private: |
| 48 RRectEffect(const SkRRect&, Type); | 52 RRectEffect(EdgeType, const SkRRect&, RRectType); |
| 49 | 53 |
| 50 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; | 54 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; |
| 51 | 55 |
| 52 SkRRect fRRect; | 56 SkRRect fRRect; |
| 53 Type fType; | 57 EdgeType fEdgeType; |
| 58 RRectType fRRectType; |
| 54 | 59 |
| 55 GR_DECLARE_EFFECT_TEST; | 60 GR_DECLARE_EFFECT_TEST; |
| 56 | 61 |
| 57 typedef GrEffect INHERITED; | 62 typedef GrEffect INHERITED; |
| 58 }; | 63 }; |
| 59 | 64 |
| 60 const SkScalar RRectEffect::kRadiusMin = 0.5f; | 65 const SkScalar RRectEffect::kRadiusMin = 0.5f; |
| 61 | 66 |
| 62 GrEffectRef* RRectEffect::Create(const SkRRect& rrect, Type type) { | 67 GrEffectRef* RRectEffect::Create(EdgeType edgeType, const SkRRect& rrect, RRectT
ype rrtype) { |
| 63 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(RRectEffect, (rrect, type)
))); | 68 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(RRectEffect, (edgeType, rr
ect, rrtype)))); |
| 64 } | 69 } |
| 65 | 70 |
| 66 void RRectEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlag
s) const { | 71 void RRectEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlag
s) const { |
| 67 *validFlags = 0; | 72 *validFlags = 0; |
| 68 } | 73 } |
| 69 | 74 |
| 70 const GrBackendEffectFactory& RRectEffect::getFactory() const { | 75 const GrBackendEffectFactory& RRectEffect::getFactory() const { |
| 71 return GrTBackendEffectFactory<RRectEffect>::getInstance(); | 76 return GrTBackendEffectFactory<RRectEffect>::getInstance(); |
| 72 } | 77 } |
| 73 | 78 |
| 74 RRectEffect::RRectEffect(const SkRRect& rrect, Type type) | 79 RRectEffect::RRectEffect(EdgeType edgeType, const SkRRect& rrect, RRectType rrty
pe) |
| 75 : fRRect(rrect) | 80 : fRRect(rrect) |
| 76 , fType(type) { | 81 , fEdgeType(edgeType) |
| 82 , fRRectType(rrtype) { |
| 77 this->setWillReadFragmentPosition(); | 83 this->setWillReadFragmentPosition(); |
| 78 } | 84 } |
| 79 | 85 |
| 80 bool RRectEffect::onIsEqual(const GrEffect& other) const { | 86 bool RRectEffect::onIsEqual(const GrEffect& other) const { |
| 81 const RRectEffect& rre = CastEffect<RRectEffect>(other); | 87 const RRectEffect& rre = CastEffect<RRectEffect>(other); |
| 82 // type is derived from fRRect, so no need to check it. | 88 // type is derived from fRRect, so no need to check it. |
| 83 return fRRect == rre.fRRect; | 89 return fEdgeType == rre.fEdgeType && fRRect == rre.fRRect; |
| 84 } | 90 } |
| 85 | 91 |
| 86 ////////////////////////////////////////////////////////////////////////////// | 92 ////////////////////////////////////////////////////////////////////////////// |
| 87 | 93 |
| 88 GR_DEFINE_EFFECT_TEST(RRectEffect); | 94 GR_DEFINE_EFFECT_TEST(RRectEffect); |
| 89 | 95 |
| 90 GrEffectRef* RRectEffect::TestCreate(SkRandom* random, | 96 GrEffectRef* RRectEffect::TestCreate(SkRandom* random, |
| 91 GrContext*, | 97 GrContext*, |
| 92 const GrDrawTargetCaps& caps, | 98 const GrDrawTargetCaps& caps, |
| 93 GrTexture*[]) { | 99 GrTexture*[]) { |
| 94 SkScalar w = random->nextRangeScalar(20.f, 1000.f); | 100 SkScalar w = random->nextRangeScalar(20.f, 1000.f); |
| 95 SkScalar h = random->nextRangeScalar(20.f, 1000.f); | 101 SkScalar h = random->nextRangeScalar(20.f, 1000.f); |
| 96 SkScalar r = random->nextRangeF(kRadiusMin, 9.f); | 102 SkScalar r = random->nextRangeF(kRadiusMin, 9.f); |
| 103 EdgeType et = (EdgeType) random->nextULessThan(kEdgeTypeCnt); |
| 97 SkRRect rrect; | 104 SkRRect rrect; |
| 98 rrect.setRectXY(SkRect::MakeWH(w, h), r, r); | 105 rrect.setRectXY(SkRect::MakeWH(w, h), r, r); |
| 99 | 106 |
| 100 return GrRRectEffect::Create(rrect); | 107 return GrRRectEffect::Create(et, rrect); |
| 101 } | 108 } |
| 102 | 109 |
| 103 ////////////////////////////////////////////////////////////////////////////// | 110 ////////////////////////////////////////////////////////////////////////////// |
| 104 | 111 |
| 105 class GLRRectEffect : public GrGLEffect { | 112 class GLRRectEffect : public GrGLEffect { |
| 106 public: | 113 public: |
| 107 GLRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&); | 114 GLRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&); |
| 108 | 115 |
| 109 virtual void emitCode(GrGLShaderBuilder* builder, | 116 virtual void emitCode(GrGLShaderBuilder* builder, |
| 110 const GrDrawEffect& drawEffect, | 117 const GrDrawEffect& drawEffect, |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 // the rrect will have a (0,0) vector at all four corners. So long as the ra
dius > 0.5 they will | 170 // the rrect will have a (0,0) vector at all four corners. So long as the ra
dius > 0.5 they will |
| 164 // correctly produce an alpha value of 1 at all four corners. We take the mi
n of all the alphas. | 171 // correctly produce an alpha value of 1 at all four corners. We take the mi
n of all the alphas. |
| 165 // The code below is a simplified version of the above that performs maxs on
the vector | 172 // The code below is a simplified version of the above that performs maxs on
the vector |
| 166 // components before computing distances and alpha values so that only one d
istance computation | 173 // components before computing distances and alpha values so that only one d
istance computation |
| 167 // need be computed to determine the min alpha. | 174 // need be computed to determine the min alpha. |
| 168 // | 175 // |
| 169 // For the cases where one half of the rrect is rectangular we drop one of t
he x or y | 176 // For the cases where one half of the rrect is rectangular we drop one of t
he x or y |
| 170 // computations, compute a separate rect edge alpha for the rect side, and m
ul the two computed | 177 // computations, compute a separate rect edge alpha for the rect side, and m
ul the two computed |
| 171 // alphas together. | 178 // alphas together. |
| 172 switch (rre.getType()) { | 179 switch (rre.getType()) { |
| 173 case RRectEffect::kCircleCorner_Type: | 180 case RRectEffect::kCircleCorner_RRectType: |
| 174 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); | 181 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); |
| 175 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); | 182 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); |
| 176 builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n")
; | 183 builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n")
; |
| 177 builder->fsCodeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0.
0, 1.0);\n", | 184 builder->fsCodeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0.
0, 1.0);\n", |
| 178 radiusPlusHalfName); | 185 radiusPlusHalfName); |
| 179 break; | 186 break; |
| 180 case RRectEffect::kLeftCircleTab_Type: | 187 case RRectEffect::kLeftCircleTab_RRectType: |
| 181 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); | 188 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); |
| 182 builder->fsCodeAppendf("\t\tfloat dy1 = %s.y - %s.w;\n", fragmentPos
, rectName); | 189 builder->fsCodeAppendf("\t\tfloat dy1 = %s.y - %s.w;\n", fragmentPos
, rectName); |
| 183 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, d
y1)), 0.0);\n"); | 190 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, d
y1)), 0.0);\n"); |
| 184 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.
0, 1.0);\n", | 191 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.
0, 1.0);\n", |
| 185 rectName, fragmentPos); | 192 rectName, fragmentPos); |
| 186 builder->fsCodeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - le
ngth(dxy), 0.0, 1.0);\n", | 193 builder->fsCodeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - le
ngth(dxy), 0.0, 1.0);\n", |
| 187 radiusPlusHalfName); | 194 radiusPlusHalfName); |
| 188 break; | 195 break; |
| 189 case RRectEffect::kTopCircleTab_Type: | 196 case RRectEffect::kTopCircleTab_RRectType: |
| 190 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); | 197 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName,
fragmentPos); |
| 191 builder->fsCodeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentPos
, rectName); | 198 builder->fsCodeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentPos
, rectName); |
| 192 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), dxy
0.y), 0.0);\n"); | 199 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), dxy
0.y), 0.0);\n"); |
| 193 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0
.0, 1.0);\n", | 200 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0
.0, 1.0);\n", |
| 194 rectName, fragmentPos); | 201 rectName, fragmentPos); |
| 195 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - l
ength(dxy), 0.0, 1.0);\n", | 202 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - l
ength(dxy), 0.0, 1.0);\n", |
| 196 radiusPlusHalfName); | 203 radiusPlusHalfName); |
| 197 break; | 204 break; |
| 198 case RRectEffect::kRightCircleTab_Type: | 205 case RRectEffect::kRightCircleTab_RRectType: |
| 199 builder->fsCodeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, f
ragmentPos); | 206 builder->fsCodeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, f
ragmentPos); |
| 200 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); | 207 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); |
| 201 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1
.y)), 0.0);\n"); | 208 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1
.y)), 0.0);\n"); |
| 202 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0
, 1.0);\n", | 209 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0
, 1.0);\n", |
| 203 fragmentPos, rectName); | 210 fragmentPos, rectName); |
| 204 builder->fsCodeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - len
gth(dxy), 0.0, 1.0);\n", | 211 builder->fsCodeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - len
gth(dxy), 0.0, 1.0);\n", |
| 205 radiusPlusHalfName); | 212 radiusPlusHalfName); |
| 206 break; | 213 break; |
| 207 case RRectEffect::kBottomCircleTab_Type: | 214 case RRectEffect::kBottomCircleTab_RRectType: |
| 208 builder->fsCodeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, f
ragmentPos); | 215 builder->fsCodeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, f
ragmentPos); |
| 209 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); | 216 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP
os, rectName); |
| 210 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), dxy
1.y), 0.0);\n"); | 217 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), dxy
1.y), 0.0);\n"); |
| 211 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0,
1.0);\n", | 218 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0,
1.0);\n", |
| 212 fragmentPos, rectName); | 219 fragmentPos, rectName); |
| 213 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - leng
th(dxy), 0.0, 1.0);\n", | 220 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - leng
th(dxy), 0.0, 1.0);\n", |
| 214 radiusPlusHalfName); | 221 radiusPlusHalfName); |
| 215 break; | 222 break; |
| 216 } | 223 } |
| 224 |
| 225 if (kInverseFillAA_EdgeType == rre.getEdgeType()) { |
| 226 builder->fsCodeAppend("\t\talpha = 1.0 - alpha;\n"); |
| 227 } |
| 217 | 228 |
| 218 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, | 229 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, |
| 219 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st
r()); | 230 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st
r()); |
| 220 } | 231 } |
| 221 | 232 |
| 222 GrGLEffect::EffectKey GLRRectEffect::GenKey(const GrDrawEffect& drawEffect, cons
t GrGLCaps&) { | 233 GrGLEffect::EffectKey GLRRectEffect::GenKey(const GrDrawEffect& drawEffect, cons
t GrGLCaps&) { |
| 223 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); | 234 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); |
| 224 return rre.getType(); | 235 GR_STATIC_ASSERT(kEdgeTypeCnt <= 4); |
| 236 return (rre.getType() << 2) | rre.getEdgeType(); |
| 225 } | 237 } |
| 226 | 238 |
| 227 void GLRRectEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect&
drawEffect) { | 239 void GLRRectEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect&
drawEffect) { |
| 228 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); | 240 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); |
| 229 const SkRRect& rrect = rre.getRRect(); | 241 const SkRRect& rrect = rre.getRRect(); |
| 230 if (rrect != fPrevRRect) { | 242 if (rrect != fPrevRRect) { |
| 231 SkRect rect = rrect.getBounds(); | 243 SkRect rect = rrect.getBounds(); |
| 232 SkScalar radius = 0; | 244 SkScalar radius = 0; |
| 233 switch (rre.getType()) { | 245 switch (rre.getType()) { |
| 234 case RRectEffect::kCircleCorner_Type: | 246 case RRectEffect::kCircleCorner_RRectType: |
| 235 SkASSERT(rrect.isSimpleCircular()); | 247 SkASSERT(rrect.isSimpleCircular()); |
| 236 radius = rrect.getSimpleRadii().fX; | 248 radius = rrect.getSimpleRadii().fX; |
| 237 SkASSERT(radius >= RRectEffect::kRadiusMin); | 249 SkASSERT(radius >= RRectEffect::kRadiusMin); |
| 238 rect.inset(radius, radius); | 250 rect.inset(radius, radius); |
| 239 break; | 251 break; |
| 240 case RRectEffect::kLeftCircleTab_Type: | 252 case RRectEffect::kLeftCircleTab_RRectType: |
| 241 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; | 253 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; |
| 242 rect.fLeft += radius; | 254 rect.fLeft += radius; |
| 243 rect.fTop += radius; | 255 rect.fTop += radius; |
| 244 rect.fRight += 0.5f; | 256 rect.fRight += 0.5f; |
| 245 rect.fBottom -= radius; | 257 rect.fBottom -= radius; |
| 246 break; | 258 break; |
| 247 case RRectEffect::kTopCircleTab_Type: | 259 case RRectEffect::kTopCircleTab_RRectType: |
| 248 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; | 260 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; |
| 249 rect.fLeft += radius; | 261 rect.fLeft += radius; |
| 250 rect.fTop += radius; | 262 rect.fTop += radius; |
| 251 rect.fRight -= radius; | 263 rect.fRight -= radius; |
| 252 rect.fBottom += 0.5f; | 264 rect.fBottom += 0.5f; |
| 253 break; | 265 break; |
| 254 case RRectEffect::kRightCircleTab_Type: | 266 case RRectEffect::kRightCircleTab_RRectType: |
| 255 radius = rrect.radii(SkRRect::kUpperRight_Corner).fX; | 267 radius = rrect.radii(SkRRect::kUpperRight_Corner).fX; |
| 256 rect.fLeft -= 0.5f; | 268 rect.fLeft -= 0.5f; |
| 257 rect.fTop += radius; | 269 rect.fTop += radius; |
| 258 rect.fRight -= radius; | 270 rect.fRight -= radius; |
| 259 rect.fBottom -= radius; | 271 rect.fBottom -= radius; |
| 260 break; | 272 break; |
| 261 case RRectEffect::kBottomCircleTab_Type: | 273 case RRectEffect::kBottomCircleTab_RRectType: |
| 262 radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX; | 274 radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX; |
| 263 rect.fLeft += radius; | 275 rect.fLeft += radius; |
| 264 rect.fTop -= 0.5f; | 276 rect.fTop -= 0.5f; |
| 265 rect.fRight -= radius; | 277 rect.fRight -= radius; |
| 266 rect.fBottom -= radius; | 278 rect.fBottom -= radius; |
| 267 break; | 279 break; |
| 268 } | 280 } |
| 269 uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.f
Bottom); | 281 uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.f
Bottom); |
| 270 uman.set1f(fRadiusPlusHalfUniform, radius + 0.5f); | 282 uman.set1f(fRadiusPlusHalfUniform, radius + 0.5f); |
| 271 fPrevRRect = rrect; | 283 fPrevRRect = rrect; |
| 272 } | 284 } |
| 273 } | 285 } |
| 274 | 286 |
| 275 ////////////////////////////////////////////////////////////////////////////// | 287 ////////////////////////////////////////////////////////////////////////////// |
| 276 | 288 |
| 277 GrEffectRef* GrRRectEffect::Create(const SkRRect& rrect) { | 289 GrEffectRef* GrRRectEffect::Create(EdgeType edgeType, const SkRRect& rrect) { |
| 278 RRectEffect::Type type; | 290 RRectEffect::RRectType rrtype; |
| 279 if (rrect.isSimpleCircular()) { | 291 if (rrect.isSimpleCircular()) { |
| 280 if (rrect.getSimpleRadii().fX < RRectEffect::kRadiusMin) { | 292 if (rrect.getSimpleRadii().fX < RRectEffect::kRadiusMin) { |
| 281 return NULL; | 293 return NULL; |
| 282 } | 294 } |
| 283 type = RRectEffect::kCircleCorner_Type; | 295 rrtype = RRectEffect::kCircleCorner_RRectType; |
| 284 } else if (rrect.isComplex()) { | 296 } else if (rrect.isComplex()) { |
| 285 // Check for the "tab" cases - two adjacent circular corners and two squ
are corners. | 297 // Check for the "tab" cases - two adjacent circular corners and two squ
are corners. |
| 286 SkScalar radius = 0; | 298 SkScalar radius = 0; |
| 287 int circleCornerBitfield = 0; | 299 int circleCornerBitfield = 0; |
| 288 for (int c = 0; c < 4; ++c) { | 300 for (int c = 0; c < 4; ++c) { |
| 289 const SkVector& r = rrect.radii((SkRRect::Corner)c); | 301 const SkVector& r = rrect.radii((SkRRect::Corner)c); |
| 290 SkASSERT((0 == r.fX) == (0 == r.fY)); | 302 SkASSERT((0 == r.fX) == (0 == r.fY)); |
| 291 if (0 == r.fX) { | 303 if (0 == r.fX) { |
| 292 continue; | 304 continue; |
| 293 } | 305 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 307 circleCornerBitfield |= 1 << c; | 319 circleCornerBitfield |= 1 << c; |
| 308 } | 320 } |
| 309 } | 321 } |
| 310 | 322 |
| 311 GR_STATIC_ASSERT(SkRRect::kUpperLeft_Corner == 0); | 323 GR_STATIC_ASSERT(SkRRect::kUpperLeft_Corner == 0); |
| 312 GR_STATIC_ASSERT(SkRRect::kUpperRight_Corner == 1); | 324 GR_STATIC_ASSERT(SkRRect::kUpperRight_Corner == 1); |
| 313 GR_STATIC_ASSERT(SkRRect::kLowerRight_Corner == 2); | 325 GR_STATIC_ASSERT(SkRRect::kLowerRight_Corner == 2); |
| 314 GR_STATIC_ASSERT(SkRRect::kLowerLeft_Corner == 3); | 326 GR_STATIC_ASSERT(SkRRect::kLowerLeft_Corner == 3); |
| 315 switch (circleCornerBitfield) { | 327 switch (circleCornerBitfield) { |
| 316 case 3: | 328 case 3: |
| 317 type = RRectEffect::kTopCircleTab_Type; | 329 rrtype = RRectEffect::kTopCircleTab_RRectType; |
| 318 break; | 330 break; |
| 319 case 6: | 331 case 6: |
| 320 type = RRectEffect::kRightCircleTab_Type; | 332 rrtype = RRectEffect::kRightCircleTab_RRectType; |
| 321 break; | 333 break; |
| 322 case 9: | 334 case 9: |
| 323 type = RRectEffect::kLeftCircleTab_Type; | 335 rrtype = RRectEffect::kLeftCircleTab_RRectType; |
| 324 break; | 336 break; |
| 325 case 12: | 337 case 12: |
| 326 type = RRectEffect::kBottomCircleTab_Type; | 338 rrtype = RRectEffect::kBottomCircleTab_RRectType; |
| 327 break; | 339 break; |
| 328 default: | 340 default: |
| 329 return NULL; | 341 return NULL; |
| 330 } | 342 } |
| 331 } else { | 343 } else { |
| 332 return NULL; | 344 return NULL; |
| 333 } | 345 } |
| 334 return RRectEffect::Create(rrect, type); | 346 return RRectEffect::Create(edgeType, rrect, rrtype); |
| 335 } | 347 } |
| OLD | NEW |