blob: f3d1e0b5a16f87d4a8859eeda2d0f9c1ac7bd701 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
reed@android.com097a3512010-07-13 18:35:14 +00008#include "Test.h"
9#include "SkRegion.h"
10#include "SkRandom.h"
11
mike@reedtribe.org5a7ae4f2012-11-07 01:57:32 +000012static void Union(SkRegion* rgn, const SkIRect& rect) {
13 rgn->op(rect, SkRegion::kUnion_Op);
14}
15
16#define TEST_NO_INTERSECT(rgn, rect) REPORTER_ASSERT(reporter, !rgn.intersects(rect))
17#define TEST_INTERSECT(rgn, rect) REPORTER_ASSERT(reporter, rgn.intersects(rect))
18#define TEST_NO_CONTAINS(rgn, rect) REPORTER_ASSERT(reporter, rgn.contains(rect))
19
20// inspired by http://code.google.com/p/skia/issues/detail?id=958
21//
22static void test_fromchrome(skiatest::Reporter* reporter) {
23 SkRegion r;
24 Union(&r, SkIRect::MakeXYWH(0, 0, 1, 1));
25 TEST_NO_INTERSECT(r, SkIRect::MakeXYWH(0, 0, 0, 0));
26 TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 0, 2, 2));
27 TEST_INTERSECT(r, SkIRect::MakeXYWH(-1, 0, 2, 2));
28 TEST_INTERSECT(r, SkIRect::MakeXYWH(-1, -1, 2, 2));
29 TEST_INTERSECT(r, SkIRect::MakeXYWH(0, -1, 2, 2));
30 TEST_INTERSECT(r, SkIRect::MakeXYWH(-1, -1, 3, 3));
31
32 Union(&r, SkIRect::MakeXYWH(0, 0, 3, 3));
33 Union(&r, SkIRect::MakeXYWH(10, 0, 3, 3));
34 Union(&r, SkIRect::MakeXYWH(0, 10, 13, 3));
35 TEST_INTERSECT(r, SkIRect::MakeXYWH(-1, -1, 2, 2));
36 TEST_INTERSECT(r, SkIRect::MakeXYWH(2, -1, 2, 2));
37 TEST_INTERSECT(r, SkIRect::MakeXYWH(2, 2, 2, 2));
38 TEST_INTERSECT(r, SkIRect::MakeXYWH(-1, 2, 2, 2));
39
40 TEST_INTERSECT(r, SkIRect::MakeXYWH(9, -1, 2, 2));
41 TEST_INTERSECT(r, SkIRect::MakeXYWH(12, -1, 2, 2));
42 TEST_INTERSECT(r, SkIRect::MakeXYWH(12, 2, 2, 2));
43 TEST_INTERSECT(r, SkIRect::MakeXYWH(9, 2, 2, 2));
44
45 TEST_INTERSECT(r, SkIRect::MakeXYWH(0, -1, 13, 5));
46 TEST_INTERSECT(r, SkIRect::MakeXYWH(1, -1, 11, 5));
47 TEST_INTERSECT(r, SkIRect::MakeXYWH(2, -1, 9, 5));
48 TEST_INTERSECT(r, SkIRect::MakeXYWH(2, -1, 8, 5));
49 TEST_INTERSECT(r, SkIRect::MakeXYWH(3, -1, 8, 5));
50
51 TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 1, 13, 1));
52 TEST_INTERSECT(r, SkIRect::MakeXYWH(1, 1, 11, 1));
53 TEST_INTERSECT(r, SkIRect::MakeXYWH(2, 1, 9, 1));
54 TEST_INTERSECT(r, SkIRect::MakeXYWH(2, 1, 8, 1));
55 TEST_INTERSECT(r, SkIRect::MakeXYWH(3, 1, 8, 1));
56
57 TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 0, 13, 13));
58 TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 1, 13, 11));
59 TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 2, 13, 9));
60 TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 2, 13, 8));
61
62
63 // These test SkRegion::contains(Rect) and SkRegion::contains(Region)
64
65 SkRegion container;
66 Union(&container, SkIRect::MakeXYWH(0, 0, 40, 20));
67 Union(&container, SkIRect::MakeXYWH(30, 20, 10, 20));
68 TEST_NO_CONTAINS(container, SkIRect::MakeXYWH(0, 0, 10, 39));
69 TEST_NO_CONTAINS(container, SkIRect::MakeXYWH(29, 0, 10, 39));
70}
71
reed@google.com8a0d8ff2012-04-30 16:28:04 +000072static void test_empties(skiatest::Reporter* reporter) {
73 SkRegion valid(SkIRect::MakeWH(10, 10));
74 SkRegion empty, empty2;
75
76 REPORTER_ASSERT(reporter, empty.isEmpty());
77 REPORTER_ASSERT(reporter, !valid.isEmpty());
78
79 // test intersects
80 REPORTER_ASSERT(reporter, !empty.intersects(empty2));
81 REPORTER_ASSERT(reporter, !valid.intersects(empty));
82
83 // test contains
84 REPORTER_ASSERT(reporter, !empty.contains(empty2));
85 REPORTER_ASSERT(reporter, !valid.contains(empty));
86 REPORTER_ASSERT(reporter, !empty.contains(valid));
87}
88
mike@reedtribe.org67c31842012-04-28 20:09:19 +000089enum {
90 W = 256,
91 H = 256
92};
93
94static SkIRect randRect(SkRandom& rand) {
95 int x = rand.nextU() % W;
96 int y = rand.nextU() % H;
97 int w = rand.nextU() % W;
98 int h = rand.nextU() % H;
99 return SkIRect::MakeXYWH(x, y, w >> 1, h >> 1);
100}
101
102static void randRgn(SkRandom& rand, SkRegion* rgn, int n) {
103 rgn->setEmpty();
104 for (int i = 0; i < n; ++i) {
105 rgn->op(randRect(rand), SkRegion::kUnion_Op);
106 }
107}
108
109static bool slow_contains(const SkRegion& outer, const SkRegion& inner) {
110 SkRegion tmp;
111 tmp.op(outer, inner, SkRegion::kUnion_Op);
112 return outer == tmp;
113}
114
reed@google.com7ab71ba2012-05-02 16:09:21 +0000115static bool slow_contains(const SkRegion& outer, const SkIRect& r) {
116 SkRegion tmp;
117 tmp.op(outer, SkRegion(r), SkRegion::kUnion_Op);
118 return outer == tmp;
119}
120
mike@reedtribe.org67c31842012-04-28 20:09:19 +0000121static bool slow_intersects(const SkRegion& outer, const SkRegion& inner) {
122 SkRegion tmp;
123 return tmp.op(outer, inner, SkRegion::kIntersect_Op);
124}
125
reed@google.com7ab71ba2012-05-02 16:09:21 +0000126static void test_contains_iter(skiatest::Reporter* reporter, const SkRegion& rgn) {
127 SkRegion::Iterator iter(rgn);
128 while (!iter.done()) {
129 SkIRect r = iter.rect();
130 REPORTER_ASSERT(reporter, rgn.contains(r));
131 r.inset(-1, -1);
132 REPORTER_ASSERT(reporter, !rgn.contains(r));
133 iter.next();
134 }
135}
136
mike@reedtribe.org67c31842012-04-28 20:09:19 +0000137static void contains_proc(skiatest::Reporter* reporter,
138 const SkRegion& a, const SkRegion& b) {
reed@google.com7ab71ba2012-05-02 16:09:21 +0000139 // test rgn
mike@reedtribe.org67c31842012-04-28 20:09:19 +0000140 bool c0 = a.contains(b);
141 bool c1 = slow_contains(a, b);
142 REPORTER_ASSERT(reporter, c0 == c1);
reed@google.com7ab71ba2012-05-02 16:09:21 +0000143
144 // test rect
145 SkIRect r = a.getBounds();
146 r.inset(r.width()/4, r.height()/4);
147 c0 = a.contains(r);
148 c1 = slow_contains(a, r);
149 REPORTER_ASSERT(reporter, c0 == c1);
150
151 test_contains_iter(reporter, a);
152 test_contains_iter(reporter, b);
mike@reedtribe.org67c31842012-04-28 20:09:19 +0000153}
154
reed@google.com684119d2012-05-02 16:52:12 +0000155static void test_intersects_iter(skiatest::Reporter* reporter, const SkRegion& rgn) {
156 SkRegion::Iterator iter(rgn);
157 while (!iter.done()) {
158 SkIRect r = iter.rect();
159 REPORTER_ASSERT(reporter, rgn.intersects(r));
160 r.inset(-1, -1);
161 REPORTER_ASSERT(reporter, rgn.intersects(r));
162 iter.next();
163 }
164}
165
mike@reedtribe.org67c31842012-04-28 20:09:19 +0000166static void intersects_proc(skiatest::Reporter* reporter,
167 const SkRegion& a, const SkRegion& b) {
168 bool c0 = a.intersects(b);
169 bool c1 = slow_intersects(a, b);
170 REPORTER_ASSERT(reporter, c0 == c1);
reed@google.com684119d2012-05-02 16:52:12 +0000171
172 test_intersects_iter(reporter, a);
173 test_intersects_iter(reporter, b);
mike@reedtribe.org67c31842012-04-28 20:09:19 +0000174}
175
176static void test_proc(skiatest::Reporter* reporter,
177 void (*proc)(skiatest::Reporter*,
178 const SkRegion& a, const SkRegion&)) {
179 SkRandom rand;
180 for (int i = 0; i < 10000; ++i) {
181 SkRegion outer;
182 randRgn(rand, &outer, 8);
183 SkRegion inner;
184 randRgn(rand, &inner, 2);
185 proc(reporter, outer, inner);
186 }
187}
188
reed@android.com097a3512010-07-13 18:35:14 +0000189static void rand_rect(SkIRect* rect, SkRandom& rand) {
190 int bits = 6;
191 int shift = 32 - bits;
192 rect->set(rand.nextU() >> shift, rand.nextU() >> shift,
193 rand.nextU() >> shift, rand.nextU() >> shift);
194 rect->sort();
195}
196
197static bool test_rects(const SkIRect rect[], int count) {
198 SkRegion rgn0, rgn1;
199
200 for (int i = 0; i < count; i++) {
201 rgn0.op(rect[i], SkRegion::kUnion_Op);
202 }
203 rgn1.setRects(rect, count);
204
205 if (rgn0 != rgn1) {
206 SkDebugf("\n");
207 for (int i = 0; i < count; i++) {
208 SkDebugf(" { %d, %d, %d, %d },\n",
209 rect[i].fLeft, rect[i].fTop,
210 rect[i].fRight, rect[i].fBottom);
211 }
212 SkDebugf("\n");
213 return false;
214 }
215 return true;
216}
217
218static void TestRegion(skiatest::Reporter* reporter) {
219 const SkIRect r2[] = {
220 { 0, 0, 1, 1 },
221 { 2, 2, 3, 3 },
222 };
223 REPORTER_ASSERT(reporter, test_rects(r2, SK_ARRAY_COUNT(r2)));
rmistry@google.comd6176b02012-08-23 18:14:13 +0000224
reed@android.com097a3512010-07-13 18:35:14 +0000225 const SkIRect rects[] = {
226 { 0, 0, 1, 2 },
227 { 2, 1, 3, 3 },
228 { 4, 0, 5, 1 },
229 { 6, 0, 7, 4 },
230 };
231 REPORTER_ASSERT(reporter, test_rects(rects, SK_ARRAY_COUNT(rects)));
232
233 SkRandom rand;
234 for (int i = 0; i < 1000; i++) {
235 SkRegion rgn0, rgn1;
236
237 const int N = 8;
238 SkIRect rect[N];
239 for (int j = 0; j < N; j++) {
240 rand_rect(&rect[j], rand);
241 }
242 REPORTER_ASSERT(reporter, test_rects(rect, N));
243 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000244
mike@reedtribe.org67c31842012-04-28 20:09:19 +0000245 test_proc(reporter, contains_proc);
246 test_proc(reporter, intersects_proc);
reed@google.com8a0d8ff2012-04-30 16:28:04 +0000247 test_empties(reporter);
mike@reedtribe.org5a7ae4f2012-11-07 01:57:32 +0000248 test_fromchrome(reporter);
reed@android.com097a3512010-07-13 18:35:14 +0000249}
250
251#include "TestClassDef.h"
252DEFINE_TESTCLASS("Region", RegionTestClass, TestRegion)