| 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 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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, const SkMatrix& localMatrix) | 177 CircleEdgeEffect(GrColor color, bool stroke, const SkMatrix& localMatrix) |
| 178 : INHERITED(color, false, localMatrix) { | 178 : INHERITED(color, SkMatrix::I(), localMatrix) { |
| 179 this->initClassID<CircleEdgeEffect>(); | 179 this->initClassID<CircleEdgeEffect>(); |
| 180 fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_Gr
VertexAttribType)); | 180 fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_Gr
VertexAttribType)); |
| 181 fInCircleEdge = &this->addVertexAttrib(GrAttribute("inCircleEdge", | 181 fInCircleEdge = &this->addVertexAttrib(GrAttribute("inCircleEdge", |
| 182 kVec4f_GrVertexAttrib
Type)); | 182 kVec4f_GrVertexAttrib
Type)); |
| 183 fStroke = stroke; | 183 fStroke = stroke; |
| 184 } | 184 } |
| 185 | 185 |
| 186 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { | 186 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { |
| 187 const CircleEdgeEffect& cee = other.cast<CircleEdgeEffect>(); | 187 const CircleEdgeEffect& cee = other.cast<CircleEdgeEffect>(); |
| 188 return cee.fStroke == fStroke; | 188 return cee.fStroke == fStroke; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 206 | 206 |
| 207 typedef GrGeometryProcessor INHERITED; | 207 typedef GrGeometryProcessor INHERITED; |
| 208 }; | 208 }; |
| 209 | 209 |
| 210 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(CircleEdgeEffect); | 210 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(CircleEdgeEffect); |
| 211 | 211 |
| 212 GrGeometryProcessor* CircleEdgeEffect::TestCreate(SkRandom* random, | 212 GrGeometryProcessor* CircleEdgeEffect::TestCreate(SkRandom* random, |
| 213 GrContext* context, | 213 GrContext* context, |
| 214 const GrDrawTargetCaps&, | 214 const GrDrawTargetCaps&, |
| 215 GrTexture* textures[]) { | 215 GrTexture* textures[]) { |
| 216 return CircleEdgeEffect::Create(GrRandomColor(random), random->nextBool(), | 216 return CircleEdgeEffect::Create(GrRandomColor(random), |
| 217 random->nextBool(), |
| 217 GrProcessorUnitTest::TestMatrix(random)); | 218 GrProcessorUnitTest::TestMatrix(random)); |
| 218 } | 219 } |
| 219 | 220 |
| 220 /////////////////////////////////////////////////////////////////////////////// | 221 /////////////////////////////////////////////////////////////////////////////// |
| 221 | 222 |
| 222 /** | 223 /** |
| 223 * The output of this effect is a modulation of the input color and coverage for
an axis-aligned | 224 * The output of this effect is a modulation of the input color and coverage for
an axis-aligned |
| 224 * ellipse, specified as a 2D offset from center, and the reciprocals of the out
er and inner radii, | 225 * ellipse, specified as a 2D offset from center, and the reciprocals of the out
er and inner radii, |
| 225 * in both x and y directions. | 226 * in both x and y directions. |
| 226 * | 227 * |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 356 const BatchTracker& mine = m.cast<BatchTracker>(); | 357 const BatchTracker& mine = m.cast<BatchTracker>(); |
| 357 const BatchTracker& theirs = t.cast<BatchTracker>(); | 358 const BatchTracker& theirs = t.cast<BatchTracker>(); |
| 358 return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords, | 359 return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords, |
| 359 that, theirs.fUsesLocalCoords) && | 360 that, theirs.fUsesLocalCoords) && |
| 360 CanCombineOutput(mine.fInputColorType, mine.fColor, | 361 CanCombineOutput(mine.fInputColorType, mine.fColor, |
| 361 theirs.fInputColorType, theirs.fColor); | 362 theirs.fInputColorType, theirs.fColor); |
| 362 } | 363 } |
| 363 | 364 |
| 364 private: | 365 private: |
| 365 EllipseEdgeEffect(GrColor color, bool stroke, const SkMatrix& localMatrix) | 366 EllipseEdgeEffect(GrColor color, bool stroke, const SkMatrix& localMatrix) |
| 366 : INHERITED(color, false, localMatrix) { | 367 : INHERITED(color, SkMatrix::I(), localMatrix) { |
| 367 this->initClassID<EllipseEdgeEffect>(); | 368 this->initClassID<EllipseEdgeEffect>(); |
| 368 fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_Gr
VertexAttribType)); | 369 fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_Gr
VertexAttribType)); |
| 369 fInEllipseOffset = &this->addVertexAttrib(GrAttribute("inEllipseOffset", | 370 fInEllipseOffset = &this->addVertexAttrib(GrAttribute("inEllipseOffset", |
| 370 kVec2f_GrVertexAtt
ribType)); | 371 kVec2f_GrVertexAtt
ribType)); |
| 371 fInEllipseRadii = &this->addVertexAttrib(GrAttribute("inEllipseRadii", | 372 fInEllipseRadii = &this->addVertexAttrib(GrAttribute("inEllipseRadii", |
| 372 kVec4f_GrVertexAttr
ibType)); | 373 kVec4f_GrVertexAttr
ibType)); |
| 373 fStroke = stroke; | 374 fStroke = stroke; |
| 374 } | 375 } |
| 375 | 376 |
| 376 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { | 377 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 397 | 398 |
| 398 typedef GrGeometryProcessor INHERITED; | 399 typedef GrGeometryProcessor INHERITED; |
| 399 }; | 400 }; |
| 400 | 401 |
| 401 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(EllipseEdgeEffect); | 402 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(EllipseEdgeEffect); |
| 402 | 403 |
| 403 GrGeometryProcessor* EllipseEdgeEffect::TestCreate(SkRandom* random, | 404 GrGeometryProcessor* EllipseEdgeEffect::TestCreate(SkRandom* random, |
| 404 GrContext* context, | 405 GrContext* context, |
| 405 const GrDrawTargetCaps&, | 406 const GrDrawTargetCaps&, |
| 406 GrTexture* textures[]) { | 407 GrTexture* textures[]) { |
| 407 return EllipseEdgeEffect::Create(GrRandomColor(random), random->nextBool(), | 408 return EllipseEdgeEffect::Create(GrRandomColor(random), |
| 409 random->nextBool(), |
| 408 GrProcessorUnitTest::TestMatrix(random)); | 410 GrProcessorUnitTest::TestMatrix(random)); |
| 409 } | 411 } |
| 410 | 412 |
| 411 /////////////////////////////////////////////////////////////////////////////// | 413 /////////////////////////////////////////////////////////////////////////////// |
| 412 | 414 |
| 413 /** | 415 /** |
| 414 * The output of this effect is a modulation of the input color and coverage for
an ellipse, | 416 * The output of this effect is a modulation of the input color and coverage for
an ellipse, |
| 415 * specified as a 2D offset from center for both the outer and inner paths (if s
troked). The | 417 * specified as a 2D offset from center for both the outer and inner paths (if s
troked). The |
| 416 * implict equation used is for a unit circle (x^2 + y^2 - 1 = 0) and the edge c
orrected by | 418 * implict equation used is for a unit circle (x^2 + y^2 - 1 = 0) and the edge c
orrected by |
| 417 * using differentials. | 419 * using differentials. |
| 418 * | 420 * |
| 419 * The result is device-independent and can be used with any affine matrix. | 421 * The result is device-independent and can be used with any affine matrix. |
| 420 */ | 422 */ |
| 421 | 423 |
| 422 class DIEllipseEdgeEffect : public GrGeometryProcessor { | 424 class DIEllipseEdgeEffect : public GrGeometryProcessor { |
| 423 public: | 425 public: |
| 424 enum Mode { kStroke = 0, kHairline, kFill }; | 426 enum Mode { kStroke = 0, kHairline, kFill }; |
| 425 | 427 |
| 426 static GrGeometryProcessor* Create(GrColor color, Mode mode) { | 428 static GrGeometryProcessor* Create(GrColor color, const SkMatrix& viewMatrix
, Mode mode) { |
| 427 return SkNEW_ARGS(DIEllipseEdgeEffect, (color, mode)); | 429 return SkNEW_ARGS(DIEllipseEdgeEffect, (color, viewMatrix, mode)); |
| 428 } | 430 } |
| 429 | 431 |
| 430 virtual ~DIEllipseEdgeEffect() {} | 432 virtual ~DIEllipseEdgeEffect() {} |
| 431 | 433 |
| 432 virtual const char* name() const SK_OVERRIDE { return "DIEllipseEdge"; } | 434 virtual const char* name() const SK_OVERRIDE { return "DIEllipseEdge"; } |
| 433 | 435 |
| 434 const GrAttribute* inPosition() const { return fInPosition; } | 436 const GrAttribute* inPosition() const { return fInPosition; } |
| 435 const GrAttribute* inEllipseOffsets0() const { return fInEllipseOffsets0; } | 437 const GrAttribute* inEllipseOffsets0() const { return fInEllipseOffsets0; } |
| 436 const GrAttribute* inEllipseOffsets1() const { return fInEllipseOffsets1; } | 438 const GrAttribute* inEllipseOffsets1() const { return fInEllipseOffsets1; } |
| 437 | 439 |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 const GrBatchTracker& t) const SK_OVERRIDE { | 566 const GrBatchTracker& t) const SK_OVERRIDE { |
| 565 const BatchTracker& mine = m.cast<BatchTracker>(); | 567 const BatchTracker& mine = m.cast<BatchTracker>(); |
| 566 const BatchTracker& theirs = t.cast<BatchTracker>(); | 568 const BatchTracker& theirs = t.cast<BatchTracker>(); |
| 567 return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords, | 569 return CanCombineLocalMatrices(*this, mine.fUsesLocalCoords, |
| 568 that, theirs.fUsesLocalCoords) && | 570 that, theirs.fUsesLocalCoords) && |
| 569 CanCombineOutput(mine.fInputColorType, mine.fColor, | 571 CanCombineOutput(mine.fInputColorType, mine.fColor, |
| 570 theirs.fInputColorType, theirs.fColor); | 572 theirs.fInputColorType, theirs.fColor); |
| 571 } | 573 } |
| 572 | 574 |
| 573 private: | 575 private: |
| 574 DIEllipseEdgeEffect(GrColor color, Mode mode) : INHERITED(color) { | 576 DIEllipseEdgeEffect(GrColor color, const SkMatrix& viewMatrix, Mode mode) |
| 577 : INHERITED(color, viewMatrix) { |
| 575 this->initClassID<DIEllipseEdgeEffect>(); | 578 this->initClassID<DIEllipseEdgeEffect>(); |
| 576 fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_Gr
VertexAttribType)); | 579 fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_Gr
VertexAttribType)); |
| 577 fInEllipseOffsets0 = &this->addVertexAttrib(GrAttribute("inEllipseOffset
s0", | 580 fInEllipseOffsets0 = &this->addVertexAttrib(GrAttribute("inEllipseOffset
s0", |
| 578 kVec2f_GrVertexA
ttribType)); | 581 kVec2f_GrVertexA
ttribType)); |
| 579 fInEllipseOffsets1 = &this->addVertexAttrib(GrAttribute("inEllipseOffset
s1", | 582 fInEllipseOffsets1 = &this->addVertexAttrib(GrAttribute("inEllipseOffset
s1", |
| 580 kVec2f_GrVertexA
ttribType)); | 583 kVec2f_GrVertexA
ttribType)); |
| 581 fMode = mode; | 584 fMode = mode; |
| 582 } | 585 } |
| 583 | 586 |
| 584 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { | 587 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 605 | 608 |
| 606 typedef GrGeometryProcessor INHERITED; | 609 typedef GrGeometryProcessor INHERITED; |
| 607 }; | 610 }; |
| 608 | 611 |
| 609 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DIEllipseEdgeEffect); | 612 GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DIEllipseEdgeEffect); |
| 610 | 613 |
| 611 GrGeometryProcessor* DIEllipseEdgeEffect::TestCreate(SkRandom* random, | 614 GrGeometryProcessor* DIEllipseEdgeEffect::TestCreate(SkRandom* random, |
| 612 GrContext* context, | 615 GrContext* context, |
| 613 const GrDrawTargetCaps&, | 616 const GrDrawTargetCaps&, |
| 614 GrTexture* textures[]) { | 617 GrTexture* textures[]) { |
| 615 return DIEllipseEdgeEffect::Create(GrRandomColor(random), (Mode)(random->nex
tRangeU(0,2))); | 618 return DIEllipseEdgeEffect::Create(GrRandomColor(random), |
| 619 GrProcessorUnitTest::TestMatrix(random), |
| 620 (Mode)(random->nextRangeU(0,2))); |
| 616 } | 621 } |
| 617 | 622 |
| 618 /////////////////////////////////////////////////////////////////////////////// | 623 /////////////////////////////////////////////////////////////////////////////// |
| 619 | 624 |
| 620 void GrOvalRenderer::reset() { | 625 void GrOvalRenderer::reset() { |
| 621 SkSafeSetNull(fRRectIndexBuffer); | 626 SkSafeSetNull(fRRectIndexBuffer); |
| 622 SkSafeSetNull(fStrokeRRectIndexBuffer); | 627 SkSafeSetNull(fStrokeRRectIndexBuffer); |
| 623 } | 628 } |
| 624 | 629 |
| 625 bool GrOvalRenderer::drawOval(GrDrawTarget* target, | 630 bool GrOvalRenderer::drawOval(GrDrawTarget* target, |
| 626 GrDrawState* drawState, | 631 GrDrawState* drawState, |
| 627 GrColor color, | 632 GrColor color, |
| 633 const SkMatrix& viewMatrix, |
| 628 bool useAA, | 634 bool useAA, |
| 629 const SkRect& oval, | 635 const SkRect& oval, |
| 630 const SkStrokeRec& stroke) | 636 const SkStrokeRec& stroke) |
| 631 { | 637 { |
| 632 bool useCoverageAA = useAA && | 638 bool useCoverageAA = useAA && |
| 633 !drawState->getRenderTarget()->isMultisampled() && | 639 !drawState->getRenderTarget()->isMultisampled() && |
| 634 drawState->canUseFracCoveragePrimProc(color, *target->caps()); | 640 drawState->canUseFracCoveragePrimProc(color, *target->caps()); |
| 635 | 641 |
| 636 if (!useCoverageAA) { | 642 if (!useCoverageAA) { |
| 637 return false; | 643 return false; |
| 638 } | 644 } |
| 639 | 645 |
| 640 const SkMatrix& vm = drawState->getViewMatrix(); | |
| 641 | |
| 642 // we can draw circles | 646 // we can draw circles |
| 643 if (SkScalarNearlyEqual(oval.width(), oval.height()) | 647 if (SkScalarNearlyEqual(oval.width(), oval.height()) && circle_stays_circle(
viewMatrix)) { |
| 644 && circle_stays_circle(vm)) { | 648 this->drawCircle(target, drawState, color, viewMatrix, useCoverageAA, ov
al, stroke); |
| 645 this->drawCircle(target, drawState, color, useCoverageAA, oval, stroke); | |
| 646 // if we have shader derivative support, render as device-independent | 649 // if we have shader derivative support, render as device-independent |
| 647 } else if (target->caps()->shaderDerivativeSupport()) { | 650 } else if (target->caps()->shaderDerivativeSupport()) { |
| 648 return this->drawDIEllipse(target, drawState, color, useCoverageAA, oval
, stroke); | 651 return this->drawDIEllipse(target, drawState, color, viewMatrix, useCove
rageAA, oval, |
| 652 stroke); |
| 649 // otherwise axis-aligned ellipses only | 653 // otherwise axis-aligned ellipses only |
| 650 } else if (vm.rectStaysRect()) { | 654 } else if (viewMatrix.rectStaysRect()) { |
| 651 return this->drawEllipse(target, drawState, color, useCoverageAA, oval,
stroke); | 655 return this->drawEllipse(target, drawState, color, viewMatrix, useCovera
geAA, oval, stroke); |
| 652 } else { | 656 } else { |
| 653 return false; | 657 return false; |
| 654 } | 658 } |
| 655 | 659 |
| 656 return true; | 660 return true; |
| 657 } | 661 } |
| 658 | 662 |
| 659 /////////////////////////////////////////////////////////////////////////////// | 663 /////////////////////////////////////////////////////////////////////////////// |
| 660 | 664 |
| 661 void GrOvalRenderer::drawCircle(GrDrawTarget* target, | 665 void GrOvalRenderer::drawCircle(GrDrawTarget* target, |
| 662 GrDrawState* drawState, | 666 GrDrawState* drawState, |
| 663 GrColor color, | 667 GrColor color, |
| 668 const SkMatrix& viewMatrix, |
| 664 bool useCoverageAA, | 669 bool useCoverageAA, |
| 665 const SkRect& circle, | 670 const SkRect& circle, |
| 666 const SkStrokeRec& stroke) | 671 const SkStrokeRec& stroke) { |
| 667 { | |
| 668 const SkMatrix& vm = drawState->getViewMatrix(); | |
| 669 SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY()); | 672 SkPoint center = SkPoint::Make(circle.centerX(), circle.centerY()); |
| 670 vm.mapPoints(¢er, 1); | 673 viewMatrix.mapPoints(¢er, 1); |
| 671 SkScalar radius = vm.mapRadius(SkScalarHalf(circle.width())); | 674 SkScalar radius = viewMatrix.mapRadius(SkScalarHalf(circle.width())); |
| 672 SkScalar strokeWidth = vm.mapRadius(stroke.getWidth()); | 675 SkScalar strokeWidth = viewMatrix.mapRadius(stroke.getWidth()); |
| 673 | 676 |
| 674 SkMatrix invert; | 677 SkMatrix invert; |
| 675 if (!vm.invert(&invert)) { | 678 if (!viewMatrix.invert(&invert)) { |
| 676 return; | 679 return; |
| 677 } | 680 } |
| 678 | 681 |
| 679 GrDrawState::AutoViewMatrixRestore avmr(drawState); | |
| 680 | |
| 681 SkStrokeRec::Style style = stroke.getStyle(); | 682 SkStrokeRec::Style style = stroke.getStyle(); |
| 682 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || | 683 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || |
| 683 SkStrokeRec::kHairline_Style == style; | 684 SkStrokeRec::kHairline_Style == style; |
| 684 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; | 685 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; |
| 685 | 686 |
| 686 SkScalar innerRadius = 0.0f; | 687 SkScalar innerRadius = 0.0f; |
| 687 SkScalar outerRadius = radius; | 688 SkScalar outerRadius = radius; |
| 688 SkScalar halfWidth = 0; | 689 SkScalar halfWidth = 0; |
| 689 if (hasStroke) { | 690 if (hasStroke) { |
| 690 if (SkScalarNearlyZero(strokeWidth)) { | 691 if (SkScalarNearlyZero(strokeWidth)) { |
| 691 halfWidth = SK_ScalarHalf; | 692 halfWidth = SK_ScalarHalf; |
| 692 } else { | 693 } else { |
| 693 halfWidth = SkScalarHalf(strokeWidth); | 694 halfWidth = SkScalarHalf(strokeWidth); |
| 694 } | 695 } |
| 695 | 696 |
| 696 outerRadius += halfWidth; | 697 outerRadius += halfWidth; |
| 697 if (isStrokeOnly) { | 698 if (isStrokeOnly) { |
| 698 innerRadius = radius - halfWidth; | 699 innerRadius = radius - halfWidth; |
| 699 } | 700 } |
| 700 } | 701 } |
| 701 | 702 |
| 702 SkAutoTUnref<GrGeometryProcessor> gp( | 703 SkAutoTUnref<GrGeometryProcessor> gp( |
| 703 CircleEdgeEffect::Create(color, isStrokeOnly && innerRadius > 0, inv
ert)); | 704 CircleEdgeEffect::Create(color, isStrokeOnly && innerRadius > 0,inve
rt)); |
| 704 | 705 |
| 705 GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); | 706 GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); |
| 706 SkASSERT(gp->getVertexStride() == sizeof(CircleVertex)); | 707 SkASSERT(gp->getVertexStride() == sizeof(CircleVertex)); |
| 707 if (!geo.succeeded()) { | 708 if (!geo.succeeded()) { |
| 708 SkDebugf("Failed to get space for vertices!\n"); | 709 SkDebugf("Failed to get space for vertices!\n"); |
| 709 return; | 710 return; |
| 710 } | 711 } |
| 711 | 712 |
| 712 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); | 713 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); |
| 713 | 714 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 750 target->setIndexSourceToBuffer(fGpu->getQuadIndexBuffer()); | 751 target->setIndexSourceToBuffer(fGpu->getQuadIndexBuffer()); |
| 751 target->drawIndexedInstances(drawState, gp, kTriangles_GrPrimitiveType, 1, 4
, 6, &bounds); | 752 target->drawIndexedInstances(drawState, gp, kTriangles_GrPrimitiveType, 1, 4
, 6, &bounds); |
| 752 target->resetIndexSource(); | 753 target->resetIndexSource(); |
| 753 } | 754 } |
| 754 | 755 |
| 755 /////////////////////////////////////////////////////////////////////////////// | 756 /////////////////////////////////////////////////////////////////////////////// |
| 756 | 757 |
| 757 bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, | 758 bool GrOvalRenderer::drawEllipse(GrDrawTarget* target, |
| 758 GrDrawState* drawState, | 759 GrDrawState* drawState, |
| 759 GrColor color, | 760 GrColor color, |
| 761 const SkMatrix& viewMatrix, |
| 760 bool useCoverageAA, | 762 bool useCoverageAA, |
| 761 const SkRect& ellipse, | 763 const SkRect& ellipse, |
| 762 const SkStrokeRec& stroke) | 764 const SkStrokeRec& stroke) { |
| 763 { | |
| 764 #ifdef SK_DEBUG | 765 #ifdef SK_DEBUG |
| 765 { | 766 { |
| 766 // we should have checked for this previously | 767 // we should have checked for this previously |
| 767 bool isAxisAlignedEllipse = drawState->getViewMatrix().rectStaysRect(); | 768 bool isAxisAlignedEllipse = viewMatrix.rectStaysRect(); |
| 768 SkASSERT(useCoverageAA && isAxisAlignedEllipse); | 769 SkASSERT(useCoverageAA && isAxisAlignedEllipse); |
| 769 } | 770 } |
| 770 #endif | 771 #endif |
| 771 | 772 |
| 772 // do any matrix crunching before we reset the draw state for device coords | 773 // do any matrix crunching before we reset the draw state for device coords |
| 773 const SkMatrix& vm = drawState->getViewMatrix(); | |
| 774 SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); | 774 SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); |
| 775 vm.mapPoints(¢er, 1); | 775 viewMatrix.mapPoints(¢er, 1); |
| 776 SkScalar ellipseXRadius = SkScalarHalf(ellipse.width()); | 776 SkScalar ellipseXRadius = SkScalarHalf(ellipse.width()); |
| 777 SkScalar ellipseYRadius = SkScalarHalf(ellipse.height()); | 777 SkScalar ellipseYRadius = SkScalarHalf(ellipse.height()); |
| 778 SkScalar xRadius = SkScalarAbs(vm[SkMatrix::kMScaleX]*ellipseXRadius + | 778 SkScalar xRadius = SkScalarAbs(viewMatrix[SkMatrix::kMScaleX]*ellipseXRadius
+ |
| 779 vm[SkMatrix::kMSkewY]*ellipseYRadius); | 779 viewMatrix[SkMatrix::kMSkewY]*ellipseYRadius)
; |
| 780 SkScalar yRadius = SkScalarAbs(vm[SkMatrix::kMSkewX]*ellipseXRadius + | 780 SkScalar yRadius = SkScalarAbs(viewMatrix[SkMatrix::kMSkewX]*ellipseXRadius
+ |
| 781 vm[SkMatrix::kMScaleY]*ellipseYRadius); | 781 viewMatrix[SkMatrix::kMScaleY]*ellipseYRadius
); |
| 782 | 782 |
| 783 // do (potentially) anisotropic mapping of stroke | 783 // do (potentially) anisotropic mapping of stroke |
| 784 SkVector scaledStroke; | 784 SkVector scaledStroke; |
| 785 SkScalar strokeWidth = stroke.getWidth(); | 785 SkScalar strokeWidth = stroke.getWidth(); |
| 786 scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] + vm[SkMat
rix::kMSkewY])); | 786 scaledStroke.fX = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMScaleX] + |
| 787 scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] + vm[SkMatr
ix::kMScaleY])); | 787 viewMatrix[SkMatrix::kMSkewY])); |
| 788 scaledStroke.fY = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSkewX] + |
| 789 viewMatrix[SkMatrix::kMScaleY])); |
| 788 | 790 |
| 789 SkStrokeRec::Style style = stroke.getStyle(); | 791 SkStrokeRec::Style style = stroke.getStyle(); |
| 790 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || | 792 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || |
| 791 SkStrokeRec::kHairline_Style == style; | 793 SkStrokeRec::kHairline_Style == style; |
| 792 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; | 794 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; |
| 793 | 795 |
| 794 SkScalar innerXRadius = 0; | 796 SkScalar innerXRadius = 0; |
| 795 SkScalar innerYRadius = 0; | 797 SkScalar innerYRadius = 0; |
| 796 if (hasStroke) { | 798 if (hasStroke) { |
| 797 if (SkScalarNearlyZero(scaledStroke.length())) { | 799 if (SkScalarNearlyZero(scaledStroke.length())) { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 816 if (isStrokeOnly) { | 818 if (isStrokeOnly) { |
| 817 innerXRadius = xRadius - scaledStroke.fX; | 819 innerXRadius = xRadius - scaledStroke.fX; |
| 818 innerYRadius = yRadius - scaledStroke.fY; | 820 innerYRadius = yRadius - scaledStroke.fY; |
| 819 } | 821 } |
| 820 | 822 |
| 821 xRadius += scaledStroke.fX; | 823 xRadius += scaledStroke.fX; |
| 822 yRadius += scaledStroke.fY; | 824 yRadius += scaledStroke.fY; |
| 823 } | 825 } |
| 824 | 826 |
| 825 SkMatrix invert; | 827 SkMatrix invert; |
| 826 if (!vm.invert(&invert)) { | 828 if (!viewMatrix.invert(&invert)) { |
| 827 return false; | 829 return false; |
| 828 } | 830 } |
| 829 | 831 |
| 830 GrDrawState::AutoViewMatrixRestore avmr(drawState); | |
| 831 | |
| 832 SkAutoTUnref<GrGeometryProcessor> gp( | 832 SkAutoTUnref<GrGeometryProcessor> gp( |
| 833 EllipseEdgeEffect::Create(color, isStrokeOnly && innerXRadius > 0 &&
innerYRadius > 0, | 833 EllipseEdgeEffect::Create(color, |
| 834 isStrokeOnly && innerXRadius > 0 && innerY
Radius > 0, |
| 834 invert)); | 835 invert)); |
| 835 | 836 |
| 836 GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); | 837 GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); |
| 837 SkASSERT(gp->getVertexStride() == sizeof(EllipseVertex)); | 838 SkASSERT(gp->getVertexStride() == sizeof(EllipseVertex)); |
| 838 if (!geo.succeeded()) { | 839 if (!geo.succeeded()) { |
| 839 SkDebugf("Failed to get space for vertices!\n"); | 840 SkDebugf("Failed to get space for vertices!\n"); |
| 840 return false; | 841 return false; |
| 841 } | 842 } |
| 842 | 843 |
| 843 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); | 844 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 884 target->setIndexSourceToBuffer(fGpu->getQuadIndexBuffer()); | 885 target->setIndexSourceToBuffer(fGpu->getQuadIndexBuffer()); |
| 885 target->drawIndexedInstances(drawState, gp, kTriangles_GrPrimitiveType, 1, 4
, 6, &bounds); | 886 target->drawIndexedInstances(drawState, gp, kTriangles_GrPrimitiveType, 1, 4
, 6, &bounds); |
| 886 target->resetIndexSource(); | 887 target->resetIndexSource(); |
| 887 | 888 |
| 888 return true; | 889 return true; |
| 889 } | 890 } |
| 890 | 891 |
| 891 bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target, | 892 bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target, |
| 892 GrDrawState* drawState, | 893 GrDrawState* drawState, |
| 893 GrColor color, | 894 GrColor color, |
| 895 const SkMatrix& viewMatrix, |
| 894 bool useCoverageAA, | 896 bool useCoverageAA, |
| 895 const SkRect& ellipse, | 897 const SkRect& ellipse, |
| 896 const SkStrokeRec& stroke) | 898 const SkStrokeRec& stroke) { |
| 897 { | |
| 898 const SkMatrix& vm = drawState->getViewMatrix(); | |
| 899 | |
| 900 SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); | 899 SkPoint center = SkPoint::Make(ellipse.centerX(), ellipse.centerY()); |
| 901 SkScalar xRadius = SkScalarHalf(ellipse.width()); | 900 SkScalar xRadius = SkScalarHalf(ellipse.width()); |
| 902 SkScalar yRadius = SkScalarHalf(ellipse.height()); | 901 SkScalar yRadius = SkScalarHalf(ellipse.height()); |
| 903 | 902 |
| 904 SkStrokeRec::Style style = stroke.getStyle(); | 903 SkStrokeRec::Style style = stroke.getStyle(); |
| 905 DIEllipseEdgeEffect::Mode mode = (SkStrokeRec::kStroke_Style == style) ? | 904 DIEllipseEdgeEffect::Mode mode = (SkStrokeRec::kStroke_Style == style) ? |
| 906 DIEllipseEdgeEffect::kStroke : | 905 DIEllipseEdgeEffect::kStroke : |
| 907 (SkStrokeRec::kHairline_Style == style) ? | 906 (SkStrokeRec::kHairline_Style == style) ? |
| 908 DIEllipseEdgeEffect::kHairline : DIEllipseEd
geEffect::kFill; | 907 DIEllipseEdgeEffect::kHairline : DIEllipseEd
geEffect::kFill; |
| 909 | 908 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 939 xRadius += strokeWidth; | 938 xRadius += strokeWidth; |
| 940 yRadius += strokeWidth; | 939 yRadius += strokeWidth; |
| 941 } | 940 } |
| 942 if (DIEllipseEdgeEffect::kStroke == mode) { | 941 if (DIEllipseEdgeEffect::kStroke == mode) { |
| 943 mode = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseEdgeEffect::kSt
roke : | 942 mode = (innerXRadius > 0 && innerYRadius > 0) ? DIEllipseEdgeEffect::kSt
roke : |
| 944 DIEllipseEdgeEffect::kFi
ll; | 943 DIEllipseEdgeEffect::kFi
ll; |
| 945 } | 944 } |
| 946 SkScalar innerRatioX = SkScalarDiv(xRadius, innerXRadius); | 945 SkScalar innerRatioX = SkScalarDiv(xRadius, innerXRadius); |
| 947 SkScalar innerRatioY = SkScalarDiv(yRadius, innerYRadius); | 946 SkScalar innerRatioY = SkScalarDiv(yRadius, innerYRadius); |
| 948 | 947 |
| 949 SkAutoTUnref<GrGeometryProcessor> gp(DIEllipseEdgeEffect::Create(color, mode
)); | 948 SkAutoTUnref<GrGeometryProcessor> gp(DIEllipseEdgeEffect::Create(color, view
Matrix, mode)); |
| 950 | 949 |
| 951 GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); | 950 GrDrawTarget::AutoReleaseGeometry geo(target, 4, gp->getVertexStride(), 0); |
| 952 SkASSERT(gp->getVertexStride() == sizeof(DIEllipseVertex)); | 951 SkASSERT(gp->getVertexStride() == sizeof(DIEllipseVertex)); |
| 953 if (!geo.succeeded()) { | 952 if (!geo.succeeded()) { |
| 954 SkDebugf("Failed to get space for vertices!\n"); | 953 SkDebugf("Failed to get space for vertices!\n"); |
| 955 return false; | 954 return false; |
| 956 } | 955 } |
| 957 | 956 |
| 958 DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(geo.vertices()); | 957 DIEllipseVertex* verts = reinterpret_cast<DIEllipseVertex*>(geo.vertices()); |
| 959 | 958 |
| 960 // This expands the outer rect so that after CTM we end up with a half-pixel
border | 959 // This expands the outer rect so that after CTM we end up with a half-pixel
border |
| 961 SkScalar a = vm[SkMatrix::kMScaleX]; | 960 SkScalar a = viewMatrix[SkMatrix::kMScaleX]; |
| 962 SkScalar b = vm[SkMatrix::kMSkewX]; | 961 SkScalar b = viewMatrix[SkMatrix::kMSkewX]; |
| 963 SkScalar c = vm[SkMatrix::kMSkewY]; | 962 SkScalar c = viewMatrix[SkMatrix::kMSkewY]; |
| 964 SkScalar d = vm[SkMatrix::kMScaleY]; | 963 SkScalar d = viewMatrix[SkMatrix::kMScaleY]; |
| 965 SkScalar geoDx = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(a*a + c*c)); | 964 SkScalar geoDx = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(a*a + c*c)); |
| 966 SkScalar geoDy = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(b*b + d*d)); | 965 SkScalar geoDy = SkScalarDiv(SK_ScalarHalf, SkScalarSqrt(b*b + d*d)); |
| 967 // This adjusts the "radius" to include the half-pixel border | 966 // This adjusts the "radius" to include the half-pixel border |
| 968 SkScalar offsetDx = SkScalarDiv(geoDx, xRadius); | 967 SkScalar offsetDx = SkScalarDiv(geoDx, xRadius); |
| 969 SkScalar offsetDy = SkScalarDiv(geoDy, yRadius); | 968 SkScalar offsetDy = SkScalarDiv(geoDy, yRadius); |
| 970 | 969 |
| 971 SkRect bounds = SkRect::MakeLTRB( | 970 SkRect bounds = SkRect::MakeLTRB( |
| 972 center.fX - xRadius - geoDx, | 971 center.fX - xRadius - geoDx, |
| 973 center.fY - yRadius - geoDy, | 972 center.fY - yRadius - geoDy, |
| 974 center.fX + xRadius + geoDx, | 973 center.fX + xRadius + geoDx, |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1039 kNumRRectsInInd
exBuffer, | 1038 kNumRRectsInInd
exBuffer, |
| 1040 kVertsPerRRect)
; | 1039 kVertsPerRRect)
; |
| 1041 } | 1040 } |
| 1042 return fRRectIndexBuffer; | 1041 return fRRectIndexBuffer; |
| 1043 } | 1042 } |
| 1044 } | 1043 } |
| 1045 | 1044 |
| 1046 bool GrOvalRenderer::drawDRRect(GrDrawTarget* target, | 1045 bool GrOvalRenderer::drawDRRect(GrDrawTarget* target, |
| 1047 GrDrawState* drawState, | 1046 GrDrawState* drawState, |
| 1048 GrColor color, | 1047 GrColor color, |
| 1048 const SkMatrix& viewMatrix, |
| 1049 bool useAA, | 1049 bool useAA, |
| 1050 const SkRRect& origOuter, | 1050 const SkRRect& origOuter, |
| 1051 const SkRRect& origInner) { | 1051 const SkRRect& origInner) { |
| 1052 bool applyAA = useAA && | 1052 bool applyAA = useAA && |
| 1053 !drawState->getRenderTarget()->isMultisampled() && | 1053 !drawState->getRenderTarget()->isMultisampled() && |
| 1054 drawState->canUseFracCoveragePrimProc(color, *target->caps())
; | 1054 drawState->canUseFracCoveragePrimProc(color, *target->caps())
; |
| 1055 GrDrawState::AutoRestoreEffects are; | 1055 GrDrawState::AutoRestoreEffects are; |
| 1056 if (!origInner.isEmpty()) { | 1056 if (!origInner.isEmpty()) { |
| 1057 SkTCopyOnFirstWrite<SkRRect> inner(origInner); | 1057 SkTCopyOnFirstWrite<SkRRect> inner(origInner); |
| 1058 if (!drawState->getViewMatrix().isIdentity()) { | 1058 if (!viewMatrix.isIdentity()) { |
| 1059 if (!origInner.transform(drawState->getViewMatrix(), inner.writable(
))) { | 1059 if (!origInner.transform(viewMatrix, inner.writable())) { |
| 1060 return false; | 1060 return false; |
| 1061 } | 1061 } |
| 1062 } | 1062 } |
| 1063 GrPrimitiveEdgeType edgeType = applyAA ? | 1063 GrPrimitiveEdgeType edgeType = applyAA ? |
| 1064 kInverseFillAA_GrProcessorEdgeType : | 1064 kInverseFillAA_GrProcessorEdgeType : |
| 1065 kInverseFillBW_GrProcessorEdgeType; | 1065 kInverseFillBW_GrProcessorEdgeType; |
| 1066 // TODO this needs to be a geometry processor | 1066 // TODO this needs to be a geometry processor |
| 1067 GrFragmentProcessor* fp = GrRRectEffect::Create(edgeType, *inner); | 1067 GrFragmentProcessor* fp = GrRRectEffect::Create(edgeType, *inner); |
| 1068 if (NULL == fp) { | 1068 if (NULL == fp) { |
| 1069 return false; | 1069 return false; |
| 1070 } | 1070 } |
| 1071 are.set(drawState); | 1071 are.set(drawState); |
| 1072 drawState->addCoverageProcessor(fp)->unref(); | 1072 drawState->addCoverageProcessor(fp)->unref(); |
| 1073 } | 1073 } |
| 1074 | 1074 |
| 1075 SkStrokeRec fillRec(SkStrokeRec::kFill_InitStyle); | 1075 SkStrokeRec fillRec(SkStrokeRec::kFill_InitStyle); |
| 1076 if (this->drawRRect(target, drawState, color, useAA, origOuter, fillRec)) { | 1076 if (this->drawRRect(target, drawState, color, viewMatrix, useAA, origOuter,
fillRec)) { |
| 1077 return true; | 1077 return true; |
| 1078 } | 1078 } |
| 1079 | 1079 |
| 1080 SkASSERT(!origOuter.isEmpty()); | 1080 SkASSERT(!origOuter.isEmpty()); |
| 1081 SkTCopyOnFirstWrite<SkRRect> outer(origOuter); | 1081 SkTCopyOnFirstWrite<SkRRect> outer(origOuter); |
| 1082 if (!drawState->getViewMatrix().isIdentity()) { | 1082 if (!viewMatrix.isIdentity()) { |
| 1083 if (!origOuter.transform(drawState->getViewMatrix(), outer.writable()))
{ | 1083 if (!origOuter.transform(viewMatrix, outer.writable())) { |
| 1084 return false; | 1084 return false; |
| 1085 } | 1085 } |
| 1086 } | 1086 } |
| 1087 GrPrimitiveEdgeType edgeType = applyAA ? kFillAA_GrProcessorEdgeType : | 1087 GrPrimitiveEdgeType edgeType = applyAA ? kFillAA_GrProcessorEdgeType : |
| 1088 kFillBW_GrProcessorEdgeType; | 1088 kFillBW_GrProcessorEdgeType; |
| 1089 GrFragmentProcessor* effect = GrRRectEffect::Create(edgeType, *outer); | 1089 GrFragmentProcessor* effect = GrRRectEffect::Create(edgeType, *outer); |
| 1090 if (NULL == effect) { | 1090 if (NULL == effect) { |
| 1091 return false; | 1091 return false; |
| 1092 } | 1092 } |
| 1093 if (!are.isSet()) { | 1093 if (!are.isSet()) { |
| 1094 are.set(drawState); | 1094 are.set(drawState); |
| 1095 } | 1095 } |
| 1096 | 1096 |
| 1097 SkMatrix invert; | 1097 SkMatrix invert; |
| 1098 if (!drawState->getViewMatrix().invert(&invert)) { | 1098 if (!viewMatrix.invert(&invert)) { |
| 1099 return false; | 1099 return false; |
| 1100 } | 1100 } |
| 1101 | 1101 |
| 1102 GrDrawState::AutoViewMatrixRestore avmr(drawState); | |
| 1103 drawState->addCoverageProcessor(effect)->unref(); | 1102 drawState->addCoverageProcessor(effect)->unref(); |
| 1104 SkRect bounds = outer->getBounds(); | 1103 SkRect bounds = outer->getBounds(); |
| 1105 if (applyAA) { | 1104 if (applyAA) { |
| 1106 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); | 1105 bounds.outset(SK_ScalarHalf, SK_ScalarHalf); |
| 1107 } | 1106 } |
| 1108 target->drawRect(drawState, color, bounds, NULL, &invert); | 1107 target->drawRect(drawState, color, SkMatrix::I(), bounds, NULL, &invert); |
| 1109 return true; | 1108 return true; |
| 1110 } | 1109 } |
| 1111 | 1110 |
| 1112 bool GrOvalRenderer::drawRRect(GrDrawTarget* target, | 1111 bool GrOvalRenderer::drawRRect(GrDrawTarget* target, |
| 1113 GrDrawState* drawState, | 1112 GrDrawState* drawState, |
| 1114 GrColor color, | 1113 GrColor color, |
| 1114 const SkMatrix& viewMatrix, |
| 1115 bool useAA, | 1115 bool useAA, |
| 1116 const SkRRect& rrect, | 1116 const SkRRect& rrect, |
| 1117 const SkStrokeRec& stroke) { | 1117 const SkStrokeRec& stroke) { |
| 1118 if (rrect.isOval()) { | 1118 if (rrect.isOval()) { |
| 1119 return this->drawOval(target, drawState, color, useAA, rrect.getBounds()
, stroke); | 1119 return this->drawOval(target, drawState, color, viewMatrix, useAA, rrect
.getBounds(), |
| 1120 stroke); |
| 1120 } | 1121 } |
| 1121 | 1122 |
| 1122 bool useCoverageAA = useAA && | 1123 bool useCoverageAA = useAA && |
| 1123 !drawState->getRenderTarget()->isMultisampled() && | 1124 !drawState->getRenderTarget()->isMultisampled() && |
| 1124 drawState->canUseFracCoveragePrimProc(color, *target->caps()); | 1125 drawState->canUseFracCoveragePrimProc(color, *target->caps()); |
| 1125 | 1126 |
| 1126 // only anti-aliased rrects for now | 1127 // only anti-aliased rrects for now |
| 1127 if (!useCoverageAA) { | 1128 if (!useCoverageAA) { |
| 1128 return false; | 1129 return false; |
| 1129 } | 1130 } |
| 1130 | 1131 |
| 1131 const SkMatrix& vm = drawState->getViewMatrix(); | 1132 if (!viewMatrix.rectStaysRect() || !rrect.isSimple()) { |
| 1132 | |
| 1133 if (!vm.rectStaysRect() || !rrect.isSimple()) { | |
| 1134 return false; | 1133 return false; |
| 1135 } | 1134 } |
| 1136 | 1135 |
| 1137 // do any matrix crunching before we reset the draw state for device coords | 1136 // do any matrix crunching before we reset the draw state for device coords |
| 1138 const SkRect& rrectBounds = rrect.getBounds(); | 1137 const SkRect& rrectBounds = rrect.getBounds(); |
| 1139 SkRect bounds; | 1138 SkRect bounds; |
| 1140 vm.mapRect(&bounds, rrectBounds); | 1139 viewMatrix.mapRect(&bounds, rrectBounds); |
| 1141 | 1140 |
| 1142 SkVector radii = rrect.getSimpleRadii(); | 1141 SkVector radii = rrect.getSimpleRadii(); |
| 1143 SkScalar xRadius = SkScalarAbs(vm[SkMatrix::kMScaleX]*radii.fX + | 1142 SkScalar xRadius = SkScalarAbs(viewMatrix[SkMatrix::kMScaleX]*radii.fX + |
| 1144 vm[SkMatrix::kMSkewY]*radii.fY); | 1143 viewMatrix[SkMatrix::kMSkewY]*radii.fY); |
| 1145 SkScalar yRadius = SkScalarAbs(vm[SkMatrix::kMSkewX]*radii.fX + | 1144 SkScalar yRadius = SkScalarAbs(viewMatrix[SkMatrix::kMSkewX]*radii.fX + |
| 1146 vm[SkMatrix::kMScaleY]*radii.fY); | 1145 viewMatrix[SkMatrix::kMScaleY]*radii.fY); |
| 1147 | 1146 |
| 1148 SkStrokeRec::Style style = stroke.getStyle(); | 1147 SkStrokeRec::Style style = stroke.getStyle(); |
| 1149 | 1148 |
| 1150 // do (potentially) anisotropic mapping of stroke | 1149 // do (potentially) anisotropic mapping of stroke |
| 1151 SkVector scaledStroke; | 1150 SkVector scaledStroke; |
| 1152 SkScalar strokeWidth = stroke.getWidth(); | 1151 SkScalar strokeWidth = stroke.getWidth(); |
| 1153 | 1152 |
| 1154 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || | 1153 bool isStrokeOnly = SkStrokeRec::kStroke_Style == style || |
| 1155 SkStrokeRec::kHairline_Style == style; | 1154 SkStrokeRec::kHairline_Style == style; |
| 1156 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; | 1155 bool hasStroke = isStrokeOnly || SkStrokeRec::kStrokeAndFill_Style == style; |
| 1157 | 1156 |
| 1158 if (hasStroke) { | 1157 if (hasStroke) { |
| 1159 if (SkStrokeRec::kHairline_Style == style) { | 1158 if (SkStrokeRec::kHairline_Style == style) { |
| 1160 scaledStroke.set(1, 1); | 1159 scaledStroke.set(1, 1); |
| 1161 } else { | 1160 } else { |
| 1162 scaledStroke.fX = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMScaleX] + | 1161 scaledStroke.fX = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSc
aleX] + |
| 1163 vm[SkMatrix::kMSkewY])); | 1162 viewMatrix[SkMatrix::kMSk
ewY])); |
| 1164 scaledStroke.fY = SkScalarAbs(strokeWidth*(vm[SkMatrix::kMSkewX] + | 1163 scaledStroke.fY = SkScalarAbs(strokeWidth*(viewMatrix[SkMatrix::kMSk
ewX] + |
| 1165 vm[SkMatrix::kMScaleY])); | 1164 viewMatrix[SkMatrix::kMSc
aleY])); |
| 1166 } | 1165 } |
| 1167 | 1166 |
| 1168 // if half of strokewidth is greater than radius, we don't handle that r
ight now | 1167 // if half of strokewidth is greater than radius, we don't handle that r
ight now |
| 1169 if (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStrok
e.fY > yRadius) { | 1168 if (SK_ScalarHalf*scaledStroke.fX > xRadius || SK_ScalarHalf*scaledStrok
e.fY > yRadius) { |
| 1170 return false; | 1169 return false; |
| 1171 } | 1170 } |
| 1172 } | 1171 } |
| 1173 | 1172 |
| 1174 // The way the effect interpolates the offset-to-ellipse/circle-center attri
bute only works on | 1173 // The way the effect interpolates the offset-to-ellipse/circle-center attri
bute only works on |
| 1175 // the interior of the rrect if the radii are >= 0.5. Otherwise, the inner r
ect of the nine- | 1174 // the interior of the rrect if the radii are >= 0.5. Otherwise, the inner r
ect of the nine- |
| 1176 // patch will have fractional coverage. This only matters when the interior
is actually filled. | 1175 // patch will have fractional coverage. This only matters when the interior
is actually filled. |
| 1177 // We could consider falling back to rect rendering here, since a tiny radiu
s is | 1176 // We could consider falling back to rect rendering here, since a tiny radiu
s is |
| 1178 // indistinguishable from a square corner. | 1177 // indistinguishable from a square corner. |
| 1179 if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) { | 1178 if (!isStrokeOnly && (SK_ScalarHalf > xRadius || SK_ScalarHalf > yRadius)) { |
| 1180 return false; | 1179 return false; |
| 1181 } | 1180 } |
| 1182 | 1181 |
| 1183 // reset to device coordinates | 1182 // reset to device coordinates |
| 1184 SkMatrix invert; | 1183 SkMatrix invert; |
| 1185 if (!vm.invert(&invert)) { | 1184 if (!viewMatrix.invert(&invert)) { |
| 1186 SkDebugf("Failed to invert\n"); | 1185 SkDebugf("Failed to invert\n"); |
| 1187 return false; | 1186 return false; |
| 1188 } | 1187 } |
| 1189 | 1188 |
| 1190 GrDrawState::AutoViewMatrixRestore avmr(drawState); | |
| 1191 | |
| 1192 GrIndexBuffer* indexBuffer = this->rRectIndexBuffer(isStrokeOnly); | 1189 GrIndexBuffer* indexBuffer = this->rRectIndexBuffer(isStrokeOnly); |
| 1193 if (NULL == indexBuffer) { | 1190 if (NULL == indexBuffer) { |
| 1194 SkDebugf("Failed to create index buffer!\n"); | 1191 SkDebugf("Failed to create index buffer!\n"); |
| 1195 return false; | 1192 return false; |
| 1196 } | 1193 } |
| 1197 | 1194 |
| 1198 // if the corners are circles, use the circle renderer | 1195 // if the corners are circles, use the circle renderer |
| 1199 if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius
) { | 1196 if ((!hasStroke || scaledStroke.fX == scaledStroke.fY) && xRadius == yRadius
) { |
| 1200 SkScalar innerRadius = 0.0f; | 1197 SkScalar innerRadius = 0.0f; |
| 1201 SkScalar outerRadius = xRadius; | 1198 SkScalar outerRadius = xRadius; |
| 1202 SkScalar halfWidth = 0; | 1199 SkScalar halfWidth = 0; |
| 1203 if (hasStroke) { | 1200 if (hasStroke) { |
| 1204 if (SkScalarNearlyZero(scaledStroke.fX)) { | 1201 if (SkScalarNearlyZero(scaledStroke.fX)) { |
| 1205 halfWidth = SK_ScalarHalf; | 1202 halfWidth = SK_ScalarHalf; |
| 1206 } else { | 1203 } else { |
| 1207 halfWidth = SkScalarHalf(scaledStroke.fX); | 1204 halfWidth = SkScalarHalf(scaledStroke.fX); |
| 1208 } | 1205 } |
| 1209 | 1206 |
| 1210 if (isStrokeOnly) { | 1207 if (isStrokeOnly) { |
| 1211 innerRadius = xRadius - halfWidth; | 1208 innerRadius = xRadius - halfWidth; |
| 1212 } | 1209 } |
| 1213 outerRadius += halfWidth; | 1210 outerRadius += halfWidth; |
| 1214 bounds.outset(halfWidth, halfWidth); | 1211 bounds.outset(halfWidth, halfWidth); |
| 1215 } | 1212 } |
| 1216 | 1213 |
| 1217 isStrokeOnly = (isStrokeOnly && innerRadius >= 0); | 1214 isStrokeOnly = (isStrokeOnly && innerRadius >= 0); |
| 1218 | 1215 |
| 1219 SkAutoTUnref<GrGeometryProcessor> effect(CircleEdgeEffect::Create(color,
isStrokeOnly, | 1216 SkAutoTUnref<GrGeometryProcessor> effect(CircleEdgeEffect::Create(color, |
| 1217 isStro
keOnly, |
| 1220 invert
)); | 1218 invert
)); |
| 1221 | 1219 |
| 1222 GrDrawTarget::AutoReleaseGeometry geo(target, 16, effect->getVertexStrid
e(), 0); | 1220 GrDrawTarget::AutoReleaseGeometry geo(target, 16, effect->getVertexStrid
e(), 0); |
| 1223 SkASSERT(effect->getVertexStride() == sizeof(CircleVertex)); | 1221 SkASSERT(effect->getVertexStride() == sizeof(CircleVertex)); |
| 1224 if (!geo.succeeded()) { | 1222 if (!geo.succeeded()) { |
| 1225 SkDebugf("Failed to get space for vertices!\n"); | 1223 SkDebugf("Failed to get space for vertices!\n"); |
| 1226 return false; | 1224 return false; |
| 1227 } | 1225 } |
| 1228 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); | 1226 CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices()); |
| 1229 | 1227 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1309 innerYRadius = yRadius - scaledStroke.fY; | 1307 innerYRadius = yRadius - scaledStroke.fY; |
| 1310 } | 1308 } |
| 1311 | 1309 |
| 1312 xRadius += scaledStroke.fX; | 1310 xRadius += scaledStroke.fX; |
| 1313 yRadius += scaledStroke.fY; | 1311 yRadius += scaledStroke.fY; |
| 1314 bounds.outset(scaledStroke.fX, scaledStroke.fY); | 1312 bounds.outset(scaledStroke.fX, scaledStroke.fY); |
| 1315 } | 1313 } |
| 1316 | 1314 |
| 1317 isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0); | 1315 isStrokeOnly = (isStrokeOnly && innerXRadius >= 0 && innerYRadius >= 0); |
| 1318 | 1316 |
| 1319 SkAutoTUnref<GrGeometryProcessor> effect(EllipseEdgeEffect::Create(color
, isStrokeOnly, | 1317 SkAutoTUnref<GrGeometryProcessor> effect(EllipseEdgeEffect::Create(color
, |
| 1318 isStr
okeOnly, |
| 1320 inver
t)); | 1319 inver
t)); |
| 1321 | 1320 |
| 1322 GrDrawTarget::AutoReleaseGeometry geo(target, 16, effect->getVertexStrid
e(), 0); | 1321 GrDrawTarget::AutoReleaseGeometry geo(target, 16, effect->getVertexStrid
e(), 0); |
| 1323 SkASSERT(effect->getVertexStride() == sizeof(EllipseVertex)); | 1322 SkASSERT(effect->getVertexStride() == sizeof(EllipseVertex)); |
| 1324 if (!geo.succeeded()) { | 1323 if (!geo.succeeded()) { |
| 1325 SkDebugf("Failed to get space for vertices!\n"); | 1324 SkDebugf("Failed to get space for vertices!\n"); |
| 1326 return false; | 1325 return false; |
| 1327 } | 1326 } |
| 1328 | 1327 |
| 1329 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); | 1328 EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices()); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1384 int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 : | 1383 int indexCnt = isStrokeOnly ? SK_ARRAY_COUNT(gRRectIndices) - 6 : |
| 1385 SK_ARRAY_COUNT(gRRectIndices); | 1384 SK_ARRAY_COUNT(gRRectIndices); |
| 1386 target->setIndexSourceToBuffer(indexBuffer); | 1385 target->setIndexSourceToBuffer(indexBuffer); |
| 1387 target->drawIndexedInstances(drawState, effect, kTriangles_GrPrimitiveTy
pe, 1, 16, indexCnt, | 1386 target->drawIndexedInstances(drawState, effect, kTriangles_GrPrimitiveTy
pe, 1, 16, indexCnt, |
| 1388 &bounds); | 1387 &bounds); |
| 1389 } | 1388 } |
| 1390 | 1389 |
| 1391 target->resetIndexSource(); | 1390 target->resetIndexSource(); |
| 1392 return true; | 1391 return true; |
| 1393 } | 1392 } |
| OLD | NEW |