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 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 static const SkScalar kIntervals[] = { 0.25, 3.f, 0.5, 2.f }; | 426 static const SkScalar kIntervals[] = { 0.25, 3.f, 0.5, 2.f }; |
427 static const SkScalar kPhase = 0.75; | 427 static const SkScalar kPhase = 0.75; |
428 return SkDashPathEffect::Make(kIntervals, SK_ARRAY_COUNT(kIntervals), kPhase
); | 428 return SkDashPathEffect::Make(kIntervals, SK_ARRAY_COUNT(kIntervals), kPhase
); |
429 } | 429 } |
430 | 430 |
431 static sk_sp<SkPathEffect> make_null_dash() { | 431 static sk_sp<SkPathEffect> make_null_dash() { |
432 static const SkScalar kNullIntervals[] = {0, 0, 0, 0, 0, 0}; | 432 static const SkScalar kNullIntervals[] = {0, 0, 0, 0, 0, 0}; |
433 return SkDashPathEffect::Make(kNullIntervals, SK_ARRAY_COUNT(kNullIntervals)
, 0.f); | 433 return SkDashPathEffect::Make(kNullIntervals, SK_ARRAY_COUNT(kNullIntervals)
, 0.f); |
434 } | 434 } |
435 | 435 |
| 436 ////////////////////////////////////////////////////////////////////////////// |
| 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 |
436 template<typename GEO> | 506 template<typename GEO> |
437 static void test_basic(skiatest::Reporter* reporter, const GEO& geo) { | 507 static void test_basic(skiatest::Reporter* reporter, const GEO& geo) { |
438 sk_sp<SkPathEffect> dashPE = make_dash(); | 508 sk_sp<SkPathEffect> dashPE = make_dash(); |
439 | 509 |
440 TestCase::SelfExpectations expectations; | 510 TestCase::SelfExpectations expectations; |
441 SkPaint fill; | 511 SkPaint fill; |
442 | 512 |
443 TestCase fillCase(geo, fill, reporter); | 513 TestCase fillCase(geo, fill, reporter); |
444 expectations.fPEHasEffect = false; | 514 expectations.fPEHasEffect = false; |
445 expectations.fPEHasValidKey = false; | 515 expectations.fPEHasValidKey = false; |
446 expectations.fStrokeApplies = false; | 516 expectations.fStrokeApplies = false; |
447 fillCase.testExpectations(reporter, expectations); | 517 fillCase.testExpectations(reporter, expectations); |
448 // Test that another GrShape instance built from the same primitive is the s
ame. | 518 // Test that another GrShape instance built from the same primitive is the s
ame. |
449 TestCase(geo, fill, reporter).compare(reporter, fillCase, | 519 TestCase(geo, fill, reporter).compare(reporter, fillCase, |
450 TestCase::kAllSame_ComparisonExpecatio
n); | 520 TestCase::kAllSame_ComparisonExpecatio
n); |
451 | 521 |
452 SkPaint stroke2RoundBevel; | 522 SkPaint stroke2RoundBevel; |
453 stroke2RoundBevel.setStyle(SkPaint::kStroke_Style); | 523 stroke2RoundBevel.setStyle(SkPaint::kStroke_Style); |
454 stroke2RoundBevel.setStrokeCap(SkPaint::kRound_Cap); | 524 stroke2RoundBevel.setStrokeCap(SkPaint::kRound_Cap); |
455 stroke2RoundBevel.setStrokeJoin(SkPaint::kBevel_Join); | 525 stroke2RoundBevel.setStrokeJoin(SkPaint::kBevel_Join); |
456 stroke2RoundBevel.setStrokeWidth(2.f); | 526 stroke2RoundBevel.setStrokeWidth(2.f); |
457 TestCase stroke2RoundBevelCase(geo, stroke2RoundBevel, reporter); | 527 TestCase stroke2RoundBevelCase(geo, stroke2RoundBevel, reporter); |
458 expectations.fPEHasValidKey = true; | 528 expectations.fPEHasValidKey = true; |
459 expectations.fPEHasEffect = false; | 529 expectations.fPEHasEffect = false; |
460 expectations.fStrokeApplies = true; | 530 expectations.fStrokeApplies = !stroke_is_converted_to_fill(geo); |
461 stroke2RoundBevelCase.testExpectations(reporter, expectations); | 531 stroke2RoundBevelCase.testExpectations(reporter, expectations); |
462 TestCase(geo, stroke2RoundBevel, reporter).compare(reporter, stroke2RoundBev
elCase, | 532 TestCase(geo, stroke2RoundBevel, reporter).compare(reporter, stroke2RoundBev
elCase, |
463 TestCase::kAllSame_Compar
isonExpecation); | 533 TestCase::kAllSame_Compar
isonExpecation); |
464 | 534 |
465 SkPaint stroke2RoundBevelDash = stroke2RoundBevel; | 535 SkPaint stroke2RoundBevelDash = stroke2RoundBevel; |
466 stroke2RoundBevelDash.setPathEffect(make_dash()); | 536 stroke2RoundBevelDash.setPathEffect(make_dash()); |
467 TestCase stroke2RoundBevelDashCase(geo, stroke2RoundBevelDash, reporter); | 537 TestCase stroke2RoundBevelDashCase(geo, stroke2RoundBevelDash, reporter); |
468 expectations.fPEHasValidKey = true; | 538 expectations.fPEHasValidKey = true; |
469 expectations.fPEHasEffect = true; | 539 expectations.fPEHasEffect = true; |
470 expectations.fStrokeApplies = true; | 540 expectations.fStrokeApplies = true; |
471 stroke2RoundBevelDashCase.testExpectations(reporter, expectations); | 541 stroke2RoundBevelDashCase.testExpectations(reporter, expectations); |
472 TestCase(geo, stroke2RoundBevelDash, reporter).compare(reporter, stroke2Roun
dBevelDashCase, | 542 TestCase(geo, stroke2RoundBevelDash, reporter).compare(reporter, stroke2Roun
dBevelDashCase, |
473 TestCase::kAllSame_Co
mparisonExpecation); | 543 TestCase::kAllSame_Co
mparisonExpecation); |
474 | 544 |
475 fillCase.compare(reporter, stroke2RoundBevelCase, | 545 if (fill_changes_geom(geo) || stroke_is_converted_to_fill(geo)) { |
476 TestCase::kSameUpToStroke_ComparisonExpecation); | 546 fillCase.compare(reporter, stroke2RoundBevelCase, |
477 fillCase.compare(reporter, stroke2RoundBevelDashCase, | 547 TestCase::kAllDifferent_ComparisonExpecation); |
478 TestCase::kSameUpToPE_ComparisonExpecation); | 548 fillCase.compare(reporter, stroke2RoundBevelDashCase, |
479 stroke2RoundBevelCase.compare(reporter, stroke2RoundBevelDashCase, | 549 TestCase::kAllDifferent_ComparisonExpecation); |
480 TestCase::kSameUpToPE_ComparisonExpecation); | 550 } else { |
| 551 fillCase.compare(reporter, stroke2RoundBevelCase, |
| 552 TestCase::kSameUpToStroke_ComparisonExpecation); |
| 553 fillCase.compare(reporter, stroke2RoundBevelDashCase, |
| 554 TestCase::kSameUpToPE_ComparisonExpecation); |
| 555 } |
| 556 if (stroke_is_converted_to_fill(geo)) { |
| 557 stroke2RoundBevelCase.compare(reporter, stroke2RoundBevelDashCase, |
| 558 TestCase::kAllDifferent_ComparisonExpecati
on); |
| 559 } else { |
| 560 stroke2RoundBevelCase.compare(reporter, stroke2RoundBevelDashCase, |
| 561 TestCase::kSameUpToPE_ComparisonExpecation
); |
| 562 } |
481 | 563 |
482 // Stroke and fill cases | 564 // Stroke and fill cases |
483 SkPaint stroke2RoundBevelAndFill = stroke2RoundBevel; | 565 SkPaint stroke2RoundBevelAndFill = stroke2RoundBevel; |
484 stroke2RoundBevelAndFill.setStyle(SkPaint::kStrokeAndFill_Style); | 566 stroke2RoundBevelAndFill.setStyle(SkPaint::kStrokeAndFill_Style); |
485 TestCase stroke2RoundBevelAndFillCase(geo, stroke2RoundBevelAndFill, reporte
r); | 567 TestCase stroke2RoundBevelAndFillCase(geo, stroke2RoundBevelAndFill, reporte
r); |
486 expectations.fPEHasValidKey = true; | 568 expectations.fPEHasValidKey = true; |
487 expectations.fPEHasEffect = false; | 569 expectations.fPEHasEffect = false; |
488 expectations.fStrokeApplies = true; | 570 expectations.fStrokeApplies = !stroke_is_converted_to_fill(geo); |
489 stroke2RoundBevelAndFillCase.testExpectations(reporter, expectations); | 571 stroke2RoundBevelAndFillCase.testExpectations(reporter, expectations); |
490 TestCase(geo, stroke2RoundBevelAndFill, reporter).compare(reporter, | 572 TestCase(geo, stroke2RoundBevelAndFill, reporter).compare(reporter, |
491 stroke2RoundBevelAndFillCase, TestCase::kAllSame_ComparisonExpecatio
n); | 573 stroke2RoundBevelAndFillCase, TestCase::kAllSame_ComparisonExpecatio
n); |
492 | 574 |
493 SkPaint stroke2RoundBevelAndFillDash = stroke2RoundBevelDash; | 575 SkPaint stroke2RoundBevelAndFillDash = stroke2RoundBevelDash; |
494 stroke2RoundBevelAndFillDash.setStyle(SkPaint::kStrokeAndFill_Style); | 576 stroke2RoundBevelAndFillDash.setStyle(SkPaint::kStrokeAndFill_Style); |
495 TestCase stroke2RoundBevelAndFillDashCase(geo, stroke2RoundBevelAndFillDash,
reporter); | 577 TestCase stroke2RoundBevelAndFillDashCase(geo, stroke2RoundBevelAndFillDash,
reporter); |
496 expectations.fPEHasValidKey = true; | 578 expectations.fPEHasValidKey = true; |
497 expectations.fPEHasEffect = false; | 579 expectations.fPEHasEffect = false; |
498 expectations.fStrokeApplies = true; | 580 expectations.fStrokeApplies = !stroke_is_converted_to_fill(geo); |
499 stroke2RoundBevelAndFillDashCase.testExpectations(reporter, expectations); | 581 stroke2RoundBevelAndFillDashCase.testExpectations(reporter, expectations); |
500 TestCase(geo, stroke2RoundBevelAndFillDash, reporter).compare( | 582 TestCase(geo, stroke2RoundBevelAndFillDash, reporter).compare( |
501 reporter, stroke2RoundBevelAndFillDashCase, TestCase::kAllSame_Compariso
nExpecation); | 583 reporter, stroke2RoundBevelAndFillDashCase, TestCase::kAllSame_Compariso
nExpecation); |
502 stroke2RoundBevelAndFillDashCase.compare(reporter, stroke2RoundBevelAndFillC
ase, | 584 stroke2RoundBevelAndFillDashCase.compare(reporter, stroke2RoundBevelAndFillC
ase, |
503 TestCase::kAllSame_ComparisonExpeca
tion); | 585 TestCase::kAllSame_ComparisonExpeca
tion); |
504 | 586 |
505 SkPaint hairline; | 587 SkPaint hairline; |
506 hairline.setStyle(SkPaint::kStroke_Style); | 588 hairline.setStyle(SkPaint::kStroke_Style); |
507 hairline.setStrokeWidth(0.f); | 589 hairline.setStrokeWidth(0.f); |
508 TestCase hairlineCase(geo, hairline, reporter); | 590 TestCase hairlineCase(geo, hairline, reporter); |
509 // Since hairline style doesn't change the SkPath data, it is keyed identica
lly to fill. | 591 // Since hairline style doesn't change the SkPath data, it is keyed identica
lly to fill (except |
510 hairlineCase.compare(reporter, fillCase, TestCase::kAllSame_ComparisonExpeca
tion); | 592 // in the line and unclosed rect cases). |
| 593 if (fill_changes_geom(geo)) { |
| 594 hairlineCase.compare(reporter, fillCase, TestCase::kAllDifferent_Compari
sonExpecation); |
| 595 } else { |
| 596 hairlineCase.compare(reporter, fillCase, TestCase::kAllSame_ComparisonEx
pecation); |
| 597 } |
511 REPORTER_ASSERT(reporter, hairlineCase.baseShape().style().isSimpleHairline(
)); | 598 REPORTER_ASSERT(reporter, hairlineCase.baseShape().style().isSimpleHairline(
)); |
512 REPORTER_ASSERT(reporter, hairlineCase.appliedFullStyleShape().style().isSim
pleHairline()); | 599 REPORTER_ASSERT(reporter, hairlineCase.appliedFullStyleShape().style().isSim
pleHairline()); |
513 REPORTER_ASSERT(reporter, hairlineCase.appliedPathEffectShape().style().isSi
mpleHairline()); | 600 REPORTER_ASSERT(reporter, hairlineCase.appliedPathEffectShape().style().isSi
mpleHairline()); |
514 } | |
515 | 601 |
516 // Was the shape pre-style geometry stored as something other than a general pat
h. This somewhat | |
517 // relies on knowing the internals of GrShape to know that this combination of t
ests is sufficient. | |
518 static bool is_non_path(const GrShape& shape) { | |
519 return shape.asRRect(nullptr, nullptr, nullptr, nullptr) || shape.asLine(nul
lptr, nullptr) || | |
520 shape.isEmpty(); | |
521 } | 602 } |
522 | 603 |
523 template<typename GEO> | 604 template<typename GEO> |
524 static void test_scale(skiatest::Reporter* reporter, const GEO& geo) { | 605 static void test_scale(skiatest::Reporter* reporter, const GEO& geo) { |
525 sk_sp<SkPathEffect> dashPE = make_dash(); | 606 sk_sp<SkPathEffect> dashPE = make_dash(); |
526 | 607 |
527 static const SkScalar kS1 = 1.f; | 608 static const SkScalar kS1 = 1.f; |
528 static const SkScalar kS2 = 2.f; | 609 static const SkScalar kS2 = 2.f; |
529 | 610 |
530 // Scale may affect the key for stroked results. However, there are two ways
in which that may | |
531 // not occur. The base shape may instantly recognized that the geo + stroke
is equivalent to | |
532 // a simple filled geometry. An example is a stroked line may become a fille
d rrect. | |
533 // Alternatively, after applying the style the output path may be recognized
as a simpler shape | |
534 // causing the shape with style applied to have a purely geometric key rathe
r than a key derived | |
535 // from the base geometry and the style params (and scale factor). | |
536 auto wasSimplified = [](const TestCase& c) { | |
537 return !c.baseShape().style().applies() || is_non_path(c.appliedFullStyl
eShape()); | |
538 }; | |
539 SkPaint fill; | 611 SkPaint fill; |
540 TestCase fillCase1(geo, fill, reporter, kS1); | 612 TestCase fillCase1(geo, fill, reporter, kS1); |
541 TestCase fillCase2(geo, fill, reporter, kS2); | 613 TestCase fillCase2(geo, fill, reporter, kS2); |
542 // Scale doesn't affect fills. | 614 // Scale doesn't affect fills. |
543 fillCase1.compare(reporter, fillCase2, TestCase::kAllSame_ComparisonExpecati
on); | 615 fillCase1.compare(reporter, fillCase2, TestCase::kAllSame_ComparisonExpecati
on); |
544 | 616 |
545 SkPaint hairline; | 617 SkPaint hairline; |
546 hairline.setStyle(SkPaint::kStroke_Style); | 618 hairline.setStyle(SkPaint::kStroke_Style); |
547 hairline.setStrokeWidth(0.f); | 619 hairline.setStrokeWidth(0.f); |
548 TestCase hairlineCase1(geo, hairline, reporter, kS1); | 620 TestCase hairlineCase1(geo, hairline, reporter, kS1); |
549 TestCase hairlineCase2(geo, hairline, reporter, kS2); | 621 TestCase hairlineCase2(geo, hairline, reporter, kS2); |
550 // Scale doesn't affect hairlines. | 622 // Scale doesn't affect hairlines. |
551 hairlineCase1.compare(reporter, hairlineCase2, TestCase::kAllSame_Comparison
Expecation); | 623 hairlineCase1.compare(reporter, hairlineCase2, TestCase::kAllSame_Comparison
Expecation); |
552 | 624 |
553 SkPaint stroke; | 625 SkPaint stroke; |
554 stroke.setStyle(SkPaint::kStroke_Style); | 626 stroke.setStyle(SkPaint::kStroke_Style); |
555 stroke.setStrokeWidth(2.f); | 627 stroke.setStrokeWidth(2.f); |
556 TestCase strokeCase1(geo, stroke, reporter, kS1); | 628 TestCase strokeCase1(geo, stroke, reporter, kS1); |
557 TestCase strokeCase2(geo, stroke, reporter, kS2); | 629 TestCase strokeCase2(geo, stroke, reporter, kS2); |
558 // Scale affects the stroke | 630 // Scale affects the stroke |
559 if (wasSimplified(strokeCase1)) { | 631 if (stroke_is_converted_to_fill(geo)) { |
560 REPORTER_ASSERT(reporter, wasSimplified(strokeCase2)); | 632 REPORTER_ASSERT(reporter, !strokeCase1.baseShape().style().applies()); |
561 strokeCase1.compare(reporter, strokeCase2, TestCase::kAllSame_Comparison
Expecation); | 633 strokeCase1.compare(reporter, strokeCase2, TestCase::kAllSame_Comparison
Expecation); |
562 } else { | 634 } else { |
563 strokeCase1.compare(reporter, strokeCase2, TestCase::kSameUpToStroke_Com
parisonExpecation); | 635 strokeCase1.compare(reporter, strokeCase2, TestCase::kSameUpToStroke_Com
parisonExpecation); |
564 } | 636 } |
565 | 637 |
566 SkPaint strokeDash = stroke; | 638 SkPaint strokeDash = stroke; |
567 strokeDash.setPathEffect(make_dash()); | 639 strokeDash.setPathEffect(make_dash()); |
568 TestCase strokeDashCase1(geo, strokeDash, reporter, kS1); | 640 TestCase strokeDashCase1(geo, strokeDash, reporter, kS1); |
569 TestCase strokeDashCase2(geo, strokeDash, reporter, kS2); | 641 TestCase strokeDashCase2(geo, strokeDash, reporter, kS2); |
570 // Scale affects the dash and the stroke. | 642 // Scale affects the dash and the stroke. |
571 if (wasSimplified(strokeDashCase1)) { | 643 strokeDashCase1.compare(reporter, strokeDashCase2, |
572 REPORTER_ASSERT(reporter, wasSimplified(strokeDashCase2)); | 644 TestCase::kSameUpToPE_ComparisonExpecation); |
573 strokeDashCase1.compare(reporter, strokeDashCase2, | |
574 TestCase::kAllSame_ComparisonExpecation); | |
575 } else { | |
576 strokeDashCase1.compare(reporter, strokeDashCase2, | |
577 TestCase::kSameUpToPE_ComparisonExpecation); | |
578 } | |
579 | 645 |
580 // Stroke and fill cases | 646 // Stroke and fill cases |
581 SkPaint strokeAndFill = stroke; | 647 SkPaint strokeAndFill = stroke; |
582 strokeAndFill.setStyle(SkPaint::kStrokeAndFill_Style); | 648 strokeAndFill.setStyle(SkPaint::kStrokeAndFill_Style); |
583 TestCase strokeAndFillCase1(geo, strokeAndFill, reporter, kS1); | 649 TestCase strokeAndFillCase1(geo, strokeAndFill, reporter, kS1); |
584 TestCase strokeAndFillCase2(geo, strokeAndFill, reporter, kS2); | 650 TestCase strokeAndFillCase2(geo, strokeAndFill, reporter, kS2); |
585 SkPaint strokeAndFillDash = strokeDash; | 651 SkPaint strokeAndFillDash = strokeDash; |
586 strokeAndFillDash.setStyle(SkPaint::kStrokeAndFill_Style); | 652 strokeAndFillDash.setStyle(SkPaint::kStrokeAndFill_Style); |
587 // Dash is ignored for stroke and fill | 653 // Dash is ignored for stroke and fill |
588 TestCase strokeAndFillDashCase1(geo, strokeAndFillDash, reporter, kS1); | 654 TestCase strokeAndFillDashCase1(geo, strokeAndFillDash, reporter, kS1); |
589 TestCase strokeAndFillDashCase2(geo, strokeAndFillDash, reporter, kS2); | 655 TestCase strokeAndFillDashCase2(geo, strokeAndFillDash, reporter, kS2); |
590 // Scale affects the stroke. Scale affects the stroke, but check to make sur
e this didn't | 656 // Scale affects the stroke, but check to make sure this didn't become a sim
pler shape (e.g. |
591 // become a simpler shape (e.g. stroke-and-filled rect can become a rect), i
n which case the | 657 // stroke-and-filled rect can become a rect), in which case the scale should
n't matter and the |
592 // scale shouldn't matter and the geometries should agree. | 658 // geometries should agree. |
593 if (wasSimplified(strokeAndFillCase1)) { | 659 if (stroke_and_fill_is_converted_to_fill(geo, strokeAndFillDash)) { |
594 REPORTER_ASSERT(reporter, wasSimplified(strokeAndFillCase1)); | 660 REPORTER_ASSERT(reporter, !strokeAndFillCase1.baseShape().style().applie
s()); |
595 REPORTER_ASSERT(reporter, wasSimplified(strokeAndFillDashCase1)); | |
596 REPORTER_ASSERT(reporter, wasSimplified(strokeAndFillDashCase2)); | |
597 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, | 661 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, |
598 TestCase::kAllSame_ComparisonExpecation); | 662 TestCase::kAllSame_ComparisonExpecation); |
599 strokeAndFillDashCase1.compare(reporter, strokeAndFillDashCase2, | 663 strokeAndFillDashCase1.compare(reporter, strokeAndFillDashCase2, |
600 TestCase::kAllSame_ComparisonExpecation); | 664 TestCase::kAllSame_ComparisonExpecation); |
601 } else { | 665 } else { |
602 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, | 666 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, |
603 TestCase::kSameUpToStroke_ComparisonExpecatio
n); | 667 TestCase::kSameUpToStroke_ComparisonExpecatio
n); |
604 } | 668 } |
605 strokeAndFillDashCase1.compare(reporter, strokeAndFillCase1, | 669 strokeAndFillDashCase1.compare(reporter, strokeAndFillCase1, |
606 TestCase::kAllSame_ComparisonExpecation); | 670 TestCase::kAllSame_ComparisonExpecation); |
(...skipping 15 matching lines...) Expand all Loading... |
622 SkPaint strokeB; | 686 SkPaint strokeB; |
623 strokeB.setStyle(SkPaint::kStroke_Style); | 687 strokeB.setStyle(SkPaint::kStroke_Style); |
624 strokeB.setStrokeWidth(2.f); | 688 strokeB.setStrokeWidth(2.f); |
625 setter(&strokeB, b); | 689 setter(&strokeB, b); |
626 | 690 |
627 TestCase strokeACase(geo, strokeA, reporter); | 691 TestCase strokeACase(geo, strokeA, reporter); |
628 TestCase strokeBCase(geo, strokeB, reporter); | 692 TestCase strokeBCase(geo, strokeB, reporter); |
629 if (paramAffectsStroke) { | 693 if (paramAffectsStroke) { |
630 // If stroking is immediately incorporated into a geometric transformati
on then the base | 694 // If stroking is immediately incorporated into a geometric transformati
on then the base |
631 // shapes will differ. | 695 // shapes will differ. |
632 if (strokeACase.baseShape().style().applies()) { | 696 if (stroke_is_converted_to_fill(geo)) { |
| 697 strokeACase.compare(reporter, strokeBCase, |
| 698 TestCase::kAllDifferent_ComparisonExpecation); |
| 699 } else { |
633 strokeACase.compare(reporter, strokeBCase, | 700 strokeACase.compare(reporter, strokeBCase, |
634 TestCase::kSameUpToStroke_ComparisonExpecation); | 701 TestCase::kSameUpToStroke_ComparisonExpecation); |
635 } else { | |
636 strokeACase.compare(reporter, strokeBCase, | |
637 TestCase::kAllDifferent_ComparisonExpecation); | |
638 } | 702 } |
639 } else { | 703 } else { |
640 strokeACase.compare(reporter, strokeBCase, TestCase::kAllSame_Comparison
Expecation); | 704 strokeACase.compare(reporter, strokeBCase, TestCase::kAllSame_Comparison
Expecation); |
641 } | 705 } |
642 | 706 |
643 SkPaint strokeAndFillA = strokeA; | 707 SkPaint strokeAndFillA = strokeA; |
644 SkPaint strokeAndFillB = strokeB; | 708 SkPaint strokeAndFillB = strokeB; |
645 strokeAndFillA.setStyle(SkPaint::kStrokeAndFill_Style); | 709 strokeAndFillA.setStyle(SkPaint::kStrokeAndFill_Style); |
646 strokeAndFillB.setStyle(SkPaint::kStrokeAndFill_Style); | 710 strokeAndFillB.setStyle(SkPaint::kStrokeAndFill_Style); |
647 TestCase strokeAndFillACase(geo, strokeAndFillA, reporter); | 711 TestCase strokeAndFillACase(geo, strokeAndFillA, reporter); |
648 TestCase strokeAndFillBCase(geo, strokeAndFillB, reporter); | 712 TestCase strokeAndFillBCase(geo, strokeAndFillB, reporter); |
649 if (paramAffectsStroke) { | 713 if (paramAffectsStroke) { |
650 // If stroking is immediately incorporated into a geometric transformati
on then the base | 714 // If stroking is immediately incorporated into a geometric transformati
on then the base |
651 // shapes will differ. | 715 // shapes will differ. |
652 if (strokeAndFillACase.baseShape().style().applies()) { | 716 if (stroke_and_fill_is_converted_to_fill(geo, strokeAndFillA) || |
| 717 stroke_and_fill_is_converted_to_fill(geo, strokeAndFillB)) { |
653 strokeAndFillACase.compare(reporter, strokeAndFillBCase, | 718 strokeAndFillACase.compare(reporter, strokeAndFillBCase, |
654 TestCase::kSameUpToStroke_ComparisonExpecation); | 719 TestCase::kAllDifferent_ComparisonExpecat
ion); |
655 } else { | 720 } else { |
656 strokeAndFillACase.compare(reporter, strokeAndFillBCase, | 721 strokeAndFillACase.compare(reporter, strokeAndFillBCase, |
657 TestCase::kAllDifferent_ComparisonExpecation); | 722 TestCase::kSameUpToStroke_ComparisonExpec
ation); |
658 } | 723 } |
659 } else { | 724 } else { |
660 strokeAndFillACase.compare(reporter, strokeAndFillBCase, | 725 strokeAndFillACase.compare(reporter, strokeAndFillBCase, |
661 TestCase::kAllSame_ComparisonExpecation); | 726 TestCase::kAllSame_ComparisonExpecation); |
662 } | 727 } |
663 | 728 |
664 // Make sure stroking params don't affect fill style. | 729 // Make sure stroking params don't affect fill style. |
665 SkPaint fillA = strokeA, fillB = strokeB; | 730 SkPaint fillA = strokeA, fillB = strokeB; |
666 fillA.setStyle(SkPaint::kFill_Style); | 731 fillA.setStyle(SkPaint::kFill_Style); |
667 fillB.setStyle(SkPaint::kFill_Style); | 732 fillB.setStyle(SkPaint::kFill_Style); |
668 TestCase fillACase(geo, fillA, reporter); | 733 TestCase fillACase(geo, fillA, reporter); |
669 TestCase fillBCase(geo, fillB, reporter); | 734 TestCase fillBCase(geo, fillB, reporter); |
670 fillACase.compare(reporter, fillBCase, TestCase::kAllSame_ComparisonExpecati
on); | 735 fillACase.compare(reporter, fillBCase, TestCase::kAllSame_ComparisonExpecati
on); |
671 | 736 |
672 // Make sure just applying the dash but not stroke gives the same key for bo
th stroking | 737 // Make sure just applying the dash but not stroke gives the same key for bo
th stroking |
673 // variations. | 738 // variations. |
674 SkPaint dashA = strokeA, dashB = strokeB; | 739 SkPaint dashA = strokeA, dashB = strokeB; |
675 dashA.setPathEffect(make_dash()); | 740 dashA.setPathEffect(make_dash()); |
676 dashB.setPathEffect(make_dash()); | 741 dashB.setPathEffect(make_dash()); |
677 TestCase dashACase(geo, dashA, reporter); | 742 TestCase dashACase(geo, dashA, reporter); |
678 TestCase dashBCase(geo, dashB, reporter); | 743 TestCase dashBCase(geo, dashB, reporter); |
679 if (paramAffectsDashAndStroke) { | 744 if (paramAffectsDashAndStroke) { |
680 // If stroking is immediately incorporated into a geometric transformati
on then the base | 745 dashACase.compare(reporter, dashBCase, TestCase::kSameUpToStroke_Compari
sonExpecation); |
681 // shapes will differ. | |
682 if (dashACase.baseShape().style().applies()) { | |
683 dashACase.compare(reporter, dashBCase, TestCase::kSameUpToStroke_Com
parisonExpecation); | |
684 } else { | |
685 dashACase.compare(reporter, dashBCase, TestCase::kAllDifferent_Compa
risonExpecation); | |
686 } | |
687 } else { | 746 } else { |
688 dashACase.compare(reporter, dashBCase, TestCase::kAllSame_ComparisonExpe
cation); | 747 dashACase.compare(reporter, dashBCase, TestCase::kAllSame_ComparisonExpe
cation); |
689 } | 748 } |
690 } | 749 } |
691 | 750 |
692 template <typename GEO, typename T> | 751 template <typename GEO, typename T> |
693 static void test_stroke_param(skiatest::Reporter* reporter, const GEO& geo, | 752 static void test_stroke_param(skiatest::Reporter* reporter, const GEO& geo, |
694 std::function<void(SkPaint*, T)> setter, T a, T b)
{ | 753 std::function<void(SkPaint*, T)> setter, T a, T b)
{ |
695 test_stroke_param_impl(reporter, geo, setter, a, b, true, true); | 754 test_stroke_param_impl(reporter, geo, setter, a, b, true, true); |
696 }; | 755 }; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 SkPaint nullDash; | 853 SkPaint nullDash; |
795 nullDash.setStyle(SkPaint::kStroke_Style); | 854 nullDash.setStyle(SkPaint::kStroke_Style); |
796 nullDash.setStrokeWidth(1.f); | 855 nullDash.setStrokeWidth(1.f); |
797 nullDash.setPathEffect(make_null_dash()); | 856 nullDash.setPathEffect(make_null_dash()); |
798 | 857 |
799 TestCase fillCase(geo, fill, reporter); | 858 TestCase fillCase(geo, fill, reporter); |
800 TestCase strokeCase(geo, stroke, reporter); | 859 TestCase strokeCase(geo, stroke, reporter); |
801 TestCase dashCase(geo, dash, reporter); | 860 TestCase dashCase(geo, dash, reporter); |
802 TestCase nullDashCase(geo, nullDash, reporter); | 861 TestCase nullDashCase(geo, nullDash, reporter); |
803 | 862 |
804 nullDashCase.compare(reporter, fillCase, TestCase::kSameUpToStroke_Compariso
nExpecation); | 863 // We expect the null dash to be ignored so nullDashCase should match stroke
Case, always. |
805 nullDashCase.compare(reporter, strokeCase, TestCase::kAllSame_ComparisonExpe
cation); | 864 nullDashCase.compare(reporter, strokeCase, TestCase::kAllSame_ComparisonExpe
cation); |
806 nullDashCase.compare(reporter, dashCase, TestCase::kSameUpToPE_ComparisonExp
ecation); | 865 // 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. |
| 867 if (fill_changes_geom(geo) || stroke_is_converted_to_fill(geo)) { |
| 868 nullDashCase.compare(reporter, fillCase, TestCase::kAllDifferent_Compari
sonExpecation); |
| 869 } else { |
| 870 nullDashCase.compare(reporter, fillCase, TestCase::kSameUpToStroke_Compa
risonExpecation); |
| 871 } |
| 872 // 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)) { |
| 874 nullDashCase.compare(reporter, dashCase, TestCase::kAllDifferent_Compari
sonExpecation); |
| 875 } else { |
| 876 nullDashCase.compare(reporter, dashCase, TestCase::kSameUpToPE_Compariso
nExpecation); |
| 877 } |
807 } | 878 } |
808 | 879 |
809 template <typename GEO> | 880 template <typename GEO> |
810 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)
{ |
811 /** | 882 /** |
812 * This path effect takes any input path and turns it into a rrect. It passe
s through stroke | 883 * This path effect takes any input path and turns it into a rrect. It passe
s through stroke |
813 * info. | 884 * info. |
814 */ | 885 */ |
815 class RRectPathEffect : SkPathEffect { | 886 class RRectPathEffect : SkPathEffect { |
816 public: | 887 public: |
(...skipping 24 matching lines...) Expand all Loading... |
841 SkPaint pe; | 912 SkPaint pe; |
842 pe.setPathEffect(RRectPathEffect::Make()); | 913 pe.setPathEffect(RRectPathEffect::Make()); |
843 TestCase geoPECase(geo, pe, reporter); | 914 TestCase geoPECase(geo, pe, reporter); |
844 | 915 |
845 SkPaint peStroke; | 916 SkPaint peStroke; |
846 peStroke.setPathEffect(RRectPathEffect::Make()); | 917 peStroke.setPathEffect(RRectPathEffect::Make()); |
847 peStroke.setStrokeWidth(2.f); | 918 peStroke.setStrokeWidth(2.f); |
848 peStroke.setStyle(SkPaint::kStroke_Style); | 919 peStroke.setStyle(SkPaint::kStroke_Style); |
849 TestCase geoPEStrokeCase(geo, peStroke, reporter); | 920 TestCase geoPEStrokeCase(geo, peStroke, reporter); |
850 | 921 |
851 fillGeoCase.compare(reporter, geoPECase, TestCase::kSameUpToPE_ComparisonExp
ecation); | 922 // Check whether constructing the filled case would cause the base shape to
have a different |
852 fillGeoCase.compare(reporter, geoPEStrokeCase, TestCase::kSameUpToPE_Compari
sonExpecation); | 923 // geometry (because of a geometric transformation upon initial GrShape cons
truction). |
| 924 if (fill_changes_geom(geo)) { |
| 925 fillGeoCase.compare(reporter, geoPECase, TestCase::kAllDifferent_Compari
sonExpecation); |
| 926 fillGeoCase.compare(reporter, geoPEStrokeCase, |
| 927 TestCase::kAllDifferent_ComparisonExpecation); |
| 928 } else { |
| 929 fillGeoCase.compare(reporter, geoPECase, TestCase::kSameUpToPE_Compariso
nExpecation); |
| 930 fillGeoCase.compare(reporter, geoPEStrokeCase, TestCase::kSameUpToPE_Com
parisonExpecation); |
| 931 } |
853 geoPECase.compare(reporter, geoPEStrokeCase, | 932 geoPECase.compare(reporter, geoPEStrokeCase, |
854 TestCase::kSameUpToStroke_ComparisonExpecation); | 933 TestCase::kSameUpToStroke_ComparisonExpecation); |
855 | 934 |
856 TestCase rrectFillCase(RRectPathEffect::RRect(), fill, reporter); | 935 TestCase rrectFillCase(RRectPathEffect::RRect(), fill, reporter); |
857 SkPaint stroke = peStroke; | 936 SkPaint stroke = peStroke; |
858 stroke.setPathEffect(nullptr); | 937 stroke.setPathEffect(nullptr); |
859 TestCase rrectStrokeCase(RRectPathEffect::RRect(), stroke, reporter); | 938 TestCase rrectStrokeCase(RRectPathEffect::RRect(), stroke, reporter); |
860 | 939 |
861 SkRRect rrect; | 940 SkRRect rrect; |
862 // Applying the path effect should make a SkRRect shape. There is no further
stroking in the | 941 // Applying the path effect should make a SkRRect shape. There is no further
stroking in the |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1190 kStrokeAndFill | 1269 kStrokeAndFill |
1191 }; | 1270 }; |
1192 | 1271 |
1193 // SkStrokeRec has no default cons., so init with kFill before calling the s
etters below. | 1272 // SkStrokeRec has no default cons., so init with kFill before calling the s
etters below. |
1194 SkStrokeRec strokeRecs[4] { SkStrokeRec::kFill_InitStyle, SkStrokeRec::kFill
_InitStyle, | 1273 SkStrokeRec strokeRecs[4] { SkStrokeRec::kFill_InitStyle, SkStrokeRec::kFill
_InitStyle, |
1195 SkStrokeRec::kFill_InitStyle, SkStrokeRec::kFill
_InitStyle}; | 1274 SkStrokeRec::kFill_InitStyle, SkStrokeRec::kFill
_InitStyle}; |
1196 strokeRecs[kFill].setFillStyle(); | 1275 strokeRecs[kFill].setFillStyle(); |
1197 strokeRecs[kStroke].setStrokeStyle(2.f); | 1276 strokeRecs[kStroke].setStrokeStyle(2.f); |
1198 strokeRecs[kHairline].setHairlineStyle(); | 1277 strokeRecs[kHairline].setHairlineStyle(); |
1199 strokeRecs[kStrokeAndFill].setStrokeStyle(3.f, true); | 1278 strokeRecs[kStrokeAndFill].setStrokeStyle(3.f, true); |
| 1279 // Use a bevel join to avoid complications of stroke+filled rects becoming f
illed rects before |
| 1280 // applyStyle() is called. |
| 1281 strokeRecs[kStrokeAndFill].setStrokeParams(SkPaint::kButt_Cap, SkPaint::kBev
el_Join, 1.f); |
1200 sk_sp<SkPathEffect> dashEffect = make_dash(); | 1282 sk_sp<SkPathEffect> dashEffect = make_dash(); |
1201 | 1283 |
1202 static constexpr Style kStyleCnt = static_cast<Style>(SK_ARRAY_COUNT(strokeR
ecs)); | 1284 static constexpr Style kStyleCnt = static_cast<Style>(SK_ARRAY_COUNT(strokeR
ecs)); |
1203 | 1285 |
1204 auto index = [](bool inverted, | 1286 auto index = [](bool inverted, |
1205 SkPath::Direction dir, | 1287 SkPath::Direction dir, |
1206 unsigned start, | 1288 unsigned start, |
1207 Style style, | 1289 Style style, |
1208 bool dash) -> int { | 1290 bool dash) -> int { |
1209 return inverted * (2 * 8 * kStyleCnt * 2) + | 1291 return inverted * (2 * 8 * kStyleCnt * 2) + |
(...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1691 for (bool inverseFill : {false, true}) { | 1773 for (bool inverseFill : {false, true}) { |
1692 if (inverseFill) { | 1774 if (inverseFill) { |
1693 if (testPath.fPath.getFillType() == SkPath::kEvenOdd_FillType) { | 1775 if (testPath.fPath.getFillType() == SkPath::kEvenOdd_FillType) { |
1694 testPath.fPath.setFillType(SkPath::kInverseEvenOdd_FillType)
; | 1776 testPath.fPath.setFillType(SkPath::kInverseEvenOdd_FillType)
; |
1695 } else { | 1777 } else { |
1696 SkASSERT(testPath.fPath.getFillType() == SkPath::kWinding_Fi
llType); | 1778 SkASSERT(testPath.fPath.getFillType() == SkPath::kWinding_Fi
llType); |
1697 testPath.fPath.setFillType(SkPath::kInverseWinding_FillType)
; | 1779 testPath.fPath.setFillType(SkPath::kInverseWinding_FillType)
; |
1698 } | 1780 } |
1699 } | 1781 } |
1700 const SkPath& path = testPath.fPath; | 1782 const SkPath& path = testPath.fPath; |
1701 // These tests all assume that the original GrShape for fill and str
oke will be the | 1783 test_basic(reporter, path); |
1702 // same. | 1784 test_null_dash(reporter, path); |
1703 // However, that is not the case in special cases (e.g. an unclosed
rect becomes a RRect | 1785 test_path_effect_makes_rrect(reporter, path); |
1704 // GrShape with a fill style but becomes a Path GrShape when stroked
). Similarly, a path | |
1705 // that is a line becomes empty when filled but is special-cased as
a line when stroked. | |
1706 if (testPath.fIsRRectForFill == testPath.fIsRRectForStroke && !testP
ath.fIsLine) { | |
1707 test_basic(reporter, path); | |
1708 test_null_dash(reporter, path); | |
1709 test_path_effect_makes_rrect(reporter, path); | |
1710 } | |
1711 test_scale(reporter, path); | 1786 test_scale(reporter, path); |
1712 // This test uses a stroking paint, hence use of fIsRRectForStroke | 1787 // This test uses a stroking paint, hence use of fIsRRectForStroke |
1713 test_volatile_path(reporter, path, testPath.fIsRRectForStroke || tes
tPath.fIsLine); | 1788 test_volatile_path(reporter, path, testPath.fIsRRectForStroke || tes
tPath.fIsLine); |
1714 test_dash_fill(reporter, path); | 1789 test_dash_fill(reporter, path); |
1715 // Test modifying various stroke params. | 1790 // Test modifying various stroke params. |
1716 test_stroke_param<SkPath, SkScalar>( | 1791 test_stroke_param<SkPath, SkScalar>( |
1717 reporter, path, | 1792 reporter, path, |
1718 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, | 1793 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, |
1719 SkIntToScalar(2), SkIntToScalar(4)); | 1794 SkIntToScalar(2), SkIntToScalar(4)); |
1720 test_stroke_join(reporter, path); | 1795 test_stroke_join(reporter, path); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1765 test_volatile_path(reporter, SkPath(), true); | 1840 test_volatile_path(reporter, SkPath(), true); |
1766 | 1841 |
1767 test_empty_shape(reporter); | 1842 test_empty_shape(reporter); |
1768 | 1843 |
1769 test_lines(reporter); | 1844 test_lines(reporter); |
1770 | 1845 |
1771 test_stroked_lines(reporter); | 1846 test_stroked_lines(reporter); |
1772 } | 1847 } |
1773 | 1848 |
1774 #endif | 1849 #endif |
OLD | NEW |