OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 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 <initializer_list> | 8 #include <initializer_list> |
9 #include <functional> | 9 #include <functional> |
10 #include "Test.h" | 10 #include "Test.h" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 return false; | 67 return false; |
68 } | 68 } |
69 } | 69 } |
70 #ifdef SK_BUILD_FOR_WIN | 70 #ifdef SK_BUILD_FOR_WIN |
71 free(const_cast<uint8_t*>(kZeros)); | 71 free(const_cast<uint8_t*>(kZeros)); |
72 #endif | 72 #endif |
73 return true; | 73 return true; |
74 } | 74 } |
75 | 75 |
76 namespace { | 76 namespace { |
| 77 /** |
| 78 * Geo is a factory for creating a GrShape from another representation. It also
answers some |
| 79 * questions about expected behavior for GrShape given the inputs. |
| 80 */ |
| 81 class Geo { |
| 82 public: |
| 83 virtual ~Geo() {}; |
| 84 virtual GrShape makeShape(const SkPaint&) const = 0; |
| 85 virtual SkPath path() const = 0; |
| 86 // These functions allow tests to check for special cases where style gets |
| 87 // applied by GrShape in its constructor (without calling GrShape::applyStyl
e). |
| 88 // These unfortunately rely on knowing details of GrShape's implementation. |
| 89 // These predicates are factored out here to avoid littering the rest of the |
| 90 // test code with GrShape implementation details. |
| 91 virtual bool fillChangesGeom() const { return false; } |
| 92 virtual bool strokeIsConvertedToFill() const { return false; } |
| 93 virtual bool strokeAndFillIsConvertedToFill(const SkPaint&) const { return f
alse; } |
| 94 // Is this something we expect GrShape to recognize as something simpler tha
n a path. |
| 95 virtual bool isNonPath(const SkPaint& paint) const { return true; } |
| 96 }; |
| 97 |
| 98 class RectGeo : public Geo { |
| 99 public: |
| 100 RectGeo(const SkRect& rect) : fRect(rect) {} |
| 101 |
| 102 SkPath path() const override { |
| 103 SkPath path; |
| 104 path.addRect(fRect); |
| 105 return path; |
| 106 } |
| 107 |
| 108 GrShape makeShape(const SkPaint& paint) const override { |
| 109 return GrShape(fRect, paint); |
| 110 } |
| 111 |
| 112 bool strokeAndFillIsConvertedToFill(const SkPaint& paint) const override { |
| 113 SkASSERT(paint.getStyle() == SkPaint::kStrokeAndFill_Style); |
| 114 // Converted to an outset rectangle. |
| 115 return paint.getStrokeJoin() == SkPaint::kMiter_Join && |
| 116 paint.getStrokeMiter() >= SK_ScalarSqrt2; |
| 117 } |
| 118 |
| 119 private: |
| 120 SkRect fRect; |
| 121 }; |
| 122 |
| 123 class RRectGeo : public Geo { |
| 124 public: |
| 125 RRectGeo(const SkRRect& rrect) : fRRect(rrect) {} |
| 126 |
| 127 GrShape makeShape(const SkPaint& paint) const override { |
| 128 return GrShape(fRRect, paint); |
| 129 } |
| 130 |
| 131 SkPath path() const override { |
| 132 SkPath path; |
| 133 path.addRRect(fRRect); |
| 134 return path; |
| 135 } |
| 136 |
| 137 bool strokeAndFillIsConvertedToFill(const SkPaint& paint) const override { |
| 138 SkASSERT(paint.getStyle() == SkPaint::kStrokeAndFill_Style); |
| 139 if (fRRect.isRect()) { |
| 140 return RectGeo(fRRect.rect()).strokeAndFillIsConvertedToFill(paint); |
| 141 } |
| 142 return false; |
| 143 } |
| 144 |
| 145 private: |
| 146 SkRRect fRRect; |
| 147 }; |
| 148 |
| 149 class PathGeo : public Geo { |
| 150 public: |
| 151 enum class Invert { kNo, kYes }; |
| 152 |
| 153 PathGeo(const SkPath& path, Invert invert) : fPath(path) { |
| 154 SkASSERT(!path.isInverseFillType()); |
| 155 if (Invert::kYes == invert) { |
| 156 if (fPath.getFillType() == SkPath::kEvenOdd_FillType) { |
| 157 fPath.setFillType(SkPath::kInverseEvenOdd_FillType); |
| 158 } else { |
| 159 SkASSERT(fPath.getFillType() == SkPath::kWinding_FillType); |
| 160 fPath.setFillType(SkPath::kInverseWinding_FillType); |
| 161 } |
| 162 } |
| 163 } |
| 164 |
| 165 GrShape makeShape(const SkPaint& paint) const override { |
| 166 return GrShape(fPath, paint); |
| 167 } |
| 168 |
| 169 SkPath path() const override { return fPath; } |
| 170 |
| 171 bool fillChangesGeom() const override { |
| 172 // unclosed rects get closed. Lines get turned into empty geometry |
| 173 return this->isUnclosedRect() || (fPath.isLine(nullptr) && !fPath.isInve
rseFillType()); |
| 174 } |
| 175 |
| 176 bool strokeIsConvertedToFill() const override { |
| 177 return this->isAxisAlignedLine(); |
| 178 } |
| 179 |
| 180 bool strokeAndFillIsConvertedToFill(const SkPaint& paint) const override { |
| 181 SkASSERT(paint.getStyle() == SkPaint::kStrokeAndFill_Style); |
| 182 if (this->isAxisAlignedLine()) { |
| 183 // The fill is ignored (zero area) and the stroke is converted to a
rrect. |
| 184 return true; |
| 185 } |
| 186 SkRect rect; |
| 187 unsigned start; |
| 188 SkPath::Direction dir; |
| 189 if (SkPathPriv::IsSimpleClosedRect(fPath, &rect, &dir, &start)) { |
| 190 return RectGeo(rect).strokeAndFillIsConvertedToFill(paint); |
| 191 } |
| 192 return false; |
| 193 } |
| 194 |
| 195 bool isNonPath(const SkPaint& paint) const override { |
| 196 return fPath.isLine(nullptr) || fPath.isEmpty(); |
| 197 } |
| 198 |
| 199 private: |
| 200 bool isAxisAlignedLine() const { |
| 201 SkPoint pts[2]; |
| 202 if (!fPath.isLine(pts)) { |
| 203 return false; |
| 204 } |
| 205 return pts[0].fX == pts[1].fX || pts[0].fY == pts[1].fY; |
| 206 } |
| 207 |
| 208 bool isUnclosedRect() const { |
| 209 bool closed; |
| 210 return fPath.isRect(nullptr, &closed, nullptr) && !closed; |
| 211 } |
| 212 |
| 213 SkPath fPath; |
| 214 }; |
| 215 |
| 216 class RRectPathGeo : public PathGeo { |
| 217 public: |
| 218 enum class RRectForStroke { kNo, kYes }; |
| 219 |
| 220 RRectPathGeo(const SkPath& path, const SkRRect& equivalentRRect, RRectForStr
oke rrectForStroke, |
| 221 Invert invert) |
| 222 : PathGeo(path, invert) |
| 223 , fRRect(equivalentRRect) |
| 224 , fRRectForStroke(rrectForStroke) {} |
| 225 |
| 226 RRectPathGeo(const SkPath& path, const SkRect& equivalentRect, RRectForStrok
e rrectForStroke, |
| 227 Invert invert) |
| 228 : RRectPathGeo(path, SkRRect::MakeRect(equivalentRect), rrectForStro
ke, invert) {} |
| 229 |
| 230 bool isNonPath(const SkPaint& paint) const override { |
| 231 if (SkPaint::kFill_Style == paint.getStyle() || RRectForStroke::kYes ==
fRRectForStroke) { |
| 232 return true; |
| 233 } |
| 234 return false; |
| 235 } |
| 236 |
| 237 const SkRRect& rrect() const { return fRRect; } |
| 238 |
| 239 private: |
| 240 SkRRect fRRect; |
| 241 RRectForStroke fRRectForStroke; |
| 242 }; |
| 243 |
77 class TestCase { | 244 class TestCase { |
78 public: | 245 public: |
79 template <typename GEO> | 246 TestCase(const Geo& geo, const SkPaint& paint, skiatest::Reporter* r, |
80 TestCase(const GEO& geo, const SkPaint& paint, skiatest::Reporter* r, | 247 SkScalar scale = SK_Scalar1) : fBase(geo.makeShape(paint)) { |
81 SkScalar scale = SK_Scalar1) : fBase(geo, paint) { | |
82 this->init(r, scale); | 248 this->init(r, scale); |
83 } | 249 } |
84 | 250 |
| 251 template<typename... ShapeArgs> |
| 252 TestCase(skiatest::Reporter* r, ShapeArgs... shapeArgs) |
| 253 : fBase(shapeArgs...) { |
| 254 this->init(r, SK_Scalar1); |
| 255 } |
| 256 |
85 TestCase(const GrShape& shape, skiatest::Reporter* r, SkScalar scale = SK_Sc
alar1) | 257 TestCase(const GrShape& shape, skiatest::Reporter* r, SkScalar scale = SK_Sc
alar1) |
86 : fBase(shape) { | 258 : fBase(shape) { |
87 this->init(r, scale); | 259 this->init(r, scale); |
88 } | 260 } |
89 | 261 |
90 struct SelfExpectations { | 262 struct SelfExpectations { |
91 bool fPEHasEffect; | 263 bool fPEHasEffect; |
92 bool fPEHasValidKey; | 264 bool fPEHasValidKey; |
93 bool fStrokeApplies; | 265 bool fStrokeApplies; |
94 }; | 266 }; |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 static const SkScalar kIntervals[] = { 0.25, 3.f, 0.5, 2.f }; | 598 static const SkScalar kIntervals[] = { 0.25, 3.f, 0.5, 2.f }; |
427 static const SkScalar kPhase = 0.75; | 599 static const SkScalar kPhase = 0.75; |
428 return SkDashPathEffect::Make(kIntervals, SK_ARRAY_COUNT(kIntervals), kPhase
); | 600 return SkDashPathEffect::Make(kIntervals, SK_ARRAY_COUNT(kIntervals), kPhase
); |
429 } | 601 } |
430 | 602 |
431 static sk_sp<SkPathEffect> make_null_dash() { | 603 static sk_sp<SkPathEffect> make_null_dash() { |
432 static const SkScalar kNullIntervals[] = {0, 0, 0, 0, 0, 0}; | 604 static const SkScalar kNullIntervals[] = {0, 0, 0, 0, 0, 0}; |
433 return SkDashPathEffect::Make(kNullIntervals, SK_ARRAY_COUNT(kNullIntervals)
, 0.f); | 605 return SkDashPathEffect::Make(kNullIntervals, SK_ARRAY_COUNT(kNullIntervals)
, 0.f); |
434 } | 606 } |
435 | 607 |
436 ////////////////////////////////////////////////////////////////////////////// | 608 static void test_basic(skiatest::Reporter* reporter, const Geo& geo) { |
437 // These functions allow tests to check for special cases where style gets | |
438 // applied by GrShape in its constructor (without calling GrShape::applyStyle). | |
439 // These unfortunately rely on knowing details of GrShape's implementation. | |
440 // These predicates are factored out here to avoid littering the rest of the | |
441 // test code with GrShape implementation details. | |
442 | |
443 static bool path_is_axis_aligned_line(const SkPath& path) { | |
444 SkPoint pts[2]; | |
445 if (!path.isLine(pts)) { | |
446 return false; | |
447 } | |
448 return pts[0].fX == pts[1].fX || pts[0].fY == pts[1].fY; | |
449 } | |
450 | |
451 static bool path_is_unclosed_rect(const SkPath& path) { | |
452 bool closed; | |
453 return path.isRect(nullptr, &closed, nullptr) && !closed; | |
454 } | |
455 | |
456 // Will a GrShape constructed from a geometry perform a geometric transformation
if the style is | |
457 // simple fill that would not otherwise be applied. | |
458 template <typename GEO> static bool fill_changes_geom(const GEO& geo) { return f
alse; } | |
459 template <> bool fill_changes_geom<SkPath>(const SkPath& path) { | |
460 // unclosed rects get closed. Lines get turned into empty geometry | |
461 return path_is_unclosed_rect(path) || (path.isLine(nullptr) && !path.isInver
seFillType()); | |
462 } | |
463 | |
464 // Will a GrShape constructed from the geometry with a stroke style (without pat
h effect) perform a | |
465 // geometric transformation that applies the the stroke immediately without stor
ing a stroke style. | |
466 template <typename GEO> static bool stroke_is_converted_to_fill(const GEO& geo)
{ return false; } | |
467 template <> bool stroke_is_converted_to_fill(const SkPath& path) { | |
468 // converted to a rrect. | |
469 return path_is_axis_aligned_line(path); | |
470 } | |
471 | |
472 // Will a GrShape constructed from the geometry with a stroke-and-fill style (wi
thout path effect) | |
473 // perform a geometric transformation that applies the the stroke immediately wi
thout storing a | |
474 // stroke-and-fill style. | |
475 template <typename GEO> static bool stroke_and_fill_is_converted_to_fill(const G
EO& geo, const SkPaint& paint); | |
476 template <> bool stroke_and_fill_is_converted_to_fill(const SkRect& rect, const
SkPaint& paint) { | |
477 SkASSERT(paint.getStyle() == SkPaint::kStrokeAndFill_Style); | |
478 // Converted to an outset rectangle. | |
479 return paint.getStrokeJoin() == SkPaint::kMiter_Join && | |
480 paint.getStrokeMiter() >= SK_ScalarSqrt2; | |
481 } | |
482 template <> bool stroke_and_fill_is_converted_to_fill(const SkPath& path, const
SkPaint& paint) { | |
483 SkASSERT(paint.getStyle() == SkPaint::kStrokeAndFill_Style); | |
484 if (path_is_axis_aligned_line(path)) { | |
485 // The fill is ignored (zero area) and the stroke is converted to a rrec
t. | |
486 return true; | |
487 } | |
488 SkRect rect; | |
489 unsigned start; | |
490 SkPath::Direction dir; | |
491 if (SkPathPriv::IsSimpleClosedRect(path, &rect, &dir, &start)) { | |
492 return stroke_and_fill_is_converted_to_fill<SkRect>(rect, paint); | |
493 } | |
494 return false; | |
495 } | |
496 template <> bool stroke_and_fill_is_converted_to_fill(const SkRRect& rr, const S
kPaint& paint) { | |
497 SkASSERT(paint.getStyle() == SkPaint::kStrokeAndFill_Style); | |
498 if (rr.isRect()) { | |
499 return stroke_and_fill_is_converted_to_fill<SkRect>(rr.rect(), paint); | |
500 } | |
501 return false; | |
502 } | |
503 | |
504 ////////////////////////////////////////////////////////////////////////////// | |
505 | |
506 template<typename GEO> | |
507 static void test_basic(skiatest::Reporter* reporter, const GEO& geo) { | |
508 sk_sp<SkPathEffect> dashPE = make_dash(); | 609 sk_sp<SkPathEffect> dashPE = make_dash(); |
509 | 610 |
510 TestCase::SelfExpectations expectations; | 611 TestCase::SelfExpectations expectations; |
511 SkPaint fill; | 612 SkPaint fill; |
512 | 613 |
513 TestCase fillCase(geo, fill, reporter); | 614 TestCase fillCase(geo, fill, reporter); |
514 expectations.fPEHasEffect = false; | 615 expectations.fPEHasEffect = false; |
515 expectations.fPEHasValidKey = false; | 616 expectations.fPEHasValidKey = false; |
516 expectations.fStrokeApplies = false; | 617 expectations.fStrokeApplies = false; |
517 fillCase.testExpectations(reporter, expectations); | 618 fillCase.testExpectations(reporter, expectations); |
518 // Test that another GrShape instance built from the same primitive is the s
ame. | 619 // Test that another GrShape instance built from the same primitive is the s
ame. |
519 TestCase(geo, fill, reporter).compare(reporter, fillCase, | 620 TestCase(geo, fill, reporter).compare(reporter, fillCase, |
520 TestCase::kAllSame_ComparisonExpecatio
n); | 621 TestCase::kAllSame_ComparisonExpecatio
n); |
521 | 622 |
522 SkPaint stroke2RoundBevel; | 623 SkPaint stroke2RoundBevel; |
523 stroke2RoundBevel.setStyle(SkPaint::kStroke_Style); | 624 stroke2RoundBevel.setStyle(SkPaint::kStroke_Style); |
524 stroke2RoundBevel.setStrokeCap(SkPaint::kRound_Cap); | 625 stroke2RoundBevel.setStrokeCap(SkPaint::kRound_Cap); |
525 stroke2RoundBevel.setStrokeJoin(SkPaint::kBevel_Join); | 626 stroke2RoundBevel.setStrokeJoin(SkPaint::kBevel_Join); |
526 stroke2RoundBevel.setStrokeWidth(2.f); | 627 stroke2RoundBevel.setStrokeWidth(2.f); |
527 TestCase stroke2RoundBevelCase(geo, stroke2RoundBevel, reporter); | 628 TestCase stroke2RoundBevelCase(geo, stroke2RoundBevel, reporter); |
528 expectations.fPEHasValidKey = true; | 629 expectations.fPEHasValidKey = true; |
529 expectations.fPEHasEffect = false; | 630 expectations.fPEHasEffect = false; |
530 expectations.fStrokeApplies = !stroke_is_converted_to_fill(geo); | 631 expectations.fStrokeApplies = !geo.strokeIsConvertedToFill(); |
531 stroke2RoundBevelCase.testExpectations(reporter, expectations); | 632 stroke2RoundBevelCase.testExpectations(reporter, expectations); |
532 TestCase(geo, stroke2RoundBevel, reporter).compare(reporter, stroke2RoundBev
elCase, | 633 TestCase(geo, stroke2RoundBevel, reporter).compare(reporter, stroke2RoundBev
elCase, |
533 TestCase::kAllSame_Compar
isonExpecation); | 634 TestCase::kAllSame_Compar
isonExpecation); |
534 | 635 |
535 SkPaint stroke2RoundBevelDash = stroke2RoundBevel; | 636 SkPaint stroke2RoundBevelDash = stroke2RoundBevel; |
536 stroke2RoundBevelDash.setPathEffect(make_dash()); | 637 stroke2RoundBevelDash.setPathEffect(make_dash()); |
537 TestCase stroke2RoundBevelDashCase(geo, stroke2RoundBevelDash, reporter); | 638 TestCase stroke2RoundBevelDashCase(geo, stroke2RoundBevelDash, reporter); |
538 expectations.fPEHasValidKey = true; | 639 expectations.fPEHasValidKey = true; |
539 expectations.fPEHasEffect = true; | 640 expectations.fPEHasEffect = true; |
540 expectations.fStrokeApplies = true; | 641 expectations.fStrokeApplies = true; |
541 stroke2RoundBevelDashCase.testExpectations(reporter, expectations); | 642 stroke2RoundBevelDashCase.testExpectations(reporter, expectations); |
542 TestCase(geo, stroke2RoundBevelDash, reporter).compare(reporter, stroke2Roun
dBevelDashCase, | 643 TestCase(geo, stroke2RoundBevelDash, reporter).compare(reporter, stroke2Roun
dBevelDashCase, |
543 TestCase::kAllSame_Co
mparisonExpecation); | 644 TestCase::kAllSame_Co
mparisonExpecation); |
544 | 645 |
545 if (fill_changes_geom(geo) || stroke_is_converted_to_fill(geo)) { | 646 if (geo.fillChangesGeom() || geo.strokeIsConvertedToFill()) { |
546 fillCase.compare(reporter, stroke2RoundBevelCase, | 647 fillCase.compare(reporter, stroke2RoundBevelCase, |
547 TestCase::kAllDifferent_ComparisonExpecation); | 648 TestCase::kAllDifferent_ComparisonExpecation); |
548 fillCase.compare(reporter, stroke2RoundBevelDashCase, | 649 fillCase.compare(reporter, stroke2RoundBevelDashCase, |
549 TestCase::kAllDifferent_ComparisonExpecation); | 650 TestCase::kAllDifferent_ComparisonExpecation); |
550 } else { | 651 } else { |
551 fillCase.compare(reporter, stroke2RoundBevelCase, | 652 fillCase.compare(reporter, stroke2RoundBevelCase, |
552 TestCase::kSameUpToStroke_ComparisonExpecation); | 653 TestCase::kSameUpToStroke_ComparisonExpecation); |
553 fillCase.compare(reporter, stroke2RoundBevelDashCase, | 654 fillCase.compare(reporter, stroke2RoundBevelDashCase, |
554 TestCase::kSameUpToPE_ComparisonExpecation); | 655 TestCase::kSameUpToPE_ComparisonExpecation); |
555 } | 656 } |
556 if (stroke_is_converted_to_fill(geo)) { | 657 if (geo.strokeIsConvertedToFill()) { |
557 stroke2RoundBevelCase.compare(reporter, stroke2RoundBevelDashCase, | 658 stroke2RoundBevelCase.compare(reporter, stroke2RoundBevelDashCase, |
558 TestCase::kAllDifferent_ComparisonExpecati
on); | 659 TestCase::kAllDifferent_ComparisonExpecati
on); |
559 } else { | 660 } else { |
560 stroke2RoundBevelCase.compare(reporter, stroke2RoundBevelDashCase, | 661 stroke2RoundBevelCase.compare(reporter, stroke2RoundBevelDashCase, |
561 TestCase::kSameUpToPE_ComparisonExpecation
); | 662 TestCase::kSameUpToPE_ComparisonExpecation
); |
562 } | 663 } |
563 | 664 |
564 // Stroke and fill cases | 665 // Stroke and fill cases |
565 SkPaint stroke2RoundBevelAndFill = stroke2RoundBevel; | 666 SkPaint stroke2RoundBevelAndFill = stroke2RoundBevel; |
566 stroke2RoundBevelAndFill.setStyle(SkPaint::kStrokeAndFill_Style); | 667 stroke2RoundBevelAndFill.setStyle(SkPaint::kStrokeAndFill_Style); |
567 TestCase stroke2RoundBevelAndFillCase(geo, stroke2RoundBevelAndFill, reporte
r); | 668 TestCase stroke2RoundBevelAndFillCase(geo, stroke2RoundBevelAndFill, reporte
r); |
568 expectations.fPEHasValidKey = true; | 669 expectations.fPEHasValidKey = true; |
569 expectations.fPEHasEffect = false; | 670 expectations.fPEHasEffect = false; |
570 expectations.fStrokeApplies = !stroke_is_converted_to_fill(geo); | 671 expectations.fStrokeApplies = !geo.strokeIsConvertedToFill(); |
571 stroke2RoundBevelAndFillCase.testExpectations(reporter, expectations); | 672 stroke2RoundBevelAndFillCase.testExpectations(reporter, expectations); |
572 TestCase(geo, stroke2RoundBevelAndFill, reporter).compare(reporter, | 673 TestCase(geo, stroke2RoundBevelAndFill, reporter).compare(reporter, |
573 stroke2RoundBevelAndFillCase, TestCase::kAllSame_ComparisonExpecatio
n); | 674 stroke2RoundBevelAndFillCase, TestCase::kAllSame_ComparisonExpecatio
n); |
574 | 675 |
575 SkPaint stroke2RoundBevelAndFillDash = stroke2RoundBevelDash; | 676 SkPaint stroke2RoundBevelAndFillDash = stroke2RoundBevelDash; |
576 stroke2RoundBevelAndFillDash.setStyle(SkPaint::kStrokeAndFill_Style); | 677 stroke2RoundBevelAndFillDash.setStyle(SkPaint::kStrokeAndFill_Style); |
577 TestCase stroke2RoundBevelAndFillDashCase(geo, stroke2RoundBevelAndFillDash,
reporter); | 678 TestCase stroke2RoundBevelAndFillDashCase(geo, stroke2RoundBevelAndFillDash,
reporter); |
578 expectations.fPEHasValidKey = true; | 679 expectations.fPEHasValidKey = true; |
579 expectations.fPEHasEffect = false; | 680 expectations.fPEHasEffect = false; |
580 expectations.fStrokeApplies = !stroke_is_converted_to_fill(geo); | 681 expectations.fStrokeApplies = !geo.strokeIsConvertedToFill(); |
581 stroke2RoundBevelAndFillDashCase.testExpectations(reporter, expectations); | 682 stroke2RoundBevelAndFillDashCase.testExpectations(reporter, expectations); |
582 TestCase(geo, stroke2RoundBevelAndFillDash, reporter).compare( | 683 TestCase(geo, stroke2RoundBevelAndFillDash, reporter).compare( |
583 reporter, stroke2RoundBevelAndFillDashCase, TestCase::kAllSame_Compariso
nExpecation); | 684 reporter, stroke2RoundBevelAndFillDashCase, TestCase::kAllSame_Compariso
nExpecation); |
584 stroke2RoundBevelAndFillDashCase.compare(reporter, stroke2RoundBevelAndFillC
ase, | 685 stroke2RoundBevelAndFillDashCase.compare(reporter, stroke2RoundBevelAndFillC
ase, |
585 TestCase::kAllSame_ComparisonExpeca
tion); | 686 TestCase::kAllSame_ComparisonExpeca
tion); |
586 | 687 |
587 SkPaint hairline; | 688 SkPaint hairline; |
588 hairline.setStyle(SkPaint::kStroke_Style); | 689 hairline.setStyle(SkPaint::kStroke_Style); |
589 hairline.setStrokeWidth(0.f); | 690 hairline.setStrokeWidth(0.f); |
590 TestCase hairlineCase(geo, hairline, reporter); | 691 TestCase hairlineCase(geo, hairline, reporter); |
591 // Since hairline style doesn't change the SkPath data, it is keyed identica
lly to fill (except | 692 // Since hairline style doesn't change the SkPath data, it is keyed identica
lly to fill (except |
592 // in the line and unclosed rect cases). | 693 // in the line and unclosed rect cases). |
593 if (fill_changes_geom(geo)) { | 694 if (geo.fillChangesGeom()) { |
594 hairlineCase.compare(reporter, fillCase, TestCase::kAllDifferent_Compari
sonExpecation); | 695 hairlineCase.compare(reporter, fillCase, TestCase::kAllDifferent_Compari
sonExpecation); |
595 } else { | 696 } else { |
596 hairlineCase.compare(reporter, fillCase, TestCase::kAllSame_ComparisonEx
pecation); | 697 hairlineCase.compare(reporter, fillCase, TestCase::kAllSame_ComparisonEx
pecation); |
597 } | 698 } |
598 REPORTER_ASSERT(reporter, hairlineCase.baseShape().style().isSimpleHairline(
)); | 699 REPORTER_ASSERT(reporter, hairlineCase.baseShape().style().isSimpleHairline(
)); |
599 REPORTER_ASSERT(reporter, hairlineCase.appliedFullStyleShape().style().isSim
pleHairline()); | 700 REPORTER_ASSERT(reporter, hairlineCase.appliedFullStyleShape().style().isSim
pleHairline()); |
600 REPORTER_ASSERT(reporter, hairlineCase.appliedPathEffectShape().style().isSi
mpleHairline()); | 701 REPORTER_ASSERT(reporter, hairlineCase.appliedPathEffectShape().style().isSi
mpleHairline()); |
601 | 702 |
602 } | 703 } |
603 | 704 |
604 template<typename GEO> | 705 static void test_scale(skiatest::Reporter* reporter, const Geo& geo) { |
605 static void test_scale(skiatest::Reporter* reporter, const GEO& geo) { | |
606 sk_sp<SkPathEffect> dashPE = make_dash(); | 706 sk_sp<SkPathEffect> dashPE = make_dash(); |
607 | 707 |
608 static const SkScalar kS1 = 1.f; | 708 static const SkScalar kS1 = 1.f; |
609 static const SkScalar kS2 = 2.f; | 709 static const SkScalar kS2 = 2.f; |
610 | 710 |
611 SkPaint fill; | 711 SkPaint fill; |
612 TestCase fillCase1(geo, fill, reporter, kS1); | 712 TestCase fillCase1(geo, fill, reporter, kS1); |
613 TestCase fillCase2(geo, fill, reporter, kS2); | 713 TestCase fillCase2(geo, fill, reporter, kS2); |
614 // Scale doesn't affect fills. | 714 // Scale doesn't affect fills. |
615 fillCase1.compare(reporter, fillCase2, TestCase::kAllSame_ComparisonExpecati
on); | 715 fillCase1.compare(reporter, fillCase2, TestCase::kAllSame_ComparisonExpecati
on); |
616 | 716 |
617 SkPaint hairline; | 717 SkPaint hairline; |
618 hairline.setStyle(SkPaint::kStroke_Style); | 718 hairline.setStyle(SkPaint::kStroke_Style); |
619 hairline.setStrokeWidth(0.f); | 719 hairline.setStrokeWidth(0.f); |
620 TestCase hairlineCase1(geo, hairline, reporter, kS1); | 720 TestCase hairlineCase1(geo, hairline, reporter, kS1); |
621 TestCase hairlineCase2(geo, hairline, reporter, kS2); | 721 TestCase hairlineCase2(geo, hairline, reporter, kS2); |
622 // Scale doesn't affect hairlines. | 722 // Scale doesn't affect hairlines. |
623 hairlineCase1.compare(reporter, hairlineCase2, TestCase::kAllSame_Comparison
Expecation); | 723 hairlineCase1.compare(reporter, hairlineCase2, TestCase::kAllSame_Comparison
Expecation); |
624 | 724 |
625 SkPaint stroke; | 725 SkPaint stroke; |
626 stroke.setStyle(SkPaint::kStroke_Style); | 726 stroke.setStyle(SkPaint::kStroke_Style); |
627 stroke.setStrokeWidth(2.f); | 727 stroke.setStrokeWidth(2.f); |
628 TestCase strokeCase1(geo, stroke, reporter, kS1); | 728 TestCase strokeCase1(geo, stroke, reporter, kS1); |
629 TestCase strokeCase2(geo, stroke, reporter, kS2); | 729 TestCase strokeCase2(geo, stroke, reporter, kS2); |
630 // Scale affects the stroke | 730 // Scale affects the stroke |
631 if (stroke_is_converted_to_fill(geo)) { | 731 if (geo.strokeIsConvertedToFill()) { |
632 REPORTER_ASSERT(reporter, !strokeCase1.baseShape().style().applies()); | 732 REPORTER_ASSERT(reporter, !strokeCase1.baseShape().style().applies()); |
633 strokeCase1.compare(reporter, strokeCase2, TestCase::kAllSame_Comparison
Expecation); | 733 strokeCase1.compare(reporter, strokeCase2, TestCase::kAllSame_Comparison
Expecation); |
634 } else { | 734 } else { |
635 strokeCase1.compare(reporter, strokeCase2, TestCase::kSameUpToStroke_Com
parisonExpecation); | 735 strokeCase1.compare(reporter, strokeCase2, TestCase::kSameUpToStroke_Com
parisonExpecation); |
636 } | 736 } |
637 | 737 |
638 SkPaint strokeDash = stroke; | 738 SkPaint strokeDash = stroke; |
639 strokeDash.setPathEffect(make_dash()); | 739 strokeDash.setPathEffect(make_dash()); |
640 TestCase strokeDashCase1(geo, strokeDash, reporter, kS1); | 740 TestCase strokeDashCase1(geo, strokeDash, reporter, kS1); |
641 TestCase strokeDashCase2(geo, strokeDash, reporter, kS2); | 741 TestCase strokeDashCase2(geo, strokeDash, reporter, kS2); |
642 // Scale affects the dash and the stroke. | 742 // Scale affects the dash and the stroke. |
643 strokeDashCase1.compare(reporter, strokeDashCase2, | 743 strokeDashCase1.compare(reporter, strokeDashCase2, |
644 TestCase::kSameUpToPE_ComparisonExpecation); | 744 TestCase::kSameUpToPE_ComparisonExpecation); |
645 | 745 |
646 // Stroke and fill cases | 746 // Stroke and fill cases |
647 SkPaint strokeAndFill = stroke; | 747 SkPaint strokeAndFill = stroke; |
648 strokeAndFill.setStyle(SkPaint::kStrokeAndFill_Style); | 748 strokeAndFill.setStyle(SkPaint::kStrokeAndFill_Style); |
649 TestCase strokeAndFillCase1(geo, strokeAndFill, reporter, kS1); | 749 TestCase strokeAndFillCase1(geo, strokeAndFill, reporter, kS1); |
650 TestCase strokeAndFillCase2(geo, strokeAndFill, reporter, kS2); | 750 TestCase strokeAndFillCase2(geo, strokeAndFill, reporter, kS2); |
651 SkPaint strokeAndFillDash = strokeDash; | 751 SkPaint strokeAndFillDash = strokeDash; |
652 strokeAndFillDash.setStyle(SkPaint::kStrokeAndFill_Style); | 752 strokeAndFillDash.setStyle(SkPaint::kStrokeAndFill_Style); |
653 // Dash is ignored for stroke and fill | 753 // Dash is ignored for stroke and fill |
654 TestCase strokeAndFillDashCase1(geo, strokeAndFillDash, reporter, kS1); | 754 TestCase strokeAndFillDashCase1(geo, strokeAndFillDash, reporter, kS1); |
655 TestCase strokeAndFillDashCase2(geo, strokeAndFillDash, reporter, kS2); | 755 TestCase strokeAndFillDashCase2(geo, strokeAndFillDash, reporter, kS2); |
656 // Scale affects the stroke, but check to make sure this didn't become a sim
pler shape (e.g. | 756 // Scale affects the stroke, but check to make sure this didn't become a sim
pler shape (e.g. |
657 // stroke-and-filled rect can become a rect), in which case the scale should
n't matter and the | 757 // stroke-and-filled rect can become a rect), in which case the scale should
n't matter and the |
658 // geometries should agree. | 758 // geometries should agree. |
659 if (stroke_and_fill_is_converted_to_fill(geo, strokeAndFillDash)) { | 759 if (geo.strokeAndFillIsConvertedToFill(strokeAndFillDash)) { |
660 REPORTER_ASSERT(reporter, !strokeAndFillCase1.baseShape().style().applie
s()); | 760 REPORTER_ASSERT(reporter, !strokeAndFillCase1.baseShape().style().applie
s()); |
661 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, | 761 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, |
662 TestCase::kAllSame_ComparisonExpecation); | 762 TestCase::kAllSame_ComparisonExpecation); |
663 strokeAndFillDashCase1.compare(reporter, strokeAndFillDashCase2, | 763 strokeAndFillDashCase1.compare(reporter, strokeAndFillDashCase2, |
664 TestCase::kAllSame_ComparisonExpecation); | 764 TestCase::kAllSame_ComparisonExpecation); |
665 } else { | 765 } else { |
666 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, | 766 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, |
667 TestCase::kSameUpToStroke_ComparisonExpecatio
n); | 767 TestCase::kSameUpToStroke_ComparisonExpecatio
n); |
668 } | 768 } |
669 strokeAndFillDashCase1.compare(reporter, strokeAndFillCase1, | 769 strokeAndFillDashCase1.compare(reporter, strokeAndFillCase1, |
670 TestCase::kAllSame_ComparisonExpecation); | 770 TestCase::kAllSame_ComparisonExpecation); |
671 strokeAndFillDashCase2.compare(reporter, strokeAndFillCase2, | 771 strokeAndFillDashCase2.compare(reporter, strokeAndFillCase2, |
672 TestCase::kAllSame_ComparisonExpecation); | 772 TestCase::kAllSame_ComparisonExpecation); |
673 } | 773 } |
674 | 774 |
675 template <typename GEO, typename T> | 775 template <typename T> |
676 static void test_stroke_param_impl(skiatest::Reporter* reporter, const GEO& geo, | 776 static void test_stroke_param_impl(skiatest::Reporter* reporter, const Geo& geo, |
677 std::function<void(SkPaint*, T)> setter, T a,
T b, | 777 std::function<void(SkPaint*, T)> setter, T a,
T b, |
678 bool paramAffectsStroke, | 778 bool paramAffectsStroke, |
679 bool paramAffectsDashAndStroke) { | 779 bool paramAffectsDashAndStroke) { |
680 // Set the stroke width so that we don't get hairline. However, call the set
ter afterward so | 780 // Set the stroke width so that we don't get hairline. However, call the set
ter afterward so |
681 // that it can override the stroke width. | 781 // that it can override the stroke width. |
682 SkPaint strokeA; | 782 SkPaint strokeA; |
683 strokeA.setStyle(SkPaint::kStroke_Style); | 783 strokeA.setStyle(SkPaint::kStroke_Style); |
684 strokeA.setStrokeWidth(2.f); | 784 strokeA.setStrokeWidth(2.f); |
685 setter(&strokeA, a); | 785 setter(&strokeA, a); |
686 SkPaint strokeB; | 786 SkPaint strokeB; |
687 strokeB.setStyle(SkPaint::kStroke_Style); | 787 strokeB.setStyle(SkPaint::kStroke_Style); |
688 strokeB.setStrokeWidth(2.f); | 788 strokeB.setStrokeWidth(2.f); |
689 setter(&strokeB, b); | 789 setter(&strokeB, b); |
690 | 790 |
691 TestCase strokeACase(geo, strokeA, reporter); | 791 TestCase strokeACase(geo, strokeA, reporter); |
692 TestCase strokeBCase(geo, strokeB, reporter); | 792 TestCase strokeBCase(geo, strokeB, reporter); |
693 if (paramAffectsStroke) { | 793 if (paramAffectsStroke) { |
694 // If stroking is immediately incorporated into a geometric transformati
on then the base | 794 // If stroking is immediately incorporated into a geometric transformati
on then the base |
695 // shapes will differ. | 795 // shapes will differ. |
696 if (stroke_is_converted_to_fill(geo)) { | 796 if (geo.strokeIsConvertedToFill()) { |
697 strokeACase.compare(reporter, strokeBCase, | 797 strokeACase.compare(reporter, strokeBCase, |
698 TestCase::kAllDifferent_ComparisonExpecation); | 798 TestCase::kAllDifferent_ComparisonExpecation); |
699 } else { | 799 } else { |
700 strokeACase.compare(reporter, strokeBCase, | 800 strokeACase.compare(reporter, strokeBCase, |
701 TestCase::kSameUpToStroke_ComparisonExpecation); | 801 TestCase::kSameUpToStroke_ComparisonExpecation); |
702 } | 802 } |
703 } else { | 803 } else { |
704 strokeACase.compare(reporter, strokeBCase, TestCase::kAllSame_Comparison
Expecation); | 804 strokeACase.compare(reporter, strokeBCase, TestCase::kAllSame_Comparison
Expecation); |
705 } | 805 } |
706 | 806 |
707 SkPaint strokeAndFillA = strokeA; | 807 SkPaint strokeAndFillA = strokeA; |
708 SkPaint strokeAndFillB = strokeB; | 808 SkPaint strokeAndFillB = strokeB; |
709 strokeAndFillA.setStyle(SkPaint::kStrokeAndFill_Style); | 809 strokeAndFillA.setStyle(SkPaint::kStrokeAndFill_Style); |
710 strokeAndFillB.setStyle(SkPaint::kStrokeAndFill_Style); | 810 strokeAndFillB.setStyle(SkPaint::kStrokeAndFill_Style); |
711 TestCase strokeAndFillACase(geo, strokeAndFillA, reporter); | 811 TestCase strokeAndFillACase(geo, strokeAndFillA, reporter); |
712 TestCase strokeAndFillBCase(geo, strokeAndFillB, reporter); | 812 TestCase strokeAndFillBCase(geo, strokeAndFillB, reporter); |
713 if (paramAffectsStroke) { | 813 if (paramAffectsStroke) { |
714 // If stroking is immediately incorporated into a geometric transformati
on then the base | 814 // If stroking is immediately incorporated into a geometric transformati
on then the base |
715 // shapes will differ. | 815 // shapes will differ. |
716 if (stroke_and_fill_is_converted_to_fill(geo, strokeAndFillA) || | 816 if (geo.strokeAndFillIsConvertedToFill(strokeAndFillA) || |
717 stroke_and_fill_is_converted_to_fill(geo, strokeAndFillB)) { | 817 geo.strokeAndFillIsConvertedToFill(strokeAndFillB)) { |
718 strokeAndFillACase.compare(reporter, strokeAndFillBCase, | 818 strokeAndFillACase.compare(reporter, strokeAndFillBCase, |
719 TestCase::kAllDifferent_ComparisonExpecat
ion); | 819 TestCase::kAllDifferent_ComparisonExpecat
ion); |
720 } else { | 820 } else { |
721 strokeAndFillACase.compare(reporter, strokeAndFillBCase, | 821 strokeAndFillACase.compare(reporter, strokeAndFillBCase, |
722 TestCase::kSameUpToStroke_ComparisonExpec
ation); | 822 TestCase::kSameUpToStroke_ComparisonExpec
ation); |
723 } | 823 } |
724 } else { | 824 } else { |
725 strokeAndFillACase.compare(reporter, strokeAndFillBCase, | 825 strokeAndFillACase.compare(reporter, strokeAndFillBCase, |
726 TestCase::kAllSame_ComparisonExpecation); | 826 TestCase::kAllSame_ComparisonExpecation); |
727 } | 827 } |
(...skipping 13 matching lines...) Expand all Loading... |
741 dashB.setPathEffect(make_dash()); | 841 dashB.setPathEffect(make_dash()); |
742 TestCase dashACase(geo, dashA, reporter); | 842 TestCase dashACase(geo, dashA, reporter); |
743 TestCase dashBCase(geo, dashB, reporter); | 843 TestCase dashBCase(geo, dashB, reporter); |
744 if (paramAffectsDashAndStroke) { | 844 if (paramAffectsDashAndStroke) { |
745 dashACase.compare(reporter, dashBCase, TestCase::kSameUpToStroke_Compari
sonExpecation); | 845 dashACase.compare(reporter, dashBCase, TestCase::kSameUpToStroke_Compari
sonExpecation); |
746 } else { | 846 } else { |
747 dashACase.compare(reporter, dashBCase, TestCase::kAllSame_ComparisonExpe
cation); | 847 dashACase.compare(reporter, dashBCase, TestCase::kAllSame_ComparisonExpe
cation); |
748 } | 848 } |
749 } | 849 } |
750 | 850 |
751 template <typename GEO, typename T> | 851 template <typename T> |
752 static void test_stroke_param(skiatest::Reporter* reporter, const GEO& geo, | 852 static void test_stroke_param(skiatest::Reporter* reporter, const Geo& geo, |
753 std::function<void(SkPaint*, T)> setter, T a, T b)
{ | 853 std::function<void(SkPaint*, T)> setter, T a, T b)
{ |
754 test_stroke_param_impl(reporter, geo, setter, a, b, true, true); | 854 test_stroke_param_impl(reporter, geo, setter, a, b, true, true); |
755 }; | 855 }; |
756 | 856 |
757 template <typename GEO> | 857 static void test_stroke_cap(skiatest::Reporter* reporter, const Geo& geo) { |
758 static void test_stroke_cap(skiatest::Reporter* reporter, const GEO& geo) { | 858 SkPaint hairline; |
759 GrShape shape(geo, GrStyle(SkStrokeRec::kHairline_InitStyle)); | 859 hairline.setStrokeWidth(0); |
| 860 hairline.setStyle(SkPaint::kStroke_Style); |
| 861 GrShape shape = geo.makeShape(hairline); |
760 // The cap should only affect shapes that may be open. | 862 // The cap should only affect shapes that may be open. |
761 bool affectsStroke = !shape.knownToBeClosed(); | 863 bool affectsStroke = !shape.knownToBeClosed(); |
762 // Dashing adds ends that need caps. | 864 // Dashing adds ends that need caps. |
763 bool affectsDashAndStroke = true; | 865 bool affectsDashAndStroke = true; |
764 test_stroke_param_impl<GEO, SkPaint::Cap>( | 866 test_stroke_param_impl<SkPaint::Cap>( |
765 reporter, | 867 reporter, |
766 geo, | 868 geo, |
767 [](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);}, | 869 [](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);}, |
768 SkPaint::kButt_Cap, SkPaint::kRound_Cap, | 870 SkPaint::kButt_Cap, SkPaint::kRound_Cap, |
769 affectsStroke, | 871 affectsStroke, |
770 affectsDashAndStroke); | 872 affectsDashAndStroke); |
771 }; | 873 }; |
772 | 874 |
773 static bool shape_known_not_to_have_joins(const GrShape& shape) { | 875 static bool shape_known_not_to_have_joins(const GrShape& shape) { |
774 return shape.asLine(nullptr, nullptr) || shape.isEmpty(); | 876 return shape.asLine(nullptr, nullptr) || shape.isEmpty(); |
775 } | 877 } |
776 | 878 |
777 template <typename GEO> | 879 static void test_stroke_join(skiatest::Reporter* reporter, const Geo& geo) { |
778 static void test_stroke_join(skiatest::Reporter* reporter, const GEO& geo) { | 880 SkPaint hairline; |
779 GrShape shape(geo, GrStyle(SkStrokeRec::kHairline_InitStyle)); | 881 hairline.setStrokeWidth(0); |
| 882 hairline.setStyle(SkPaint::kStroke_Style); |
| 883 GrShape shape = geo.makeShape(hairline); |
780 // GrShape recognizes certain types don't have joins and will prevent the jo
in type from | 884 // GrShape recognizes certain types don't have joins and will prevent the jo
in type from |
781 // affecting the style key. | 885 // affecting the style key. |
782 // Dashing doesn't add additional joins. However, GrShape currently loses tr
ack of this | 886 // Dashing doesn't add additional joins. However, GrShape currently loses tr
ack of this |
783 // after applying the dash. | 887 // after applying the dash. |
784 bool affectsStroke = !shape_known_not_to_have_joins(shape); | 888 bool affectsStroke = !shape_known_not_to_have_joins(shape); |
785 test_stroke_param_impl<GEO, SkPaint::Join>( | 889 test_stroke_param_impl<SkPaint::Join>( |
786 reporter, | 890 reporter, |
787 geo, | 891 geo, |
788 [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);}, | 892 [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);}, |
789 SkPaint::kRound_Join, SkPaint::kBevel_Join, | 893 SkPaint::kRound_Join, SkPaint::kBevel_Join, |
790 affectsStroke, true); | 894 affectsStroke, true); |
791 }; | 895 }; |
792 | 896 |
793 template <typename GEO> | 897 static void test_miter_limit(skiatest::Reporter* reporter, const Geo& geo) { |
794 static void test_miter_limit(skiatest::Reporter* reporter, const GEO& geo) { | |
795 auto setMiterJoinAndLimit = [](SkPaint* p, SkScalar miter) { | 898 auto setMiterJoinAndLimit = [](SkPaint* p, SkScalar miter) { |
796 p->setStrokeJoin(SkPaint::kMiter_Join); | 899 p->setStrokeJoin(SkPaint::kMiter_Join); |
797 p->setStrokeMiter(miter); | 900 p->setStrokeMiter(miter); |
798 }; | 901 }; |
799 | 902 |
800 auto setOtherJoinAndLimit = [](SkPaint* p, SkScalar miter) { | 903 auto setOtherJoinAndLimit = [](SkPaint* p, SkScalar miter) { |
801 p->setStrokeJoin(SkPaint::kRound_Join); | 904 p->setStrokeJoin(SkPaint::kRound_Join); |
802 p->setStrokeMiter(miter); | 905 p->setStrokeMiter(miter); |
803 }; | 906 }; |
804 | 907 |
805 GrShape shape(geo, GrStyle(SkStrokeRec::kHairline_InitStyle)); | 908 SkPaint hairline; |
| 909 hairline.setStrokeWidth(0); |
| 910 hairline.setStyle(SkPaint::kStroke_Style); |
| 911 GrShape shape = geo.makeShape(hairline); |
806 bool mayHaveJoins = !shape_known_not_to_have_joins(shape); | 912 bool mayHaveJoins = !shape_known_not_to_have_joins(shape); |
807 | 913 |
808 // The miter limit should affect stroked and dashed-stroked cases when the j
oin type is | 914 // The miter limit should affect stroked and dashed-stroked cases when the j
oin type is |
809 // miter. | 915 // miter. |
810 test_stroke_param_impl<GEO, SkScalar>( | 916 test_stroke_param_impl<SkScalar>( |
811 reporter, | 917 reporter, |
812 geo, | 918 geo, |
813 setMiterJoinAndLimit, | 919 setMiterJoinAndLimit, |
814 0.5f, 0.75f, | 920 0.5f, 0.75f, |
815 mayHaveJoins, | 921 mayHaveJoins, |
816 true); | 922 true); |
817 | 923 |
818 // The miter limit should not affect stroked and dashed-stroked cases when t
he join type is | 924 // The miter limit should not affect stroked and dashed-stroked cases when t
he join type is |
819 // not miter. | 925 // not miter. |
820 test_stroke_param_impl<GEO, SkScalar>( | 926 test_stroke_param_impl<SkScalar>( |
821 reporter, | 927 reporter, |
822 geo, | 928 geo, |
823 setOtherJoinAndLimit, | 929 setOtherJoinAndLimit, |
824 0.5f, 0.75f, | 930 0.5f, 0.75f, |
825 false, | 931 false, |
826 false); | 932 false); |
827 } | 933 } |
828 | 934 |
829 template<typename GEO> | 935 static void test_dash_fill(skiatest::Reporter* reporter, const Geo& geo) { |
830 static void test_dash_fill(skiatest::Reporter* reporter, const GEO& geo) { | |
831 // A dash with no stroke should have no effect | 936 // A dash with no stroke should have no effect |
832 using DashFactoryFn = sk_sp<SkPathEffect>(*)(); | 937 using DashFactoryFn = sk_sp<SkPathEffect>(*)(); |
833 for (DashFactoryFn md : {&make_dash, &make_null_dash}) { | 938 for (DashFactoryFn md : {&make_dash, &make_null_dash}) { |
834 SkPaint dashFill; | 939 SkPaint dashFill; |
835 dashFill.setPathEffect((*md)()); | 940 dashFill.setPathEffect((*md)()); |
836 TestCase dashFillCase(geo, dashFill, reporter); | 941 TestCase dashFillCase(geo, dashFill, reporter); |
837 | 942 |
838 TestCase fillCase(geo, SkPaint(), reporter); | 943 TestCase fillCase(geo, SkPaint(), reporter); |
839 dashFillCase.compare(reporter, fillCase, TestCase::kAllSame_ComparisonEx
pecation); | 944 dashFillCase.compare(reporter, fillCase, TestCase::kAllSame_ComparisonEx
pecation); |
840 } | 945 } |
841 } | 946 } |
842 | 947 |
843 template<typename GEO> | 948 void test_null_dash(skiatest::Reporter* reporter, const Geo& geo) { |
844 void test_null_dash(skiatest::Reporter* reporter, const GEO& geo) { | |
845 SkPaint fill; | 949 SkPaint fill; |
846 SkPaint stroke; | 950 SkPaint stroke; |
847 stroke.setStyle(SkPaint::kStroke_Style); | 951 stroke.setStyle(SkPaint::kStroke_Style); |
848 stroke.setStrokeWidth(1.f); | 952 stroke.setStrokeWidth(1.f); |
849 SkPaint dash; | 953 SkPaint dash; |
850 dash.setStyle(SkPaint::kStroke_Style); | 954 dash.setStyle(SkPaint::kStroke_Style); |
851 dash.setStrokeWidth(1.f); | 955 dash.setStrokeWidth(1.f); |
852 dash.setPathEffect(make_dash()); | 956 dash.setPathEffect(make_dash()); |
853 SkPaint nullDash; | 957 SkPaint nullDash; |
854 nullDash.setStyle(SkPaint::kStroke_Style); | 958 nullDash.setStyle(SkPaint::kStroke_Style); |
855 nullDash.setStrokeWidth(1.f); | 959 nullDash.setStrokeWidth(1.f); |
856 nullDash.setPathEffect(make_null_dash()); | 960 nullDash.setPathEffect(make_null_dash()); |
857 | 961 |
858 TestCase fillCase(geo, fill, reporter); | 962 TestCase fillCase(geo, fill, reporter); |
859 TestCase strokeCase(geo, stroke, reporter); | 963 TestCase strokeCase(geo, stroke, reporter); |
860 TestCase dashCase(geo, dash, reporter); | 964 TestCase dashCase(geo, dash, reporter); |
861 TestCase nullDashCase(geo, nullDash, reporter); | 965 TestCase nullDashCase(geo, nullDash, reporter); |
862 | 966 |
863 // We expect the null dash to be ignored so nullDashCase should match stroke
Case, always. | 967 // We expect the null dash to be ignored so nullDashCase should match stroke
Case, always. |
864 nullDashCase.compare(reporter, strokeCase, TestCase::kAllSame_ComparisonExpe
cation); | 968 nullDashCase.compare(reporter, strokeCase, TestCase::kAllSame_ComparisonExpe
cation); |
865 // Check whether the fillCase or strokeCase/nullDashCase would undergo a geo
metric tranformation | 969 // Check whether the fillCase or strokeCase/nullDashCase would undergo a geo
metric tranformation |
866 // on construction in order to determine how to compare the fill and stroke. | 970 // on construction in order to determine how to compare the fill and stroke. |
867 if (fill_changes_geom(geo) || stroke_is_converted_to_fill(geo)) { | 971 if (geo.fillChangesGeom() || geo.strokeIsConvertedToFill()) { |
868 nullDashCase.compare(reporter, fillCase, TestCase::kAllDifferent_Compari
sonExpecation); | 972 nullDashCase.compare(reporter, fillCase, TestCase::kAllDifferent_Compari
sonExpecation); |
869 } else { | 973 } else { |
870 nullDashCase.compare(reporter, fillCase, TestCase::kSameUpToStroke_Compa
risonExpecation); | 974 nullDashCase.compare(reporter, fillCase, TestCase::kSameUpToStroke_Compa
risonExpecation); |
871 } | 975 } |
872 // In the null dash case we may immediately convert to a fill, but not for t
he normal dash case. | 976 // In the null dash case we may immediately convert to a fill, but not for t
he normal dash case. |
873 if (stroke_is_converted_to_fill(geo)) { | 977 if (geo.strokeIsConvertedToFill()) { |
874 nullDashCase.compare(reporter, dashCase, TestCase::kAllDifferent_Compari
sonExpecation); | 978 nullDashCase.compare(reporter, dashCase, TestCase::kAllDifferent_Compari
sonExpecation); |
875 } else { | 979 } else { |
876 nullDashCase.compare(reporter, dashCase, TestCase::kSameUpToPE_Compariso
nExpecation); | 980 nullDashCase.compare(reporter, dashCase, TestCase::kSameUpToPE_Compariso
nExpecation); |
877 } | 981 } |
878 } | 982 } |
879 | 983 |
880 template <typename GEO> | 984 void test_path_effect_makes_rrect(skiatest::Reporter* reporter, const Geo& geo)
{ |
881 void test_path_effect_makes_rrect(skiatest::Reporter* reporter, const GEO& geo)
{ | |
882 /** | 985 /** |
883 * This path effect takes any input path and turns it into a rrect. It passe
s through stroke | 986 * This path effect takes any input path and turns it into a rrect. It passe
s through stroke |
884 * info. | 987 * info. |
885 */ | 988 */ |
886 class RRectPathEffect : SkPathEffect { | 989 class RRectPathEffect : SkPathEffect { |
887 public: | 990 public: |
888 static const SkRRect& RRect() { | 991 static const SkRRect& RRect() { |
889 static const SkRRect kRRect = SkRRect::MakeRectXY(SkRect::MakeWH(12,
12), 3, 5); | 992 static const SkRRect kRRect = SkRRect::MakeRectXY(SkRect::MakeWH(12,
12), 3, 5); |
890 return kRRect; | 993 return kRRect; |
891 } | 994 } |
(...skipping 22 matching lines...) Expand all Loading... |
914 TestCase geoPECase(geo, pe, reporter); | 1017 TestCase geoPECase(geo, pe, reporter); |
915 | 1018 |
916 SkPaint peStroke; | 1019 SkPaint peStroke; |
917 peStroke.setPathEffect(RRectPathEffect::Make()); | 1020 peStroke.setPathEffect(RRectPathEffect::Make()); |
918 peStroke.setStrokeWidth(2.f); | 1021 peStroke.setStrokeWidth(2.f); |
919 peStroke.setStyle(SkPaint::kStroke_Style); | 1022 peStroke.setStyle(SkPaint::kStroke_Style); |
920 TestCase geoPEStrokeCase(geo, peStroke, reporter); | 1023 TestCase geoPEStrokeCase(geo, peStroke, reporter); |
921 | 1024 |
922 // Check whether constructing the filled case would cause the base shape to
have a different | 1025 // Check whether constructing the filled case would cause the base shape to
have a different |
923 // geometry (because of a geometric transformation upon initial GrShape cons
truction). | 1026 // geometry (because of a geometric transformation upon initial GrShape cons
truction). |
924 if (fill_changes_geom(geo)) { | 1027 if (geo.fillChangesGeom()) { |
925 fillGeoCase.compare(reporter, geoPECase, TestCase::kAllDifferent_Compari
sonExpecation); | 1028 fillGeoCase.compare(reporter, geoPECase, TestCase::kAllDifferent_Compari
sonExpecation); |
926 fillGeoCase.compare(reporter, geoPEStrokeCase, | 1029 fillGeoCase.compare(reporter, geoPEStrokeCase, |
927 TestCase::kAllDifferent_ComparisonExpecation); | 1030 TestCase::kAllDifferent_ComparisonExpecation); |
928 } else { | 1031 } else { |
929 fillGeoCase.compare(reporter, geoPECase, TestCase::kSameUpToPE_Compariso
nExpecation); | 1032 fillGeoCase.compare(reporter, geoPECase, TestCase::kSameUpToPE_Compariso
nExpecation); |
930 fillGeoCase.compare(reporter, geoPEStrokeCase, TestCase::kSameUpToPE_Com
parisonExpecation); | 1033 fillGeoCase.compare(reporter, geoPEStrokeCase, TestCase::kSameUpToPE_Com
parisonExpecation); |
931 } | 1034 } |
932 geoPECase.compare(reporter, geoPEStrokeCase, | 1035 geoPECase.compare(reporter, geoPEStrokeCase, |
933 TestCase::kSameUpToStroke_ComparisonExpecation); | 1036 TestCase::kSameUpToStroke_ComparisonExpecation); |
934 | 1037 |
935 TestCase rrectFillCase(RRectPathEffect::RRect(), fill, reporter); | 1038 TestCase rrectFillCase(reporter, RRectPathEffect::RRect(), fill); |
936 SkPaint stroke = peStroke; | 1039 SkPaint stroke = peStroke; |
937 stroke.setPathEffect(nullptr); | 1040 stroke.setPathEffect(nullptr); |
938 TestCase rrectStrokeCase(RRectPathEffect::RRect(), stroke, reporter); | 1041 TestCase rrectStrokeCase(reporter, RRectPathEffect::RRect(), stroke); |
939 | 1042 |
940 SkRRect rrect; | 1043 SkRRect rrect; |
941 // Applying the path effect should make a SkRRect shape. There is no further
stroking in the | 1044 // Applying the path effect should make a SkRRect shape. There is no further
stroking in the |
942 // geoPECase, so the full style should be the same as just the PE. | 1045 // geoPECase, so the full style should be the same as just the PE. |
943 REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectShape().asRRect(&rrect,
nullptr, nullptr, | 1046 REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectShape().asRRect(&rrect,
nullptr, nullptr, |
944 nullptr
)); | 1047 nullptr
)); |
945 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); | 1048 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); |
946 REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectKey() == rrectFillCase.
baseKey()); | 1049 REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectKey() == rrectFillCase.
baseKey()); |
947 | 1050 |
948 REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleShape().asRRect(&rrect,
nullptr, nullptr, | 1051 REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleShape().asRRect(&rrect,
nullptr, nullptr, |
949 nullptr)
); | 1052 nullptr)
); |
950 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); | 1053 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); |
951 REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleKey() == rrectFillCase.b
aseKey()); | 1054 REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleKey() == rrectFillCase.b
aseKey()); |
952 | 1055 |
953 // In the PE+stroke case applying the full style should be the same as just
stroking the rrect. | 1056 // In the PE+stroke case applying the full style should be the same as just
stroking the rrect. |
954 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectShape().asRRect(&
rrect, nullptr, | 1057 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectShape().asRRect(&
rrect, nullptr, |
955 n
ullptr, nullptr)); | 1058 n
ullptr, nullptr)); |
956 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); | 1059 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); |
957 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectKey() == rrectFil
lCase.baseKey()); | 1060 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectKey() == rrectFil
lCase.baseKey()); |
958 | 1061 |
959 REPORTER_ASSERT(reporter, !geoPEStrokeCase.appliedFullStyleShape().asRRect(&
rrect, nullptr, | 1062 REPORTER_ASSERT(reporter, !geoPEStrokeCase.appliedFullStyleShape().asRRect(&
rrect, nullptr, |
960 n
ullptr, nullptr)); | 1063 n
ullptr, nullptr)); |
961 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleKey() == | 1064 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleKey() == |
962 rrectStrokeCase.appliedFullStyleKey()); | 1065 rrectStrokeCase.appliedFullStyleKey()); |
963 } | 1066 } |
964 | 1067 |
965 template <typename GEO> | 1068 void test_unknown_path_effect(skiatest::Reporter* reporter, const Geo& geo) { |
966 void test_unknown_path_effect(skiatest::Reporter* reporter, const GEO& geo) { | |
967 /** | 1069 /** |
968 * This path effect just adds two lineTos to the input path. | 1070 * This path effect just adds two lineTos to the input path. |
969 */ | 1071 */ |
970 class AddLineTosPathEffect : SkPathEffect { | 1072 class AddLineTosPathEffect : SkPathEffect { |
971 public: | 1073 public: |
972 bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, | 1074 bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, |
973 const SkRect* cullR) const override { | 1075 const SkRect* cullR) const override { |
974 *dst = src; | 1076 *dst = src; |
975 dst->lineTo(0, 0); | 1077 dst->lineTo(0, 0); |
976 dst->lineTo(10, 10); | 1078 dst->lineTo(10, 10); |
(...skipping 19 matching lines...) Expand all Loading... |
996 peStroke.setStrokeWidth(2.f); | 1098 peStroke.setStrokeWidth(2.f); |
997 peStroke.setStyle(SkPaint::kStroke_Style); | 1099 peStroke.setStyle(SkPaint::kStroke_Style); |
998 TestCase geoPEStrokeCase(geo, peStroke, reporter); | 1100 TestCase geoPEStrokeCase(geo, peStroke, reporter); |
999 TestCase::SelfExpectations expectations; | 1101 TestCase::SelfExpectations expectations; |
1000 expectations.fPEHasEffect = true; | 1102 expectations.fPEHasEffect = true; |
1001 expectations.fPEHasValidKey = false; | 1103 expectations.fPEHasValidKey = false; |
1002 expectations.fStrokeApplies = true; | 1104 expectations.fStrokeApplies = true; |
1003 geoPEStrokeCase.testExpectations(reporter, expectations); | 1105 geoPEStrokeCase.testExpectations(reporter, expectations); |
1004 } | 1106 } |
1005 | 1107 |
1006 template <typename GEO> | 1108 void test_make_hairline_path_effect(skiatest::Reporter* reporter, const Geo& geo
) { |
1007 void test_make_hairline_path_effect(skiatest::Reporter* reporter, const GEO& geo
, bool isNonPath) { | |
1008 /** | 1109 /** |
1009 * This path effect just changes the stroke rec to hairline. | 1110 * This path effect just changes the stroke rec to hairline. |
1010 */ | 1111 */ |
1011 class MakeHairlinePathEffect : SkPathEffect { | 1112 class MakeHairlinePathEffect : SkPathEffect { |
1012 public: | 1113 public: |
1013 bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* strokeRec, | 1114 bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* strokeRec, |
1014 const SkRect* cullR) const override { | 1115 const SkRect* cullR) const override { |
1015 *dst = src; | 1116 *dst = src; |
1016 strokeRec->setHairlineStyle(); | 1117 strokeRec->setHairlineStyle(); |
1017 return true; | 1118 return true; |
(...skipping 11 matching lines...) Expand all Loading... |
1029 SkPaint fill; | 1130 SkPaint fill; |
1030 SkPaint pe; | 1131 SkPaint pe; |
1031 pe.setPathEffect(MakeHairlinePathEffect::Make()); | 1132 pe.setPathEffect(MakeHairlinePathEffect::Make()); |
1032 | 1133 |
1033 TestCase peCase(geo, pe, reporter); | 1134 TestCase peCase(geo, pe, reporter); |
1034 | 1135 |
1035 SkPath a, b, c; | 1136 SkPath a, b, c; |
1036 peCase.baseShape().asPath(&a); | 1137 peCase.baseShape().asPath(&a); |
1037 peCase.appliedPathEffectShape().asPath(&b); | 1138 peCase.appliedPathEffectShape().asPath(&b); |
1038 peCase.appliedFullStyleShape().asPath(&c); | 1139 peCase.appliedFullStyleShape().asPath(&c); |
1039 if (isNonPath) { | 1140 if (geo.isNonPath(pe)) { |
1040 // RRect types can have a change in start index or direction after the P
E is applied. This | 1141 // RRect types can have a change in start index or direction after the P
E is applied. This |
1041 // is because once the PE is applied, GrShape may canonicalize the dir a
nd index since it | 1142 // is because once the PE is applied, GrShape may canonicalize the dir a
nd index since it |
1042 // is not germane to the styling any longer. | 1143 // is not germane to the styling any longer. |
1043 // Instead we just check that the paths would fill the same both before
and after styling. | 1144 // Instead we just check that the paths would fill the same both before
and after styling. |
1044 REPORTER_ASSERT(reporter, paths_fill_same(a, b)); | 1145 REPORTER_ASSERT(reporter, paths_fill_same(a, b)); |
1045 REPORTER_ASSERT(reporter, paths_fill_same(a, c)); | 1146 REPORTER_ASSERT(reporter, paths_fill_same(a, c)); |
1046 } else { | 1147 } else { |
1047 // The base shape cannot perform canonicalization on the path's fill typ
e because of an | 1148 // The base shape cannot perform canonicalization on the path's fill typ
e because of an |
1048 // unknown path effect. However, after the path effect is applied the re
sulting hairline | 1149 // unknown path effect. However, after the path effect is applied the re
sulting hairline |
1049 // shape will canonicalize the path fill type since hairlines (and strok
ing in general) | 1150 // shape will canonicalize the path fill type since hairlines (and strok
ing in general) |
1050 // don't distinguish between even/odd and non-zero winding. | 1151 // don't distinguish between even/odd and non-zero winding. |
1051 a.setFillType(b.getFillType()); | 1152 a.setFillType(b.getFillType()); |
1052 REPORTER_ASSERT(reporter, a == b); | 1153 REPORTER_ASSERT(reporter, a == b); |
1053 REPORTER_ASSERT(reporter, a == c); | 1154 REPORTER_ASSERT(reporter, a == c); |
1054 REPORTER_ASSERT(reporter, peCase.appliedPathEffectKey().empty()); | 1155 REPORTER_ASSERT(reporter, peCase.appliedPathEffectKey().empty()); |
1055 REPORTER_ASSERT(reporter, peCase.appliedFullStyleKey().empty()); | 1156 REPORTER_ASSERT(reporter, peCase.appliedFullStyleKey().empty()); |
1056 } | 1157 } |
1057 REPORTER_ASSERT(reporter, peCase.appliedPathEffectShape().style().isSimpleHa
irline()); | 1158 REPORTER_ASSERT(reporter, peCase.appliedPathEffectShape().style().isSimpleHa
irline()); |
1058 REPORTER_ASSERT(reporter, peCase.appliedFullStyleShape().style().isSimpleHai
rline()); | 1159 REPORTER_ASSERT(reporter, peCase.appliedFullStyleShape().style().isSimpleHai
rline()); |
1059 } | 1160 } |
1060 | 1161 |
1061 /** | 1162 void test_volatile_path(skiatest::Reporter* reporter, const Geo& geo) { |
1062 * isNonPath indicates whether the initial shape made from the path is expected
to be recognized | 1163 SkPath vPath = geo.path(); |
1063 * as a simpler shape type (e.g. rrect) | |
1064 */ | |
1065 void test_volatile_path(skiatest::Reporter* reporter, const SkPath& path, | |
1066 bool isNonPath) { | |
1067 SkPath vPath(path); | |
1068 vPath.setIsVolatile(true); | 1164 vPath.setIsVolatile(true); |
1069 | 1165 |
1070 SkPaint dashAndStroke; | 1166 SkPaint dashAndStroke; |
1071 dashAndStroke.setPathEffect(make_dash()); | 1167 dashAndStroke.setPathEffect(make_dash()); |
1072 dashAndStroke.setStrokeWidth(2.f); | 1168 dashAndStroke.setStrokeWidth(2.f); |
1073 dashAndStroke.setStyle(SkPaint::kStroke_Style); | 1169 dashAndStroke.setStyle(SkPaint::kStroke_Style); |
1074 TestCase volatileCase(vPath, dashAndStroke, reporter); | 1170 TestCase volatileCase(reporter, vPath, dashAndStroke); |
1075 // We expect a shape made from a volatile path to have a key iff the shape i
s recognized | 1171 // We expect a shape made from a volatile path to have a key iff the shape i
s recognized |
1076 // as a specialized geometry. | 1172 // as a specialized geometry. |
1077 if (isNonPath) { | 1173 if (geo.isNonPath(dashAndStroke)) { |
1078 REPORTER_ASSERT(reporter, SkToBool(volatileCase.baseKey().count())); | 1174 REPORTER_ASSERT(reporter, SkToBool(volatileCase.baseKey().count())); |
1079 // In this case all the keys should be identical to the non-volatile cas
e. | 1175 // In this case all the keys should be identical to the non-volatile cas
e. |
1080 TestCase nonVolatileCase(path, dashAndStroke, reporter); | 1176 TestCase nonVolatileCase(reporter, geo.path(), dashAndStroke); |
1081 volatileCase.compare(reporter, nonVolatileCase, TestCase::kAllSame_Compa
risonExpecation); | 1177 volatileCase.compare(reporter, nonVolatileCase, TestCase::kAllSame_Compa
risonExpecation); |
1082 } else { | 1178 } else { |
1083 // None of the keys should be valid. | 1179 // None of the keys should be valid. |
1084 REPORTER_ASSERT(reporter, !SkToBool(volatileCase.baseKey().count())); | 1180 REPORTER_ASSERT(reporter, !SkToBool(volatileCase.baseKey().count())); |
1085 REPORTER_ASSERT(reporter, !SkToBool(volatileCase.appliedPathEffectKey().
count())); | 1181 REPORTER_ASSERT(reporter, !SkToBool(volatileCase.appliedPathEffectKey().
count())); |
1086 REPORTER_ASSERT(reporter, !SkToBool(volatileCase.appliedFullStyleKey().c
ount())); | 1182 REPORTER_ASSERT(reporter, !SkToBool(volatileCase.appliedFullStyleKey().c
ount())); |
1087 REPORTER_ASSERT(reporter, !SkToBool(volatileCase.appliedPathEffectThenSt
rokeKey().count())); | 1183 REPORTER_ASSERT(reporter, !SkToBool(volatileCase.appliedPathEffectThenSt
rokeKey().count())); |
1088 } | 1184 } |
1089 } | 1185 } |
1090 | 1186 |
1091 template <typename GEO> | 1187 void test_path_effect_makes_empty_shape(skiatest::Reporter* reporter, const Geo&
geo) { |
1092 void test_path_effect_makes_empty_shape(skiatest::Reporter* reporter, const GEO&
geo) { | |
1093 /** | 1188 /** |
1094 * This path effect returns an empty path. | 1189 * This path effect returns an empty path. |
1095 */ | 1190 */ |
1096 class EmptyPathEffect : SkPathEffect { | 1191 class EmptyPathEffect : SkPathEffect { |
1097 public: | 1192 public: |
1098 bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, | 1193 bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, |
1099 const SkRect* cullR) const override { | 1194 const SkRect* cullR) const override { |
1100 dst->reset(); | 1195 dst->reset(); |
1101 return true; | 1196 return true; |
1102 } | 1197 } |
(...skipping 27 matching lines...) Expand all Loading... |
1130 peStroke.setStrokeWidth(2.f); | 1225 peStroke.setStrokeWidth(2.f); |
1131 peStroke.setStyle(SkPaint::kStroke_Style); | 1226 peStroke.setStyle(SkPaint::kStroke_Style); |
1132 TestCase geoPEStrokeCase(geo, peStroke, reporter); | 1227 TestCase geoPEStrokeCase(geo, peStroke, reporter); |
1133 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleKey() == emptyKey)
; | 1228 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleKey() == emptyKey)
; |
1134 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectKey() == emptyKey
); | 1229 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectKey() == emptyKey
); |
1135 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectThenStrokeKey() =
= emptyKey); | 1230 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectThenStrokeKey() =
= emptyKey); |
1136 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectShape().isEmpty()
); | 1231 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectShape().isEmpty()
); |
1137 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleShape().isEmpty())
; | 1232 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleShape().isEmpty())
; |
1138 } | 1233 } |
1139 | 1234 |
1140 template <typename GEO> | 1235 void test_path_effect_fails(skiatest::Reporter* reporter, const Geo& geo) { |
1141 void test_path_effect_fails(skiatest::Reporter* reporter, const GEO& geo) { | |
1142 /** | 1236 /** |
1143 * This path effect always fails to apply. | 1237 * This path effect always fails to apply. |
1144 */ | 1238 */ |
1145 class FailurePathEffect : SkPathEffect { | 1239 class FailurePathEffect : SkPathEffect { |
1146 public: | 1240 public: |
1147 bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, | 1241 bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, |
1148 const SkRect* cullR) const override { | 1242 const SkRect* cullR) const override { |
1149 return false; | 1243 return false; |
1150 } | 1244 } |
1151 void computeFastBounds(SkRect* dst, const SkRect& src) const override { | 1245 void computeFastBounds(SkRect* dst, const SkRect& src) const override { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1196 REPORTER_ASSERT(reporter, paths_fill_same(a, b)); | 1290 REPORTER_ASSERT(reporter, paths_fill_same(a, b)); |
1197 | 1291 |
1198 strokeCase.appliedFullStyleShape().asPath(&a); | 1292 strokeCase.appliedFullStyleShape().asPath(&a); |
1199 peStrokeCase.appliedFullStyleShape().asPath(&b); | 1293 peStrokeCase.appliedFullStyleShape().asPath(&b); |
1200 REPORTER_ASSERT(reporter, paths_fill_same(a, b)); | 1294 REPORTER_ASSERT(reporter, paths_fill_same(a, b)); |
1201 } | 1295 } |
1202 | 1296 |
1203 void test_empty_shape(skiatest::Reporter* reporter) { | 1297 void test_empty_shape(skiatest::Reporter* reporter) { |
1204 SkPath emptyPath; | 1298 SkPath emptyPath; |
1205 SkPaint fill; | 1299 SkPaint fill; |
1206 TestCase fillEmptyCase(emptyPath, fill, reporter); | 1300 TestCase fillEmptyCase(reporter, emptyPath, fill); |
1207 REPORTER_ASSERT(reporter, fillEmptyCase.baseShape().isEmpty()); | 1301 REPORTER_ASSERT(reporter, fillEmptyCase.baseShape().isEmpty()); |
1208 REPORTER_ASSERT(reporter, fillEmptyCase.appliedPathEffectShape().isEmpty()); | 1302 REPORTER_ASSERT(reporter, fillEmptyCase.appliedPathEffectShape().isEmpty()); |
1209 REPORTER_ASSERT(reporter, fillEmptyCase.appliedFullStyleShape().isEmpty()); | 1303 REPORTER_ASSERT(reporter, fillEmptyCase.appliedFullStyleShape().isEmpty()); |
1210 | 1304 |
1211 Key emptyKey(fillEmptyCase.baseKey()); | 1305 Key emptyKey(fillEmptyCase.baseKey()); |
1212 REPORTER_ASSERT(reporter, emptyKey.count()); | 1306 REPORTER_ASSERT(reporter, emptyKey.count()); |
1213 TestCase::SelfExpectations expectations; | 1307 TestCase::SelfExpectations expectations; |
1214 expectations.fStrokeApplies = false; | 1308 expectations.fStrokeApplies = false; |
1215 expectations.fPEHasEffect = false; | 1309 expectations.fPEHasEffect = false; |
1216 // This will test whether applying style preserves emptiness | 1310 // This will test whether applying style preserves emptiness |
1217 fillEmptyCase.testExpectations(reporter, expectations); | 1311 fillEmptyCase.testExpectations(reporter, expectations); |
1218 | 1312 |
1219 // Stroking an empty path should have no effect | 1313 // Stroking an empty path should have no effect |
1220 SkPath emptyPath2; | 1314 SkPath emptyPath2; |
1221 SkPaint stroke; | 1315 SkPaint stroke; |
1222 stroke.setStrokeWidth(2.f); | 1316 stroke.setStrokeWidth(2.f); |
1223 stroke.setStyle(SkPaint::kStroke_Style); | 1317 stroke.setStyle(SkPaint::kStroke_Style); |
1224 TestCase strokeEmptyCase(emptyPath2, stroke, reporter); | 1318 TestCase strokeEmptyCase(reporter, emptyPath2, stroke); |
1225 strokeEmptyCase.compare(reporter, fillEmptyCase, TestCase::kAllSame_Comparis
onExpecation); | 1319 strokeEmptyCase.compare(reporter, fillEmptyCase, TestCase::kAllSame_Comparis
onExpecation); |
1226 | 1320 |
1227 // Dashing and stroking an empty path should have no effect | 1321 // Dashing and stroking an empty path should have no effect |
1228 SkPath emptyPath3; | 1322 SkPath emptyPath3; |
1229 SkPaint dashAndStroke; | 1323 SkPaint dashAndStroke; |
1230 dashAndStroke.setPathEffect(make_dash()); | 1324 dashAndStroke.setPathEffect(make_dash()); |
1231 dashAndStroke.setStrokeWidth(2.f); | 1325 dashAndStroke.setStrokeWidth(2.f); |
1232 dashAndStroke.setStyle(SkPaint::kStroke_Style); | 1326 dashAndStroke.setStyle(SkPaint::kStroke_Style); |
1233 TestCase dashAndStrokeEmptyCase(emptyPath3, dashAndStroke, reporter); | 1327 TestCase dashAndStrokeEmptyCase(reporter, emptyPath3, dashAndStroke); |
1234 dashAndStrokeEmptyCase.compare(reporter, fillEmptyCase, | 1328 dashAndStrokeEmptyCase.compare(reporter, fillEmptyCase, |
1235 TestCase::kAllSame_ComparisonExpecation); | 1329 TestCase::kAllSame_ComparisonExpecation); |
1236 | 1330 |
1237 // A shape made from an empty rrect should behave the same as an empty path. | 1331 // A shape made from an empty rrect should behave the same as an empty path. |
1238 SkRRect emptyRRect = SkRRect::MakeRect(SkRect::MakeEmpty()); | 1332 SkRRect emptyRRect = SkRRect::MakeRect(SkRect::MakeEmpty()); |
1239 REPORTER_ASSERT(reporter, emptyRRect.getType() == SkRRect::kEmpty_Type); | 1333 REPORTER_ASSERT(reporter, emptyRRect.getType() == SkRRect::kEmpty_Type); |
1240 TestCase dashAndStrokeEmptyRRectCase(emptyRRect, dashAndStroke, reporter); | 1334 TestCase dashAndStrokeEmptyRRectCase(reporter, emptyRRect, dashAndStroke); |
1241 dashAndStrokeEmptyRRectCase.compare(reporter, fillEmptyCase, | 1335 dashAndStrokeEmptyRRectCase.compare(reporter, fillEmptyCase, |
1242 TestCase::kAllSame_ComparisonExpecation)
; | 1336 TestCase::kAllSame_ComparisonExpecation)
; |
1243 | 1337 |
1244 // Same for a rect. | 1338 // Same for a rect. |
1245 SkRect emptyRect = SkRect::MakeEmpty(); | 1339 SkRect emptyRect = SkRect::MakeEmpty(); |
1246 TestCase dashAndStrokeEmptyRectCase(emptyRect, dashAndStroke, reporter); | 1340 TestCase dashAndStrokeEmptyRectCase(reporter, emptyRect, dashAndStroke); |
1247 dashAndStrokeEmptyRectCase.compare(reporter, fillEmptyCase, | 1341 dashAndStrokeEmptyRectCase.compare(reporter, fillEmptyCase, |
1248 TestCase::kAllSame_ComparisonExpecation); | 1342 TestCase::kAllSame_ComparisonExpecation); |
1249 } | 1343 } |
1250 | 1344 |
1251 // rect and oval types have rrect start indices that collapse to the same point.
Here we select the | 1345 // rect and oval types have rrect start indices that collapse to the same point.
Here we select the |
1252 // canonical point in these cases. | 1346 // canonical point in these cases. |
1253 unsigned canonicalize_rrect_start(int s, const SkRRect& rrect) { | 1347 unsigned canonicalize_rrect_start(int s, const SkRRect& rrect) { |
1254 switch (rrect.getType()) { | 1348 switch (rrect.getType()) { |
1255 case SkRRect::kRect_Type: | 1349 case SkRRect::kRect_Type: |
1256 return (s + 1) & 0b110; | 1350 return (s + 1) & 0b110; |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1528 SkPaint fill; | 1622 SkPaint fill; |
1529 SkPaint stroke; | 1623 SkPaint stroke; |
1530 stroke.setStyle(SkPaint::kStroke_Style); | 1624 stroke.setStyle(SkPaint::kStroke_Style); |
1531 stroke.setStrokeWidth(2.f); | 1625 stroke.setStrokeWidth(2.f); |
1532 SkPaint hairline; | 1626 SkPaint hairline; |
1533 hairline.setStyle(SkPaint::kStroke_Style); | 1627 hairline.setStyle(SkPaint::kStroke_Style); |
1534 hairline.setStrokeWidth(0.f); | 1628 hairline.setStrokeWidth(0.f); |
1535 SkPaint dash = stroke; | 1629 SkPaint dash = stroke; |
1536 dash.setPathEffect(make_dash()); | 1630 dash.setPathEffect(make_dash()); |
1537 | 1631 |
1538 TestCase fillAB(lineAB, fill, r); | 1632 TestCase fillAB(r, lineAB, fill); |
1539 TestCase fillEmpty(SkPath(), fill, r); | 1633 TestCase fillEmpty(r, SkPath(), fill); |
1540 fillAB.compare(r, fillEmpty, TestCase::kAllSame_ComparisonExpecation); | 1634 fillAB.compare(r, fillEmpty, TestCase::kAllSame_ComparisonExpecation); |
1541 REPORTER_ASSERT(r, !fillAB.baseShape().asLine(nullptr, nullptr)); | 1635 REPORTER_ASSERT(r, !fillAB.baseShape().asLine(nullptr, nullptr)); |
1542 | 1636 |
1543 TestCase strokeAB(lineAB, stroke, r); | 1637 TestCase strokeAB(r, lineAB, stroke); |
1544 TestCase strokeBA(lineBA, stroke, r); | 1638 TestCase strokeBA(r, lineBA, stroke); |
1545 TestCase strokeAC(lineAC, stroke, r); | 1639 TestCase strokeAC(r, lineAC, stroke); |
1546 | 1640 |
1547 TestCase hairlineAB(lineAB, hairline, r); | 1641 TestCase hairlineAB(r, lineAB, hairline); |
1548 TestCase hairlineBA(lineBA, hairline, r); | 1642 TestCase hairlineBA(r, lineBA, hairline); |
1549 TestCase hairlineAC(lineAC, hairline, r); | 1643 TestCase hairlineAC(r, lineAC, hairline); |
1550 | 1644 |
1551 TestCase dashAB(lineAB, dash, r); | 1645 TestCase dashAB(r, lineAB, dash); |
1552 TestCase dashBA(lineBA, dash, r); | 1646 TestCase dashBA(r, lineBA, dash); |
1553 TestCase dashAC(lineAC, dash, r); | 1647 TestCase dashAC(r, lineAC, dash); |
1554 | 1648 |
1555 strokeAB.compare(r, fillAB, TestCase::kAllDifferent_ComparisonExpecation); | 1649 strokeAB.compare(r, fillAB, TestCase::kAllDifferent_ComparisonExpecation); |
1556 | 1650 |
1557 strokeAB.compare(r, strokeBA, TestCase::kAllSame_ComparisonExpecation); | 1651 strokeAB.compare(r, strokeBA, TestCase::kAllSame_ComparisonExpecation); |
1558 strokeAB.compare(r, strokeAC, TestCase::kAllDifferent_ComparisonExpecation); | 1652 strokeAB.compare(r, strokeAC, TestCase::kAllDifferent_ComparisonExpecation); |
1559 | 1653 |
1560 hairlineAB.compare(r, hairlineBA, TestCase::kAllSame_ComparisonExpecation); | 1654 hairlineAB.compare(r, hairlineBA, TestCase::kAllSame_ComparisonExpecation); |
1561 hairlineAB.compare(r, hairlineAC, TestCase::kAllDifferent_ComparisonExpecati
on); | 1655 hairlineAB.compare(r, hairlineAC, TestCase::kAllDifferent_ComparisonExpecati
on); |
1562 | 1656 |
1563 dashAB.compare(r, dashBA, TestCase::kAllDifferent_ComparisonExpecation); | 1657 dashAB.compare(r, dashBA, TestCase::kAllDifferent_ComparisonExpecation); |
(...skipping 24 matching lines...) Expand all Loading... |
1588 REPORTER_ASSERT(r, strokeAB.baseShape().asLine(pts, &inverted) && !inverted
&& | 1682 REPORTER_ASSERT(r, strokeAB.baseShape().asLine(pts, &inverted) && !inverted
&& |
1589 pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]); | 1683 pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]); |
1590 REPORTER_ASSERT(r, hairlineAB.baseShape().asLine(pts, &inverted) && !inverte
d && | 1684 REPORTER_ASSERT(r, hairlineAB.baseShape().asLine(pts, &inverted) && !inverte
d && |
1591 pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]); | 1685 pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]); |
1592 REPORTER_ASSERT(r, dashAB.baseShape().asLine(pts, &inverted) && !inverted && | 1686 REPORTER_ASSERT(r, dashAB.baseShape().asLine(pts, &inverted) && !inverted && |
1593 pts[0] == kA && pts[1] == kB); | 1687 pts[0] == kA && pts[1] == kB); |
1594 REPORTER_ASSERT(r, dashBA.baseShape().asLine(pts, &inverted) && !inverted && | 1688 REPORTER_ASSERT(r, dashBA.baseShape().asLine(pts, &inverted) && !inverted && |
1595 pts[0] == kB && pts[1] == kA); | 1689 pts[0] == kB && pts[1] == kA); |
1596 | 1690 |
1597 | 1691 |
1598 TestCase strokeInvAB(invLineAB, stroke, r); | 1692 TestCase strokeInvAB(r, invLineAB, stroke); |
1599 TestCase hairlineInvAB(invLineAB, hairline, r); | 1693 TestCase hairlineInvAB(r, invLineAB, hairline); |
1600 TestCase dashInvAB(invLineAB, dash, r); | 1694 TestCase dashInvAB(r, invLineAB, dash); |
1601 strokeInvAB.compare(r, strokeAB, TestCase::kAllDifferent_ComparisonExpecatio
n); | 1695 strokeInvAB.compare(r, strokeAB, TestCase::kAllDifferent_ComparisonExpecatio
n); |
1602 hairlineInvAB.compare(r, hairlineAB, TestCase::kAllDifferent_ComparisonExpec
ation); | 1696 hairlineInvAB.compare(r, hairlineAB, TestCase::kAllDifferent_ComparisonExpec
ation); |
1603 // Dashing ignores inverse. | 1697 // Dashing ignores inverse. |
1604 dashInvAB.compare(r, dashAB, TestCase::kAllSame_ComparisonExpecation); | 1698 dashInvAB.compare(r, dashAB, TestCase::kAllSame_ComparisonExpecation); |
1605 | 1699 |
1606 REPORTER_ASSERT(r, strokeInvAB.baseShape().asLine(pts, &inverted) && inverte
d && | 1700 REPORTER_ASSERT(r, strokeInvAB.baseShape().asLine(pts, &inverted) && inverte
d && |
1607 pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]); | 1701 pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]); |
1608 REPORTER_ASSERT(r, hairlineInvAB.baseShape().asLine(pts, &inverted) && inver
ted && | 1702 REPORTER_ASSERT(r, hairlineInvAB.baseShape().asLine(pts, &inverted) && inver
ted && |
1609 pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]); | 1703 pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]); |
1610 // Dashing ignores inverse. | 1704 // Dashing ignores inverse. |
(...skipping 15 matching lines...) Expand all Loading... |
1626 SkPaint roundCap = buttCap; | 1720 SkPaint roundCap = buttCap; |
1627 roundCap.setStrokeCap(SkPaint::kRound_Cap); | 1721 roundCap.setStrokeCap(SkPaint::kRound_Cap); |
1628 | 1722 |
1629 // vertical | 1723 // vertical |
1630 SkPath linePath; | 1724 SkPath linePath; |
1631 linePath.moveTo(4, 4); | 1725 linePath.moveTo(4, 4); |
1632 linePath.lineTo(4, 5); | 1726 linePath.lineTo(4, 5); |
1633 | 1727 |
1634 SkPaint fill; | 1728 SkPaint fill; |
1635 | 1729 |
1636 TestCase(linePath, buttCap, r).compare(r, TestCase(SkRect::MakeLTRB(2, 4, 6,
5), fill, r), | 1730 TestCase(r, linePath, buttCap).compare(r, TestCase(r, SkRect::MakeLTRB(2, 4,
6, 5), fill), |
1637 TestCase::kAllSame_ComparisonExpecati
on); | 1731 TestCase::kAllSame_ComparisonExpecati
on); |
1638 | 1732 |
1639 TestCase(linePath, squareCap, r).compare(r, TestCase(SkRect::MakeLTRB(2, 2,
6, 7), fill, r), | 1733 TestCase(r, linePath, squareCap).compare(r, TestCase(r, SkRect::MakeLTRB(2,
2, 6, 7), fill), |
1640 TestCase::kAllSame_ComparisonExpeca
tion); | 1734 TestCase::kAllSame_ComparisonExpeca
tion); |
1641 | 1735 |
1642 TestCase(linePath, roundCap, r).compare(r, | 1736 TestCase(r, linePath, roundCap).compare(r, |
1643 TestCase(SkRRect::MakeRectXY(SkRect::MakeLTRB(2, 2, 6, 7), 2, 2), fill,
r), | 1737 TestCase(r, SkRRect::MakeRectXY(SkRect::MakeLTRB(2, 2, 6, 7), 2, 2), fil
l), |
1644 TestCase::kAllSame_ComparisonExpecation); | 1738 TestCase::kAllSame_ComparisonExpecation); |
1645 | 1739 |
1646 // horizontal | 1740 // horizontal |
1647 linePath.reset(); | 1741 linePath.reset(); |
1648 linePath.moveTo(4, 4); | 1742 linePath.moveTo(4, 4); |
1649 linePath.lineTo(5, 4); | 1743 linePath.lineTo(5, 4); |
1650 | 1744 |
1651 TestCase(linePath, buttCap, r).compare(r, TestCase(SkRect::MakeLTRB(4, 2, 5,
6), fill, r), | 1745 TestCase(r, linePath, buttCap).compare(r, TestCase(r, SkRect::MakeLTRB(4, 2,
5, 6), fill), |
1652 TestCase::kAllSame_ComparisonExpecati
on); | 1746 TestCase::kAllSame_ComparisonExpecati
on); |
1653 TestCase(linePath, squareCap, r).compare(r, TestCase(SkRect::MakeLTRB(2, 2,
7, 6), fill, r), | 1747 TestCase(r, linePath, squareCap).compare(r, TestCase(r, SkRect::MakeLTRB(2,
2, 7, 6), fill), |
1654 TestCase::kAllSame_ComparisonExpeca
tion); | 1748 TestCase::kAllSame_ComparisonExpeca
tion); |
1655 TestCase(linePath, roundCap, r).compare(r, | 1749 TestCase(r, linePath, roundCap).compare(r, |
1656 TestCase(SkRRect::MakeRectXY(SkRect::MakeLTRB(2, 2, 7, 6), 2, 2), fill,
r), | 1750 TestCase(r, SkRRect::MakeRectXY(SkRect::MakeLTRB(2, 2, 7, 6), 2, 2), fi
ll), |
1657 TestCase::kAllSame_ComparisonExpecation); | 1751 TestCase::kAllSame_ComparisonExpecation); |
1658 | 1752 |
1659 // point | 1753 // point |
1660 linePath.reset(); | 1754 linePath.reset(); |
1661 linePath.moveTo(4, 4); | 1755 linePath.moveTo(4, 4); |
1662 linePath.lineTo(4, 4); | 1756 linePath.lineTo(4, 4); |
1663 | 1757 |
1664 TestCase(linePath, buttCap, r).compare(r, TestCase(SkRect::MakeEmpty(), fill
, r), | 1758 TestCase(r, linePath, buttCap).compare(r, TestCase(r, SkRect::MakeEmpty(), f
ill), |
1665 TestCase::kAllSame_ComparisonExpecati
on); | 1759 TestCase::kAllSame_ComparisonExpecati
on); |
1666 TestCase(linePath, squareCap, r).compare(r, TestCase(SkRect::MakeLTRB(2, 2,
6, 6), fill, r), | 1760 TestCase(r, linePath, squareCap).compare(r, TestCase(r, SkRect::MakeLTRB(2,
2, 6, 6), fill), |
1667 TestCase::kAllSame_ComparisonExpeca
tion); | 1761 TestCase::kAllSame_ComparisonExpeca
tion); |
1668 TestCase(linePath, roundCap, r).compare(r, | 1762 TestCase(r, linePath, roundCap).compare(r, |
1669 TestCase(SkRRect::MakeRectXY(SkRect::MakeLTRB(2, 2, 6, 6), 2, 2), fill,
r), | 1763 TestCase(r, SkRRect::MakeRectXY(SkRect::MakeLTRB(2, 2, 6, 6), 2, 2), fil
l), |
1670 TestCase::kAllSame_ComparisonExpecation); | 1764 TestCase::kAllSame_ComparisonExpecation); |
1671 } | 1765 } |
1672 | 1766 |
1673 DEF_TEST(GrShape, reporter) { | 1767 DEF_TEST(GrShape, reporter) { |
| 1768 SkTArray<std::unique_ptr<Geo>> geos; |
| 1769 SkTArray<std::unique_ptr<RRectPathGeo>> rrectPathGeos; |
| 1770 |
1674 for (auto r : { SkRect::MakeWH(10, 20), | 1771 for (auto r : { SkRect::MakeWH(10, 20), |
1675 SkRect::MakeWH(-10, -20), | 1772 SkRect::MakeWH(-10, -20), |
1676 SkRect::MakeWH(-10, 20), | 1773 SkRect::MakeWH(-10, 20), |
1677 SkRect::MakeWH(10, -20)}) { | 1774 SkRect::MakeWH(10, -20)}) { |
1678 test_basic(reporter, r); | 1775 geos.emplace_back(new RectGeo(r)); |
1679 test_scale(reporter, r); | 1776 SkPath rectPath; |
1680 test_dash_fill(reporter, r); | 1777 rectPath.addRect(r); |
1681 test_null_dash(reporter, r); | 1778 geos.emplace_back(new RRectPathGeo(rectPath, r, RRectPathGeo::RRectForSt
roke::kYes, |
1682 // Test modifying various stroke params. | 1779 PathGeo::Invert::kNo)); |
1683 test_stroke_param<SkRect, SkScalar>( | 1780 geos.emplace_back(new RRectPathGeo(rectPath, r, RRectPathGeo::RRectForSt
roke::kYes, |
1684 reporter, r, | 1781 PathGeo::Invert::kYes)); |
1685 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, | 1782 rrectPathGeos.emplace_back(new RRectPathGeo(rectPath, r, RRectPathGeo::R
RectForStroke::kYes, |
1686 SkIntToScalar(2), SkIntToScalar(4)); | 1783 PathGeo::Invert::kNo)); |
1687 test_stroke_join(reporter, r); | |
1688 test_stroke_cap(reporter, r); | |
1689 test_miter_limit(reporter, r); | |
1690 test_path_effect_makes_rrect(reporter, r); | |
1691 test_unknown_path_effect(reporter, r); | |
1692 test_path_effect_makes_empty_shape(reporter, r); | |
1693 test_path_effect_fails(reporter, r); | |
1694 test_make_hairline_path_effect(reporter, r, true); | |
1695 GrShape shape(r); | |
1696 REPORTER_ASSERT(reporter, !shape.asLine(nullptr, nullptr)); | |
1697 } | 1784 } |
1698 | |
1699 for (auto rr : { SkRRect::MakeRect(SkRect::MakeWH(10, 10)), | 1785 for (auto rr : { SkRRect::MakeRect(SkRect::MakeWH(10, 10)), |
1700 SkRRect::MakeRectXY(SkRect::MakeWH(10, 10), 3, 4), | 1786 SkRRect::MakeRectXY(SkRect::MakeWH(10, 10), 3, 4), |
1701 SkRRect::MakeOval(SkRect::MakeWH(20, 20))}) { | 1787 SkRRect::MakeOval(SkRect::MakeWH(20, 20))}) { |
1702 test_basic(reporter, rr); | 1788 geos.emplace_back(new RRectGeo(rr)); |
1703 test_rrect(reporter, rr); | 1789 test_rrect(reporter, rr); |
1704 test_scale(reporter, rr); | 1790 SkPath rectPath; |
1705 test_dash_fill(reporter, rr); | 1791 rectPath.addRRect(rr); |
1706 test_null_dash(reporter, rr); | 1792 geos.emplace_back(new RRectPathGeo(rectPath, rr, RRectPathGeo::RRectForS
troke::kYes, |
1707 // Test modifying various stroke params. | 1793 PathGeo::Invert::kNo)); |
1708 test_stroke_param<SkRRect, SkScalar>( | 1794 geos.emplace_back(new RRectPathGeo(rectPath, rr, RRectPathGeo::RRectForS
troke::kYes, |
1709 reporter, rr, | 1795 PathGeo::Invert::kYes)); |
1710 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, | 1796 rrectPathGeos.emplace_back(new RRectPathGeo(rectPath, rr, |
1711 SkIntToScalar(2), SkIntToScalar(4)); | 1797 RRectPathGeo::RRectForStroke
::kYes, |
1712 test_stroke_join(reporter, rr); | 1798 PathGeo::Invert::kNo)); |
1713 test_stroke_cap(reporter, rr); | |
1714 test_miter_limit(reporter, rr); | |
1715 test_path_effect_makes_rrect(reporter, rr); | |
1716 test_unknown_path_effect(reporter, rr); | |
1717 test_path_effect_makes_empty_shape(reporter, rr); | |
1718 test_path_effect_fails(reporter, rr); | |
1719 test_make_hairline_path_effect(reporter, rr, true); | |
1720 GrShape shape(rr); | |
1721 REPORTER_ASSERT(reporter, !shape.asLine(nullptr, nullptr)); | |
1722 } | 1799 } |
1723 | 1800 |
1724 struct TestPath { | |
1725 TestPath(const SkPath& path, bool isRRectFill, bool isRRectStroke, bool
isLine, | |
1726 const SkRRect& rrect) | |
1727 : fPath(path) | |
1728 , fIsRRectForFill(isRRectFill) | |
1729 , fIsRRectForStroke(isRRectStroke) | |
1730 , fIsLine(isLine) | |
1731 , fRRect(rrect) {} | |
1732 SkPath fPath; | |
1733 bool fIsRRectForFill; | |
1734 bool fIsRRectForStroke; | |
1735 bool fIsLine; | |
1736 SkRRect fRRect; | |
1737 }; | |
1738 SkTArray<TestPath> paths; | |
1739 | |
1740 SkPath circlePath; | |
1741 circlePath.addCircle(10, 10, 10); | |
1742 paths.emplace_back(circlePath, true, true, false, SkRRect::MakeOval(SkRect::
MakeWH(20,20))); | |
1743 | |
1744 SkPath rectPath; | |
1745 rectPath.addRect(SkRect::MakeWH(10, 10)); | |
1746 paths.emplace_back(rectPath, true, true, false, SkRRect::MakeRect(SkRect::Ma
keWH(10, 10))); | |
1747 | |
1748 SkPath openRectPath; | 1801 SkPath openRectPath; |
1749 openRectPath.moveTo(0, 0); | 1802 openRectPath.moveTo(0, 0); |
1750 openRectPath.lineTo(10, 0); | 1803 openRectPath.lineTo(10, 0); |
1751 openRectPath.lineTo(10, 10); | 1804 openRectPath.lineTo(10, 10); |
1752 openRectPath.lineTo(0, 10); | 1805 openRectPath.lineTo(0, 10); |
1753 paths.emplace_back(openRectPath, true, false, false, SkRRect::MakeRect(SkRec
t::MakeWH(10, 10))); | 1806 geos.emplace_back(new RRectPathGeo(openRectPath, SkRect::MakeWH(10, 10), |
| 1807 RRectPathGeo::RRectForStroke::kNo, PathGe
o::Invert::kNo)); |
| 1808 geos.emplace_back(new RRectPathGeo(openRectPath, SkRect::MakeWH(10, 10), |
| 1809 RRectPathGeo::RRectForStroke::kNo, PathGe
o::Invert::kYes)); |
| 1810 rrectPathGeos.emplace_back(new RRectPathGeo(openRectPath, SkRect::MakeWH(10,
10), |
| 1811 RRectPathGeo::RRectForStroke::kN
o, |
| 1812 PathGeo::Invert::kNo)); |
1754 | 1813 |
1755 SkPath quadPath; | 1814 SkPath quadPath; |
1756 quadPath.quadTo(10, 10, 5, 8); | 1815 quadPath.quadTo(10, 10, 5, 8); |
1757 paths.emplace_back(quadPath, false, false, false, SkRRect()); | 1816 geos.emplace_back(new PathGeo(quadPath, PathGeo::Invert::kNo)); |
| 1817 geos.emplace_back(new PathGeo(quadPath, PathGeo::Invert::kYes)); |
1758 | 1818 |
1759 SkPath linePath; | 1819 SkPath linePath; |
1760 linePath.lineTo(10, 10); | 1820 linePath.lineTo(10, 10); |
1761 paths.emplace_back(linePath, false, false, true, SkRRect()); | 1821 geos.emplace_back(new PathGeo(linePath, PathGeo::Invert::kNo)); |
| 1822 geos.emplace_back(new PathGeo(linePath, PathGeo::Invert::kYes)); |
1762 | 1823 |
1763 // Horizontal and vertical paths become rrects when stroked. | 1824 // Horizontal and vertical paths become rrects when stroked. |
1764 SkPath vLinePath; | 1825 SkPath vLinePath; |
1765 vLinePath.lineTo(0, 10); | 1826 vLinePath.lineTo(0, 10); |
1766 paths.emplace_back(vLinePath, false, false, true, SkRRect()); | 1827 geos.emplace_back(new PathGeo(vLinePath, PathGeo::Invert::kNo)); |
| 1828 geos.emplace_back(new PathGeo(vLinePath, PathGeo::Invert::kYes)); |
1767 | 1829 |
1768 SkPath hLinePath; | 1830 SkPath hLinePath; |
1769 hLinePath.lineTo(10, 0); | 1831 hLinePath.lineTo(10, 0); |
1770 paths.emplace_back(hLinePath, false, false, true, SkRRect()); | 1832 geos.emplace_back(new PathGeo(hLinePath, PathGeo::Invert::kNo)); |
| 1833 geos.emplace_back(new PathGeo(hLinePath, PathGeo::Invert::kYes)); |
1771 | 1834 |
1772 for (auto testPath : paths) { | 1835 for (int i = 0; i < geos.count(); ++i) { |
1773 for (bool inverseFill : {false, true}) { | 1836 test_basic(reporter, *geos[i]); |
1774 if (inverseFill) { | 1837 test_scale(reporter, *geos[i]); |
1775 if (testPath.fPath.getFillType() == SkPath::kEvenOdd_FillType) { | 1838 test_dash_fill(reporter, *geos[i]); |
1776 testPath.fPath.setFillType(SkPath::kInverseEvenOdd_FillType)
; | 1839 test_null_dash(reporter, *geos[i]); |
1777 } else { | 1840 // Test modifying various stroke params. |
1778 SkASSERT(testPath.fPath.getFillType() == SkPath::kWinding_Fi
llType); | 1841 test_stroke_param<SkScalar>( |
1779 testPath.fPath.setFillType(SkPath::kInverseWinding_FillType)
; | 1842 reporter, *geos[i], |
1780 } | |
1781 } | |
1782 const SkPath& path = testPath.fPath; | |
1783 test_basic(reporter, path); | |
1784 test_null_dash(reporter, path); | |
1785 test_path_effect_makes_rrect(reporter, path); | |
1786 test_scale(reporter, path); | |
1787 // This test uses a stroking paint, hence use of fIsRRectForStroke | |
1788 test_volatile_path(reporter, path, testPath.fIsRRectForStroke || tes
tPath.fIsLine); | |
1789 test_dash_fill(reporter, path); | |
1790 // Test modifying various stroke params. | |
1791 test_stroke_param<SkPath, SkScalar>( | |
1792 reporter, path, | |
1793 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, | 1843 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, |
1794 SkIntToScalar(2), SkIntToScalar(4)); | 1844 SkIntToScalar(2), SkIntToScalar(4)); |
1795 test_stroke_join(reporter, path); | 1845 test_stroke_join(reporter, *geos[i]); |
1796 test_stroke_cap(reporter, path); | 1846 test_stroke_cap(reporter, *geos[i]); |
1797 test_miter_limit(reporter, path); | 1847 test_miter_limit(reporter, *geos[i]); |
1798 test_unknown_path_effect(reporter, path); | 1848 test_path_effect_makes_rrect(reporter, *geos[i]); |
1799 test_path_effect_makes_empty_shape(reporter, path); | 1849 test_unknown_path_effect(reporter, *geos[i]); |
1800 test_path_effect_fails(reporter, path); | 1850 test_path_effect_makes_empty_shape(reporter, *geos[i]); |
1801 test_make_hairline_path_effect(reporter, path, testPath.fIsRRectForS
troke || | 1851 test_path_effect_fails(reporter, *geos[i]); |
1802 testPath.fIsLine); | 1852 test_make_hairline_path_effect(reporter, *geos[i]); |
1803 } | 1853 test_volatile_path(reporter, *geos[i]); |
1804 } | 1854 } |
1805 | 1855 |
1806 for (auto testPath : paths) { | 1856 for (int i = 0; i < rrectPathGeos.count(); ++i) { |
1807 const SkPath& path = testPath.fPath; | 1857 const RRectPathGeo& rrgeo = *rrectPathGeos[i]; |
1808 | |
1809 SkPaint fillPaint; | 1858 SkPaint fillPaint; |
1810 TestCase fillPathCase(path, fillPaint, reporter); | 1859 TestCase fillPathCase(reporter, rrgeo.path(), fillPaint); |
1811 SkRRect rrect; | 1860 SkRRect rrect; |
1812 REPORTER_ASSERT(reporter, testPath.fIsRRectForFill == | 1861 REPORTER_ASSERT(reporter, rrgeo.isNonPath(fillPaint) == |
1813 fillPathCase.baseShape().asRRect(&rrect, nullp
tr, nullptr, | 1862 fillPathCase.baseShape().asRRect(&rrect, nullp
tr, nullptr, |
1814 nullptr)); | 1863 nullptr)); |
1815 if (testPath.fIsRRectForFill) { | 1864 if (rrgeo.isNonPath(fillPaint)) { |
1816 TestCase fillPathCase2(testPath.fPath, fillPaint, reporter); | 1865 TestCase fillPathCase2(reporter, rrgeo.path(), fillPaint); |
1817 REPORTER_ASSERT(reporter, rrect == testPath.fRRect); | 1866 REPORTER_ASSERT(reporter, rrect == rrgeo.rrect()); |
1818 TestCase fillRRectCase(rrect, fillPaint, reporter); | 1867 TestCase fillRRectCase(reporter, rrect, fillPaint); |
1819 fillPathCase2.compare(reporter, fillRRectCase, | 1868 fillPathCase2.compare(reporter, fillRRectCase, |
1820 TestCase::kAllSame_ComparisonExpecation); | 1869 TestCase::kAllSame_ComparisonExpecation); |
1821 } | 1870 } |
1822 SkPaint strokePaint; | 1871 SkPaint strokePaint; |
1823 strokePaint.setStrokeWidth(3.f); | 1872 strokePaint.setStrokeWidth(3.f); |
1824 strokePaint.setStyle(SkPaint::kStroke_Style); | 1873 strokePaint.setStyle(SkPaint::kStroke_Style); |
1825 TestCase strokePathCase(path, strokePaint, reporter); | 1874 TestCase strokePathCase(reporter, rrgeo.path(), strokePaint); |
1826 if (testPath.fIsRRectForStroke) { | 1875 if (rrgeo.isNonPath(strokePaint)) { |
1827 REPORTER_ASSERT(reporter, strokePathCase.baseShape().asRRect(&rrect,
nullptr, nullptr, | 1876 REPORTER_ASSERT(reporter, strokePathCase.baseShape().asRRect(&rrect,
nullptr, nullptr, |
1828 nullptr
)); | 1877 nullptr
)); |
1829 } | 1878 REPORTER_ASSERT(reporter, rrect == rrgeo.rrect()); |
1830 | 1879 TestCase strokeRRectCase(reporter, rrect, strokePaint); |
1831 if (testPath.fIsRRectForStroke) { | |
1832 REPORTER_ASSERT(reporter, rrect == testPath.fRRect); | |
1833 TestCase strokeRRectCase(rrect, strokePaint, reporter); | |
1834 strokePathCase.compare(reporter, strokeRRectCase, | 1880 strokePathCase.compare(reporter, strokeRRectCase, |
1835 TestCase::kAllSame_ComparisonExpecation); | 1881 TestCase::kAllSame_ComparisonExpecation); |
1836 } | 1882 } |
1837 } | 1883 } |
1838 | 1884 |
1839 // Test a volatile empty path. | 1885 // Test a volatile empty path. |
1840 test_volatile_path(reporter, SkPath(), true); | 1886 test_volatile_path(reporter, PathGeo(SkPath(), PathGeo::Invert::kNo)); |
1841 | 1887 |
1842 test_empty_shape(reporter); | 1888 test_empty_shape(reporter); |
1843 | 1889 |
1844 test_lines(reporter); | 1890 test_lines(reporter); |
1845 | 1891 |
1846 test_stroked_lines(reporter); | 1892 test_stroked_lines(reporter); |
1847 } | 1893 } |
1848 | 1894 |
1849 #endif | 1895 #endif |
OLD | NEW |