Chromium Code Reviews| 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 class GLRRectEffect; | 16 class GLRRectEffect; |
| 17 | 17 |
| 18 class RRectEffect : public GrEffect { | 18 class RRectEffect : public GrEffect { |
| 19 public: | 19 public: |
| 20 // This effect only supports circular corner rrects where all corners have t he same radius | 20 // This effect only supports circular corner rrects where the radius is >= k RadiusMin. |
| 21 // which must be <= kRadiusMin. | |
| 22 static const SkScalar kRadiusMin; | 21 static const SkScalar kRadiusMin; |
| 23 | 22 |
| 24 static GrEffectRef* Create(const SkRRect&); | 23 /// The types of circular corner rrects supported |
| 24 enum Type { | |
| 25 kCircleCorner_Type, //<! All four corners have the same circular rad ius. | |
| 26 kLeftCircleTab_Type, //<! The left side has circular corners and the right is a rect. | |
| 27 kTopCircleTab_Type, //<! etc | |
| 28 kRightCircleTab_Type, | |
| 29 kBottomCircleTab_Type, | |
| 30 }; | |
| 31 | |
| 32 static GrEffectRef* Create(const SkRRect&, Type); | |
| 25 | 33 |
| 26 virtual ~RRectEffect() {}; | 34 virtual ~RRectEffect() {}; |
| 27 static const char* Name() { return "RRect"; } | 35 static const char* Name() { return "RRect"; } |
| 28 | 36 |
| 29 const SkRRect& getRRect() const { return fRRect; } | 37 const SkRRect& getRRect() const { return fRRect; } |
| 30 | 38 |
| 39 Type getType() const { return fType; } | |
| 40 | |
| 31 typedef GLRRectEffect GLEffect; | 41 typedef GLRRectEffect GLEffect; |
| 32 | 42 |
| 33 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags ) const SK_OVERRIDE; | 43 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags ) const SK_OVERRIDE; |
| 34 | 44 |
| 35 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; | 45 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; |
| 36 | 46 |
| 37 private: | 47 private: |
| 38 RRectEffect(const SkRRect&); | 48 RRectEffect(const SkRRect&, Type); |
| 39 | 49 |
| 40 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; | 50 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE; |
| 41 | 51 |
| 52 Type fType; | |
| 42 SkRRect fRRect; | 53 SkRRect fRRect; |
| 43 | 54 |
| 44 GR_DECLARE_EFFECT_TEST; | 55 GR_DECLARE_EFFECT_TEST; |
| 45 | 56 |
| 46 typedef GrEffect INHERITED; | 57 typedef GrEffect INHERITED; |
| 47 }; | 58 }; |
| 48 | 59 |
| 49 const SkScalar RRectEffect::kRadiusMin = 0.5f; | 60 const SkScalar RRectEffect::kRadiusMin = 0.5f; |
| 50 | 61 |
| 51 GrEffectRef* RRectEffect::Create(const SkRRect& rrect) { | 62 GrEffectRef* RRectEffect::Create(const SkRRect& rrect, Type type) { |
| 52 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(RRectEffect, (rrect)))); | 63 return CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(RRectEffect, (rrect, type) ))); |
| 53 } | 64 } |
| 54 | 65 |
| 55 void RRectEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlag s) const { | 66 void RRectEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlag s) const { |
| 56 *validFlags = 0; | 67 *validFlags = 0; |
| 57 } | 68 } |
| 58 | 69 |
| 59 const GrBackendEffectFactory& RRectEffect::getFactory() const { | 70 const GrBackendEffectFactory& RRectEffect::getFactory() const { |
| 60 return GrTBackendEffectFactory<RRectEffect>::getInstance(); | 71 return GrTBackendEffectFactory<RRectEffect>::getInstance(); |
| 61 } | 72 } |
| 62 | 73 |
| 63 RRectEffect::RRectEffect(const SkRRect& rrect) | 74 RRectEffect::RRectEffect(const SkRRect& rrect, Type type) |
| 64 : fRRect(rrect) { | 75 : fRRect(rrect) |
| 76 , fType(type) { | |
| 65 this->setWillReadFragmentPosition(); | 77 this->setWillReadFragmentPosition(); |
| 66 } | 78 } |
| 67 | 79 |
| 68 bool RRectEffect::onIsEqual(const GrEffect& other) const { | 80 bool RRectEffect::onIsEqual(const GrEffect& other) const { |
| 69 const RRectEffect& rre = CastEffect<RRectEffect>(other); | 81 const RRectEffect& rre = CastEffect<RRectEffect>(other); |
| 82 // type is derived from fRRect, so no need to check it. | |
| 70 return fRRect == rre.fRRect; | 83 return fRRect == rre.fRRect; |
| 71 } | 84 } |
| 72 | 85 |
| 73 ////////////////////////////////////////////////////////////////////////////// | 86 ////////////////////////////////////////////////////////////////////////////// |
| 74 | 87 |
| 75 GR_DEFINE_EFFECT_TEST(RRectEffect); | 88 GR_DEFINE_EFFECT_TEST(RRectEffect); |
| 76 | 89 |
| 77 GrEffectRef* RRectEffect::TestCreate(SkRandom* random, | 90 GrEffectRef* RRectEffect::TestCreate(SkRandom* random, |
| 78 GrContext*, | 91 GrContext*, |
| 79 const GrDrawTargetCaps& caps, | 92 const GrDrawTargetCaps& caps, |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 94 GLRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&); | 107 GLRRectEffect(const GrBackendEffectFactory&, const GrDrawEffect&); |
| 95 | 108 |
| 96 virtual void emitCode(GrGLShaderBuilder* builder, | 109 virtual void emitCode(GrGLShaderBuilder* builder, |
| 97 const GrDrawEffect& drawEffect, | 110 const GrDrawEffect& drawEffect, |
| 98 EffectKey key, | 111 EffectKey key, |
| 99 const char* outputColor, | 112 const char* outputColor, |
| 100 const char* inputColor, | 113 const char* inputColor, |
| 101 const TransformedCoordsArray&, | 114 const TransformedCoordsArray&, |
| 102 const TextureSamplerArray&) SK_OVERRIDE; | 115 const TextureSamplerArray&) SK_OVERRIDE; |
| 103 | 116 |
| 104 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&) { retur n 0; } | 117 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); |
| 105 | 118 |
| 106 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE; | 119 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER RIDE; |
| 107 | 120 |
| 108 private: | 121 private: |
| 109 GrGLUniformManager::UniformHandle fInnerRectUniform; | 122 GrGLUniformManager::UniformHandle fInnerRectUniform; |
| 110 GrGLUniformManager::UniformHandle fRadiusPlusHalfUniform; | 123 GrGLUniformManager::UniformHandle fRadiusPlusHalfUniform; |
| 111 SkRRect fPrevRRect; | 124 SkRRect fPrevRRect; |
| 112 typedef GrGLEffect INHERITED; | 125 typedef GrGLEffect INHERITED; |
| 113 }; | 126 }; |
| 114 | 127 |
| 115 GLRRectEffect::GLRRectEffect(const GrBackendEffectFactory& factory, | 128 GLRRectEffect::GLRRectEffect(const GrBackendEffectFactory& factory, |
| 116 const GrDrawEffect& drawEffect) | 129 const GrDrawEffect& drawEffect) |
| 117 : INHERITED (factory) { | 130 : INHERITED (factory) { |
| 118 fPrevRRect.setEmpty(); | 131 fPrevRRect.setEmpty(); |
| 119 } | 132 } |
| 120 | 133 |
| 121 void GLRRectEffect::emitCode(GrGLShaderBuilder* builder, | 134 void GLRRectEffect::emitCode(GrGLShaderBuilder* builder, |
| 122 const GrDrawEffect& drawEffect, | 135 const GrDrawEffect& drawEffect, |
| 123 EffectKey key, | 136 EffectKey key, |
| 124 const char* outputColor, | 137 const char* outputColor, |
| 125 const char* inputColor, | 138 const char* inputColor, |
| 126 const TransformedCoordsArray&, | 139 const TransformedCoordsArray&, |
| 127 const TextureSamplerArray& samplers) { | 140 const TextureSamplerArray& samplers) { |
| 141 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); | |
| 128 const char *rectName; | 142 const char *rectName; |
| 129 const char *radiusPlusHalfName; | 143 const char *radiusPlusHalfName; |
| 130 // The inner rect is the rrect bounds inset by the radius. Its top, left, ri ght, and bottom | 144 // The inner rect is the rrect bounds inset by the radius. Its top, left, ri ght, and bottom |
| 131 // edges correspond to components x, y, z, and w, respectively. | 145 // edges correspond to components x, y, z, and w, respectively. When one sid e of the rrect has |
| 146 // rectangular corners, that side's value corresponds to the rect edge's val ue outset by half a | |
| 147 // pixel. | |
| 132 fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibil ity, | 148 fInnerRectUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibil ity, |
| 133 kVec4f_GrSLType, | 149 kVec4f_GrSLType, |
| 134 "innerRect", | 150 "innerRect", |
| 135 &rectName); | 151 &rectName); |
| 136 fRadiusPlusHalfUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Vi sibility, | 152 fRadiusPlusHalfUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Vi sibility, |
| 137 kFloat_GrSLType, | 153 kFloat_GrSLType, |
| 138 "radiusPlusHalf", | 154 "radiusPlusHalf", |
| 139 &radiusPlusHalfName); | 155 &radiusPlusHalfName); |
| 140 const char* fragmentPos = builder->fragmentPosition(); | 156 const char* fragmentPos = builder->fragmentPosition(); |
| 141 // At each quarter-circle corner we compute a vector that is the offset of t he fragment position | 157 // At each quarter-circle corner we compute a vector that is the offset of t he fragment position |
| 142 // from the circle center. The vector is pinned in x and y to be in the quar ter-plane relevant | 158 // from the circle center. The vector is pinned in x and y to be in the quar ter-plane relevant |
| 143 // to that corner. This means that points near the interior near the rrect t op edge will have | 159 // to that corner. This means that points near the interior near the rrect t op edge will have |
| 144 // a vector that points straight up for both the TL left and TR corners. Com puting an | 160 // a vector that points straight up for both the TL left and TR corners. Com puting an |
| 145 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly, | 161 // alpha from this vector at either the TR or TL corner will give the correc t result. Similarly, |
| 146 // fragments near the other three edges will get the correct AA. Fragments i n the interior of | 162 // fragments near the other three edges will get the correct AA. Fragments i n the interior of |
| 147 // the rrect will have a (0,0) vector at all four corners. So long as the ra dius > 0.5 they will | 163 // the rrect will have a (0,0) vector at all four corners. So long as the ra dius > 0.5 they will |
| 148 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas. | 164 // correctly produce an alpha value of 1 at all four corners. We take the mi n of all the alphas. |
| 149 // The code below is a simplified version of the above that performs maxs on the vector | 165 // The code below is a simplified version of the above that performs maxs on the vector |
| 150 // components before computing distances and alpha values so that only one d istance computation | 166 // components before computing distances and alpha values so that only one d istance computation |
| 151 // need be computed to determine the min alpha. | 167 // need be computed to determine the min alpha. |
| 152 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmen tPos); | 168 // |
| 153 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentPos, rect Name); | 169 // For the cases where one half of the rrect is rectangular we drop one of t he x or y |
| 154 builder->fsCodeAppend("\t\tvec2 dxy = max(max(dxy0, dxy1), 0.0);\n"); | 170 // computations, compute a separate rect edge alpha for the rect side, and m ul the two computed |
| 155 builder->fsCodeAppendf("\t\tfloat alpha = clamp(%s - length(dxy), 0.0, 1.0); \n", | 171 // alphas together. |
| 156 radiusPlusHalfName); | 172 switch (rre.getType()) { |
| 173 case RRectEffect::kCircleCorner_Type: | |
| 174 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); | |
| 176 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", | |
| 178 radiusPlusHalfName); | |
| 179 break; | |
| 180 case RRectEffect::kLeftCircleTab_Type: | |
| 181 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); | |
| 183 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy0.x, max(dxy0.y, d y1)), 0.0);\n"); | |
|
robertphillips
2014/02/21 19:26:36
\n?
bsalomon
2014/02/21 21:20:45
Done. x4
| |
| 184 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0. 0, 1.0);\n", rectName, fragmentPos); | |
| 185 builder->fsCodeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - le ngth(dxy), 0.0, 1.0);\n", | |
| 186 radiusPlusHalfName); | |
| 187 break; | |
| 188 case RRectEffect::kTopCircleTab_Type: | |
| 189 builder->fsCodeAppendf("\t\tvec2 dxy0 = %s.xy - %s.xy;\n", rectName, fragmentPos); | |
| 190 builder->fsCodeAppendf("\t\tfloat dx1 = %s.x - %s.z;\n", fragmentPos , rectName); | |
| 191 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dxy0.x, dx1), dxy 0.y), 0.0);\n"); | |
|
robertphillips
2014/02/21 19:26:36
\n?
| |
| 192 builder->fsCodeAppendf("\t\tfloat bottomAlpha = clamp(%s.w - %s.y, 0 .0, 1.0);\n", rectName, fragmentPos); | |
| 193 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - l ength(dxy), 0.0, 1.0);\n", | |
| 194 radiusPlusHalfName); | |
| 195 break; | |
| 196 case RRectEffect::kRightCircleTab_Type: | |
| 197 builder->fsCodeAppendf("\t\tfloat dy0 = %s.y - %s.y;\n", rectName, f ragmentPos); | |
| 198 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP os, rectName); | |
| 199 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(dxy1.x, max(dy0, dxy1 .y)), 0.0);\n"); | |
|
robertphillips
2014/02/21 19:26:36
\n?
| |
| 200 builder->fsCodeAppendf("\t\tfloat leftAlpha = clamp(%s.x - %s.x, 0.0 , 1.0);\n", fragmentPos, rectName); | |
| 201 builder->fsCodeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - len gth(dxy), 0.0, 1.0);\n", | |
| 202 radiusPlusHalfName); | |
| 203 break; | |
| 204 case RRectEffect::kBottomCircleTab_Type: | |
| 205 builder->fsCodeAppendf("\t\tfloat dx0 = %s.x - %s.x;\n", rectName, f ragmentPos); | |
| 206 builder->fsCodeAppendf("\t\tvec2 dxy1 = %s.xy - %s.zw;\n", fragmentP os, rectName); | |
| 207 builder->fsCodeAppend("\t\tvec2 dxy = max(vec2(max(dx0, dxy1.x), dxy 1.y), 0.0);\n"); | |
|
robertphillips
2014/02/21 19:26:36
\n?
| |
| 208 builder->fsCodeAppendf("\t\tfloat topAlpha = clamp(%s.y - %s.y, 0.0, 1.0);\n", fragmentPos, rectName); | |
| 209 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - leng th(dxy), 0.0, 1.0);\n", | |
| 210 radiusPlusHalfName); | |
| 211 break; | |
| 212 } | |
| 157 | 213 |
| 158 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, | 214 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, |
| 159 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st r()); | 215 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st r()); |
| 160 } | 216 } |
| 161 | 217 |
| 218 GrGLEffect::EffectKey GLRRectEffect::GenKey(const GrDrawEffect& drawEffect, cons t GrGLCaps&) { | |
| 219 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); | |
| 220 return rre.getType(); | |
| 221 } | |
| 222 | |
| 162 void GLRRectEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) { | 223 void GLRRectEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) { |
| 163 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); | 224 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); |
| 164 const SkRRect& rrect = rre.getRRect(); | 225 const SkRRect& rrect = rre.getRRect(); |
| 165 if (rrect != fPrevRRect) { | 226 if (rrect != fPrevRRect) { |
| 166 SkASSERT(rrect.isSimpleCircular()); | |
| 167 SkRect rect = rrect.getBounds(); | 227 SkRect rect = rrect.getBounds(); |
| 168 SkScalar radius = rrect.getSimpleRadii().fX; | 228 SkScalar radius; |
| 169 SkASSERT(radius >= RRectEffect::kRadiusMin); | 229 switch (rre.getType()) { |
| 170 rect.inset(radius, radius); | 230 case RRectEffect::kCircleCorner_Type: |
| 231 SkASSERT(rrect.isSimpleCircular()); | |
| 232 radius = rrect.getSimpleRadii().fX; | |
| 233 SkASSERT(radius >= RRectEffect::kRadiusMin); | |
| 234 rect.inset(radius, radius); | |
| 235 break; | |
| 236 case RRectEffect::kLeftCircleTab_Type: | |
| 237 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; | |
| 238 rect.fLeft += radius; | |
| 239 rect.fTop += radius; | |
| 240 rect.fRight += 0.5f; | |
| 241 rect.fBottom -= radius; | |
| 242 break; | |
| 243 case RRectEffect::kTopCircleTab_Type: | |
| 244 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; | |
| 245 rect.fLeft += radius; | |
| 246 rect.fTop += radius; | |
| 247 rect.fRight -= radius; | |
| 248 rect.fBottom += 0.5f; | |
| 249 break; | |
| 250 case RRectEffect::kRightCircleTab_Type: | |
| 251 radius = rrect.radii(SkRRect::kUpperRight_Corner).fX; | |
| 252 rect.fLeft -= 0.5f; | |
| 253 rect.fTop += radius; | |
| 254 rect.fRight -= radius; | |
| 255 rect.fBottom -= radius; | |
| 256 break; | |
| 257 case RRectEffect::kBottomCircleTab_Type: | |
| 258 radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX; | |
| 259 rect.fLeft += radius; | |
| 260 rect.fTop -= 0.5f; | |
| 261 rect.fRight -= radius; | |
| 262 rect.fBottom -= radius; | |
| 263 break; | |
| 264 } | |
| 171 uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.f Bottom); | 265 uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.f Bottom); |
| 172 uman.set1f(fRadiusPlusHalfUniform, radius + 0.5f); | 266 uman.set1f(fRadiusPlusHalfUniform, radius + 0.5f); |
| 173 fPrevRRect = rrect; | 267 fPrevRRect = rrect; |
| 174 } | 268 } |
| 175 } | 269 } |
| 176 | 270 |
| 177 ////////////////////////////////////////////////////////////////////////////// | 271 ////////////////////////////////////////////////////////////////////////////// |
| 178 | 272 |
| 179 GrEffectRef* GrRRectEffect::Create(const SkRRect& rrect) { | 273 GrEffectRef* GrRRectEffect::Create(const SkRRect& rrect) { |
| 180 if (!rrect.isSimpleCircular()) { | 274 RRectEffect::Type type; |
| 275 if (rrect.isSimpleCircular()) { | |
| 276 if (rrect.getSimpleRadii().fX < RRectEffect::kRadiusMin) { | |
| 277 return NULL; | |
| 278 } | |
| 279 type = RRectEffect::kCircleCorner_Type; | |
| 280 } else if (rrect.isComplex()) { | |
| 281 // Check for the "tab" cases - two adjacent circular corners and two squ are corners. | |
| 282 SkScalar radius; | |
| 283 int circleCornerBitfield = 0; | |
| 284 for (int c = 0; c < 4; ++c) { | |
| 285 const SkVector& r = rrect.radii((SkRRect::Corner)c); | |
| 286 SkASSERT((0 == r.fX) == (0 == r.fY)); | |
| 287 if (0 == r.fX) { | |
| 288 continue; | |
| 289 } | |
| 290 if (r.fX != r.fY) { | |
| 291 circleCornerBitfield = 0; | |
|
robertphillips
2014/02/21 19:26:36
just return NULL here?
bsalomon
2014/02/21 21:20:45
Done. x3
| |
| 292 break; | |
| 293 } | |
| 294 if (!circleCornerBitfield) { | |
| 295 radius = r.fX; | |
| 296 if (radius < RRectEffect::kRadiusMin) { | |
|
robertphillips
2014/02/21 19:26:36
can't we just return NULL here?
| |
| 297 break; | |
| 298 } | |
| 299 circleCornerBitfield = 1 << c; | |
| 300 } else { | |
| 301 if (r.fX != radius) { | |
| 302 circleCornerBitfield = 0; | |
| 303 break; | |
| 304 } | |
| 305 circleCornerBitfield |= 1 << c; | |
| 306 } | |
| 307 } | |
| 308 | |
| 309 GR_STATIC_ASSERT(SkRRect::kUpperLeft_Corner == 0); | |
| 310 GR_STATIC_ASSERT(SkRRect::kUpperRight_Corner == 1); | |
| 311 GR_STATIC_ASSERT(SkRRect::kLowerRight_Corner == 2); | |
| 312 GR_STATIC_ASSERT(SkRRect::kLowerLeft_Corner == 3); | |
| 313 switch (circleCornerBitfield) { | |
| 314 case 3: | |
| 315 type = RRectEffect::kTopCircleTab_Type; | |
| 316 break; | |
| 317 case 6: | |
| 318 type = RRectEffect::kRightCircleTab_Type; | |
| 319 break; | |
| 320 case 9: | |
| 321 type = RRectEffect::kLeftCircleTab_Type; | |
| 322 break; | |
| 323 case 12: | |
| 324 type = RRectEffect::kBottomCircleTab_Type; | |
| 325 break; | |
| 326 default: | |
| 327 return NULL; | |
| 328 } | |
| 329 } else { | |
| 181 return NULL; | 330 return NULL; |
| 182 } | 331 } |
| 183 | 332 return RRectEffect::Create(rrect, type); |
| 184 if (rrect.getSimpleRadii().fX < RRectEffect::kRadiusMin) { | |
| 185 return NULL; | |
| 186 } | |
| 187 | |
| 188 return RRectEffect::Create(rrect); | |
| 189 } | 333 } |
| OLD | NEW |