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