| 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 | 75 |
| 76 namespace { | 76 namespace { |
| 77 class TestCase { | 77 class TestCase { |
| 78 public: | 78 public: |
| 79 template <typename GEO> | 79 template <typename GEO> |
| 80 TestCase(const GEO& geo, const SkPaint& paint, skiatest::Reporter* r, | 80 TestCase(const GEO& geo, const SkPaint& paint, skiatest::Reporter* r, |
| 81 SkScalar scale = SK_Scalar1) : fBase(geo, paint) { | 81 SkScalar scale = SK_Scalar1) : fBase(geo, paint) { |
| 82 this->init(r, scale); | 82 this->init(r, scale); |
| 83 } | 83 } |
| 84 | 84 |
| 85 TestCase(const GrShape& shape, skiatest::Reporter* r, SkScalar scale = SK_Sc
alar1) |
| 86 : fBase(shape) { |
| 87 this->init(r, scale); |
| 88 } |
| 89 |
| 85 struct SelfExpectations { | 90 struct SelfExpectations { |
| 86 bool fPEHasEffect; | 91 bool fPEHasEffect; |
| 87 bool fPEHasValidKey; | 92 bool fPEHasValidKey; |
| 88 bool fStrokeApplies; | 93 bool fStrokeApplies; |
| 89 }; | 94 }; |
| 90 | 95 |
| 91 void testExpectations(skiatest::Reporter* reporter, SelfExpectations expecta
tions) const; | 96 void testExpectations(skiatest::Reporter* reporter, SelfExpectations expecta
tions) const; |
| 92 | 97 |
| 93 enum ComparisonExpecation { | 98 enum ComparisonExpecation { |
| 94 kAllDifferent_ComparisonExpecation, | 99 kAllDifferent_ComparisonExpecation, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 114 SkPath path; | 119 SkPath path; |
| 115 shape.asPath(&path); | 120 shape.asPath(&path); |
| 116 // If the bounds are empty, the path ought to be as well. | 121 // If the bounds are empty, the path ought to be as well. |
| 117 if (bounds.isEmpty()) { | 122 if (bounds.isEmpty()) { |
| 118 REPORTER_ASSERT(r, path.isEmpty()); | 123 REPORTER_ASSERT(r, path.isEmpty()); |
| 119 return; | 124 return; |
| 120 } | 125 } |
| 121 if (path.isEmpty()) { | 126 if (path.isEmpty()) { |
| 122 return; | 127 return; |
| 123 } | 128 } |
| 124 REPORTER_ASSERT(r, test_bounds_by_rasterizing(path, bounds)); | 129 // The bounds API explicitly calls out that it does not consider inverse
ness. |
| 130 SkPath p = path; |
| 131 p.setFillType(SkPath::ConvertToNonInverseFillType(path.getFillType())); |
| 132 REPORTER_ASSERT(r, test_bounds_by_rasterizing(p, bounds)); |
| 125 } | 133 } |
| 126 | 134 |
| 127 void init(skiatest::Reporter* r, SkScalar scale) { | 135 void init(skiatest::Reporter* r, SkScalar scale) { |
| 128 fAppliedPE = fBase.applyStyle(GrStyle::Apply::kPathEffectOnly,
scale); | 136 fAppliedPE = fBase.applyStyle(GrStyle::Apply::kPathEffectOnly,
scale); |
| 129 fAppliedPEThenStroke = fAppliedPE.applyStyle(GrStyle::Apply::kPathEffect
AndStrokeRec, | 137 fAppliedPEThenStroke = fAppliedPE.applyStyle(GrStyle::Apply::kPathEffect
AndStrokeRec, |
| 130 scale); | 138 scale); |
| 131 fAppliedFull = fBase.applyStyle(GrStyle::Apply::kPathEffectAndSt
rokeRec, scale); | 139 fAppliedFull = fBase.applyStyle(GrStyle::Apply::kPathEffectAndSt
rokeRec, scale); |
| 132 | 140 |
| 133 make_key(&fBaseKey, fBase); | 141 make_key(&fBaseKey, fBase); |
| 134 make_key(&fAppliedPEKey, fAppliedPE); | 142 make_key(&fAppliedPEKey, fAppliedPE); |
| 135 make_key(&fAppliedPEThenStrokeKey, fAppliedPEThenStroke); | 143 make_key(&fAppliedPEThenStrokeKey, fAppliedPEThenStroke); |
| 136 make_key(&fAppliedFullKey, fAppliedFull); | 144 make_key(&fAppliedFullKey, fAppliedFull); |
| 137 | 145 |
| 138 // Applying the path effect and then the stroke should always be the sam
e as applying | 146 // Applying the path effect and then the stroke should always be the sam
e as applying |
| 139 // both in one go. | 147 // both in one go. |
| 140 REPORTER_ASSERT(r, fAppliedPEThenStrokeKey == fAppliedFullKey); | 148 REPORTER_ASSERT(r, fAppliedPEThenStrokeKey == fAppliedFullKey); |
| 141 SkPath a, b; | 149 SkPath a, b; |
| 142 fAppliedPEThenStroke.asPath(&a); | 150 fAppliedPEThenStroke.asPath(&a); |
| 143 fAppliedFull.asPath(&b); | 151 fAppliedFull.asPath(&b); |
| 144 // If the output of the path effect is a rrect then it is possible for a
and b to be | 152 // If the output of the path effect is a rrect then it is possible for a
and b to be |
| 145 // different paths that fill identically. The reason is that fAppliedFul
l will do this: | 153 // different paths that fill identically. The reason is that fAppliedFul
l will do this: |
| 146 // base -> apply path effect -> rrect_as_path -> stroke -> stroked_rrect
_as_path | 154 // base -> apply path effect -> rrect_as_path -> stroke -> stroked_rrect
_as_path |
| 147 // fAppliedPEThenStroke will have converted the rrect_as_path back to a
rrect. However, | 155 // fAppliedPEThenStroke will have converted the rrect_as_path back to a
rrect. However, |
| 148 // now that there is no longer a path effect, the direction and starting
index get | 156 // now that there is no longer a path effect, the direction and starting
index get |
| 149 // canonicalized before the stroke. | 157 // canonicalized before the stroke. |
| 150 if (fAppliedPE.asRRect(nullptr, nullptr, nullptr)) { | 158 if (fAppliedPE.asRRect(nullptr, nullptr, nullptr, nullptr)) { |
| 151 REPORTER_ASSERT(r, paths_fill_same(a, b)); | 159 REPORTER_ASSERT(r, paths_fill_same(a, b)); |
| 152 } else { | 160 } else { |
| 153 REPORTER_ASSERT(r, a == b); | 161 REPORTER_ASSERT(r, a == b); |
| 154 } | 162 } |
| 155 REPORTER_ASSERT(r, fAppliedFull.isEmpty() == fAppliedPEThenStroke.isEmpt
y()); | 163 REPORTER_ASSERT(r, fAppliedFull.isEmpty() == fAppliedPEThenStroke.isEmpt
y()); |
| 156 | 164 |
| 157 SkPath path; | 165 SkPath path; |
| 158 fBase.asPath(&path); | 166 fBase.asPath(&path); |
| 159 REPORTER_ASSERT(r, path.isEmpty() == fBase.isEmpty()); | 167 REPORTER_ASSERT(r, path.isEmpty() == fBase.isEmpty()); |
| 160 REPORTER_ASSERT(r, path.getSegmentMasks() == fBase.segmentMask()); | 168 REPORTER_ASSERT(r, path.getSegmentMasks() == fBase.segmentMask()); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 254 // but one has a path effect in its style and the other doesn't then asPath(
) and the unstyled | 262 // but one has a path effect in its style and the other doesn't then asPath(
) and the unstyled |
| 255 // key will differ. GrShape will have canonicalized the direction and start
point for the shape | 263 // key will differ. GrShape will have canonicalized the direction and start
point for the shape |
| 256 // without the path effect. If *both* have path effects then they should hav
e both preserved | 264 // without the path effect. If *both* have path effects then they should hav
e both preserved |
| 257 // the direction and starting point. | 265 // the direction and starting point. |
| 258 | 266 |
| 259 // The asRRect() output params are all initialized just to silence compiler
warnings about | 267 // The asRRect() output params are all initialized just to silence compiler
warnings about |
| 260 // uninitialized variables. | 268 // uninitialized variables. |
| 261 SkRRect rrectA = SkRRect::MakeEmpty(), rrectB = SkRRect::MakeEmpty(); | 269 SkRRect rrectA = SkRRect::MakeEmpty(), rrectB = SkRRect::MakeEmpty(); |
| 262 SkPath::Direction dirA = SkPath::kCW_Direction, dirB = SkPath::kCW_Direction
; | 270 SkPath::Direction dirA = SkPath::kCW_Direction, dirB = SkPath::kCW_Direction
; |
| 263 unsigned startA = ~0U, startB = ~0U; | 271 unsigned startA = ~0U, startB = ~0U; |
| 272 bool invertedA = true, invertedB = true; |
| 264 | 273 |
| 265 bool aIsRRect = a.asRRect(&rrectA, &dirA, &startA); | 274 bool aIsRRect = a.asRRect(&rrectA, &dirA, &startA, &invertedA); |
| 266 bool bIsRRect = b.asRRect(&rrectB, &dirB, &startB); | 275 bool bIsRRect = b.asRRect(&rrectB, &dirB, &startB, &invertedB); |
| 267 bool aHasPE = a.style().hasPathEffect(); | 276 bool aHasPE = a.style().hasPathEffect(); |
| 268 bool bHasPE = b.style().hasPathEffect(); | 277 bool bHasPE = b.style().hasPathEffect(); |
| 269 bool allowSameRRectButDiffStartAndDir = (aIsRRect && bIsRRect) && (aHasPE !=
bHasPE); | 278 bool allowSameRRectButDiffStartAndDir = (aIsRRect && bIsRRect) && (aHasPE !=
bHasPE); |
| 279 |
| 270 SkPath pathA, pathB; | 280 SkPath pathA, pathB; |
| 271 a.asPath(&pathA); | 281 a.asPath(&pathA); |
| 272 b.asPath(&pathB); | 282 b.asPath(&pathB); |
| 283 |
| 284 // Having a fill style or non-dash path effect can prevent 'a' but not 'b' f
rom turning an |
| 285 // inverse fill type into a non-inverse fill type. |
| 286 bool ignoreInversenessDifference = false; |
| 287 if (pathA.isInverseFillType() != pathB.isInverseFillType()) { |
| 288 const GrShape* s1 = pathA.isInverseFillType() ? &a : &b; |
| 289 const GrShape* s2 = pathA.isInverseFillType() ? &b : &a; |
| 290 SkStrokeRec::Style style1 = s1->style().strokeRec().getStyle(); |
| 291 SkStrokeRec::Style style2 = s2->style().strokeRec().getStyle(); |
| 292 bool canDropInverse1 = !s1->style().hasNonDashPathEffect() && |
| 293 (SkStrokeRec::kStroke_Style == style1 || |
| 294 SkStrokeRec::kHairline_Style == style1); |
| 295 bool canDropInverse2 = !s2->style().hasNonDashPathEffect() && |
| 296 (SkStrokeRec::kStroke_Style == style2 || |
| 297 SkStrokeRec::kHairline_Style == style2); |
| 298 ignoreInversenessDifference = !canDropInverse1 && canDropInverse2; |
| 299 } |
| 300 |
| 273 if (allowSameRRectButDiffStartAndDir) { | 301 if (allowSameRRectButDiffStartAndDir) { |
| 274 REPORTER_ASSERT(r, rrectA == rrectB); | 302 REPORTER_ASSERT(r, rrectA == rrectB); |
| 275 REPORTER_ASSERT(r, paths_fill_same(pathA, pathB)); | 303 REPORTER_ASSERT(r, paths_fill_same(pathA, pathB)); |
| 304 REPORTER_ASSERT(r, ignoreInversenessDifference || invertedA == invertedB
); |
| 276 } else { | 305 } else { |
| 277 REPORTER_ASSERT(r, pathA == pathB); | 306 SkPath pA = pathA; |
| 278 REPORTER_ASSERT(r, keyA == keyB); | 307 SkPath pB = pathB; |
| 308 if (ignoreInversenessDifference) { |
| 309 pA.setFillType(SkPath::ConvertToNonInverseFillType(pathA.getFillType
())); |
| 310 pB.setFillType(SkPath::ConvertToNonInverseFillType(pathB.getFillType
())); |
| 311 REPORTER_ASSERT(r, keyA != keyB); |
| 312 } else { |
| 313 REPORTER_ASSERT(r, keyA == keyB); |
| 314 } |
| 315 REPORTER_ASSERT(r, pA == pB); |
| 279 REPORTER_ASSERT(r, aIsRRect == bIsRRect); | 316 REPORTER_ASSERT(r, aIsRRect == bIsRRect); |
| 280 if (aIsRRect) { | 317 if (aIsRRect) { |
| 281 REPORTER_ASSERT(r, rrectA == rrectB); | 318 REPORTER_ASSERT(r, rrectA == rrectB); |
| 282 REPORTER_ASSERT(r, dirA == dirB); | 319 REPORTER_ASSERT(r, dirA == dirB); |
| 283 REPORTER_ASSERT(r, startA == startB); | 320 REPORTER_ASSERT(r, startA == startB); |
| 321 REPORTER_ASSERT(r, ignoreInversenessDifference || invertedA == inver
tedB); |
| 284 } | 322 } |
| 285 } | 323 } |
| 286 REPORTER_ASSERT(r, a.isEmpty() == b.isEmpty()); | 324 REPORTER_ASSERT(r, a.isEmpty() == b.isEmpty()); |
| 287 REPORTER_ASSERT(r, a.knownToBeClosed() == b.knownToBeClosed()); | 325 REPORTER_ASSERT(r, a.knownToBeClosed() == b.knownToBeClosed()); |
| 288 REPORTER_ASSERT(r, a.bounds() == b.bounds()); | 326 REPORTER_ASSERT(r, a.bounds() == b.bounds()); |
| 289 REPORTER_ASSERT(r, a.segmentMask() == b.segmentMask()); | 327 REPORTER_ASSERT(r, a.segmentMask() == b.segmentMask()); |
| 290 } | 328 } |
| 291 | 329 |
| 292 void TestCase::compare(skiatest::Reporter* r, const TestCase& that, | 330 void TestCase::compare(skiatest::Reporter* r, const TestCase& that, |
| 293 ComparisonExpecation expectation) const { | 331 ComparisonExpecation expectation) const { |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 TestCase strokeAndFillCase1(geo, strokeAndFill, reporter, kS1); | 489 TestCase strokeAndFillCase1(geo, strokeAndFill, reporter, kS1); |
| 452 TestCase strokeAndFillCase2(geo, strokeAndFill, reporter, kS2); | 490 TestCase strokeAndFillCase2(geo, strokeAndFill, reporter, kS2); |
| 453 SkPaint strokeAndFillDash = strokeDash; | 491 SkPaint strokeAndFillDash = strokeDash; |
| 454 strokeAndFillDash.setStyle(SkPaint::kStrokeAndFill_Style); | 492 strokeAndFillDash.setStyle(SkPaint::kStrokeAndFill_Style); |
| 455 // Dash is ignored for stroke and fill | 493 // Dash is ignored for stroke and fill |
| 456 TestCase strokeAndFillDashCase1(geo, strokeAndFillDash, reporter, kS1); | 494 TestCase strokeAndFillDashCase1(geo, strokeAndFillDash, reporter, kS1); |
| 457 TestCase strokeAndFillDashCase2(geo, strokeAndFillDash, reporter, kS2); | 495 TestCase strokeAndFillDashCase2(geo, strokeAndFillDash, reporter, kS2); |
| 458 // Scale affects the stroke. Though, this can wind up creating a rect when t
he input is a rect. | 496 // Scale affects the stroke. Though, this can wind up creating a rect when t
he input is a rect. |
| 459 // In that case we wind up with a pure geometry key and the geometries are t
he same. | 497 // In that case we wind up with a pure geometry key and the geometries are t
he same. |
| 460 SkRRect rrect; | 498 SkRRect rrect; |
| 461 if (strokeAndFillCase1.appliedFullStyleShape().asRRect(&rrect, nullptr, null
ptr)) { | 499 if (strokeAndFillCase1.appliedFullStyleShape().asRRect(&rrect, nullptr, null
ptr, nullptr)) { |
| 462 // We currently only expect to get here in the rect->rect case. | 500 // We currently only expect to get here in the rect->rect case. |
| 463 REPORTER_ASSERT(reporter, rrect.isRect()); | 501 REPORTER_ASSERT(reporter, rrect.isRect()); |
| 464 REPORTER_ASSERT(reporter, | 502 REPORTER_ASSERT(reporter, |
| 465 strokeAndFillCase1.baseShape().asRRect(&rrect, nullptr,
nullptr) && | 503 strokeAndFillCase1.baseShape().asRRect(&rrect, nullptr,
nullptr, nullptr) && |
| 466 rrect.isRect()); | 504 rrect.isRect()); |
| 467 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, | 505 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, |
| 468 TestCase::kAllSame_ComparisonExpecation); | 506 TestCase::kAllSame_ComparisonExpecation); |
| 469 } else { | 507 } else { |
| 470 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, | 508 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, |
| 471 TestCase::kSameUpToStroke_ComparisonExpecatio
n); | 509 TestCase::kSameUpToStroke_ComparisonExpecatio
n); |
| 472 strokeAndFillDashCase1.compare(reporter, strokeAndFillDashCase2, | 510 strokeAndFillDashCase1.compare(reporter, strokeAndFillDashCase2, |
| 473 TestCase::kSameUpToStroke_ComparisonExpec
ation); | 511 TestCase::kSameUpToStroke_ComparisonExpec
ation); |
| 474 } | 512 } |
| 475 strokeAndFillDashCase1.compare(reporter, strokeAndFillCase1, | 513 strokeAndFillDashCase1.compare(reporter, strokeAndFillCase1, |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 680 TestCase::kSameUpToStroke_ComparisonExpecation); | 718 TestCase::kSameUpToStroke_ComparisonExpecation); |
| 681 | 719 |
| 682 TestCase rrectFillCase(RRectPathEffect::RRect(), fill, reporter); | 720 TestCase rrectFillCase(RRectPathEffect::RRect(), fill, reporter); |
| 683 SkPaint stroke = peStroke; | 721 SkPaint stroke = peStroke; |
| 684 stroke.setPathEffect(nullptr); | 722 stroke.setPathEffect(nullptr); |
| 685 TestCase rrectStrokeCase(RRectPathEffect::RRect(), stroke, reporter); | 723 TestCase rrectStrokeCase(RRectPathEffect::RRect(), stroke, reporter); |
| 686 | 724 |
| 687 SkRRect rrect; | 725 SkRRect rrect; |
| 688 // Applying the path effect should make a SkRRect shape. There is no further
stroking in the | 726 // Applying the path effect should make a SkRRect shape. There is no further
stroking in the |
| 689 // geoPECase, so the full style should be the same as just the PE. | 727 // geoPECase, so the full style should be the same as just the PE. |
| 690 REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectShape().asRRect(&rrect,
nullptr, nullptr)); | 728 REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectShape().asRRect(&rrect,
nullptr, nullptr, |
| 729 nullptr
)); |
| 691 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); | 730 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); |
| 692 REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectKey() == rrectFillCase.
baseKey()); | 731 REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectKey() == rrectFillCase.
baseKey()); |
| 693 | 732 |
| 694 REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleShape().asRRect(&rrect,
nullptr, nullptr)); | 733 REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleShape().asRRect(&rrect,
nullptr, nullptr, |
| 734 nullptr)
); |
| 695 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); | 735 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); |
| 696 REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleKey() == rrectFillCase.b
aseKey()); | 736 REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleKey() == rrectFillCase.b
aseKey()); |
| 697 | 737 |
| 698 // In the PE+stroke case applying the full style should be the same as just
stroking the rrect. | 738 // In the PE+stroke case applying the full style should be the same as just
stroking the rrect. |
| 699 REPORTER_ASSERT(reporter, | 739 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectShape().asRRect(&
rrect, nullptr, |
| 700 geoPEStrokeCase.appliedPathEffectShape().asRRect(&rrect, nul
lptr, nullptr)); | 740 n
ullptr, nullptr)); |
| 701 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); | 741 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); |
| 702 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectKey() == rrectFil
lCase.baseKey()); | 742 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectKey() == rrectFil
lCase.baseKey()); |
| 703 | 743 |
| 704 REPORTER_ASSERT(reporter, | 744 REPORTER_ASSERT(reporter, !geoPEStrokeCase.appliedFullStyleShape().asRRect(&
rrect, nullptr, |
| 705 !geoPEStrokeCase.appliedFullStyleShape().asRRect(&rrect, nul
lptr, nullptr)); | 745 n
ullptr, nullptr)); |
| 706 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleKey() == | 746 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleKey() == |
| 707 rrectStrokeCase.appliedFullStyleKey()); | 747 rrectStrokeCase.appliedFullStyleKey()); |
| 708 } | 748 } |
| 709 | 749 |
| 710 template <typename GEO> | 750 template <typename GEO> |
| 711 void test_unknown_path_effect(skiatest::Reporter* reporter, const GEO& geo) { | 751 void test_unknown_path_effect(skiatest::Reporter* reporter, const GEO& geo) { |
| 712 /** | 752 /** |
| 713 * This path effect just adds two lineTos to the input path. | 753 * This path effect just adds two lineTos to the input path. |
| 714 */ | 754 */ |
| 715 class AddLineTosPathEffect : SkPathEffect { | 755 class AddLineTosPathEffect : SkPathEffect { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 754 * This path effect just changes the stroke rec to hairline. | 794 * This path effect just changes the stroke rec to hairline. |
| 755 */ | 795 */ |
| 756 class MakeHairlinePathEffect : SkPathEffect { | 796 class MakeHairlinePathEffect : SkPathEffect { |
| 757 public: | 797 public: |
| 758 bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* strokeRec, | 798 bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* strokeRec, |
| 759 const SkRect* cullR) const override { | 799 const SkRect* cullR) const override { |
| 760 *dst = src; | 800 *dst = src; |
| 761 strokeRec->setHairlineStyle(); | 801 strokeRec->setHairlineStyle(); |
| 762 return true; | 802 return true; |
| 763 } | 803 } |
| 764 void computeFastBounds(SkRect* dst, const SkRect& src) const override {
*dst = src; } | 804 void computeFastBounds(SkRect* dst, const SkRect& src) const override {
*dst = src; } |
| 765 static sk_sp<SkPathEffect> Make() { | 805 static sk_sp<SkPathEffect> Make() { |
| 766 return sk_sp<SkPathEffect>(new MakeHairlinePathEffect); | 806 return sk_sp<SkPathEffect>(new MakeHairlinePathEffect); |
| 767 } | 807 } |
| 768 Factory getFactory() const override { return nullptr; } | 808 Factory getFactory() const override { return nullptr; } |
| 769 void toString(SkString*) const override {} | 809 void toString(SkString*) const override {} |
| 770 private: | 810 private: |
| 771 MakeHairlinePathEffect() {} | 811 MakeHairlinePathEffect() {} |
| 772 }; | 812 }; |
| 773 | 813 |
| 774 SkPaint fill; | 814 SkPaint fill; |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 981 dashAndStrokeEmptyRRectCase.compare(reporter, fillEmptyCase, | 1021 dashAndStrokeEmptyRRectCase.compare(reporter, fillEmptyCase, |
| 982 TestCase::kAllSame_ComparisonExpecation)
; | 1022 TestCase::kAllSame_ComparisonExpecation)
; |
| 983 | 1023 |
| 984 // Same for a rect. | 1024 // Same for a rect. |
| 985 SkRect emptyRect = SkRect::MakeEmpty(); | 1025 SkRect emptyRect = SkRect::MakeEmpty(); |
| 986 TestCase dashAndStrokeEmptyRectCase(emptyRect, dashAndStroke, reporter); | 1026 TestCase dashAndStrokeEmptyRectCase(emptyRect, dashAndStroke, reporter); |
| 987 dashAndStrokeEmptyRectCase.compare(reporter, fillEmptyCase, | 1027 dashAndStrokeEmptyRectCase.compare(reporter, fillEmptyCase, |
| 988 TestCase::kAllSame_ComparisonExpecation); | 1028 TestCase::kAllSame_ComparisonExpecation); |
| 989 } | 1029 } |
| 990 | 1030 |
| 1031 // rect and oval types have rrect start indices that collapse to the same point.
Here we select the |
| 1032 // canonical point in these cases. |
| 1033 unsigned canonicalize_rrect_start(int s, const SkRRect& rrect) { |
| 1034 switch (rrect.getType()) { |
| 1035 case SkRRect::kRect_Type: |
| 1036 return (s + 1) & 0b110; |
| 1037 case SkRRect::kOval_Type: |
| 1038 return s & 0b110; |
| 1039 default: |
| 1040 return s; |
| 1041 } |
| 1042 } |
| 1043 |
| 1044 void test_rrect(skiatest::Reporter* r, const SkRRect& rrect) { |
| 1045 enum { |
| 1046 kFill, |
| 1047 kStroke, |
| 1048 kHairline, |
| 1049 kStrokeAndFill |
| 1050 }; |
| 1051 |
| 1052 // SkStrokeRec has no default cons., so init with kFill before calling the s
etters below. |
| 1053 SkStrokeRec strokeRecs[4] { SkStrokeRec::kFill_InitStyle, SkStrokeRec::kFill
_InitStyle, |
| 1054 SkStrokeRec::kFill_InitStyle, SkStrokeRec::kFill
_InitStyle}; |
| 1055 strokeRecs[kFill].setFillStyle(); |
| 1056 strokeRecs[kStroke].setStrokeStyle(2.f); |
| 1057 strokeRecs[kHairline].setHairlineStyle(); |
| 1058 strokeRecs[kStrokeAndFill].setStrokeStyle(3.f, true); |
| 1059 sk_sp<SkPathEffect> dashEffect = make_dash(); |
| 1060 |
| 1061 GrShape shapes[2 /* inverted */] |
| 1062 [2 /* direction */] |
| 1063 [8 /* start index */] |
| 1064 [SK_ARRAY_COUNT(strokeRecs)] |
| 1065 [2 /* dash */]; |
| 1066 for (int inverted = 0; inverted < 2; ++inverted) { |
| 1067 for (int ccw = 0; ccw < 2; ++ccw) { |
| 1068 for (unsigned s = 0; s < 8; ++s) { |
| 1069 for (size_t style = 0; style < SK_ARRAY_COUNT(strokeRecs); ++sty
le) { |
| 1070 for (int dash = 0; dash < 2; ++dash) { |
| 1071 SkPath::Direction dir = ccw ? SkPath::kCCW_Direction |
| 1072 : SkPath::kCW_Direction; |
| 1073 SkPathEffect* pe = dash ? dashEffect.get() : nullptr; |
| 1074 shapes[inverted][ccw][s][style][dash] = |
| 1075 GrShape(rrect, dir, s, SkToBool(inverted), |
| 1076 GrStyle(strokeRecs[style], pe)); |
| 1077 } |
| 1078 } |
| 1079 } |
| 1080 } |
| 1081 } |
| 1082 |
| 1083 const GrShape& exampleFillCase = shapes[0][0][0][kFill][0]; |
| 1084 Key exampleFillCaseKey; |
| 1085 make_key(&exampleFillCaseKey, exampleFillCase); |
| 1086 |
| 1087 const GrShape& exampleStrokeAndFillCase = shapes[0][0][0][kStrokeAndFill][0]
; |
| 1088 Key exampleStrokeAndFillCaseKey; |
| 1089 make_key(&exampleStrokeAndFillCaseKey, exampleStrokeAndFillCase); |
| 1090 |
| 1091 const GrShape& exampleInvFillCase = shapes[1][0][0][kFill][0]; |
| 1092 Key exampleInvFillCaseKey; |
| 1093 make_key(&exampleInvFillCaseKey, exampleInvFillCase); |
| 1094 |
| 1095 const GrShape& exampleInvStrokeAndFillCase = shapes[1][0][0][kStrokeAndFill]
[0]; |
| 1096 Key exampleInvStrokeAndFillCaseKey; |
| 1097 make_key(&exampleInvStrokeAndFillCaseKey, exampleInvStrokeAndFillCase); |
| 1098 |
| 1099 const GrShape& exampleStrokeCase = shapes[0][0][0][kStroke][0]; |
| 1100 Key exampleStrokeCaseKey; |
| 1101 make_key(&exampleStrokeCaseKey, exampleStrokeCase); |
| 1102 |
| 1103 const GrShape& exampleHairlineCase = shapes[0][0][0][kHairline][0]; |
| 1104 Key exampleHairlineCaseKey; |
| 1105 make_key(&exampleHairlineCaseKey, exampleHairlineCase); |
| 1106 |
| 1107 // These are dummy initializations to suppress warnings. |
| 1108 SkRRect rr = SkRRect::MakeEmpty(); |
| 1109 SkPath::Direction dir = SkPath::kCW_Direction; |
| 1110 unsigned start = ~0U; |
| 1111 bool inv = true; |
| 1112 |
| 1113 REPORTER_ASSERT(r, exampleFillCase.asRRect(&rr, &dir, &start, &inv)); |
| 1114 REPORTER_ASSERT(r, rr == rrect); |
| 1115 REPORTER_ASSERT(r, SkPath::kCW_Direction == dir); |
| 1116 REPORTER_ASSERT(r, 0 == start); |
| 1117 REPORTER_ASSERT(r, !inv); |
| 1118 |
| 1119 REPORTER_ASSERT(r, exampleInvFillCase.asRRect(&rr, &dir, &start, &inv)); |
| 1120 REPORTER_ASSERT(r, rr == rrect); |
| 1121 REPORTER_ASSERT(r, SkPath::kCW_Direction == dir); |
| 1122 REPORTER_ASSERT(r, 0 == start); |
| 1123 REPORTER_ASSERT(r, inv); |
| 1124 |
| 1125 REPORTER_ASSERT(r, exampleStrokeAndFillCase.asRRect(&rr, &dir, &start, &inv)
); |
| 1126 REPORTER_ASSERT(r, rr == rrect); |
| 1127 REPORTER_ASSERT(r, SkPath::kCW_Direction == dir); |
| 1128 REPORTER_ASSERT(r, 0 == start); |
| 1129 REPORTER_ASSERT(r, !inv); |
| 1130 |
| 1131 REPORTER_ASSERT(r, exampleInvStrokeAndFillCase.asRRect(&rr, &dir, &start, &i
nv)); |
| 1132 REPORTER_ASSERT(r, rr == rrect); |
| 1133 REPORTER_ASSERT(r, SkPath::kCW_Direction == dir); |
| 1134 REPORTER_ASSERT(r, 0 == start); |
| 1135 REPORTER_ASSERT(r, inv); |
| 1136 |
| 1137 REPORTER_ASSERT(r, exampleHairlineCase.asRRect(&rr, &dir, &start, &inv)); |
| 1138 REPORTER_ASSERT(r, rr == rrect); |
| 1139 REPORTER_ASSERT(r, SkPath::kCW_Direction == dir); |
| 1140 REPORTER_ASSERT(r, 0 == start); |
| 1141 REPORTER_ASSERT(r, !inv); |
| 1142 |
| 1143 REPORTER_ASSERT(r, exampleStrokeCase.asRRect(&rr, &dir, &start, &inv)); |
| 1144 REPORTER_ASSERT(r, rr == rrect); |
| 1145 REPORTER_ASSERT(r, SkPath::kCW_Direction == dir); |
| 1146 REPORTER_ASSERT(r, 0 == start); |
| 1147 REPORTER_ASSERT(r, !inv); |
| 1148 |
| 1149 // Remember that the key reflects the geometry before styling is applied. |
| 1150 REPORTER_ASSERT(r, exampleFillCaseKey != exampleInvFillCaseKey); |
| 1151 REPORTER_ASSERT(r, exampleFillCaseKey == exampleStrokeAndFillCaseKey); |
| 1152 REPORTER_ASSERT(r, exampleFillCaseKey != exampleInvStrokeAndFillCaseKey); |
| 1153 REPORTER_ASSERT(r, exampleFillCaseKey == exampleStrokeCaseKey); |
| 1154 REPORTER_ASSERT(r, exampleFillCaseKey == exampleHairlineCaseKey); |
| 1155 REPORTER_ASSERT(r, exampleInvStrokeAndFillCaseKey == exampleInvFillCaseKey); |
| 1156 |
| 1157 for (int inverted = 0; inverted < 2; ++inverted) { |
| 1158 for (int ccw = 0; ccw < 2; ++ccw) { |
| 1159 for (unsigned s = 0; s < 8; ++s) { |
| 1160 for (int dash = 0; dash < 2; ++dash) { |
| 1161 const GrShape& fillCase = shapes[inverted][ccw][s][kFill][da
sh]; |
| 1162 Key fillCaseKey; |
| 1163 make_key(&fillCaseKey, fillCase); |
| 1164 |
| 1165 const GrShape& strokeAndFillCase = |
| 1166 shapes[inverted][ccw][s][kStrokeAndFill][dash]; |
| 1167 Key strokeAndFillCaseKey; |
| 1168 make_key(&strokeAndFillCaseKey, strokeAndFillCase); |
| 1169 |
| 1170 // Both fill and stroke-and-fill shapes must respect the inv
erseness and both |
| 1171 // ignore dashing. |
| 1172 REPORTER_ASSERT(r, !fillCase.style().pathEffect()); |
| 1173 REPORTER_ASSERT(r, !strokeAndFillCase.style().pathEffect()); |
| 1174 TestCase a(fillCase, r); |
| 1175 TestCase b(inverted ? exampleInvFillCase : exampleFillCase,
r); |
| 1176 TestCase c(strokeAndFillCase, r); |
| 1177 TestCase d(inverted ? exampleInvStrokeAndFillCase |
| 1178 : exampleStrokeAndFillCase, r); |
| 1179 a.compare(r, b, TestCase::kAllSame_ComparisonExpecation); |
| 1180 c.compare(r, d, TestCase::kAllSame_ComparisonExpecation); |
| 1181 |
| 1182 const GrShape& strokeCase = shapes[inverted][ccw][s][kStroke
][dash]; |
| 1183 const GrShape& hairlineCase = shapes[inverted][ccw][s][kHair
line][dash]; |
| 1184 |
| 1185 TestCase e(strokeCase, r); |
| 1186 TestCase f(exampleStrokeCase, r); |
| 1187 TestCase g(hairlineCase, r); |
| 1188 TestCase h(exampleHairlineCase, r); |
| 1189 |
| 1190 // Both hairline and stroke shapes must respect the dashing
and both |
| 1191 // ignore inverseness. |
| 1192 if (dash) { |
| 1193 unsigned expectedStart = canonicalize_rrect_start(s, rre
ct); |
| 1194 REPORTER_ASSERT(r, strokeCase.style().pathEffect()); |
| 1195 REPORTER_ASSERT(r, hairlineCase.style().pathEffect()); |
| 1196 |
| 1197 REPORTER_ASSERT(r, strokeCase.asRRect(&rr, &dir, &start,
&inv)); |
| 1198 REPORTER_ASSERT(r, rr == rrect); |
| 1199 REPORTER_ASSERT(r, (SkPath::kCCW_Direction == dir) == cc
w); |
| 1200 REPORTER_ASSERT(r, start == expectedStart); |
| 1201 REPORTER_ASSERT(r, !inv); |
| 1202 REPORTER_ASSERT(r, hairlineCase.asRRect(&rr, &dir, &star
t, &inv)); |
| 1203 REPORTER_ASSERT(r, rr == rrect); |
| 1204 REPORTER_ASSERT(r, (SkPath::kCCW_Direction == dir) == cc
w); |
| 1205 REPORTER_ASSERT(r, start == expectedStart); |
| 1206 REPORTER_ASSERT(r, !inv); |
| 1207 |
| 1208 // The pre-style case for the dash will match the non-da
sh example iff the |
| 1209 // dir and start match (dir=cw, start=0). |
| 1210 if (0 == expectedStart && 0 == ccw) { |
| 1211 e.compare(r, f, TestCase::kSameUpToPE_ComparisonExpe
cation); |
| 1212 g.compare(r, h, TestCase::kSameUpToPE_ComparisonExpe
cation); |
| 1213 } else { |
| 1214 e.compare(r, f, TestCase::kAllDifferent_ComparisonEx
pecation); |
| 1215 g.compare(r, h, TestCase::kAllDifferent_ComparisonEx
pecation); |
| 1216 } |
| 1217 } else { |
| 1218 REPORTER_ASSERT(r, !strokeCase.style().pathEffect()); |
| 1219 REPORTER_ASSERT(r, !hairlineCase.style().pathEffect()); |
| 1220 e.compare(r, f, TestCase::kAllSame_ComparisonExpecation)
; |
| 1221 g.compare(r, h, TestCase::kAllSame_ComparisonExpecation)
; |
| 1222 } |
| 1223 } |
| 1224 } |
| 1225 } |
| 1226 } |
| 1227 } |
| 1228 |
| 991 DEF_TEST(GrShape, reporter) { | 1229 DEF_TEST(GrShape, reporter) { |
| 992 for (auto r : { SkRect::MakeWH(10, 20), | 1230 for (auto r : { SkRect::MakeWH(10, 20), |
| 993 SkRect::MakeWH(-10, -20), | 1231 SkRect::MakeWH(-10, -20), |
| 994 SkRect::MakeWH(-10, 20), | 1232 SkRect::MakeWH(-10, 20), |
| 995 SkRect::MakeWH(10, -20)}) { | 1233 SkRect::MakeWH(10, -20)}) { |
| 996 test_basic(reporter, r); | 1234 test_basic(reporter, r); |
| 997 test_scale(reporter, r); | 1235 test_scale(reporter, r); |
| 998 test_dash_fill(reporter, r); | 1236 test_dash_fill(reporter, r); |
| 999 test_null_dash(reporter, r); | 1237 test_null_dash(reporter, r); |
| 1000 // Test modifying various stroke params. | 1238 // Test modifying various stroke params. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1012 test_unknown_path_effect(reporter, r); | 1250 test_unknown_path_effect(reporter, r); |
| 1013 test_path_effect_makes_empty_shape(reporter, r); | 1251 test_path_effect_makes_empty_shape(reporter, r); |
| 1014 test_path_effect_fails(reporter, r); | 1252 test_path_effect_fails(reporter, r); |
| 1015 test_make_hairline_path_effect(reporter, r, true); | 1253 test_make_hairline_path_effect(reporter, r, true); |
| 1016 } | 1254 } |
| 1017 | 1255 |
| 1018 for (auto rr : { SkRRect::MakeRect(SkRect::MakeWH(10, 10)), | 1256 for (auto rr : { SkRRect::MakeRect(SkRect::MakeWH(10, 10)), |
| 1019 SkRRect::MakeRectXY(SkRect::MakeWH(10, 10), 3, 4), | 1257 SkRRect::MakeRectXY(SkRect::MakeWH(10, 10), 3, 4), |
| 1020 SkRRect::MakeOval(SkRect::MakeWH(20, 20))}) { | 1258 SkRRect::MakeOval(SkRect::MakeWH(20, 20))}) { |
| 1021 test_basic(reporter, rr); | 1259 test_basic(reporter, rr); |
| 1260 test_rrect(reporter, rr); |
| 1022 test_scale(reporter, rr); | 1261 test_scale(reporter, rr); |
| 1023 test_dash_fill(reporter, rr); | 1262 test_dash_fill(reporter, rr); |
| 1024 test_null_dash(reporter, rr); | 1263 test_null_dash(reporter, rr); |
| 1025 // Test modifying various stroke params. | 1264 // Test modifying various stroke params. |
| 1026 test_stroke_param<SkRRect, SkScalar>( | 1265 test_stroke_param<SkRRect, SkScalar>( |
| 1027 reporter, rr, | 1266 reporter, rr, |
| 1028 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, | 1267 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, |
| 1029 SkIntToScalar(2), SkIntToScalar(4)); | 1268 SkIntToScalar(2), SkIntToScalar(4)); |
| 1030 test_stroke_param<SkRRect, SkPaint::Join>( | 1269 test_stroke_param<SkRRect, SkPaint::Join>( |
| 1031 reporter, rr, | 1270 reporter, rr, |
| 1032 [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);
}, | 1271 [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);
}, |
| 1033 SkPaint::kMiter_Join, SkPaint::kRound_Join); | 1272 SkPaint::kMiter_Join, SkPaint::kRound_Join); |
| 1034 test_stroke_cap(reporter, rr); | 1273 test_stroke_cap(reporter, rr); |
| 1035 test_miter_limit(reporter, rr); | 1274 test_miter_limit(reporter, rr); |
| 1036 test_path_effect_makes_rrect(reporter, rr); | 1275 test_path_effect_makes_rrect(reporter, rr); |
| 1037 test_unknown_path_effect(reporter, rr); | 1276 test_unknown_path_effect(reporter, rr); |
| 1038 test_path_effect_makes_empty_shape(reporter, rr); | 1277 test_path_effect_makes_empty_shape(reporter, rr); |
| 1039 test_path_effect_fails(reporter, rr); | 1278 test_path_effect_fails(reporter, rr); |
| 1040 test_make_hairline_path_effect(reporter, rr, true); | 1279 test_make_hairline_path_effect(reporter, rr, true); |
| 1041 } | 1280 } |
| 1042 | 1281 |
| 1043 struct TestPath { | 1282 struct TestPath { |
| 1044 TestPath(const SkPath& path, bool isRRectFill, bool isRRectStroke ,const
SkRRect& rrect) | 1283 TestPath(const SkPath& path, bool isRRectFill, bool isRRectStroke, const
SkRRect& rrect) |
| 1045 : fPath(path) | 1284 : fPath(path) |
| 1046 , fIsRRectForFill(isRRectFill) | 1285 , fIsRRectForFill(isRRectFill) |
| 1047 , fIsRRectForStroke(isRRectStroke) | 1286 , fIsRRectForStroke(isRRectStroke) |
| 1048 , fRRect(rrect) {} | 1287 , fRRect(rrect) {} |
| 1049 SkPath fPath; | 1288 SkPath fPath; |
| 1050 bool fIsRRectForFill; | 1289 bool fIsRRectForFill; |
| 1051 bool fIsRRectForStroke; | 1290 bool fIsRRectForStroke; |
| 1052 SkRRect fRRect; | 1291 SkRRect fRRect; |
| 1053 }; | 1292 }; |
| 1054 SkTArray<TestPath> paths; | 1293 SkTArray<TestPath> paths; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1066 openRectPath.lineTo(10, 0); | 1305 openRectPath.lineTo(10, 0); |
| 1067 openRectPath.lineTo(10, 10); | 1306 openRectPath.lineTo(10, 10); |
| 1068 openRectPath.lineTo(0, 10); | 1307 openRectPath.lineTo(0, 10); |
| 1069 paths.emplace_back(openRectPath, true, false, SkRRect::MakeRect(SkRect::Make
WH(10, 10))); | 1308 paths.emplace_back(openRectPath, true, false, SkRRect::MakeRect(SkRect::Make
WH(10, 10))); |
| 1070 | 1309 |
| 1071 SkPath quadPath; | 1310 SkPath quadPath; |
| 1072 quadPath.quadTo(10, 10, 5, 8); | 1311 quadPath.quadTo(10, 10, 5, 8); |
| 1073 paths.emplace_back(quadPath, false, false, SkRRect()); | 1312 paths.emplace_back(quadPath, false, false, SkRRect()); |
| 1074 | 1313 |
| 1075 for (auto testPath : paths) { | 1314 for (auto testPath : paths) { |
| 1315 for (bool inverseFill : {false, true}) { |
| 1316 if (inverseFill) { |
| 1317 if (testPath.fPath.getFillType() == SkPath::kEvenOdd_FillType) { |
| 1318 testPath.fPath.setFillType(SkPath::kInverseEvenOdd_FillType)
; |
| 1319 } else { |
| 1320 SkASSERT(testPath.fPath.getFillType() == SkPath::kWinding_Fi
llType); |
| 1321 testPath.fPath.setFillType(SkPath::kInverseWinding_FillType)
; |
| 1322 } |
| 1323 } |
| 1324 const SkPath& path = testPath.fPath; |
| 1325 // These tests all assume that the original GrShape for fill and str
oke will be the |
| 1326 // same. |
| 1327 // However, that is not the case in special cases (e.g. an unclosed
rect becomes a RRect |
| 1328 // GrShape with a fill style but becomes a Path GrShape when stroked
). |
| 1329 if (testPath.fIsRRectForFill == testPath.fIsRRectForStroke) { |
| 1330 test_basic(reporter, path); |
| 1331 test_null_dash(reporter, path); |
| 1332 test_path_effect_makes_rrect(reporter, path); |
| 1333 } |
| 1334 test_scale(reporter, path); |
| 1335 // This test uses a stroking paint, hence use of fIsRRectForStroke |
| 1336 test_volatile_path(reporter, path, testPath.fIsRRectForStroke); |
| 1337 test_dash_fill(reporter, path); |
| 1338 // Test modifying various stroke params. |
| 1339 test_stroke_param<SkPath, SkScalar>( |
| 1340 reporter, path, |
| 1341 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, |
| 1342 SkIntToScalar(2), SkIntToScalar(4)); |
| 1343 test_stroke_param<SkPath, SkPaint::Join>( |
| 1344 reporter, path, |
| 1345 [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);}, |
| 1346 SkPaint::kMiter_Join, SkPaint::kRound_Join); |
| 1347 test_stroke_cap(reporter, path); |
| 1348 test_miter_limit(reporter, path); |
| 1349 test_unknown_path_effect(reporter, path); |
| 1350 test_path_effect_makes_empty_shape(reporter, path); |
| 1351 test_path_effect_fails(reporter, path); |
| 1352 test_make_hairline_path_effect(reporter, path, testPath.fIsRRectForS
troke); |
| 1353 } |
| 1354 } |
| 1355 for (auto testPath : paths) { |
| 1076 const SkPath& path = testPath.fPath; | 1356 const SkPath& path = testPath.fPath; |
| 1077 // These tests all assume that the original GrShape for fill and stroke
will be the same. | |
| 1078 // However, that is not the case in special cases (e.g. a unclosed rect
becomes a RRect | |
| 1079 // GrShape with a fill style but becomes a Path GrShape when stroked). | |
| 1080 if (testPath.fIsRRectForFill == testPath.fIsRRectForStroke) { | |
| 1081 test_basic(reporter, path); | |
| 1082 test_null_dash(reporter, path); | |
| 1083 test_path_effect_makes_rrect(reporter, path); | |
| 1084 } | |
| 1085 test_scale(reporter, path); | |
| 1086 // This test uses a stroking paint, hence use of fIsRRectForStroke | |
| 1087 test_volatile_path(reporter, path, testPath.fIsRRectForStroke); | |
| 1088 test_dash_fill(reporter, path); | |
| 1089 // Test modifying various stroke params. | |
| 1090 test_stroke_param<SkPath, SkScalar>( | |
| 1091 reporter, path, | |
| 1092 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, | |
| 1093 SkIntToScalar(2), SkIntToScalar(4)); | |
| 1094 test_stroke_param<SkPath, SkPaint::Join>( | |
| 1095 reporter, path, | |
| 1096 [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);}, | |
| 1097 SkPaint::kMiter_Join, SkPaint::kRound_Join); | |
| 1098 test_stroke_cap(reporter, path); | |
| 1099 test_miter_limit(reporter, path); | |
| 1100 test_unknown_path_effect(reporter, path); | |
| 1101 test_path_effect_makes_empty_shape(reporter, path); | |
| 1102 test_path_effect_fails(reporter, path); | |
| 1103 test_make_hairline_path_effect(reporter, path, testPath.fIsRRectForStrok
e); | |
| 1104 | 1357 |
| 1105 SkPaint fillPaint; | 1358 SkPaint fillPaint; |
| 1106 TestCase fillPathCase(path, fillPaint, reporter); | 1359 TestCase fillPathCase(path, fillPaint, reporter); |
| 1107 SkRRect rrect; | 1360 SkRRect rrect; |
| 1108 REPORTER_ASSERT(reporter, testPath.fIsRRectForFill == | 1361 REPORTER_ASSERT(reporter, testPath.fIsRRectForFill == |
| 1109 fillPathCase.baseShape().asRRect(&rrect, nullp
tr, nullptr)); | 1362 fillPathCase.baseShape().asRRect(&rrect, nullp
tr, nullptr, |
| 1363 nullptr)); |
| 1110 if (testPath.fIsRRectForFill) { | 1364 if (testPath.fIsRRectForFill) { |
| 1111 TestCase fillPathCase2(path, fillPaint, reporter); | 1365 TestCase fillPathCase2(testPath.fPath, fillPaint, reporter); |
| 1112 REPORTER_ASSERT(reporter, rrect == testPath.fRRect); | 1366 REPORTER_ASSERT(reporter, rrect == testPath.fRRect); |
| 1113 TestCase fillRRectCase(rrect, fillPaint, reporter); | 1367 TestCase fillRRectCase(rrect, fillPaint, reporter); |
| 1114 fillPathCase2.compare(reporter, fillRRectCase, TestCase::kAllSame_Co
mparisonExpecation); | 1368 fillPathCase2.compare(reporter, fillRRectCase, |
| 1369 TestCase::kAllSame_ComparisonExpecation); |
| 1115 } | 1370 } |
| 1116 | |
| 1117 SkPaint strokePaint; | 1371 SkPaint strokePaint; |
| 1118 strokePaint.setStrokeWidth(3.f); | 1372 strokePaint.setStrokeWidth(3.f); |
| 1119 strokePaint.setStyle(SkPaint::kStroke_Style); | 1373 strokePaint.setStyle(SkPaint::kStroke_Style); |
| 1120 TestCase strokePathCase(path, strokePaint, reporter); | 1374 TestCase strokePathCase(path, strokePaint, reporter); |
| 1121 REPORTER_ASSERT(reporter, testPath.fIsRRectForStroke == | 1375 REPORTER_ASSERT(reporter, testPath.fIsRRectForStroke == |
| 1122 strokePathCase.baseShape().asRRect(&rrect, nul
lptr, nullptr)); | 1376 strokePathCase.baseShape().asRRect(&rrect, nul
lptr, nullptr, |
| 1377 nullptr)); |
| 1123 if (testPath.fIsRRectForStroke) { | 1378 if (testPath.fIsRRectForStroke) { |
| 1124 REPORTER_ASSERT(reporter, rrect == testPath.fRRect); | 1379 REPORTER_ASSERT(reporter, rrect == testPath.fRRect); |
| 1125 TestCase strokeRRectCase(rrect, strokePaint, reporter); | 1380 TestCase strokeRRectCase(rrect, strokePaint, reporter); |
| 1126 strokePathCase.compare(reporter, strokeRRectCase, | 1381 strokePathCase.compare(reporter, strokeRRectCase, |
| 1127 TestCase::kAllSame_ComparisonExpecation); | 1382 TestCase::kAllSame_ComparisonExpecation); |
| 1128 } | 1383 } |
| 1129 } | 1384 } |
| 1130 | 1385 |
| 1131 // Test a volatile empty path. | 1386 // Test a volatile empty path. |
| 1132 test_volatile_path(reporter, SkPath(), true); | 1387 test_volatile_path(reporter, SkPath(), true); |
| 1133 | 1388 |
| 1134 test_empty_shape(reporter); | 1389 test_empty_shape(reporter); |
| 1135 } | 1390 } |
| 1136 | 1391 |
| 1137 #endif | 1392 #endif |
| OLD | NEW |