| 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 |