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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
112 const Key& baseKey() const { return fBaseKey; } | 112 const Key& baseKey() const { return fBaseKey; } |
113 const Key& appliedPathEffectKey() const { return fAppliedPEKey; } | 113 const Key& appliedPathEffectKey() const { return fAppliedPEKey; } |
114 const Key& appliedFullStyleKey() const { return fAppliedFullKey; } | 114 const Key& appliedFullStyleKey() const { return fAppliedFullKey; } |
115 const Key& appliedPathEffectThenStrokeKey() const { return fAppliedPEThenStr
okeKey; } | 115 const Key& appliedPathEffectThenStrokeKey() const { return fAppliedPEThenStr
okeKey; } |
116 | 116 |
117 private: | 117 private: |
118 static void CheckBounds(skiatest::Reporter* r, const GrShape& shape, const S
kRect& bounds) { | 118 static void CheckBounds(skiatest::Reporter* r, const GrShape& shape, const S
kRect& bounds) { |
119 SkPath path; | 119 SkPath path; |
120 shape.asPath(&path); | 120 shape.asPath(&path); |
121 // 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. |
122 if (bounds.isEmpty()) { | 122 if (bounds.fLeft > bounds.fRight || bounds.fTop > bounds.fBottom) { |
123 REPORTER_ASSERT(r, path.isEmpty()); | 123 REPORTER_ASSERT(r, path.isEmpty()); |
124 return; | 124 return; |
125 } | 125 } |
126 if (path.isEmpty()) { | 126 if (path.isEmpty()) { |
127 return; | 127 return; |
128 } | 128 } |
129 // The bounds API explicitly calls out that it does not consider inverse
ness. | 129 // The bounds API explicitly calls out that it does not consider inverse
ness. |
130 SkPath p = path; | 130 SkPath p = path; |
131 p.setFillType(SkPath::ConvertToNonInverseFillType(path.getFillType())); | 131 p.setFillType(SkPath::ConvertToNonInverseFillType(path.getFillType())); |
132 REPORTER_ASSERT(r, test_bounds_by_rasterizing(p, bounds)); | 132 REPORTER_ASSERT(r, test_bounds_by_rasterizing(p, bounds)); |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 hairline.setStyle(SkPaint::kStroke_Style); | 506 hairline.setStyle(SkPaint::kStroke_Style); |
507 hairline.setStrokeWidth(0.f); | 507 hairline.setStrokeWidth(0.f); |
508 TestCase hairlineCase(geo, hairline, reporter); | 508 TestCase hairlineCase(geo, hairline, reporter); |
509 // Since hairline style doesn't change the SkPath data, it is keyed identica
lly to fill. | 509 // Since hairline style doesn't change the SkPath data, it is keyed identica
lly to fill. |
510 hairlineCase.compare(reporter, fillCase, TestCase::kAllSame_ComparisonExpeca
tion); | 510 hairlineCase.compare(reporter, fillCase, TestCase::kAllSame_ComparisonExpeca
tion); |
511 REPORTER_ASSERT(reporter, hairlineCase.baseShape().style().isSimpleHairline(
)); | 511 REPORTER_ASSERT(reporter, hairlineCase.baseShape().style().isSimpleHairline(
)); |
512 REPORTER_ASSERT(reporter, hairlineCase.appliedFullStyleShape().style().isSim
pleHairline()); | 512 REPORTER_ASSERT(reporter, hairlineCase.appliedFullStyleShape().style().isSim
pleHairline()); |
513 REPORTER_ASSERT(reporter, hairlineCase.appliedPathEffectShape().style().isSi
mpleHairline()); | 513 REPORTER_ASSERT(reporter, hairlineCase.appliedPathEffectShape().style().isSi
mpleHairline()); |
514 } | 514 } |
515 | 515 |
| 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 } |
| 522 |
516 template<typename GEO> | 523 template<typename GEO> |
517 static void test_scale(skiatest::Reporter* reporter, const GEO& geo) { | 524 static void test_scale(skiatest::Reporter* reporter, const GEO& geo) { |
518 sk_sp<SkPathEffect> dashPE = make_dash(); | 525 sk_sp<SkPathEffect> dashPE = make_dash(); |
519 | 526 |
520 static const SkScalar kS1 = 1.f; | 527 static const SkScalar kS1 = 1.f; |
521 static const SkScalar kS2 = 2.f; | 528 static const SkScalar kS2 = 2.f; |
522 | 529 |
| 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 }; |
523 SkPaint fill; | 539 SkPaint fill; |
524 TestCase fillCase1(geo, fill, reporter, kS1); | 540 TestCase fillCase1(geo, fill, reporter, kS1); |
525 TestCase fillCase2(geo, fill, reporter, kS2); | 541 TestCase fillCase2(geo, fill, reporter, kS2); |
526 // Scale doesn't affect fills. | 542 // Scale doesn't affect fills. |
527 fillCase1.compare(reporter, fillCase2, TestCase::kAllSame_ComparisonExpecati
on); | 543 fillCase1.compare(reporter, fillCase2, TestCase::kAllSame_ComparisonExpecati
on); |
528 | 544 |
529 SkPaint hairline; | 545 SkPaint hairline; |
530 hairline.setStyle(SkPaint::kStroke_Style); | 546 hairline.setStyle(SkPaint::kStroke_Style); |
531 hairline.setStrokeWidth(0.f); | 547 hairline.setStrokeWidth(0.f); |
532 TestCase hairlineCase1(geo, hairline, reporter, kS1); | 548 TestCase hairlineCase1(geo, hairline, reporter, kS1); |
533 TestCase hairlineCase2(geo, hairline, reporter, kS2); | 549 TestCase hairlineCase2(geo, hairline, reporter, kS2); |
534 // Scale doesn't affect hairlines. | 550 // Scale doesn't affect hairlines. |
535 hairlineCase1.compare(reporter, hairlineCase2, TestCase::kAllSame_Comparison
Expecation); | 551 hairlineCase1.compare(reporter, hairlineCase2, TestCase::kAllSame_Comparison
Expecation); |
536 | 552 |
537 SkPaint stroke; | 553 SkPaint stroke; |
538 stroke.setStyle(SkPaint::kStroke_Style); | 554 stroke.setStyle(SkPaint::kStroke_Style); |
539 stroke.setStrokeWidth(2.f); | 555 stroke.setStrokeWidth(2.f); |
540 TestCase strokeCase1(geo, stroke, reporter, kS1); | 556 TestCase strokeCase1(geo, stroke, reporter, kS1); |
541 TestCase strokeCase2(geo, stroke, reporter, kS2); | 557 TestCase strokeCase2(geo, stroke, reporter, kS2); |
542 // Scale affects the stroke. | 558 // Scale affects the stroke |
543 strokeCase1.compare(reporter, strokeCase2, TestCase::kSameUpToStroke_Compari
sonExpecation); | 559 if (wasSimplified(strokeCase1)) { |
| 560 REPORTER_ASSERT(reporter, wasSimplified(strokeCase2)); |
| 561 strokeCase1.compare(reporter, strokeCase2, TestCase::kAllSame_Comparison
Expecation); |
| 562 } else { |
| 563 strokeCase1.compare(reporter, strokeCase2, TestCase::kSameUpToStroke_Com
parisonExpecation); |
| 564 } |
544 | 565 |
545 SkPaint strokeDash = stroke; | 566 SkPaint strokeDash = stroke; |
546 strokeDash.setPathEffect(make_dash()); | 567 strokeDash.setPathEffect(make_dash()); |
547 TestCase strokeDashCase1(geo, strokeDash, reporter, kS1); | 568 TestCase strokeDashCase1(geo, strokeDash, reporter, kS1); |
548 TestCase strokeDashCase2(geo, strokeDash, reporter, kS2); | 569 TestCase strokeDashCase2(geo, strokeDash, reporter, kS2); |
549 // Scale affects the dash and the stroke. | 570 // Scale affects the dash and the stroke. |
550 strokeDashCase1.compare(reporter, strokeDashCase2, TestCase::kSameUpToPE_Co
mparisonExpecation); | 571 if (wasSimplified(strokeDashCase1)) { |
| 572 REPORTER_ASSERT(reporter, wasSimplified(strokeDashCase2)); |
| 573 strokeDashCase1.compare(reporter, strokeDashCase2, |
| 574 TestCase::kAllSame_ComparisonExpecation); |
| 575 } else { |
| 576 strokeDashCase1.compare(reporter, strokeDashCase2, |
| 577 TestCase::kSameUpToPE_ComparisonExpecation); |
| 578 } |
551 | 579 |
552 // Stroke and fill cases | 580 // Stroke and fill cases |
553 SkPaint strokeAndFill = stroke; | 581 SkPaint strokeAndFill = stroke; |
554 strokeAndFill.setStyle(SkPaint::kStrokeAndFill_Style); | 582 strokeAndFill.setStyle(SkPaint::kStrokeAndFill_Style); |
555 TestCase strokeAndFillCase1(geo, strokeAndFill, reporter, kS1); | 583 TestCase strokeAndFillCase1(geo, strokeAndFill, reporter, kS1); |
556 TestCase strokeAndFillCase2(geo, strokeAndFill, reporter, kS2); | 584 TestCase strokeAndFillCase2(geo, strokeAndFill, reporter, kS2); |
557 SkPaint strokeAndFillDash = strokeDash; | 585 SkPaint strokeAndFillDash = strokeDash; |
558 strokeAndFillDash.setStyle(SkPaint::kStrokeAndFill_Style); | 586 strokeAndFillDash.setStyle(SkPaint::kStrokeAndFill_Style); |
559 // Dash is ignored for stroke and fill | 587 // Dash is ignored for stroke and fill |
560 TestCase strokeAndFillDashCase1(geo, strokeAndFillDash, reporter, kS1); | 588 TestCase strokeAndFillDashCase1(geo, strokeAndFillDash, reporter, kS1); |
561 TestCase strokeAndFillDashCase2(geo, strokeAndFillDash, reporter, kS2); | 589 TestCase strokeAndFillDashCase2(geo, strokeAndFillDash, reporter, kS2); |
562 // Scale affects the stroke. Though, this can wind up creating a rect when t
he input is a rect. | 590 // Scale affects the stroke. Scale affects the stroke, but check to make sur
e this didn't |
563 // In that case we wind up with a pure geometry key and the geometries are t
he same. | 591 // become a simpler shape (e.g. stroke-and-filled rect can become a rect), i
n which case the |
564 SkRRect rrect; | 592 // scale shouldn't matter and the geometries should agree. |
565 if (strokeAndFillCase1.appliedFullStyleShape().asRRect(&rrect, nullptr, null
ptr, nullptr)) { | 593 if (wasSimplified(strokeAndFillCase1)) { |
566 // We currently only expect to get here in the rect->rect case. | 594 REPORTER_ASSERT(reporter, wasSimplified(strokeAndFillCase1)); |
567 REPORTER_ASSERT(reporter, rrect.isRect()); | 595 REPORTER_ASSERT(reporter, wasSimplified(strokeAndFillDashCase1)); |
568 REPORTER_ASSERT(reporter, | 596 REPORTER_ASSERT(reporter, wasSimplified(strokeAndFillDashCase2)); |
569 strokeAndFillCase1.baseShape().asRRect(&rrect, nullptr,
nullptr, nullptr) && | |
570 rrect.isRect()); | |
571 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, | 597 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, |
572 TestCase::kAllSame_ComparisonExpecation); | 598 TestCase::kAllSame_ComparisonExpecation); |
| 599 strokeAndFillDashCase1.compare(reporter, strokeAndFillDashCase2, |
| 600 TestCase::kAllSame_ComparisonExpecation); |
573 } else { | 601 } else { |
574 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, | 602 strokeAndFillCase1.compare(reporter, strokeAndFillCase2, |
575 TestCase::kSameUpToStroke_ComparisonExpecatio
n); | 603 TestCase::kSameUpToStroke_ComparisonExpecatio
n); |
576 strokeAndFillDashCase1.compare(reporter, strokeAndFillDashCase2, | |
577 TestCase::kSameUpToStroke_ComparisonExpec
ation); | |
578 } | 604 } |
579 strokeAndFillDashCase1.compare(reporter, strokeAndFillCase1, | 605 strokeAndFillDashCase1.compare(reporter, strokeAndFillCase1, |
580 TestCase::kAllSame_ComparisonExpecation); | 606 TestCase::kAllSame_ComparisonExpecation); |
581 strokeAndFillDashCase2.compare(reporter, strokeAndFillCase2, | 607 strokeAndFillDashCase2.compare(reporter, strokeAndFillCase2, |
582 TestCase::kAllSame_ComparisonExpecation); | 608 TestCase::kAllSame_ComparisonExpecation); |
583 } | 609 } |
584 | 610 |
585 template <typename GEO, typename T> | 611 template <typename GEO, typename T> |
586 static void test_stroke_param_impl(skiatest::Reporter* reporter, const GEO& geo, | 612 static void test_stroke_param_impl(skiatest::Reporter* reporter, const GEO& geo, |
587 std::function<void(SkPaint*, T)> setter, T a,
T b, | 613 std::function<void(SkPaint*, T)> setter, T a,
T b, |
588 bool paramAffectsStroke, | 614 bool paramAffectsStroke, |
589 bool paramAffectsDashAndStroke) { | 615 bool paramAffectsDashAndStroke) { |
590 // Set the stroke width so that we don't get hairline. However, call the set
ter afterward so | 616 // Set the stroke width so that we don't get hairline. However, call the set
ter afterward so |
591 // that it can override the stroke width. | 617 // that it can override the stroke width. |
592 SkPaint strokeA; | 618 SkPaint strokeA; |
593 strokeA.setStyle(SkPaint::kStroke_Style); | 619 strokeA.setStyle(SkPaint::kStroke_Style); |
594 strokeA.setStrokeWidth(2.f); | 620 strokeA.setStrokeWidth(2.f); |
595 setter(&strokeA, a); | 621 setter(&strokeA, a); |
596 SkPaint strokeB; | 622 SkPaint strokeB; |
597 strokeB.setStyle(SkPaint::kStroke_Style); | 623 strokeB.setStyle(SkPaint::kStroke_Style); |
598 strokeB.setStrokeWidth(2.f); | 624 strokeB.setStrokeWidth(2.f); |
599 setter(&strokeB, b); | 625 setter(&strokeB, b); |
600 | 626 |
601 TestCase strokeACase(geo, strokeA, reporter); | 627 TestCase strokeACase(geo, strokeA, reporter); |
602 TestCase strokeBCase(geo, strokeB, reporter); | 628 TestCase strokeBCase(geo, strokeB, reporter); |
603 if (paramAffectsStroke) { | 629 if (paramAffectsStroke) { |
604 strokeACase.compare(reporter, strokeBCase, TestCase::kSameUpToStroke_Com
parisonExpecation); | 630 // If stroking is immediately incorporated into a geometric transformati
on then the base |
| 631 // shapes will differ. |
| 632 if (strokeACase.baseShape().style().applies()) { |
| 633 strokeACase.compare(reporter, strokeBCase, |
| 634 TestCase::kSameUpToStroke_ComparisonExpecation); |
| 635 } else { |
| 636 strokeACase.compare(reporter, strokeBCase, |
| 637 TestCase::kAllDifferent_ComparisonExpecation); |
| 638 } |
605 } else { | 639 } else { |
606 strokeACase.compare(reporter, strokeBCase, TestCase::kAllSame_Comparison
Expecation); | 640 strokeACase.compare(reporter, strokeBCase, TestCase::kAllSame_Comparison
Expecation); |
607 } | 641 } |
608 | 642 |
609 SkPaint strokeAndFillA = strokeA; | 643 SkPaint strokeAndFillA = strokeA; |
610 SkPaint strokeAndFillB = strokeB; | 644 SkPaint strokeAndFillB = strokeB; |
611 strokeAndFillA.setStyle(SkPaint::kStrokeAndFill_Style); | 645 strokeAndFillA.setStyle(SkPaint::kStrokeAndFill_Style); |
612 strokeAndFillB.setStyle(SkPaint::kStrokeAndFill_Style); | 646 strokeAndFillB.setStyle(SkPaint::kStrokeAndFill_Style); |
613 TestCase strokeAndFillACase(geo, strokeAndFillA, reporter); | 647 TestCase strokeAndFillACase(geo, strokeAndFillA, reporter); |
614 TestCase strokeAndFillBCase(geo, strokeAndFillB, reporter); | 648 TestCase strokeAndFillBCase(geo, strokeAndFillB, reporter); |
615 if (paramAffectsStroke) { | 649 if (paramAffectsStroke) { |
616 strokeAndFillACase.compare(reporter, strokeAndFillBCase, | 650 // If stroking is immediately incorporated into a geometric transformati
on then the base |
617 TestCase::kSameUpToStroke_ComparisonExpecatio
n); | 651 // shapes will differ. |
| 652 if (strokeAndFillACase.baseShape().style().applies()) { |
| 653 strokeAndFillACase.compare(reporter, strokeAndFillBCase, |
| 654 TestCase::kSameUpToStroke_ComparisonExpecation); |
| 655 } else { |
| 656 strokeAndFillACase.compare(reporter, strokeAndFillBCase, |
| 657 TestCase::kAllDifferent_ComparisonExpecation); |
| 658 } |
618 } else { | 659 } else { |
619 strokeAndFillACase.compare(reporter, strokeAndFillBCase, | 660 strokeAndFillACase.compare(reporter, strokeAndFillBCase, |
620 TestCase::kAllSame_ComparisonExpecation); | 661 TestCase::kAllSame_ComparisonExpecation); |
621 } | 662 } |
622 | 663 |
623 // Make sure stroking params don't affect fill style. | 664 // Make sure stroking params don't affect fill style. |
624 SkPaint fillA = strokeA, fillB = strokeB; | 665 SkPaint fillA = strokeA, fillB = strokeB; |
625 fillA.setStyle(SkPaint::kFill_Style); | 666 fillA.setStyle(SkPaint::kFill_Style); |
626 fillB.setStyle(SkPaint::kFill_Style); | 667 fillB.setStyle(SkPaint::kFill_Style); |
627 TestCase fillACase(geo, fillA, reporter); | 668 TestCase fillACase(geo, fillA, reporter); |
628 TestCase fillBCase(geo, fillB, reporter); | 669 TestCase fillBCase(geo, fillB, reporter); |
629 fillACase.compare(reporter, fillBCase, TestCase::kAllSame_ComparisonExpecati
on); | 670 fillACase.compare(reporter, fillBCase, TestCase::kAllSame_ComparisonExpecati
on); |
630 | 671 |
631 // Make sure just applying the dash but not stroke gives the same key for bo
th stroking | 672 // Make sure just applying the dash but not stroke gives the same key for bo
th stroking |
632 // variations. | 673 // variations. |
633 SkPaint dashA = strokeA, dashB = strokeB; | 674 SkPaint dashA = strokeA, dashB = strokeB; |
634 dashA.setPathEffect(make_dash()); | 675 dashA.setPathEffect(make_dash()); |
635 dashB.setPathEffect(make_dash()); | 676 dashB.setPathEffect(make_dash()); |
636 TestCase dashACase(geo, dashA, reporter); | 677 TestCase dashACase(geo, dashA, reporter); |
637 TestCase dashBCase(geo, dashB, reporter); | 678 TestCase dashBCase(geo, dashB, reporter); |
638 if (paramAffectsDashAndStroke) { | 679 if (paramAffectsDashAndStroke) { |
639 dashACase.compare(reporter, dashBCase, TestCase::kSameUpToStroke_Compari
sonExpecation); | 680 // If stroking is immediately incorporated into a geometric transformati
on then the base |
| 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 } |
640 } else { | 687 } else { |
641 dashACase.compare(reporter, dashBCase, TestCase::kAllSame_ComparisonExpe
cation); | 688 dashACase.compare(reporter, dashBCase, TestCase::kAllSame_ComparisonExpe
cation); |
642 } | 689 } |
643 } | 690 } |
644 | 691 |
645 template <typename GEO, typename T> | 692 template <typename GEO, typename T> |
646 static void test_stroke_param(skiatest::Reporter* reporter, const GEO& geo, | 693 static void test_stroke_param(skiatest::Reporter* reporter, const GEO& geo, |
647 std::function<void(SkPaint*, T)> setter, T a, T b)
{ | 694 std::function<void(SkPaint*, T)> setter, T a, T b)
{ |
648 test_stroke_param_impl(reporter, geo, setter, a, b, true, true); | 695 test_stroke_param_impl(reporter, geo, setter, a, b, true, true); |
649 }; | 696 }; |
650 | 697 |
651 template <typename GEO> | 698 template <typename GEO> |
652 static void test_stroke_cap(skiatest::Reporter* reporter, const GEO& geo) { | 699 static void test_stroke_cap(skiatest::Reporter* reporter, const GEO& geo) { |
653 GrShape shape(geo, GrStyle(SkStrokeRec::kHairline_InitStyle)); | 700 GrShape shape(geo, GrStyle(SkStrokeRec::kHairline_InitStyle)); |
654 // The cap should only affect shapes that may be open. | 701 // The cap should only affect shapes that may be open. |
655 bool affectsStroke = !shape.knownToBeClosed(); | 702 bool affectsStroke = !shape.knownToBeClosed(); |
656 // Dashing adds ends that need caps. | 703 // Dashing adds ends that need caps. |
657 bool affectsDashAndStroke = true; | 704 bool affectsDashAndStroke = true; |
658 test_stroke_param_impl<GEO, SkPaint::Cap>( | 705 test_stroke_param_impl<GEO, SkPaint::Cap>( |
659 reporter, | 706 reporter, |
660 geo, | 707 geo, |
661 [](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);}, | 708 [](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);}, |
662 SkPaint::kButt_Cap, SkPaint::kRound_Cap, | 709 SkPaint::kButt_Cap, SkPaint::kRound_Cap, |
663 affectsStroke, | 710 affectsStroke, |
664 affectsDashAndStroke); | 711 affectsDashAndStroke); |
665 }; | 712 }; |
666 | 713 |
| 714 static bool shape_known_not_to_have_joins(const GrShape& shape) { |
| 715 return shape.asLine(nullptr, nullptr) || shape.isEmpty(); |
| 716 } |
| 717 |
| 718 template <typename GEO> |
| 719 static void test_stroke_join(skiatest::Reporter* reporter, const GEO& geo) { |
| 720 GrShape shape(geo, GrStyle(SkStrokeRec::kHairline_InitStyle)); |
| 721 // GrShape recognizes certain types don't have joins and will prevent the jo
in type from |
| 722 // affecting the style key. |
| 723 // Dashing doesn't add additional joins. However, GrShape currently loses tr
ack of this |
| 724 // after applying the dash. |
| 725 bool affectsStroke = !shape_known_not_to_have_joins(shape); |
| 726 test_stroke_param_impl<GEO, SkPaint::Join>( |
| 727 reporter, |
| 728 geo, |
| 729 [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);}, |
| 730 SkPaint::kRound_Join, SkPaint::kBevel_Join, |
| 731 affectsStroke, true); |
| 732 }; |
| 733 |
667 template <typename GEO> | 734 template <typename GEO> |
668 static void test_miter_limit(skiatest::Reporter* reporter, const GEO& geo) { | 735 static void test_miter_limit(skiatest::Reporter* reporter, const GEO& geo) { |
669 auto setMiterJoinAndLimit = [](SkPaint* p, SkScalar miter) { | 736 auto setMiterJoinAndLimit = [](SkPaint* p, SkScalar miter) { |
670 p->setStrokeJoin(SkPaint::kMiter_Join); | 737 p->setStrokeJoin(SkPaint::kMiter_Join); |
671 p->setStrokeMiter(miter); | 738 p->setStrokeMiter(miter); |
672 }; | 739 }; |
673 | 740 |
674 auto setOtherJoinAndLimit = [](SkPaint* p, SkScalar miter) { | 741 auto setOtherJoinAndLimit = [](SkPaint* p, SkScalar miter) { |
675 p->setStrokeJoin(SkPaint::kRound_Join); | 742 p->setStrokeJoin(SkPaint::kRound_Join); |
676 p->setStrokeMiter(miter); | 743 p->setStrokeMiter(miter); |
677 }; | 744 }; |
678 | 745 |
| 746 GrShape shape(geo, GrStyle(SkStrokeRec::kHairline_InitStyle)); |
| 747 bool mayHaveJoins = !shape_known_not_to_have_joins(shape); |
| 748 |
679 // The miter limit should affect stroked and dashed-stroked cases when the j
oin type is | 749 // The miter limit should affect stroked and dashed-stroked cases when the j
oin type is |
680 // miter. | 750 // miter. |
681 test_stroke_param_impl<GEO, SkScalar>( | 751 test_stroke_param_impl<GEO, SkScalar>( |
682 reporter, | 752 reporter, |
683 geo, | 753 geo, |
684 setMiterJoinAndLimit, | 754 setMiterJoinAndLimit, |
685 0.5f, 0.75f, | 755 0.5f, 0.75f, |
686 true, | 756 mayHaveJoins, |
687 true); | 757 true); |
688 | 758 |
689 // The miter limit should not affect stroked and dashed-stroked cases when t
he join type is | 759 // The miter limit should not affect stroked and dashed-stroked cases when t
he join type is |
690 // not miter. | 760 // not miter. |
691 test_stroke_param_impl<GEO, SkScalar>( | 761 test_stroke_param_impl<GEO, SkScalar>( |
692 reporter, | 762 reporter, |
693 geo, | 763 geo, |
694 setOtherJoinAndLimit, | 764 setOtherJoinAndLimit, |
695 0.5f, 0.75f, | 765 0.5f, 0.75f, |
696 false, | 766 false, |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
984 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleKey() == emptyKey)
; | 1054 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleKey() == emptyKey)
; |
985 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectKey() == emptyKey
); | 1055 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectKey() == emptyKey
); |
986 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectThenStrokeKey() =
= emptyKey); | 1056 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectThenStrokeKey() =
= emptyKey); |
987 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectShape().isEmpty()
); | 1057 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectShape().isEmpty()
); |
988 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleShape().isEmpty())
; | 1058 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleShape().isEmpty())
; |
989 } | 1059 } |
990 | 1060 |
991 template <typename GEO> | 1061 template <typename GEO> |
992 void test_path_effect_fails(skiatest::Reporter* reporter, const GEO& geo) { | 1062 void test_path_effect_fails(skiatest::Reporter* reporter, const GEO& geo) { |
993 /** | 1063 /** |
994 * This path effect returns an empty path. | 1064 * This path effect always fails to apply. |
995 */ | 1065 */ |
996 class FailurePathEffect : SkPathEffect { | 1066 class FailurePathEffect : SkPathEffect { |
997 public: | 1067 public: |
998 bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, | 1068 bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, |
999 const SkRect* cullR) const override { | 1069 const SkRect* cullR) const override { |
1000 return false; | 1070 return false; |
1001 } | 1071 } |
1002 void computeFastBounds(SkRect* dst, const SkRect& src) const override { | 1072 void computeFastBounds(SkRect* dst, const SkRect& src) const override { |
1003 *dst = src; | 1073 *dst = src; |
1004 } | 1074 } |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1454 REPORTER_ASSERT(r, strokeInvAB.baseShape().asLine(pts, &inverted) && inverte
d && | 1524 REPORTER_ASSERT(r, strokeInvAB.baseShape().asLine(pts, &inverted) && inverte
d && |
1455 pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]); | 1525 pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]); |
1456 REPORTER_ASSERT(r, hairlineInvAB.baseShape().asLine(pts, &inverted) && inver
ted && | 1526 REPORTER_ASSERT(r, hairlineInvAB.baseShape().asLine(pts, &inverted) && inver
ted && |
1457 pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]); | 1527 pts[0] == canonicalPts[0] && pts[1] == canonicalPts[1]); |
1458 // Dashing ignores inverse. | 1528 // Dashing ignores inverse. |
1459 REPORTER_ASSERT(r, dashInvAB.baseShape().asLine(pts, &inverted) && !inverted
&& | 1529 REPORTER_ASSERT(r, dashInvAB.baseShape().asLine(pts, &inverted) && !inverted
&& |
1460 pts[0] == kA && pts[1] == kB); | 1530 pts[0] == kA && pts[1] == kB); |
1461 | 1531 |
1462 } | 1532 } |
1463 | 1533 |
| 1534 static void test_stroked_lines(skiatest::Reporter* r) { |
| 1535 // Paints to try |
| 1536 SkPaint buttCap; |
| 1537 buttCap.setStyle(SkPaint::kStroke_Style); |
| 1538 buttCap.setStrokeWidth(4); |
| 1539 buttCap.setStrokeCap(SkPaint::kButt_Cap); |
| 1540 |
| 1541 SkPaint squareCap = buttCap; |
| 1542 squareCap.setStrokeCap(SkPaint::kSquare_Cap); |
| 1543 |
| 1544 SkPaint roundCap = buttCap; |
| 1545 roundCap.setStrokeCap(SkPaint::kRound_Cap); |
| 1546 |
| 1547 // vertical |
| 1548 SkPath linePath; |
| 1549 linePath.moveTo(4, 4); |
| 1550 linePath.lineTo(4, 5); |
| 1551 |
| 1552 SkPaint fill; |
| 1553 |
| 1554 TestCase(linePath, buttCap, r).compare(r, TestCase(SkRect::MakeLTRB(2, 4, 6,
5), fill, r), |
| 1555 TestCase::kAllSame_ComparisonExpecati
on); |
| 1556 |
| 1557 TestCase(linePath, squareCap, r).compare(r, TestCase(SkRect::MakeLTRB(2, 2,
6, 7), fill, r), |
| 1558 TestCase::kAllSame_ComparisonExpeca
tion); |
| 1559 |
| 1560 TestCase(linePath, roundCap, r).compare(r, |
| 1561 TestCase(SkRRect::MakeRectXY(SkRect::MakeLTRB(2, 2, 6, 7), 2, 2), fill,
r), |
| 1562 TestCase::kAllSame_ComparisonExpecation); |
| 1563 |
| 1564 // horizontal |
| 1565 linePath.reset(); |
| 1566 linePath.moveTo(4, 4); |
| 1567 linePath.lineTo(5, 4); |
| 1568 |
| 1569 TestCase(linePath, buttCap, r).compare(r, TestCase(SkRect::MakeLTRB(4, 2, 5,
6), fill, r), |
| 1570 TestCase::kAllSame_ComparisonExpecati
on); |
| 1571 TestCase(linePath, squareCap, r).compare(r, TestCase(SkRect::MakeLTRB(2, 2,
7, 6), fill, r), |
| 1572 TestCase::kAllSame_ComparisonExpeca
tion); |
| 1573 TestCase(linePath, roundCap, r).compare(r, |
| 1574 TestCase(SkRRect::MakeRectXY(SkRect::MakeLTRB(2, 2, 7, 6), 2, 2), fill,
r), |
| 1575 TestCase::kAllSame_ComparisonExpecation); |
| 1576 |
| 1577 // point |
| 1578 linePath.reset(); |
| 1579 linePath.moveTo(4, 4); |
| 1580 linePath.lineTo(4, 4); |
| 1581 |
| 1582 TestCase(linePath, buttCap, r).compare(r, TestCase(SkRect::MakeEmpty(), fill
, r), |
| 1583 TestCase::kAllSame_ComparisonExpecati
on); |
| 1584 TestCase(linePath, squareCap, r).compare(r, TestCase(SkRect::MakeLTRB(2, 2,
6, 6), fill, r), |
| 1585 TestCase::kAllSame_ComparisonExpeca
tion); |
| 1586 TestCase(linePath, roundCap, r).compare(r, |
| 1587 TestCase(SkRRect::MakeRectXY(SkRect::MakeLTRB(2, 2, 6, 6), 2, 2), fill,
r), |
| 1588 TestCase::kAllSame_ComparisonExpecation); |
| 1589 } |
| 1590 |
1464 DEF_TEST(GrShape, reporter) { | 1591 DEF_TEST(GrShape, reporter) { |
1465 for (auto r : { SkRect::MakeWH(10, 20), | 1592 for (auto r : { SkRect::MakeWH(10, 20), |
1466 SkRect::MakeWH(-10, -20), | 1593 SkRect::MakeWH(-10, -20), |
1467 SkRect::MakeWH(-10, 20), | 1594 SkRect::MakeWH(-10, 20), |
1468 SkRect::MakeWH(10, -20)}) { | 1595 SkRect::MakeWH(10, -20)}) { |
1469 test_basic(reporter, r); | 1596 test_basic(reporter, r); |
1470 test_scale(reporter, r); | 1597 test_scale(reporter, r); |
1471 test_dash_fill(reporter, r); | 1598 test_dash_fill(reporter, r); |
1472 test_null_dash(reporter, r); | 1599 test_null_dash(reporter, r); |
1473 // Test modifying various stroke params. | 1600 // Test modifying various stroke params. |
1474 test_stroke_param<SkRect, SkScalar>( | 1601 test_stroke_param<SkRect, SkScalar>( |
1475 reporter, r, | 1602 reporter, r, |
1476 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, | 1603 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, |
1477 SkIntToScalar(2), SkIntToScalar(4)); | 1604 SkIntToScalar(2), SkIntToScalar(4)); |
1478 test_stroke_param<SkRect, SkPaint::Join>( | 1605 test_stroke_join(reporter, r); |
1479 reporter, r, | |
1480 [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);}, | |
1481 SkPaint::kMiter_Join, SkPaint::kRound_Join); | |
1482 test_stroke_cap(reporter, r); | 1606 test_stroke_cap(reporter, r); |
1483 test_miter_limit(reporter, r); | 1607 test_miter_limit(reporter, r); |
1484 test_path_effect_makes_rrect(reporter, r); | 1608 test_path_effect_makes_rrect(reporter, r); |
1485 test_unknown_path_effect(reporter, r); | 1609 test_unknown_path_effect(reporter, r); |
1486 test_path_effect_makes_empty_shape(reporter, r); | 1610 test_path_effect_makes_empty_shape(reporter, r); |
1487 test_path_effect_fails(reporter, r); | 1611 test_path_effect_fails(reporter, r); |
1488 test_make_hairline_path_effect(reporter, r, true); | 1612 test_make_hairline_path_effect(reporter, r, true); |
1489 GrShape shape(r); | 1613 GrShape shape(r); |
1490 REPORTER_ASSERT(reporter, !shape.asLine(nullptr, nullptr)); | 1614 REPORTER_ASSERT(reporter, !shape.asLine(nullptr, nullptr)); |
1491 } | 1615 } |
1492 | 1616 |
1493 for (auto rr : { SkRRect::MakeRect(SkRect::MakeWH(10, 10)), | 1617 for (auto rr : { SkRRect::MakeRect(SkRect::MakeWH(10, 10)), |
1494 SkRRect::MakeRectXY(SkRect::MakeWH(10, 10), 3, 4), | 1618 SkRRect::MakeRectXY(SkRect::MakeWH(10, 10), 3, 4), |
1495 SkRRect::MakeOval(SkRect::MakeWH(20, 20))}) { | 1619 SkRRect::MakeOval(SkRect::MakeWH(20, 20))}) { |
1496 test_basic(reporter, rr); | 1620 test_basic(reporter, rr); |
1497 test_rrect(reporter, rr); | 1621 test_rrect(reporter, rr); |
1498 test_scale(reporter, rr); | 1622 test_scale(reporter, rr); |
1499 test_dash_fill(reporter, rr); | 1623 test_dash_fill(reporter, rr); |
1500 test_null_dash(reporter, rr); | 1624 test_null_dash(reporter, rr); |
1501 // Test modifying various stroke params. | 1625 // Test modifying various stroke params. |
1502 test_stroke_param<SkRRect, SkScalar>( | 1626 test_stroke_param<SkRRect, SkScalar>( |
1503 reporter, rr, | 1627 reporter, rr, |
1504 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, | 1628 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, |
1505 SkIntToScalar(2), SkIntToScalar(4)); | 1629 SkIntToScalar(2), SkIntToScalar(4)); |
1506 test_stroke_param<SkRRect, SkPaint::Join>( | 1630 test_stroke_join(reporter, rr); |
1507 reporter, rr, | |
1508 [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);
}, | |
1509 SkPaint::kMiter_Join, SkPaint::kRound_Join); | |
1510 test_stroke_cap(reporter, rr); | 1631 test_stroke_cap(reporter, rr); |
1511 test_miter_limit(reporter, rr); | 1632 test_miter_limit(reporter, rr); |
1512 test_path_effect_makes_rrect(reporter, rr); | 1633 test_path_effect_makes_rrect(reporter, rr); |
1513 test_unknown_path_effect(reporter, rr); | 1634 test_unknown_path_effect(reporter, rr); |
1514 test_path_effect_makes_empty_shape(reporter, rr); | 1635 test_path_effect_makes_empty_shape(reporter, rr); |
1515 test_path_effect_fails(reporter, rr); | 1636 test_path_effect_fails(reporter, rr); |
1516 test_make_hairline_path_effect(reporter, rr, true); | 1637 test_make_hairline_path_effect(reporter, rr, true); |
1517 GrShape shape(rr); | 1638 GrShape shape(rr); |
1518 REPORTER_ASSERT(reporter, !shape.asLine(nullptr, nullptr)); | 1639 REPORTER_ASSERT(reporter, !shape.asLine(nullptr, nullptr)); |
1519 } | 1640 } |
(...skipping 30 matching lines...) Expand all Loading... |
1550 paths.emplace_back(openRectPath, true, false, false, SkRRect::MakeRect(SkRec
t::MakeWH(10, 10))); | 1671 paths.emplace_back(openRectPath, true, false, false, SkRRect::MakeRect(SkRec
t::MakeWH(10, 10))); |
1551 | 1672 |
1552 SkPath quadPath; | 1673 SkPath quadPath; |
1553 quadPath.quadTo(10, 10, 5, 8); | 1674 quadPath.quadTo(10, 10, 5, 8); |
1554 paths.emplace_back(quadPath, false, false, false, SkRRect()); | 1675 paths.emplace_back(quadPath, false, false, false, SkRRect()); |
1555 | 1676 |
1556 SkPath linePath; | 1677 SkPath linePath; |
1557 linePath.lineTo(10, 10); | 1678 linePath.lineTo(10, 10); |
1558 paths.emplace_back(linePath, false, false, true, SkRRect()); | 1679 paths.emplace_back(linePath, false, false, true, SkRRect()); |
1559 | 1680 |
| 1681 // Horizontal and vertical paths become rrects when stroked. |
| 1682 SkPath vLinePath; |
| 1683 vLinePath.lineTo(0, 10); |
| 1684 paths.emplace_back(vLinePath, false, false, true, SkRRect()); |
| 1685 |
| 1686 SkPath hLinePath; |
| 1687 hLinePath.lineTo(10, 0); |
| 1688 paths.emplace_back(hLinePath, false, false, true, SkRRect()); |
| 1689 |
1560 for (auto testPath : paths) { | 1690 for (auto testPath : paths) { |
1561 for (bool inverseFill : {false, true}) { | 1691 for (bool inverseFill : {false, true}) { |
1562 if (inverseFill) { | 1692 if (inverseFill) { |
1563 if (testPath.fPath.getFillType() == SkPath::kEvenOdd_FillType) { | 1693 if (testPath.fPath.getFillType() == SkPath::kEvenOdd_FillType) { |
1564 testPath.fPath.setFillType(SkPath::kInverseEvenOdd_FillType)
; | 1694 testPath.fPath.setFillType(SkPath::kInverseEvenOdd_FillType)
; |
1565 } else { | 1695 } else { |
1566 SkASSERT(testPath.fPath.getFillType() == SkPath::kWinding_Fi
llType); | 1696 SkASSERT(testPath.fPath.getFillType() == SkPath::kWinding_Fi
llType); |
1567 testPath.fPath.setFillType(SkPath::kInverseWinding_FillType)
; | 1697 testPath.fPath.setFillType(SkPath::kInverseWinding_FillType)
; |
1568 } | 1698 } |
1569 } | 1699 } |
(...skipping 10 matching lines...) Expand all Loading... |
1580 } | 1710 } |
1581 test_scale(reporter, path); | 1711 test_scale(reporter, path); |
1582 // This test uses a stroking paint, hence use of fIsRRectForStroke | 1712 // This test uses a stroking paint, hence use of fIsRRectForStroke |
1583 test_volatile_path(reporter, path, testPath.fIsRRectForStroke || tes
tPath.fIsLine); | 1713 test_volatile_path(reporter, path, testPath.fIsRRectForStroke || tes
tPath.fIsLine); |
1584 test_dash_fill(reporter, path); | 1714 test_dash_fill(reporter, path); |
1585 // Test modifying various stroke params. | 1715 // Test modifying various stroke params. |
1586 test_stroke_param<SkPath, SkScalar>( | 1716 test_stroke_param<SkPath, SkScalar>( |
1587 reporter, path, | 1717 reporter, path, |
1588 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, | 1718 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, |
1589 SkIntToScalar(2), SkIntToScalar(4)); | 1719 SkIntToScalar(2), SkIntToScalar(4)); |
1590 test_stroke_param<SkPath, SkPaint::Join>( | 1720 test_stroke_join(reporter, path); |
1591 reporter, path, | |
1592 [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);}, | |
1593 SkPaint::kMiter_Join, SkPaint::kRound_Join); | |
1594 test_stroke_cap(reporter, path); | 1721 test_stroke_cap(reporter, path); |
1595 test_miter_limit(reporter, path); | 1722 test_miter_limit(reporter, path); |
1596 test_unknown_path_effect(reporter, path); | 1723 test_unknown_path_effect(reporter, path); |
1597 test_path_effect_makes_empty_shape(reporter, path); | 1724 test_path_effect_makes_empty_shape(reporter, path); |
1598 test_path_effect_fails(reporter, path); | 1725 test_path_effect_fails(reporter, path); |
1599 test_make_hairline_path_effect(reporter, path, testPath.fIsRRectForS
troke || | 1726 test_make_hairline_path_effect(reporter, path, testPath.fIsRRectForS
troke || |
1600 testPath.fIsLine); | 1727 testPath.fIsLine); |
1601 } | 1728 } |
1602 } | 1729 } |
1603 | 1730 |
(...skipping 10 matching lines...) Expand all Loading... |
1614 TestCase fillPathCase2(testPath.fPath, fillPaint, reporter); | 1741 TestCase fillPathCase2(testPath.fPath, fillPaint, reporter); |
1615 REPORTER_ASSERT(reporter, rrect == testPath.fRRect); | 1742 REPORTER_ASSERT(reporter, rrect == testPath.fRRect); |
1616 TestCase fillRRectCase(rrect, fillPaint, reporter); | 1743 TestCase fillRRectCase(rrect, fillPaint, reporter); |
1617 fillPathCase2.compare(reporter, fillRRectCase, | 1744 fillPathCase2.compare(reporter, fillRRectCase, |
1618 TestCase::kAllSame_ComparisonExpecation); | 1745 TestCase::kAllSame_ComparisonExpecation); |
1619 } | 1746 } |
1620 SkPaint strokePaint; | 1747 SkPaint strokePaint; |
1621 strokePaint.setStrokeWidth(3.f); | 1748 strokePaint.setStrokeWidth(3.f); |
1622 strokePaint.setStyle(SkPaint::kStroke_Style); | 1749 strokePaint.setStyle(SkPaint::kStroke_Style); |
1623 TestCase strokePathCase(path, strokePaint, reporter); | 1750 TestCase strokePathCase(path, strokePaint, reporter); |
1624 REPORTER_ASSERT(reporter, testPath.fIsRRectForStroke == | 1751 if (testPath.fIsRRectForStroke) { |
1625 strokePathCase.baseShape().asRRect(&rrect, nul
lptr, nullptr, | 1752 REPORTER_ASSERT(reporter, strokePathCase.baseShape().asRRect(&rrect,
nullptr, nullptr, |
1626 nullptr)); | 1753 nullptr
)); |
| 1754 } |
| 1755 |
1627 if (testPath.fIsRRectForStroke) { | 1756 if (testPath.fIsRRectForStroke) { |
1628 REPORTER_ASSERT(reporter, rrect == testPath.fRRect); | 1757 REPORTER_ASSERT(reporter, rrect == testPath.fRRect); |
1629 TestCase strokeRRectCase(rrect, strokePaint, reporter); | 1758 TestCase strokeRRectCase(rrect, strokePaint, reporter); |
1630 strokePathCase.compare(reporter, strokeRRectCase, | 1759 strokePathCase.compare(reporter, strokeRRectCase, |
1631 TestCase::kAllSame_ComparisonExpecation); | 1760 TestCase::kAllSame_ComparisonExpecation); |
1632 } | 1761 } |
1633 } | 1762 } |
1634 | 1763 |
1635 // Test a volatile empty path. | 1764 // Test a volatile empty path. |
1636 test_volatile_path(reporter, SkPath(), true); | 1765 test_volatile_path(reporter, SkPath(), true); |
1637 | 1766 |
1638 test_empty_shape(reporter); | 1767 test_empty_shape(reporter); |
1639 | 1768 |
1640 test_lines(reporter); | 1769 test_lines(reporter); |
| 1770 |
| 1771 test_stroked_lines(reporter); |
1641 } | 1772 } |
1642 | 1773 |
1643 #endif | 1774 #endif |
OLD | NEW |