1e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger/* 2e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger * Copyright 2013 Google Inc. 3e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger * 4e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger * Use of this source code is governed by a BSD-style license that can be 5e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger * found in the LICENSE file. 6e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger */ 7e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 8e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#include "GrOvalRenderer.h" 9e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "GrEffect.h" 117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "gl/GrGLEffect.h" 127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "gl/GrGLSL.h" 137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "GrTBackendEffectFactory.h" 14e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 15e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#include "GrDrawState.h" 16e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#include "GrDrawTarget.h" 177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "GrGpu.h" 187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkRRect.h" 20e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#include "SkStrokeRec.h" 21e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 22e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek SollenbergerSK_DEFINE_INST_COUNT(GrOvalRenderer) 23e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 24e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergernamespace { 25e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 26e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergerstruct CircleVertex { 277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrPoint fPos; 287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrPoint fOffset; 29e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkScalar fOuterRadius; 30e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkScalar fInnerRadius; 31e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger}; 32e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 33e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergerstruct EllipseVertex { 347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrPoint fPos; 357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrPoint fOffset; 367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrPoint fOuterRadii; 377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrPoint fInnerRadii; 38e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger}; 39e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 40e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergerinline bool circle_stays_circle(const SkMatrix& m) { 41e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return m.isSimilarity(); 42e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger} 43e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 44e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger} 45e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/** 497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * The output of this effect is a modulation of the input color and coverage for a circle, 507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * specified as offset_x, offset_y (both from center point), outer radius and inner radius. 517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger */ 527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerclass CircleEdgeEffect : public GrEffect { 547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerpublic: 557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger static GrEffectRef* Create(bool stroke) { 567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GR_CREATE_STATIC_EFFECT(gCircleStrokeEdge, CircleEdgeEffect, (true)); 577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GR_CREATE_STATIC_EFFECT(gCircleFillEdge, CircleEdgeEffect, (false)); 587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (stroke) { 607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger gCircleStrokeEdge->ref(); 617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return gCircleStrokeEdge; 627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } else { 637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger gCircleFillEdge->ref(); 647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return gCircleFillEdge; 657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger virtual void getConstantColorComponents(GrColor* color, 697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger uint32_t* validFlags) const SK_OVERRIDE { 707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *validFlags = 0; 717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return GrTBackendEffectFactory<CircleEdgeEffect>::getInstance(); 757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger virtual ~CircleEdgeEffect() {} 787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger static const char* Name() { return "CircleEdge"; } 807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger inline bool isStroked() const { return fStroke; } 827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger class GLEffect : public GrGLEffect { 847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger public: 857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger : INHERITED (factory) {} 877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger virtual void emitCode(GrGLShaderBuilder* builder, 897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const GrDrawEffect& drawEffect, 907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger EffectKey key, 917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const char* outputColor, 927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const char* inputColor, 937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const TextureSamplerArray& samplers) SK_OVERRIDE { 947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const CircleEdgeEffect& circleEffect = drawEffect.castEffect<CircleEdgeEffect>(); 957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const char *vsName, *fsName; 967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->addVarying(kVec4f_GrSLType, "CircleEdge", &vsName, &fsName); 977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const SkString* attrName = 997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); 1007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str()); 1017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->fsCodeAppendf("\tfloat d = length(%s.xy);\n", fsName); 1037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->fsCodeAppendf("\tfloat edgeAlpha = clamp(%s.z - d, 0.0, 1.0);\n", fsName); 1047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (circleEffect.isStroked()) { 1057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->fsCodeAppendf("\tfloat innerAlpha = clamp(d - %s.w, 0.0, 1.0);\n", fsName); 1067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->fsCodeAppend("\tedgeAlpha *= innerAlpha;\n"); 1077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 1087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkString modulate; 1107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha"); 1117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); 1127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 1137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 1157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const CircleEdgeEffect& circleEffect = drawEffect.castEffect<CircleEdgeEffect>(); 1167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return circleEffect.isStroked() ? 0x1 : 0x0; 1187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 1197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} 1217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger private: 1237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger typedef GrGLEffect INHERITED; 1247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger }; 1257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerprivate: 1287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger CircleEdgeEffect(bool stroke) : GrEffect() { 1297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger this->addVertexAttrib(kVec4f_GrSLType); 1307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger fStroke = stroke; 1317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 1327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { 1347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const CircleEdgeEffect& cee = CastEffect<CircleEdgeEffect>(other); 1357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return cee.fStroke == fStroke; 1367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 1377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bool fStroke; 1397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GR_DECLARE_EFFECT_TEST; 1417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger typedef GrEffect INHERITED; 1437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}; 1447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerGR_DEFINE_EFFECT_TEST(CircleEdgeEffect); 1467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerGrEffectRef* CircleEdgeEffect::TestCreate(SkMWCRandom* random, 1487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrContext* context, 1497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const GrDrawTargetCaps&, 1507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrTexture* textures[]) { 1517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return CircleEdgeEffect::Create(random->nextBool()); 1527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 1537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 1557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/** 1577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * The output of this effect is a modulation of the input color and coverage for an axis-aligned 1587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * ellipse, specified as a 2D offset from center, and the reciprocals of the outer and inner radii, 1597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * in both x and y directions. 1607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * 1617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * We are using an implicit function of x^2/a^2 + y^2/b^2 - 1 = 0. 1627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger */ 1637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerclass EllipseEdgeEffect : public GrEffect { 1657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerpublic: 1667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger static GrEffectRef* Create(bool stroke) { 1677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GR_CREATE_STATIC_EFFECT(gEllipseStrokeEdge, EllipseEdgeEffect, (true)); 1687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GR_CREATE_STATIC_EFFECT(gEllipseFillEdge, EllipseEdgeEffect, (false)); 1697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (stroke) { 1717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger gEllipseStrokeEdge->ref(); 1727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return gEllipseStrokeEdge; 1737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } else { 1747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger gEllipseFillEdge->ref(); 1757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return gEllipseFillEdge; 1767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 1777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 1787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger virtual void getConstantColorComponents(GrColor* color, 1807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger uint32_t* validFlags) const SK_OVERRIDE { 1817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *validFlags = 0; 1827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 1837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 1857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return GrTBackendEffectFactory<EllipseEdgeEffect>::getInstance(); 1867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 1877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger virtual ~EllipseEdgeEffect() {} 1897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger static const char* Name() { return "EllipseEdge"; } 1917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger inline bool isStroked() const { return fStroke; } 1937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger class GLEffect : public GrGLEffect { 1957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger public: 1967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 1977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger : INHERITED (factory) {} 1987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger virtual void emitCode(GrGLShaderBuilder* builder, 2007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const GrDrawEffect& drawEffect, 2017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger EffectKey key, 2027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const char* outputColor, 2037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const char* inputColor, 2047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const TextureSamplerArray& samplers) SK_OVERRIDE { 2057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<EllipseEdgeEffect>(); 2067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const char *vsOffsetName, *fsOffsetName; 2087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const char *vsRadiiName, *fsRadiiName; 2097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->addVarying(kVec2f_GrSLType, "EllipseOffsets", &vsOffsetName, &fsOffsetName); 2117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const SkString* attr0Name = 2127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]); 2137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->vsCodeAppendf("\t%s = %s;\n", vsOffsetName, attr0Name->c_str()); 2147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->addVarying(kVec4f_GrSLType, "EllipseRadii", &vsRadiiName, &fsRadiiName); 2167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const SkString* attr1Name = 2177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[1]); 2187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->vsCodeAppendf("\t%s = %s;\n", vsRadiiName, attr1Name->c_str()); 2197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // for outer curve 2217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->fsCodeAppendf("\tvec2 scaledOffset = %s*%s.xy;\n", fsOffsetName, fsRadiiName); 2227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->fsCodeAppend("\tfloat test = dot(scaledOffset, scaledOffset) - 1.0;\n"); 2237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->fsCodeAppendf("\tvec2 grad = 2.0*scaledOffset*%s.xy;\n", fsRadiiName); 22458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger builder->fsCodeAppend("\tfloat grad_dot = dot(grad, grad);\n"); 22558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger // we need to clamp the length^2 of the gradiant vector to a non-zero value, because 22658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger // on the Nexus 4 the undefined result of inversesqrt(0) drops out an entire tile 22758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger // TODO: restrict this to Adreno-only 22858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger builder->fsCodeAppend("\tgrad_dot = max(grad_dot, 1.0e-4);\n"); 22958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger builder->fsCodeAppend("\tfloat invlen = inversesqrt(grad_dot);\n"); 2307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->fsCodeAppend("\tfloat edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);\n"); 2317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // for inner curve 2337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (ellipseEffect.isStroked()) { 2347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->fsCodeAppendf("\tscaledOffset = %s*%s.zw;\n", fsOffsetName, fsRadiiName); 2357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->fsCodeAppend("\ttest = dot(scaledOffset, scaledOffset) - 1.0;\n"); 2367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->fsCodeAppendf("\tgrad = 2.0*scaledOffset*%s.zw;\n", fsRadiiName); 2377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->fsCodeAppend("\tinvlen = inversesqrt(dot(grad, grad));\n"); 2387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->fsCodeAppend("\tedgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);\n"); 2397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 2407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkString modulate; 2427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha"); 2437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str()); 2447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 2457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 2477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const EllipseEdgeEffect& ellipseEffect = drawEffect.castEffect<EllipseEdgeEffect>(); 2487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return ellipseEffect.isStroked() ? 0x1 : 0x0; 2507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 2517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE { 2537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 2547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger private: 2567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger typedef GrGLEffect INHERITED; 2577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger }; 2587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerprivate: 2607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger EllipseEdgeEffect(bool stroke) : GrEffect() { 2617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger this->addVertexAttrib(kVec2f_GrSLType); 2627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger this->addVertexAttrib(kVec4f_GrSLType); 2637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger fStroke = stroke; 2647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 2657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { 2677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const EllipseEdgeEffect& eee = CastEffect<EllipseEdgeEffect>(other); 2687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return eee.fStroke == fStroke; 2697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 2707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bool fStroke; 2727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GR_DECLARE_EFFECT_TEST; 2747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger typedef GrEffect INHERITED; 2767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}; 2777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerGR_DEFINE_EFFECT_TEST(EllipseEdgeEffect); 2797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerGrEffectRef* EllipseEdgeEffect::TestCreate(SkMWCRandom* random, 2817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrContext* context, 2827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const GrDrawTargetCaps&, 2837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrTexture* textures[]) { 2847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return EllipseEdgeEffect::Create(random->nextBool()); 2857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 2867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 2887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 28958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergervoid GrOvalRenderer::reset() { 29058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger GrSafeSetNull(fRRectIndexBuffer); 29158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger} 29258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 2937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerbool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, bool useAA, 29458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger const SkRect& oval, const SkStrokeRec& stroke) 295e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger{ 2967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (!useAA) { 297e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return false; 298e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 299e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 300e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger const SkMatrix& vm = context->getMatrix(); 301e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 302e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // we can draw circles 303e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (SkScalarNearlyEqual(oval.width(), oval.height()) 304e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger && circle_stays_circle(vm)) { 3057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger this->drawCircle(target, useAA, oval, stroke); 306e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 307e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // and axis-aligned ellipses only 308e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } else if (vm.rectStaysRect()) { 3097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return this->drawEllipse(target, useAA, oval, stroke); 310e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 311e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } else { 312e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return false; 313e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 314e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 315e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return true; 316e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger} 317e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 3187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergernamespace { 3197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 3207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 3217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 3227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// position + edge 3237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerextern const GrVertexAttrib gCircleVertexAttribs[] = { 3247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 3257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger {kVec4f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} 3267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}; 3277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 3287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}; 3297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 330e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenbergervoid GrOvalRenderer::drawCircle(GrDrawTarget* target, 3317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bool useAA, 33258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger const SkRect& circle, 333e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger const SkStrokeRec& stroke) 334e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger{ 335e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger GrDrawState* drawState = target->drawState(); 336e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 337e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger const SkMatrix& vm = drawState->getViewMatrix(); 338e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger GrPoint center = GrPoint::Make(circle.centerX(), circle.centerY()); 339e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger vm.mapPoints(¢er, 1); 340e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkScalar radius = vm.mapRadius(SkScalarHalf(circle.width())); 341e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkScalar strokeWidth = vm.mapRadius(stroke.getWidth()); 342e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 34358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger GrDrawState::AutoViewMatrixRestore avmr; 34458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (!avmr.setIdentity(drawState)) { 345e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return; 346e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 347e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 3487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger drawState->setVertexAttribs<gCircleVertexAttribs>(SK_ARRAY_COUNT(gCircleVertexAttribs)); 349e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger GrAssert(sizeof(CircleVertex) == drawState->getVertexSize()); 350e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 351e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); 352e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (!geo.succeeded()) { 353e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger GrPrintf("Failed to get space for vertices!\n"); 354e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger return; 355e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 356e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 357e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); 358e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 359e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkStrokeRec::Style style = stroke.getStyle(); 360e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style); 361e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 3627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrEffectRef* effect = CircleEdgeEffect::Create(isStroked); 363e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger static const int kCircleEdgeAttrIndex = 1; 36458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref(); 365e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 366e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkScalar innerRadius = 0.0f; 367e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkScalar outerRadius = radius; 368e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger SkScalar halfWidth = 0; 369e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (style != SkStrokeRec::kFill_Style) { 370e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (SkScalarNearlyZero(strokeWidth)) { 371e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger halfWidth = SK_ScalarHalf; 372e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } else { 373e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger halfWidth = SkScalarHalf(strokeWidth); 374e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 375e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 376e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger outerRadius += halfWidth; 377e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (isStroked) { 3787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger innerRadius = radius - halfWidth; 3797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger isStroked = (innerRadius > 0); 380e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 381e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 382e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 3837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // The radii are outset for two reasons. First, it allows the shader to simply perform 3847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the 3857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // verts of the bounding box that is rendered and the outset ensures the box will cover all 3867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // pixels partially covered by the circle. 3877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger outerRadius += SK_ScalarHalf; 3887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger innerRadius -= SK_ScalarHalf; 3897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 3907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkRect bounds = SkRect::MakeLTRB( 3917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger center.fX - outerRadius, 3927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger center.fY - outerRadius, 3937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger center.fX + outerRadius, 3947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger center.fY + outerRadius 3957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger ); 3967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 3977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop); 3987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[0].fOffset = SkPoint::Make(-outerRadius, -outerRadius); 3997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[0].fOuterRadius = outerRadius; 4007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[0].fInnerRadius = innerRadius; 4017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 4027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[1].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); 4037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[1].fOffset = SkPoint::Make(outerRadius, -outerRadius); 4047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[1].fOuterRadius = outerRadius; 4057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[1].fInnerRadius = innerRadius; 4067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 4077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[2].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom); 4087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[2].fOffset = SkPoint::Make(-outerRadius, outerRadius); 4097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[2].fOuterRadius = outerRadius; 4107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[2].fInnerRadius = innerRadius; 4117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 4127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); 4137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[3].fOffset = SkPoint::Make(outerRadius, outerRadius); 4147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[3].fOuterRadius = outerRadius; 4157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[3].fInnerRadius = innerRadius; 4167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 4177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds); 4187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 419e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 4207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 421e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 4227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergernamespace { 423e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 4247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// position + edge 4257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerextern const GrVertexAttrib gEllipseVertexAttribs[] = { 4267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, 4277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}, 4287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger {kVec4f_GrVertexAttribType, 2*sizeof(GrPoint), kEffect_GrVertexAttribBinding} 4297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}; 430e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 4317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}; 432e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 4337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerbool GrOvalRenderer::drawEllipse(GrDrawTarget* target, 4347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bool useAA, 43558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger const SkRect& ellipse, 436e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger const SkStrokeRec& stroke) 437e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger{ 438e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger GrDrawState* drawState = target->drawState(); 439e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#ifdef SK_DEBUG 440e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger { 441e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger // we should have checked for this previously 442e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger bool isAxisAlignedEllipse = drawState->getViewMatrix().rectStaysRect(); 4437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkASSERT(useAA && isAxisAlignedEllipse); 444e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 445e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger#endif 446e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 4477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // do any matrix crunching before we reset the draw state for device coords 448e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger const SkMatrix& vm = drawState->getViewMatrix(); 449e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger GrPoint center = GrPoint::Make(ellipse.centerX(), ellipse.centerY()); 450e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger vm.mapPoints(¢er, 1); 4517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar ellipseXRadius = SkScalarHalf(ellipse.width()); 4527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar ellipseYRadius = SkScalarHalf(ellipse.height()); 4537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar xRadius = SkScalarAbs(vm[SkMatrix::kMScaleX]*ellipseXRadius + 4547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger vm[SkMatrix::kMSkewY]*ellipseYRadius); 4557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar yRadius = SkScalarAbs(vm[SkMatrix::kMSkewX]*ellipseXRadius + 4567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger vm[SkMatrix::kMScaleY]*ellipseYRadius); 4577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 4587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // do (potentially) anisotropic mapping of stroke 4597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkVector scaledStroke; 4607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar strokeWidth = stroke.getWidth(); 4617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] + vm[SkMatrix::kMSkewY])); 4627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] + vm[SkMatrix::kMScaleY])); 4637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 4647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkStrokeRec::Style style = stroke.getStyle(); 4657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style); 4667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 4677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar innerXRadius = 0.0f; 4687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar innerYRadius = 0.0f; 4697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (SkStrokeRec::kFill_Style != style) { 4707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (SkScalarNearlyZero(scaledStroke.length())) { 4717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); 4727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } else { 4737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger scaledStroke.scale(SK_ScalarHalf); 4747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 4757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 4767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // we only handle thick strokes for near-circular ellipses 4777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (scaledStroke.length() > SK_ScalarHalf && 4787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)) { 4797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 4807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 4817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 4827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // we don't handle it if curvature of the stroke is less than curvature of the ellipse 4837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStroke.fY)*xRadius || 4847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStroke.fX)*yRadius) { 4857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 4867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 4877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 4887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // this is legit only if scale & translation (which should be the case at the moment) 4897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (isStroked) { 4907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger innerXRadius = xRadius - scaledStroke.fX; 4917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger innerYRadius = yRadius - scaledStroke.fY; 4927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger isStroked = (innerXRadius > 0 && innerYRadius > 0); 4937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 4947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 4957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger xRadius += scaledStroke.fX; 4967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger yRadius += scaledStroke.fY; 4977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 498e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 49958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger GrDrawState::AutoViewMatrixRestore avmr; 50058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (!avmr.setIdentity(drawState)) { 5017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 502e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 503e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 5047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger drawState->setVertexAttribs<gEllipseVertexAttribs>(SK_ARRAY_COUNT(gEllipseVertexAttribs)); 505e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger GrAssert(sizeof(EllipseVertex) == drawState->getVertexSize()); 506e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 507e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0); 508e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger if (!geo.succeeded()) { 509e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger GrPrintf("Failed to get space for vertices!\n"); 5107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 511e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 512e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 513e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); 514e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 5157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrEffectRef* effect = EllipseEdgeEffect::Create(isStroked); 516e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 517e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger static const int kEllipseCenterAttrIndex = 1; 518e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger static const int kEllipseEdgeAttrIndex = 2; 51958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger drawState->addCoverageEffect(effect, kEllipseCenterAttrIndex, kEllipseEdgeAttrIndex)->unref(); 520e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 5217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // Compute the reciprocals of the radii here to save time in the shader 5227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar xRadRecip = SkScalarInvert(xRadius); 5237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar yRadRecip = SkScalarInvert(yRadius); 5247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar xInnerRadRecip = SkScalarInvert(innerXRadius); 5257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar yInnerRadRecip = SkScalarInvert(innerYRadius); 526e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 5277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // We've extended the outer x radius out half a pixel to antialias. 5287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // This will also expand the rect so all the pixels will be captured. 5297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // TODO: Consider if we should use sqrt(2)/2 instead 5307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger xRadius += SK_ScalarHalf; 5317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger yRadius += SK_ScalarHalf; 5327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkRect bounds = SkRect::MakeLTRB( 5347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger center.fX - xRadius, 5357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger center.fY - yRadius, 5367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger center.fX + xRadius, 5377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger center.fY + yRadius 5387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger ); 5397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[0].fPos = SkPoint::Make(bounds.fLeft, bounds.fTop); 5417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[0].fOffset = SkPoint::Make(-xRadius, -yRadius); 5427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[0].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 5437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[0].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 5447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[1].fPos = SkPoint::Make(bounds.fRight, bounds.fTop); 5467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[1].fOffset = SkPoint::Make(xRadius, -yRadius); 5477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[1].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 5487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[1].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 5497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[2].fPos = SkPoint::Make(bounds.fLeft, bounds.fBottom); 5517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[2].fOffset = SkPoint::Make(-xRadius, yRadius); 5527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[2].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 5537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[2].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 5547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[3].fPos = SkPoint::Make(bounds.fRight, bounds.fBottom); 5567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[3].fOffset = SkPoint::Make(xRadius, yRadius); 5577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[3].fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 5587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts[3].fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 5597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4, &bounds); 561e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 5627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return true; 5637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 564e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 5657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 566e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 5677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerstatic const uint16_t gRRectIndices[] = { 5687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // corners 5697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 0, 1, 5, 0, 5, 4, 5707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 2, 3, 7, 2, 7, 6, 5717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 8, 9, 13, 8, 13, 12, 5727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 10, 11, 15, 10, 15, 14, 5737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // edges 5757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 1, 2, 6, 1, 6, 5, 5767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 4, 5, 9, 4, 9, 8, 5777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6, 7, 11, 6, 11, 10, 5787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 9, 10, 14, 9, 14, 13, 5797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // center 5817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // we place this at the end so that we can ignore these indices when rendering stroke-only 5827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5, 6, 10, 5, 10, 9 5837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}; 5847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 5867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerGrIndexBuffer* GrOvalRenderer::rRectIndexBuffer(GrGpu* gpu) { 5877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (NULL == fRRectIndexBuffer) { 5887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger fRRectIndexBuffer = 5897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger gpu->createIndexBuffer(sizeof(gRRectIndices), false); 5907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (NULL != fRRectIndexBuffer) { 5917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#if GR_DEBUG 5927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bool updated = 5937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif 5947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger fRRectIndexBuffer->updateData(gRRectIndices, 5957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger sizeof(gRRectIndices)); 5967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GR_DEBUGASSERT(updated); 597e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 598e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 5997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return fRRectIndexBuffer; 6007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 601e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 6027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerbool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, bool useAA, 6037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const SkRRect& rrect, const SkStrokeRec& stroke) 6047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger{ 6057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // only anti-aliased rrects for now 6067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (!useAA) { 6077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 6087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 609e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 6107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const SkMatrix& vm = context->getMatrix(); 6117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#ifdef SK_DEBUG 6127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger { 6137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // we should have checked for this previously 6147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkASSERT(useAA && vm.rectStaysRect() && rrect.isSimple()); 615e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger } 6167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif 617e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 6187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // do any matrix crunching before we reset the draw state for device coords 6197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger const SkRect& rrectBounds = rrect.getBounds(); 6207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkRect bounds; 6217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger vm.mapRect(&bounds, rrectBounds); 622e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger 6237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkVector radii = rrect.getSimpleRadii(); 6247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar xRadius = SkScalarAbs(vm[SkMatrix::kMScaleX]*radii.fX + 6257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger vm[SkMatrix::kMSkewY]*radii.fY); 6267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar yRadius = SkScalarAbs(vm[SkMatrix::kMSkewX]*radii.fX + 6277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger vm[SkMatrix::kMScaleY]*radii.fY); 6287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // if hairline stroke is greater than radius, we don't handle that right now 6307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkStrokeRec::Style style = stroke.getStyle(); 6317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (SkStrokeRec::kHairline_Style == style && 6327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger (SK_ScalarHalf >= xRadius || SK_ScalarHalf >= yRadius)) { 6337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 6347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 6357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // do (potentially) anisotropic mapping of stroke 6377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkVector scaledStroke; 6387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar strokeWidth = stroke.getWidth(); 6397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] + vm[SkMatrix::kMSkewY])); 6407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] + vm[SkMatrix::kMScaleY])); 6417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // if half of strokewidth is greater than radius, we don't handle that right now 6437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (SK_ScalarHalf*scaledStroke.fX >= xRadius || SK_ScalarHalf*scaledStroke.fY >= yRadius) { 6447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 6457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 6467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // reset to device coordinates 6487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrDrawState* drawState = target->drawState(); 64958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger GrDrawState::AutoViewMatrixRestore avmr; 65058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (!avmr.setIdentity(drawState)) { 6517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 6527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 6537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style); 6557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrIndexBuffer* indexBuffer = this->rRectIndexBuffer(context->getGpu()); 6577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (NULL == indexBuffer) { 6587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrPrintf("Failed to create index buffer!\n"); 6597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 6607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 6617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // if the corners are circles, use the circle renderer 6637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if ((!isStroked || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius) { 6647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger drawState->setVertexAttribs<gCircleVertexAttribs>(SK_ARRAY_COUNT(gCircleVertexAttribs)); 6657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrAssert(sizeof(CircleVertex) == drawState->getVertexSize()); 6667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0); 6687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (!geo.succeeded()) { 6697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrPrintf("Failed to get space for vertices!\n"); 6707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 6717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 6727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); 6737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar innerRadius = 0.0f; 6757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar outerRadius = xRadius; 6767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar halfWidth = 0; 6777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (style != SkStrokeRec::kFill_Style) { 6787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (SkScalarNearlyZero(scaledStroke.fX)) { 6797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger halfWidth = SK_ScalarHalf; 6807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } else { 6817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger halfWidth = SkScalarHalf(scaledStroke.fX); 6827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 6837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (isStroked) { 6857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger innerRadius = xRadius - halfWidth; 6867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger isStroked = (innerRadius > 0); 6877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 6887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger outerRadius += halfWidth; 6897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bounds.outset(halfWidth, halfWidth); 6907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 6917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrEffectRef* effect = CircleEdgeEffect::Create(isStroked); 6937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger static const int kCircleEdgeAttrIndex = 1; 69458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref(); 6957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 6967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // The radii are outset for two reasons. First, it allows the shader to simply perform 6977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the 6987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // verts of the bounding box that is rendered and the outset ensures the box will cover all 6997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // pixels partially covered by the circle. 7007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger outerRadius += SK_ScalarHalf; 7017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger innerRadius -= SK_ScalarHalf; 7027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // Expand the rect so all the pixels will be captured. 7047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bounds.outset(SK_ScalarHalf, SK_ScalarHalf); 7057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar yCoords[4] = { 7077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bounds.fTop, 7087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bounds.fTop + outerRadius, 7097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bounds.fBottom - outerRadius, 7107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bounds.fBottom 7117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger }; 7127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar yOuterRadii[4] = { 7137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger -outerRadius, 7147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 0, 7157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 0, 7167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger outerRadius 7177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger }; 7187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger for (int i = 0; i < 4; ++i) { 7197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]); 7207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fOffset = SkPoint::Make(-outerRadius, yOuterRadii[i]); 7217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fOuterRadius = outerRadius; 7227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fInnerRadius = innerRadius; 7237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts++; 7247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fPos = SkPoint::Make(bounds.fLeft + outerRadius, yCoords[i]); 7267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fOffset = SkPoint::Make(0, yOuterRadii[i]); 7277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fOuterRadius = outerRadius; 7287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fInnerRadius = innerRadius; 7297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts++; 7307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fPos = SkPoint::Make(bounds.fRight - outerRadius, yCoords[i]); 7327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fOffset = SkPoint::Make(0, yOuterRadii[i]); 7337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fOuterRadius = outerRadius; 7347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fInnerRadius = innerRadius; 7357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts++; 7367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]); 7387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fOffset = SkPoint::Make(outerRadius, yOuterRadii[i]); 7397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fOuterRadius = outerRadius; 7407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fInnerRadius = innerRadius; 7417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts++; 7427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 7437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // drop out the middle quad if we're stroked 7457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger int indexCnt = isStroked ? GR_ARRAY_COUNT(gRRectIndices)-6 : GR_ARRAY_COUNT(gRRectIndices); 7467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger target->setIndexSourceToBuffer(indexBuffer); 7477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bounds); 7487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // otherwise we use the ellipse renderer 7507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } else { 7517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger drawState->setVertexAttribs<gEllipseVertexAttribs>(SK_ARRAY_COUNT(gEllipseVertexAttribs)); 7527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrAssert(sizeof(EllipseVertex) == drawState->getVertexSize()); 7537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar innerXRadius = 0.0f; 7557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar innerYRadius = 0.0f; 7567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (SkStrokeRec::kFill_Style != style) { 7577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (SkScalarNearlyZero(scaledStroke.length())) { 7587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger scaledStroke.set(SK_ScalarHalf, SK_ScalarHalf); 7597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } else { 7607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger scaledStroke.scale(SK_ScalarHalf); 7617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 7627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // we only handle thick strokes for near-circular ellipses 7647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (scaledStroke.length() > SK_ScalarHalf && 7657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger (SK_ScalarHalf*xRadius > yRadius || SK_ScalarHalf*yRadius > xRadius)) { 7667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 7677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 7687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // we don't handle it if curvature of the stroke is less than curvature of the ellipse 7707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (scaledStroke.fX*(yRadius*yRadius) < (scaledStroke.fY*scaledStroke.fY)*xRadius || 7717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger scaledStroke.fY*(xRadius*xRadius) < (scaledStroke.fX*scaledStroke.fX)*yRadius) { 7727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 7737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 7747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // this is legit only if scale & translation (which should be the case at the moment) 7767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (isStroked) { 7777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger innerXRadius = xRadius - scaledStroke.fX; 7787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger innerYRadius = yRadius - scaledStroke.fY; 7797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger isStroked = (innerXRadius > 0 && innerYRadius > 0); 7807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 7817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger xRadius += scaledStroke.fX; 7837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger yRadius += scaledStroke.fY; 7847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bounds.outset(scaledStroke.fX, scaledStroke.fY); 7857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 7867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrDrawTarget::AutoReleaseGeometry geo(target, 16, 0); 7887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger if (!geo.succeeded()) { 7897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrPrintf("Failed to get space for vertices!\n"); 7907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return false; 7917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 7927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); 7937839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 7947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger GrEffectRef* effect = EllipseEdgeEffect::Create(isStroked); 7957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger static const int kEllipseOffsetAttrIndex = 1; 7967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger static const int kEllipseRadiiAttrIndex = 2; 79758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger drawState->addCoverageEffect(effect, 79858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger kEllipseOffsetAttrIndex, kEllipseRadiiAttrIndex)->unref(); 7997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 8007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // Compute the reciprocals of the radii here to save time in the shader 8017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar xRadRecip = SkScalarInvert(xRadius); 8027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar yRadRecip = SkScalarInvert(yRadius); 8037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar xInnerRadRecip = SkScalarInvert(innerXRadius); 8047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar yInnerRadRecip = SkScalarInvert(innerYRadius); 8057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 8067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // Extend the radii out half a pixel to antialias. 8077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar xOuterRadius = xRadius + SK_ScalarHalf; 8087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar yOuterRadius = yRadius + SK_ScalarHalf; 8097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 8107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // Expand the rect so all the pixels will be captured. 8117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bounds.outset(SK_ScalarHalf, SK_ScalarHalf); 8127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 8137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar yCoords[4] = { 8147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bounds.fTop, 8157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bounds.fTop + yOuterRadius, 8167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bounds.fBottom - yOuterRadius, 8177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger bounds.fBottom 8187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger }; 8197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkScalar yOuterOffsets[4] = { 82058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger yOuterRadius, 8217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SK_ScalarNearlyZero, // we're using inversesqrt() in the shader, so can't be exactly 0 8227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SK_ScalarNearlyZero, 8237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger yOuterRadius 8247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger }; 8257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 8267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger for (int i = 0; i < 4; ++i) { 8277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]); 82858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger verts->fOffset = SkPoint::Make(xOuterRadius, yOuterOffsets[i]); 8297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 8307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 8317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts++; 8327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 8337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fPos = SkPoint::Make(bounds.fLeft + xOuterRadius, yCoords[i]); 8347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fOffset = SkPoint::Make(SK_ScalarNearlyZero, yOuterOffsets[i]); 8357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 8367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 8377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts++; 8387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 8397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fPos = SkPoint::Make(bounds.fRight - xOuterRadius, yCoords[i]); 8407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fOffset = SkPoint::Make(SK_ScalarNearlyZero, yOuterOffsets[i]); 8417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 8427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 8437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts++; 8447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 8457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]); 8467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fOffset = SkPoint::Make(xOuterRadius, yOuterOffsets[i]); 8477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); 8487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); 8497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger verts++; 8507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 8517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 8527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger // drop out the middle quad if we're stroked 8537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger int indexCnt = isStroked ? GR_ARRAY_COUNT(gRRectIndices)-6 : GR_ARRAY_COUNT(gRRectIndices); 8547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger target->setIndexSourceToBuffer(indexBuffer); 8557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger target->drawIndexed(kTriangles_GrPrimitiveType, 0, 0, 16, indexCnt, &bounds); 8567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger } 8577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 8587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return true; 859e2022cc36e47b9f0d219eb5cd24be61772c28d3bDerek Sollenberger} 860