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 "GrEffect.h" | 10 #include "GrEffect.h" |
11 #include "gl/GrGLEffect.h" | 11 #include "gl/GrGLEffect.h" |
12 #include "gl/GrGLSL.h" | 12 #include "gl/GrGLSL.h" |
13 #include "GrTBackendEffectFactory.h" | 13 #include "GrTBackendEffectFactory.h" |
14 | 14 |
15 #include "GrDrawState.h" | 15 #include "GrDrawState.h" |
16 #include "GrDrawTarget.h" | 16 #include "GrDrawTarget.h" |
17 #include "SkStrokeRec.h" | 17 #include "SkStrokeRec.h" |
18 | 18 |
19 SK_DEFINE_INST_COUNT(GrOvalRenderer) | 19 SK_DEFINE_INST_COUNT(GrOvalRenderer) |
20 | 20 |
21 namespace { | 21 namespace { |
22 | 22 |
23 struct CircleVertex { | 23 struct CircleVertex { |
24 GrPoint fPos; | 24 GrPoint fPos; |
25 GrPoint fCenter; | 25 GrPoint fOffset; |
26 SkScalar fOuterRadius; | 26 SkScalar fOuterRadius; |
27 SkScalar fInnerRadius; | 27 SkScalar fInnerRadius; |
28 }; | 28 }; |
29 | 29 |
30 struct EllipseVertex { | 30 struct EllipseVertex { |
31 GrPoint fPos; | 31 GrPoint fPos; |
32 GrPoint fCenter; | |
33 SkScalar fOuterXRadius; | 32 SkScalar fOuterXRadius; |
34 SkScalar fOuterXYRatio; | |
35 SkScalar fInnerXRadius; | 33 SkScalar fInnerXRadius; |
36 SkScalar fInnerXYRatio; | 34 GrPoint fOuterOffset; |
35 GrPoint fInnerOffset; | |
37 }; | 36 }; |
38 | 37 |
39 inline bool circle_stays_circle(const SkMatrix& m) { | 38 inline bool circle_stays_circle(const SkMatrix& m) { |
40 return m.isSimilarity(); | 39 return m.isSimilarity(); |
41 } | 40 } |
42 | 41 |
43 } | 42 } |
44 | 43 |
45 /////////////////////////////////////////////////////////////////////////////// | 44 /////////////////////////////////////////////////////////////////////////////// |
46 | 45 |
47 /** | 46 /** |
48 * The output of this effect is a modulation of the input color and coverage for a circle, | 47 * 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 | 48 * specified as offset_x, offset_y (both from center point), outer radius and in ner radius. |
50 * (y-down). | |
51 */ | 49 */ |
52 | 50 |
53 class CircleEdgeEffect : public GrEffect { | 51 class CircleEdgeEffect : public GrEffect { |
54 public: | 52 public: |
55 static GrEffectRef* Create(bool stroke) { | 53 static GrEffectRef* Create(bool stroke) { |
56 // we go through this so we only have one copy of each effect (stroked/f illed) | 54 // we go through this so we only have one copy of each effect (stroked/f illed) |
57 static SkAutoTUnref<GrEffectRef> gCircleStrokeEdgeEffectRef( | 55 static SkAutoTUnref<GrEffectRef> gCircleStrokeEdgeEffectRef( |
58 CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(CircleEdgeEff ect, (true))))); | 56 CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(CircleEdgeEff ect, (true))))); |
59 static SkAutoTUnref<GrEffectRef> gCircleFillEdgeEffectRef( | 57 static SkAutoTUnref<GrEffectRef> gCircleFillEdgeEffectRef( |
60 CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(CircleEdgeEff ect, (false))))); | 58 CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(CircleEdgeEff ect, (false))))); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
95 const char* inputColor, | 93 const char* inputColor, |
96 const TextureSamplerArray& samplers) SK_OVERRIDE { | 94 const TextureSamplerArray& samplers) SK_OVERRIDE { |
97 const CircleEdgeEffect& circleEffect = drawEffect.castEffect<CircleE dgeEffect>(); | 95 const CircleEdgeEffect& circleEffect = drawEffect.castEffect<CircleE dgeEffect>(); |
98 const char *vsName, *fsName; | 96 const char *vsName, *fsName; |
99 builder->addVarying(kVec4f_GrSLType, "CircleEdge", &vsName, &fsName) ; | 97 builder->addVarying(kVec4f_GrSLType, "CircleEdge", &vsName, &fsName) ; |
100 | 98 |
101 const SkString* attrName = | 99 const SkString* attrName = |
102 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[0]); | 100 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[0]); |
103 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); | 101 builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); |
104 | 102 |
105 builder->fsCodeAppendf("\tfloat d = distance(%s.xy, %s.xy);\n", | 103 builder->fsCodeAppendf("\tfloat d = length(%s.xy);\n", fsName); |
106 builder->fragmentPosition(), fsName); | |
107 builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0 );\n", fsName); | 104 builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0 );\n", fsName); |
108 if (circleEffect.isStroked()) { | 105 if (circleEffect.isStroked()) { |
109 builder->fsCodeAppendf("\tfloat innerAlpha = clamp(d - %s.w, 0.0 , 1.0);\n", fsName); | 106 builder->fsCodeAppendf("\tfloat innerAlpha = clamp(d - %s.w, 0.0 , 1.0);\n", fsName); |
110 builder->fsCodeAppend("\tedgeAlpha *= innerAlpha;\n"); | 107 builder->fsCodeAppend("\tedgeAlpha *= innerAlpha;\n"); |
111 } | 108 } |
109 | |
112 SkString modulate; | 110 SkString modulate; |
113 GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha"); | 111 GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha"); |
114 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str() ); | 112 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str() ); |
115 } | 113 } |
116 | 114 |
117 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) { | 115 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) { |
118 const CircleEdgeEffect& circleEffect = drawEffect.castEffect<CircleE dgeEffect>(); | 116 const CircleEdgeEffect& circleEffect = drawEffect.castEffect<CircleE dgeEffect>(); |
119 | 117 |
120 return circleEffect.isStroked() ? 0x1 : 0x0; | 118 return circleEffect.isStroked() ? 0x1 : 0x0; |
121 } | 119 } |
(...skipping 29 matching lines...) Expand all Loading... | |
151 GrContext* context, | 149 GrContext* context, |
152 const GrDrawTargetCaps&, | 150 const GrDrawTargetCaps&, |
153 GrTexture* textures[]) { | 151 GrTexture* textures[]) { |
154 return CircleEdgeEffect::Create(random->nextBool()); | 152 return CircleEdgeEffect::Create(random->nextBool()); |
155 } | 153 } |
156 | 154 |
157 /////////////////////////////////////////////////////////////////////////////// | 155 /////////////////////////////////////////////////////////////////////////////// |
158 | 156 |
159 /** | 157 /** |
160 * The output of this effect is a modulation of the input color and coverage for an axis-aligned | 158 * The output of this effect is a modulation of the input color and coverage for an axis-aligned |
161 * ellipse, specified as center_x, center_y, x_radius, x_radius/y_radius in wind ow space (y-down). | 159 * ellipse, specified as outer and inner radii, and outer and inner offsets fro m center. |
162 */ | 160 */ |
163 | 161 |
164 class EllipseEdgeEffect : public GrEffect { | 162 class EllipseEdgeEffect : public GrEffect { |
165 public: | 163 public: |
166 static GrEffectRef* Create(bool stroke) { | 164 static GrEffectRef* Create(bool stroke) { |
167 // we go through this so we only have one copy of each effect (stroked/f illed) | 165 // we go through this so we only have one copy of each effect (stroked/f illed) |
168 static SkAutoTUnref<GrEffectRef> gEllipseStrokeEdgeEffectRef( | 166 static SkAutoTUnref<GrEffectRef> gEllipseStrokeEdgeEffectRef( |
169 CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipseEdgeEf fect, (true))))); | 167 CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipseEdgeEf fect, (true))))); |
170 static SkAutoTUnref<GrEffectRef> gEllipseFillEdgeEffectRef( | 168 static SkAutoTUnref<GrEffectRef> gEllipseFillEdgeEffectRef( |
171 CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipseEdgeEf fect, (false))))); | 169 CreateEffectRef(AutoEffectUnref(SkNEW_ARGS(EllipseEdgeEf fect, (false))))); |
(...skipping 28 matching lines...) Expand all Loading... | |
200 : INHERITED (factory) {} | 198 : INHERITED (factory) {} |
201 | 199 |
202 virtual void emitCode(GrGLShaderBuilder* builder, | 200 virtual void emitCode(GrGLShaderBuilder* builder, |
203 const GrDrawEffect& drawEffect, | 201 const GrDrawEffect& drawEffect, |
204 EffectKey key, | 202 EffectKey key, |
205 const char* outputColor, | 203 const char* outputColor, |
206 const char* inputColor, | 204 const char* inputColor, |
207 const TextureSamplerArray& samplers) SK_OVERRIDE { | 205 const TextureSamplerArray& samplers) SK_OVERRIDE { |
208 const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<Ellip seEdgeEffect>(); | 206 const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<Ellip seEdgeEffect>(); |
209 | 207 |
210 const char *vsCenterName, *fsCenterName; | 208 const char *vsRadiiName, *fsRadiiName; |
211 const char *vsEdgeName, *fsEdgeName; | 209 const char *vsOffsetsName, *fsOffsetsName; |
212 | 210 |
213 builder->addVarying(kVec2f_GrSLType, "EllipseCenter", &vsCenterName, &fsCenterName); | 211 builder->addVarying(kVec2f_GrSLType, "EllipseRadii", &vsRadiiName, & fsRadiiName); |
214 const SkString* attr0Name = | 212 const SkString* attr0Name = |
215 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[0]); | 213 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[0]); |
216 builder->vsCodeAppendf("\t%s = %s;\n", vsCenterName, attr0Name->c_st r()); | 214 builder->vsCodeAppendf("\t%s = %s;\n", vsRadiiName, attr0Name->c_str ()); |
217 | 215 |
218 builder->addVarying(kVec4f_GrSLType, "EllipseEdge", &vsEdgeName, &fs EdgeName); | 216 builder->addVarying(kVec4f_GrSLType, "EllipseOffsets", &vsOffsetsNam e, &fsOffsetsName); |
219 const SkString* attr1Name = | 217 const SkString* attr1Name = |
220 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[1]); | 218 builder->getEffectAttributeName(drawEffect.getVertexAttribIndice s()[1]); |
221 builder->vsCodeAppendf("\t%s = %s;\n", vsEdgeName, attr1Name->c_str( )); | 219 builder->vsCodeAppendf("\t%s = %s;\n", vsOffsetsName, attr1Name->c_s tr()); |
222 | 220 |
223 // translate to origin | 221 // get length of offset |
224 builder->fsCodeAppendf("\tvec2 outerOffset = (%s.xy - %s.xy);\n", | 222 builder->fsCodeAppendf("\tfloat dOuter = length(%s.xy);\n", fsOffset sName); |
225 builder->fragmentPosition(), fsCenterName); | |
226 builder->fsCodeAppend("\tvec2 innerOffset = outerOffset;\n"); | |
227 // scale y by xRadius/yRadius | |
228 builder->fsCodeAppendf("\touterOffset.y *= %s.y;\n", fsEdgeName); | |
229 builder->fsCodeAppend("\tfloat dOuter = length(outerOffset);\n"); | |
230 // compare outer lengths against xOuterRadius | 223 // compare outer lengths against xOuterRadius |
231 builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.x-dOuter, 0.0, 1.0);\n", | 224 builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.x-dOuter, 0.0, 1.0);\n", |
232 fsEdgeName); | 225 fsRadiiName); |
233 | 226 |
234 if (ellipseEffect.isStroked()) { | 227 if (ellipseEffect.isStroked()) { |
235 builder->fsCodeAppendf("\tinnerOffset.y *= %s.w;\n", fsEdgeName) ; | 228 builder->fsCodeAppendf("\tfloat dInner = length(%s.zw);\n", fsOf fsetsName); |
236 builder->fsCodeAppend("\tfloat dInner = length(innerOffset);\n") ; | |
237 | 229 |
238 // compare inner lengths against xInnerRadius | 230 // compare inner lengths against xInnerRadius |
239 builder->fsCodeAppendf("\tfloat innerAlpha = clamp(dInner-%s.z, 0.0, 1.0);\n", | 231 builder->fsCodeAppendf("\tfloat innerAlpha = clamp(dInner-%s.y, 0.0, 1.0);\n", |
240 fsEdgeName); | 232 fsRadiiName); |
241 builder->fsCodeAppend("\tedgeAlpha *= innerAlpha;\n"); | 233 builder->fsCodeAppend("\tedgeAlpha *= innerAlpha;\n"); |
242 } | 234 } |
243 | 235 |
244 SkString modulate; | 236 SkString modulate; |
245 GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha"); | 237 GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha"); |
246 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str() ); | 238 builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str() ); |
247 } | 239 } |
248 | 240 |
249 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) { | 241 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrG LCaps&) { |
250 const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<Ellip seEdgeEffect>(); | 242 const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<Ellip seEdgeEffect>(); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
377 } | 369 } |
378 } | 370 } |
379 | 371 |
380 // The radii are outset for two reasons. First, it allows the shader to simp ly perform | 372 // The radii are outset for two reasons. First, it allows the shader to simp ly perform |
381 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is use d to compute the | 373 // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is use d to compute the |
382 // verts of the bounding box that is rendered and the outset ensures the box will cover all | 374 // verts of the bounding box that is rendered and the outset ensures the box will cover all |
383 // pixels partially covered by the circle. | 375 // pixels partially covered by the circle. |
384 outerRadius += SK_ScalarHalf; | 376 outerRadius += SK_ScalarHalf; |
385 innerRadius -= SK_ScalarHalf; | 377 innerRadius -= SK_ScalarHalf; |
386 | 378 |
387 for (int i = 0; i < 4; ++i) { | |
388 verts[i].fCenter = center; | |
389 verts[i].fOuterRadius = outerRadius; | |
390 verts[i].fInnerRadius = innerRadius; | |
391 } | |
392 | |
393 SkRect bounds = SkRect::MakeLTRB( | 379 SkRect bounds = SkRect::MakeLTRB( |
394 center.fX - outerRadius, | 380 center.fX - outerRadius, |
395 center.fY - outerRadius, | 381 center.fY - outerRadius, |
396 center.fX + outerRadius, | 382 center.fX + outerRadius, |
397 center.fY + outerRadius | 383 center.fY + outerRadius |
398 ); | 384 ); |
399 | 385 |
400 verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop); | 386 verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop); |
387 verts[0].fOffset = SkPoint::Make(-outerRadius, -outerRadius); | |
388 verts[0].fOuterRadius = outerRadius; | |
389 verts[0].fInnerRadius = innerRadius; | |
390 | |
401 verts[1].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); | 391 verts[1].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); |
392 verts[1].fOffset = SkPoint::Make(outerRadius, -outerRadius); | |
393 verts[1].fOuterRadius = outerRadius; | |
394 verts[1].fInnerRadius = innerRadius; | |
395 | |
402 verts[2].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom); | 396 verts[2].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom); |
397 verts[2].fOffset = SkPoint::Make(-outerRadius, outerRadius); | |
398 verts[2].fOuterRadius = outerRadius; | |
399 verts[2].fInnerRadius = innerRadius; | |
400 | |
403 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); | 401 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); |
402 verts[3].fOffset = SkPoint::Make(outerRadius, outerRadius); | |
403 verts[3].fOuterRadius = outerRadius; | |
404 verts[3].fInnerRadius = innerRadius; | |
404 | 405 |
405 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds); | 406 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds); |
406 } | 407 } |
407 | 408 |
408 void GrOvalRenderer::drawEllipse(GrDrawTarget* target, | 409 void GrOvalRenderer::drawEllipse(GrDrawTarget* target, |
409 const GrPaint& paint, | 410 const GrPaint& paint, |
410 const GrRect& ellipse, | 411 const GrRect& ellipse, |
411 const SkStrokeRec& stroke) | 412 const SkStrokeRec& stroke) |
412 { | 413 { |
413 GrDrawState* drawState = target->drawState(); | 414 GrDrawState* drawState = target->drawState(); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
488 innerXRadius = SkMaxScalar(0, xRadius - scaledStroke.fX); | 489 innerXRadius = SkMaxScalar(0, xRadius - scaledStroke.fX); |
489 innerRatio = innerXRadius/innerYRadius; | 490 innerRatio = innerXRadius/innerYRadius; |
490 } | 491 } |
491 } | 492 } |
492 xRadius += scaledStroke.fX; | 493 xRadius += scaledStroke.fX; |
493 yRadius += scaledStroke.fY; | 494 yRadius += scaledStroke.fY; |
494 } | 495 } |
495 | 496 |
496 SkScalar outerRatio = SkScalarDiv(xRadius, yRadius); | 497 SkScalar outerRatio = SkScalarDiv(xRadius, yRadius); |
497 | 498 |
498 for (int i = 0; i < 4; ++i) { | 499 // We've extended the outer x radius out half a pixel to antialias. |
499 verts[i].fCenter = center; | 500 // This will also expand the rect so all the pixels will be captured. |
500 verts[i].fOuterXRadius = xRadius + 0.5f; | 501 xRadius += SK_ScalarHalf; |
501 verts[i].fOuterXYRatio = outerRatio; | 502 yRadius += SK_ScalarHalf; |
502 verts[i].fInnerXRadius = innerXRadius - 0.5f; | 503 innerXRadius -= SK_ScalarHalf; |
503 verts[i].fInnerXYRatio = innerRatio; | |
504 } | |
505 | 504 |
506 SkScalar L = -xRadius; | 505 SkRect bounds = SkRect::MakeLTRB( |
507 SkScalar R = +xRadius; | 506 center.fX - xRadius, |
508 SkScalar T = -yRadius; | 507 center.fY - yRadius, |
509 SkScalar B = +yRadius; | 508 center.fX + xRadius, |
509 center.fY + yRadius | |
510 ); | |
510 | 511 |
511 // We've extended the outer x radius out half a pixel to antialias. | 512 // The offsets are created by scaling the y radius by the appropriate ratio. This way we end up |
512 // Expand the drawn rect here so all the pixels will be captured. | 513 // with a circle equation which can be checked quickly in the shader. We nee d one offset for |
513 L += center.fX - SK_ScalarHalf; | 514 // outer and one for inner because they have different scale factors -- othe rwise we end up with |
514 R += center.fX + SK_ScalarHalf; | 515 // non-uniform strokes. |
515 T += center.fY - SK_ScalarHalf; | 516 verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop); |
516 B += center.fY + SK_ScalarHalf; | 517 verts[0].fOuterXRadius = xRadius; |
518 verts[0].fInnerXRadius = innerXRadius; | |
519 verts[0].fOuterOffset = SkPoint::Make(-xRadius, -outerRatio*yRadius); | |
520 verts[0].fInnerOffset = SkPoint::Make(-xRadius, -innerRatio*yRadius); | |
517 | 521 |
518 verts[0].fPos = SkPoint::Make(L, T); | 522 verts[1].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); |
519 verts[1].fPos = SkPoint::Make(R, T); | 523 verts[1].fOuterXRadius = xRadius; |
520 verts[2].fPos = SkPoint::Make(L, B); | 524 verts[1].fInnerXRadius = innerXRadius; |
521 verts[3].fPos = SkPoint::Make(R, B); | 525 verts[1].fOuterOffset = SkPoint::Make(xRadius, -outerRatio*yRadius); |
526 verts[1].fInnerOffset = SkPoint::Make(xRadius, -innerRatio*yRadius); | |
522 | 527 |
523 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4); | 528 verts[2].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom); |
529 verts[2].fOuterXRadius = xRadius; | |
530 verts[2].fInnerXRadius = innerXRadius; | |
531 verts[2].fOuterOffset = SkPoint::Make(-xRadius, outerRatio*yRadius); | |
532 verts[2].fInnerOffset = SkPoint::Make(-xRadius, innerRatio*yRadius); | |
533 | |
534 verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); | |
535 verts[3].fOuterXRadius = xRadius; | |
536 verts[3].fInnerXRadius = innerXRadius; | |
537 verts[3].fOuterOffset = SkPoint::Make(xRadius, outerRatio*yRadius); | |
538 verts[3].fInnerOffset = SkPoint::Make(xRadius, innerRatio*yRadius); | |
539 | |
robertphillips
2013/04/10 23:18:39
For the rect edge passing the bounds actually slow
| |
540 target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds); | |
524 } | 541 } |
OLD | NEW |