Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Side by Side Diff: tests/GrShapeTest.cpp

Issue 1922713002: Add support for building GrShape from SkPath and more tests (Closed) Base URL: https://chromium.googlesource.com/skia.git@strokeinfo
Patch Set: Address comments Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrShape.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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. We onl y produce a pathe
437 // effect key for dash path effects. So the only way another arbitrary path effect can produce
438 // a styled result with a key is to produce a non-path shape that has a pur ely geometric key.
439 SkPaint peStroke;
440 peStroke.setPathEffect(AddLineTosPathEffect::Make());
441 peStroke.setStrokeWidth(2.f);
442 peStroke.setStyle(SkPaint::kStroke_Style);
443 TestCase geoPEStrokeCase(geo, peStroke);
444 TestCase::SelfExpectations expectations;
445 expectations.fPEHasEffect = true;
446 expectations.fPEHasValidKey = false;
447 expectations.fStrokeApplies = true;
448 geoPEStrokeCase.testExpectations(reporter, expectations);
449 }
450
291 DEF_TEST(GrShape, reporter) { 451 DEF_TEST(GrShape, reporter) {
292 sk_sp<SkPathEffect> dashPE = make_dash(); 452 sk_sp<SkPathEffect> dashPE = make_dash();
293 453
294 for (auto rr : { SkRRect::MakeRect(SkRect::MakeWH(10, 10)), 454 for (auto rr : { SkRRect::MakeRect(SkRect::MakeWH(10, 10)),
295 SkRRect::MakeRectXY(SkRect::MakeWH(10, 10), 3, 4)}) { 455 SkRRect::MakeRectXY(SkRect::MakeWH(10, 10), 3, 4)}) {
296 test_basic(reporter, rr); 456 test_basic(reporter, rr);
297 test_dash_fill(reporter, rr); 457 test_dash_fill(reporter, rr);
298 test_null_dash(reporter, rr); 458 test_null_dash(reporter, rr);
299 // Test modifying various stroke params. 459 // Test modifying various stroke params.
300 test_stroke_param<SkScalar>( 460 test_stroke_param<SkRRect, SkScalar>(
301 reporter, rr, 461 reporter, rr,
302 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);}, 462 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);},
303 SkIntToScalar(2), SkIntToScalar(4)); 463 SkIntToScalar(2), SkIntToScalar(4));
304 test_stroke_param<SkPaint::Cap>( 464 test_stroke_param<SkRRect, SkPaint::Cap>(
305 reporter, rr, 465 reporter, rr,
306 [](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);}, 466 [](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);},
307 SkPaint::kButt_Cap, SkPaint::kRound_Cap); 467 SkPaint::kButt_Cap, SkPaint::kRound_Cap);
308 test_stroke_param<SkPaint::Join>( 468 test_stroke_param<SkRRect, SkPaint::Join>(
309 reporter, rr, 469 reporter, rr,
310 [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j); }, 470 [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j); },
311 SkPaint::kMiter_Join, SkPaint::kRound_Join); 471 SkPaint::kMiter_Join, SkPaint::kRound_Join);
312 test_miter_limit(reporter, rr); 472 test_miter_limit(reporter, rr);
473 test_path_effect_makes_rrect(reporter, rr);
474 test_unknown_path_effect(reporter, rr);
475 }
476
477 struct TestPath {
478 TestPath(const SkPath& path, bool isRRectFill, bool isRRectStroke ,const SkRRect& rrect)
479 : fPath(path)
480 , fIsRRectForFill(isRRectFill)
481 , fIsRRectForStroke(isRRectStroke)
482 , fRRect(rrect) {}
483 SkPath fPath;
484 bool fIsRRectForFill;
485 bool fIsRRectForStroke;
486 SkRRect fRRect;
487 };
488 SkTArray<TestPath> paths;
489
490 SkPath circlePath;
491 circlePath.addCircle(10, 10, 10);
492 paths.emplace_back(circlePath, true, true, SkRRect::MakeOval(SkRect::MakeWH( 20,20)));
493
494 SkPath rectPath;
495 rectPath.addRect(SkRect::MakeWH(10, 10));
496 paths.emplace_back(rectPath, true, true, SkRRect::MakeRect(SkRect::MakeWH(10 , 10)));
497
498 SkPath openRectPath;
499 openRectPath.moveTo(0, 0);
500 openRectPath.lineTo(10, 0);
501 openRectPath.lineTo(10, 10);
502 openRectPath.lineTo(0, 10);
503 paths.emplace_back(openRectPath, true, false, SkRRect::MakeRect(SkRect::Make WH(10, 10)));
504
505 SkPath quadPath;
506 quadPath.quadTo(10, 10, 5, 8);
507 paths.emplace_back(quadPath, false, false, SkRRect());
508
509 for (auto testPath : paths) {
510 const SkPath& path = testPath.fPath;
511 // These tests all assume that the original GrShape for fill and stroke will be the same.
512 // However, that is not the case in special cases (e.g. a unclosed rect becomes a RRect
513 // GrShape with a fill style but becomes a Path GrShape when stroked).
514 if (testPath.fIsRRectForFill == testPath.fIsRRectForStroke) {
515 test_basic(reporter, path);
516 test_null_dash(reporter, path);
517 test_path_effect_makes_rrect(reporter, path);
518 }
519 test_dash_fill(reporter, path);
520 // Test modifying various stroke params.
521 test_stroke_param<SkPath, SkScalar>(
522 reporter, path,
523 [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);},
524 SkIntToScalar(2), SkIntToScalar(4));
525 test_stroke_param<SkPath, SkPaint::Cap>(
526 reporter, path,
527 [](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);},
528 SkPaint::kButt_Cap, SkPaint::kRound_Cap);
529 test_stroke_param<SkPath, SkPaint::Join>(
530 reporter, path,
531 [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);},
532 SkPaint::kMiter_Join, SkPaint::kRound_Join);
533 test_miter_limit(reporter, path);
534 test_unknown_path_effect(reporter, path);
535
536 SkPaint fillPaint;
537 TestCase fillPathCase(path, fillPaint);
538 SkRRect rrect;
539 REPORTER_ASSERT(reporter, testPath.fIsRRectForFill ==
540 fillPathCase.baseShape().asRRect(&rrect));
541 if (testPath.fIsRRectForFill) {
542 REPORTER_ASSERT(reporter, rrect == testPath.fRRect);
543 TestCase fillRRectCase(rrect, fillPaint);
544 fillPathCase.compare(reporter, fillRRectCase, TestCase::kAllSame_Com parisonExpecation);
545 }
546
547 SkPaint strokePaint;
548 strokePaint.setStrokeWidth(3.f);
549 strokePaint.setStyle(SkPaint::kStroke_Style);
550 TestCase strokePathCase(path, strokePaint);
551 REPORTER_ASSERT(reporter, testPath.fIsRRectForStroke ==
552 strokePathCase.baseShape().asRRect(&rrect));
553 if (testPath.fIsRRectForStroke) {
554 REPORTER_ASSERT(reporter, rrect == testPath.fRRect);
555 TestCase strokeRRectCase(rrect, strokePaint);
556 strokePathCase.compare(reporter, strokeRRectCase,
557 TestCase::kAllSame_ComparisonExpecation);
558 }
313 } 559 }
314 } 560 }
315 561
316 #endif 562 #endif
OLDNEW
« no previous file with comments | « src/gpu/GrShape.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698