OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 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 "Test.h" | 8 #include "Test.h" |
9 #include "SkClipStack.h" | 9 #include "SkClipStack.h" |
10 #include "SkPath.h" | 10 #include "SkPath.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 | 26 |
27 // Build up a clip stack with a path, an empty clip, and a rect. | 27 // Build up a clip stack with a path, an empty clip, and a rect. |
28 s.save(); | 28 s.save(); |
29 REPORTER_ASSERT(reporter, 1 == s.getSaveCount()); | 29 REPORTER_ASSERT(reporter, 1 == s.getSaveCount()); |
30 | 30 |
31 SkPath p; | 31 SkPath p; |
32 p.moveTo(5, 6); | 32 p.moveTo(5, 6); |
33 p.lineTo(7, 8); | 33 p.lineTo(7, 8); |
34 p.lineTo(5, 9); | 34 p.lineTo(5, 9); |
35 p.close(); | 35 p.close(); |
36 s.clipDevPath(p, SkRegion::kIntersect_Op, doAA); | 36 s.clipDevPath(p, SkCanvas::kIntersect_Op, doAA); |
37 | 37 |
38 s.save(); | 38 s.save(); |
39 REPORTER_ASSERT(reporter, 2 == s.getSaveCount()); | 39 REPORTER_ASSERT(reporter, 2 == s.getSaveCount()); |
40 | 40 |
41 SkRect r = SkRect::MakeLTRB(1, 2, 3, 4); | 41 SkRect r = SkRect::MakeLTRB(1, 2, 3, 4); |
42 s.clipDevRect(r, SkRegion::kIntersect_Op, doAA); | 42 s.clipDevRect(r, SkCanvas::kIntersect_Op, doAA); |
43 r = SkRect::MakeLTRB(10, 11, 12, 13); | 43 r = SkRect::MakeLTRB(10, 11, 12, 13); |
44 s.clipDevRect(r, SkRegion::kIntersect_Op, doAA); | 44 s.clipDevRect(r, SkCanvas::kIntersect_Op, doAA); |
45 | 45 |
46 s.save(); | 46 s.save(); |
47 REPORTER_ASSERT(reporter, 3 == s.getSaveCount()); | 47 REPORTER_ASSERT(reporter, 3 == s.getSaveCount()); |
48 | 48 |
49 r = SkRect::MakeLTRB(14, 15, 16, 17); | 49 r = SkRect::MakeLTRB(14, 15, 16, 17); |
50 s.clipDevRect(r, SkRegion::kUnion_Op, doAA); | 50 s.clipDevRect(r, SkCanvas::kUnion_Op, doAA); |
51 | 51 |
52 // Test that assignment works. | 52 // Test that assignment works. |
53 SkClipStack copy = s; | 53 SkClipStack copy = s; |
54 REPORTER_ASSERT(reporter, s == copy); | 54 REPORTER_ASSERT(reporter, s == copy); |
55 | 55 |
56 // Test that different save levels triggers not equal. | 56 // Test that different save levels triggers not equal. |
57 s.restore(); | 57 s.restore(); |
58 REPORTER_ASSERT(reporter, 2 == s.getSaveCount()); | 58 REPORTER_ASSERT(reporter, 2 == s.getSaveCount()); |
59 REPORTER_ASSERT(reporter, s != copy); | 59 REPORTER_ASSERT(reporter, s != copy); |
60 | 60 |
61 // Test that an equal, but not copied version is equal. | 61 // Test that an equal, but not copied version is equal. |
62 s.save(); | 62 s.save(); |
63 REPORTER_ASSERT(reporter, 3 == s.getSaveCount()); | 63 REPORTER_ASSERT(reporter, 3 == s.getSaveCount()); |
64 r = SkRect::MakeLTRB(14, 15, 16, 17); | 64 r = SkRect::MakeLTRB(14, 15, 16, 17); |
65 s.clipDevRect(r, SkRegion::kUnion_Op, doAA); | 65 s.clipDevRect(r, SkCanvas::kUnion_Op, doAA); |
66 REPORTER_ASSERT(reporter, s == copy); | 66 REPORTER_ASSERT(reporter, s == copy); |
67 | 67 |
68 // Test that a different op on one level triggers not equal. | 68 // Test that a different op on one level triggers not equal. |
69 s.restore(); | 69 s.restore(); |
70 REPORTER_ASSERT(reporter, 2 == s.getSaveCount()); | 70 REPORTER_ASSERT(reporter, 2 == s.getSaveCount()); |
71 s.save(); | 71 s.save(); |
72 REPORTER_ASSERT(reporter, 3 == s.getSaveCount()); | 72 REPORTER_ASSERT(reporter, 3 == s.getSaveCount()); |
73 r = SkRect::MakeLTRB(14, 15, 16, 17); | 73 r = SkRect::MakeLTRB(14, 15, 16, 17); |
74 s.clipDevRect(r, SkRegion::kIntersect_Op, doAA); | 74 s.clipDevRect(r, SkCanvas::kIntersect_Op, doAA); |
75 REPORTER_ASSERT(reporter, s != copy); | 75 REPORTER_ASSERT(reporter, s != copy); |
76 | 76 |
77 // Test that version constructed with rect-path rather than a rect is still
considered equal. | 77 // Test that version constructed with rect-path rather than a rect is still
considered equal. |
78 s.restore(); | 78 s.restore(); |
79 s.save(); | 79 s.save(); |
80 SkPath rp; | 80 SkPath rp; |
81 rp.addRect(r); | 81 rp.addRect(r); |
82 s.clipDevPath(rp, SkRegion::kUnion_Op, doAA); | 82 s.clipDevPath(rp, SkCanvas::kUnion_Op, doAA); |
83 REPORTER_ASSERT(reporter, s == copy); | 83 REPORTER_ASSERT(reporter, s == copy); |
84 | 84 |
85 // Test that different rects triggers not equal. | 85 // Test that different rects triggers not equal. |
86 s.restore(); | 86 s.restore(); |
87 REPORTER_ASSERT(reporter, 2 == s.getSaveCount()); | 87 REPORTER_ASSERT(reporter, 2 == s.getSaveCount()); |
88 s.save(); | 88 s.save(); |
89 REPORTER_ASSERT(reporter, 3 == s.getSaveCount()); | 89 REPORTER_ASSERT(reporter, 3 == s.getSaveCount()); |
90 | 90 |
91 r = SkRect::MakeLTRB(24, 25, 26, 27); | 91 r = SkRect::MakeLTRB(24, 25, 26, 27); |
92 s.clipDevRect(r, SkRegion::kUnion_Op, doAA); | 92 s.clipDevRect(r, SkCanvas::kUnion_Op, doAA); |
93 REPORTER_ASSERT(reporter, s != copy); | 93 REPORTER_ASSERT(reporter, s != copy); |
94 | 94 |
95 // Sanity check | 95 // Sanity check |
96 s.restore(); | 96 s.restore(); |
97 REPORTER_ASSERT(reporter, 2 == s.getSaveCount()); | 97 REPORTER_ASSERT(reporter, 2 == s.getSaveCount()); |
98 | 98 |
99 copy.restore(); | 99 copy.restore(); |
100 REPORTER_ASSERT(reporter, 2 == copy.getSaveCount()); | 100 REPORTER_ASSERT(reporter, 2 == copy.getSaveCount()); |
101 REPORTER_ASSERT(reporter, s == copy); | 101 REPORTER_ASSERT(reporter, s == copy); |
102 s.restore(); | 102 s.restore(); |
103 REPORTER_ASSERT(reporter, 1 == s.getSaveCount()); | 103 REPORTER_ASSERT(reporter, 1 == s.getSaveCount()); |
104 copy.restore(); | 104 copy.restore(); |
105 REPORTER_ASSERT(reporter, 1 == copy.getSaveCount()); | 105 REPORTER_ASSERT(reporter, 1 == copy.getSaveCount()); |
106 REPORTER_ASSERT(reporter, s == copy); | 106 REPORTER_ASSERT(reporter, s == copy); |
107 | 107 |
108 // Test that different paths triggers not equal. | 108 // Test that different paths triggers not equal. |
109 s.restore(); | 109 s.restore(); |
110 REPORTER_ASSERT(reporter, 0 == s.getSaveCount()); | 110 REPORTER_ASSERT(reporter, 0 == s.getSaveCount()); |
111 s.save(); | 111 s.save(); |
112 REPORTER_ASSERT(reporter, 1 == s.getSaveCount()); | 112 REPORTER_ASSERT(reporter, 1 == s.getSaveCount()); |
113 | 113 |
114 p.addRect(r); | 114 p.addRect(r); |
115 s.clipDevPath(p, SkRegion::kIntersect_Op, doAA); | 115 s.clipDevPath(p, SkCanvas::kIntersect_Op, doAA); |
116 REPORTER_ASSERT(reporter, s != copy); | 116 REPORTER_ASSERT(reporter, s != copy); |
117 } | 117 } |
118 | 118 |
119 static void assert_count(skiatest::Reporter* reporter, const SkClipStack& stack, | 119 static void assert_count(skiatest::Reporter* reporter, const SkClipStack& stack, |
120 int count) { | 120 int count) { |
121 SkClipStack::B2TIter iter(stack); | 121 SkClipStack::B2TIter iter(stack); |
122 int counter = 0; | 122 int counter = 0; |
123 while (iter.next()) { | 123 while (iter.next()) { |
124 counter += 1; | 124 counter += 1; |
125 } | 125 } |
126 REPORTER_ASSERT(reporter, count == counter); | 126 REPORTER_ASSERT(reporter, count == counter); |
127 } | 127 } |
128 | 128 |
129 // Exercise the SkClipStack's bottom to top and bidirectional iterators | 129 // Exercise the SkClipStack's bottom to top and bidirectional iterators |
130 // (including the skipToTopmost functionality) | 130 // (including the skipToTopmost functionality) |
131 static void test_iterators(skiatest::Reporter* reporter) { | 131 static void test_iterators(skiatest::Reporter* reporter) { |
132 SkClipStack stack; | 132 SkClipStack stack; |
133 | 133 |
134 static const SkRect gRects[] = { | 134 static const SkRect gRects[] = { |
135 { 0, 0, 40, 40 }, | 135 { 0, 0, 40, 40 }, |
136 { 60, 0, 100, 40 }, | 136 { 60, 0, 100, 40 }, |
137 { 0, 60, 40, 100 }, | 137 { 0, 60, 40, 100 }, |
138 { 60, 60, 100, 100 } | 138 { 60, 60, 100, 100 } |
139 }; | 139 }; |
140 | 140 |
141 for (size_t i = 0; i < SK_ARRAY_COUNT(gRects); i++) { | 141 for (size_t i = 0; i < SK_ARRAY_COUNT(gRects); i++) { |
142 // the union op will prevent these from being fused together | 142 // the union op will prevent these from being fused together |
143 stack.clipDevRect(gRects[i], SkRegion::kUnion_Op, false); | 143 stack.clipDevRect(gRects[i], SkCanvas::kUnion_Op, false); |
144 } | 144 } |
145 | 145 |
146 assert_count(reporter, stack, 4); | 146 assert_count(reporter, stack, 4); |
147 | 147 |
148 // bottom to top iteration | 148 // bottom to top iteration |
149 { | 149 { |
150 const SkClipStack::Element* element = nullptr; | 150 const SkClipStack::Element* element = nullptr; |
151 | 151 |
152 SkClipStack::B2TIter iter(stack); | 152 SkClipStack::B2TIter iter(stack); |
153 int i; | 153 int i; |
(...skipping 20 matching lines...) Expand all Loading... |
174 | 174 |
175 SkASSERT(i == -1); | 175 SkASSERT(i == -1); |
176 } | 176 } |
177 | 177 |
178 // skipToTopmost | 178 // skipToTopmost |
179 { | 179 { |
180 const SkClipStack::Element* element = nullptr; | 180 const SkClipStack::Element* element = nullptr; |
181 | 181 |
182 SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart); | 182 SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart); |
183 | 183 |
184 element = iter.skipToTopmost(SkRegion::kUnion_Op); | 184 element = iter.skipToTopmost(SkCanvas::kUnion_Op); |
185 REPORTER_ASSERT(reporter, SkClipStack::Element::kRect_Type == element->g
etType()); | 185 REPORTER_ASSERT(reporter, SkClipStack::Element::kRect_Type == element->g
etType()); |
186 REPORTER_ASSERT(reporter, element->getRect() == gRects[3]); | 186 REPORTER_ASSERT(reporter, element->getRect() == gRects[3]); |
187 } | 187 } |
188 } | 188 } |
189 | 189 |
190 // Exercise the SkClipStack's getConservativeBounds computation | 190 // Exercise the SkClipStack's getConservativeBounds computation |
191 static void test_bounds(skiatest::Reporter* reporter, SkClipStack::Element::Type
primType) { | 191 static void test_bounds(skiatest::Reporter* reporter, SkClipStack::Element::Type
primType) { |
192 static const int gNumCases = 20; | 192 static const int gNumCases = 20; |
193 static const SkRect gAnswerRectsBW[gNumCases] = { | 193 static const SkRect gAnswerRectsBW[gNumCases] = { |
194 // A op B | 194 // A op B |
(...skipping 18 matching lines...) Expand all Loading... |
213 { 0, 0, 100, 100 }, | 213 { 0, 0, 100, 100 }, |
214 | 214 |
215 // invA op invB | 215 // invA op invB |
216 { 0, 0, 100, 100 }, | 216 { 0, 0, 100, 100 }, |
217 { 40, 40, 80, 80 }, | 217 { 40, 40, 80, 80 }, |
218 { 0, 0, 100, 100 }, | 218 { 0, 0, 100, 100 }, |
219 { 10, 10, 80, 80 }, | 219 { 10, 10, 80, 80 }, |
220 { 10, 10, 50, 50 }, | 220 { 10, 10, 50, 50 }, |
221 }; | 221 }; |
222 | 222 |
223 static const SkRegion::Op gOps[] = { | 223 static const SkCanvas::ClipOp gOps[] = { |
224 SkRegion::kIntersect_Op, | 224 SkCanvas::kIntersect_Op, |
225 SkRegion::kDifference_Op, | 225 SkCanvas::kDifference_Op, |
226 SkRegion::kUnion_Op, | 226 SkCanvas::kUnion_Op, |
227 SkRegion::kXOR_Op, | 227 SkCanvas::kXOR_Op, |
228 SkRegion::kReverseDifference_Op | 228 SkCanvas::kReverseDifference_Op |
229 }; | 229 }; |
230 | 230 |
231 SkRect rectA, rectB; | 231 SkRect rectA, rectB; |
232 | 232 |
233 rectA.iset(10, 10, 50, 50); | 233 rectA.iset(10, 10, 50, 50); |
234 rectB.iset(40, 40, 80, 80); | 234 rectB.iset(40, 40, 80, 80); |
235 | 235 |
236 SkRRect rrectA, rrectB; | 236 SkRRect rrectA, rrectB; |
237 rrectA.setOval(rectA); | 237 rrectA.setOval(rectA); |
238 rrectB.setRectXY(rectB, SkIntToScalar(1), SkIntToScalar(2)); | 238 rrectB.setRectXY(rectB, SkIntToScalar(1), SkIntToScalar(2)); |
(...skipping 19 matching lines...) Expand all Loading... |
258 pathA.setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType : | 258 pathA.setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType : |
259 SkPath::kEvenOdd_FillType); | 259 SkPath::kEvenOdd_FillType); |
260 pathB.setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType : | 260 pathB.setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType : |
261 SkPath::kEvenOdd_FillType); | 261 SkPath::kEvenOdd_FillType); |
262 | 262 |
263 switch (primType) { | 263 switch (primType) { |
264 case SkClipStack::Element::kEmpty_Type: | 264 case SkClipStack::Element::kEmpty_Type: |
265 SkDEBUGFAIL("Don't call this with kEmpty."); | 265 SkDEBUGFAIL("Don't call this with kEmpty."); |
266 break; | 266 break; |
267 case SkClipStack::Element::kRect_Type: | 267 case SkClipStack::Element::kRect_Type: |
268 stack.clipDevRect(rectA, SkRegion::kIntersect_Op, false); | 268 stack.clipDevRect(rectA, SkCanvas::kIntersect_Op, false); |
269 stack.clipDevRect(rectB, gOps[op], false); | 269 stack.clipDevRect(rectB, gOps[op], false); |
270 break; | 270 break; |
271 case SkClipStack::Element::kRRect_Type: | 271 case SkClipStack::Element::kRRect_Type: |
272 stack.clipDevRRect(rrectA, SkRegion::kIntersect_Op, false); | 272 stack.clipDevRRect(rrectA, SkCanvas::kIntersect_Op, false); |
273 stack.clipDevRRect(rrectB, gOps[op], false); | 273 stack.clipDevRRect(rrectB, gOps[op], false); |
274 break; | 274 break; |
275 case SkClipStack::Element::kPath_Type: | 275 case SkClipStack::Element::kPath_Type: |
276 stack.clipDevPath(pathA, SkRegion::kIntersect_Op, false); | 276 stack.clipDevPath(pathA, SkCanvas::kIntersect_Op, false); |
277 stack.clipDevPath(pathB, gOps[op], false); | 277 stack.clipDevPath(pathB, gOps[op], false); |
278 break; | 278 break; |
279 } | 279 } |
280 | 280 |
281 REPORTER_ASSERT(reporter, !stack.isWideOpen()); | 281 REPORTER_ASSERT(reporter, !stack.isWideOpen()); |
282 REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID != stack.getTo
pmostGenID()); | 282 REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID != stack.getTo
pmostGenID()); |
283 | 283 |
284 stack.getConservativeBounds(0, 0, 100, 100, &devClipBound, | 284 stack.getConservativeBounds(0, 0, 100, 100, &devClipBound, |
285 &isIntersectionOfRects); | 285 &isIntersectionOfRects); |
286 | 286 |
287 if (SkClipStack::Element::kRect_Type == primType) { | 287 if (SkClipStack::Element::kRect_Type == primType) { |
288 REPORTER_ASSERT(reporter, isIntersectionOfRects == | 288 REPORTER_ASSERT(reporter, isIntersectionOfRects == |
289 (gOps[op] == SkRegion::kIntersect_Op)); | 289 (gOps[op] == SkCanvas::kIntersect_Op)); |
290 } else { | 290 } else { |
291 REPORTER_ASSERT(reporter, !isIntersectionOfRects); | 291 REPORTER_ASSERT(reporter, !isIntersectionOfRects); |
292 } | 292 } |
293 | 293 |
294 SkASSERT(testCase < gNumCases); | 294 SkASSERT(testCase < gNumCases); |
295 REPORTER_ASSERT(reporter, devClipBound == gAnswerRectsBW[testCase]); | 295 REPORTER_ASSERT(reporter, devClipBound == gAnswerRectsBW[testCase]); |
296 ++testCase; | 296 ++testCase; |
297 | 297 |
298 stack.restore(); | 298 stack.restore(); |
299 } | 299 } |
(...skipping 27 matching lines...) Expand all Loading... |
327 SkClipStack stack; | 327 SkClipStack stack; |
328 | 328 |
329 SkPath clipA, clipB; | 329 SkPath clipA, clipB; |
330 | 330 |
331 clipA.addRoundRect(rectA, SkIntToScalar(5), SkIntToScalar(5)); | 331 clipA.addRoundRect(rectA, SkIntToScalar(5), SkIntToScalar(5)); |
332 clipA.setFillType(SkPath::kInverseEvenOdd_FillType); | 332 clipA.setFillType(SkPath::kInverseEvenOdd_FillType); |
333 | 333 |
334 clipB.addRoundRect(rectB, SkIntToScalar(5), SkIntToScalar(5)); | 334 clipB.addRoundRect(rectB, SkIntToScalar(5), SkIntToScalar(5)); |
335 clipB.setFillType(SkPath::kInverseEvenOdd_FillType); | 335 clipB.setFillType(SkPath::kInverseEvenOdd_FillType); |
336 | 336 |
337 stack.clipDevPath(clipA, SkRegion::kReplace_Op, false); | 337 stack.clipDevPath(clipA, SkCanvas::kReplace_Op, false); |
338 stack.clipDevPath(clipB, SkRegion::kUnion_Op, false); | 338 stack.clipDevPath(clipB, SkCanvas::kUnion_Op, false); |
339 | 339 |
340 REPORTER_ASSERT(reporter, stack.isWideOpen()); | 340 REPORTER_ASSERT(reporter, stack.isWideOpen()); |
341 REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID == stack.getTopmos
tGenID()); | 341 REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID == stack.getTopmos
tGenID()); |
342 } | 342 } |
343 | 343 |
344 // Test out union w/ a wide open clip | 344 // Test out union w/ a wide open clip |
345 { | 345 { |
346 SkClipStack stack; | 346 SkClipStack stack; |
347 | 347 |
348 stack.clipDevRect(rectA, SkRegion::kUnion_Op, false); | 348 stack.clipDevRect(rectA, SkCanvas::kUnion_Op, false); |
349 | 349 |
350 REPORTER_ASSERT(reporter, stack.isWideOpen()); | 350 REPORTER_ASSERT(reporter, stack.isWideOpen()); |
351 REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID == stack.getTopmos
tGenID()); | 351 REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID == stack.getTopmos
tGenID()); |
352 } | 352 } |
353 | 353 |
354 // Test out empty difference from a wide open clip | 354 // Test out empty difference from a wide open clip |
355 { | 355 { |
356 SkClipStack stack; | 356 SkClipStack stack; |
357 | 357 |
358 SkRect emptyRect; | 358 SkRect emptyRect; |
359 emptyRect.setEmpty(); | 359 emptyRect.setEmpty(); |
360 | 360 |
361 stack.clipDevRect(emptyRect, SkRegion::kDifference_Op, false); | 361 stack.clipDevRect(emptyRect, SkCanvas::kDifference_Op, false); |
362 | 362 |
363 REPORTER_ASSERT(reporter, stack.isWideOpen()); | 363 REPORTER_ASSERT(reporter, stack.isWideOpen()); |
364 REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID == stack.getTopmos
tGenID()); | 364 REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID == stack.getTopmos
tGenID()); |
365 } | 365 } |
366 | 366 |
367 // Test out return to wide open | 367 // Test out return to wide open |
368 { | 368 { |
369 SkClipStack stack; | 369 SkClipStack stack; |
370 | 370 |
371 stack.save(); | 371 stack.save(); |
372 | 372 |
373 stack.clipDevRect(rectA, SkRegion::kReplace_Op, false); | 373 stack.clipDevRect(rectA, SkCanvas::kReplace_Op, false); |
374 | 374 |
375 REPORTER_ASSERT(reporter, !stack.isWideOpen()); | 375 REPORTER_ASSERT(reporter, !stack.isWideOpen()); |
376 REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID != stack.getTopmos
tGenID()); | 376 REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID != stack.getTopmos
tGenID()); |
377 | 377 |
378 stack.restore(); | 378 stack.restore(); |
379 | 379 |
380 REPORTER_ASSERT(reporter, stack.isWideOpen()); | 380 REPORTER_ASSERT(reporter, stack.isWideOpen()); |
381 REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID == stack.getTopmos
tGenID()); | 381 REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID == stack.getTopmos
tGenID()); |
382 } | 382 } |
383 } | 383 } |
(...skipping 13 matching lines...) Expand all Loading... |
397 } | 397 } |
398 | 398 |
399 static void test_rect_inverse_fill(skiatest::Reporter* reporter) { | 399 static void test_rect_inverse_fill(skiatest::Reporter* reporter) { |
400 // non-intersecting rectangles | 400 // non-intersecting rectangles |
401 SkRect rect = SkRect::MakeLTRB(0, 0, 10, 10); | 401 SkRect rect = SkRect::MakeLTRB(0, 0, 10, 10); |
402 | 402 |
403 SkPath path; | 403 SkPath path; |
404 path.addRect(rect); | 404 path.addRect(rect); |
405 path.toggleInverseFillType(); | 405 path.toggleInverseFillType(); |
406 SkClipStack stack; | 406 SkClipStack stack; |
407 stack.clipDevPath(path, SkRegion::kIntersect_Op, false); | 407 stack.clipDevPath(path, SkCanvas::kIntersect_Op, false); |
408 | 408 |
409 SkRect bounds; | 409 SkRect bounds; |
410 SkClipStack::BoundsType boundsType; | 410 SkClipStack::BoundsType boundsType; |
411 stack.getBounds(&bounds, &boundsType); | 411 stack.getBounds(&bounds, &boundsType); |
412 REPORTER_ASSERT(reporter, SkClipStack::kInsideOut_BoundsType == boundsType); | 412 REPORTER_ASSERT(reporter, SkClipStack::kInsideOut_BoundsType == boundsType); |
413 REPORTER_ASSERT(reporter, bounds == rect); | 413 REPORTER_ASSERT(reporter, bounds == rect); |
414 } | 414 } |
415 | 415 |
416 static void test_rect_replace(skiatest::Reporter* reporter) { | 416 static void test_rect_replace(skiatest::Reporter* reporter) { |
417 SkRect rect = SkRect::MakeWH(100, 100); | 417 SkRect rect = SkRect::MakeWH(100, 100); |
418 SkRect rect2 = SkRect::MakeXYWH(50, 50, 100, 100); | 418 SkRect rect2 = SkRect::MakeXYWH(50, 50, 100, 100); |
419 | 419 |
420 SkRect bound; | 420 SkRect bound; |
421 SkClipStack::BoundsType type; | 421 SkClipStack::BoundsType type; |
422 bool isIntersectionOfRects; | 422 bool isIntersectionOfRects; |
423 | 423 |
424 // Adding a new rect with the replace operator should not increase | 424 // Adding a new rect with the replace operator should not increase |
425 // the stack depth. BW replacing BW. | 425 // the stack depth. BW replacing BW. |
426 { | 426 { |
427 SkClipStack stack; | 427 SkClipStack stack; |
428 REPORTER_ASSERT(reporter, 0 == count(stack)); | 428 REPORTER_ASSERT(reporter, 0 == count(stack)); |
429 stack.clipDevRect(rect, SkRegion::kReplace_Op, false); | 429 stack.clipDevRect(rect, SkCanvas::kReplace_Op, false); |
430 REPORTER_ASSERT(reporter, 1 == count(stack)); | 430 REPORTER_ASSERT(reporter, 1 == count(stack)); |
431 stack.clipDevRect(rect, SkRegion::kReplace_Op, false); | 431 stack.clipDevRect(rect, SkCanvas::kReplace_Op, false); |
432 REPORTER_ASSERT(reporter, 1 == count(stack)); | 432 REPORTER_ASSERT(reporter, 1 == count(stack)); |
433 } | 433 } |
434 | 434 |
435 // Adding a new rect with the replace operator should not increase | 435 // Adding a new rect with the replace operator should not increase |
436 // the stack depth. AA replacing AA. | 436 // the stack depth. AA replacing AA. |
437 { | 437 { |
438 SkClipStack stack; | 438 SkClipStack stack; |
439 REPORTER_ASSERT(reporter, 0 == count(stack)); | 439 REPORTER_ASSERT(reporter, 0 == count(stack)); |
440 stack.clipDevRect(rect, SkRegion::kReplace_Op, true); | 440 stack.clipDevRect(rect, SkCanvas::kReplace_Op, true); |
441 REPORTER_ASSERT(reporter, 1 == count(stack)); | 441 REPORTER_ASSERT(reporter, 1 == count(stack)); |
442 stack.clipDevRect(rect, SkRegion::kReplace_Op, true); | 442 stack.clipDevRect(rect, SkCanvas::kReplace_Op, true); |
443 REPORTER_ASSERT(reporter, 1 == count(stack)); | 443 REPORTER_ASSERT(reporter, 1 == count(stack)); |
444 } | 444 } |
445 | 445 |
446 // Adding a new rect with the replace operator should not increase | 446 // Adding a new rect with the replace operator should not increase |
447 // the stack depth. BW replacing AA replacing BW. | 447 // the stack depth. BW replacing AA replacing BW. |
448 { | 448 { |
449 SkClipStack stack; | 449 SkClipStack stack; |
450 REPORTER_ASSERT(reporter, 0 == count(stack)); | 450 REPORTER_ASSERT(reporter, 0 == count(stack)); |
451 stack.clipDevRect(rect, SkRegion::kReplace_Op, false); | 451 stack.clipDevRect(rect, SkCanvas::kReplace_Op, false); |
452 REPORTER_ASSERT(reporter, 1 == count(stack)); | 452 REPORTER_ASSERT(reporter, 1 == count(stack)); |
453 stack.clipDevRect(rect, SkRegion::kReplace_Op, true); | 453 stack.clipDevRect(rect, SkCanvas::kReplace_Op, true); |
454 REPORTER_ASSERT(reporter, 1 == count(stack)); | 454 REPORTER_ASSERT(reporter, 1 == count(stack)); |
455 stack.clipDevRect(rect, SkRegion::kReplace_Op, false); | 455 stack.clipDevRect(rect, SkCanvas::kReplace_Op, false); |
456 REPORTER_ASSERT(reporter, 1 == count(stack)); | 456 REPORTER_ASSERT(reporter, 1 == count(stack)); |
457 } | 457 } |
458 | 458 |
459 // Make sure replace clip rects don't collapse too much. | 459 // Make sure replace clip rects don't collapse too much. |
460 { | 460 { |
461 SkClipStack stack; | 461 SkClipStack stack; |
462 stack.clipDevRect(rect, SkRegion::kReplace_Op, false); | 462 stack.clipDevRect(rect, SkCanvas::kReplace_Op, false); |
463 stack.clipDevRect(rect2, SkRegion::kIntersect_Op, false); | 463 stack.clipDevRect(rect2, SkCanvas::kIntersect_Op, false); |
464 REPORTER_ASSERT(reporter, 1 == count(stack)); | 464 REPORTER_ASSERT(reporter, 1 == count(stack)); |
465 | 465 |
466 stack.save(); | 466 stack.save(); |
467 stack.clipDevRect(rect, SkRegion::kReplace_Op, false); | 467 stack.clipDevRect(rect, SkCanvas::kReplace_Op, false); |
468 REPORTER_ASSERT(reporter, 2 == count(stack)); | 468 REPORTER_ASSERT(reporter, 2 == count(stack)); |
469 stack.getBounds(&bound, &type, &isIntersectionOfRects); | 469 stack.getBounds(&bound, &type, &isIntersectionOfRects); |
470 REPORTER_ASSERT(reporter, bound == rect); | 470 REPORTER_ASSERT(reporter, bound == rect); |
471 stack.restore(); | 471 stack.restore(); |
472 REPORTER_ASSERT(reporter, 1 == count(stack)); | 472 REPORTER_ASSERT(reporter, 1 == count(stack)); |
473 | 473 |
474 stack.save(); | 474 stack.save(); |
475 stack.clipDevRect(rect, SkRegion::kReplace_Op, false); | 475 stack.clipDevRect(rect, SkCanvas::kReplace_Op, false); |
476 stack.clipDevRect(rect, SkRegion::kReplace_Op, false); | 476 stack.clipDevRect(rect, SkCanvas::kReplace_Op, false); |
477 REPORTER_ASSERT(reporter, 2 == count(stack)); | 477 REPORTER_ASSERT(reporter, 2 == count(stack)); |
478 stack.restore(); | 478 stack.restore(); |
479 REPORTER_ASSERT(reporter, 1 == count(stack)); | 479 REPORTER_ASSERT(reporter, 1 == count(stack)); |
480 | 480 |
481 stack.save(); | 481 stack.save(); |
482 stack.clipDevRect(rect, SkRegion::kReplace_Op, false); | 482 stack.clipDevRect(rect, SkCanvas::kReplace_Op, false); |
483 stack.clipDevRect(rect2, SkRegion::kIntersect_Op, false); | 483 stack.clipDevRect(rect2, SkCanvas::kIntersect_Op, false); |
484 stack.clipDevRect(rect, SkRegion::kReplace_Op, false); | 484 stack.clipDevRect(rect, SkCanvas::kReplace_Op, false); |
485 REPORTER_ASSERT(reporter, 2 == count(stack)); | 485 REPORTER_ASSERT(reporter, 2 == count(stack)); |
486 stack.restore(); | 486 stack.restore(); |
487 REPORTER_ASSERT(reporter, 1 == count(stack)); | 487 REPORTER_ASSERT(reporter, 1 == count(stack)); |
488 } | 488 } |
489 } | 489 } |
490 | 490 |
491 // Simplified path-based version of test_rect_replace. | 491 // Simplified path-based version of test_rect_replace. |
492 static void test_path_replace(skiatest::Reporter* reporter) { | 492 static void test_path_replace(skiatest::Reporter* reporter) { |
493 SkRect rect = SkRect::MakeWH(100, 100); | 493 SkRect rect = SkRect::MakeWH(100, 100); |
494 SkPath path; | 494 SkPath path; |
495 path.addCircle(50, 50, 50); | 495 path.addCircle(50, 50, 50); |
496 | 496 |
497 // Replace operation doesn't grow the stack. | 497 // Replace operation doesn't grow the stack. |
498 { | 498 { |
499 SkClipStack stack; | 499 SkClipStack stack; |
500 REPORTER_ASSERT(reporter, 0 == count(stack)); | 500 REPORTER_ASSERT(reporter, 0 == count(stack)); |
501 stack.clipDevPath(path, SkRegion::kReplace_Op, false); | 501 stack.clipDevPath(path, SkCanvas::kReplace_Op, false); |
502 REPORTER_ASSERT(reporter, 1 == count(stack)); | 502 REPORTER_ASSERT(reporter, 1 == count(stack)); |
503 stack.clipDevPath(path, SkRegion::kReplace_Op, false); | 503 stack.clipDevPath(path, SkCanvas::kReplace_Op, false); |
504 REPORTER_ASSERT(reporter, 1 == count(stack)); | 504 REPORTER_ASSERT(reporter, 1 == count(stack)); |
505 } | 505 } |
506 | 506 |
507 // Replacing rect with path. | 507 // Replacing rect with path. |
508 { | 508 { |
509 SkClipStack stack; | 509 SkClipStack stack; |
510 stack.clipDevRect(rect, SkRegion::kReplace_Op, true); | 510 stack.clipDevRect(rect, SkCanvas::kReplace_Op, true); |
511 REPORTER_ASSERT(reporter, 1 == count(stack)); | 511 REPORTER_ASSERT(reporter, 1 == count(stack)); |
512 stack.clipDevPath(path, SkRegion::kReplace_Op, true); | 512 stack.clipDevPath(path, SkCanvas::kReplace_Op, true); |
513 REPORTER_ASSERT(reporter, 1 == count(stack)); | 513 REPORTER_ASSERT(reporter, 1 == count(stack)); |
514 } | 514 } |
515 } | 515 } |
516 | 516 |
517 // Test out SkClipStack's merging of rect clips. In particular exercise | 517 // Test out SkClipStack's merging of rect clips. In particular exercise |
518 // merging of aa vs. bw rects. | 518 // merging of aa vs. bw rects. |
519 static void test_rect_merging(skiatest::Reporter* reporter) { | 519 static void test_rect_merging(skiatest::Reporter* reporter) { |
520 | 520 |
521 SkRect overlapLeft = SkRect::MakeLTRB(10, 10, 50, 50); | 521 SkRect overlapLeft = SkRect::MakeLTRB(10, 10, 50, 50); |
522 SkRect overlapRight = SkRect::MakeLTRB(40, 40, 80, 80); | 522 SkRect overlapRight = SkRect::MakeLTRB(40, 40, 80, 80); |
523 | 523 |
524 SkRect nestedParent = SkRect::MakeLTRB(10, 10, 90, 90); | 524 SkRect nestedParent = SkRect::MakeLTRB(10, 10, 90, 90); |
525 SkRect nestedChild = SkRect::MakeLTRB(40, 40, 60, 60); | 525 SkRect nestedChild = SkRect::MakeLTRB(40, 40, 60, 60); |
526 | 526 |
527 SkRect bound; | 527 SkRect bound; |
528 SkClipStack::BoundsType type; | 528 SkClipStack::BoundsType type; |
529 bool isIntersectionOfRects; | 529 bool isIntersectionOfRects; |
530 | 530 |
531 // all bw overlapping - should merge | 531 // all bw overlapping - should merge |
532 { | 532 { |
533 SkClipStack stack; | 533 SkClipStack stack; |
534 | 534 |
535 stack.clipDevRect(overlapLeft, SkRegion::kReplace_Op, false); | 535 stack.clipDevRect(overlapLeft, SkCanvas::kReplace_Op, false); |
536 | 536 |
537 stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, false); | 537 stack.clipDevRect(overlapRight, SkCanvas::kIntersect_Op, false); |
538 | 538 |
539 REPORTER_ASSERT(reporter, 1 == count(stack)); | 539 REPORTER_ASSERT(reporter, 1 == count(stack)); |
540 | 540 |
541 stack.getBounds(&bound, &type, &isIntersectionOfRects); | 541 stack.getBounds(&bound, &type, &isIntersectionOfRects); |
542 | 542 |
543 REPORTER_ASSERT(reporter, isIntersectionOfRects); | 543 REPORTER_ASSERT(reporter, isIntersectionOfRects); |
544 } | 544 } |
545 | 545 |
546 // all aa overlapping - should merge | 546 // all aa overlapping - should merge |
547 { | 547 { |
548 SkClipStack stack; | 548 SkClipStack stack; |
549 | 549 |
550 stack.clipDevRect(overlapLeft, SkRegion::kReplace_Op, true); | 550 stack.clipDevRect(overlapLeft, SkCanvas::kReplace_Op, true); |
551 | 551 |
552 stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, true); | 552 stack.clipDevRect(overlapRight, SkCanvas::kIntersect_Op, true); |
553 | 553 |
554 REPORTER_ASSERT(reporter, 1 == count(stack)); | 554 REPORTER_ASSERT(reporter, 1 == count(stack)); |
555 | 555 |
556 stack.getBounds(&bound, &type, &isIntersectionOfRects); | 556 stack.getBounds(&bound, &type, &isIntersectionOfRects); |
557 | 557 |
558 REPORTER_ASSERT(reporter, isIntersectionOfRects); | 558 REPORTER_ASSERT(reporter, isIntersectionOfRects); |
559 } | 559 } |
560 | 560 |
561 // mixed overlapping - should _not_ merge | 561 // mixed overlapping - should _not_ merge |
562 { | 562 { |
563 SkClipStack stack; | 563 SkClipStack stack; |
564 | 564 |
565 stack.clipDevRect(overlapLeft, SkRegion::kReplace_Op, true); | 565 stack.clipDevRect(overlapLeft, SkCanvas::kReplace_Op, true); |
566 | 566 |
567 stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, false); | 567 stack.clipDevRect(overlapRight, SkCanvas::kIntersect_Op, false); |
568 | 568 |
569 REPORTER_ASSERT(reporter, 2 == count(stack)); | 569 REPORTER_ASSERT(reporter, 2 == count(stack)); |
570 | 570 |
571 stack.getBounds(&bound, &type, &isIntersectionOfRects); | 571 stack.getBounds(&bound, &type, &isIntersectionOfRects); |
572 | 572 |
573 REPORTER_ASSERT(reporter, !isIntersectionOfRects); | 573 REPORTER_ASSERT(reporter, !isIntersectionOfRects); |
574 } | 574 } |
575 | 575 |
576 // mixed nested (bw inside aa) - should merge | 576 // mixed nested (bw inside aa) - should merge |
577 { | 577 { |
578 SkClipStack stack; | 578 SkClipStack stack; |
579 | 579 |
580 stack.clipDevRect(nestedParent, SkRegion::kReplace_Op, true); | 580 stack.clipDevRect(nestedParent, SkCanvas::kReplace_Op, true); |
581 | 581 |
582 stack.clipDevRect(nestedChild, SkRegion::kIntersect_Op, false); | 582 stack.clipDevRect(nestedChild, SkCanvas::kIntersect_Op, false); |
583 | 583 |
584 REPORTER_ASSERT(reporter, 1 == count(stack)); | 584 REPORTER_ASSERT(reporter, 1 == count(stack)); |
585 | 585 |
586 stack.getBounds(&bound, &type, &isIntersectionOfRects); | 586 stack.getBounds(&bound, &type, &isIntersectionOfRects); |
587 | 587 |
588 REPORTER_ASSERT(reporter, isIntersectionOfRects); | 588 REPORTER_ASSERT(reporter, isIntersectionOfRects); |
589 } | 589 } |
590 | 590 |
591 // mixed nested (aa inside bw) - should merge | 591 // mixed nested (aa inside bw) - should merge |
592 { | 592 { |
593 SkClipStack stack; | 593 SkClipStack stack; |
594 | 594 |
595 stack.clipDevRect(nestedParent, SkRegion::kReplace_Op, false); | 595 stack.clipDevRect(nestedParent, SkCanvas::kReplace_Op, false); |
596 | 596 |
597 stack.clipDevRect(nestedChild, SkRegion::kIntersect_Op, true); | 597 stack.clipDevRect(nestedChild, SkCanvas::kIntersect_Op, true); |
598 | 598 |
599 REPORTER_ASSERT(reporter, 1 == count(stack)); | 599 REPORTER_ASSERT(reporter, 1 == count(stack)); |
600 | 600 |
601 stack.getBounds(&bound, &type, &isIntersectionOfRects); | 601 stack.getBounds(&bound, &type, &isIntersectionOfRects); |
602 | 602 |
603 REPORTER_ASSERT(reporter, isIntersectionOfRects); | 603 REPORTER_ASSERT(reporter, isIntersectionOfRects); |
604 } | 604 } |
605 | 605 |
606 // reverse nested (aa inside bw) - should _not_ merge | 606 // reverse nested (aa inside bw) - should _not_ merge |
607 { | 607 { |
608 SkClipStack stack; | 608 SkClipStack stack; |
609 | 609 |
610 stack.clipDevRect(nestedChild, SkRegion::kReplace_Op, false); | 610 stack.clipDevRect(nestedChild, SkCanvas::kReplace_Op, false); |
611 | 611 |
612 stack.clipDevRect(nestedParent, SkRegion::kIntersect_Op, true); | 612 stack.clipDevRect(nestedParent, SkCanvas::kIntersect_Op, true); |
613 | 613 |
614 REPORTER_ASSERT(reporter, 2 == count(stack)); | 614 REPORTER_ASSERT(reporter, 2 == count(stack)); |
615 | 615 |
616 stack.getBounds(&bound, &type, &isIntersectionOfRects); | 616 stack.getBounds(&bound, &type, &isIntersectionOfRects); |
617 | 617 |
618 REPORTER_ASSERT(reporter, !isIntersectionOfRects); | 618 REPORTER_ASSERT(reporter, !isIntersectionOfRects); |
619 } | 619 } |
620 } | 620 } |
621 | 621 |
622 static void test_quickContains(skiatest::Reporter* reporter) { | 622 static void test_quickContains(skiatest::Reporter* reporter) { |
623 SkRect testRect = SkRect::MakeLTRB(10, 10, 40, 40); | 623 SkRect testRect = SkRect::MakeLTRB(10, 10, 40, 40); |
624 SkRect insideRect = SkRect::MakeLTRB(20, 20, 30, 30); | 624 SkRect insideRect = SkRect::MakeLTRB(20, 20, 30, 30); |
625 SkRect intersectingRect = SkRect::MakeLTRB(25, 25, 50, 50); | 625 SkRect intersectingRect = SkRect::MakeLTRB(25, 25, 50, 50); |
626 SkRect outsideRect = SkRect::MakeLTRB(0, 0, 50, 50); | 626 SkRect outsideRect = SkRect::MakeLTRB(0, 0, 50, 50); |
627 SkRect nonIntersectingRect = SkRect::MakeLTRB(100, 100, 110, 110); | 627 SkRect nonIntersectingRect = SkRect::MakeLTRB(100, 100, 110, 110); |
628 | 628 |
629 SkPath insideCircle; | 629 SkPath insideCircle; |
630 insideCircle.addCircle(25, 25, 5); | 630 insideCircle.addCircle(25, 25, 5); |
631 SkPath intersectingCircle; | 631 SkPath intersectingCircle; |
632 intersectingCircle.addCircle(25, 40, 10); | 632 intersectingCircle.addCircle(25, 40, 10); |
633 SkPath outsideCircle; | 633 SkPath outsideCircle; |
634 outsideCircle.addCircle(25, 25, 50); | 634 outsideCircle.addCircle(25, 25, 50); |
635 SkPath nonIntersectingCircle; | 635 SkPath nonIntersectingCircle; |
636 nonIntersectingCircle.addCircle(100, 100, 5); | 636 nonIntersectingCircle.addCircle(100, 100, 5); |
637 | 637 |
638 { | 638 { |
639 SkClipStack stack; | 639 SkClipStack stack; |
640 stack.clipDevRect(outsideRect, SkRegion::kDifference_Op, false); | 640 stack.clipDevRect(outsideRect, SkCanvas::kDifference_Op, false); |
641 // return false because quickContains currently does not care for kDiffe
rence_Op | 641 // return false because quickContains currently does not care for kDiffe
rence_Op |
642 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); | 642 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); |
643 } | 643 } |
644 | 644 |
645 // Replace Op tests | 645 // Replace Op tests |
646 { | 646 { |
647 SkClipStack stack; | 647 SkClipStack stack; |
648 stack.clipDevRect(outsideRect, SkRegion::kReplace_Op, false); | 648 stack.clipDevRect(outsideRect, SkCanvas::kReplace_Op, false); |
649 REPORTER_ASSERT(reporter, true == stack.quickContains(testRect)); | 649 REPORTER_ASSERT(reporter, true == stack.quickContains(testRect)); |
650 } | 650 } |
651 | 651 |
652 { | 652 { |
653 SkClipStack stack; | 653 SkClipStack stack; |
654 stack.clipDevRect(insideRect, SkRegion::kIntersect_Op, false); | 654 stack.clipDevRect(insideRect, SkCanvas::kIntersect_Op, false); |
655 stack.save(); // To prevent in-place substitution by replace OP | 655 stack.save(); // To prevent in-place substitution by replace OP |
656 stack.clipDevRect(outsideRect, SkRegion::kReplace_Op, false); | 656 stack.clipDevRect(outsideRect, SkCanvas::kReplace_Op, false); |
657 REPORTER_ASSERT(reporter, true == stack.quickContains(testRect)); | 657 REPORTER_ASSERT(reporter, true == stack.quickContains(testRect)); |
658 stack.restore(); | 658 stack.restore(); |
659 } | 659 } |
660 | 660 |
661 { | 661 { |
662 SkClipStack stack; | 662 SkClipStack stack; |
663 stack.clipDevRect(outsideRect, SkRegion::kIntersect_Op, false); | 663 stack.clipDevRect(outsideRect, SkCanvas::kIntersect_Op, false); |
664 stack.save(); // To prevent in-place substitution by replace OP | 664 stack.save(); // To prevent in-place substitution by replace OP |
665 stack.clipDevRect(insideRect, SkRegion::kReplace_Op, false); | 665 stack.clipDevRect(insideRect, SkCanvas::kReplace_Op, false); |
666 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); | 666 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); |
667 stack.restore(); | 667 stack.restore(); |
668 } | 668 } |
669 | 669 |
670 // Verify proper traversal of multi-element clip | 670 // Verify proper traversal of multi-element clip |
671 { | 671 { |
672 SkClipStack stack; | 672 SkClipStack stack; |
673 stack.clipDevRect(insideRect, SkRegion::kIntersect_Op, false); | 673 stack.clipDevRect(insideRect, SkCanvas::kIntersect_Op, false); |
674 // Use a path for second clip to prevent in-place intersection | 674 // Use a path for second clip to prevent in-place intersection |
675 stack.clipDevPath(outsideCircle, SkRegion::kIntersect_Op, false); | 675 stack.clipDevPath(outsideCircle, SkCanvas::kIntersect_Op, false); |
676 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); | 676 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); |
677 } | 677 } |
678 | 678 |
679 // Intersect Op tests with rectangles | 679 // Intersect Op tests with rectangles |
680 { | 680 { |
681 SkClipStack stack; | 681 SkClipStack stack; |
682 stack.clipDevRect(outsideRect, SkRegion::kIntersect_Op, false); | 682 stack.clipDevRect(outsideRect, SkCanvas::kIntersect_Op, false); |
683 REPORTER_ASSERT(reporter, true == stack.quickContains(testRect)); | 683 REPORTER_ASSERT(reporter, true == stack.quickContains(testRect)); |
684 } | 684 } |
685 | 685 |
686 { | 686 { |
687 SkClipStack stack; | 687 SkClipStack stack; |
688 stack.clipDevRect(insideRect, SkRegion::kIntersect_Op, false); | 688 stack.clipDevRect(insideRect, SkCanvas::kIntersect_Op, false); |
689 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); | 689 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); |
690 } | 690 } |
691 | 691 |
692 { | 692 { |
693 SkClipStack stack; | 693 SkClipStack stack; |
694 stack.clipDevRect(intersectingRect, SkRegion::kIntersect_Op, false); | 694 stack.clipDevRect(intersectingRect, SkCanvas::kIntersect_Op, false); |
695 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); | 695 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); |
696 } | 696 } |
697 | 697 |
698 { | 698 { |
699 SkClipStack stack; | 699 SkClipStack stack; |
700 stack.clipDevRect(nonIntersectingRect, SkRegion::kIntersect_Op, false); | 700 stack.clipDevRect(nonIntersectingRect, SkCanvas::kIntersect_Op, false); |
701 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); | 701 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); |
702 } | 702 } |
703 | 703 |
704 // Intersect Op tests with circle paths | 704 // Intersect Op tests with circle paths |
705 { | 705 { |
706 SkClipStack stack; | 706 SkClipStack stack; |
707 stack.clipDevPath(outsideCircle, SkRegion::kIntersect_Op, false); | 707 stack.clipDevPath(outsideCircle, SkCanvas::kIntersect_Op, false); |
708 REPORTER_ASSERT(reporter, true == stack.quickContains(testRect)); | 708 REPORTER_ASSERT(reporter, true == stack.quickContains(testRect)); |
709 } | 709 } |
710 | 710 |
711 { | 711 { |
712 SkClipStack stack; | 712 SkClipStack stack; |
713 stack.clipDevPath(insideCircle, SkRegion::kIntersect_Op, false); | 713 stack.clipDevPath(insideCircle, SkCanvas::kIntersect_Op, false); |
714 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); | 714 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); |
715 } | 715 } |
716 | 716 |
717 { | 717 { |
718 SkClipStack stack; | 718 SkClipStack stack; |
719 stack.clipDevPath(intersectingCircle, SkRegion::kIntersect_Op, false); | 719 stack.clipDevPath(intersectingCircle, SkCanvas::kIntersect_Op, false); |
720 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); | 720 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); |
721 } | 721 } |
722 | 722 |
723 { | 723 { |
724 SkClipStack stack; | 724 SkClipStack stack; |
725 stack.clipDevPath(nonIntersectingCircle, SkRegion::kIntersect_Op, false)
; | 725 stack.clipDevPath(nonIntersectingCircle, SkCanvas::kIntersect_Op, false)
; |
726 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); | 726 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); |
727 } | 727 } |
728 | 728 |
729 // Intersect Op tests with inverse filled rectangles | 729 // Intersect Op tests with inverse filled rectangles |
730 { | 730 { |
731 SkClipStack stack; | 731 SkClipStack stack; |
732 SkPath path; | 732 SkPath path; |
733 path.addRect(outsideRect); | 733 path.addRect(outsideRect); |
734 path.toggleInverseFillType(); | 734 path.toggleInverseFillType(); |
735 stack.clipDevPath(path, SkRegion::kIntersect_Op, false); | 735 stack.clipDevPath(path, SkCanvas::kIntersect_Op, false); |
736 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); | 736 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); |
737 } | 737 } |
738 | 738 |
739 { | 739 { |
740 SkClipStack stack; | 740 SkClipStack stack; |
741 SkPath path; | 741 SkPath path; |
742 path.addRect(insideRect); | 742 path.addRect(insideRect); |
743 path.toggleInverseFillType(); | 743 path.toggleInverseFillType(); |
744 stack.clipDevPath(path, SkRegion::kIntersect_Op, false); | 744 stack.clipDevPath(path, SkCanvas::kIntersect_Op, false); |
745 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); | 745 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); |
746 } | 746 } |
747 | 747 |
748 { | 748 { |
749 SkClipStack stack; | 749 SkClipStack stack; |
750 SkPath path; | 750 SkPath path; |
751 path.addRect(intersectingRect); | 751 path.addRect(intersectingRect); |
752 path.toggleInverseFillType(); | 752 path.toggleInverseFillType(); |
753 stack.clipDevPath(path, SkRegion::kIntersect_Op, false); | 753 stack.clipDevPath(path, SkCanvas::kIntersect_Op, false); |
754 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); | 754 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); |
755 } | 755 } |
756 | 756 |
757 { | 757 { |
758 SkClipStack stack; | 758 SkClipStack stack; |
759 SkPath path; | 759 SkPath path; |
760 path.addRect(nonIntersectingRect); | 760 path.addRect(nonIntersectingRect); |
761 path.toggleInverseFillType(); | 761 path.toggleInverseFillType(); |
762 stack.clipDevPath(path, SkRegion::kIntersect_Op, false); | 762 stack.clipDevPath(path, SkCanvas::kIntersect_Op, false); |
763 REPORTER_ASSERT(reporter, true == stack.quickContains(testRect)); | 763 REPORTER_ASSERT(reporter, true == stack.quickContains(testRect)); |
764 } | 764 } |
765 | 765 |
766 // Intersect Op tests with inverse filled circles | 766 // Intersect Op tests with inverse filled circles |
767 { | 767 { |
768 SkClipStack stack; | 768 SkClipStack stack; |
769 SkPath path = outsideCircle; | 769 SkPath path = outsideCircle; |
770 path.toggleInverseFillType(); | 770 path.toggleInverseFillType(); |
771 stack.clipDevPath(path, SkRegion::kIntersect_Op, false); | 771 stack.clipDevPath(path, SkCanvas::kIntersect_Op, false); |
772 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); | 772 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); |
773 } | 773 } |
774 | 774 |
775 { | 775 { |
776 SkClipStack stack; | 776 SkClipStack stack; |
777 SkPath path = insideCircle; | 777 SkPath path = insideCircle; |
778 path.toggleInverseFillType(); | 778 path.toggleInverseFillType(); |
779 stack.clipDevPath(path, SkRegion::kIntersect_Op, false); | 779 stack.clipDevPath(path, SkCanvas::kIntersect_Op, false); |
780 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); | 780 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); |
781 } | 781 } |
782 | 782 |
783 { | 783 { |
784 SkClipStack stack; | 784 SkClipStack stack; |
785 SkPath path = intersectingCircle; | 785 SkPath path = intersectingCircle; |
786 path.toggleInverseFillType(); | 786 path.toggleInverseFillType(); |
787 stack.clipDevPath(path, SkRegion::kIntersect_Op, false); | 787 stack.clipDevPath(path, SkCanvas::kIntersect_Op, false); |
788 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); | 788 REPORTER_ASSERT(reporter, false == stack.quickContains(testRect)); |
789 } | 789 } |
790 | 790 |
791 { | 791 { |
792 SkClipStack stack; | 792 SkClipStack stack; |
793 SkPath path = nonIntersectingCircle; | 793 SkPath path = nonIntersectingCircle; |
794 path.toggleInverseFillType(); | 794 path.toggleInverseFillType(); |
795 stack.clipDevPath(path, SkRegion::kIntersect_Op, false); | 795 stack.clipDevPath(path, SkCanvas::kIntersect_Op, false); |
796 REPORTER_ASSERT(reporter, true == stack.quickContains(testRect)); | 796 REPORTER_ASSERT(reporter, true == stack.quickContains(testRect)); |
797 } | 797 } |
798 } | 798 } |
799 | 799 |
800 static void set_region_to_stack(const SkClipStack& stack, const SkIRect& bounds,
SkRegion* region) { | 800 static void set_region_to_stack(const SkClipStack& stack, const SkIRect& bounds,
SkRegion* region) { |
801 region->setRect(bounds); | 801 region->setRect(bounds); |
802 SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart); | 802 SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart); |
803 while (const SkClipStack::Element *element = iter.next()) { | 803 while (const SkClipStack::Element *element = iter.next()) { |
804 SkRegion elemRegion; | 804 SkRegion elemRegion; |
805 SkRegion boundsRgn(bounds); | 805 SkRegion boundsRgn(bounds); |
806 SkPath path; | 806 SkPath path; |
807 | 807 |
808 switch (element->getType()) { | 808 switch (element->getType()) { |
809 case SkClipStack::Element::kEmpty_Type: | 809 case SkClipStack::Element::kEmpty_Type: |
810 elemRegion.setEmpty(); | 810 elemRegion.setEmpty(); |
811 break; | 811 break; |
812 default: | 812 default: |
813 element->asPath(&path); | 813 element->asPath(&path); |
814 elemRegion.setPath(path, boundsRgn); | 814 elemRegion.setPath(path, boundsRgn); |
815 break; | 815 break; |
816 } | 816 } |
817 region->op(elemRegion, element->getOp()); | 817 region->op(elemRegion, (SkRegion::Op)element->getOp()); |
818 } | 818 } |
819 } | 819 } |
820 | 820 |
821 static void test_invfill_diff_bug(skiatest::Reporter* reporter) { | 821 static void test_invfill_diff_bug(skiatest::Reporter* reporter) { |
822 SkClipStack stack; | 822 SkClipStack stack; |
823 stack.clipDevRect({10, 10, 20, 20}, SkRegion::kIntersect_Op, false); | 823 stack.clipDevRect({10, 10, 20, 20}, SkCanvas::kIntersect_Op, false); |
824 | 824 |
825 SkPath path; | 825 SkPath path; |
826 path.addRect({30, 10, 40, 20}); | 826 path.addRect({30, 10, 40, 20}); |
827 path.setFillType(SkPath::kInverseWinding_FillType); | 827 path.setFillType(SkPath::kInverseWinding_FillType); |
828 stack.clipDevPath(path, SkRegion::kDifference_Op, false); | 828 stack.clipDevPath(path, SkCanvas::kDifference_Op, false); |
829 | 829 |
830 REPORTER_ASSERT(reporter, SkClipStack::kEmptyGenID == stack.getTopmostGenID(
)); | 830 REPORTER_ASSERT(reporter, SkClipStack::kEmptyGenID == stack.getTopmostGenID(
)); |
831 | 831 |
832 SkRect stackBounds; | 832 SkRect stackBounds; |
833 SkClipStack::BoundsType stackBoundsType; | 833 SkClipStack::BoundsType stackBoundsType; |
834 stack.getBounds(&stackBounds, &stackBoundsType); | 834 stack.getBounds(&stackBounds, &stackBoundsType); |
835 | 835 |
836 REPORTER_ASSERT(reporter, stackBounds.isEmpty()); | 836 REPORTER_ASSERT(reporter, stackBounds.isEmpty()); |
837 REPORTER_ASSERT(reporter, SkClipStack::kNormal_BoundsType == stackBoundsType
); | 837 REPORTER_ASSERT(reporter, SkClipStack::kNormal_BoundsType == stackBoundsType
); |
838 | 838 |
839 SkRegion region; | 839 SkRegion region; |
840 set_region_to_stack(stack, {0, 0, 50, 30}, ®ion); | 840 set_region_to_stack(stack, {0, 0, 50, 30}, ®ion); |
841 | 841 |
842 REPORTER_ASSERT(reporter, region.isEmpty()); | 842 REPORTER_ASSERT(reporter, region.isEmpty()); |
843 } | 843 } |
844 | 844 |
845 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 845 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
846 | 846 |
847 #if SK_SUPPORT_GPU | 847 #if SK_SUPPORT_GPU |
848 // Functions that add a shape to the clip stack. The shape is computed from a re
ctangle. | 848 // Functions that add a shape to the clip stack. The shape is computed from a re
ctangle. |
849 // AA is always disabled since the clip stack reducer can cause changes in aa ra
sterization of the | 849 // AA is always disabled since the clip stack reducer can cause changes in aa ra
sterization of the |
850 // stack. A fractional edge repeated in different elements may be rasterized few
er times using the | 850 // stack. A fractional edge repeated in different elements may be rasterized few
er times using the |
851 // reduced stack. | 851 // reduced stack. |
852 typedef void (*AddElementFunc) (const SkRect& rect, | 852 typedef void (*AddElementFunc) (const SkRect& rect, |
853 bool invert, | 853 bool invert, |
854 SkRegion::Op op, | 854 SkCanvas::ClipOp op, |
855 SkClipStack* stack, | 855 SkClipStack* stack, |
856 bool doAA); | 856 bool doAA); |
857 | 857 |
858 static void add_round_rect(const SkRect& rect, bool invert, SkRegion::Op op, SkC
lipStack* stack, | 858 static void add_round_rect(const SkRect& rect, bool invert, SkCanvas::ClipOp op,
SkClipStack* stack, |
859 bool doAA) { | 859 bool doAA) { |
860 SkScalar rx = rect.width() / 10; | 860 SkScalar rx = rect.width() / 10; |
861 SkScalar ry = rect.height() / 20; | 861 SkScalar ry = rect.height() / 20; |
862 if (invert) { | 862 if (invert) { |
863 SkPath path; | 863 SkPath path; |
864 path.addRoundRect(rect, rx, ry); | 864 path.addRoundRect(rect, rx, ry); |
865 path.setFillType(SkPath::kInverseWinding_FillType); | 865 path.setFillType(SkPath::kInverseWinding_FillType); |
866 stack->clipDevPath(path, op, doAA); | 866 stack->clipDevPath(path, op, doAA); |
867 } else { | 867 } else { |
868 SkRRect rrect; | 868 SkRRect rrect; |
869 rrect.setRectXY(rect, rx, ry); | 869 rrect.setRectXY(rect, rx, ry); |
870 stack->clipDevRRect(rrect, op, doAA); | 870 stack->clipDevRRect(rrect, op, doAA); |
871 } | 871 } |
872 }; | 872 }; |
873 | 873 |
874 static void add_rect(const SkRect& rect, bool invert, SkRegion::Op op, SkClipSta
ck* stack, | 874 static void add_rect(const SkRect& rect, bool invert, SkCanvas::ClipOp op, SkCli
pStack* stack, |
875 bool doAA) { | 875 bool doAA) { |
876 if (invert) { | 876 if (invert) { |
877 SkPath path; | 877 SkPath path; |
878 path.addRect(rect); | 878 path.addRect(rect); |
879 path.setFillType(SkPath::kInverseWinding_FillType); | 879 path.setFillType(SkPath::kInverseWinding_FillType); |
880 stack->clipDevPath(path, op, doAA); | 880 stack->clipDevPath(path, op, doAA); |
881 } else { | 881 } else { |
882 stack->clipDevRect(rect, op, doAA); | 882 stack->clipDevRect(rect, op, doAA); |
883 } | 883 } |
884 }; | 884 }; |
885 | 885 |
886 static void add_oval(const SkRect& rect, bool invert, SkRegion::Op op, SkClipSta
ck* stack, | 886 static void add_oval(const SkRect& rect, bool invert, SkCanvas::ClipOp op, SkCli
pStack* stack, |
887 bool doAA) { | 887 bool doAA) { |
888 SkPath path; | 888 SkPath path; |
889 path.addOval(rect); | 889 path.addOval(rect); |
890 if (invert) { | 890 if (invert) { |
891 path.setFillType(SkPath::kInverseWinding_FillType); | 891 path.setFillType(SkPath::kInverseWinding_FillType); |
892 } | 892 } |
893 stack->clipDevPath(path, op, doAA); | 893 stack->clipDevPath(path, op, doAA); |
894 }; | 894 }; |
895 | 895 |
896 static void add_elem_to_stack(const SkClipStack::Element& element, SkClipStack*
stack) { | 896 static void add_elem_to_stack(const SkClipStack::Element& element, SkClipStack*
stack) { |
(...skipping 25 matching lines...) Expand all Loading... |
922 enum { | 922 enum { |
923 kNumTests = 250, | 923 kNumTests = 250, |
924 kMinElemsPerTest = 1, | 924 kMinElemsPerTest = 1, |
925 kMaxElemsPerTest = 50, | 925 kMaxElemsPerTest = 50, |
926 }; | 926 }; |
927 | 927 |
928 // min/max size of a clip element as a fraction of kBounds. | 928 // min/max size of a clip element as a fraction of kBounds. |
929 static const SkScalar kMinElemSizeFrac = SK_Scalar1 / 5; | 929 static const SkScalar kMinElemSizeFrac = SK_Scalar1 / 5; |
930 static const SkScalar kMaxElemSizeFrac = SK_Scalar1; | 930 static const SkScalar kMaxElemSizeFrac = SK_Scalar1; |
931 | 931 |
932 static const SkRegion::Op kOps[] = { | 932 static const SkCanvas::ClipOp kOps[] = { |
933 SkRegion::kDifference_Op, | 933 SkCanvas::kDifference_Op, |
934 SkRegion::kIntersect_Op, | 934 SkCanvas::kIntersect_Op, |
935 SkRegion::kUnion_Op, | 935 SkCanvas::kUnion_Op, |
936 SkRegion::kXOR_Op, | 936 SkCanvas::kXOR_Op, |
937 SkRegion::kReverseDifference_Op, | 937 SkCanvas::kReverseDifference_Op, |
938 SkRegion::kReplace_Op, | 938 SkCanvas::kReplace_Op, |
939 }; | 939 }; |
940 | 940 |
941 // Replace operations short-circuit the optimizer. We want to make sure that
we test this code | 941 // Replace operations short-circuit the optimizer. We want to make sure that
we test this code |
942 // path a little bit but we don't want it to prevent us from testing many lo
nger traversals in | 942 // path a little bit but we don't want it to prevent us from testing many lo
nger traversals in |
943 // the optimizer. | 943 // the optimizer. |
944 static const int kReplaceDiv = 4 * kMaxElemsPerTest; | 944 static const int kReplaceDiv = 4 * kMaxElemsPerTest; |
945 | 945 |
946 // We want to test inverse fills. However, they are quite rare in practice s
o don't over do it. | 946 // We want to test inverse fills. However, they are quite rare in practice s
o don't over do it. |
947 static const SkScalar kFractionInverted = SK_Scalar1 / kMaxElemsPerTest; | 947 static const SkScalar kFractionInverted = SK_Scalar1 / kMaxElemsPerTest; |
948 | 948 |
949 static const SkScalar kFractionAntialiased = 0.25; | 949 static const SkScalar kFractionAntialiased = 0.25; |
950 | 950 |
951 static const AddElementFunc kElementFuncs[] = { | 951 static const AddElementFunc kElementFuncs[] = { |
952 add_rect, | 952 add_rect, |
953 add_round_rect, | 953 add_round_rect, |
954 add_oval, | 954 add_oval, |
955 }; | 955 }; |
956 | 956 |
957 SkRandom r; | 957 SkRandom r; |
958 | 958 |
959 for (int i = 0; i < kNumTests; ++i) { | 959 for (int i = 0; i < kNumTests; ++i) { |
960 SkString testCase; | 960 SkString testCase; |
961 testCase.printf("Iteration %d", i); | 961 testCase.printf("Iteration %d", i); |
962 | 962 |
963 // Randomly generate a clip stack. | 963 // Randomly generate a clip stack. |
964 SkClipStack stack; | 964 SkClipStack stack; |
965 int numElems = r.nextRangeU(kMinElemsPerTest, kMaxElemsPerTest); | 965 int numElems = r.nextRangeU(kMinElemsPerTest, kMaxElemsPerTest); |
966 bool doAA = r.nextBiasedBool(kFractionAntialiased); | 966 bool doAA = r.nextBiasedBool(kFractionAntialiased); |
967 for (int e = 0; e < numElems; ++e) { | 967 for (int e = 0; e < numElems; ++e) { |
968 SkRegion::Op op = kOps[r.nextULessThan(SK_ARRAY_COUNT(kOps))]; | 968 SkCanvas::ClipOp op = kOps[r.nextULessThan(SK_ARRAY_COUNT(kOps))]; |
969 if (op == SkRegion::kReplace_Op) { | 969 if (op == SkCanvas::kReplace_Op) { |
970 if (r.nextU() % kReplaceDiv) { | 970 if (r.nextU() % kReplaceDiv) { |
971 --e; | 971 --e; |
972 continue; | 972 continue; |
973 } | 973 } |
974 } | 974 } |
975 | 975 |
976 // saves can change the clip stack behavior when an element is added
. | 976 // saves can change the clip stack behavior when an element is added
. |
977 bool doSave = r.nextBool(); | 977 bool doSave = r.nextBool(); |
978 | 978 |
979 SkSize size = SkSize::Make( | 979 SkSize size = SkSize::Make( |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1044 // whether the result is bounded or not, the whole plane should star
t outside the clip. | 1044 // whether the result is bounded or not, the whole plane should star
t outside the clip. |
1045 reducedStack.clipEmpty(); | 1045 reducedStack.clipEmpty(); |
1046 } | 1046 } |
1047 for (ElementList::Iter iter(reduced->elements()); iter.get(); iter.next(
)) { | 1047 for (ElementList::Iter iter(reduced->elements()); iter.get(); iter.next(
)) { |
1048 add_elem_to_stack(*iter.get(), &reducedStack); | 1048 add_elem_to_stack(*iter.get(), &reducedStack); |
1049 } | 1049 } |
1050 | 1050 |
1051 SkIRect ibounds = reduced->hasIBounds() ? reduced->ibounds() : kIBounds; | 1051 SkIRect ibounds = reduced->hasIBounds() ? reduced->ibounds() : kIBounds; |
1052 | 1052 |
1053 // GrReducedClipStack assumes that the final result is clipped to the re
turned bounds | 1053 // GrReducedClipStack assumes that the final result is clipped to the re
turned bounds |
1054 reducedStack.clipDevRect(ibounds, SkRegion::kIntersect_Op); | 1054 reducedStack.clipDevRect(ibounds, SkCanvas::kIntersect_Op); |
1055 stack.clipDevRect(ibounds, SkRegion::kIntersect_Op); | 1055 stack.clipDevRect(ibounds, SkCanvas::kIntersect_Op); |
1056 | 1056 |
1057 // convert both the original stack and reduced stack to SkRegions and se
e if they're equal | 1057 // convert both the original stack and reduced stack to SkRegions and se
e if they're equal |
1058 SkRegion region; | 1058 SkRegion region; |
1059 set_region_to_stack(stack, ibounds, ®ion); | 1059 set_region_to_stack(stack, ibounds, ®ion); |
1060 | 1060 |
1061 SkRegion reducedRegion; | 1061 SkRegion reducedRegion; |
1062 set_region_to_stack(reducedStack, ibounds, &reducedRegion); | 1062 set_region_to_stack(reducedStack, ibounds, &reducedRegion); |
1063 | 1063 |
1064 REPORTER_ASSERT_MESSAGE(reporter, region == reducedRegion, testCase.c_st
r()); | 1064 REPORTER_ASSERT_MESSAGE(reporter, region == reducedRegion, testCase.c_st
r()); |
1065 | 1065 |
1066 reduced->~GrReducedClip(); | 1066 reduced->~GrReducedClip(); |
1067 } | 1067 } |
1068 } | 1068 } |
1069 | 1069 |
1070 #ifdef SK_BUILD_FOR_WIN | 1070 #ifdef SK_BUILD_FOR_WIN |
1071 #define SUPPRESS_VISIBILITY_WARNING | 1071 #define SUPPRESS_VISIBILITY_WARNING |
1072 #else | 1072 #else |
1073 #define SUPPRESS_VISIBILITY_WARNING __attribute__((visibility("hidden"))) | 1073 #define SUPPRESS_VISIBILITY_WARNING __attribute__((visibility("hidden"))) |
1074 #endif | 1074 #endif |
1075 | 1075 |
1076 static void test_reduced_clip_stack_genid(skiatest::Reporter* reporter) { | 1076 static void test_reduced_clip_stack_genid(skiatest::Reporter* reporter) { |
1077 { | 1077 { |
1078 SkClipStack stack; | 1078 SkClipStack stack; |
1079 stack.clipDevRect(SkRect::MakeXYWH(0, 0, 100, 100), SkRegion::kReplace_O
p, true); | 1079 stack.clipDevRect(SkRect::MakeXYWH(0, 0, 100, 100), SkCanvas::kReplace_O
p, true); |
1080 stack.clipDevRect(SkRect::MakeXYWH(0, 0, SkScalar(50.3), SkScalar(50.3))
, SkRegion::kReplace_Op, true); | 1080 stack.clipDevRect(SkRect::MakeXYWH(0, 0, SkScalar(50.3), SkScalar(50.3))
, SkCanvas::kReplace_Op, true); |
1081 SkRect bounds = SkRect::MakeXYWH(0, 0, 100, 100); | 1081 SkRect bounds = SkRect::MakeXYWH(0, 0, 100, 100); |
1082 | 1082 |
1083 SkAlignedSTStorage<1, GrReducedClip> storage; | 1083 SkAlignedSTStorage<1, GrReducedClip> storage; |
1084 memset(storage.get(), 0, sizeof(GrReducedClip)); | 1084 memset(storage.get(), 0, sizeof(GrReducedClip)); |
1085 GR_STATIC_ASSERT(0 == SkClipStack::kInvalidGenID); | 1085 GR_STATIC_ASSERT(0 == SkClipStack::kInvalidGenID); |
1086 const GrReducedClip* reduced = new (storage.get()) GrReducedClip(stack,
bounds); | 1086 const GrReducedClip* reduced = new (storage.get()) GrReducedClip(stack,
bounds); |
1087 | 1087 |
1088 REPORTER_ASSERT(reporter, reduced->elements().count() == 1); | 1088 REPORTER_ASSERT(reporter, reduced->elements().count() == 1); |
1089 // Clips will be cached based on the generation id. Make sure the gen id
is valid. | 1089 // Clips will be cached based on the generation id. Make sure the gen id
is valid. |
1090 REPORTER_ASSERT(reporter, SkClipStack::kInvalidGenID != reduced->element
sGenID()); | 1090 REPORTER_ASSERT(reporter, SkClipStack::kInvalidGenID != reduced->element
sGenID()); |
1091 | 1091 |
1092 reduced->~GrReducedClip(); | 1092 reduced->~GrReducedClip(); |
1093 } | 1093 } |
1094 { | 1094 { |
1095 SkClipStack stack; | 1095 SkClipStack stack; |
1096 | 1096 |
1097 // Create a clip with following 25.3, 25.3 boxes which are 25 apart: | 1097 // Create a clip with following 25.3, 25.3 boxes which are 25 apart: |
1098 // A B | 1098 // A B |
1099 // C D | 1099 // C D |
1100 | 1100 |
1101 stack.clipDevRect(SkRect::MakeXYWH(0, 0, SkScalar(25.3), SkScalar(25.3))
, SkRegion::kReplace_Op, true); | 1101 stack.clipDevRect(SkRect::MakeXYWH(0, 0, SkScalar(25.3), SkScalar(25.3))
, SkCanvas::kReplace_Op, true); |
1102 int32_t genIDA = stack.getTopmostGenID(); | 1102 int32_t genIDA = stack.getTopmostGenID(); |
1103 stack.clipDevRect(SkRect::MakeXYWH(50, 0, SkScalar(25.3), SkScalar(25.3)
), SkRegion::kUnion_Op, true); | 1103 stack.clipDevRect(SkRect::MakeXYWH(50, 0, SkScalar(25.3), SkScalar(25.3)
), SkCanvas::kUnion_Op, true); |
1104 int32_t genIDB = stack.getTopmostGenID(); | 1104 int32_t genIDB = stack.getTopmostGenID(); |
1105 stack.clipDevRect(SkRect::MakeXYWH(0, 50, SkScalar(25.3), SkScalar(25.3)
), SkRegion::kUnion_Op, true); | 1105 stack.clipDevRect(SkRect::MakeXYWH(0, 50, SkScalar(25.3), SkScalar(25.3)
), SkCanvas::kUnion_Op, true); |
1106 int32_t genIDC = stack.getTopmostGenID(); | 1106 int32_t genIDC = stack.getTopmostGenID(); |
1107 stack.clipDevRect(SkRect::MakeXYWH(50, 50, SkScalar(25.3), SkScalar(25.3
)), SkRegion::kUnion_Op, true); | 1107 stack.clipDevRect(SkRect::MakeXYWH(50, 50, SkScalar(25.3), SkScalar(25.3
)), SkCanvas::kUnion_Op, true); |
1108 int32_t genIDD = stack.getTopmostGenID(); | 1108 int32_t genIDD = stack.getTopmostGenID(); |
1109 | 1109 |
1110 | 1110 |
1111 #define IXYWH SkIRect::MakeXYWH | 1111 #define IXYWH SkIRect::MakeXYWH |
1112 #define XYWH SkRect::MakeXYWH | 1112 #define XYWH SkRect::MakeXYWH |
1113 | 1113 |
1114 SkIRect stackBounds = IXYWH(0, 0, 76, 76); | 1114 SkIRect stackBounds = IXYWH(0, 0, 76, 76); |
1115 | 1115 |
1116 // The base test is to test each rect in two ways: | 1116 // The base test is to test each rect in two ways: |
1117 // 1) The box dimensions. (Should reduce to "all in", no elements). | 1117 // 1) The box dimensions. (Should reduce to "all in", no elements). |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1176 REPORTER_ASSERT(reporter, reduced.hasIBounds()); | 1176 REPORTER_ASSERT(reporter, reduced.hasIBounds()); |
1177 SkASSERT(reduced.hasIBounds()); | 1177 SkASSERT(reduced.hasIBounds()); |
1178 REPORTER_ASSERT(reporter, reduced.ibounds() == testCases[i].clipIRec
t); | 1178 REPORTER_ASSERT(reporter, reduced.ibounds() == testCases[i].clipIRec
t); |
1179 SkASSERT(reduced.ibounds() == testCases[i].clipIRect); | 1179 SkASSERT(reduced.ibounds() == testCases[i].clipIRect); |
1180 } | 1180 } |
1181 } | 1181 } |
1182 } | 1182 } |
1183 | 1183 |
1184 static void test_reduced_clip_stack_no_aa_crash(skiatest::Reporter* reporter) { | 1184 static void test_reduced_clip_stack_no_aa_crash(skiatest::Reporter* reporter) { |
1185 SkClipStack stack; | 1185 SkClipStack stack; |
1186 stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 100, 100), SkRegion::kReplace_Op); | 1186 stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 100, 100), SkCanvas::kReplace_Op); |
1187 stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 50, 50), SkRegion::kReplace_Op); | 1187 stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 50, 50), SkCanvas::kReplace_Op); |
1188 SkRect bounds = SkRect::MakeXYWH(0, 0, 100, 100); | 1188 SkRect bounds = SkRect::MakeXYWH(0, 0, 100, 100); |
1189 | 1189 |
1190 // At the time, this would crash. | 1190 // At the time, this would crash. |
1191 const GrReducedClip reduced(stack, bounds); | 1191 const GrReducedClip reduced(stack, bounds); |
1192 REPORTER_ASSERT(reporter, reduced.elements().isEmpty()); | 1192 REPORTER_ASSERT(reporter, reduced.elements().isEmpty()); |
1193 } | 1193 } |
1194 | 1194 |
1195 enum class ClipMethod { | 1195 enum class ClipMethod { |
1196 kSkipDraw, | 1196 kSkipDraw, |
1197 kIgnoreClip, | 1197 kIgnoreClip, |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1277 constexpr SkScalar kMaxScale = 3; | 1277 constexpr SkScalar kMaxScale = 3; |
1278 constexpr int kNumIters = 8; | 1278 constexpr int kNumIters = 8; |
1279 | 1279 |
1280 SkString name; | 1280 SkString name; |
1281 SkRandom rand; | 1281 SkRandom rand; |
1282 | 1282 |
1283 for (int i = 0; i < kNumIters; ++i) { | 1283 for (int i = 0; i < kNumIters; ++i) { |
1284 // Pixel-aligned rect (iior=true). | 1284 // Pixel-aligned rect (iior=true). |
1285 name.printf("Pixel-aligned rect test, iter %i", i); | 1285 name.printf("Pixel-aligned rect test, iter %i", i); |
1286 SkClipStack stack; | 1286 SkClipStack stack; |
1287 stack.clipDevRect(alignedRect, SkRegion::kIntersect_Op, true); | 1287 stack.clipDevRect(alignedRect, SkCanvas::kIntersect_Op, true); |
1288 test_aa_query(reporter, name, stack, m, {IL, IT, IR, IB}, ClipMethod::kI
gnoreClip); | 1288 test_aa_query(reporter, name, stack, m, {IL, IT, IR, IB}, ClipMethod::kI
gnoreClip); |
1289 test_aa_query(reporter, name, stack, m, {IL, IT-1, IR, IT}, ClipMethod::
kSkipDraw); | 1289 test_aa_query(reporter, name, stack, m, {IL, IT-1, IR, IT}, ClipMethod::
kSkipDraw); |
1290 test_aa_query(reporter, name, stack, m, {IL, IT-2, IR, IB}, ClipMethod::
kScissor); | 1290 test_aa_query(reporter, name, stack, m, {IL, IT-2, IR, IB}, ClipMethod::
kScissor); |
1291 | 1291 |
1292 // Rect (iior=true). | 1292 // Rect (iior=true). |
1293 name.printf("Rect test, iter %i", i); | 1293 name.printf("Rect test, iter %i", i); |
1294 stack.reset(); | 1294 stack.reset(); |
1295 stack.clipDevRect(rect, SkRegion::kIntersect_Op, true); | 1295 stack.clipDevRect(rect, SkCanvas::kIntersect_Op, true); |
1296 test_aa_query(reporter, name, stack, m, {L, T, R, B}, ClipMethod::kIgno
reClip); | 1296 test_aa_query(reporter, name, stack, m, {L, T, R, B}, ClipMethod::kIgno
reClip); |
1297 test_aa_query(reporter, name, stack, m, {L-.1f, T, L, B}, ClipMethod::kS
kipDraw); | 1297 test_aa_query(reporter, name, stack, m, {L-.1f, T, L, B}, ClipMethod::kS
kipDraw); |
1298 test_aa_query(reporter, name, stack, m, {L-.1f, T, L+.1f, B}, ClipMethod
::kAAElements, 1); | 1298 test_aa_query(reporter, name, stack, m, {L-.1f, T, L+.1f, B}, ClipMethod
::kAAElements, 1); |
1299 | 1299 |
1300 // Difference rect (iior=false, inside-out bounds). | 1300 // Difference rect (iior=false, inside-out bounds). |
1301 name.printf("Difference rect test, iter %i", i); | 1301 name.printf("Difference rect test, iter %i", i); |
1302 stack.reset(); | 1302 stack.reset(); |
1303 stack.clipDevRect(rect, SkRegion::kDifference_Op, true); | 1303 stack.clipDevRect(rect, SkCanvas::kDifference_Op, true); |
1304 test_aa_query(reporter, name, stack, m, {L, T, R, B}, ClipMethod::kSkipD
raw); | 1304 test_aa_query(reporter, name, stack, m, {L, T, R, B}, ClipMethod::kSkipD
raw); |
1305 test_aa_query(reporter, name, stack, m, {L, T-.1f, R, T}, ClipMethod::kI
gnoreClip); | 1305 test_aa_query(reporter, name, stack, m, {L, T-.1f, R, T}, ClipMethod::kI
gnoreClip); |
1306 test_aa_query(reporter, name, stack, m, {L, T-.1f, R, T+.1f}, ClipMethod
::kAAElements, 1); | 1306 test_aa_query(reporter, name, stack, m, {L, T-.1f, R, T+.1f}, ClipMethod
::kAAElements, 1); |
1307 | 1307 |
1308 // Complex clip (iior=false, normal bounds). | 1308 // Complex clip (iior=false, normal bounds). |
1309 name.printf("Complex clip test, iter %i", i); | 1309 name.printf("Complex clip test, iter %i", i); |
1310 stack.reset(); | 1310 stack.reset(); |
1311 stack.clipDevRect(rect, SkRegion::kIntersect_Op, true); | 1311 stack.clipDevRect(rect, SkCanvas::kIntersect_Op, true); |
1312 stack.clipDevRect(innerRect, SkRegion::kXOR_Op, true); | 1312 stack.clipDevRect(innerRect, SkCanvas::kXOR_Op, true); |
1313 test_aa_query(reporter, name, stack, m, {l, t, r, b}, ClipMethod::kSkipD
raw); | 1313 test_aa_query(reporter, name, stack, m, {l, t, r, b}, ClipMethod::kSkipD
raw); |
1314 test_aa_query(reporter, name, stack, m, {r-.1f, t, R, b}, ClipMethod::kA
AElements, 1); | 1314 test_aa_query(reporter, name, stack, m, {r-.1f, t, R, b}, ClipMethod::kA
AElements, 1); |
1315 test_aa_query(reporter, name, stack, m, {r-.1f, t, R+.1f, b}, ClipMethod
::kAAElements, 2); | 1315 test_aa_query(reporter, name, stack, m, {r-.1f, t, R+.1f, b}, ClipMethod
::kAAElements, 2); |
1316 test_aa_query(reporter, name, stack, m, {r, t, R+.1f, b}, ClipMethod::kA
AElements, 1); | 1316 test_aa_query(reporter, name, stack, m, {r, t, R+.1f, b}, ClipMethod::kA
AElements, 1); |
1317 test_aa_query(reporter, name, stack, m, {r, t, R, b}, ClipMethod::kIgnor
eClip); | 1317 test_aa_query(reporter, name, stack, m, {r, t, R, b}, ClipMethod::kIgnor
eClip); |
1318 test_aa_query(reporter, name, stack, m, {R, T, R+.1f, B}, ClipMethod::kS
kipDraw); | 1318 test_aa_query(reporter, name, stack, m, {R, T, R+.1f, B}, ClipMethod::kS
kipDraw); |
1319 | 1319 |
1320 // Complex clip where outer rect is pixel aligned (iior=false, normal bo
unds). | 1320 // Complex clip where outer rect is pixel aligned (iior=false, normal bo
unds). |
1321 name.printf("Aligned Complex clip test, iter %i", i); | 1321 name.printf("Aligned Complex clip test, iter %i", i); |
1322 stack.reset(); | 1322 stack.reset(); |
1323 stack.clipDevRect(alignedRect, SkRegion::kIntersect_Op, true); | 1323 stack.clipDevRect(alignedRect, SkCanvas::kIntersect_Op, true); |
1324 stack.clipDevRect(innerRect, SkRegion::kXOR_Op, true); | 1324 stack.clipDevRect(innerRect, SkCanvas::kXOR_Op, true); |
1325 test_aa_query(reporter, name, stack, m, {l, t, r, b}, ClipMethod::kSkipD
raw); | 1325 test_aa_query(reporter, name, stack, m, {l, t, r, b}, ClipMethod::kSkipD
raw); |
1326 test_aa_query(reporter, name, stack, m, {l, b-.1f, r, IB}, ClipMethod::k
AAElements, 1); | 1326 test_aa_query(reporter, name, stack, m, {l, b-.1f, r, IB}, ClipMethod::k
AAElements, 1); |
1327 test_aa_query(reporter, name, stack, m, {l, b-.1f, r, IB+.1f}, ClipMetho
d::kAAElements, 1); | 1327 test_aa_query(reporter, name, stack, m, {l, b-.1f, r, IB+.1f}, ClipMetho
d::kAAElements, 1); |
1328 test_aa_query(reporter, name, stack, m, {l, b, r, IB+.1f}, ClipMethod::k
AAElements, 0); | 1328 test_aa_query(reporter, name, stack, m, {l, b, r, IB+.1f}, ClipMethod::k
AAElements, 0); |
1329 test_aa_query(reporter, name, stack, m, {l, b, r, IB}, ClipMethod::kIgno
reClip); | 1329 test_aa_query(reporter, name, stack, m, {l, b, r, IB}, ClipMethod::kIgno
reClip); |
1330 test_aa_query(reporter, name, stack, m, {IL, IB, IR, IB+.1f}, ClipMethod
::kSkipDraw); | 1330 test_aa_query(reporter, name, stack, m, {IL, IB, IR, IB+.1f}, ClipMethod
::kSkipDraw); |
1331 | 1331 |
1332 // Apply random transforms and try again. This ensures the clip stack re
duction is hardened | 1332 // Apply random transforms and try again. This ensures the clip stack re
duction is hardened |
1333 // against FP rounding error. | 1333 // against FP rounding error. |
1334 SkScalar sx = rand.nextRangeScalar(kMinScale, kMaxScale); | 1334 SkScalar sx = rand.nextRangeScalar(kMinScale, kMaxScale); |
(...skipping 20 matching lines...) Expand all Loading... |
1355 REPORTER_ASSERT(reporter, 0 == stack.getSaveCount()); | 1355 REPORTER_ASSERT(reporter, 0 == stack.getSaveCount()); |
1356 assert_count(reporter, stack, 0); | 1356 assert_count(reporter, stack, 0); |
1357 | 1357 |
1358 static const SkIRect gRects[] = { | 1358 static const SkIRect gRects[] = { |
1359 { 0, 0, 100, 100 }, | 1359 { 0, 0, 100, 100 }, |
1360 { 25, 25, 125, 125 }, | 1360 { 25, 25, 125, 125 }, |
1361 { 0, 0, 1000, 1000 }, | 1361 { 0, 0, 1000, 1000 }, |
1362 { 0, 0, 75, 75 } | 1362 { 0, 0, 75, 75 } |
1363 }; | 1363 }; |
1364 for (size_t i = 0; i < SK_ARRAY_COUNT(gRects); i++) { | 1364 for (size_t i = 0; i < SK_ARRAY_COUNT(gRects); i++) { |
1365 stack.clipDevRect(gRects[i], SkRegion::kIntersect_Op); | 1365 stack.clipDevRect(gRects[i], SkCanvas::kIntersect_Op); |
1366 } | 1366 } |
1367 | 1367 |
1368 // all of the above rects should have been intersected, leaving only 1 rect | 1368 // all of the above rects should have been intersected, leaving only 1 rect |
1369 SkClipStack::B2TIter iter(stack); | 1369 SkClipStack::B2TIter iter(stack); |
1370 const SkClipStack::Element* element = iter.next(); | 1370 const SkClipStack::Element* element = iter.next(); |
1371 SkRect answer; | 1371 SkRect answer; |
1372 answer.iset(25, 25, 75, 75); | 1372 answer.iset(25, 25, 75, 75); |
1373 | 1373 |
1374 REPORTER_ASSERT(reporter, element); | 1374 REPORTER_ASSERT(reporter, element); |
1375 REPORTER_ASSERT(reporter, SkClipStack::Element::kRect_Type == element->getTy
pe()); | 1375 REPORTER_ASSERT(reporter, SkClipStack::Element::kRect_Type == element->getTy
pe()); |
1376 REPORTER_ASSERT(reporter, SkRegion::kIntersect_Op == element->getOp()); | 1376 REPORTER_ASSERT(reporter, SkCanvas::kIntersect_Op == element->getOp()); |
1377 REPORTER_ASSERT(reporter, element->getRect() == answer); | 1377 REPORTER_ASSERT(reporter, element->getRect() == answer); |
1378 // now check that we only had one in our iterator | 1378 // now check that we only had one in our iterator |
1379 REPORTER_ASSERT(reporter, !iter.next()); | 1379 REPORTER_ASSERT(reporter, !iter.next()); |
1380 | 1380 |
1381 stack.reset(); | 1381 stack.reset(); |
1382 REPORTER_ASSERT(reporter, 0 == stack.getSaveCount()); | 1382 REPORTER_ASSERT(reporter, 0 == stack.getSaveCount()); |
1383 assert_count(reporter, stack, 0); | 1383 assert_count(reporter, stack, 0); |
1384 | 1384 |
1385 test_assign_and_comparison(reporter); | 1385 test_assign_and_comparison(reporter); |
1386 test_iterators(reporter); | 1386 test_iterators(reporter); |
1387 test_bounds(reporter, SkClipStack::Element::kRect_Type); | 1387 test_bounds(reporter, SkClipStack::Element::kRect_Type); |
1388 test_bounds(reporter, SkClipStack::Element::kRRect_Type); | 1388 test_bounds(reporter, SkClipStack::Element::kRRect_Type); |
1389 test_bounds(reporter, SkClipStack::Element::kPath_Type); | 1389 test_bounds(reporter, SkClipStack::Element::kPath_Type); |
1390 test_isWideOpen(reporter); | 1390 test_isWideOpen(reporter); |
1391 test_rect_merging(reporter); | 1391 test_rect_merging(reporter); |
1392 test_rect_replace(reporter); | 1392 test_rect_replace(reporter); |
1393 test_rect_inverse_fill(reporter); | 1393 test_rect_inverse_fill(reporter); |
1394 test_path_replace(reporter); | 1394 test_path_replace(reporter); |
1395 test_quickContains(reporter); | 1395 test_quickContains(reporter); |
1396 test_invfill_diff_bug(reporter); | 1396 test_invfill_diff_bug(reporter); |
1397 #if SK_SUPPORT_GPU | 1397 #if SK_SUPPORT_GPU |
1398 test_reduced_clip_stack(reporter); | 1398 test_reduced_clip_stack(reporter); |
1399 test_reduced_clip_stack_genid(reporter); | 1399 test_reduced_clip_stack_genid(reporter); |
1400 test_reduced_clip_stack_no_aa_crash(reporter); | 1400 test_reduced_clip_stack_no_aa_crash(reporter); |
1401 test_reduced_clip_stack_aa(reporter); | 1401 test_reduced_clip_stack_aa(reporter); |
1402 #endif | 1402 #endif |
1403 } | 1403 } |
OLD | NEW |