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" |
11 #if SK_SUPPORT_GPU | 11 #if SK_SUPPORT_GPU |
12 #include "GrShape.h" | 12 #include "GrShape.h" |
13 #include "SkCanvas.h" | 13 #include "SkCanvas.h" |
14 #include "SkDashPathEffect.h" | 14 #include "SkDashPathEffect.h" |
15 #include "SkPath.h" | 15 #include "SkPath.h" |
| 16 #include "SkPathOps.h" |
16 #include "SkSurface.h" | 17 #include "SkSurface.h" |
17 | 18 |
18 using Key = SkTArray<uint32_t>; | 19 using Key = SkTArray<uint32_t>; |
19 | 20 |
20 static bool make_key(Key* key, const GrShape& shape) { | 21 static bool make_key(Key* key, const GrShape& shape) { |
21 int size = shape.unstyledKeySize(); | 22 int size = shape.unstyledKeySize(); |
22 if (size <= 0) { | 23 if (size <= 0) { |
23 key->reset(0); | 24 key->reset(0); |
24 return false; | 25 return false; |
25 } | 26 } |
26 SkASSERT(size); | 27 SkASSERT(size); |
27 key->reset(size); | 28 key->reset(size); |
28 shape.writeUnstyledKey(key->begin()); | 29 shape.writeUnstyledKey(key->begin()); |
29 return true; | 30 return true; |
30 } | 31 } |
31 | 32 |
| 33 static bool paths_fill_same(const SkPath& a, const SkPath& b) { |
| 34 SkPath pathXor; |
| 35 Op(a, b, SkPathOp::kXOR_SkPathOp, &pathXor); |
| 36 return pathXor.isEmpty(); |
| 37 } |
| 38 |
32 static bool test_bounds_by_rasterizing(const SkPath& path, const SkRect& bounds)
{ | 39 static bool test_bounds_by_rasterizing(const SkPath& path, const SkRect& bounds)
{ |
33 static constexpr int kRes = 2000; | 40 static constexpr int kRes = 2000; |
34 // This tolerance is in units of 1/kRes fractions of the bounds width/height
. | 41 // This tolerance is in units of 1/kRes fractions of the bounds width/height
. |
35 static constexpr int kTol = 0; | 42 static constexpr int kTol = 0; |
36 GR_STATIC_ASSERT(kRes % 4 == 0); | 43 GR_STATIC_ASSERT(kRes % 4 == 0); |
37 SkImageInfo info = SkImageInfo::MakeA8(kRes, kRes); | 44 SkImageInfo info = SkImageInfo::MakeA8(kRes, kRes); |
38 sk_sp<SkSurface> surface = SkSurface::MakeRaster(info); | 45 sk_sp<SkSurface> surface = SkSurface::MakeRaster(info); |
39 surface->getCanvas()->clear(0x0); | 46 surface->getCanvas()->clear(0x0); |
40 SkRect clip = SkRect::MakeXYWH(kRes/4, kRes/4, kRes/2, kRes/2); | 47 SkRect clip = SkRect::MakeXYWH(kRes/4, kRes/4, kRes/2, kRes/2); |
41 SkMatrix matrix; | 48 SkMatrix matrix; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 make_key(&fAppliedPEKey, fAppliedPE); | 134 make_key(&fAppliedPEKey, fAppliedPE); |
128 make_key(&fAppliedPEThenStrokeKey, fAppliedPEThenStroke); | 135 make_key(&fAppliedPEThenStrokeKey, fAppliedPEThenStroke); |
129 make_key(&fAppliedFullKey, fAppliedFull); | 136 make_key(&fAppliedFullKey, fAppliedFull); |
130 | 137 |
131 // Applying the path effect and then the stroke should always be the sam
e as applying | 138 // Applying the path effect and then the stroke should always be the sam
e as applying |
132 // both in one go. | 139 // both in one go. |
133 REPORTER_ASSERT(r, fAppliedPEThenStrokeKey == fAppliedFullKey); | 140 REPORTER_ASSERT(r, fAppliedPEThenStrokeKey == fAppliedFullKey); |
134 SkPath a, b; | 141 SkPath a, b; |
135 fAppliedPEThenStroke.asPath(&a); | 142 fAppliedPEThenStroke.asPath(&a); |
136 fAppliedFull.asPath(&b); | 143 fAppliedFull.asPath(&b); |
137 REPORTER_ASSERT(r, a == b); | 144 // 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: |
| 146 // 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, |
| 148 // now that there is no longer a path effect, the direction and starting
index get |
| 149 // canonicalized before the stroke. |
| 150 if (fAppliedPE.asRRect(nullptr, nullptr, nullptr)) { |
| 151 REPORTER_ASSERT(r, paths_fill_same(a, b)); |
| 152 } else { |
| 153 REPORTER_ASSERT(r, a == b); |
| 154 } |
138 REPORTER_ASSERT(r, fAppliedFull.isEmpty() == fAppliedPEThenStroke.isEmpt
y()); | 155 REPORTER_ASSERT(r, fAppliedFull.isEmpty() == fAppliedPEThenStroke.isEmpt
y()); |
139 | 156 |
140 SkPath path; | 157 SkPath path; |
141 fBase.asPath(&path); | 158 fBase.asPath(&path); |
142 REPORTER_ASSERT(r, path.isEmpty() == fBase.isEmpty()); | 159 REPORTER_ASSERT(r, path.isEmpty() == fBase.isEmpty()); |
143 fAppliedPE.asPath(&path); | 160 fAppliedPE.asPath(&path); |
144 REPORTER_ASSERT(r, path.isEmpty() == fAppliedPE.isEmpty()); | 161 REPORTER_ASSERT(r, path.isEmpty() == fAppliedPE.isEmpty()); |
145 fAppliedFull.asPath(&path); | 162 fAppliedFull.asPath(&path); |
146 REPORTER_ASSERT(r, path.isEmpty() == fAppliedFull.isEmpty()); | 163 REPORTER_ASSERT(r, path.isEmpty() == fAppliedFull.isEmpty()); |
147 | 164 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 fAppliedPE.asPath(&b); | 237 fAppliedPE.asPath(&b); |
221 REPORTER_ASSERT(reporter, a == b); | 238 REPORTER_ASSERT(reporter, a == b); |
222 if (expectations.fStrokeApplies) { | 239 if (expectations.fStrokeApplies) { |
223 REPORTER_ASSERT(reporter, fBaseKey != fAppliedFullKey); | 240 REPORTER_ASSERT(reporter, fBaseKey != fAppliedFullKey); |
224 } else { | 241 } else { |
225 REPORTER_ASSERT(reporter, fBaseKey == fAppliedFullKey); | 242 REPORTER_ASSERT(reporter, fBaseKey == fAppliedFullKey); |
226 } | 243 } |
227 } | 244 } |
228 } | 245 } |
229 | 246 |
230 void TestCase::compare(skiatest::Reporter* reporter, const TestCase& that, | 247 void check_equivalence(skiatest::Reporter* r, const GrShape& a, const GrShape& b
, |
| 248 const Key& keyA, const Key& keyB) { |
| 249 // GrShape only respects the input winding direction and start point for rre
ct shapes |
| 250 // when there is a path effect. Thus, if there are two GrShapes representing
the same rrect |
| 251 // but one has a path effect in its style and the other doesn't then asPath(
) and the unstyled |
| 252 // key will differ. GrShape will have canonicalized the direction and start
point for the shape |
| 253 // without the path effect. If *both* have path effects then they should hav
e both preserved |
| 254 // the direction and starting point. |
| 255 |
| 256 // The asRRect() output params are all initialized just to silence compiler
warnings about |
| 257 // uninitialized variables. |
| 258 SkRRect rrectA = SkRRect::MakeEmpty(), rrectB = SkRRect::MakeEmpty(); |
| 259 SkPath::Direction dirA = SkPath::kCW_Direction, dirB = SkPath::kCW_Direction
; |
| 260 unsigned startA = ~0U, startB = ~0U; |
| 261 |
| 262 bool aIsRRect = a.asRRect(&rrectA, &dirA, &startA); |
| 263 bool bIsRRect = b.asRRect(&rrectB, &dirB, &startB); |
| 264 bool aHasPE = a.style().hasPathEffect(); |
| 265 bool bHasPE = b.style().hasPathEffect(); |
| 266 bool allowSameRRectButDiffStartAndDir = (aIsRRect && bIsRRect) && (aHasPE !=
bHasPE); |
| 267 SkPath pathA, pathB; |
| 268 a.asPath(&pathA); |
| 269 b.asPath(&pathB); |
| 270 if (allowSameRRectButDiffStartAndDir) { |
| 271 REPORTER_ASSERT(r, rrectA == rrectB); |
| 272 REPORTER_ASSERT(r, paths_fill_same(pathA, pathB)); |
| 273 } else { |
| 274 REPORTER_ASSERT(r, pathA == pathB); |
| 275 REPORTER_ASSERT(r, keyA == keyB); |
| 276 REPORTER_ASSERT(r, aIsRRect == bIsRRect); |
| 277 if (aIsRRect) { |
| 278 REPORTER_ASSERT(r, rrectA == rrectB); |
| 279 REPORTER_ASSERT(r, dirA == dirB); |
| 280 REPORTER_ASSERT(r, startA == startB); |
| 281 } |
| 282 } |
| 283 REPORTER_ASSERT(r, a.isEmpty() == b.isEmpty()); |
| 284 REPORTER_ASSERT(r, a.knownToBeClosed() == b.knownToBeClosed()); |
| 285 REPORTER_ASSERT(r, a.bounds() == b.bounds()); |
| 286 } |
| 287 |
| 288 void TestCase::compare(skiatest::Reporter* r, const TestCase& that, |
231 ComparisonExpecation expectation) const { | 289 ComparisonExpecation expectation) const { |
232 SkPath a, b; | 290 SkPath a, b; |
233 switch (expectation) { | 291 switch (expectation) { |
234 case kAllDifferent_ComparisonExpecation: | 292 case kAllDifferent_ComparisonExpecation: |
235 REPORTER_ASSERT(reporter, fBaseKey != that.fBaseKey); | 293 REPORTER_ASSERT(r, fBaseKey != that.fBaseKey); |
236 REPORTER_ASSERT(reporter, fAppliedPEKey != that.fAppliedPEKey); | 294 REPORTER_ASSERT(r, fAppliedPEKey != that.fAppliedPEKey); |
237 REPORTER_ASSERT(reporter, fAppliedFullKey != that.fAppliedFullKey); | 295 REPORTER_ASSERT(r, fAppliedFullKey != that.fAppliedFullKey); |
238 break; | 296 break; |
239 case kSameUpToPE_ComparisonExpecation: | 297 case kSameUpToPE_ComparisonExpecation: |
240 REPORTER_ASSERT(reporter, fBaseKey == that.fBaseKey); | 298 check_equivalence(r, fBase, that.fBase, fBaseKey, that.fBaseKey); |
241 fBase.asPath(&a); | 299 REPORTER_ASSERT(r, fAppliedPEKey != that.fAppliedPEKey); |
242 that.fBase.asPath(&b); | 300 REPORTER_ASSERT(r, fAppliedFullKey != that.fAppliedFullKey); |
243 REPORTER_ASSERT(reporter, a == b); | |
244 REPORTER_ASSERT(reporter, fBase.isEmpty() == that.fBase.isEmpty()); | |
245 REPORTER_ASSERT(reporter, fAppliedPEKey != that.fAppliedPEKey); | |
246 REPORTER_ASSERT(reporter, fAppliedFullKey != that.fAppliedFullKey); | |
247 break; | 301 break; |
248 case kSameUpToStroke_ComparisonExpecation: | 302 case kSameUpToStroke_ComparisonExpecation: |
249 REPORTER_ASSERT(reporter, fBaseKey == that.fBaseKey); | 303 check_equivalence(r, fBase, that.fBase, fBaseKey, that.fBaseKey); |
250 fBase.asPath(&a); | 304 check_equivalence(r, fAppliedPE, that.fAppliedPE, fAppliedPEKey, tha
t.fAppliedPEKey); |
251 that.fBase.asPath(&b); | 305 REPORTER_ASSERT(r, fAppliedFullKey != that.fAppliedFullKey); |
252 REPORTER_ASSERT(reporter, a == b); | |
253 REPORTER_ASSERT(reporter, fBase.isEmpty() == that.fBase.isEmpty()); | |
254 REPORTER_ASSERT(reporter, fAppliedPEKey == that.fAppliedPEKey); | |
255 fAppliedPE.asPath(&a); | |
256 that.fAppliedPE.asPath(&b); | |
257 REPORTER_ASSERT(reporter, a == b); | |
258 REPORTER_ASSERT(reporter, fAppliedPE.isEmpty() == that.fAppliedPE.is
Empty()); | |
259 REPORTER_ASSERT(reporter, fAppliedFullKey != that.fAppliedFullKey); | |
260 break; | 306 break; |
261 case kAllSame_ComparisonExpecation: | 307 case kAllSame_ComparisonExpecation: |
262 REPORTER_ASSERT(reporter, fBaseKey == that.fBaseKey); | 308 check_equivalence(r, fBase, that.fBase, fBaseKey, that.fBaseKey); |
263 fBase.asPath(&a); | 309 check_equivalence(r, fAppliedPE, that.fAppliedPE, fAppliedPEKey, tha
t.fAppliedPEKey); |
264 that.fBase.asPath(&b); | 310 check_equivalence(r, fAppliedFull, that.fAppliedFull, fAppliedFullKe
y, |
265 REPORTER_ASSERT(reporter, a == b); | 311 that.fAppliedFullKey); |
266 REPORTER_ASSERT(reporter, fBase.isEmpty() == that.fBase.isEmpty()); | |
267 REPORTER_ASSERT(reporter, fAppliedPEKey == that.fAppliedPEKey); | |
268 fAppliedPE.asPath(&a); | |
269 that.fAppliedPE.asPath(&b); | |
270 REPORTER_ASSERT(reporter, a == b); | |
271 REPORTER_ASSERT(reporter, fAppliedPE.isEmpty() == that.fAppliedPE.is
Empty()); | |
272 REPORTER_ASSERT(reporter, fAppliedFullKey == that.fAppliedFullKey); | |
273 fAppliedFull.asPath(&a); | |
274 that.fAppliedFull.asPath(&b); | |
275 REPORTER_ASSERT(reporter, a == b); | |
276 REPORTER_ASSERT(reporter, fAppliedFull.isEmpty() == that.fAppliedFul
l.isEmpty()); | |
277 break; | 312 break; |
278 } | 313 } |
279 } | 314 } |
280 } // namespace | 315 } // namespace |
281 | 316 |
282 static sk_sp<SkPathEffect> make_dash() { | 317 static sk_sp<SkPathEffect> make_dash() { |
283 static const SkScalar kIntervals[] = { 0.25, 3.f, 0.5, 2.f }; | 318 static const SkScalar kIntervals[] = { 0.25, 3.f, 0.5, 2.f }; |
284 static const SkScalar kPhase = 0.75; | 319 static const SkScalar kPhase = 0.75; |
285 return SkDashPathEffect::Make(kIntervals, SK_ARRAY_COUNT(kIntervals), kPhase
); | 320 return SkDashPathEffect::Make(kIntervals, SK_ARRAY_COUNT(kIntervals), kPhase
); |
286 } | 321 } |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
412 strokeDashCase1.compare(reporter, strokeDashCase2, TestCase::kSameUpToPE_Co
mparisonExpecation); | 447 strokeDashCase1.compare(reporter, strokeDashCase2, TestCase::kSameUpToPE_Co
mparisonExpecation); |
413 | 448 |
414 // Stroke and fill cases | 449 // Stroke and fill cases |
415 SkPaint strokeAndFill = stroke; | 450 SkPaint strokeAndFill = stroke; |
416 strokeAndFill.setStyle(SkPaint::kStrokeAndFill_Style); | 451 strokeAndFill.setStyle(SkPaint::kStrokeAndFill_Style); |
417 TestCase strokeAndFillCase1(geo, strokeAndFill, reporter, kS1); | 452 TestCase strokeAndFillCase1(geo, strokeAndFill, reporter, kS1); |
418 TestCase strokeAndFillCase2(geo, strokeAndFill, reporter, kS2); | 453 TestCase strokeAndFillCase2(geo, strokeAndFill, reporter, kS2); |
419 // Scale affects the stroke. Though, this can wind up creating a rect when t
he input is a rect. | 454 // Scale affects the stroke. Though, this can wind up creating a rect when t
he input is a rect. |
420 // In that case we wind up with a pure geometry key and the geometries are t
he same. | 455 // In that case we wind up with a pure geometry key and the geometries are t
he same. |
421 SkRRect rrect; | 456 SkRRect rrect; |
422 if (strokeAndFillCase1.appliedFullStyleShape().asRRect(&rrect)) { | 457 if (strokeAndFillCase1.appliedFullStyleShape().asRRect(&rrect, nullptr, null
ptr)) { |
423 // We currently only expect to get here in the rect->rect case. | 458 // We currently only expect to get here in the rect->rect case. |
424 REPORTER_ASSERT(reporter, rrect.isRect()); | 459 REPORTER_ASSERT(reporter, rrect.isRect()); |
425 REPORTER_ASSERT(reporter, strokeAndFillCase1.baseShape().asRRect(&rrect)
&& rrect.isRect()); | 460 REPORTER_ASSERT(reporter, |
| 461 strokeAndFillCase1.baseShape().asRRect(&rrect, nullptr,
nullptr) && |
| 462 rrect.isRect()); |
426 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, | 463 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, |
427 TestCase::kAllSame_ComparisonExpecation); | 464 TestCase::kAllSame_ComparisonExpecation); |
428 } else { | 465 } else { |
429 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, | 466 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, |
430 TestCase::kSameUpToStroke_ComparisonExpecatio
n); | 467 TestCase::kSameUpToStroke_ComparisonExpecatio
n); |
431 } | 468 } |
432 | 469 |
433 SkPaint strokeAndFillDash = strokeDash; | 470 SkPaint strokeAndFillDash = strokeDash; |
434 strokeAndFillDash.setStyle(SkPaint::kStrokeAndFill_Style); | 471 strokeAndFillDash.setStyle(SkPaint::kStrokeAndFill_Style); |
435 TestCase strokeAndFillDashCase1(geo, strokeAndFillDash, reporter, kS1); | 472 TestCase strokeAndFillDashCase1(geo, strokeAndFillDash, reporter, kS1); |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
654 TestCase::kSameUpToStroke_ComparisonExpecation); | 691 TestCase::kSameUpToStroke_ComparisonExpecation); |
655 | 692 |
656 TestCase rrectFillCase(RRectPathEffect::RRect(), fill, reporter); | 693 TestCase rrectFillCase(RRectPathEffect::RRect(), fill, reporter); |
657 SkPaint stroke = peStroke; | 694 SkPaint stroke = peStroke; |
658 stroke.setPathEffect(nullptr); | 695 stroke.setPathEffect(nullptr); |
659 TestCase rrectStrokeCase(RRectPathEffect::RRect(), stroke, reporter); | 696 TestCase rrectStrokeCase(RRectPathEffect::RRect(), stroke, reporter); |
660 | 697 |
661 SkRRect rrect; | 698 SkRRect rrect; |
662 // Applying the path effect should make a SkRRect shape. There is no further
stroking in the | 699 // Applying the path effect should make a SkRRect shape. There is no further
stroking in the |
663 // geoPECase, so the full style should be the same as just the PE. | 700 // geoPECase, so the full style should be the same as just the PE. |
664 REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectShape().asRRect(&rrect)
); | 701 REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectShape().asRRect(&rrect,
nullptr, nullptr)); |
665 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); | 702 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); |
666 REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectKey() == rrectFillCase.
baseKey()); | 703 REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectKey() == rrectFillCase.
baseKey()); |
667 | 704 |
668 REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleShape().asRRect(&rrect))
; | 705 REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleShape().asRRect(&rrect,
nullptr, nullptr)); |
669 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); | 706 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); |
670 REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleKey() == rrectFillCase.b
aseKey()); | 707 REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleKey() == rrectFillCase.b
aseKey()); |
671 | 708 |
672 // In the PE+stroke case applying the full style should be the same as just
stroking the rrect. | 709 // In the PE+stroke case applying the full style should be the same as just
stroking the rrect. |
673 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectShape().asRRect(&
rrect)); | 710 REPORTER_ASSERT(reporter, |
| 711 geoPEStrokeCase.appliedPathEffectShape().asRRect(&rrect, nul
lptr, nullptr)); |
674 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); | 712 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); |
675 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectKey() == rrectFil
lCase.baseKey()); | 713 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectKey() == rrectFil
lCase.baseKey()); |
676 | 714 |
677 REPORTER_ASSERT(reporter, !geoPEStrokeCase.appliedFullStyleShape().asRRect(&
rrect)); | 715 REPORTER_ASSERT(reporter, |
| 716 !geoPEStrokeCase.appliedFullStyleShape().asRRect(&rrect, nul
lptr, nullptr)); |
678 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleKey() == | 717 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleKey() == |
679 rrectStrokeCase.appliedFullStyleKey()); | 718 rrectStrokeCase.appliedFullStyleKey()); |
680 } | 719 } |
681 | 720 |
682 template <typename GEO> | 721 template <typename GEO> |
683 void test_unknown_path_effect(skiatest::Reporter* reporter, const GEO& geo) { | 722 void test_unknown_path_effect(skiatest::Reporter* reporter, const GEO& geo) { |
684 /** | 723 /** |
685 * This path effect just adds two lineTos to the input path. | 724 * This path effect just adds two lineTos to the input path. |
686 */ | 725 */ |
687 class AddLineTosPathEffect : SkPathEffect { | 726 class AddLineTosPathEffect : SkPathEffect { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
742 private: | 781 private: |
743 MakeHairlinePathEffect() {} | 782 MakeHairlinePathEffect() {} |
744 }; | 783 }; |
745 | 784 |
746 SkPaint fill; | 785 SkPaint fill; |
747 SkPaint pe; | 786 SkPaint pe; |
748 pe.setPathEffect(MakeHairlinePathEffect::Make()); | 787 pe.setPathEffect(MakeHairlinePathEffect::Make()); |
749 | 788 |
750 TestCase peCase(geo, pe, reporter); | 789 TestCase peCase(geo, pe, reporter); |
751 | 790 |
752 SkPath a, b; | 791 SkPath a, b, c; |
753 peCase.baseShape().asPath(&a); | 792 peCase.baseShape().asPath(&a); |
754 peCase.appliedPathEffectShape().asPath(&b); | 793 peCase.appliedPathEffectShape().asPath(&b); |
755 REPORTER_ASSERT(reporter, a == b); | 794 peCase.appliedFullStyleShape().asPath(&c); |
756 peCase.appliedFullStyleShape().asPath(&b); | |
757 REPORTER_ASSERT(reporter, a == b); | |
758 REPORTER_ASSERT(reporter, peCase.appliedPathEffectShape().style().isSimpleHa
irline()); | |
759 REPORTER_ASSERT(reporter, peCase.appliedFullStyleShape().style().isSimpleHai
rline()); | |
760 if (isNonPath) { | 795 if (isNonPath) { |
761 REPORTER_ASSERT(reporter, peCase.appliedPathEffectKey() == peCase.baseKe
y()); | 796 // RRect types can have a change in start index or direction after the P
E is applied. This |
762 REPORTER_ASSERT(reporter, peCase.appliedFullStyleKey() == peCase.baseKey
()); | 797 // is because once the PE is applied, GrShape may canonicalize the dir a
nd index since it |
| 798 // is not germane to the styling any longer. |
| 799 // Instead we just check that the paths would fill the same both before
and after styling. |
| 800 REPORTER_ASSERT(reporter, paths_fill_same(a, b)); |
| 801 REPORTER_ASSERT(reporter, paths_fill_same(a, c)); |
763 } else { | 802 } else { |
| 803 REPORTER_ASSERT(reporter, a == b); |
| 804 REPORTER_ASSERT(reporter, a == c); |
764 REPORTER_ASSERT(reporter, peCase.appliedPathEffectKey().empty()); | 805 REPORTER_ASSERT(reporter, peCase.appliedPathEffectKey().empty()); |
765 REPORTER_ASSERT(reporter, peCase.appliedFullStyleKey().empty()); | 806 REPORTER_ASSERT(reporter, peCase.appliedFullStyleKey().empty()); |
766 } | 807 } |
| 808 REPORTER_ASSERT(reporter, peCase.appliedPathEffectShape().style().isSimpleHa
irline()); |
| 809 REPORTER_ASSERT(reporter, peCase.appliedFullStyleShape().style().isSimpleHai
rline()); |
767 } | 810 } |
768 | 811 |
769 /** | 812 /** |
770 * isNonPath indicates whether the initial shape made from the path is expected
to be recognized | 813 * isNonPath indicates whether the initial shape made from the path is expected
to be recognized |
771 * as a simpler shape type (e.g. rrect) | 814 * as a simpler shape type (e.g. rrect) |
772 */ | 815 */ |
773 void test_volatile_path(skiatest::Reporter* reporter, const SkPath& path, | 816 void test_volatile_path(skiatest::Reporter* reporter, const SkPath& path, |
774 bool isNonPath) { | 817 bool isNonPath) { |
775 SkPath vPath(path); | 818 SkPath vPath(path); |
776 vPath.setIsVolatile(true); | 819 vPath.setIsVolatile(true); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
887 TestCase::kAllSame_ComparisonExpecation)
; | 930 TestCase::kAllSame_ComparisonExpecation)
; |
888 | 931 |
889 // Same for a rect. | 932 // Same for a rect. |
890 SkRect emptyRect = SkRect::MakeEmpty(); | 933 SkRect emptyRect = SkRect::MakeEmpty(); |
891 TestCase dashAndStrokeEmptyRectCase(emptyRect, dashAndStroke, reporter); | 934 TestCase dashAndStrokeEmptyRectCase(emptyRect, dashAndStroke, reporter); |
892 dashAndStrokeEmptyRectCase.compare(reporter, fillEmptyCase, | 935 dashAndStrokeEmptyRectCase.compare(reporter, fillEmptyCase, |
893 TestCase::kAllSame_ComparisonExpecation); | 936 TestCase::kAllSame_ComparisonExpecation); |
894 } | 937 } |
895 | 938 |
896 DEF_TEST(GrShape, reporter) { | 939 DEF_TEST(GrShape, reporter) { |
897 sk_sp<SkPathEffect> dashPE = make_dash(); | 940 for (auto r : { SkRect::MakeWH(10, 20), |
| 941 SkRect::MakeWH(-10, -20), |
| 942 SkRect::MakeWH(-10, 20), |
| 943 SkRect::MakeWH(10, -20)}) { |
| 944 test_basic(reporter, r); |
| 945 test_scale(reporter, r); |
| 946 test_dash_fill(reporter, r); |
| 947 test_null_dash(reporter, r); |
| 948 // Test modifying various stroke params. |
| 949 test_stroke_param<SkRect, SkScalar>( |
| 950 reporter, r, |
| 951 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, |
| 952 SkIntToScalar(2), SkIntToScalar(4)); |
| 953 test_stroke_param<SkRect, SkPaint::Join>( |
| 954 reporter, r, |
| 955 [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);}, |
| 956 SkPaint::kMiter_Join, SkPaint::kRound_Join); |
| 957 test_stroke_cap(reporter, r); |
| 958 test_miter_limit(reporter, r); |
| 959 test_path_effect_makes_rrect(reporter, r); |
| 960 test_unknown_path_effect(reporter, r); |
| 961 test_path_effect_makes_empty_shape(reporter, r); |
| 962 test_make_hairline_path_effect(reporter, r, true); |
| 963 } |
898 | 964 |
899 for (auto rr : { SkRRect::MakeRect(SkRect::MakeWH(10, 10)), | 965 for (auto rr : { SkRRect::MakeRect(SkRect::MakeWH(10, 10)), |
900 SkRRect::MakeRectXY(SkRect::MakeWH(10, 10), 3, 4)}) { | 966 SkRRect::MakeRectXY(SkRect::MakeWH(10, 10), 3, 4), |
| 967 SkRRect::MakeOval(SkRect::MakeWH(20, 20))}) { |
901 test_basic(reporter, rr); | 968 test_basic(reporter, rr); |
902 test_scale(reporter, rr); | 969 test_scale(reporter, rr); |
903 test_dash_fill(reporter, rr); | 970 test_dash_fill(reporter, rr); |
904 test_null_dash(reporter, rr); | 971 test_null_dash(reporter, rr); |
905 // Test modifying various stroke params. | 972 // Test modifying various stroke params. |
906 test_stroke_param<SkRRect, SkScalar>( | 973 test_stroke_param<SkRRect, SkScalar>( |
907 reporter, rr, | 974 reporter, rr, |
908 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, | 975 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, |
909 SkIntToScalar(2), SkIntToScalar(4)); | 976 SkIntToScalar(2), SkIntToScalar(4)); |
910 test_stroke_param<SkRRect, SkPaint::Join>( | 977 test_stroke_param<SkRRect, SkPaint::Join>( |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
977 test_stroke_cap(reporter, path); | 1044 test_stroke_cap(reporter, path); |
978 test_miter_limit(reporter, path); | 1045 test_miter_limit(reporter, path); |
979 test_unknown_path_effect(reporter, path); | 1046 test_unknown_path_effect(reporter, path); |
980 test_path_effect_makes_empty_shape(reporter, path); | 1047 test_path_effect_makes_empty_shape(reporter, path); |
981 test_make_hairline_path_effect(reporter, path, testPath.fIsRRectForStrok
e); | 1048 test_make_hairline_path_effect(reporter, path, testPath.fIsRRectForStrok
e); |
982 | 1049 |
983 SkPaint fillPaint; | 1050 SkPaint fillPaint; |
984 TestCase fillPathCase(path, fillPaint, reporter); | 1051 TestCase fillPathCase(path, fillPaint, reporter); |
985 SkRRect rrect; | 1052 SkRRect rrect; |
986 REPORTER_ASSERT(reporter, testPath.fIsRRectForFill == | 1053 REPORTER_ASSERT(reporter, testPath.fIsRRectForFill == |
987 fillPathCase.baseShape().asRRect(&rrect)); | 1054 fillPathCase.baseShape().asRRect(&rrect, nullp
tr, nullptr)); |
988 if (testPath.fIsRRectForFill) { | 1055 if (testPath.fIsRRectForFill) { |
| 1056 TestCase fillPathCase2(path, fillPaint, reporter); |
989 REPORTER_ASSERT(reporter, rrect == testPath.fRRect); | 1057 REPORTER_ASSERT(reporter, rrect == testPath.fRRect); |
990 TestCase fillRRectCase(rrect, fillPaint, reporter); | 1058 TestCase fillRRectCase(rrect, fillPaint, reporter); |
991 fillPathCase.compare(reporter, fillRRectCase, TestCase::kAllSame_Com
parisonExpecation); | 1059 fillPathCase2.compare(reporter, fillRRectCase, TestCase::kAllSame_Co
mparisonExpecation); |
992 } | 1060 } |
993 | 1061 |
994 SkPaint strokePaint; | 1062 SkPaint strokePaint; |
995 strokePaint.setStrokeWidth(3.f); | 1063 strokePaint.setStrokeWidth(3.f); |
996 strokePaint.setStyle(SkPaint::kStroke_Style); | 1064 strokePaint.setStyle(SkPaint::kStroke_Style); |
997 TestCase strokePathCase(path, strokePaint, reporter); | 1065 TestCase strokePathCase(path, strokePaint, reporter); |
998 REPORTER_ASSERT(reporter, testPath.fIsRRectForStroke == | 1066 REPORTER_ASSERT(reporter, testPath.fIsRRectForStroke == |
999 strokePathCase.baseShape().asRRect(&rrect)); | 1067 strokePathCase.baseShape().asRRect(&rrect, nul
lptr, nullptr)); |
1000 if (testPath.fIsRRectForStroke) { | 1068 if (testPath.fIsRRectForStroke) { |
1001 REPORTER_ASSERT(reporter, rrect == testPath.fRRect); | 1069 REPORTER_ASSERT(reporter, rrect == testPath.fRRect); |
1002 TestCase strokeRRectCase(rrect, strokePaint, reporter); | 1070 TestCase strokeRRectCase(rrect, strokePaint, reporter); |
1003 strokePathCase.compare(reporter, strokeRRectCase, | 1071 strokePathCase.compare(reporter, strokeRRectCase, |
1004 TestCase::kAllSame_ComparisonExpecation); | 1072 TestCase::kAllSame_ComparisonExpecation); |
1005 } | 1073 } |
1006 } | 1074 } |
1007 | 1075 |
1008 // Test a volatile empty path. | 1076 // Test a volatile empty path. |
1009 test_volatile_path(reporter, SkPath(), true); | 1077 test_volatile_path(reporter, SkPath(), true); |
1010 | 1078 |
1011 test_empty_shape(reporter); | 1079 test_empty_shape(reporter); |
1012 } | 1080 } |
1013 | 1081 |
1014 #endif | 1082 #endif |
OLD | NEW |