• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/core/SkMatrix.h"
9 #include "include/core/SkPath.h"
10 #include "include/core/SkPathTypes.h"
11 #include "include/core/SkPoint.h"
12 #include "include/core/SkRRect.h"
13 #include "include/core/SkRect.h"
14 #include "include/core/SkRegion.h"
15 #include "include/core/SkScalar.h"
16 #include "include/core/SkTypes.h"
17 #include "include/private/base/SkDebug.h"
18 #include "src/base/SkAutoMalloc.h"
19 #include "src/base/SkRandom.h"
20 #include "tests/Test.h"
21 
22 #include <array>
23 #include <cstddef>
24 #include <cstdint>
25 
Union(SkRegion * rgn,const SkIRect & rect)26 static void Union(SkRegion* rgn, const SkIRect& rect) {
27     rgn->op(rect, SkRegion::kUnion_Op);
28 }
29 
30 #define TEST_NO_INTERSECT(rgn, rect)    REPORTER_ASSERT(reporter, !rgn.intersects(rect))
31 #define TEST_INTERSECT(rgn, rect)       REPORTER_ASSERT(reporter, rgn.intersects(rect))
32 #define TEST_NO_CONTAINS(rgn, rect)     REPORTER_ASSERT(reporter, !rgn.contains(rect))
33 
34 // inspired by http://code.google.com/p/skia/issues/detail?id=958
35 //
test_fromchrome(skiatest::Reporter * reporter)36 static void test_fromchrome(skiatest::Reporter* reporter) {
37     SkRegion r;
38     Union(&r, SkIRect::MakeXYWH(0, 0, 1, 1));
39     TEST_NO_INTERSECT(r, SkIRect::MakeXYWH(0, 0, 0, 0));
40     TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 0, 2, 2));
41     TEST_INTERSECT(r, SkIRect::MakeXYWH(-1, 0, 2, 2));
42     TEST_INTERSECT(r, SkIRect::MakeXYWH(-1, -1, 2, 2));
43     TEST_INTERSECT(r, SkIRect::MakeXYWH(0, -1, 2, 2));
44     TEST_INTERSECT(r, SkIRect::MakeXYWH(-1, -1, 3, 3));
45 
46     Union(&r, SkIRect::MakeXYWH(0, 0, 3, 3));
47     Union(&r, SkIRect::MakeXYWH(10, 0, 3, 3));
48     Union(&r, SkIRect::MakeXYWH(0, 10, 13, 3));
49     TEST_INTERSECT(r, SkIRect::MakeXYWH(-1, -1, 2, 2));
50     TEST_INTERSECT(r, SkIRect::MakeXYWH(2, -1, 2, 2));
51     TEST_INTERSECT(r, SkIRect::MakeXYWH(2, 2, 2, 2));
52     TEST_INTERSECT(r, SkIRect::MakeXYWH(-1, 2, 2, 2));
53 
54     TEST_INTERSECT(r, SkIRect::MakeXYWH(9, -1, 2, 2));
55     TEST_INTERSECT(r, SkIRect::MakeXYWH(12, -1, 2, 2));
56     TEST_INTERSECT(r, SkIRect::MakeXYWH(12, 2, 2, 2));
57     TEST_INTERSECT(r, SkIRect::MakeXYWH(9, 2, 2, 2));
58 
59     TEST_INTERSECT(r, SkIRect::MakeXYWH(0, -1, 13, 5));
60     TEST_INTERSECT(r, SkIRect::MakeXYWH(1, -1, 11, 5));
61     TEST_INTERSECT(r, SkIRect::MakeXYWH(2, -1, 9, 5));
62     TEST_INTERSECT(r, SkIRect::MakeXYWH(2, -1, 8, 5));
63     TEST_INTERSECT(r, SkIRect::MakeXYWH(3, -1, 8, 5));
64 
65     TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 1, 13, 1));
66     TEST_INTERSECT(r, SkIRect::MakeXYWH(1, 1, 11, 1));
67     TEST_INTERSECT(r, SkIRect::MakeXYWH(2, 1, 9, 1));
68     TEST_INTERSECT(r, SkIRect::MakeXYWH(2, 1, 8, 1));
69     TEST_INTERSECT(r, SkIRect::MakeXYWH(3, 1, 8, 1));
70 
71     TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 0, 13, 13));
72     TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 1, 13, 11));
73     TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 2, 13, 9));
74     TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 2, 13, 8));
75 
76 
77     // These test SkRegion::contains(Rect) and SkRegion::contains(Region)
78 
79     SkRegion container;
80     Union(&container, SkIRect::MakeXYWH(0, 0, 40, 20));
81     Union(&container, SkIRect::MakeXYWH(30, 20, 10, 20));
82     TEST_NO_CONTAINS(container, SkIRect::MakeXYWH(0, 0, 10, 39));
83     TEST_NO_CONTAINS(container, SkIRect::MakeXYWH(29, 0, 10, 39));
84 
85     {
86         SkRegion rgn;
87         Union(&rgn, SkIRect::MakeXYWH(0, 0, 10, 10));
88         Union(&rgn, SkIRect::MakeLTRB(5, 10, 20, 20));
89         TEST_INTERSECT(rgn, SkIRect::MakeXYWH(15, 0, 5, 11));
90     }
91 }
92 
test_empties(skiatest::Reporter * reporter)93 static void test_empties(skiatest::Reporter* reporter) {
94     SkRegion valid(SkIRect::MakeWH(10, 10));
95     SkRegion empty, empty2;
96 
97     REPORTER_ASSERT(reporter, empty.isEmpty());
98     REPORTER_ASSERT(reporter, !valid.isEmpty());
99 
100     // test intersects
101     REPORTER_ASSERT(reporter, !empty.intersects(empty2));
102     REPORTER_ASSERT(reporter, !valid.intersects(empty));
103 
104     // test contains
105     REPORTER_ASSERT(reporter, !empty.contains(empty2));
106     REPORTER_ASSERT(reporter, !valid.contains(empty));
107     REPORTER_ASSERT(reporter, !empty.contains(valid));
108 
109     SkPath emptyPath;
110     emptyPath.moveTo(1, 5);
111     emptyPath.close();
112     SkRegion openClip;
113     openClip.setRect({-16000, -16000, 16000, 16000});
114     empty.setPath(emptyPath, openClip);  // should not assert
115 }
116 
117 enum {
118     W = 256,
119     H = 256
120 };
121 
randRect(SkRandom & rand)122 static SkIRect randRect(SkRandom& rand) {
123     int x = rand.nextU() % W;
124     int y = rand.nextU() % H;
125     int w = rand.nextU() % W;
126     int h = rand.nextU() % H;
127     return SkIRect::MakeXYWH(x, y, w >> 1, h >> 1);
128 }
129 
randRgn(SkRandom & rand,SkRegion * rgn,int n)130 static void randRgn(SkRandom& rand, SkRegion* rgn, int n) {
131     rgn->setEmpty();
132     for (int i = 0; i < n; ++i) {
133         rgn->op(randRect(rand), SkRegion::kUnion_Op);
134     }
135 }
136 
slow_contains(const SkRegion & outer,const SkRegion & inner)137 static bool slow_contains(const SkRegion& outer, const SkRegion& inner) {
138     SkRegion tmp;
139     tmp.op(outer, inner, SkRegion::kUnion_Op);
140     return outer == tmp;
141 }
142 
slow_contains(const SkRegion & outer,const SkIRect & r)143 static bool slow_contains(const SkRegion& outer, const SkIRect& r) {
144     SkRegion tmp;
145     tmp.op(outer, SkRegion(r), SkRegion::kUnion_Op);
146     return outer == tmp;
147 }
148 
slow_intersects(const SkRegion & outer,const SkRegion & inner)149 static bool slow_intersects(const SkRegion& outer, const SkRegion& inner) {
150     SkRegion tmp;
151     return tmp.op(outer, inner, SkRegion::kIntersect_Op);
152 }
153 
test_contains_iter(skiatest::Reporter * reporter,const SkRegion & rgn)154 static void test_contains_iter(skiatest::Reporter* reporter, const SkRegion& rgn) {
155     SkRegion::Iterator iter(rgn);
156     while (!iter.done()) {
157         SkIRect r = iter.rect();
158         REPORTER_ASSERT(reporter, rgn.contains(r));
159         r.inset(-1, -1);
160         REPORTER_ASSERT(reporter, !rgn.contains(r));
161         iter.next();
162     }
163 }
164 
contains_proc(skiatest::Reporter * reporter,const SkRegion & a,const SkRegion & b)165 static void contains_proc(skiatest::Reporter* reporter,
166                           const SkRegion& a, const SkRegion& b) {
167     // test rgn
168     bool c0 = a.contains(b);
169     bool c1 = slow_contains(a, b);
170     REPORTER_ASSERT(reporter, c0 == c1);
171 
172     // test rect
173     SkIRect r = a.getBounds();
174     r.inset(r.width()/4, r.height()/4);
175     c0 = a.contains(r);
176     c1 = slow_contains(a, r);
177     REPORTER_ASSERT(reporter, c0 == c1);
178 
179     test_contains_iter(reporter, a);
180     test_contains_iter(reporter, b);
181 }
182 
test_intersects_iter(skiatest::Reporter * reporter,const SkRegion & rgn)183 static void test_intersects_iter(skiatest::Reporter* reporter, const SkRegion& rgn) {
184     SkRegion::Iterator iter(rgn);
185     while (!iter.done()) {
186         SkIRect r = iter.rect();
187         REPORTER_ASSERT(reporter, rgn.intersects(r));
188         r.inset(-1, -1);
189         REPORTER_ASSERT(reporter, rgn.intersects(r));
190         iter.next();
191     }
192 }
193 
intersects_proc(skiatest::Reporter * reporter,const SkRegion & a,const SkRegion & b)194 static void intersects_proc(skiatest::Reporter* reporter,
195                           const SkRegion& a, const SkRegion& b) {
196     bool c0 = a.intersects(b);
197     bool c1 = slow_intersects(a, b);
198     REPORTER_ASSERT(reporter, c0 == c1);
199 
200     test_intersects_iter(reporter, a);
201     test_intersects_iter(reporter, b);
202 }
203 
test_proc(skiatest::Reporter * reporter,void (* proc)(skiatest::Reporter *,const SkRegion & a,const SkRegion &))204 static void test_proc(skiatest::Reporter* reporter,
205                       void (*proc)(skiatest::Reporter*,
206                                    const SkRegion& a, const SkRegion&)) {
207     SkRandom rand;
208     for (int i = 0; i < 10000; ++i) {
209         SkRegion outer;
210         randRgn(rand, &outer, 8);
211         SkRegion inner;
212         randRgn(rand, &inner, 2);
213         proc(reporter, outer, inner);
214     }
215 }
216 
rand_rect(SkIRect * rect,SkRandom & rand)217 static void rand_rect(SkIRect* rect, SkRandom& rand) {
218     int bits = 6;
219     int shift = 32 - bits;
220     rect->setLTRB(rand.nextU() >> shift, rand.nextU() >> shift,
221                   rand.nextU() >> shift, rand.nextU() >> shift);
222     rect->sort();
223 }
224 
test_rects(const SkIRect rect[],int count)225 static bool test_rects(const SkIRect rect[], int count) {
226     SkRegion rgn0, rgn1;
227 
228     for (int i = 0; i < count; i++) {
229         rgn0.op(rect[i], SkRegion::kUnion_Op);
230     }
231     rgn1.setRects(rect, count);
232 
233     if (rgn0 != rgn1) {
234         SkDebugf("\n");
235         for (int i = 0; i < count; i++) {
236             SkDebugf(" { %d, %d, %d, %d },\n",
237                      rect[i].fLeft, rect[i].fTop,
238                      rect[i].fRight, rect[i].fBottom);
239         }
240         SkDebugf("\n");
241         return false;
242     }
243     return true;
244 }
245 
DEF_TEST(Region,reporter)246 DEF_TEST(Region, reporter) {
247     const SkIRect r2[] = {
248         { 0, 0, 1, 1 },
249         { 2, 2, 3, 3 },
250     };
251     REPORTER_ASSERT(reporter, test_rects(r2, std::size(r2)));
252 
253     const SkIRect rects[] = {
254         { 0, 0, 1, 2 },
255         { 2, 1, 3, 3 },
256         { 4, 0, 5, 1 },
257         { 6, 0, 7, 4 },
258     };
259     REPORTER_ASSERT(reporter, test_rects(rects, std::size(rects)));
260 
261     SkRandom rand;
262     for (int i = 0; i < 1000; i++) {
263         SkRegion rgn0, rgn1;
264 
265         const int N = 8;
266         SkIRect rect[N];
267         for (int j = 0; j < N; j++) {
268             rand_rect(&rect[j], rand);
269         }
270         REPORTER_ASSERT(reporter, test_rects(rect, N));
271     }
272 
273     test_proc(reporter, contains_proc);
274     test_proc(reporter, intersects_proc);
275     test_empties(reporter);
276     test_fromchrome(reporter);
277 }
278 
279 // Test that writeToMemory reports the same number of bytes whether there was a
280 // buffer to write to or not.
test_write(const SkRegion & region,skiatest::Reporter * r)281 static void test_write(const SkRegion& region, skiatest::Reporter* r) {
282     const size_t bytesNeeded = region.writeToMemory(nullptr);
283     SkAutoMalloc storage(bytesNeeded);
284     const size_t bytesWritten = region.writeToMemory(storage.get());
285     REPORTER_ASSERT(r, bytesWritten == bytesNeeded);
286 
287     // Also check that the bytes are meaningful.
288     SkRegion copy;
289     REPORTER_ASSERT(r, copy.readFromMemory(storage.get(), bytesNeeded));
290     REPORTER_ASSERT(r, region == copy);
291 }
292 
DEF_TEST(Region_writeToMemory,r)293 DEF_TEST(Region_writeToMemory, r) {
294     // Test an empty region.
295     SkRegion region;
296     REPORTER_ASSERT(r, region.isEmpty());
297     test_write(region, r);
298 
299     // Test a rectangular region
300     bool nonEmpty = region.setRect({0, 0, 50, 50});
301     REPORTER_ASSERT(r, nonEmpty);
302     REPORTER_ASSERT(r, region.isRect());
303     test_write(region, r);
304 
305     // Test a complex region
306     nonEmpty = region.op({50, 50, 100, 100}, SkRegion::kUnion_Op);
307     REPORTER_ASSERT(r, nonEmpty);
308     REPORTER_ASSERT(r, region.isComplex());
309     test_write(region, r);
310 
311     SkRegion complexRegion;
312     Union(&complexRegion, SkIRect::MakeXYWH(0, 0, 1, 1));
313     Union(&complexRegion, SkIRect::MakeXYWH(0, 0, 3, 3));
314     Union(&complexRegion, SkIRect::MakeXYWH(10, 0, 3, 3));
315     Union(&complexRegion, SkIRect::MakeXYWH(0, 10, 13, 3));
316     test_write(complexRegion, r);
317 
318     Union(&complexRegion, SkIRect::MakeXYWH(10, 20, 3, 3));
319     Union(&complexRegion, SkIRect::MakeXYWH(0,  20, 3, 3));
320     test_write(complexRegion, r);
321 }
322 
DEF_TEST(Region_readFromMemory_bad,r)323 DEF_TEST(Region_readFromMemory_bad, r) {
324     // These assume what our binary format is: conceivably we could change it
325     // and might need to remove or change some of these tests.
326     SkRegion region;
327 
328     {
329         // invalid boundary rectangle
330         int32_t data[5] = {0, 4, 4, 8, 2};
331         REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
332     }
333     // Region Layout, Serialized Format:
334     //    COUNT LEFT TOP RIGHT BOTTOM Y_SPAN_COUNT TOTAL_INTERVAL_COUNT
335     //    Top ( Bottom Span_Interval_Count ( Left Right )* Sentinel )+ Sentinel
336     {
337         // Example of valid data
338         int32_t data[] = {9, 0, 0, 10, 10, 1, 2, 0, 10, 2, 0, 4, 6, 10,
339                           2147483647, 2147483647};
340         REPORTER_ASSERT(r, 0 != region.readFromMemory(data, sizeof(data)));
341     }
342     {
343         // Example of valid data with 4 intervals
344         int32_t data[] = {19, 0, 0, 30, 30, 3, 4, 0, 10, 2, 0, 10, 20, 30,
345                           2147483647, 20, 0, 2147483647, 30, 2, 0, 10, 20, 30,
346                           2147483647, 2147483647};
347         REPORTER_ASSERT(r, 0 != region.readFromMemory(data, sizeof(data)));
348     }
349     {
350         // Short count
351         int32_t data[] = {8, 0, 0, 10, 10, 1, 2, 0, 10, 2, 0, 4, 6, 10,
352                           2147483647, 2147483647};
353         REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
354     }
355     {
356         // bounds don't match
357         int32_t data[] = {9, 0, 0, 10, 11, 1, 2, 0, 10, 2, 0, 4, 6, 10,
358                           2147483647, 2147483647};
359         REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
360     }
361     {
362         //  bad yspan count
363         int32_t data[] = {9, 0, 0, 10, 10, 2, 2, 0, 10, 2, 0, 4, 6, 10,
364                           2147483647, 2147483647};
365         REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
366     }
367     {
368         // bad int count
369         int32_t data[] = {9, 0, 0, 10, 10, 1, 3, 0, 10, 2, 0, 4, 6, 10,
370                           2147483647, 2147483647};
371         REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
372     }
373     {
374         // bad final sentinal
375         int32_t data[] = {9, 0, 0, 10, 10, 1, 2, 0, 10, 2, 0, 4, 6, 10,
376                           2147483647, -1};
377         REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
378     }
379     {
380         // bad row sentinal
381         int32_t data[] = {9, 0, 0, 10, 10, 1, 2, 0, 10, 2, 0, 4, 6, 10,
382                           -1, 2147483647};
383         REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
384     }
385     {
386         // starts with empty yspan
387         int32_t data[] = {12, 0, 0, 10, 10, 2, 2, -5, 0, 0, 2147483647, 10,
388                           2, 0, 4, 6, 10, 2147483647, 2147483647};
389         REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
390     }
391     {
392         // ends with empty yspan
393         int32_t data[] = {12, 0, 0, 10, 10, 2, 2, 0, 10, 2, 0, 4, 6, 10,
394                           2147483647, 15, 0, 2147483647, 2147483647};
395         REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
396     }
397     {
398         // y intervals out of order
399         int32_t data[] = {19, 0, -20, 30, 10, 3, 4, 0, 10, 2, 0, 10, 20, 30,
400                           2147483647, -20, 0, 2147483647, -10, 2, 0, 10, 20, 30,
401                           2147483647, 2147483647};
402         REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
403     }
404     {
405         // x intervals out of order
406         int32_t data[] = {9, 0, 0, 10, 10, 1, 2, 0, 10, 2, 6, 10, 0, 4,
407                           2147483647, 2147483647};
408         REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
409     }
410 }
411 
DEF_TEST(region_toobig,reporter)412 DEF_TEST(region_toobig, reporter) {
413     const int big = 1 << 30;
414     const SkIRect neg = SkIRect::MakeXYWH(-big, -big, 10, 10);
415     const SkIRect pos = SkIRect::MakeXYWH( big,  big, 10, 10);
416 
417     REPORTER_ASSERT(reporter, !neg.isEmpty());
418     REPORTER_ASSERT(reporter, !pos.isEmpty());
419 
420     SkRegion negR(neg);
421     SkRegion posR(pos);
422 
423     REPORTER_ASSERT(reporter, !negR.isEmpty());
424     REPORTER_ASSERT(reporter, !posR.isEmpty());
425 
426     SkRegion rgn;
427     rgn.op(negR, posR, SkRegion::kUnion_Op);
428 
429     // If we union those to rectangles, the resulting coordinates span more than int32_t, so
430     // we must mark the region as empty.
431     REPORTER_ASSERT(reporter, rgn.isEmpty());
432 }
433 
DEF_TEST(region_inverse_union_skbug_7491,reporter)434 DEF_TEST(region_inverse_union_skbug_7491, reporter) {
435     SkPath path;
436     path.setFillType(SkPathFillType::kInverseWinding);
437     path.moveTo(10, 20); path.lineTo(10, 30); path.lineTo(10.1f, 10); path.close();
438 
439     SkRegion clip;
440     clip.op(SkIRect::MakeLTRB(10, 10, 15, 20), SkRegion::kUnion_Op);
441     clip.op(SkIRect::MakeLTRB(20, 10, 25, 20), SkRegion::kUnion_Op);
442 
443     SkRegion rgn;
444     rgn.setPath(path, clip);
445 
446     REPORTER_ASSERT(reporter, clip == rgn);
447 }
448 
DEF_TEST(giant_path_region,reporter)449 DEF_TEST(giant_path_region, reporter) {
450     const SkScalar big = 32767;
451     SkPath path;
452     path.moveTo(-big, 0);
453     path.quadTo(big, 0, big, big);
454     SkIRect ir = path.getBounds().round();
455     SkRegion rgn;
456     rgn.setPath(path, SkRegion(ir));
457 }
458 
DEF_TEST(rrect_region_crbug_850350,reporter)459 DEF_TEST(rrect_region_crbug_850350, reporter) {
460     SkMatrix m;
461     m.reset();
462     m[1] = 0.753662348f;
463     m[3] = 1.40079998E+20f;
464 
465     const SkPoint corners[] = {
466         { 2.65876e-19f, 0.0194088f },
467         { 4896, 0.00114702f },
468         { 0, 0 },
469         { 0.00114702f, 0.00495333f },
470     };
471     SkRRect rrect;
472     rrect.setRectRadii({-8.72387e-31f, 1.29996e-38f, 4896, 1.125f}, corners);
473 
474     SkPath path;
475     path.addRRect(rrect);
476     path.transform(m);
477 
478     SkRegion rgn;
479     rgn.setPath(path, SkRegion{SkIRect{0, 0, 24, 24}});
480 }
481 
DEF_TEST(region_bug_chromium_873051,reporter)482 DEF_TEST(region_bug_chromium_873051, reporter) {
483     SkRegion region;
484     REPORTER_ASSERT(reporter,  region.setRect({0, 0, 0x7FFFFFFE, 0x7FFFFFFE}));
485     REPORTER_ASSERT(reporter, !region.setRect({0, 0, 0x7FFFFFFE, 0x7FFFFFFF}));
486     REPORTER_ASSERT(reporter, !region.setRect({0, 0, 0x7FFFFFFF, 0x7FFFFFFE}));
487     REPORTER_ASSERT(reporter, !region.setRect({0, 0, 0x7FFFFFFF, 0x7FFFFFFF}));
488 }
489 
DEF_TEST(region_empty_iter,reporter)490 DEF_TEST(region_empty_iter, reporter) {
491     SkRegion::Iterator emptyIter;
492     REPORTER_ASSERT(reporter, !emptyIter.rewind());
493     REPORTER_ASSERT(reporter, emptyIter.done());
494     auto eRect = emptyIter.rect();
495     REPORTER_ASSERT(reporter, eRect.isEmpty());
496     REPORTER_ASSERT(reporter, SkIRect::MakeEmpty() == eRect);
497     REPORTER_ASSERT(reporter, !emptyIter.rgn());
498 
499     SkRegion region;
500     SkRegion::Iterator resetIter;
501     resetIter.reset(region);
502     REPORTER_ASSERT(reporter, resetIter.rewind());
503     REPORTER_ASSERT(reporter, resetIter.done());
504     auto rRect = resetIter.rect();
505     REPORTER_ASSERT(reporter, rRect.isEmpty());
506     REPORTER_ASSERT(reporter, SkIRect::MakeEmpty() == rRect);
507     REPORTER_ASSERT(reporter, resetIter.rgn());
508     REPORTER_ASSERT(reporter, resetIter.rgn()->isEmpty());
509 
510     SkRegion::Iterator iter(region);
511     REPORTER_ASSERT(reporter, iter.done());
512     auto iRect = iter.rect();
513     REPORTER_ASSERT(reporter, iRect.isEmpty());
514     REPORTER_ASSERT(reporter, SkIRect::MakeEmpty() == iRect);
515     REPORTER_ASSERT(reporter, iter.rgn());
516     REPORTER_ASSERT(reporter, iter.rgn()->isEmpty());
517 
518     SkRegion::Cliperator clipIter(region, {0, 0, 100, 100});
519     REPORTER_ASSERT(reporter, clipIter.done());
520     auto cRect = clipIter.rect();
521     REPORTER_ASSERT(reporter, cRect.isEmpty());
522     REPORTER_ASSERT(reporter, SkIRect::MakeEmpty() == cRect);
523 
524     SkRegion::Spanerator spanIter(region, 0, 0, 100);
525     int left = 0, right = 0;
526     REPORTER_ASSERT(reporter, !spanIter.next(&left, &right));
527     REPORTER_ASSERT(reporter, !left);
528     REPORTER_ASSERT(reporter, !right);
529 }
530