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 |
42 SkRRect fRRect; | 52 SkRRect fRRect; |
| 53 Type fType; |
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"); |
| 184 builder->fsCodeAppendf("\t\tfloat rightAlpha = clamp(%s.z - %s.x, 0.
0, 1.0);\n", |
| 185 rectName, fragmentPos); |
| 186 builder->fsCodeAppendf("\t\tfloat alpha = rightAlpha * clamp(%s - le
ngth(dxy), 0.0, 1.0);\n", |
| 187 radiusPlusHalfName); |
| 188 break; |
| 189 case RRectEffect::kTopCircleTab_Type: |
| 190 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); |
| 192 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", |
| 194 rectName, fragmentPos); |
| 195 builder->fsCodeAppendf("\t\tfloat alpha = bottomAlpha * clamp(%s - l
ength(dxy), 0.0, 1.0);\n", |
| 196 radiusPlusHalfName); |
| 197 break; |
| 198 case RRectEffect::kRightCircleTab_Type: |
| 199 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); |
| 201 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", |
| 203 fragmentPos, rectName); |
| 204 builder->fsCodeAppendf("\t\tfloat alpha = leftAlpha * clamp(%s - len
gth(dxy), 0.0, 1.0);\n", |
| 205 radiusPlusHalfName); |
| 206 break; |
| 207 case RRectEffect::kBottomCircleTab_Type: |
| 208 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); |
| 210 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", |
| 212 fragmentPos, rectName); |
| 213 builder->fsCodeAppendf("\t\tfloat alpha = topAlpha * clamp(%s - leng
th(dxy), 0.0, 1.0);\n", |
| 214 radiusPlusHalfName); |
| 215 break; |
| 216 } |
157 | 217 |
158 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, | 218 builder->fsCodeAppendf("\t\t%s = %s;\n", outputColor, |
159 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st
r()); | 219 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_st
r()); |
160 } | 220 } |
161 | 221 |
| 222 GrGLEffect::EffectKey GLRRectEffect::GenKey(const GrDrawEffect& drawEffect, cons
t GrGLCaps&) { |
| 223 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); |
| 224 return rre.getType(); |
| 225 } |
| 226 |
162 void GLRRectEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect&
drawEffect) { | 227 void GLRRectEffect::setData(const GrGLUniformManager& uman, const GrDrawEffect&
drawEffect) { |
163 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); | 228 const RRectEffect& rre = drawEffect.castEffect<RRectEffect>(); |
164 const SkRRect& rrect = rre.getRRect(); | 229 const SkRRect& rrect = rre.getRRect(); |
165 if (rrect != fPrevRRect) { | 230 if (rrect != fPrevRRect) { |
166 SkASSERT(rrect.isSimpleCircular()); | |
167 SkRect rect = rrect.getBounds(); | 231 SkRect rect = rrect.getBounds(); |
168 SkScalar radius = rrect.getSimpleRadii().fX; | 232 SkScalar radius = 0; |
169 SkASSERT(radius >= RRectEffect::kRadiusMin); | 233 switch (rre.getType()) { |
170 rect.inset(radius, radius); | 234 case RRectEffect::kCircleCorner_Type: |
| 235 SkASSERT(rrect.isSimpleCircular()); |
| 236 radius = rrect.getSimpleRadii().fX; |
| 237 SkASSERT(radius >= RRectEffect::kRadiusMin); |
| 238 rect.inset(radius, radius); |
| 239 break; |
| 240 case RRectEffect::kLeftCircleTab_Type: |
| 241 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; |
| 242 rect.fLeft += radius; |
| 243 rect.fTop += radius; |
| 244 rect.fRight += 0.5f; |
| 245 rect.fBottom -= radius; |
| 246 break; |
| 247 case RRectEffect::kTopCircleTab_Type: |
| 248 radius = rrect.radii(SkRRect::kUpperLeft_Corner).fX; |
| 249 rect.fLeft += radius; |
| 250 rect.fTop += radius; |
| 251 rect.fRight -= radius; |
| 252 rect.fBottom += 0.5f; |
| 253 break; |
| 254 case RRectEffect::kRightCircleTab_Type: |
| 255 radius = rrect.radii(SkRRect::kUpperRight_Corner).fX; |
| 256 rect.fLeft -= 0.5f; |
| 257 rect.fTop += radius; |
| 258 rect.fRight -= radius; |
| 259 rect.fBottom -= radius; |
| 260 break; |
| 261 case RRectEffect::kBottomCircleTab_Type: |
| 262 radius = rrect.radii(SkRRect::kLowerLeft_Corner).fX; |
| 263 rect.fLeft += radius; |
| 264 rect.fTop -= 0.5f; |
| 265 rect.fRight -= radius; |
| 266 rect.fBottom -= radius; |
| 267 break; |
| 268 } |
171 uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.f
Bottom); | 269 uman.set4f(fInnerRectUniform, rect.fLeft, rect.fTop, rect.fRight, rect.f
Bottom); |
172 uman.set1f(fRadiusPlusHalfUniform, radius + 0.5f); | 270 uman.set1f(fRadiusPlusHalfUniform, radius + 0.5f); |
173 fPrevRRect = rrect; | 271 fPrevRRect = rrect; |
174 } | 272 } |
175 } | 273 } |
176 | 274 |
177 ////////////////////////////////////////////////////////////////////////////// | 275 ////////////////////////////////////////////////////////////////////////////// |
178 | 276 |
179 GrEffectRef* GrRRectEffect::Create(const SkRRect& rrect) { | 277 GrEffectRef* GrRRectEffect::Create(const SkRRect& rrect) { |
180 if (!rrect.isSimpleCircular()) { | 278 RRectEffect::Type type; |
| 279 if (rrect.isSimpleCircular()) { |
| 280 if (rrect.getSimpleRadii().fX < RRectEffect::kRadiusMin) { |
| 281 return NULL; |
| 282 } |
| 283 type = RRectEffect::kCircleCorner_Type; |
| 284 } else if (rrect.isComplex()) { |
| 285 // Check for the "tab" cases - two adjacent circular corners and two squ
are corners. |
| 286 SkScalar radius = 0; |
| 287 int circleCornerBitfield = 0; |
| 288 for (int c = 0; c < 4; ++c) { |
| 289 const SkVector& r = rrect.radii((SkRRect::Corner)c); |
| 290 SkASSERT((0 == r.fX) == (0 == r.fY)); |
| 291 if (0 == r.fX) { |
| 292 continue; |
| 293 } |
| 294 if (r.fX != r.fY) { |
| 295 return NULL; |
| 296 } |
| 297 if (!circleCornerBitfield) { |
| 298 radius = r.fX; |
| 299 if (radius < RRectEffect::kRadiusMin) { |
| 300 return NULL; |
| 301 } |
| 302 circleCornerBitfield = 1 << c; |
| 303 } else { |
| 304 if (r.fX != radius) { |
| 305 return NULL; |
| 306 } |
| 307 circleCornerBitfield |= 1 << c; |
| 308 } |
| 309 } |
| 310 |
| 311 GR_STATIC_ASSERT(SkRRect::kUpperLeft_Corner == 0); |
| 312 GR_STATIC_ASSERT(SkRRect::kUpperRight_Corner == 1); |
| 313 GR_STATIC_ASSERT(SkRRect::kLowerRight_Corner == 2); |
| 314 GR_STATIC_ASSERT(SkRRect::kLowerLeft_Corner == 3); |
| 315 switch (circleCornerBitfield) { |
| 316 case 3: |
| 317 type = RRectEffect::kTopCircleTab_Type; |
| 318 break; |
| 319 case 6: |
| 320 type = RRectEffect::kRightCircleTab_Type; |
| 321 break; |
| 322 case 9: |
| 323 type = RRectEffect::kLeftCircleTab_Type; |
| 324 break; |
| 325 case 12: |
| 326 type = RRectEffect::kBottomCircleTab_Type; |
| 327 break; |
| 328 default: |
| 329 return NULL; |
| 330 } |
| 331 } else { |
181 return NULL; | 332 return NULL; |
182 } | 333 } |
183 | 334 return RRectEffect::Create(rrect, type); |
184 if (rrect.getSimpleRadii().fX < RRectEffect::kRadiusMin) { | |
185 return NULL; | |
186 } | |
187 | |
188 return RRectEffect::Create(rrect); | |
189 } | 335 } |
OLD | NEW |