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 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
111 // The returned array's count will be 0 if the key shape has no key. | 111 // The returned array's count will be 0 if the key shape has no key. |
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. |
robertphillips
2016/07/15 18:48:38
add an isInverted predicate ?
bsalomon
2016/07/18 14:02:41
I think I want to shy away from adding more method
| |
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 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
505 SkPaint hairline; | 505 SkPaint hairline; |
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 |
robertphillips
2016/07/15 18:48:38
geomeetry ?
bsalomon
2016/07/18 14:02:41
Done.
| |
516 // Was the shape pre-style geomeetry stored as something other than a general pa th. 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) { | |
robertphillips
2016/07/15 18:48:38
Don't we also know this for oval and simple RRect
bsalomon
2016/07/18 14:02:41
Yes, that will come in time, along with Dr. Rects.
| |
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 |