Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include <initializer_list> | 8 #include <initializer_list> |
| 9 #include <functional> | 9 #include <functional> |
| 10 #include "Test.h" | 10 #include "Test.h" |
| 11 #if SK_SUPPORT_GPU | 11 #if SK_SUPPORT_GPU |
| 12 #include "GrShape.h" | 12 #include "GrShape.h" |
| 13 #include "SkPath.h" | 13 #include "SkPath.h" |
| 14 #include "SkDashPathEffect.h" | 14 #include "SkDashPathEffect.h" |
| 15 | 15 |
| 16 using Key = SkTArray<uint32_t>; | |
| 17 | |
| 18 static bool make_key(Key* key, const GrShape& shape) { | |
| 19 int size = shape.unstyledKeySize(); | |
| 20 if (size <= 0) { | |
| 21 key->reset(0); | |
| 22 return false; | |
| 23 } | |
| 24 SkASSERT(size); | |
| 25 key->reset(size); | |
| 26 shape.writeUnstyledKey(key->begin()); | |
| 27 return true; | |
| 28 } | |
| 29 | |
| 16 namespace { | 30 namespace { |
| 31 | |
| 17 class TestCase { | 32 class TestCase { |
| 18 public: | 33 public: |
| 19 TestCase(const SkRRect& rrect, const SkPaint& paint) : fBase(rrect, paint) { | 34 template <typename GEO> |
| 35 TestCase(const GEO& geo, const SkPaint& paint) : fBase(geo, paint) { | |
| 20 this->init(); | 36 this->init(); |
| 21 } | 37 } |
| 22 | 38 |
| 23 struct SelfExpectations { | 39 struct SelfExpectations { |
| 24 bool fPEHasEffect; | 40 bool fPEHasEffect; |
| 25 bool fPEHasValidKey; | 41 bool fPEHasValidKey; |
| 26 bool fStrokeApplies; | 42 bool fStrokeApplies; |
| 27 }; | 43 }; |
| 28 | 44 |
| 29 void testExpectations(skiatest::Reporter* reporter, SelfExpectations expecta tions) const; | 45 void testExpectations(skiatest::Reporter* reporter, SelfExpectations expecta tions) const; |
| 30 | 46 |
| 31 enum ComparisonExpecation { | 47 enum ComparisonExpecation { |
| 32 kAllDifferent_ComparisonExpecation, | 48 kAllDifferent_ComparisonExpecation, |
| 33 kSameUpToPE_ComparisonExpecation, | 49 kSameUpToPE_ComparisonExpecation, |
| 34 kSameUpToStroke_ComparisonExpecation, | 50 kSameUpToStroke_ComparisonExpecation, |
| 35 kAllSame_ComparisonExpecation, | 51 kAllSame_ComparisonExpecation, |
| 36 }; | 52 }; |
| 37 | 53 |
| 38 void compare(skiatest::Reporter*, const TestCase& that, ComparisonExpecation ) const; | 54 void compare(skiatest::Reporter*, const TestCase& that, ComparisonExpecation ) const; |
| 39 | 55 |
| 56 const GrShape& baseShape() const { return fBase; } | |
| 57 const GrShape& appliedPathEffectShape() const { return fAppliedPE; } | |
| 58 const GrShape& appliedFullStyleShape() const { return fAppliedFull; } | |
| 59 | |
| 60 // The returned array's count will be 0 if the key shape has no key. | |
| 61 const Key& baseKey() const { return fBaseKey; } | |
| 62 const Key& appliedPathEffectKey() const { return fAppliedPEKey; } | |
| 63 const Key& appliedFullStyleKey() const { return fAppliedFullKey; } | |
| 64 | |
| 40 private: | 65 private: |
| 41 void init() { | 66 void init() { |
| 42 fAppliedPE = fBase.applyPathEffect(); | 67 fAppliedPE = fBase.applyPathEffect(); |
| 43 fAppliedPEThenStroke = fAppliedPE.applyFullStyle(); | 68 fAppliedPEThenStroke = fAppliedPE.applyFullStyle(); |
| 44 fAppliedFull = fBase.applyFullStyle(); | 69 fAppliedFull = fBase.applyFullStyle(); |
| 45 | 70 |
| 46 fBaseKeyIsValid = MakeKey(&fBaseKey, fBase); | 71 make_key(&fBaseKey, fBase); |
| 47 fAppliedPEKeyIsValid = MakeKey(&fAppliedPEKey, fAppliedPE); | 72 make_key(&fAppliedPEKey, fAppliedPE); |
| 48 fAppliedPEThenStrokeKeyIsValid = MakeKey(&fAppliedPEThenStrokeKey, fAppl iedPEThenStroke); | 73 make_key(&fAppliedPEThenStrokeKey, fAppliedPEThenStroke); |
| 49 fAppliedFullKeyIsValid = MakeKey(&fAppliedFullKey, fAppliedFull) ; | 74 make_key(&fAppliedFullKey, fAppliedFull); |
| 50 } | |
| 51 | |
| 52 using Key = SkTArray<uint32_t>; | |
| 53 | |
| 54 static bool MakeKey(Key* key, const GrShape& shape) { | |
| 55 int size = shape.unstyledKeySize(); | |
| 56 if (size <= 0) { | |
| 57 return false; | |
| 58 } | |
| 59 key->reset(size); | |
| 60 shape.writeUnstyledKey(key->begin()); | |
| 61 return true; | |
| 62 } | 75 } |
| 63 | 76 |
| 64 GrShape fBase; | 77 GrShape fBase; |
| 65 GrShape fAppliedPE; | 78 GrShape fAppliedPE; |
| 66 GrShape fAppliedPEThenStroke; | 79 GrShape fAppliedPEThenStroke; |
| 67 GrShape fAppliedFull; | 80 GrShape fAppliedFull; |
| 68 | 81 |
| 69 Key fBaseKey; | 82 Key fBaseKey; |
| 70 Key fAppliedPEKey; | 83 Key fAppliedPEKey; |
| 71 Key fAppliedPEThenStrokeKey; | 84 Key fAppliedPEThenStrokeKey; |
| 72 Key fAppliedFullKey; | 85 Key fAppliedFullKey; |
| 73 | 86 |
| 74 bool fBaseKeyIsValid; | |
| 75 bool fAppliedPEKeyIsValid; | |
| 76 bool fAppliedPEThenStrokeKeyIsValid; | |
| 77 bool fAppliedFullKeyIsValid; | |
| 78 }; | 87 }; |
| 79 | 88 |
| 80 void TestCase::testExpectations(skiatest::Reporter* reporter, SelfExpectations e xpectations) const { | 89 void TestCase::testExpectations(skiatest::Reporter* reporter, SelfExpectations e xpectations) const { |
| 81 // Applying the path effect and then the stroke should always be the same as applying | 90 // Applying the path effect and then the stroke should always be the same as applying |
| 82 // both in one go. | 91 // both in one go. |
| 83 REPORTER_ASSERT(reporter, fAppliedPEThenStrokeKey == fAppliedFullKey); | 92 REPORTER_ASSERT(reporter, fAppliedPEThenStrokeKey == fAppliedFullKey); |
| 93 SkPath a, b; | |
| 94 fAppliedPEThenStroke.asPath(&a); | |
| 95 fAppliedFull.asPath(&b); | |
| 96 REPORTER_ASSERT(reporter, a == b); | |
| 84 // The base's key should always be valid (unless the path is volatile) | 97 // The base's key should always be valid (unless the path is volatile) |
| 85 REPORTER_ASSERT(reporter, fBaseKeyIsValid); | 98 REPORTER_ASSERT(reporter, fBaseKey.count()); |
| 86 if (expectations.fPEHasEffect) { | 99 if (expectations.fPEHasEffect) { |
| 87 REPORTER_ASSERT(reporter, fBaseKey != fAppliedPEKey); | 100 REPORTER_ASSERT(reporter, fBaseKey != fAppliedPEKey); |
| 88 REPORTER_ASSERT(reporter, expectations.fPEHasEffect == fAppliedPEKeyIsVa lid); | 101 REPORTER_ASSERT(reporter, expectations.fPEHasValidKey == SkToBool(fAppli edPEKey.count())); |
| 89 REPORTER_ASSERT(reporter, fBaseKey != fAppliedFullKey); | 102 REPORTER_ASSERT(reporter, fBaseKey != fAppliedFullKey); |
| 90 REPORTER_ASSERT(reporter, expectations.fPEHasEffect == fAppliedFullKeyIs Valid); | 103 REPORTER_ASSERT(reporter, expectations.fPEHasValidKey == SkToBool(fAppli edFullKey.count())); |
| 91 if (expectations.fStrokeApplies && expectations.fPEHasValidKey) { | 104 if (expectations.fStrokeApplies && expectations.fPEHasValidKey) { |
| 92 REPORTER_ASSERT(reporter, fAppliedPEKey != fAppliedFullKey); | 105 REPORTER_ASSERT(reporter, fAppliedPEKey != fAppliedFullKey); |
| 93 REPORTER_ASSERT(reporter, expectations.fPEHasEffect == fAppliedFullK eyIsValid); | 106 REPORTER_ASSERT(reporter, SkToBool(fAppliedFullKey.count())); |
| 94 } | 107 } |
| 95 } else { | 108 } else { |
| 96 REPORTER_ASSERT(reporter, fBaseKey == fAppliedPEKey); | 109 REPORTER_ASSERT(reporter, fBaseKey == fAppliedPEKey); |
| 110 fBase.asPath(&a); | |
| 111 fAppliedPE.asPath(&b); | |
| 112 REPORTER_ASSERT(reporter, a == b); | |
| 97 if (expectations.fStrokeApplies) { | 113 if (expectations.fStrokeApplies) { |
| 98 REPORTER_ASSERT(reporter, fBaseKey != fAppliedFullKey); | 114 REPORTER_ASSERT(reporter, fBaseKey != fAppliedFullKey); |
| 99 } else { | 115 } else { |
| 100 REPORTER_ASSERT(reporter, fBaseKey == fAppliedFullKey); | 116 REPORTER_ASSERT(reporter, fBaseKey == fAppliedFullKey); |
| 101 } | 117 } |
| 102 } | 118 } |
| 103 } | 119 } |
| 104 | 120 |
| 105 void TestCase::compare(skiatest::Reporter* reporter, const TestCase& that, | 121 void TestCase::compare(skiatest::Reporter* reporter, const TestCase& that, |
| 106 ComparisonExpecation expectation) const { | 122 ComparisonExpecation expectation) const { |
| 123 SkPath a, b; | |
| 107 switch (expectation) { | 124 switch (expectation) { |
| 108 case kAllDifferent_ComparisonExpecation: | 125 case kAllDifferent_ComparisonExpecation: |
| 109 REPORTER_ASSERT(reporter, fBaseKey != that.fBaseKey); | 126 REPORTER_ASSERT(reporter, fBaseKey != that.fBaseKey); |
| 110 REPORTER_ASSERT(reporter, fAppliedPEKey != that.fAppliedPEKey); | 127 REPORTER_ASSERT(reporter, fAppliedPEKey != that.fAppliedPEKey); |
| 111 REPORTER_ASSERT(reporter, fAppliedFullKey != that.fAppliedFullKey); | 128 REPORTER_ASSERT(reporter, fAppliedFullKey != that.fAppliedFullKey); |
| 112 break; | 129 break; |
| 113 case kSameUpToPE_ComparisonExpecation: | 130 case kSameUpToPE_ComparisonExpecation: |
| 114 REPORTER_ASSERT(reporter, fBaseKey == that.fBaseKey); | 131 REPORTER_ASSERT(reporter, fBaseKey == that.fBaseKey); |
| 132 fBase.asPath(&a); | |
| 133 that.fBase.asPath(&b); | |
| 134 REPORTER_ASSERT(reporter, a == b); | |
| 115 REPORTER_ASSERT(reporter, fAppliedPEKey != that.fAppliedPEKey); | 135 REPORTER_ASSERT(reporter, fAppliedPEKey != that.fAppliedPEKey); |
| 116 REPORTER_ASSERT(reporter, fAppliedFullKey != that.fAppliedFullKey); | 136 REPORTER_ASSERT(reporter, fAppliedFullKey != that.fAppliedFullKey); |
| 117 break; | 137 break; |
| 118 case kSameUpToStroke_ComparisonExpecation: | 138 case kSameUpToStroke_ComparisonExpecation: |
| 119 REPORTER_ASSERT(reporter, fBaseKey == that.fBaseKey); | 139 REPORTER_ASSERT(reporter, fBaseKey == that.fBaseKey); |
| 140 fBase.asPath(&a); | |
| 141 that.fBase.asPath(&b); | |
| 142 REPORTER_ASSERT(reporter, a == b); | |
| 120 REPORTER_ASSERT(reporter, fAppliedPEKey == that.fAppliedPEKey); | 143 REPORTER_ASSERT(reporter, fAppliedPEKey == that.fAppliedPEKey); |
| 144 fAppliedPE.asPath(&a); | |
| 145 that.fAppliedPE.asPath(&b); | |
| 146 REPORTER_ASSERT(reporter, a == b); | |
| 121 REPORTER_ASSERT(reporter, fAppliedFullKey != that.fAppliedFullKey); | 147 REPORTER_ASSERT(reporter, fAppliedFullKey != that.fAppliedFullKey); |
| 122 break; | 148 break; |
| 123 case kAllSame_ComparisonExpecation: | 149 case kAllSame_ComparisonExpecation: |
| 124 REPORTER_ASSERT(reporter, fBaseKey == that.fBaseKey); | 150 REPORTER_ASSERT(reporter, fBaseKey == that.fBaseKey); |
| 151 fBase.asPath(&a); | |
| 152 that.fBase.asPath(&b); | |
| 153 REPORTER_ASSERT(reporter, a == b); | |
| 125 REPORTER_ASSERT(reporter, fAppliedPEKey == that.fAppliedPEKey); | 154 REPORTER_ASSERT(reporter, fAppliedPEKey == that.fAppliedPEKey); |
| 155 fAppliedPE.asPath(&a); | |
| 156 that.fAppliedPE.asPath(&b); | |
| 157 REPORTER_ASSERT(reporter, a == b); | |
| 126 REPORTER_ASSERT(reporter, fAppliedFullKey == that.fAppliedFullKey); | 158 REPORTER_ASSERT(reporter, fAppliedFullKey == that.fAppliedFullKey); |
| 159 fAppliedFull.asPath(&a); | |
| 160 that.fAppliedFull.asPath(&b); | |
| 161 REPORTER_ASSERT(reporter, a == b); | |
| 127 break; | 162 break; |
| 128 } | 163 } |
| 129 } | 164 } |
| 130 } // namespace | 165 } // namespace |
| 131 | 166 |
| 132 static sk_sp<SkPathEffect> make_dash() { | 167 static sk_sp<SkPathEffect> make_dash() { |
| 133 static const SkScalar kIntervals[] = { 0.25, 3.f, 0.5, 2.f }; | 168 static const SkScalar kIntervals[] = { 0.25, 3.f, 0.5, 2.f }; |
| 134 static const SkScalar kPhase = 0.75; | 169 static const SkScalar kPhase = 0.75; |
| 135 return SkDashPathEffect::Make(kIntervals, SK_ARRAY_COUNT(kIntervals), kPhase ); | 170 return SkDashPathEffect::Make(kIntervals, SK_ARRAY_COUNT(kIntervals), kPhase ); |
| 136 } | 171 } |
| 137 | 172 |
| 138 static sk_sp<SkPathEffect> make_null_dash() { | 173 static sk_sp<SkPathEffect> make_null_dash() { |
| 139 static const SkScalar kNullIntervals[] = {0, 0, 0, 0, 0, 0}; | 174 static const SkScalar kNullIntervals[] = {0, 0, 0, 0, 0, 0}; |
| 140 return SkDashPathEffect::Make(kNullIntervals, SK_ARRAY_COUNT(kNullIntervals) , 0.f); | 175 return SkDashPathEffect::Make(kNullIntervals, SK_ARRAY_COUNT(kNullIntervals) , 0.f); |
| 141 } | 176 } |
| 142 | 177 |
| 143 static void test_basic(skiatest::Reporter* reporter, const SkRRect& rrect) { | 178 template<typename GEO> |
| 179 static void test_basic(skiatest::Reporter* reporter, const GEO& geo) { | |
| 144 sk_sp<SkPathEffect> dashPE = make_dash(); | 180 sk_sp<SkPathEffect> dashPE = make_dash(); |
| 145 | 181 |
| 146 TestCase::SelfExpectations expectations; | 182 TestCase::SelfExpectations expectations; |
| 147 SkPaint fill; | 183 SkPaint fill; |
| 148 | 184 |
| 149 TestCase fillCase(rrect, fill); | 185 TestCase fillCase(geo, fill); |
| 150 expectations.fPEHasEffect = false; | 186 expectations.fPEHasEffect = false; |
| 151 expectations.fPEHasValidKey = false; | 187 expectations.fPEHasValidKey = false; |
| 152 expectations.fStrokeApplies = false; | 188 expectations.fStrokeApplies = false; |
| 153 fillCase.testExpectations(reporter, expectations); | 189 fillCase.testExpectations(reporter, expectations); |
| 154 // Test that another GrShape instance built from the same primitive is the s ame. | 190 // Test that another GrShape instance built from the same primitive is the s ame. |
| 155 TestCase(rrect, fill).compare(reporter, fillCase, TestCase::kAllSame_Compari sonExpecation); | 191 TestCase(geo, fill).compare(reporter, fillCase, TestCase::kAllSame_Compariso nExpecation); |
| 156 | 192 |
| 157 SkPaint stroke2RoundBevel; | 193 SkPaint stroke2RoundBevel; |
| 158 stroke2RoundBevel.setStyle(SkPaint::kStroke_Style); | 194 stroke2RoundBevel.setStyle(SkPaint::kStroke_Style); |
| 159 stroke2RoundBevel.setStrokeCap(SkPaint::kRound_Cap); | 195 stroke2RoundBevel.setStrokeCap(SkPaint::kRound_Cap); |
| 160 stroke2RoundBevel.setStrokeJoin(SkPaint::kBevel_Join); | 196 stroke2RoundBevel.setStrokeJoin(SkPaint::kBevel_Join); |
| 161 stroke2RoundBevel.setStrokeWidth(2.f); | 197 stroke2RoundBevel.setStrokeWidth(2.f); |
| 162 TestCase stroke2RoundBevelCase(rrect, stroke2RoundBevel); | 198 TestCase stroke2RoundBevelCase(geo, stroke2RoundBevel); |
| 163 expectations.fPEHasValidKey = true; | 199 expectations.fPEHasValidKey = true; |
| 164 expectations.fPEHasEffect = false; | 200 expectations.fPEHasEffect = false; |
| 165 expectations.fStrokeApplies = true; | 201 expectations.fStrokeApplies = true; |
| 166 stroke2RoundBevelCase.testExpectations(reporter, expectations); | 202 stroke2RoundBevelCase.testExpectations(reporter, expectations); |
| 167 TestCase(rrect, stroke2RoundBevel).compare(reporter, stroke2RoundBevelCase, | 203 TestCase(geo, stroke2RoundBevel).compare(reporter, stroke2RoundBevelCase, |
| 168 TestCase::kAllSame_ComparisonExpe cation); | 204 TestCase::kAllSame_ComparisonExpeca tion); |
| 169 | 205 |
| 170 SkPaint stroke2RoundBevelDash = stroke2RoundBevel; | 206 SkPaint stroke2RoundBevelDash = stroke2RoundBevel; |
| 171 stroke2RoundBevelDash.setPathEffect(make_dash()); | 207 stroke2RoundBevelDash.setPathEffect(make_dash()); |
| 172 TestCase stroke2RoundBevelDashCase(rrect, stroke2RoundBevelDash); | 208 TestCase stroke2RoundBevelDashCase(geo, stroke2RoundBevelDash); |
| 173 expectations.fPEHasValidKey = true; | 209 expectations.fPEHasValidKey = true; |
| 174 expectations.fPEHasEffect = true; | 210 expectations.fPEHasEffect = true; |
| 175 expectations.fStrokeApplies = true; | 211 expectations.fStrokeApplies = true; |
| 176 stroke2RoundBevelDashCase.testExpectations(reporter, expectations); | 212 stroke2RoundBevelDashCase.testExpectations(reporter, expectations); |
| 177 TestCase(rrect, stroke2RoundBevelDash).compare(reporter, stroke2RoundBevelDa shCase, | 213 TestCase(geo, stroke2RoundBevelDash).compare(reporter, stroke2RoundBevelDash Case, |
| 178 TestCase::kAllSame_Comparison Expecation); | 214 TestCase::kAllSame_ComparisonEx pecation); |
| 179 | 215 |
| 180 fillCase.compare(reporter, stroke2RoundBevelCase, | 216 fillCase.compare(reporter, stroke2RoundBevelCase, |
| 181 TestCase::kSameUpToStroke_ComparisonExpecation); | 217 TestCase::kSameUpToStroke_ComparisonExpecation); |
| 182 fillCase.compare(reporter, stroke2RoundBevelDashCase, | 218 fillCase.compare(reporter, stroke2RoundBevelDashCase, |
| 183 TestCase::kSameUpToPE_ComparisonExpecation); | 219 TestCase::kSameUpToPE_ComparisonExpecation); |
| 184 stroke2RoundBevelCase.compare(reporter, stroke2RoundBevelDashCase, | 220 stroke2RoundBevelCase.compare(reporter, stroke2RoundBevelDashCase, |
| 185 TestCase::kSameUpToPE_ComparisonExpecation); | 221 TestCase::kSameUpToPE_ComparisonExpecation); |
| 222 | |
| 223 SkPaint hairline; | |
| 224 hairline.setStyle(SkPaint::kStroke_Style); | |
| 225 hairline.setStrokeWidth(0.f); | |
| 226 TestCase hairlineCase(geo, hairline); | |
| 227 // Since hairline style doesn't change the SkPath data, it is keyed identica lly to fill. | |
| 228 hairlineCase.compare(reporter, fillCase, TestCase::kAllSame_ComparisonExpeca tion); | |
| 186 } | 229 } |
| 187 | 230 |
| 188 template <typename T> | 231 template <typename GEO, typename T> |
| 189 static void test_stroke_param(skiatest::Reporter* reporter, const SkRRect& rrect , | 232 static void test_stroke_param(skiatest::Reporter* reporter, const GEO& geo, |
| 190 std::function<void(SkPaint*, T)> setter, T a, T b) { | 233 std::function<void(SkPaint*, T)> setter, T a, T b) { |
| 191 // Set the stroke width so that we don't get hairline. However, call the fun ction second so that | 234 // Set the stroke width so that we don't get hairline. However, call the fun ction second so that |
| 192 // it can override. | 235 // it can override. |
| 193 SkPaint strokeA; | 236 SkPaint strokeA; |
| 194 strokeA.setStyle(SkPaint::kStroke_Style); | 237 strokeA.setStyle(SkPaint::kStroke_Style); |
| 195 strokeA.setStrokeWidth(2.f); | 238 strokeA.setStrokeWidth(2.f); |
| 196 setter(&strokeA, a); | 239 setter(&strokeA, a); |
| 197 SkPaint strokeB; | 240 SkPaint strokeB; |
| 198 strokeB.setStyle(SkPaint::kStroke_Style); | 241 strokeB.setStyle(SkPaint::kStroke_Style); |
| 199 strokeB.setStrokeWidth(2.f); | 242 strokeB.setStrokeWidth(2.f); |
| 200 setter(&strokeB, b); | 243 setter(&strokeB, b); |
| 201 | 244 |
| 202 TestCase strokeACase(rrect, strokeA); | 245 TestCase strokeACase(geo, strokeA); |
| 203 TestCase strokeBCase(rrect, strokeB); | 246 TestCase strokeBCase(geo, strokeB); |
| 204 strokeACase.compare(reporter, strokeBCase, TestCase::kSameUpToStroke_Compari sonExpecation); | 247 strokeACase.compare(reporter, strokeBCase, TestCase::kSameUpToStroke_Compari sonExpecation); |
| 205 | 248 |
| 206 // Make sure stroking params don't affect fill style. | 249 // Make sure stroking params don't affect fill style. |
| 207 SkPaint fillA = strokeA, fillB = strokeB; | 250 SkPaint fillA = strokeA, fillB = strokeB; |
| 208 fillA.setStyle(SkPaint::kFill_Style); | 251 fillA.setStyle(SkPaint::kFill_Style); |
| 209 fillB.setStyle(SkPaint::kFill_Style); | 252 fillB.setStyle(SkPaint::kFill_Style); |
| 210 TestCase fillACase(rrect, fillA); | 253 TestCase fillACase(geo, fillA); |
| 211 TestCase fillBCase(rrect, fillB); | 254 TestCase fillBCase(geo, fillB); |
| 212 fillACase.compare(reporter, fillBCase, TestCase::kAllSame_ComparisonExpecati on); | 255 fillACase.compare(reporter, fillBCase, TestCase::kAllSame_ComparisonExpecati on); |
| 213 | 256 |
| 214 // Make sure just applying the dash but not stroke gives the same key for bo th stroking | 257 // Make sure just applying the dash but not stroke gives the same key for bo th stroking |
| 215 // variations. | 258 // variations. |
| 216 SkPaint dashA = strokeA, dashB = strokeB; | 259 SkPaint dashA = strokeA, dashB = strokeB; |
| 217 dashA.setPathEffect(make_dash()); | 260 dashA.setPathEffect(make_dash()); |
| 218 dashB.setPathEffect(make_dash()); | 261 dashB.setPathEffect(make_dash()); |
| 219 TestCase dashACase(rrect, dashA); | 262 TestCase dashACase(geo, dashA); |
| 220 TestCase dashBCase(rrect, dashB); | 263 TestCase dashBCase(geo, dashB); |
| 221 dashACase.compare(reporter, dashBCase, TestCase::kSameUpToStroke_ComparisonE xpecation); | 264 dashACase.compare(reporter, dashBCase, TestCase::kSameUpToStroke_ComparisonE xpecation); |
| 222 } | 265 } |
| 223 | 266 |
| 224 static void test_miter_limit(skiatest::Reporter* reporter, const SkRRect& rrect) { | 267 template <typename GEO> |
| 268 static void test_miter_limit(skiatest::Reporter* reporter, const GEO& geo) { | |
| 225 // Miter limit should only matter when stroking with miter joins. It shouldn 't affect other | 269 // Miter limit should only matter when stroking with miter joins. It shouldn 't affect other |
| 226 // joins or fills. | 270 // joins or fills. |
| 227 SkPaint miterA; | 271 SkPaint miterA; |
| 228 miterA.setStyle(SkPaint::kStroke_Style); | 272 miterA.setStyle(SkPaint::kStroke_Style); |
| 229 miterA.setStrokeWidth(2.f); | 273 miterA.setStrokeWidth(2.f); |
| 230 miterA.setStrokeJoin(SkPaint::kMiter_Join); | 274 miterA.setStrokeJoin(SkPaint::kMiter_Join); |
| 231 miterA.setStrokeMiter(0.5f); | 275 miterA.setStrokeMiter(0.5f); |
| 232 SkPaint miterB = miterA; | 276 SkPaint miterB = miterA; |
| 233 miterA.setStrokeMiter(0.6f); | 277 miterA.setStrokeMiter(0.6f); |
| 234 | 278 |
| 235 TestCase miterACase(rrect, miterA); | 279 TestCase miterACase(geo, miterA); |
| 236 TestCase miterBCase(rrect, miterB); | 280 TestCase miterBCase(geo, miterB); |
| 237 miterACase.compare(reporter, miterBCase, TestCase::kSameUpToStroke_Compariso nExpecation); | 281 miterACase.compare(reporter, miterBCase, TestCase::kSameUpToStroke_Compariso nExpecation); |
| 238 | 282 |
| 239 SkPaint noMiterA = miterA, noMiterB = miterB; | 283 SkPaint noMiterA = miterA, noMiterB = miterB; |
| 240 noMiterA.setStrokeJoin(SkPaint::kRound_Join); | 284 noMiterA.setStrokeJoin(SkPaint::kRound_Join); |
| 241 noMiterB.setStrokeJoin(SkPaint::kRound_Join); | 285 noMiterB.setStrokeJoin(SkPaint::kRound_Join); |
| 242 TestCase noMiterACase(rrect, noMiterA); | 286 TestCase noMiterACase(geo, noMiterA); |
| 243 TestCase noMiterBCase(rrect, noMiterB); | 287 TestCase noMiterBCase(geo, noMiterB); |
| 244 noMiterACase.compare(reporter, noMiterBCase, TestCase::kAllSame_ComparisonEx pecation); | 288 noMiterACase.compare(reporter, noMiterBCase, TestCase::kAllSame_ComparisonEx pecation); |
| 245 | 289 |
| 246 SkPaint fillA = miterA, fillB = miterB; | 290 SkPaint fillA = miterA, fillB = miterB; |
| 247 fillA.setStyle(SkPaint::kFill_Style); | 291 fillA.setStyle(SkPaint::kFill_Style); |
| 248 fillB.setStyle(SkPaint::kFill_Style); | 292 fillB.setStyle(SkPaint::kFill_Style); |
| 249 TestCase fillACase(rrect, fillA); | 293 TestCase fillACase(geo, fillA); |
| 250 TestCase fillBCase(rrect, fillB); | 294 TestCase fillBCase(geo, fillB); |
| 251 fillACase.compare(reporter, fillBCase, TestCase::kAllSame_ComparisonExpecati on); | 295 fillACase.compare(reporter, fillBCase, TestCase::kAllSame_ComparisonExpecati on); |
| 252 } | 296 } |
| 253 | 297 |
| 254 static void test_dash_fill(skiatest::Reporter* reporter, const SkRRect& rrect) { | 298 template<typename GEO> |
| 299 static void test_dash_fill(skiatest::Reporter* reporter, const GEO& geo) { | |
| 255 // A dash with no stroke should have no effect | 300 // A dash with no stroke should have no effect |
| 256 using DashFactoryFn = sk_sp<SkPathEffect>(*)(); | 301 using DashFactoryFn = sk_sp<SkPathEffect>(*)(); |
| 257 for (DashFactoryFn md : {&make_dash, &make_null_dash}) { | 302 for (DashFactoryFn md : {&make_dash, &make_null_dash}) { |
| 258 SkPaint dashFill; | 303 SkPaint dashFill; |
| 259 dashFill.setPathEffect((*md)()); | 304 dashFill.setPathEffect((*md)()); |
| 260 TestCase dashFillCase(rrect, dashFill); | 305 TestCase dashFillCase(geo, dashFill); |
| 261 | 306 |
| 262 TestCase fillCase(rrect, SkPaint()); | 307 TestCase fillCase(geo, SkPaint()); |
| 263 dashFillCase.compare(reporter, fillCase, TestCase::kAllSame_ComparisonEx pecation); | 308 dashFillCase.compare(reporter, fillCase, TestCase::kAllSame_ComparisonEx pecation); |
| 264 } | 309 } |
| 265 } | 310 } |
| 266 | 311 |
| 267 void test_null_dash(skiatest::Reporter* reporter, const SkRRect& rrect) { | 312 template<typename GEO> |
| 313 void test_null_dash(skiatest::Reporter* reporter, const GEO& geo) { | |
| 268 SkPaint fill; | 314 SkPaint fill; |
| 269 SkPaint stroke; | 315 SkPaint stroke; |
| 270 stroke.setStyle(SkPaint::kStroke_Style); | 316 stroke.setStyle(SkPaint::kStroke_Style); |
| 271 stroke.setStrokeWidth(1.f); | 317 stroke.setStrokeWidth(1.f); |
| 272 SkPaint dash; | 318 SkPaint dash; |
| 273 dash.setStyle(SkPaint::kStroke_Style); | 319 dash.setStyle(SkPaint::kStroke_Style); |
| 274 dash.setStrokeWidth(1.f); | 320 dash.setStrokeWidth(1.f); |
| 275 dash.setPathEffect(make_dash()); | 321 dash.setPathEffect(make_dash()); |
| 276 SkPaint nullDash; | 322 SkPaint nullDash; |
| 277 nullDash.setStyle(SkPaint::kStroke_Style); | 323 nullDash.setStyle(SkPaint::kStroke_Style); |
| 278 nullDash.setStrokeWidth(1.f); | 324 nullDash.setStrokeWidth(1.f); |
| 279 nullDash.setPathEffect(make_null_dash()); | 325 nullDash.setPathEffect(make_null_dash()); |
| 280 | 326 |
| 281 TestCase fillCase(rrect, fill); | 327 TestCase fillCase(geo, fill); |
| 282 TestCase strokeCase(rrect, stroke); | 328 TestCase strokeCase(geo, stroke); |
| 283 TestCase dashCase(rrect, dash); | 329 TestCase dashCase(geo, dash); |
| 284 TestCase nullDashCase(rrect, nullDash); | 330 TestCase nullDashCase(geo, nullDash); |
| 285 | 331 |
| 286 nullDashCase.compare(reporter, fillCase, TestCase::kSameUpToStroke_Compariso nExpecation); | 332 nullDashCase.compare(reporter, fillCase, TestCase::kSameUpToStroke_Compariso nExpecation); |
| 287 nullDashCase.compare(reporter, strokeCase, TestCase::kAllSame_ComparisonExpe cation); | 333 nullDashCase.compare(reporter, strokeCase, TestCase::kAllSame_ComparisonExpe cation); |
| 288 nullDashCase.compare(reporter, dashCase, TestCase::kSameUpToPE_ComparisonExp ecation); | 334 nullDashCase.compare(reporter, dashCase, TestCase::kSameUpToPE_ComparisonExp ecation); |
| 289 } | 335 } |
| 290 | 336 |
| 337 template <typename GEO> | |
| 338 void test_path_effect_makes_rrect(skiatest::Reporter* reporter, const GEO& geo) { | |
| 339 /** | |
| 340 * This path effect takes any input path and turns it into a rrect. It passe s through stroke | |
| 341 * info. | |
| 342 */ | |
| 343 class RRectPathEffect : SkPathEffect { | |
| 344 public: | |
| 345 static const SkRRect& RRect() { | |
| 346 static const SkRRect kRRect = SkRRect::MakeRectXY(SkRect::MakeWH(12, 12), 3, 5); | |
| 347 return kRRect; | |
| 348 } | |
| 349 | |
| 350 bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, | |
| 351 const SkRect* cullR) const override { | |
| 352 dst->reset(); | |
| 353 dst->addRRect(RRect()); | |
| 354 return true; | |
| 355 } | |
| 356 void computeFastBounds(SkRect* dst, const SkRect& src) const override { | |
| 357 *dst = RRect().getBounds(); | |
| 358 } | |
| 359 static sk_sp<SkPathEffect> Make() { return sk_sp<SkPathEffect>(new RRect PathEffect); } | |
| 360 Factory getFactory() const override { return nullptr; } | |
| 361 void toString(SkString*) const override {} | |
| 362 private: | |
| 363 RRectPathEffect() {} | |
| 364 }; | |
| 365 | |
| 366 SkPaint fill; | |
| 367 TestCase fillGeoCase(geo, fill); | |
| 368 | |
| 369 SkPaint pe; | |
| 370 pe.setPathEffect(RRectPathEffect::Make()); | |
| 371 TestCase geoPECase(geo, pe); | |
| 372 | |
| 373 SkPaint peStroke; | |
| 374 peStroke.setPathEffect(RRectPathEffect::Make()); | |
| 375 peStroke.setStrokeWidth(2.f); | |
| 376 peStroke.setStyle(SkPaint::kStroke_Style); | |
| 377 TestCase geoPEStrokeCase(geo, peStroke); | |
| 378 | |
| 379 fillGeoCase.compare(reporter, geoPECase, TestCase::kSameUpToPE_ComparisonExp ecation); | |
| 380 fillGeoCase.compare(reporter, geoPEStrokeCase, TestCase::kSameUpToPE_Compari sonExpecation); | |
| 381 geoPECase.compare(reporter, geoPEStrokeCase, | |
| 382 TestCase::kSameUpToStroke_ComparisonExpecation); | |
| 383 | |
| 384 TestCase rrectFillCase(RRectPathEffect::RRect(), fill); | |
| 385 SkPaint stroke = peStroke; | |
| 386 stroke.setPathEffect(nullptr); | |
| 387 TestCase rrectStrokeCase(RRectPathEffect::RRect(), stroke); | |
| 388 | |
| 389 SkRRect rrect; | |
| 390 // Applying the path effect should make a SkRRect shape. There is no further stroking in the | |
| 391 // geoPECase, so the full style should be the same as just the PE. | |
| 392 REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectShape().asRRect(&rrect) ); | |
| 393 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); | |
| 394 REPORTER_ASSERT(reporter, geoPECase.appliedPathEffectKey() == rrectFillCase. baseKey()); | |
| 395 | |
| 396 REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleShape().asRRect(&rrect)) ; | |
| 397 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); | |
| 398 REPORTER_ASSERT(reporter, geoPECase.appliedFullStyleKey() == rrectFillCase.b aseKey()); | |
| 399 | |
| 400 // In the PE+stroke case applying the full style should be the same as just stroking the rrect. | |
| 401 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectShape().asRRect(& rrect)); | |
| 402 REPORTER_ASSERT(reporter, rrect == RRectPathEffect::RRect()); | |
| 403 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedPathEffectKey() == rrectFil lCase.baseKey()); | |
| 404 | |
| 405 REPORTER_ASSERT(reporter, !geoPEStrokeCase.appliedFullStyleShape().asRRect(& rrect)); | |
| 406 REPORTER_ASSERT(reporter, geoPEStrokeCase.appliedFullStyleKey() == | |
| 407 rrectStrokeCase.appliedFullStyleKey()); | |
| 408 } | |
| 409 | |
| 410 template <typename GEO> | |
| 411 void test_unknown_path_effect(skiatest::Reporter* reporter, const GEO& geo) { | |
| 412 /** | |
| 413 * This path effect just adds two lineTos to the input path. | |
| 414 */ | |
| 415 class AddLineTosPathEffect : SkPathEffect { | |
| 416 public: | |
| 417 bool filterPath(SkPath* dst, const SkPath& src, SkStrokeRec*, | |
| 418 const SkRect* cullR) const override { | |
| 419 *dst = src; | |
| 420 dst->lineTo(0, 0); | |
| 421 dst->lineTo(10, 10); | |
| 422 return true; | |
| 423 } | |
| 424 void computeFastBounds(SkRect* dst, const SkRect& src) const override { | |
| 425 *dst = src; | |
| 426 dst->growToInclude(0, 0); | |
| 427 dst->growToInclude(10, 10); | |
| 428 } | |
| 429 static sk_sp<SkPathEffect> Make() { return sk_sp<SkPathEffect>(new AddLi neTosPathEffect); } | |
| 430 Factory getFactory() const override { return nullptr; } | |
| 431 void toString(SkString*) const override {} | |
| 432 private: | |
| 433 AddLineTosPathEffect() {} | |
| 434 }; | |
| 435 | |
| 436 /** This path effect should make the keys invalid when it is applied. */ | |
|
robertphillips
2016/04/26 22:18:32
Could you expand on this a bit?
bsalomon
2016/04/29 23:12:06
Done.
// This path effect should make the ke
| |
| 437 SkPaint peStroke; | |
| 438 peStroke.setPathEffect(AddLineTosPathEffect::Make()); | |
| 439 peStroke.setStrokeWidth(2.f); | |
| 440 peStroke.setStyle(SkPaint::kStroke_Style); | |
| 441 TestCase geoPEStrokeCase(geo, peStroke); | |
| 442 TestCase::SelfExpectations expectations; | |
| 443 expectations.fPEHasEffect = true; | |
| 444 expectations.fPEHasValidKey = false; | |
| 445 expectations.fStrokeApplies = true; | |
| 446 geoPEStrokeCase.testExpectations(reporter, expectations); | |
| 447 } | |
| 448 | |
| 291 DEF_TEST(GrShape, reporter) { | 449 DEF_TEST(GrShape, reporter) { |
| 292 sk_sp<SkPathEffect> dashPE = make_dash(); | 450 sk_sp<SkPathEffect> dashPE = make_dash(); |
| 293 | 451 |
| 294 for (auto rr : { SkRRect::MakeRect(SkRect::MakeWH(10, 10)), | 452 for (auto rr : { SkRRect::MakeRect(SkRect::MakeWH(10, 10)), |
| 295 SkRRect::MakeRectXY(SkRect::MakeWH(10, 10), 3, 4)}) { | 453 SkRRect::MakeRectXY(SkRect::MakeWH(10, 10), 3, 4)}) { |
| 296 test_basic(reporter, rr); | 454 test_basic(reporter, rr); |
| 297 test_dash_fill(reporter, rr); | 455 test_dash_fill(reporter, rr); |
| 298 test_null_dash(reporter, rr); | 456 test_null_dash(reporter, rr); |
| 299 // Test modifying various stroke params. | 457 // Test modifying various stroke params. |
| 300 test_stroke_param<SkScalar>( | 458 test_stroke_param<SkRRect, SkScalar>( |
| 301 reporter, rr, | 459 reporter, rr, |
| 302 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, | 460 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, |
| 303 SkIntToScalar(2), SkIntToScalar(4)); | 461 SkIntToScalar(2), SkIntToScalar(4)); |
| 304 test_stroke_param<SkPaint::Cap>( | 462 test_stroke_param<SkRRect, SkPaint::Cap>( |
| 305 reporter, rr, | 463 reporter, rr, |
| 306 [](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);}, | 464 [](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);}, |
| 307 SkPaint::kButt_Cap, SkPaint::kRound_Cap); | 465 SkPaint::kButt_Cap, SkPaint::kRound_Cap); |
| 308 test_stroke_param<SkPaint::Join>( | 466 test_stroke_param<SkRRect, SkPaint::Join>( |
| 309 reporter, rr, | 467 reporter, rr, |
| 310 [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j); }, | 468 [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j); }, |
| 311 SkPaint::kMiter_Join, SkPaint::kRound_Join); | 469 SkPaint::kMiter_Join, SkPaint::kRound_Join); |
| 312 test_miter_limit(reporter, rr); | 470 test_miter_limit(reporter, rr); |
| 471 test_path_effect_makes_rrect(reporter, rr); | |
| 472 test_unknown_path_effect(reporter, rr); | |
| 473 } | |
| 474 | |
| 475 struct TestPath { | |
| 476 TestPath(const SkPath& path, bool isRRectFill, bool isRRectStroke ,const SkRRect& rrect) | |
| 477 : fPath(path) | |
| 478 , fIsRRectForFill(isRRectFill) | |
| 479 , fIsRRectForStroke(isRRectStroke) | |
| 480 , fRRect(rrect) {} | |
| 481 SkPath fPath; | |
| 482 bool fIsRRectForFill; | |
| 483 bool fIsRRectForStroke; | |
| 484 SkRRect fRRect; | |
| 485 }; | |
| 486 SkTArray<TestPath> paths; | |
| 487 | |
| 488 SkPath circlePath; | |
| 489 circlePath.addCircle(10, 10, 10); | |
| 490 paths.emplace_back(circlePath, true, true, SkRRect::MakeOval(SkRect::MakeWH( 20,20))); | |
| 491 | |
| 492 SkPath rectPath; | |
| 493 rectPath.addRect(SkRect::MakeWH(10, 10)); | |
| 494 paths.emplace_back(rectPath, true, true, SkRRect::MakeRect(SkRect::MakeWH(10 , 10))); | |
| 495 | |
| 496 SkPath openRectPath; | |
| 497 openRectPath.moveTo(0, 0); | |
| 498 openRectPath.lineTo(10, 0); | |
| 499 openRectPath.lineTo(10, 10); | |
| 500 openRectPath.lineTo(0, 10); | |
| 501 paths.emplace_back(openRectPath, true, false, SkRRect::MakeRect(SkRect::Make WH(10, 10))); | |
| 502 | |
| 503 SkPath quadPath; | |
| 504 quadPath.quadTo(10, 10, 5, 8); | |
| 505 paths.emplace_back(quadPath, false, false, SkRRect()); | |
| 506 | |
| 507 for (auto testPath : paths) { | |
| 508 const SkPath& path = testPath.fPath; | |
|
robertphillips
2016/04/26 22:18:32
Theses tests all that the ?
bsalomon
2016/04/29 23:12:06
Done.
"These tests all assume that"
| |
| 509 // Theses tests all that the original GrShape for fill and stroke will b e the same. However, | |
| 510 // that is not the case in special cases (e.g. a unclosed rect becomes a RRect GrShape with | |
| 511 // a fill style but becomes a Path GrShape when stroked). | |
| 512 if (testPath.fIsRRectForFill == testPath.fIsRRectForStroke) { | |
| 513 test_basic(reporter, path); | |
| 514 test_null_dash(reporter, path); | |
| 515 test_path_effect_makes_rrect(reporter, path); | |
| 516 } | |
| 517 test_dash_fill(reporter, path); | |
| 518 // Test modifying various stroke params. | |
| 519 test_stroke_param<SkPath, SkScalar>( | |
| 520 reporter, path, | |
| 521 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, | |
| 522 SkIntToScalar(2), SkIntToScalar(4)); | |
| 523 test_stroke_param<SkPath, SkPaint::Cap>( | |
| 524 reporter, path, | |
| 525 [](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);}, | |
| 526 SkPaint::kButt_Cap, SkPaint::kRound_Cap); | |
| 527 test_stroke_param<SkPath, SkPaint::Join>( | |
| 528 reporter, path, | |
| 529 [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);}, | |
| 530 SkPaint::kMiter_Join, SkPaint::kRound_Join); | |
| 531 test_miter_limit(reporter, path); | |
| 532 test_unknown_path_effect(reporter, path); | |
| 533 | |
| 534 SkPaint fillPaint; | |
| 535 TestCase fillPathCase(path, fillPaint); | |
| 536 SkRRect rrect; | |
| 537 REPORTER_ASSERT(reporter, testPath.fIsRRectForFill == | |
| 538 fillPathCase.baseShape().asRRect(&rrect)); | |
| 539 if (testPath.fIsRRectForFill) { | |
| 540 REPORTER_ASSERT(reporter, rrect == testPath.fRRect); | |
| 541 TestCase fillRRectCase(rrect, fillPaint); | |
| 542 fillPathCase.compare(reporter, fillRRectCase, TestCase::kAllSame_Com parisonExpecation); | |
| 543 } | |
| 544 | |
| 545 SkPaint strokePaint; | |
| 546 strokePaint.setStrokeWidth(3.f); | |
| 547 strokePaint.setStyle(SkPaint::kStroke_Style); | |
| 548 TestCase strokePathCase(path, strokePaint); | |
| 549 REPORTER_ASSERT(reporter, testPath.fIsRRectForStroke == | |
| 550 strokePathCase.baseShape().asRRect(&rrect)); | |
| 551 if (testPath.fIsRRectForStroke) { | |
| 552 REPORTER_ASSERT(reporter, rrect == testPath.fRRect); | |
| 553 TestCase strokeRRectCase(rrect, strokePaint); | |
| 554 strokePathCase.compare(reporter, strokeRRectCase, | |
| 555 TestCase::kAllSame_ComparisonExpecation); | |
| 556 } | |
| 313 } | 557 } |
| 314 } | 558 } |
| 315 | 559 |
| 316 #endif | 560 #endif |
| OLD | NEW |