| Index: tests/GrShapeTest.cpp
|
| diff --git a/tests/GrShapeTest.cpp b/tests/GrShapeTest.cpp
|
| index 62440d4ba528c7458e326d4f4158fb6a80c278cd..49ffb1a6f3a9c2f9f6f66d81606f5bf8ba4ed29e 100644
|
| --- a/tests/GrShapeTest.cpp
|
| +++ b/tests/GrShapeTest.cpp
|
| @@ -13,10 +13,26 @@
|
| #include "SkPath.h"
|
| #include "SkDashPathEffect.h"
|
|
|
| +using Key = SkTArray<uint32_t>;
|
| +
|
| +static bool make_key(Key* key, const GrShape& shape) {
|
| + int size = shape.unstyledKeySize();
|
| + if (size <= 0) {
|
| + key->reset(0);
|
| + return false;
|
| + }
|
| + SkASSERT(size);
|
| + key->reset(size);
|
| + shape.writeUnstyledKey(key->begin());
|
| + return true;
|
| +}
|
| +
|
| namespace {
|
| +
|
| class TestCase {
|
| public:
|
| - TestCase(const SkRRect& rrect, const SkPaint& paint) : fBase(rrect, paint) {
|
| + template <typename GEO>
|
| + TestCase(const GEO& geo, const SkPaint& paint) : fBase(geo, paint) {
|
| this->init();
|
| }
|
|
|
| @@ -37,28 +53,25 @@ public:
|
|
|
| void compare(skiatest::Reporter*, const TestCase& that, ComparisonExpecation) const;
|
|
|
| + const GrShape& baseShape() const { return fBase; }
|
| + const GrShape& appliedPathEffectShape() const { return fAppliedPE; }
|
| + const GrShape& appliedFullStyleShape() const { return fAppliedFull; }
|
| +
|
| + // The returned array's count will be 0 if the key shape has no key.
|
| + const Key& baseKey() const { return fBaseKey; }
|
| + const Key& appliedPathEffectKey() const { return fAppliedPEKey; }
|
| + const Key& appliedFullStyleKey() const { return fAppliedFullKey; }
|
| +
|
| private:
|
| void init() {
|
| fAppliedPE = fBase.applyPathEffect();
|
| fAppliedPEThenStroke = fAppliedPE.applyFullStyle();
|
| fAppliedFull = fBase.applyFullStyle();
|
|
|
| - fBaseKeyIsValid = MakeKey(&fBaseKey, fBase);
|
| - fAppliedPEKeyIsValid = MakeKey(&fAppliedPEKey, fAppliedPE);
|
| - fAppliedPEThenStrokeKeyIsValid = MakeKey(&fAppliedPEThenStrokeKey, fAppliedPEThenStroke);
|
| - fAppliedFullKeyIsValid = MakeKey(&fAppliedFullKey, fAppliedFull);
|
| - }
|
| -
|
| - using Key = SkTArray<uint32_t>;
|
| -
|
| - static bool MakeKey(Key* key, const GrShape& shape) {
|
| - int size = shape.unstyledKeySize();
|
| - if (size <= 0) {
|
| - return false;
|
| - }
|
| - key->reset(size);
|
| - shape.writeUnstyledKey(key->begin());
|
| - return true;
|
| + make_key(&fBaseKey, fBase);
|
| + make_key(&fAppliedPEKey, fAppliedPE);
|
| + make_key(&fAppliedPEThenStrokeKey, fAppliedPEThenStroke);
|
| + make_key(&fAppliedFullKey, fAppliedFull);
|
| }
|
|
|
| GrShape fBase;
|
| @@ -71,29 +84,32 @@ private:
|
| Key fAppliedPEThenStrokeKey;
|
| Key fAppliedFullKey;
|
|
|
| - bool fBaseKeyIsValid;
|
| - bool fAppliedPEKeyIsValid;
|
| - bool fAppliedPEThenStrokeKeyIsValid;
|
| - bool fAppliedFullKeyIsValid;
|
| };
|
|
|
| void TestCase::testExpectations(skiatest::Reporter* reporter, SelfExpectations expectations) const {
|
| // Applying the path effect and then the stroke should always be the same as applying
|
| // both in one go.
|
| REPORTER_ASSERT(reporter, fAppliedPEThenStrokeKey == fAppliedFullKey);
|
| + SkPath a, b;
|
| + fAppliedPEThenStroke.asPath(&a);
|
| + fAppliedFull.asPath(&b);
|
| + REPORTER_ASSERT(reporter, a == b);
|
| // The base's key should always be valid (unless the path is volatile)
|
| - REPORTER_ASSERT(reporter, fBaseKeyIsValid);
|
| + REPORTER_ASSERT(reporter, fBaseKey.count());
|
| if (expectations.fPEHasEffect) {
|
| REPORTER_ASSERT(reporter, fBaseKey != fAppliedPEKey);
|
| - REPORTER_ASSERT(reporter, expectations.fPEHasEffect == fAppliedPEKeyIsValid);
|
| + REPORTER_ASSERT(reporter, expectations.fPEHasValidKey == SkToBool(fAppliedPEKey.count()));
|
| REPORTER_ASSERT(reporter, fBaseKey != fAppliedFullKey);
|
| - REPORTER_ASSERT(reporter, expectations.fPEHasEffect == fAppliedFullKeyIsValid);
|
| + REPORTER_ASSERT(reporter, expectations.fPEHasValidKey == SkToBool(fAppliedFullKey.count()));
|
| if (expectations.fStrokeApplies && expectations.fPEHasValidKey) {
|
| REPORTER_ASSERT(reporter, fAppliedPEKey != fAppliedFullKey);
|
| - REPORTER_ASSERT(reporter, expectations.fPEHasEffect == fAppliedFullKeyIsValid);
|
| + REPORTER_ASSERT(reporter, SkToBool(fAppliedFullKey.count()));
|
| }
|
| } else {
|
| REPORTER_ASSERT(reporter, fBaseKey == fAppliedPEKey);
|
| + fBase.asPath(&a);
|
| + fAppliedPE.asPath(&b);
|
| + REPORTER_ASSERT(reporter, a == b);
|
| if (expectations.fStrokeApplies) {
|
| REPORTER_ASSERT(reporter, fBaseKey != fAppliedFullKey);
|
| } else {
|
| @@ -104,6 +120,7 @@ void TestCase::testExpectations(skiatest::Reporter* reporter, SelfExpectations e
|
|
|
| void TestCase::compare(skiatest::Reporter* reporter, const TestCase& that,
|
| ComparisonExpecation expectation) const {
|
| + SkPath a, b;
|
| switch (expectation) {
|
| case kAllDifferent_ComparisonExpecation:
|
| REPORTER_ASSERT(reporter, fBaseKey != that.fBaseKey);
|
| @@ -112,18 +129,36 @@ void TestCase::compare(skiatest::Reporter* reporter, const TestCase& that,
|
| break;
|
| case kSameUpToPE_ComparisonExpecation:
|
| REPORTER_ASSERT(reporter, fBaseKey == that.fBaseKey);
|
| + fBase.asPath(&a);
|
| + that.fBase.asPath(&b);
|
| + REPORTER_ASSERT(reporter, a == b);
|
| REPORTER_ASSERT(reporter, fAppliedPEKey != that.fAppliedPEKey);
|
| REPORTER_ASSERT(reporter, fAppliedFullKey != that.fAppliedFullKey);
|
| break;
|
| case kSameUpToStroke_ComparisonExpecation:
|
| REPORTER_ASSERT(reporter, fBaseKey == that.fBaseKey);
|
| + fBase.asPath(&a);
|
| + that.fBase.asPath(&b);
|
| + REPORTER_ASSERT(reporter, a == b);
|
| REPORTER_ASSERT(reporter, fAppliedPEKey == that.fAppliedPEKey);
|
| + fAppliedPE.asPath(&a);
|
| + that.fAppliedPE.asPath(&b);
|
| + REPORTER_ASSERT(reporter, a == b);
|
| REPORTER_ASSERT(reporter, fAppliedFullKey != that.fAppliedFullKey);
|
| break;
|
| case kAllSame_ComparisonExpecation:
|
| REPORTER_ASSERT(reporter, fBaseKey == that.fBaseKey);
|
| + fBase.asPath(&a);
|
| + that.fBase.asPath(&b);
|
| + REPORTER_ASSERT(reporter, a == b);
|
| REPORTER_ASSERT(reporter, fAppliedPEKey == that.fAppliedPEKey);
|
| + fAppliedPE.asPath(&a);
|
| + that.fAppliedPE.asPath(&b);
|
| + REPORTER_ASSERT(reporter, a == b);
|
| REPORTER_ASSERT(reporter, fAppliedFullKey == that.fAppliedFullKey);
|
| + fAppliedFull.asPath(&a);
|
| + that.fAppliedFull.asPath(&b);
|
| + REPORTER_ASSERT(reporter, a == b);
|
| break;
|
| }
|
| }
|
| @@ -140,42 +175,43 @@ static sk_sp<SkPathEffect> make_null_dash() {
|
| return SkDashPathEffect::Make(kNullIntervals, SK_ARRAY_COUNT(kNullIntervals), 0.f);
|
| }
|
|
|
| -static void test_basic(skiatest::Reporter* reporter, const SkRRect& rrect) {
|
| +template<typename GEO>
|
| +static void test_basic(skiatest::Reporter* reporter, const GEO& geo) {
|
| sk_sp<SkPathEffect> dashPE = make_dash();
|
|
|
| TestCase::SelfExpectations expectations;
|
| SkPaint fill;
|
|
|
| - TestCase fillCase(rrect, fill);
|
| + TestCase fillCase(geo, fill);
|
| expectations.fPEHasEffect = false;
|
| expectations.fPEHasValidKey = false;
|
| expectations.fStrokeApplies = false;
|
| fillCase.testExpectations(reporter, expectations);
|
| // Test that another GrShape instance built from the same primitive is the same.
|
| - TestCase(rrect, fill).compare(reporter, fillCase, TestCase::kAllSame_ComparisonExpecation);
|
| + TestCase(geo, fill).compare(reporter, fillCase, TestCase::kAllSame_ComparisonExpecation);
|
|
|
| SkPaint stroke2RoundBevel;
|
| stroke2RoundBevel.setStyle(SkPaint::kStroke_Style);
|
| stroke2RoundBevel.setStrokeCap(SkPaint::kRound_Cap);
|
| stroke2RoundBevel.setStrokeJoin(SkPaint::kBevel_Join);
|
| stroke2RoundBevel.setStrokeWidth(2.f);
|
| - TestCase stroke2RoundBevelCase(rrect, stroke2RoundBevel);
|
| + TestCase stroke2RoundBevelCase(geo, stroke2RoundBevel);
|
| expectations.fPEHasValidKey = true;
|
| expectations.fPEHasEffect = false;
|
| expectations.fStrokeApplies = true;
|
| stroke2RoundBevelCase.testExpectations(reporter, expectations);
|
| - TestCase(rrect, stroke2RoundBevel).compare(reporter, stroke2RoundBevelCase,
|
| - TestCase::kAllSame_ComparisonExpecation);
|
| + TestCase(geo, stroke2RoundBevel).compare(reporter, stroke2RoundBevelCase,
|
| + TestCase::kAllSame_ComparisonExpecation);
|
|
|
| SkPaint stroke2RoundBevelDash = stroke2RoundBevel;
|
| stroke2RoundBevelDash.setPathEffect(make_dash());
|
| - TestCase stroke2RoundBevelDashCase(rrect, stroke2RoundBevelDash);
|
| + TestCase stroke2RoundBevelDashCase(geo, stroke2RoundBevelDash);
|
| expectations.fPEHasValidKey = true;
|
| expectations.fPEHasEffect = true;
|
| expectations.fStrokeApplies = true;
|
| stroke2RoundBevelDashCase.testExpectations(reporter, expectations);
|
| - TestCase(rrect, stroke2RoundBevelDash).compare(reporter, stroke2RoundBevelDashCase,
|
| - TestCase::kAllSame_ComparisonExpecation);
|
| + TestCase(geo, stroke2RoundBevelDash).compare(reporter, stroke2RoundBevelDashCase,
|
| + TestCase::kAllSame_ComparisonExpecation);
|
|
|
| fillCase.compare(reporter, stroke2RoundBevelCase,
|
| TestCase::kSameUpToStroke_ComparisonExpecation);
|
| @@ -183,10 +219,17 @@ static void test_basic(skiatest::Reporter* reporter, const SkRRect& rrect) {
|
| TestCase::kSameUpToPE_ComparisonExpecation);
|
| stroke2RoundBevelCase.compare(reporter, stroke2RoundBevelDashCase,
|
| TestCase::kSameUpToPE_ComparisonExpecation);
|
| +
|
| + SkPaint hairline;
|
| + hairline.setStyle(SkPaint::kStroke_Style);
|
| + hairline.setStrokeWidth(0.f);
|
| + TestCase hairlineCase(geo, hairline);
|
| + // Since hairline style doesn't change the SkPath data, it is keyed identically to fill.
|
| + hairlineCase.compare(reporter, fillCase, TestCase::kAllSame_ComparisonExpecation);
|
| }
|
|
|
| -template <typename T>
|
| -static void test_stroke_param(skiatest::Reporter* reporter, const SkRRect& rrect,
|
| +template <typename GEO, typename T>
|
| +static void test_stroke_param(skiatest::Reporter* reporter, const GEO& geo,
|
| std::function<void(SkPaint*, T)> setter, T a, T b) {
|
| // Set the stroke width so that we don't get hairline. However, call the function second so that
|
| // it can override.
|
| @@ -199,16 +242,16 @@ static void test_stroke_param(skiatest::Reporter* reporter, const SkRRect& rrect
|
| strokeB.setStrokeWidth(2.f);
|
| setter(&strokeB, b);
|
|
|
| - TestCase strokeACase(rrect, strokeA);
|
| - TestCase strokeBCase(rrect, strokeB);
|
| + TestCase strokeACase(geo, strokeA);
|
| + TestCase strokeBCase(geo, strokeB);
|
| strokeACase.compare(reporter, strokeBCase, TestCase::kSameUpToStroke_ComparisonExpecation);
|
|
|
| // Make sure stroking params don't affect fill style.
|
| SkPaint fillA = strokeA, fillB = strokeB;
|
| fillA.setStyle(SkPaint::kFill_Style);
|
| fillB.setStyle(SkPaint::kFill_Style);
|
| - TestCase fillACase(rrect, fillA);
|
| - TestCase fillBCase(rrect, fillB);
|
| + TestCase fillACase(geo, fillA);
|
| + TestCase fillBCase(geo, fillB);
|
| fillACase.compare(reporter, fillBCase, TestCase::kAllSame_ComparisonExpecation);
|
|
|
| // Make sure just applying the dash but not stroke gives the same key for both stroking
|
| @@ -216,12 +259,13 @@ static void test_stroke_param(skiatest::Reporter* reporter, const SkRRect& rrect
|
| SkPaint dashA = strokeA, dashB = strokeB;
|
| dashA.setPathEffect(make_dash());
|
| dashB.setPathEffect(make_dash());
|
| - TestCase dashACase(rrect, dashA);
|
| - TestCase dashBCase(rrect, dashB);
|
| + TestCase dashACase(geo, dashA);
|
| + TestCase dashBCase(geo, dashB);
|
| dashACase.compare(reporter, dashBCase, TestCase::kSameUpToStroke_ComparisonExpecation);
|
| }
|
|
|
| -static void test_miter_limit(skiatest::Reporter* reporter, const SkRRect& rrect) {
|
| +template <typename GEO>
|
| +static void test_miter_limit(skiatest::Reporter* reporter, const GEO& geo) {
|
| // Miter limit should only matter when stroking with miter joins. It shouldn't affect other
|
| // joins or fills.
|
| SkPaint miterA;
|
| @@ -232,39 +276,41 @@ static void test_miter_limit(skiatest::Reporter* reporter, const SkRRect& rrect)
|
| SkPaint miterB = miterA;
|
| miterA.setStrokeMiter(0.6f);
|
|
|
| - TestCase miterACase(rrect, miterA);
|
| - TestCase miterBCase(rrect, miterB);
|
| + TestCase miterACase(geo, miterA);
|
| + TestCase miterBCase(geo, miterB);
|
| miterACase.compare(reporter, miterBCase, TestCase::kSameUpToStroke_ComparisonExpecation);
|
|
|
| SkPaint noMiterA = miterA, noMiterB = miterB;
|
| noMiterA.setStrokeJoin(SkPaint::kRound_Join);
|
| noMiterB.setStrokeJoin(SkPaint::kRound_Join);
|
| - TestCase noMiterACase(rrect, noMiterA);
|
| - TestCase noMiterBCase(rrect, noMiterB);
|
| + TestCase noMiterACase(geo, noMiterA);
|
| + TestCase noMiterBCase(geo, noMiterB);
|
| noMiterACase.compare(reporter, noMiterBCase, TestCase::kAllSame_ComparisonExpecation);
|
|
|
| SkPaint fillA = miterA, fillB = miterB;
|
| fillA.setStyle(SkPaint::kFill_Style);
|
| fillB.setStyle(SkPaint::kFill_Style);
|
| - TestCase fillACase(rrect, fillA);
|
| - TestCase fillBCase(rrect, fillB);
|
| + TestCase fillACase(geo, fillA);
|
| + TestCase fillBCase(geo, fillB);
|
| fillACase.compare(reporter, fillBCase, TestCase::kAllSame_ComparisonExpecation);
|
| }
|
|
|
| -static void test_dash_fill(skiatest::Reporter* reporter, const SkRRect& rrect) {
|
| +template<typename GEO>
|
| +static void test_dash_fill(skiatest::Reporter* reporter, const GEO& geo) {
|
| // A dash with no stroke should have no effect
|
| using DashFactoryFn = sk_sp<SkPathEffect>(*)();
|
| for (DashFactoryFn md : {&make_dash, &make_null_dash}) {
|
| SkPaint dashFill;
|
| dashFill.setPathEffect((*md)());
|
| - TestCase dashFillCase(rrect, dashFill);
|
| + TestCase dashFillCase(geo, dashFill);
|
|
|
| - TestCase fillCase(rrect, SkPaint());
|
| + TestCase fillCase(geo, SkPaint());
|
| dashFillCase.compare(reporter, fillCase, TestCase::kAllSame_ComparisonExpecation);
|
| }
|
| }
|
|
|
| -void test_null_dash(skiatest::Reporter* reporter, const SkRRect& rrect) {
|
| +template<typename GEO>
|
| +void test_null_dash(skiatest::Reporter* reporter, const GEO& geo) {
|
| SkPaint fill;
|
| SkPaint stroke;
|
| stroke.setStyle(SkPaint::kStroke_Style);
|
| @@ -278,16 +324,130 @@ void test_null_dash(skiatest::Reporter* reporter, const SkRRect& rrect) {
|
| nullDash.setStrokeWidth(1.f);
|
| nullDash.setPathEffect(make_null_dash());
|
|
|
| - TestCase fillCase(rrect, fill);
|
| - TestCase strokeCase(rrect, stroke);
|
| - TestCase dashCase(rrect, dash);
|
| - TestCase nullDashCase(rrect, nullDash);
|
| + TestCase fillCase(geo, fill);
|
| + TestCase strokeCase(geo, stroke);
|
| + TestCase dashCase(geo, dash);
|
| + TestCase nullDashCase(geo, nullDash);
|
|
|
| nullDashCase.compare(reporter, fillCase, TestCase::kSameUpToStroke_ComparisonExpecation);
|
| nullDashCase.compare(reporter, strokeCase, TestCase::kAllSame_ComparisonExpecation);
|
| nullDashCase.compare(reporter, dashCase, TestCase::kSameUpToPE_ComparisonExpecation);
|
| }
|
|
|
| +template <typename GEO>
|
| +void test_path_effect_makes_rrect(skiatest::Reporter* reporter, const GEO& geo) {
|
| + /**
|
| + * This path effect takes any input path and turns it into a rrect. It passes through stroke
|
| + * info.
|
| + */
|
| + class RRectPathEffect : SkPathEffect {
|
| + public:
|
| + static const SkRRect& RRect() {
|
| + static const SkRRect kRRect = SkRRect::MakeRectXY(SkRect::MakeWH(12, 12), 3, 5);
|
| + return kRRect;
|
| + }
|
| +
|
| + bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*,
|
| + const SkRect* cullR) const override {
|
| + dst->reset();
|
| + dst->addRRect(RRect());
|
| + return true;
|
| + }
|
| + void computeFastBounds(SkRect* dst, const SkRect& src) const override {
|
| + *dst = RRect().getBounds();
|
| + }
|
| + static sk_sp<SkPathEffect> Make() { return sk_sp<SkPathEffect>(new RRectPathEffect); }
|
| + Factory getFactory() const override { return nullptr; }
|
| + void toString(SkString*) const override {}
|
| + private:
|
| + RRectPathEffect() {}
|
| + };
|
| +
|
| + SkPaint fill;
|
| + TestCase fillGeoCase(geo, fill);
|
| +
|
| + SkPaint pe;
|
| + pe.setPathEffect(RRectPathEffect::Make());
|
| + TestCase geoPECase(geo, pe);
|
| +
|
| + SkPaint peStroke;
|
| + peStroke.setPathEffect(RRectPathEffect::Make());
|
| + peStroke.setStrokeWidth(2.f);
|
| + peStroke.setStyle(SkPaint::kStroke_Style);
|
| + TestCase geoPEStrokeCase(geo, peStroke);
|
| +
|
| + fillGeoCase.compare(reporter, geoPECase, TestCase::kSameUpToPE_ComparisonExpecation);
|
| + fillGeoCase.compare(reporter, geoPEStrokeCase, TestCase::kSameUpToPE_ComparisonExpecation);
|
| + geoPECase.compare(reporter, geoPEStrokeCase,
|
| + TestCase::kSameUpToStroke_ComparisonExpecation);
|
| +
|
| + TestCase rrectFillCase(RRectPathEffect::RRect(), fill);
|
| + SkPaint stroke = peStroke;
|
| + stroke.setPathEffect(nullptr);
|
| + TestCase rrectStrokeCase(RRectPathEffect::RRect(), stroke);
|
| +
|
| + SkRRect rrect;
|
| + // Applying the path effect should make a SkRRect shape. There is no further stroking in the
|
| + // geoPECase, so the full style should be the same as just the PE.
|
| + REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectShape().asRRect(&rrect));
|
| + REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect());
|
| + REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectKey() == rrectFillCase.baseKey());
|
| +
|
| + REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleShape().asRRect(&rrect));
|
| + REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect());
|
| + REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleKey() == rrectFillCase.baseKey());
|
| +
|
| + // In the PE+stroke case applying the full style should be the same as just stroking the rrect.
|
| + REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectShape().asRRect(&rrect));
|
| + REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect());
|
| + REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectKey() == rrectFillCase.baseKey());
|
| +
|
| + REPORTER_ASSERT(reporter, !geoPEStrokeCase.appliedFullStyleShape().asRRect(&rrect));
|
| + REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleKey() ==
|
| + rrectStrokeCase.appliedFullStyleKey());
|
| +}
|
| +
|
| +template <typename GEO>
|
| +void test_unknown_path_effect(skiatest::Reporter* reporter, const GEO& geo) {
|
| + /**
|
| + * This path effect just adds two lineTos to the input path.
|
| + */
|
| + class AddLineTosPathEffect : SkPathEffect {
|
| + public:
|
| + bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*,
|
| + const SkRect* cullR) const override {
|
| + *dst = src;
|
| + dst->lineTo(0, 0);
|
| + dst->lineTo(10, 10);
|
| + return true;
|
| + }
|
| + void computeFastBounds(SkRect* dst, const SkRect& src) const override {
|
| + *dst = src;
|
| + dst->growToInclude(0, 0);
|
| + dst->growToInclude(10, 10);
|
| + }
|
| + static sk_sp<SkPathEffect> Make() { return sk_sp<SkPathEffect>(new AddLineTosPathEffect); }
|
| + Factory getFactory() const override { return nullptr; }
|
| + void toString(SkString*) const override {}
|
| + private:
|
| + AddLineTosPathEffect() {}
|
| + };
|
| +
|
| + // This path effect should make the keys invalid when it is applied. We only produce a pathe
|
| + // effect key for dash path effects. So the only way another arbitrary path effect can produce
|
| + // a styled result with a key is to produce a non-path shape that has a purely geometric key.
|
| + SkPaint peStroke;
|
| + peStroke.setPathEffect(AddLineTosPathEffect::Make());
|
| + peStroke.setStrokeWidth(2.f);
|
| + peStroke.setStyle(SkPaint::kStroke_Style);
|
| + TestCase geoPEStrokeCase(geo, peStroke);
|
| + TestCase::SelfExpectations expectations;
|
| + expectations.fPEHasEffect = true;
|
| + expectations.fPEHasValidKey = false;
|
| + expectations.fStrokeApplies = true;
|
| + geoPEStrokeCase.testExpectations(reporter, expectations);
|
| +}
|
| +
|
| DEF_TEST(GrShape, reporter) {
|
| sk_sp<SkPathEffect> dashPE = make_dash();
|
|
|
| @@ -297,19 +457,105 @@ DEF_TEST(GrShape, reporter) {
|
| test_dash_fill(reporter, rr);
|
| test_null_dash(reporter, rr);
|
| // Test modifying various stroke params.
|
| - test_stroke_param<SkScalar>(
|
| + test_stroke_param<SkRRect, SkScalar>(
|
| reporter, rr,
|
| [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);},
|
| SkIntToScalar(2), SkIntToScalar(4));
|
| - test_stroke_param<SkPaint::Cap>(
|
| + test_stroke_param<SkRRect, SkPaint::Cap>(
|
| reporter, rr,
|
| [](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);},
|
| SkPaint::kButt_Cap, SkPaint::kRound_Cap);
|
| - test_stroke_param<SkPaint::Join>(
|
| + test_stroke_param<SkRRect, SkPaint::Join>(
|
| reporter, rr,
|
| [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);},
|
| SkPaint::kMiter_Join, SkPaint::kRound_Join);
|
| test_miter_limit(reporter, rr);
|
| + test_path_effect_makes_rrect(reporter, rr);
|
| + test_unknown_path_effect(reporter, rr);
|
| + }
|
| +
|
| + struct TestPath {
|
| + TestPath(const SkPath& path, bool isRRectFill, bool isRRectStroke ,const SkRRect& rrect)
|
| + : fPath(path)
|
| + , fIsRRectForFill(isRRectFill)
|
| + , fIsRRectForStroke(isRRectStroke)
|
| + , fRRect(rrect) {}
|
| + SkPath fPath;
|
| + bool fIsRRectForFill;
|
| + bool fIsRRectForStroke;
|
| + SkRRect fRRect;
|
| + };
|
| + SkTArray<TestPath> paths;
|
| +
|
| + SkPath circlePath;
|
| + circlePath.addCircle(10, 10, 10);
|
| + paths.emplace_back(circlePath, true, true, SkRRect::MakeOval(SkRect::MakeWH(20,20)));
|
| +
|
| + SkPath rectPath;
|
| + rectPath.addRect(SkRect::MakeWH(10, 10));
|
| + paths.emplace_back(rectPath, true, true, SkRRect::MakeRect(SkRect::MakeWH(10, 10)));
|
| +
|
| + SkPath openRectPath;
|
| + openRectPath.moveTo(0, 0);
|
| + openRectPath.lineTo(10, 0);
|
| + openRectPath.lineTo(10, 10);
|
| + openRectPath.lineTo(0, 10);
|
| + paths.emplace_back(openRectPath, true, false, SkRRect::MakeRect(SkRect::MakeWH(10, 10)));
|
| +
|
| + SkPath quadPath;
|
| + quadPath.quadTo(10, 10, 5, 8);
|
| + paths.emplace_back(quadPath, false, false, SkRRect());
|
| +
|
| + for (auto testPath : paths) {
|
| + const SkPath& path = testPath.fPath;
|
| + // These tests all assume that the original GrShape for fill and stroke will be the same.
|
| + // However, that is not the case in special cases (e.g. a unclosed rect becomes a RRect
|
| + // GrShape with a fill style but becomes a Path GrShape when stroked).
|
| + if (testPath.fIsRRectForFill == testPath.fIsRRectForStroke) {
|
| + test_basic(reporter, path);
|
| + test_null_dash(reporter, path);
|
| + test_path_effect_makes_rrect(reporter, path);
|
| + }
|
| + test_dash_fill(reporter, path);
|
| + // Test modifying various stroke params.
|
| + test_stroke_param<SkPath, SkScalar>(
|
| + reporter, path,
|
| + [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);},
|
| + SkIntToScalar(2), SkIntToScalar(4));
|
| + test_stroke_param<SkPath, SkPaint::Cap>(
|
| + reporter, path,
|
| + [](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);},
|
| + SkPaint::kButt_Cap, SkPaint::kRound_Cap);
|
| + test_stroke_param<SkPath, SkPaint::Join>(
|
| + reporter, path,
|
| + [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);},
|
| + SkPaint::kMiter_Join, SkPaint::kRound_Join);
|
| + test_miter_limit(reporter, path);
|
| + test_unknown_path_effect(reporter, path);
|
| +
|
| + SkPaint fillPaint;
|
| + TestCase fillPathCase(path, fillPaint);
|
| + SkRRect rrect;
|
| + REPORTER_ASSERT(reporter, testPath.fIsRRectForFill ==
|
| + fillPathCase.baseShape().asRRect(&rrect));
|
| + if (testPath.fIsRRectForFill) {
|
| + REPORTER_ASSERT(reporter, rrect == testPath.fRRect);
|
| + TestCase fillRRectCase(rrect, fillPaint);
|
| + fillPathCase.compare(reporter, fillRRectCase, TestCase::kAllSame_ComparisonExpecation);
|
| + }
|
| +
|
| + SkPaint strokePaint;
|
| + strokePaint.setStrokeWidth(3.f);
|
| + strokePaint.setStyle(SkPaint::kStroke_Style);
|
| + TestCase strokePathCase(path, strokePaint);
|
| + REPORTER_ASSERT(reporter, testPath.fIsRRectForStroke ==
|
| + strokePathCase.baseShape().asRRect(&rrect));
|
| + if (testPath.fIsRRectForStroke) {
|
| + REPORTER_ASSERT(reporter, rrect == testPath.fRRect);
|
| + TestCase strokeRRectCase(rrect, strokePaint);
|
| + strokePathCase.compare(reporter, strokeRRectCase,
|
| + TestCase::kAllSame_ComparisonExpecation);
|
| + }
|
| }
|
| }
|
|
|
|
|