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 |