OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 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 "GrOvalRenderer.h" | 8 #include "GrOvalRenderer.h" |
9 | 9 |
10 #include "effects/GrCircleEdgeEffect.h" | 10 #include "GrEffect.h" |
11 #include "effects/GrEllipseEdgeEffect.h" | 11 #include "gl/GrGLEffect.h" |
12 #include "gl/GrGLSL.h" | |
13 #include "GrTBackendEffectFactory.h" | |
12 | 14 |
13 #include "GrDrawState.h" | 15 #include "GrDrawState.h" |
14 #include "GrDrawTarget.h" | 16 #include "GrDrawTarget.h" |
15 #include "SkStrokeRec.h" | 17 #include "SkStrokeRec.h" |
16 | 18 |
17 SK_DEFINE_INST_COUNT(GrOvalRenderer) | 19 SK_DEFINE_INST_COUNT(GrOvalRenderer) |
18 | 20 |
19 namespace { | 21 namespace { |
20 | 22 |
21 struct CircleVertex { | 23 struct CircleVertex { |
(...skipping 11 matching lines...) Expand all Loading... | |
33 SkScalar fInnerXRadius; | 35 SkScalar fInnerXRadius; |
34 SkScalar fInnerXYRatio; | 36 SkScalar fInnerXYRatio; |
35 }; | 37 }; |
36 | 38 |
37 inline bool circle_stays_circle(const SkMatrix& m) { | 39 inline bool circle_stays_circle(const SkMatrix& m) { |
38 return m.isSimilarity(); | 40 return m.isSimilarity(); |
39 } | 41 } |
40 | 42 |
41 } | 43 } |
42 | 44 |
45 /////////////////////////////////////////////////////////////////////////////// | |
46 | |
47 /** | |
48 * The output of this effect is a modulation of the input color and coverage for a circle, | |
49 * specified as center_x, center_y, x_radius, inner radius and outer radius in w indow space | |
50 * (y-down). | |
51 */ | |
52 | |
53 class CircleEdgeEffect : public GrEffect { | |
54 public: | |
55 static GrEffectRef* Create(bool stroke) { | |
56 // we go through this so we only have one copy of each effect (stroked/f illed) | |
57 static SkAutoTUnref<GrEffectRef> gCircleStrokeEdgeEffectRef( | |
58 CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(CircleEdgeEff ect, (true))))); | |
59 static SkAutoTUnref<GrEffectRef> gCircleFillEdgeEffectRef( | |
60 CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(CircleEdgeEff ect, (false))))); | |
61 | |
62 if (stroke) { | |
63 gCircleStrokeEdgeEffectRef.get()->ref(); | |
64 return gCircleStrokeEdgeEffectRef; | |
65 } else { | |
66 gCircleFillEdgeEffectRef.get()->ref(); | |
67 return gCircleFillEdgeEffectRef; | |
68 } | |
69 } | |
70 | |
71 virtual void getConstantColorComponents(GrColor* color, | |
72 uint32_t* validFlags) const SK_OVERR IDE { | |
73 *validFlags = 0; | |
74 } | |
75 | |
76 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { | |
77 return GrTBackendEffectFactory<CircleEdgeEffect>::getInstance(); | |
78 } | |
79 | |
80 virtual ~CircleEdgeEffect() {} | |
81 | |
82 static const char* Name() { return "CircleEdge"; } | |
83 | |
84 inline bool isStroked() const { return fStroke; } | |
85 | |
86 class GLEffect : public GrGLEffect { | |
87 public: | |
88 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) | |
89 : INHERITED (factory) {} | |
90 | |
91 virtual void emitCode(GrGLShaderBuilder* builder, | |
92 const GrDrawEffect& drawEffect, | |
93 EffectKey key, | |
94 const char* outputColor, | |
95 const char* inputColor, | |
96 const TextureSamplerArray& samplers) SK_OVERRIDE { | |
97 const CircleEdgeEffect& circleEffect = drawEffect.castEffect<CircleE dgeEffect>(); | |
98 const char *vsName, *fsName; | |
99 builder->addVarying(kVec4f_GrSLType, "CircleEdge", &vsName, &fsName) ; | |
100 | |
101 const SkString* attrName = | |
102 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[0]); | |
103 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); | |
104 | |
105 builder->fsCodeAppendf("\tfloat d = distance(%s.xy, %s.xy);\n", | |
106 builder->fragmentPosition(), fsName); | |
107 builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0 );\n", fsName); | |
108 if (circleEffect.isStroked()) { | |
109 builder->fsCodeAppendf("\tfloat innerAlpha = clamp(d - %s.w, 0.0 , 1.0);\n", fsName); | |
110 builder->fsCodeAppend("\tedgeAlpha *= innerAlpha;\n"); | |
111 } | |
112 SkString modulate; | |
113 GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha"); | |
114 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str() ); | |
115 } | |
116 | |
117 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) { | |
118 const CircleEdgeEffect& circleEffect = drawEffect.castEffect<CircleE dgeEffect>(); | |
119 | |
120 return circleEffect.isStroked() ? 0x1 : 0x0; | |
121 } | |
122 | |
123 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_ OVERRIDE { | |
robertphillips
2013/03/31 22:59:08
put this '}' on prior line?
| |
124 } | |
125 | |
126 private: | |
127 typedef GrGLEffect INHERITED; | |
128 }; | |
129 | |
130 | |
131 private: | |
132 CircleEdgeEffect(bool stroke) : GrEffect() { | |
133 this->addVertexAttrib(kVec4f_GrSLType); | |
134 fStroke = stroke; | |
135 } | |
136 | |
137 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { | |
138 const CircleEdgeEffect& cee = CastEffect<CircleEdgeEffect>(other); | |
139 return cee.fStroke == fStroke; | |
140 } | |
141 | |
142 bool fStroke; | |
143 | |
144 GR_DECLARE_EFFECT_TEST; | |
145 | |
146 typedef GrEffect INHERITED; | |
147 }; | |
148 | |
149 GR_DEFINE_EFFECT_TEST(CircleEdgeEffect); | |
150 | |
151 GrEffectRef* CircleEdgeEffect::TestCreate(SkMWCRandom* random, | |
152 GrContext* context, | |
153 const GrDrawTargetCaps&, | |
154 GrTexture* textures[]) { | |
155 return CircleEdgeEffect::Create(random->nextBool()); | |
156 } | |
157 | |
158 /////////////////////////////////////////////////////////////////////////////// | |
159 | |
160 /** | |
161 * The output of this effect is a modulation of the input color and coverage for an axis-aligned | |
162 * ellipse, specified as center_x, center_y, x_radius, x_radius/y_radius in wind ow space (y-down). | |
163 */ | |
164 | |
165 class EllipseEdgeEffect : public GrEffect { | |
166 public: | |
167 static GrEffectRef* Create(bool stroke) { | |
168 // we go through this so we only have one copy of each effect (stroked/f illed) | |
169 static SkAutoTUnref<GrEffectRef> gEllipseStrokeEdgeEffectRef( | |
170 CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipseEdgeEf fect, (true))))); | |
171 static SkAutoTUnref<GrEffectRef> gEllipseFillEdgeEffectRef( | |
172 CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipseEdgeEf fect, (false))))); | |
173 | |
174 if (stroke) { | |
175 gEllipseStrokeEdgeEffectRef.get()->ref(); | |
176 return gEllipseStrokeEdgeEffectRef; | |
177 } else { | |
178 gEllipseFillEdgeEffectRef.get()->ref(); | |
179 return gEllipseFillEdgeEffectRef; | |
180 } | |
181 } | |
182 | |
183 virtual void getConstantColorComponents(GrColor* color, | |
184 uint32_t* validFlags) const SK_OVERR IDE { | |
185 *validFlags = 0; | |
186 } | |
187 | |
188 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { | |
189 return GrTBackendEffectFactory<EllipseEdgeEffect>::getInstance(); | |
190 } | |
191 | |
192 virtual ~EllipseEdgeEffect() {} | |
193 | |
194 static const char* Name() { return "EllipseEdge"; } | |
195 | |
196 inline bool isStroked() const { return fStroke; } | |
197 | |
198 class GLEffect : public GrGLEffect { | |
199 public: | |
200 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) | |
201 : INHERITED (factory) {} | |
202 | |
203 virtual void emitCode(GrGLShaderBuilder* builder, | |
204 const GrDrawEffect& drawEffect, | |
205 EffectKey key, | |
206 const char* outputColor, | |
207 const char* inputColor, | |
208 const TextureSamplerArray& samplers) SK_OVERRIDE { | |
209 const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<Ellip seEdgeEffect>(); | |
210 | |
211 const char *vsCenterName, *fsCenterName; | |
212 const char *vsEdgeName, *fsEdgeName; | |
213 | |
214 builder->addVarying(kVec2f_GrSLType, "EllipseCenter", &vsCenterName, &fsCenterName); | |
215 const SkString* attr0Name = | |
216 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[0]); | |
217 builder->vsCodeAppendf("\t%s = %s;\n", vsCenterName, attr0Name->c_st r()); | |
218 | |
219 builder->addVarying(kVec4f_GrSLType, "EllipseEdge", &vsEdgeName, &fs EdgeName); | |
220 const SkString* attr1Name = | |
221 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[1]); | |
222 builder->vsCodeAppendf("\t%s = %s;\n", vsEdgeName, attr1Name->c_str( )); | |
223 | |
224 // translate to origin | |
225 builder->fsCodeAppendf("\tvec2 outerOffset = (%s.xy - %s.xy);\n", | |
226 builder->fragmentPosition(), fsCenterName); | |
227 builder->fsCodeAppend("\tvec2 innerOffset = outerOffset;\n"); | |
228 // scale y by xRadius/yRadius | |
229 builder->fsCodeAppendf("\touterOffset.y *= %s.y;\n", fsEdgeName); | |
230 builder->fsCodeAppend("\tfloat dOuter = length(outerOffset);\n"); | |
231 // compare outer lengths against xOuterRadius | |
232 builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.x-dOuter, 0.0, 1.0);\n", fsEdgeName); | |
233 | |
234 if (ellipseEffect.isStroked()) { | |
235 builder->fsCodeAppendf("\tinnerOffset.y *= %s.w;\n", fsEdgeName) ; | |
236 builder->fsCodeAppend("\tfloat dInner = length(innerOffset);\n") ; | |
237 | |
238 // compare inner lengths against xInnerRadius | |
robertphillips
2013/03/31 22:59:08
overlength
| |
239 builder->fsCodeAppendf("\tfloat innerAlpha = clamp(dInner-%s.z, 0.0, 1.0);\n", fsEdgeName); | |
240 builder->fsCodeAppend("\tedgeAlpha *= innerAlpha;\n"); | |
241 } | |
242 | |
243 SkString modulate; | |
244 GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha"); | |
245 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str() ); | |
246 } | |
247 | |
248 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) { | |
249 const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<Ellip seEdgeEffect>(); | |
250 | |
251 return ellipseEffect.isStroked() ? 0x1 : 0x0; | |
252 } | |
253 | |
254 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_ OVERRIDE { | |
255 } | |
256 | |
257 private: | |
258 typedef GrGLEffect INHERITED; | |
259 }; | |
260 | |
261 private: | |
262 EllipseEdgeEffect(bool stroke) : GrEffect() { | |
263 this->addVertexAttrib(kVec2f_GrSLType); | |
264 this->addVertexAttrib(kVec4f_GrSLType); | |
265 fStroke = stroke; | |
266 } | |
267 | |
268 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { | |
269 const EllipseEdgeEffect& eee = CastEffect<EllipseEdgeEffect>(other); | |
270 return eee.fStroke == fStroke; | |
271 } | |
272 | |
273 bool fStroke; | |
274 | |
275 GR_DECLARE_EFFECT_TEST; | |
276 | |
277 typedef GrEffect INHERITED; | |
278 }; | |
279 | |
280 GR_DEFINE_EFFECT_TEST(EllipseEdgeEffect); | |
281 | |
282 GrEffectRef* EllipseEdgeEffect::TestCreate(SkMWCRandom* random, | |
283 GrContext* context, | |
284 const GrDrawTargetCaps&, | |
285 GrTexture* textures[]) { | |
286 return EllipseEdgeEffect::Create(random->nextBool()); | |
287 } | |
288 | |
289 /////////////////////////////////////////////////////////////////////////////// | |
290 | |
43 bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, co nst GrPaint& paint, | 291 bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, co nst GrPaint& paint, |
44 const GrRect& oval, const SkStrokeRec& stroke) | 292 const GrRect& oval, const SkStrokeRec& stroke) |
45 { | 293 { |
46 if (!paint.isAntiAlias()) { | 294 if (!paint.isAntiAlias()) { |
47 return false; | 295 return false; |
48 } | 296 } |
49 | 297 |
50 const SkMatrix& vm = context->getMatrix(); | 298 const SkMatrix& vm = context->getMatrix(); |
51 | 299 |
52 // we can draw circles | 300 // we can draw circles |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
103 SkStrokeRec::Style style = stroke.getStyle(); | 351 SkStrokeRec::Style style = stroke.getStyle(); |
104 bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairl ine_Style == style); | 352 bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairl ine_Style == style); |
105 enum { | 353 enum { |
106 // the edge effects share this stage with glyph rendering | 354 // the edge effects share this stage with glyph rendering |
107 // (kGlyphMaskStage in GrTextContext) && SW path rendering | 355 // (kGlyphMaskStage in GrTextContext) && SW path rendering |
108 // (kPathMaskStage in GrSWMaskHelper) | 356 // (kPathMaskStage in GrSWMaskHelper) |
109 kEdgeEffectStage = GrPaint::kTotalStages, | 357 kEdgeEffectStage = GrPaint::kTotalStages, |
110 }; | 358 }; |
111 drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings); | 359 drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings); |
112 | 360 |
113 GrEffectRef* effect = GrCircleEdgeEffect::Create(isStroked); | 361 GrEffectRef* effect = CircleEdgeEffect::Create(isStroked); |
114 static const int kCircleEdgeAttrIndex = 1; | 362 static const int kCircleEdgeAttrIndex = 1; |
115 drawState->setEffect(kEdgeEffectStage, effect, kCircleEdgeAttrIndex)->unref( ); | 363 drawState->setEffect(kEdgeEffectStage, effect, kCircleEdgeAttrIndex)->unref( ); |
116 | 364 |
117 SkScalar innerRadius = 0.0f; | 365 SkScalar innerRadius = 0.0f; |
118 SkScalar outerRadius = radius; | 366 SkScalar outerRadius = radius; |
119 SkScalar halfWidth = 0; | 367 SkScalar halfWidth = 0; |
120 if (style != SkStrokeRec::kFill_Style) { | 368 if (style != SkStrokeRec::kFill_Style) { |
121 if (SkScalarNearlyZero(strokeWidth)) { | 369 if (SkScalarNearlyZero(strokeWidth)) { |
122 halfWidth = SK_ScalarHalf; | 370 halfWidth = SK_ScalarHalf; |
123 } else { | 371 } else { |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
202 SkStrokeRec::Style style = stroke.getStyle(); | 450 SkStrokeRec::Style style = stroke.getStyle(); |
203 bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairl ine_Style == style); | 451 bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairl ine_Style == style); |
204 enum { | 452 enum { |
205 // the edge effects share this stage with glyph rendering | 453 // the edge effects share this stage with glyph rendering |
206 // (kGlyphMaskStage in GrTextContext) && SW path rendering | 454 // (kGlyphMaskStage in GrTextContext) && SW path rendering |
207 // (kPathMaskStage in GrSWMaskHelper) | 455 // (kPathMaskStage in GrSWMaskHelper) |
208 kEdgeEffectStage = GrPaint::kTotalStages, | 456 kEdgeEffectStage = GrPaint::kTotalStages, |
209 }; | 457 }; |
210 drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings); | 458 drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings); |
211 | 459 |
212 GrEffectRef* effect = GrEllipseEdgeEffect::Create(isStroked); | 460 GrEffectRef* effect = EllipseEdgeEffect::Create(isStroked); |
213 static const int kEllipseCenterAttrIndex = 1; | 461 static const int kEllipseCenterAttrIndex = 1; |
214 static const int kEllipseEdgeAttrIndex = 2; | 462 static const int kEllipseEdgeAttrIndex = 2; |
215 drawState->setEffect(kEdgeEffectStage, effect, | 463 drawState->setEffect(kEdgeEffectStage, effect, |
216 kEllipseCenterAttrIndex, kEllipseEdgeAttrIndex)->unref( ); | 464 kEllipseCenterAttrIndex, kEllipseEdgeAttrIndex)->unref( ); |
217 | 465 |
218 SkScalar xRadius = SkScalarHalf(xformedRect.width()); | 466 SkScalar xRadius = SkScalarHalf(xformedRect.width()); |
219 SkScalar yRadius = SkScalarHalf(xformedRect.height()); | 467 SkScalar yRadius = SkScalarHalf(xformedRect.height()); |
220 SkScalar innerXRadius = 0.0f; | 468 SkScalar innerXRadius = 0.0f; |
221 SkScalar innerRatio = 1.0f; | 469 SkScalar innerRatio = 1.0f; |
222 | 470 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
268 T += center.fY - SK_ScalarHalf; | 516 T += center.fY - SK_ScalarHalf; |
269 B += center.fY + SK_ScalarHalf; | 517 B += center.fY + SK_ScalarHalf; |
270 | 518 |
271 verts[0].fPos = SkPoint::Make(L, T); | 519 verts[0].fPos = SkPoint::Make(L, T); |
272 verts[1].fPos = SkPoint::Make(R, T); | 520 verts[1].fPos = SkPoint::Make(R, T); |
273 verts[2].fPos = SkPoint::Make(L, B); | 521 verts[2].fPos = SkPoint::Make(L, B); |
274 verts[3].fPos = SkPoint::Make(R, B); | 522 verts[3].fPos = SkPoint::Make(R, B); |
275 | 523 |
276 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4); | 524 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4); |
277 } | 525 } |
OLD | NEW |