| Index: src/gpu/GrOvalRenderer.cpp
 | 
| diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp
 | 
| index eac6fb4a3af5b2b3a3cb1ffba7659548ed4d7be4..b9a806c9e19bfe63ee7ea2a290efff2ac6061ce8 100644
 | 
| --- a/src/gpu/GrOvalRenderer.cpp
 | 
| +++ b/src/gpu/GrOvalRenderer.cpp
 | 
| @@ -53,8 +53,14 @@ inline bool circle_stays_circle(const SkMatrix& m) {
 | 
|  ///////////////////////////////////////////////////////////////////////////////
 | 
|  
 | 
|  /**
 | 
| - * The output of this effect is a modulation of the input color and coverage for a circle,
 | 
| - * specified as offset_x, offset_y (both from center point), outer radius and inner radius.
 | 
| + * The output of this effect is a modulation of the input color and coverage for a circle. It
 | 
| + * operates in a space normalized by the circle radius (outer radius in the case of a stroke)
 | 
| + * with origin at the circle center. Two   vertex attributes are used:
 | 
| + *    vec2f : position in device space of the bounding geometry vertices
 | 
| + *    vec4f : (p.xy, outerRad, innerRad)
 | 
| + *             p is the position in the normalized space.
 | 
| + *             outerRad is the outerRadius in device space.
 | 
| + *             innerRad is the innerRadius in normalized space (ignored if not stroking).
 | 
|   */
 | 
|  
 | 
|  class CircleEdgeEffect : public GrGeometryProcessor {
 | 
| @@ -94,10 +100,10 @@ public:
 | 
|  
 | 
|              GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
 | 
|              fsBuilder->codeAppendf("float d = length(%s.xy);", v.fsIn());
 | 
| -            fsBuilder->codeAppendf("float edgeAlpha = clamp(%s.z - d, 0.0, 1.0);", v.fsIn());
 | 
| +            fsBuilder->codeAppendf("float edgeAlpha = clamp(%s.z * (1.0 - d), 0.0, 1.0);", v.fsIn());
 | 
|              if (ce.isStroked()) {
 | 
| -                fsBuilder->codeAppendf("float innerAlpha = clamp(d - %s.w, 0.0, 1.0);",
 | 
| -                                       v.fsIn());
 | 
| +                fsBuilder->codeAppendf("float innerAlpha = clamp(%s.z * (d - %s.w), 0.0, 1.0);",
 | 
| +                                       v.fsIn(), v.fsIn());
 | 
|                  fsBuilder->codeAppend("edgeAlpha *= innerAlpha;");
 | 
|              }
 | 
|  
 | 
| @@ -574,10 +580,10 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
 | 
|  
 | 
|      CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices());
 | 
|  
 | 
| -    // The radii are outset for two reasons. First, it allows the shader to simply perform
 | 
| -    // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the
 | 
| -    // verts of the bounding box that is rendered and the outset ensures the box will cover all
 | 
| -    // pixels partially covered by the circle.
 | 
| +    // The radii are outset for two reasons. First, it allows the shader to simply perform simpler
 | 
| +    // computation because the computed alpha is zero, rather than 50%, at the radius.
 | 
| +    // Second, the outer radius is used to compute the verts of the bounding box that is rendered
 | 
| +    // and the outset ensures the box will cover all partially covered by the circle.
 | 
|      outerRadius += SK_ScalarHalf;
 | 
|      innerRadius -= SK_ScalarHalf;
 | 
|  
 | 
| @@ -588,23 +594,25 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
 | 
|          center.fY + outerRadius
 | 
|      );
 | 
|  
 | 
| +    // The inner radius in the vertex data must be specified in normalized space.
 | 
| +    innerRadius = innerRadius / outerRadius;
 | 
|      verts[0].fPos = SkPoint::Make(bounds.fLeft,  bounds.fTop);
 | 
| -    verts[0].fOffset = SkPoint::Make(-outerRadius, -outerRadius);
 | 
| +    verts[0].fOffset = SkPoint::Make(-1, -1);
 | 
|      verts[0].fOuterRadius = outerRadius;
 | 
|      verts[0].fInnerRadius = innerRadius;
 | 
|  
 | 
|      verts[1].fPos = SkPoint::Make(bounds.fLeft,  bounds.fBottom);
 | 
| -    verts[1].fOffset = SkPoint::Make(-outerRadius, outerRadius);
 | 
| +    verts[1].fOffset = SkPoint::Make(-1, 1);
 | 
|      verts[1].fOuterRadius = outerRadius;
 | 
|      verts[1].fInnerRadius = innerRadius;
 | 
|  
 | 
|      verts[2].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom);
 | 
| -    verts[2].fOffset = SkPoint::Make(outerRadius, outerRadius);
 | 
| +    verts[2].fOffset = SkPoint::Make(1, 1);
 | 
|      verts[2].fOuterRadius = outerRadius;
 | 
|      verts[2].fInnerRadius = innerRadius;
 | 
|  
 | 
|      verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fTop);
 | 
| -    verts[3].fOffset = SkPoint::Make(outerRadius, -outerRadius);
 | 
| +    verts[3].fOffset = SkPoint::Make(1, -1);
 | 
|      verts[3].fOuterRadius = outerRadius;
 | 
|      verts[3].fInnerRadius = innerRadius;
 | 
|  
 | 
| @@ -1089,9 +1097,10 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target,
 | 
|          CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices());
 | 
|  
 | 
|          // The radii are outset for two reasons. First, it allows the shader to simply perform
 | 
| -        // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the
 | 
| -        // verts of the bounding box that is rendered and the outset ensures the box will cover all
 | 
| -        // pixels partially covered by the circle.
 | 
| +        // simpler computation because the computed alpha is zero, rather than 50%, at the radius.
 | 
| +        // Second, the outer radius is used to compute the verts of the bounding box that is
 | 
| +        // rendered and the outset ensures the box will cover all partially covered by the rrect
 | 
| +        // corners.
 | 
|          outerRadius += SK_ScalarHalf;
 | 
|          innerRadius -= SK_ScalarHalf;
 | 
|  
 | 
| @@ -1104,15 +1113,12 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target,
 | 
|              bounds.fBottom - outerRadius,
 | 
|              bounds.fBottom
 | 
|          };
 | 
| -        SkScalar yOuterRadii[4] = {
 | 
| -            -outerRadius,
 | 
| -            0,
 | 
| -            0,
 | 
| -            outerRadius
 | 
| -        };
 | 
| +        SkScalar yOuterRadii[4] = {-1, 0, 0, 1 };
 | 
| +        // The inner radius in the vertex data must be specified in normalized space.
 | 
| +        innerRadius = innerRadius / outerRadius;
 | 
|          for (int i = 0; i < 4; ++i) {
 | 
|              verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]);
 | 
| -            verts->fOffset = SkPoint::Make(-outerRadius, yOuterRadii[i]);
 | 
| +            verts->fOffset = SkPoint::Make(-1, yOuterRadii[i]);
 | 
|              verts->fOuterRadius = outerRadius;
 | 
|              verts->fInnerRadius = innerRadius;
 | 
|              verts++;
 | 
| @@ -1130,7 +1136,7 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target,
 | 
|              verts++;
 | 
|  
 | 
|              verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]);
 | 
| -            verts->fOffset = SkPoint::Make(outerRadius, yOuterRadii[i]);
 | 
| +            verts->fOffset = SkPoint::Make(1, yOuterRadii[i]);
 | 
|              verts->fOuterRadius = outerRadius;
 | 
|              verts->fInnerRadius = innerRadius;
 | 
|              verts++;
 | 
| 
 |