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