| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrOvalRenderer.h" | 8 #include "GrOvalRenderer.h" |
| 9 | 9 |
| 10 #include "GrProcessor.h" | 10 #include "GrProcessor.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 * with origin at the circle center. Two vertex attributes are used: | 58 * with origin at the circle center. Two vertex attributes are used: |
| 59 * vec2f : position in device space of the bounding geometry vertices | 59 * vec2f : position in device space of the bounding geometry vertices |
| 60 * vec4f : (p.xy, outerRad, innerRad) | 60 * vec4f : (p.xy, outerRad, innerRad) |
| 61 * p is the position in the normalized space. | 61 * p is the position in the normalized space. |
| 62 * outerRad is the outerRadius in device space. | 62 * outerRad is the outerRadius in device space. |
| 63 * innerRad is the innerRadius in normalized space (ignored if not s
troking). | 63 * innerRad is the innerRadius in normalized space (ignored if not s
troking). |
| 64 */ | 64 */ |
| 65 | 65 |
| 66 class CircleEdgeEffect : public GrGeometryProcessor { | 66 class CircleEdgeEffect : public GrGeometryProcessor { |
| 67 public: | 67 public: |
| 68 static GrGeometryProcessor* Create(GrColor color, bool stroke) { | 68 static GrGeometryProcessor* Create(GrColor color, bool stroke, const SkMatri
x& localMatrix) { |
| 69 return SkNEW_ARGS(CircleEdgeEffect, (color, stroke)); | 69 return SkNEW_ARGS(CircleEdgeEffect, (color, stroke, localMatrix)); |
| 70 } | 70 } |
| 71 | 71 |
| 72 const GrAttribute* inPosition() const { return fInPosition; } | 72 const GrAttribute* inPosition() const { return fInPosition; } |
| 73 const GrAttribute* inCircleEdge() const { return fInCircleEdge; } | 73 const GrAttribute* inCircleEdge() const { return fInCircleEdge; } |
| 74 virtual ~CircleEdgeEffect() {} | 74 virtual ~CircleEdgeEffect() {} |
| 75 | 75 |
| 76 virtual const char* name() const SK_OVERRIDE { return "CircleEdge"; } | 76 virtual const char* name() const SK_OVERRIDE { return "CircleEdge"; } |
| 77 | 77 |
| 78 inline bool isStroked() const { return fStroke; } | 78 inline bool isStroked() const { return fStroke; } |
| 79 | 79 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 const GrBatchTracker& t) const SK_OVERRIDE { | 167 const GrBatchTracker& t) const SK_OVERRIDE { |
| 168 const BatchTracker& mine = m.cast<BatchTracker>(); | 168 const BatchTracker& mine = m.cast<BatchTracker>(); |
| 169 const BatchTracker& theirs = t.cast<BatchTracker>(); | 169 const BatchTracker& theirs = t.cast<BatchTracker>(); |
| 170 return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords, | 170 return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords, |
| 171 that, theirs.fUsesLocalCoords) && | 171 that, theirs.fUsesLocalCoords) && |
| 172 CanCombineOutput(mine.fInputColorType, mine.fColor, | 172 CanCombineOutput(mine.fInputColorType, mine.fColor, |
| 173 theirs.fInputColorType, theirs.fColor); | 173 theirs.fInputColorType, theirs.fColor); |
| 174 } | 174 } |
| 175 | 175 |
| 176 private: | 176 private: |
| 177 CircleEdgeEffect(GrColor color, bool stroke) : INHERITED(color) { | 177 CircleEdgeEffect(GrColor color, bool stroke, const SkMatrix& localMatrix) |
| 178 : INHERITED(color, false, localMatrix) { |
| 178 this->initClassID<CircleEdgeEffect>(); | 179 this->initClassID<CircleEdgeEffect>(); |
| 179 fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_Gr
VertexAttribType)); | 180 fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_Gr
VertexAttribType)); |
| 180 fInCircleEdge = &this->addVertexAttrib(GrAttribute("inCircleEdge", | 181 fInCircleEdge = &this->addVertexAttrib(GrAttribute("inCircleEdge", |
| 181 kVec4f_GrVertexAttrib
Type)); | 182 kVec4f_GrVertexAttrib
Type)); |
| 182 fStroke = stroke; | 183 fStroke = stroke; |
| 183 } | 184 } |
| 184 | 185 |
| 185 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { | 186 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { |
| 186 const CircleEdgeEffect& cee = other.cast<CircleEdgeEffect>(); | 187 const CircleEdgeEffect& cee = other.cast<CircleEdgeEffect>(); |
| 187 return cee.fStroke == fStroke; | 188 return cee.fStroke == fStroke; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 205 | 206 |
| 206 typedef GrGeometryProcessor INHERITED; | 207 typedef GrGeometryProcessor INHERITED; |
| 207 }; | 208 }; |
| 208 | 209 |
| 209 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(CircleEdgeEffect); | 210 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(CircleEdgeEffect); |
| 210 | 211 |
| 211 GrGeometryProcessor* CircleEdgeEffect::TestCreate(SkRandom* random, | 212 GrGeometryProcessor* CircleEdgeEffect::TestCreate(SkRandom* random, |
| 212 GrContext* context, | 213 GrContext* context, |
| 213 const GrDrawTargetCaps&, | 214 const GrDrawTargetCaps&, |
| 214 GrTexture* textures[]) { | 215 GrTexture* textures[]) { |
| 215 return CircleEdgeEffect::Create(GrRandomColor(random), random->nextBool()); | 216 return CircleEdgeEffect::Create(GrRandomColor(random), random->nextBool(), |
| 217 GrProcessorUnitTest::TestMatrix(random)); |
| 216 } | 218 } |
| 217 | 219 |
| 218 /////////////////////////////////////////////////////////////////////////////// | 220 /////////////////////////////////////////////////////////////////////////////// |
| 219 | 221 |
| 220 /** | 222 /** |
| 221 * The output of this effect is a modulation of the input color and coverage for
an axis-aligned | 223 * The output of this effect is a modulation of the input color and coverage for
an axis-aligned |
| 222 * ellipse, specified as a 2D offset from center, and the reciprocals of the out
er and inner radii, | 224 * ellipse, specified as a 2D offset from center, and the reciprocals of the out
er and inner radii, |
| 223 * in both x and y directions. | 225 * in both x and y directions. |
| 224 * | 226 * |
| 225 * We are using an implicit function of x^2/a^2 + y^2/b^2 - 1 = 0. | 227 * We are using an implicit function of x^2/a^2 + y^2/b^2 - 1 = 0. |
| 226 */ | 228 */ |
| 227 | 229 |
| 228 class EllipseEdgeEffect : public GrGeometryProcessor { | 230 class EllipseEdgeEffect : public GrGeometryProcessor { |
| 229 public: | 231 public: |
| 230 static GrGeometryProcessor* Create(GrColor color, bool stroke) { | 232 static GrGeometryProcessor* Create(GrColor color, bool stroke, const SkMatri
x& localMatrix) { |
| 231 return SkNEW_ARGS(EllipseEdgeEffect, (color, stroke)); | 233 return SkNEW_ARGS(EllipseEdgeEffect, (color, stroke, localMatrix)); |
| 232 } | 234 } |
| 233 | 235 |
| 234 virtual ~EllipseEdgeEffect() {} | 236 virtual ~EllipseEdgeEffect() {} |
| 235 | 237 |
| 236 virtual const char* name() const SK_OVERRIDE { return "EllipseEdge"; } | 238 virtual const char* name() const SK_OVERRIDE { return "EllipseEdge"; } |
| 237 | 239 |
| 238 const GrAttribute* inPosition() const { return fInPosition; } | 240 const GrAttribute* inPosition() const { return fInPosition; } |
| 239 const GrAttribute* inEllipseOffset() const { return fInEllipseOffset; } | 241 const GrAttribute* inEllipseOffset() const { return fInEllipseOffset; } |
| 240 const GrAttribute* inEllipseRadii() const { return fInEllipseRadii; } | 242 const GrAttribute* inEllipseRadii() const { return fInEllipseRadii; } |
| 241 | 243 |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 const GrBatchTracker& t) const SK_OVERRIDE { | 355 const GrBatchTracker& t) const SK_OVERRIDE { |
| 354 const BatchTracker& mine = m.cast<BatchTracker>(); | 356 const BatchTracker& mine = m.cast<BatchTracker>(); |
| 355 const BatchTracker& theirs = t.cast<BatchTracker>(); | 357 const BatchTracker& theirs = t.cast<BatchTracker>(); |
| 356 return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords, | 358 return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords, |
| 357 that, theirs.fUsesLocalCoords) && | 359 that, theirs.fUsesLocalCoords) && |
| 358 CanCombineOutput(mine.fInputColorType, mine.fColor, | 360 CanCombineOutput(mine.fInputColorType, mine.fColor, |
| 359 theirs.fInputColorType, theirs.fColor); | 361 theirs.fInputColorType, theirs.fColor); |
| 360 } | 362 } |
| 361 | 363 |
| 362 private: | 364 private: |
| 363 EllipseEdgeEffect(GrColor color, bool stroke) : INHERITED(color) { | 365 EllipseEdgeEffect(GrColor color, bool stroke, const SkMatrix& localMatrix) |
| 366 : INHERITED(color, false, localMatrix) { |
| 364 this->initClassID<EllipseEdgeEffect>(); | 367 this->initClassID<EllipseEdgeEffect>(); |
| 365 fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_Gr
VertexAttribType)); | 368 fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_Gr
VertexAttribType)); |
| 366 fInEllipseOffset = &this->addVertexAttrib(GrAttribute("inEllipseOffset", | 369 fInEllipseOffset = &this->addVertexAttrib(GrAttribute("inEllipseOffset", |
| 367 kVec2f_GrVertexAtt
ribType)); | 370 kVec2f_GrVertexAtt
ribType)); |
| 368 fInEllipseRadii = &this->addVertexAttrib(GrAttribute("inEllipseRadii", | 371 fInEllipseRadii = &this->addVertexAttrib(GrAttribute("inEllipseRadii", |
| 369 kVec4f_GrVertexAttr
ibType)); | 372 kVec4f_GrVertexAttr
ibType)); |
| 370 fStroke = stroke; | 373 fStroke = stroke; |
| 371 } | 374 } |
| 372 | 375 |
| 373 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { | 376 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 394 | 397 |
| 395 typedef GrGeometryProcessor INHERITED; | 398 typedef GrGeometryProcessor INHERITED; |
| 396 }; | 399 }; |
| 397 | 400 |
| 398 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(EllipseEdgeEffect); | 401 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(EllipseEdgeEffect); |
| 399 | 402 |
| 400 GrGeometryProcessor* EllipseEdgeEffect::TestCreate(SkRandom* random, | 403 GrGeometryProcessor* EllipseEdgeEffect::TestCreate(SkRandom* random, |
| 401 GrContext* context, | 404 GrContext* context, |
| 402 const GrDrawTargetCaps&, | 405 const GrDrawTargetCaps&, |
| 403 GrTexture* textures[]) { | 406 GrTexture* textures[]) { |
| 404 return EllipseEdgeEffect::Create(GrRandomColor(random), random->nextBool()); | 407 return EllipseEdgeEffect::Create(GrRandomColor(random), random->nextBool(), |
| 408 GrProcessorUnitTest::TestMatrix(random)); |
| 405 } | 409 } |
| 406 | 410 |
| 407 /////////////////////////////////////////////////////////////////////////////// | 411 /////////////////////////////////////////////////////////////////////////////// |
| 408 | 412 |
| 409 /** | 413 /** |
| 410 * The output of this effect is a modulation of the input color and coverage for
an ellipse, | 414 * The output of this effect is a modulation of the input color and coverage for
an ellipse, |
| 411 * specified as a 2D offset from center for both the outer and inner paths (if s
troked). The | 415 * specified as a 2D offset from center for both the outer and inner paths (if s
troked). The |
| 412 * implict equation used is for a unit circle (x^2 + y^2 - 1 = 0) and the edge c
orrected by | 416 * implict equation used is for a unit circle (x^2 + y^2 - 1 = 0) and the edge c
orrected by |
| 413 * using differentials. | 417 * using differentials. |
| 414 * | 418 * |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 660 bool useCoverageAA, | 664 bool useCoverageAA, |
| 661 const SkRect& circle, | 665 const SkRect& circle, |
| 662 const SkStrokeRec& stroke) | 666 const SkStrokeRec& stroke) |
| 663 { | 667 { |
| 664 const SkMatrix& vm = drawState->getViewMatrix(); | 668 const SkMatrix& vm = drawState->getViewMatrix(); |
| 665 SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY()); | 669 SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY()); |
| 666 vm.mapPoints(¢er, 1); | 670 vm.mapPoints(¢er, 1); |
| 667 SkScalar radius = vm.mapRadius(SkScalarHalf(circle.width())); | 671 SkScalar radius = vm.mapRadius(SkScalarHalf(circle.width())); |
| 668 SkScalar strokeWidth = vm.mapRadius(stroke.getWidth()); | 672 SkScalar strokeWidth = vm.mapRadius(stroke.getWidth()); |
| 669 | 673 |
| 670 GrDrawState::AutoViewMatrixRestore avmr; | 674 SkMatrix invert; |
| 671 if (!avmr.setIdentity(drawState)) { | 675 if (!vm.invert(&invert)) { |
| 672 return; | 676 return; |
| 673 } | 677 } |
| 674 | 678 |
| 679 GrDrawState::AutoViewMatrixRestore avmr(drawState); |
| 680 |
| 675 SkStrokeRec::Style style = stroke.getStyle(); | 681 SkStrokeRec::Style style = stroke.getStyle(); |
| 676 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || | 682 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || |
| 677 SkStrokeRec::kHairline_Style == style; | 683 SkStrokeRec::kHairline_Style == style; |
| 678 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; | 684 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; |
| 679 | 685 |
| 680 SkScalar innerRadius = 0.0f; | 686 SkScalar innerRadius = 0.0f; |
| 681 SkScalar outerRadius = radius; | 687 SkScalar outerRadius = radius; |
| 682 SkScalar halfWidth = 0; | 688 SkScalar halfWidth = 0; |
| 683 if (hasStroke) { | 689 if (hasStroke) { |
| 684 if (SkScalarNearlyZero(strokeWidth)) { | 690 if (SkScalarNearlyZero(strokeWidth)) { |
| 685 halfWidth = SK_ScalarHalf; | 691 halfWidth = SK_ScalarHalf; |
| 686 } else { | 692 } else { |
| 687 halfWidth = SkScalarHalf(strokeWidth); | 693 halfWidth = SkScalarHalf(strokeWidth); |
| 688 } | 694 } |
| 689 | 695 |
| 690 outerRadius += halfWidth; | 696 outerRadius += halfWidth; |
| 691 if (isStrokeOnly) { | 697 if (isStrokeOnly) { |
| 692 innerRadius = radius - halfWidth; | 698 innerRadius = radius - halfWidth; |
| 693 } | 699 } |
| 694 } | 700 } |
| 695 | 701 |
| 696 SkAutoTUnref<GrGeometryProcessor> gp( | 702 SkAutoTUnref<GrGeometryProcessor> gp( |
| 697 CircleEdgeEffect::Create(color, isStrokeOnly && innerRadius > 0)); | 703 CircleEdgeEffect::Create(color, isStrokeOnly && innerRadius > 0, inv
ert)); |
| 698 | 704 |
| 699 GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); | 705 GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); |
| 700 SkASSERT(gp->getVertexStride() == sizeof(CircleVertex)); | 706 SkASSERT(gp->getVertexStride() == sizeof(CircleVertex)); |
| 701 if (!geo.succeeded()) { | 707 if (!geo.succeeded()) { |
| 702 SkDebugf("Failed to get space for vertices!\n"); | 708 SkDebugf("Failed to get space for vertices!\n"); |
| 703 return; | 709 return; |
| 704 } | 710 } |
| 705 | 711 |
| 706 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); | 712 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); |
| 707 | 713 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 809 // this is legit only if scale & translation (which should be the case a
t the moment) | 815 // this is legit only if scale & translation (which should be the case a
t the moment) |
| 810 if (isStrokeOnly) { | 816 if (isStrokeOnly) { |
| 811 innerXRadius = xRadius - scaledStroke.fX; | 817 innerXRadius = xRadius - scaledStroke.fX; |
| 812 innerYRadius = yRadius - scaledStroke.fY; | 818 innerYRadius = yRadius - scaledStroke.fY; |
| 813 } | 819 } |
| 814 | 820 |
| 815 xRadius += scaledStroke.fX; | 821 xRadius += scaledStroke.fX; |
| 816 yRadius += scaledStroke.fY; | 822 yRadius += scaledStroke.fY; |
| 817 } | 823 } |
| 818 | 824 |
| 819 GrDrawState::AutoViewMatrixRestore avmr; | 825 SkMatrix invert; |
| 820 if (!avmr.setIdentity(drawState)) { | 826 if (!vm.invert(&invert)) { |
| 821 return false; | 827 return false; |
| 822 } | 828 } |
| 823 | 829 |
| 830 GrDrawState::AutoViewMatrixRestore avmr(drawState); |
| 831 |
| 824 SkAutoTUnref<GrGeometryProcessor> gp( | 832 SkAutoTUnref<GrGeometryProcessor> gp( |
| 825 EllipseEdgeEffect::Create(color, isStrokeOnly && innerXRadius > 0 &&
innerYRadius > 0)); | 833 EllipseEdgeEffect::Create(color, isStrokeOnly && innerXRadius > 0 &&
innerYRadius > 0, |
| 834 invert)); |
| 826 | 835 |
| 827 GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); | 836 GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); |
| 828 SkASSERT(gp->getVertexStride() == sizeof(EllipseVertex)); | 837 SkASSERT(gp->getVertexStride() == sizeof(EllipseVertex)); |
| 829 if (!geo.succeeded()) { | 838 if (!geo.succeeded()) { |
| 830 SkDebugf("Failed to get space for vertices!\n"); | 839 SkDebugf("Failed to get space for vertices!\n"); |
| 831 return false; | 840 return false; |
| 832 } | 841 } |
| 833 | 842 |
| 834 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); | 843 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); |
| 835 | 844 |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1077 } | 1086 } |
| 1078 GrPrimitiveEdgeType edgeType = applyAA ? kFillAA_GrProcessorEdgeType : | 1087 GrPrimitiveEdgeType edgeType = applyAA ? kFillAA_GrProcessorEdgeType : |
| 1079 kFillBW_GrProcessorEdgeType; | 1088 kFillBW_GrProcessorEdgeType; |
| 1080 GrFragmentProcessor* effect = GrRRectEffect::Create(edgeType, *outer); | 1089 GrFragmentProcessor* effect = GrRRectEffect::Create(edgeType, *outer); |
| 1081 if (NULL == effect) { | 1090 if (NULL == effect) { |
| 1082 return false; | 1091 return false; |
| 1083 } | 1092 } |
| 1084 if (!are.isSet()) { | 1093 if (!are.isSet()) { |
| 1085 are.set(drawState); | 1094 are.set(drawState); |
| 1086 } | 1095 } |
| 1087 GrDrawState::AutoViewMatrixRestore avmr; | 1096 |
| 1088 if (!avmr.setIdentity(drawState)) { | 1097 SkMatrix invert; |
| 1098 if (!drawState->getViewMatrix().invert(&invert)) { |
| 1089 return false; | 1099 return false; |
| 1090 } | 1100 } |
| 1101 |
| 1102 GrDrawState::AutoViewMatrixRestore avmr(drawState); |
| 1091 drawState->addCoverageProcessor(effect)->unref(); | 1103 drawState->addCoverageProcessor(effect)->unref(); |
| 1092 SkRect bounds = outer->getBounds(); | 1104 SkRect bounds = outer->getBounds(); |
| 1093 if (applyAA) { | 1105 if (applyAA) { |
| 1094 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); | 1106 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); |
| 1095 } | 1107 } |
| 1096 target->drawSimpleRect(drawState, color, bounds); | 1108 target->drawRect(drawState, color, bounds, NULL, &invert); |
| 1097 return true; | 1109 return true; |
| 1098 } | 1110 } |
| 1099 | 1111 |
| 1100 bool GrOvalRenderer::drawRRect(GrDrawTarget* target, | 1112 bool GrOvalRenderer::drawRRect(GrDrawTarget* target, |
| 1101 GrDrawState* drawState, | 1113 GrDrawState* drawState, |
| 1102 GrColor color, | 1114 GrColor color, |
| 1103 bool useAA, | 1115 bool useAA, |
| 1104 const SkRRect& rrect, | 1116 const SkRRect& rrect, |
| 1105 const SkStrokeRec& stroke) { | 1117 const SkStrokeRec& stroke) { |
| 1106 if (rrect.isOval()) { | 1118 if (rrect.isOval()) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1162 // The way the effect interpolates the offset-to-ellipse/circle-center attri
bute only works on | 1174 // The way the effect interpolates the offset-to-ellipse/circle-center attri
bute only works on |
| 1163 // the interior of the rrect if the radii are >= 0.5. Otherwise, the inner r
ect of the nine- | 1175 // the interior of the rrect if the radii are >= 0.5. Otherwise, the inner r
ect of the nine- |
| 1164 // patch will have fractional coverage. This only matters when the interior
is actually filled. | 1176 // patch will have fractional coverage. This only matters when the interior
is actually filled. |
| 1165 // We could consider falling back to rect rendering here, since a tiny radiu
s is | 1177 // We could consider falling back to rect rendering here, since a tiny radiu
s is |
| 1166 // indistinguishable from a square corner. | 1178 // indistinguishable from a square corner. |
| 1167 if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) { | 1179 if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) { |
| 1168 return false; | 1180 return false; |
| 1169 } | 1181 } |
| 1170 | 1182 |
| 1171 // reset to device coordinates | 1183 // reset to device coordinates |
| 1172 GrDrawState::AutoViewMatrixRestore avmr; | 1184 SkMatrix invert; |
| 1173 if (!avmr.setIdentity(drawState)) { | 1185 if (!vm.invert(&invert)) { |
| 1186 SkDebugf("Failed to invert\n"); |
| 1174 return false; | 1187 return false; |
| 1175 } | 1188 } |
| 1176 | 1189 |
| 1190 GrDrawState::AutoViewMatrixRestore avmr(drawState); |
| 1191 |
| 1177 GrIndexBuffer* indexBuffer = this->rRectIndexBuffer(isStrokeOnly); | 1192 GrIndexBuffer* indexBuffer = this->rRectIndexBuffer(isStrokeOnly); |
| 1178 if (NULL == indexBuffer) { | 1193 if (NULL == indexBuffer) { |
| 1179 SkDebugf("Failed to create index buffer!\n"); | 1194 SkDebugf("Failed to create index buffer!\n"); |
| 1180 return false; | 1195 return false; |
| 1181 } | 1196 } |
| 1182 | 1197 |
| 1183 // if the corners are circles, use the circle renderer | 1198 // if the corners are circles, use the circle renderer |
| 1184 if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius
) { | 1199 if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius
) { |
| 1185 SkScalar innerRadius = 0.0f; | 1200 SkScalar innerRadius = 0.0f; |
| 1186 SkScalar outerRadius = xRadius; | 1201 SkScalar outerRadius = xRadius; |
| 1187 SkScalar halfWidth = 0; | 1202 SkScalar halfWidth = 0; |
| 1188 if (hasStroke) { | 1203 if (hasStroke) { |
| 1189 if (SkScalarNearlyZero(scaledStroke.fX)) { | 1204 if (SkScalarNearlyZero(scaledStroke.fX)) { |
| 1190 halfWidth = SK_ScalarHalf; | 1205 halfWidth = SK_ScalarHalf; |
| 1191 } else { | 1206 } else { |
| 1192 halfWidth = SkScalarHalf(scaledStroke.fX); | 1207 halfWidth = SkScalarHalf(scaledStroke.fX); |
| 1193 } | 1208 } |
| 1194 | 1209 |
| 1195 if (isStrokeOnly) { | 1210 if (isStrokeOnly) { |
| 1196 innerRadius = xRadius - halfWidth; | 1211 innerRadius = xRadius - halfWidth; |
| 1197 } | 1212 } |
| 1198 outerRadius += halfWidth; | 1213 outerRadius += halfWidth; |
| 1199 bounds.outset(halfWidth, halfWidth); | 1214 bounds.outset(halfWidth, halfWidth); |
| 1200 } | 1215 } |
| 1201 | 1216 |
| 1202 isStrokeOnly = (isStrokeOnly && innerRadius >= 0); | 1217 isStrokeOnly = (isStrokeOnly && innerRadius >= 0); |
| 1203 | 1218 |
| 1204 SkAutoTUnref<GrGeometryProcessor> effect(CircleEdgeEffect::Create(color,
isStrokeOnly)); | 1219 SkAutoTUnref<GrGeometryProcessor> effect(CircleEdgeEffect::Create(color,
isStrokeOnly, |
| 1220 invert
)); |
| 1205 | 1221 |
| 1206 GrDrawTarget::AutoReleaseGeometry geo(target, 16, effect->getVertexStrid
e(), 0); | 1222 GrDrawTarget::AutoReleaseGeometry geo(target, 16, effect->getVertexStrid
e(), 0); |
| 1207 SkASSERT(effect->getVertexStride() == sizeof(CircleVertex)); | 1223 SkASSERT(effect->getVertexStride() == sizeof(CircleVertex)); |
| 1208 if (!geo.succeeded()) { | 1224 if (!geo.succeeded()) { |
| 1209 SkDebugf("Failed to get space for vertices!\n"); | 1225 SkDebugf("Failed to get space for vertices!\n"); |
| 1210 return false; | 1226 return false; |
| 1211 } | 1227 } |
| 1212 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); | 1228 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); |
| 1213 | 1229 |
| 1214 // The radii are outset for two reasons. First, it allows the shader to
simply perform | 1230 // The radii are outset for two reasons. First, it allows the shader to
simply perform |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1293 innerYRadius = yRadius - scaledStroke.fY; | 1309 innerYRadius = yRadius - scaledStroke.fY; |
| 1294 } | 1310 } |
| 1295 | 1311 |
| 1296 xRadius += scaledStroke.fX; | 1312 xRadius += scaledStroke.fX; |
| 1297 yRadius += scaledStroke.fY; | 1313 yRadius += scaledStroke.fY; |
| 1298 bounds.outset(scaledStroke.fX, scaledStroke.fY); | 1314 bounds.outset(scaledStroke.fX, scaledStroke.fY); |
| 1299 } | 1315 } |
| 1300 | 1316 |
| 1301 isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0); | 1317 isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0); |
| 1302 | 1318 |
| 1303 SkAutoTUnref<GrGeometryProcessor> effect(EllipseEdgeEffect::Create(color
, isStrokeOnly)); | 1319 SkAutoTUnref<GrGeometryProcessor> effect(EllipseEdgeEffect::Create(color
, isStrokeOnly, |
| 1320 inver
t)); |
| 1304 | 1321 |
| 1305 GrDrawTarget::AutoReleaseGeometry geo(target, 16, effect->getVertexStrid
e(), 0); | 1322 GrDrawTarget::AutoReleaseGeometry geo(target, 16, effect->getVertexStrid
e(), 0); |
| 1306 SkASSERT(effect->getVertexStride() == sizeof(EllipseVertex)); | 1323 SkASSERT(effect->getVertexStride() == sizeof(EllipseVertex)); |
| 1307 if (!geo.succeeded()) { | 1324 if (!geo.succeeded()) { |
| 1308 SkDebugf("Failed to get space for vertices!\n"); | 1325 SkDebugf("Failed to get space for vertices!\n"); |
| 1309 return false; | 1326 return false; |
| 1310 } | 1327 } |
| 1311 | 1328 |
| 1312 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); | 1329 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); |
| 1313 | 1330 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1367 int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 : | 1384 int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 : |
| 1368 SK_ARRAY_COUNT(gRRectIndices); | 1385 SK_ARRAY_COUNT(gRRectIndices); |
| 1369 target->setIndexSourceToBuffer(indexBuffer); | 1386 target->setIndexSourceToBuffer(indexBuffer); |
| 1370 target->drawIndexedInstances(drawState, effect, kTriangles_GrPrimitiveTy
pe, 1, 16, indexCnt, | 1387 target->drawIndexedInstances(drawState, effect, kTriangles_GrPrimitiveTy
pe, 1, 16, indexCnt, |
| 1371 &bounds); | 1388 &bounds); |
| 1372 } | 1389 } |
| 1373 | 1390 |
| 1374 target->resetIndexSource(); | 1391 target->resetIndexSource(); |
| 1375 return true; | 1392 return true; |
| 1376 } | 1393 } |
| OLD | NEW |