Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2013 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "GrOvalRenderer.h"
      9 
     10 #include "GrEffect.h"
     11 #include "gl/GrGLEffect.h"
     12 #include "gl/GrGLSL.h"
     13 #include "gl/GrGLVertexEffect.h"
     14 #include "GrTBackendEffectFactory.h"
     15 
     16 #include "GrDrawState.h"
     17 #include "GrDrawTarget.h"
     18 #include "GrGpu.h"
     19 
     20 #include "SkRRect.h"
     21 #include "SkStrokeRec.h"
     22 #include "SkTLazy.h"
     23 
     24 #include "effects/GrVertexEffect.h"
     25 #include "effects/GrRRectEffect.h"
     26 
     27 namespace {
     28 
     29 struct CircleVertex {
     30     SkPoint  fPos;
     31     SkPoint  fOffset;
     32     SkScalar fOuterRadius;
     33     SkScalar fInnerRadius;
     34 };
     35 
     36 struct EllipseVertex {
     37     SkPoint  fPos;
     38     SkPoint  fOffset;
     39     SkPoint  fOuterRadii;
     40     SkPoint  fInnerRadii;
     41 };
     42 
     43 struct DIEllipseVertex {
     44     SkPoint  fPos;
     45     SkPoint  fOuterOffset;
     46     SkPoint  fInnerOffset;
     47 };
     48 
     49 inline bool circle_stays_circle(const SkMatrix& m) {
     50     return m.isSimilarity();
     51 }
     52 
     53 }
     54 
     55 ///////////////////////////////////////////////////////////////////////////////
     56 
     57 /**
     58  * The output of this effect is a modulation of the input color and coverage for a circle,
     59  * specified as offset_x, offset_y (both from center point), outer radius and inner radius.
     60  */
     61 
     62 class CircleEdgeEffect : public GrVertexEffect {
     63 public:
     64     static GrEffectRef* Create(bool stroke) {
     65         GR_CREATE_STATIC_EFFECT(gCircleStrokeEdge, CircleEdgeEffect, (true));
     66         GR_CREATE_STATIC_EFFECT(gCircleFillEdge, CircleEdgeEffect, (false));
     67 
     68         if (stroke) {
     69             gCircleStrokeEdge->ref();
     70             return gCircleStrokeEdge;
     71         } else {
     72             gCircleFillEdge->ref();
     73             return gCircleFillEdge;
     74         }
     75     }
     76 
     77     virtual void getConstantColorComponents(GrColor* color,
     78                                             uint32_t* validFlags) const SK_OVERRIDE {
     79         *validFlags = 0;
     80     }
     81 
     82     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
     83         return GrTBackendEffectFactory<CircleEdgeEffect>::getInstance();
     84     }
     85 
     86     virtual ~CircleEdgeEffect() {}
     87 
     88     static const char* Name() { return "CircleEdge"; }
     89 
     90     inline bool isStroked() const { return fStroke; }
     91 
     92     class GLEffect : public GrGLVertexEffect {
     93     public:
     94         GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
     95         : INHERITED (factory) {}
     96 
     97         virtual void emitCode(GrGLFullShaderBuilder* builder,
     98                               const GrDrawEffect& drawEffect,
     99                               EffectKey key,
    100                               const char* outputColor,
    101                               const char* inputColor,
    102                               const TransformedCoordsArray&,
    103                               const TextureSamplerArray& samplers) SK_OVERRIDE {
    104             const CircleEdgeEffect& circleEffect = drawEffect.castEffect<CircleEdgeEffect>();
    105             const char *vsName, *fsName;
    106             builder->addVarying(kVec4f_GrSLType, "CircleEdge", &vsName, &fsName);
    107 
    108             const SkString* attrName =
    109                 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
    110             builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
    111 
    112             builder->fsCodeAppendf("\tfloat d = length(%s.xy);\n", fsName);
    113             builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0);\n", fsName);
    114             if (circleEffect.isStroked()) {
    115                 builder->fsCodeAppendf("\tfloat innerAlpha = clamp(d - %s.w, 0.0, 1.0);\n", fsName);
    116                 builder->fsCodeAppend("\tedgeAlpha *= innerAlpha;\n");
    117             }
    118 
    119             builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
    120                                    (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
    121         }
    122 
    123         static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
    124             const CircleEdgeEffect& circleEffect = drawEffect.castEffect<CircleEdgeEffect>();
    125 
    126             return circleEffect.isStroked() ? 0x1 : 0x0;
    127         }
    128 
    129         virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
    130 
    131     private:
    132         typedef GrGLVertexEffect INHERITED;
    133     };
    134 
    135 
    136 private:
    137     CircleEdgeEffect(bool stroke) : GrVertexEffect() {
    138         this->addVertexAttrib(kVec4f_GrSLType);
    139         fStroke = stroke;
    140     }
    141 
    142     virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
    143         const CircleEdgeEffect& cee = CastEffect<CircleEdgeEffect>(other);
    144         return cee.fStroke == fStroke;
    145     }
    146 
    147     bool fStroke;
    148 
    149     GR_DECLARE_EFFECT_TEST;
    150 
    151     typedef GrVertexEffect INHERITED;
    152 };
    153 
    154 GR_DEFINE_EFFECT_TEST(CircleEdgeEffect);
    155 
    156 GrEffectRef* CircleEdgeEffect::TestCreate(SkRandom* random,
    157                                           GrContext* context,
    158                                           const GrDrawTargetCaps&,
    159                                           GrTexture* textures[]) {
    160     return CircleEdgeEffect::Create(random->nextBool());
    161 }
    162 
    163 ///////////////////////////////////////////////////////////////////////////////
    164 
    165 /**
    166  * The output of this effect is a modulation of the input color and coverage for an axis-aligned
    167  * ellipse, specified as a 2D offset from center, and the reciprocals of the outer and inner radii,
    168  * in both x and y directions.
    169  *
    170  * We are using an implicit function of x^2/a^2 + y^2/b^2 - 1 = 0.
    171  */
    172 
    173 class EllipseEdgeEffect : public GrVertexEffect {
    174 public:
    175     static GrEffectRef* Create(bool stroke) {
    176         GR_CREATE_STATIC_EFFECT(gEllipseStrokeEdge, EllipseEdgeEffect, (true));
    177         GR_CREATE_STATIC_EFFECT(gEllipseFillEdge, EllipseEdgeEffect, (false));
    178 
    179         if (stroke) {
    180             gEllipseStrokeEdge->ref();
    181             return gEllipseStrokeEdge;
    182         } else {
    183             gEllipseFillEdge->ref();
    184             return gEllipseFillEdge;
    185         }
    186     }
    187 
    188     virtual void getConstantColorComponents(GrColor* color,
    189                                             uint32_t* validFlags) const SK_OVERRIDE {
    190         *validFlags = 0;
    191     }
    192 
    193     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
    194         return GrTBackendEffectFactory<EllipseEdgeEffect>::getInstance();
    195     }
    196 
    197     virtual ~EllipseEdgeEffect() {}
    198 
    199     static const char* Name() { return "EllipseEdge"; }
    200 
    201     inline bool isStroked() const { return fStroke; }
    202 
    203     class GLEffect : public GrGLVertexEffect {
    204     public:
    205         GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
    206         : INHERITED (factory) {}
    207 
    208         virtual void emitCode(GrGLFullShaderBuilder* builder,
    209                               const GrDrawEffect& drawEffect,
    210                               EffectKey key,
    211                               const char* outputColor,
    212                               const char* inputColor,
    213                               const TransformedCoordsArray&,
    214                               const TextureSamplerArray& samplers) SK_OVERRIDE {
    215             const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<EllipseEdgeEffect>();
    216 
    217             const char *vsOffsetName, *fsOffsetName;
    218             const char *vsRadiiName, *fsRadiiName;
    219 
    220             builder->addVarying(kVec2f_GrSLType, "EllipseOffsets", &vsOffsetName, &fsOffsetName);
    221             const SkString* attr0Name =
    222                 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
    223             builder->vsCodeAppendf("\t%s = %s;\n", vsOffsetName, attr0Name->c_str());
    224 
    225             builder->addVarying(kVec4f_GrSLType, "EllipseRadii", &vsRadiiName, &fsRadiiName);
    226             const SkString* attr1Name =
    227                 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]);
    228             builder->vsCodeAppendf("\t%s = %s;\n", vsRadiiName, attr1Name->c_str());
    229 
    230             // for outer curve
    231             builder->fsCodeAppendf("\tvec2 scaledOffset = %s*%s.xy;\n", fsOffsetName, fsRadiiName);
    232             builder->fsCodeAppend("\tfloat test = dot(scaledOffset, scaledOffset) - 1.0;\n");
    233             builder->fsCodeAppendf("\tvec2 grad = 2.0*scaledOffset*%s.xy;\n", fsRadiiName);
    234             builder->fsCodeAppend("\tfloat grad_dot = dot(grad, grad);\n");
    235             // avoid calling inversesqrt on zero.
    236             builder->fsCodeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n");
    237             builder->fsCodeAppend("\tfloat invlen = inversesqrt(grad_dot);\n");
    238             builder->fsCodeAppend("\tfloat edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);\n");
    239 
    240             // for inner curve
    241             if (ellipseEffect.isStroked()) {
    242                 builder->fsCodeAppendf("\tscaledOffset = %s*%s.zw;\n", fsOffsetName, fsRadiiName);
    243                 builder->fsCodeAppend("\ttest = dot(scaledOffset, scaledOffset) - 1.0;\n");
    244                 builder->fsCodeAppendf("\tgrad = 2.0*scaledOffset*%s.zw;\n", fsRadiiName);
    245                 builder->fsCodeAppend("\tinvlen = inversesqrt(dot(grad, grad));\n");
    246                 builder->fsCodeAppend("\tedgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);\n");
    247             }
    248 
    249             builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
    250                                    (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
    251         }
    252 
    253         static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
    254             const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<EllipseEdgeEffect>();
    255 
    256             return ellipseEffect.isStroked() ? 0x1 : 0x0;
    257         }
    258 
    259         virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {
    260         }
    261 
    262     private:
    263         typedef GrGLVertexEffect INHERITED;
    264     };
    265 
    266 private:
    267     EllipseEdgeEffect(bool stroke) : GrVertexEffect() {
    268         this->addVertexAttrib(kVec2f_GrSLType);
    269         this->addVertexAttrib(kVec4f_GrSLType);
    270         fStroke = stroke;
    271     }
    272 
    273     virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
    274         const EllipseEdgeEffect& eee = CastEffect<EllipseEdgeEffect>(other);
    275         return eee.fStroke == fStroke;
    276     }
    277 
    278     bool fStroke;
    279 
    280     GR_DECLARE_EFFECT_TEST;
    281 
    282     typedef GrVertexEffect INHERITED;
    283 };
    284 
    285 GR_DEFINE_EFFECT_TEST(EllipseEdgeEffect);
    286 
    287 GrEffectRef* EllipseEdgeEffect::TestCreate(SkRandom* random,
    288                                            GrContext* context,
    289                                            const GrDrawTargetCaps&,
    290                                            GrTexture* textures[]) {
    291     return EllipseEdgeEffect::Create(random->nextBool());
    292 }
    293 
    294 ///////////////////////////////////////////////////////////////////////////////
    295 
    296 /**
    297  * The output of this effect is a modulation of the input color and coverage for an ellipse,
    298  * specified as a 2D offset from center for both the outer and inner paths (if stroked). The
    299  * implict equation used is for a unit circle (x^2 + y^2 - 1 = 0) and the edge corrected by
    300  * using differentials.
    301  *
    302  * The result is device-independent and can be used with any affine matrix.
    303  */
    304 
    305 class DIEllipseEdgeEffect : public GrVertexEffect {
    306 public:
    307     enum Mode { kStroke = 0, kHairline, kFill };
    308 
    309     static GrEffectRef* Create(Mode mode) {
    310         GR_CREATE_STATIC_EFFECT(gEllipseStrokeEdge, DIEllipseEdgeEffect, (kStroke));
    311         GR_CREATE_STATIC_EFFECT(gEllipseHairlineEdge, DIEllipseEdgeEffect, (kHairline));
    312         GR_CREATE_STATIC_EFFECT(gEllipseFillEdge, DIEllipseEdgeEffect, (kFill));
    313 
    314         if (kStroke == mode) {
    315             gEllipseStrokeEdge->ref();
    316             return gEllipseStrokeEdge;
    317         } else if (kHairline == mode) {
    318             gEllipseHairlineEdge->ref();
    319             return gEllipseHairlineEdge;
    320         } else {
    321             gEllipseFillEdge->ref();
    322             return gEllipseFillEdge;
    323         }
    324     }
    325 
    326     virtual void getConstantColorComponents(GrColor* color,
    327                                             uint32_t* validFlags) const SK_OVERRIDE {
    328         *validFlags = 0;
    329     }
    330 
    331     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
    332         return GrTBackendEffectFactory<DIEllipseEdgeEffect>::getInstance();
    333     }
    334 
    335     virtual ~DIEllipseEdgeEffect() {}
    336 
    337     static const char* Name() { return "DIEllipseEdge"; }
    338 
    339     inline Mode getMode() const { return fMode; }
    340 
    341     class GLEffect : public GrGLVertexEffect {
    342     public:
    343         GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
    344         : INHERITED (factory) {}
    345 
    346         virtual void emitCode(GrGLFullShaderBuilder* builder,
    347                               const GrDrawEffect& drawEffect,
    348                               EffectKey key,
    349                               const char* outputColor,
    350                               const char* inputColor,
    351                               const TransformedCoordsArray&,
    352                               const TextureSamplerArray& samplers) SK_OVERRIDE {
    353             const DIEllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<DIEllipseEdgeEffect>();
    354 
    355             SkAssertResult(builder->enableFeature(
    356                                               GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
    357 
    358             const char *vsOffsetName0, *fsOffsetName0;
    359             builder->addVarying(kVec2f_GrSLType, "EllipseOffsets0",
    360                                       &vsOffsetName0, &fsOffsetName0);
    361             const SkString* attr0Name =
    362                 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
    363             builder->vsCodeAppendf("\t%s = %s;\n", vsOffsetName0, attr0Name->c_str());
    364             const char *vsOffsetName1, *fsOffsetName1;
    365             builder->addVarying(kVec2f_GrSLType, "EllipseOffsets1",
    366                                       &vsOffsetName1, &fsOffsetName1);
    367             const SkString* attr1Name =
    368                 builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]);
    369             builder->vsCodeAppendf("\t%s = %s;\n", vsOffsetName1, attr1Name->c_str());
    370 
    371             // for outer curve
    372             builder->fsCodeAppendf("\tvec2 scaledOffset = %s.xy;\n", fsOffsetName0);
    373             builder->fsCodeAppend("\tfloat test = dot(scaledOffset, scaledOffset) - 1.0;\n");
    374             builder->fsCodeAppendf("\tvec2 duvdx = dFdx(%s);\n", fsOffsetName0);
    375             builder->fsCodeAppendf("\tvec2 duvdy = dFdy(%s);\n", fsOffsetName0);
    376             builder->fsCodeAppendf("\tvec2 grad = vec2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y,\n"
    377                                    "\t                 2.0*%s.x*duvdy.x + 2.0*%s.y*duvdy.y);\n",
    378                                    fsOffsetName0, fsOffsetName0, fsOffsetName0, fsOffsetName0);
    379 
    380             builder->fsCodeAppend("\tfloat grad_dot = dot(grad, grad);\n");
    381             // avoid calling inversesqrt on zero.
    382             builder->fsCodeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n");
    383             builder->fsCodeAppend("\tfloat invlen = inversesqrt(grad_dot);\n");
    384             if (kHairline == ellipseEffect.getMode()) {
    385                 // can probably do this with one step
    386                 builder->fsCodeAppend("\tfloat edgeAlpha = clamp(1.0-test*invlen, 0.0, 1.0);\n");
    387                 builder->fsCodeAppend("\tedgeAlpha *= clamp(1.0+test*invlen, 0.0, 1.0);\n");
    388             } else {
    389                 builder->fsCodeAppend("\tfloat edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);\n");
    390             }
    391 
    392             // for inner curve
    393             if (kStroke == ellipseEffect.getMode()) {
    394                 builder->fsCodeAppendf("\tscaledOffset = %s.xy;\n", fsOffsetName1);
    395                 builder->fsCodeAppend("\ttest = dot(scaledOffset, scaledOffset) - 1.0;\n");
    396                 builder->fsCodeAppendf("\tduvdx = dFdx(%s);\n", fsOffsetName1);
    397                 builder->fsCodeAppendf("\tduvdy = dFdy(%s);\n", fsOffsetName1);
    398                 builder->fsCodeAppendf("\tgrad = vec2(2.0*%s.x*duvdx.x + 2.0*%s.y*duvdx.y,\n"
    399                                        "\t            2.0*%s.x*duvdy.x + 2.0*%s.y*duvdy.y);\n",
    400                                        fsOffsetName1, fsOffsetName1, fsOffsetName1, fsOffsetName1);
    401                 builder->fsCodeAppend("\tinvlen = inversesqrt(dot(grad, grad));\n");
    402                 builder->fsCodeAppend("\tedgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);\n");
    403             }
    404 
    405             builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
    406                                    (GrGLSLExpr4(inputColor) * GrGLSLExpr1("edgeAlpha")).c_str());
    407         }
    408 
    409         static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
    410             const DIEllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<DIEllipseEdgeEffect>();
    411 
    412             return ellipseEffect.getMode();
    413         }
    414 
    415         virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {
    416         }
    417 
    418     private:
    419         typedef GrGLVertexEffect INHERITED;
    420     };
    421 
    422 private:
    423     DIEllipseEdgeEffect(Mode mode) : GrVertexEffect() {
    424         this->addVertexAttrib(kVec2f_GrSLType);
    425         this->addVertexAttrib(kVec2f_GrSLType);
    426         fMode = mode;
    427     }
    428 
    429     virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
    430         const DIEllipseEdgeEffect& eee = CastEffect<DIEllipseEdgeEffect>(other);
    431         return eee.fMode == fMode;
    432     }
    433 
    434     Mode fMode;
    435 
    436     GR_DECLARE_EFFECT_TEST;
    437 
    438     typedef GrVertexEffect INHERITED;
    439 };
    440 
    441 GR_DEFINE_EFFECT_TEST(DIEllipseEdgeEffect);
    442 
    443 GrEffectRef* DIEllipseEdgeEffect::TestCreate(SkRandom* random,
    444                                              GrContext* context,
    445                                              const GrDrawTargetCaps&,
    446                                              GrTexture* textures[]) {
    447     return DIEllipseEdgeEffect::Create((Mode)(random->nextRangeU(0,2)));
    448 }
    449 
    450 ///////////////////////////////////////////////////////////////////////////////
    451 
    452 void GrOvalRenderer::reset() {
    453     SkSafeSetNull(fRRectIndexBuffer);
    454 }
    455 
    456 bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, bool useAA,
    457                               const SkRect& oval, const SkStrokeRec& stroke)
    458 {
    459     bool useCoverageAA = useAA &&
    460         !target->getDrawState().getRenderTarget()->isMultisampled() &&
    461         !target->shouldDisableCoverageAAForBlend();
    462 
    463     if (!useCoverageAA) {
    464         return false;
    465     }
    466 
    467     const SkMatrix& vm = context->getMatrix();
    468 
    469     // we can draw circles
    470     if (SkScalarNearlyEqual(oval.width(), oval.height())
    471         && circle_stays_circle(vm)) {
    472         this->drawCircle(target, useCoverageAA, oval, stroke);
    473     // if we have shader derivative support, render as device-independent
    474     } else if (target->caps()->shaderDerivativeSupport()) {
    475         return this->drawDIEllipse(target, useCoverageAA, oval, stroke);
    476     // otherwise axis-aligned ellipses only
    477     } else if (vm.rectStaysRect()) {
    478         return this->drawEllipse(target, useCoverageAA, oval, stroke);
    479     } else {
    480         return false;
    481     }
    482 
    483     return true;
    484 }
    485 
    486 ///////////////////////////////////////////////////////////////////////////////
    487 
    488 // position + edge
    489 extern const GrVertexAttrib gCircleVertexAttribs[] = {
    490     {kVec2f_GrVertexAttribType, 0,               kPosition_GrVertexAttribBinding},
    491     {kVec4f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding}
    492 };
    493 
    494 void GrOvalRenderer::drawCircle(GrDrawTarget* target,
    495                                 bool useCoverageAA,
    496                                 const SkRect& circle,
    497                                 const SkStrokeRec& stroke)
    498 {
    499     GrDrawState* drawState = target->drawState();
    500 
    501     const SkMatrix& vm = drawState->getViewMatrix();
    502     SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY());
    503     vm.mapPoints(&center, 1);
    504     SkScalar radius = vm.mapRadius(SkScalarHalf(circle.width()));
    505     SkScalar strokeWidth = vm.mapRadius(stroke.getWidth());
    506 
    507     GrDrawState::AutoViewMatrixRestore avmr;
    508     if (!avmr.setIdentity(drawState)) {
    509         return;
    510     }
    511 
    512     drawState->setVertexAttribs<gCircleVertexAttribs>(SK_ARRAY_COUNT(gCircleVertexAttribs));
    513     SkASSERT(sizeof(CircleVertex) == drawState->getVertexSize());
    514 
    515     GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
    516     if (!geo.succeeded()) {
    517         GrPrintf("Failed to get space for vertices!\n");
    518         return;
    519     }
    520 
    521     CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices());
    522 
    523     SkStrokeRec::Style style = stroke.getStyle();
    524     bool isStrokeOnly = SkStrokeRec::kStroke_Style == style ||
    525                         SkStrokeRec::kHairline_Style == style;
    526     bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style;
    527 
    528     SkScalar innerRadius = 0.0f;
    529     SkScalar outerRadius = radius;
    530     SkScalar halfWidth = 0;
    531     if (hasStroke) {
    532         if (SkScalarNearlyZero(strokeWidth)) {
    533             halfWidth = SK_ScalarHalf;
    534         } else {
    535             halfWidth = SkScalarHalf(strokeWidth);
    536         }
    537 
    538         outerRadius += halfWidth;
    539         if (isStrokeOnly) {
    540             innerRadius = radius - halfWidth;
    541         }
    542     }
    543 
    544     GrEffectRef* effect = CircleEdgeEffect::Create(isStrokeOnly && innerRadius > 0);
    545     static const int kCircleEdgeAttrIndex = 1;
    546     drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref();
    547 
    548     // The radii are outset for two reasons. First, it allows the shader to simply perform
    549     // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the
    550     // verts of the bounding box that is rendered and the outset ensures the box will cover all
    551     // pixels partially covered by the circle.
    552     outerRadius += SK_ScalarHalf;
    553     innerRadius -= SK_ScalarHalf;
    554 
    555     SkRect bounds = SkRect::MakeLTRB(
    556         center.fX - outerRadius,
    557         center.fY - outerRadius,
    558         center.fX + outerRadius,
    559         center.fY + outerRadius
    560     );
    561 
    562     verts[0].fPos = SkPoint::Make(bounds.fLeft,  bounds.fTop);
    563     verts[0].fOffset = SkPoint::Make(-outerRadius, -outerRadius);
    564     verts[0].fOuterRadius = outerRadius;
    565     verts[0].fInnerRadius = innerRadius;
    566 
    567     verts[1].fPos = SkPoint::Make(bounds.fRight, bounds.fTop);
    568     verts[1].fOffset = SkPoint::Make(outerRadius, -outerRadius);
    569     verts[1].fOuterRadius = outerRadius;
    570     verts[1].fInnerRadius = innerRadius;
    571 
    572     verts[2].fPos = SkPoint::Make(bounds.fLeft,  bounds.fBottom);
    573     verts[2].fOffset = SkPoint::Make(-outerRadius, outerRadius);
    574     verts[2].fOuterRadius = outerRadius;
    575     verts[2].fInnerRadius = innerRadius;
    576 
    577     verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom);
    578     verts[3].fOffset = SkPoint::Make(outerRadius, outerRadius);
    579     verts[3].fOuterRadius = outerRadius;
    580     verts[3].fInnerRadius = innerRadius;
    581 
    582     target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds);
    583 }
    584 
    585 ///////////////////////////////////////////////////////////////////////////////
    586 
    587 // position + offset + 1/radii
    588 extern const GrVertexAttrib gEllipseVertexAttribs[] = {
    589     {kVec2f_GrVertexAttribType, 0,                 kPosition_GrVertexAttribBinding},
    590     {kVec2f_GrVertexAttribType, sizeof(SkPoint),   kEffect_GrVertexAttribBinding},
    591     {kVec4f_GrVertexAttribType, 2*sizeof(SkPoint), kEffect_GrVertexAttribBinding}
    592 };
    593 
    594 // position + offsets
    595 extern const GrVertexAttrib gDIEllipseVertexAttribs[] = {
    596     {kVec2f_GrVertexAttribType, 0,                 kPosition_GrVertexAttribBinding},
    597     {kVec2f_GrVertexAttribType, sizeof(SkPoint),   kEffect_GrVertexAttribBinding},
    598     {kVec2f_GrVertexAttribType, 2*sizeof(SkPoint), kEffect_GrVertexAttribBinding},
    599 };
    600 
    601 bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
    602                                  bool useCoverageAA,
    603                                  const SkRect& ellipse,
    604                                  const SkStrokeRec& stroke)
    605 {
    606     GrDrawState* drawState = target->drawState();
    607 #ifdef SK_DEBUG
    608     {
    609         // we should have checked for this previously
    610         bool isAxisAlignedEllipse = drawState->getViewMatrix().rectStaysRect();
    611         SkASSERT(useCoverageAA && isAxisAlignedEllipse);
    612     }
    613 #endif
    614 
    615     // do any matrix crunching before we reset the draw state for device coords
    616     const SkMatrix& vm = drawState->getViewMatrix();
    617     SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY());
    618     vm.mapPoints(&center, 1);
    619     SkScalar ellipseXRadius = SkScalarHalf(ellipse.width());
    620     SkScalar ellipseYRadius = SkScalarHalf(ellipse.height());
    621     SkScalar xRadius = SkScalarAbs(vm[SkMatrix::kMScaleX]*ellipseXRadius +
    622                                    vm[SkMatrix::kMSkewY]*ellipseYRadius);
    623     SkScalar yRadius = SkScalarAbs(vm[SkMatrix::kMSkewX]*ellipseXRadius +
    624                                    vm[SkMatrix::kMScaleY]*ellipseYRadius);
    625 
    626     // do (potentially) anisotropic mapping of stroke
    627     SkVector scaledStroke;
    628     SkScalar strokeWidth = stroke.getWidth();
    629     scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] + vm[SkMatrix::kMSkewY]));
    630     scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] + vm[SkMatrix::kMScaleY]));
    631 
    632     SkStrokeRec::Style style = stroke.getStyle();
    633     bool isStrokeOnly = SkStrokeRec::kStroke_Style == style ||
    634                         SkStrokeRec::kHairline_Style == style;
    635     bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style;
    636 
    637     SkScalar innerXRadius = 0;
    638     SkScalar innerYRadius = 0;
    639     if (hasStroke) {
    640         if (SkScalarNearlyZero(scaledStroke.length())) {
    641             scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf);
    642         } else {
    643             scaledStroke.scale(SK_ScalarHalf);
    644         }
    645 
    646         // we only handle thick strokes for near-circular ellipses
    647         if (scaledStroke.length() > SK_ScalarHalf &&
    648             (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)) {
    649             return false;
    650         }
    651 
    652         // we don't handle it if curvature of the stroke is less than curvature of the ellipse
    653         if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStroke.fY)*xRadius ||
    654             scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStroke.fX)*yRadius) {
    655             return false;
    656         }
    657 
    658         // this is legit only if scale & translation (which should be the case at the moment)
    659         if (isStrokeOnly) {
    660             innerXRadius = xRadius - scaledStroke.fX;
    661             innerYRadius = yRadius - scaledStroke.fY;
    662         }
    663 
    664         xRadius += scaledStroke.fX;
    665         yRadius += scaledStroke.fY;
    666     }
    667 
    668     GrDrawState::AutoViewMatrixRestore avmr;
    669     if (!avmr.setIdentity(drawState)) {
    670         return false;
    671     }
    672 
    673     drawState->setVertexAttribs<gEllipseVertexAttribs>(SK_ARRAY_COUNT(gEllipseVertexAttribs));
    674     SkASSERT(sizeof(EllipseVertex) == drawState->getVertexSize());
    675 
    676     GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
    677     if (!geo.succeeded()) {
    678         GrPrintf("Failed to get space for vertices!\n");
    679         return false;
    680     }
    681 
    682     EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices());
    683 
    684     GrEffectRef* effect = EllipseEdgeEffect::Create(isStrokeOnly &&
    685                                                     innerXRadius > 0 && innerYRadius > 0);
    686 
    687     static const int kEllipseCenterAttrIndex = 1;
    688     static const int kEllipseEdgeAttrIndex = 2;
    689     drawState->addCoverageEffect(effect, kEllipseCenterAttrIndex, kEllipseEdgeAttrIndex)->unref();
    690 
    691     // Compute the reciprocals of the radii here to save time in the shader
    692     SkScalar xRadRecip = SkScalarInvert(xRadius);
    693     SkScalar yRadRecip = SkScalarInvert(yRadius);
    694     SkScalar xInnerRadRecip = SkScalarInvert(innerXRadius);
    695     SkScalar yInnerRadRecip = SkScalarInvert(innerYRadius);
    696 
    697     // We've extended the outer x radius out half a pixel to antialias.
    698     // This will also expand the rect so all the pixels will be captured.
    699     // TODO: Consider if we should use sqrt(2)/2 instead
    700     xRadius += SK_ScalarHalf;
    701     yRadius += SK_ScalarHalf;
    702 
    703     SkRect bounds = SkRect::MakeLTRB(
    704         center.fX - xRadius,
    705         center.fY - yRadius,
    706         center.fX + xRadius,
    707         center.fY + yRadius
    708     );
    709 
    710     verts[0].fPos = SkPoint::Make(bounds.fLeft,  bounds.fTop);
    711     verts[0].fOffset = SkPoint::Make(-xRadius, -yRadius);
    712     verts[0].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
    713     verts[0].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
    714 
    715     verts[1].fPos = SkPoint::Make(bounds.fRight, bounds.fTop);
    716     verts[1].fOffset = SkPoint::Make(xRadius, -yRadius);
    717     verts[1].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
    718     verts[1].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
    719 
    720     verts[2].fPos = SkPoint::Make(bounds.fLeft,  bounds.fBottom);
    721     verts[2].fOffset = SkPoint::Make(-xRadius, yRadius);
    722     verts[2].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
    723     verts[2].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
    724 
    725     verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom);
    726     verts[3].fOffset = SkPoint::Make(xRadius, yRadius);
    727     verts[3].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
    728     verts[3].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
    729 
    730     target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds);
    731 
    732     return true;
    733 }
    734 
    735 bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target,
    736                                    bool useCoverageAA,
    737                                    const SkRect& ellipse,
    738                                    const SkStrokeRec& stroke)
    739 {
    740     GrDrawState* drawState = target->drawState();
    741     const SkMatrix& vm = drawState->getViewMatrix();
    742 
    743     SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY());
    744     SkScalar xRadius = SkScalarHalf(ellipse.width());
    745     SkScalar yRadius = SkScalarHalf(ellipse.height());
    746 
    747     SkStrokeRec::Style style = stroke.getStyle();
    748     DIEllipseEdgeEffect::Mode mode = (SkStrokeRec::kStroke_Style == style) ?
    749                                     DIEllipseEdgeEffect::kStroke :
    750                                     (SkStrokeRec::kHairline_Style == style) ?
    751                                     DIEllipseEdgeEffect::kHairline : DIEllipseEdgeEffect::kFill;
    752 
    753     SkScalar innerXRadius = 0;
    754     SkScalar innerYRadius = 0;
    755     if (SkStrokeRec::kFill_Style != style && SkStrokeRec::kHairline_Style != style) {
    756         SkScalar strokeWidth = stroke.getWidth();
    757 
    758         if (SkScalarNearlyZero(strokeWidth)) {
    759             strokeWidth = SK_ScalarHalf;
    760         } else {
    761             strokeWidth *= SK_ScalarHalf;
    762         }
    763 
    764         // we only handle thick strokes for near-circular ellipses
    765         if (strokeWidth > SK_ScalarHalf &&
    766             (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)) {
    767             return false;
    768         }
    769 
    770         // we don't handle it if curvature of the stroke is less than curvature of the ellipse
    771         if (strokeWidth*(yRadius*yRadius) < (strokeWidth*strokeWidth)*xRadius ||
    772             strokeWidth*(xRadius*xRadius) < (strokeWidth*strokeWidth)*yRadius) {
    773             return false;
    774         }
    775 
    776         // set inner radius (if needed)
    777         if (SkStrokeRec::kStroke_Style == style) {
    778             innerXRadius = xRadius - strokeWidth;
    779             innerYRadius = yRadius - strokeWidth;
    780         }
    781 
    782         xRadius += strokeWidth;
    783         yRadius += strokeWidth;
    784     }
    785     if (DIEllipseEdgeEffect::kStroke == mode) {
    786         mode = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseEdgeEffect::kStroke :
    787                                                         DIEllipseEdgeEffect::kFill;
    788     }
    789     SkScalar innerRatioX = SkScalarDiv(xRadius, innerXRadius);
    790     SkScalar innerRatioY = SkScalarDiv(yRadius, innerYRadius);
    791 
    792     drawState->setVertexAttribs<gDIEllipseVertexAttribs>(SK_ARRAY_COUNT(gDIEllipseVertexAttribs));
    793     SkASSERT(sizeof(DIEllipseVertex) == drawState->getVertexSize());
    794 
    795     GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
    796     if (!geo.succeeded()) {
    797         GrPrintf("Failed to get space for vertices!\n");
    798         return false;
    799     }
    800 
    801     DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(geo.vertices());
    802 
    803     GrEffectRef* effect = DIEllipseEdgeEffect::Create(mode);
    804 
    805     static const int kEllipseOuterOffsetAttrIndex = 1;
    806     static const int kEllipseInnerOffsetAttrIndex = 2;
    807     drawState->addCoverageEffect(effect, kEllipseOuterOffsetAttrIndex,
    808                                          kEllipseInnerOffsetAttrIndex)->unref();
    809 
    810     // This expands the outer rect so that after CTM we end up with a half-pixel border
    811     SkScalar a = vm[SkMatrix::kMScaleX];
    812     SkScalar b = vm[SkMatrix::kMSkewX];
    813     SkScalar c = vm[SkMatrix::kMSkewY];
    814     SkScalar d = vm[SkMatrix::kMScaleY];
    815     SkScalar geoDx = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(a*a + c*c));
    816     SkScalar geoDy = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(b*b + d*d));
    817     // This adjusts the "radius" to include the half-pixel border
    818     SkScalar offsetDx = SkScalarDiv(geoDx, xRadius);
    819     SkScalar offsetDy = SkScalarDiv(geoDy, yRadius);
    820 
    821     SkRect bounds = SkRect::MakeLTRB(
    822         center.fX - xRadius - geoDx,
    823         center.fY - yRadius - geoDy,
    824         center.fX + xRadius + geoDx,
    825         center.fY + yRadius + geoDy
    826     );
    827 
    828     verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop);
    829     verts[0].fOuterOffset = SkPoint::Make(-1.0f - offsetDx, -1.0f - offsetDy);
    830     verts[0].fInnerOffset = SkPoint::Make(-innerRatioX - offsetDx, -innerRatioY - offsetDy);
    831 
    832     verts[1].fPos = SkPoint::Make(bounds.fRight, bounds.fTop);
    833     verts[1].fOuterOffset = SkPoint::Make(1.0f + offsetDx, -1.0f - offsetDy);
    834     verts[1].fInnerOffset = SkPoint::Make(innerRatioX + offsetDx, -innerRatioY - offsetDy);
    835 
    836     verts[2].fPos = SkPoint::Make(bounds.fLeft,  bounds.fBottom);
    837     verts[2].fOuterOffset = SkPoint::Make(-1.0f - offsetDx, 1.0f + offsetDy);
    838     verts[2].fInnerOffset = SkPoint::Make(-innerRatioX - offsetDx, innerRatioY + offsetDy);
    839 
    840     verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom);
    841     verts[3].fOuterOffset = SkPoint::Make(1.0f + offsetDx, 1.0f + offsetDy);
    842     verts[3].fInnerOffset = SkPoint::Make(innerRatioX + offsetDx, innerRatioY + offsetDy);
    843 
    844     target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds);
    845 
    846     return true;
    847 }
    848 
    849 ///////////////////////////////////////////////////////////////////////////////
    850 
    851 static const uint16_t gRRectIndices[] = {
    852     // corners
    853     0, 1, 5, 0, 5, 4,
    854     2, 3, 7, 2, 7, 6,
    855     8, 9, 13, 8, 13, 12,
    856     10, 11, 15, 10, 15, 14,
    857 
    858     // edges
    859     1, 2, 6, 1, 6, 5,
    860     4, 5, 9, 4, 9, 8,
    861     6, 7, 11, 6, 11, 10,
    862     9, 10, 14, 9, 14, 13,
    863 
    864     // center
    865     // we place this at the end so that we can ignore these indices when rendering stroke-only
    866     5, 6, 10, 5, 10, 9
    867 };
    868 
    869 
    870 GrIndexBuffer* GrOvalRenderer::rRectIndexBuffer(GrGpu* gpu) {
    871     if (NULL == fRRectIndexBuffer) {
    872         fRRectIndexBuffer =
    873         gpu->createIndexBuffer(sizeof(gRRectIndices), false);
    874         if (NULL != fRRectIndexBuffer) {
    875 #ifdef SK_DEBUG
    876             bool updated =
    877 #endif
    878             fRRectIndexBuffer->updateData(gRRectIndices,
    879                                           sizeof(gRRectIndices));
    880             GR_DEBUGASSERT(updated);
    881         }
    882     }
    883     return fRRectIndexBuffer;
    884 }
    885 
    886 bool GrOvalRenderer::drawDRRect(GrDrawTarget* target, GrContext* context, bool useAA,
    887                                 const SkRRect& origOuter, const SkRRect& origInner) {
    888     bool applyAA = useAA &&
    889                    !target->getDrawState().getRenderTarget()->isMultisampled() &&
    890                    !target->shouldDisableCoverageAAForBlend();
    891     GrDrawState::AutoRestoreEffects are;
    892     if (!origInner.isEmpty()) {
    893         SkTCopyOnFirstWrite<SkRRect> inner(origInner);
    894         if (!context->getMatrix().isIdentity()) {
    895             if (!origInner.transform(context->getMatrix(), inner.writable())) {
    896                 return false;
    897             }
    898         }
    899         GrEffectEdgeType edgeType = applyAA ? kInverseFillAA_GrEffectEdgeType :
    900                                               kInverseFillBW_GrEffectEdgeType;
    901         GrEffectRef* effect = GrRRectEffect::Create(edgeType, *inner);
    902         if (NULL == effect) {
    903             return false;
    904         }
    905         are.set(target->drawState());
    906         target->drawState()->addCoverageEffect(effect)->unref();
    907     }
    908 
    909     SkStrokeRec fillRec(SkStrokeRec::kFill_InitStyle);
    910     if (this->drawRRect(target, context, useAA, origOuter, fillRec)) {
    911         return true;
    912     }
    913 
    914     SkASSERT(!origOuter.isEmpty());
    915     SkTCopyOnFirstWrite<SkRRect> outer(origOuter);
    916     if (!context->getMatrix().isIdentity()) {
    917         if (!origOuter.transform(context->getMatrix(), outer.writable())) {
    918             return false;
    919         }
    920     }
    921     GrEffectEdgeType edgeType = applyAA ? kFillAA_GrEffectEdgeType :
    922                                           kFillBW_GrEffectEdgeType;
    923     GrEffectRef* effect = GrRRectEffect::Create(edgeType, *outer);
    924     if (NULL == effect) {
    925         return false;
    926     }
    927     if (!are.isSet()) {
    928         are.set(target->drawState());
    929     }
    930     GrDrawState::AutoViewMatrixRestore avmr;
    931     if (!avmr.setIdentity(target->drawState())) {
    932         return false;
    933     }
    934     target->drawState()->addCoverageEffect(effect)->unref();
    935     SkRect bounds = outer->getBounds();
    936     if (applyAA) {
    937         bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
    938     }
    939     target->drawRect(bounds, NULL, NULL, NULL);
    940     return true;
    941 }
    942 
    943 bool GrOvalRenderer::drawRRect(GrDrawTarget* target, GrContext* context, bool useAA,
    944                                const SkRRect& rrect, const SkStrokeRec& stroke) {
    945     if (rrect.isOval()) {
    946         return this->drawOval(target, context, useAA, rrect.getBounds(), stroke);
    947     }
    948 
    949     bool useCoverageAA = useAA &&
    950         !target->getDrawState().getRenderTarget()->isMultisampled() &&
    951         !target->shouldDisableCoverageAAForBlend();
    952 
    953     // only anti-aliased rrects for now
    954     if (!useCoverageAA) {
    955         return false;
    956     }
    957 
    958     const SkMatrix& vm = context->getMatrix();
    959 
    960     if (!vm.rectStaysRect() || !rrect.isSimple()) {
    961         return false;
    962     }
    963 
    964     // do any matrix crunching before we reset the draw state for device coords
    965     const SkRect& rrectBounds = rrect.getBounds();
    966     SkRect bounds;
    967     vm.mapRect(&bounds, rrectBounds);
    968 
    969     SkVector radii = rrect.getSimpleRadii();
    970     SkScalar xRadius = SkScalarAbs(vm[SkMatrix::kMScaleX]*radii.fX +
    971                                    vm[SkMatrix::kMSkewY]*radii.fY);
    972     SkScalar yRadius = SkScalarAbs(vm[SkMatrix::kMSkewX]*radii.fX +
    973                                    vm[SkMatrix::kMScaleY]*radii.fY);
    974 
    975     SkStrokeRec::Style style = stroke.getStyle();
    976 
    977     // do (potentially) anisotropic mapping of stroke
    978     SkVector scaledStroke;
    979     SkScalar strokeWidth = stroke.getWidth();
    980 
    981     bool isStrokeOnly = SkStrokeRec::kStroke_Style == style ||
    982                         SkStrokeRec::kHairline_Style == style;
    983     bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style;
    984 
    985     if (hasStroke) {
    986         if (SkStrokeRec::kHairline_Style == style) {
    987             scaledStroke.set(1, 1);
    988         } else {
    989             scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] +
    990                                                        vm[SkMatrix::kMSkewY]));
    991             scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] +
    992                                                        vm[SkMatrix::kMScaleY]));
    993         }
    994 
    995         // if half of strokewidth is greater than radius, we don't handle that right now
    996         if (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStroke.fY > yRadius) {
    997             return false;
    998         }
    999     }
   1000 
   1001     // The way the effect interpolates the offset-to-ellipse/circle-center attribute only works on
   1002     // the interior of the rrect if the radii are >= 0.5. Otherwise, the inner rect of the nine-
   1003     // patch will have fractional coverage. This only matters when the interior is actually filled.
   1004     // We could consider falling back to rect rendering here, since a tiny radius is
   1005     // indistinguishable from a square corner.
   1006     if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) {
   1007         return false;
   1008     }
   1009 
   1010     // reset to device coordinates
   1011     GrDrawState* drawState = target->drawState();
   1012     GrDrawState::AutoViewMatrixRestore avmr;
   1013     if (!avmr.setIdentity(drawState)) {
   1014         return false;
   1015     }
   1016 
   1017     GrIndexBuffer* indexBuffer = this->rRectIndexBuffer(context->getGpu());
   1018     if (NULL == indexBuffer) {
   1019         GrPrintf("Failed to create index buffer!\n");
   1020         return false;
   1021     }
   1022 
   1023     // if the corners are circles, use the circle renderer
   1024     if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius) {
   1025         drawState->setVertexAttribs<gCircleVertexAttribs>(SK_ARRAY_COUNT(gCircleVertexAttribs));
   1026         SkASSERT(sizeof(CircleVertex) == drawState->getVertexSize());
   1027 
   1028         GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0);
   1029         if (!geo.succeeded()) {
   1030             GrPrintf("Failed to get space for vertices!\n");
   1031             return false;
   1032         }
   1033         CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices());
   1034 
   1035         SkScalar innerRadius = 0.0f;
   1036         SkScalar outerRadius = xRadius;
   1037         SkScalar halfWidth = 0;
   1038         if (hasStroke) {
   1039             if (SkScalarNearlyZero(scaledStroke.fX)) {
   1040                 halfWidth = SK_ScalarHalf;
   1041             } else {
   1042                 halfWidth = SkScalarHalf(scaledStroke.fX);
   1043             }
   1044 
   1045             if (isStrokeOnly) {
   1046                 innerRadius = xRadius - halfWidth;
   1047             }
   1048             outerRadius += halfWidth;
   1049             bounds.outset(halfWidth, halfWidth);
   1050         }
   1051 
   1052         isStrokeOnly = (isStrokeOnly && innerRadius >= 0);
   1053 
   1054         GrEffectRef* effect = CircleEdgeEffect::Create(isStrokeOnly);
   1055         static const int kCircleEdgeAttrIndex = 1;
   1056         drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref();
   1057 
   1058         // The radii are outset for two reasons. First, it allows the shader to simply perform
   1059         // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the
   1060         // verts of the bounding box that is rendered and the outset ensures the box will cover all
   1061         // pixels partially covered by the circle.
   1062         outerRadius += SK_ScalarHalf;
   1063         innerRadius -= SK_ScalarHalf;
   1064 
   1065         // Expand the rect so all the pixels will be captured.
   1066         bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
   1067 
   1068         SkScalar yCoords[4] = {
   1069             bounds.fTop,
   1070             bounds.fTop + outerRadius,
   1071             bounds.fBottom - outerRadius,
   1072             bounds.fBottom
   1073         };
   1074         SkScalar yOuterRadii[4] = {
   1075             -outerRadius,
   1076             0,
   1077             0,
   1078             outerRadius
   1079         };
   1080         for (int i = 0; i < 4; ++i) {
   1081             verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]);
   1082             verts->fOffset = SkPoint::Make(-outerRadius, yOuterRadii[i]);
   1083             verts->fOuterRadius = outerRadius;
   1084             verts->fInnerRadius = innerRadius;
   1085             verts++;
   1086 
   1087             verts->fPos = SkPoint::Make(bounds.fLeft + outerRadius, yCoords[i]);
   1088             verts->fOffset = SkPoint::Make(0, yOuterRadii[i]);
   1089             verts->fOuterRadius = outerRadius;
   1090             verts->fInnerRadius = innerRadius;
   1091             verts++;
   1092 
   1093             verts->fPos = SkPoint::Make(bounds.fRight - outerRadius, yCoords[i]);
   1094             verts->fOffset = SkPoint::Make(0, yOuterRadii[i]);
   1095             verts->fOuterRadius = outerRadius;
   1096             verts->fInnerRadius = innerRadius;
   1097             verts++;
   1098 
   1099             verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]);
   1100             verts->fOffset = SkPoint::Make(outerRadius, yOuterRadii[i]);
   1101             verts->fOuterRadius = outerRadius;
   1102             verts->fInnerRadius = innerRadius;
   1103             verts++;
   1104         }
   1105 
   1106         // drop out the middle quad if we're stroked
   1107         int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 :
   1108                                       SK_ARRAY_COUNT(gRRectIndices);
   1109         target->setIndexSourceToBuffer(indexBuffer);
   1110         target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bounds);
   1111 
   1112     // otherwise we use the ellipse renderer
   1113     } else {
   1114         drawState->setVertexAttribs<gEllipseVertexAttribs>(SK_ARRAY_COUNT(gEllipseVertexAttribs));
   1115         SkASSERT(sizeof(EllipseVertex) == drawState->getVertexSize());
   1116 
   1117         SkScalar innerXRadius = 0.0f;
   1118         SkScalar innerYRadius = 0.0f;
   1119         if (hasStroke) {
   1120             if (SkScalarNearlyZero(scaledStroke.length())) {
   1121                 scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf);
   1122             } else {
   1123                 scaledStroke.scale(SK_ScalarHalf);
   1124             }
   1125 
   1126             // we only handle thick strokes for near-circular ellipses
   1127             if (scaledStroke.length() > SK_ScalarHalf &&
   1128                 (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)) {
   1129                 return false;
   1130             }
   1131 
   1132             // we don't handle it if curvature of the stroke is less than curvature of the ellipse
   1133             if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStroke.fY)*xRadius ||
   1134                 scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStroke.fX)*yRadius) {
   1135                 return false;
   1136             }
   1137 
   1138             // this is legit only if scale & translation (which should be the case at the moment)
   1139             if (isStrokeOnly) {
   1140                 innerXRadius = xRadius - scaledStroke.fX;
   1141                 innerYRadius = yRadius - scaledStroke.fY;
   1142             }
   1143 
   1144             xRadius += scaledStroke.fX;
   1145             yRadius += scaledStroke.fY;
   1146             bounds.outset(scaledStroke.fX, scaledStroke.fY);
   1147         }
   1148 
   1149         isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0);
   1150 
   1151         GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0);
   1152         if (!geo.succeeded()) {
   1153             GrPrintf("Failed to get space for vertices!\n");
   1154             return false;
   1155         }
   1156         EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices());
   1157 
   1158         GrEffectRef* effect = EllipseEdgeEffect::Create(isStrokeOnly);
   1159         static const int kEllipseOffsetAttrIndex = 1;
   1160         static const int kEllipseRadiiAttrIndex = 2;
   1161         drawState->addCoverageEffect(effect,
   1162                                      kEllipseOffsetAttrIndex, kEllipseRadiiAttrIndex)->unref();
   1163 
   1164         // Compute the reciprocals of the radii here to save time in the shader
   1165         SkScalar xRadRecip = SkScalarInvert(xRadius);
   1166         SkScalar yRadRecip = SkScalarInvert(yRadius);
   1167         SkScalar xInnerRadRecip = SkScalarInvert(innerXRadius);
   1168         SkScalar yInnerRadRecip = SkScalarInvert(innerYRadius);
   1169 
   1170         // Extend the radii out half a pixel to antialias.
   1171         SkScalar xOuterRadius = xRadius + SK_ScalarHalf;
   1172         SkScalar yOuterRadius = yRadius + SK_ScalarHalf;
   1173 
   1174         // Expand the rect so all the pixels will be captured.
   1175         bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
   1176 
   1177         SkScalar yCoords[4] = {
   1178             bounds.fTop,
   1179             bounds.fTop + yOuterRadius,
   1180             bounds.fBottom - yOuterRadius,
   1181             bounds.fBottom
   1182         };
   1183         SkScalar yOuterOffsets[4] = {
   1184             yOuterRadius,
   1185             SK_ScalarNearlyZero, // we're using inversesqrt() in the shader, so can't be exactly 0
   1186             SK_ScalarNearlyZero,
   1187             yOuterRadius
   1188         };
   1189 
   1190         for (int i = 0; i < 4; ++i) {
   1191             verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]);
   1192             verts->fOffset = SkPoint::Make(xOuterRadius, yOuterOffsets[i]);
   1193             verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
   1194             verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
   1195             verts++;
   1196 
   1197             verts->fPos = SkPoint::Make(bounds.fLeft + xOuterRadius, yCoords[i]);
   1198             verts->fOffset = SkPoint::Make(SK_ScalarNearlyZero, yOuterOffsets[i]);
   1199             verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
   1200             verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
   1201             verts++;
   1202 
   1203             verts->fPos = SkPoint::Make(bounds.fRight - xOuterRadius, yCoords[i]);
   1204             verts->fOffset = SkPoint::Make(SK_ScalarNearlyZero, yOuterOffsets[i]);
   1205             verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
   1206             verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
   1207             verts++;
   1208 
   1209             verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]);
   1210             verts->fOffset = SkPoint::Make(xOuterRadius, yOuterOffsets[i]);
   1211             verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip);
   1212             verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip);
   1213             verts++;
   1214         }
   1215 
   1216         // drop out the middle quad if we're stroked
   1217         int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 :
   1218                                       SK_ARRAY_COUNT(gRRectIndices);
   1219         target->setIndexSourceToBuffer(indexBuffer);
   1220         target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bounds);
   1221     }
   1222 
   1223     return true;
   1224 }
   1225