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 |