blob: d10a199211b24c20b9b93689723f901e8b949e0c [file] [log] [blame]
reed@google.com209c4152011-10-26 15:03:48 +00001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkBitmap.h"
9#include "include/core/SkCanvas.h"
10#include "include/core/SkColor.h"
11#include "include/core/SkImageInfo.h"
12#include "include/core/SkMatrix.h"
13#include "include/core/SkPath.h"
14#include "include/core/SkRRect.h"
15#include "include/core/SkRect.h"
16#include "include/core/SkRegion.h"
17#include "include/core/SkScalar.h"
18#include "include/core/SkTypes.h"
19#include "include/private/SkMalloc.h"
20#include "include/utils/SkRandom.h"
21#include "src/core/SkAAClip.h"
22#include "src/core/SkMask.h"
23#include "src/core/SkRasterClip.h"
24#include "tests/Test.h"
reed@google.comd8676d22011-10-26 18:01:25 +000025
Ben Wagner1ebeefe2018-03-02 16:59:53 -050026#include <string.h>
27
mike@reedtribe.org95b85bd2011-11-23 03:12:58 +000028static bool operator==(const SkMask& a, const SkMask& b) {
29 if (a.fFormat != b.fFormat || a.fBounds != b.fBounds) {
30 return false;
31 }
32 if (!a.fImage && !b.fImage) {
33 return true;
34 }
35 if (!a.fImage || !b.fImage) {
36 return false;
37 }
38
39 size_t wbytes = a.fBounds.width();
40 switch (a.fFormat) {
41 case SkMask::kBW_Format:
42 wbytes = (wbytes + 7) >> 3;
43 break;
44 case SkMask::kA8_Format:
45 case SkMask::k3D_Format:
46 break;
47 case SkMask::kLCD16_Format:
48 wbytes <<= 1;
49 break;
mike@reedtribe.org95b85bd2011-11-23 03:12:58 +000050 case SkMask::kARGB32_Format:
51 wbytes <<= 2;
52 break;
53 default:
mtklein@google.com330313a2013-08-22 15:37:26 +000054 SkDEBUGFAIL("unknown mask format");
mike@reedtribe.org95b85bd2011-11-23 03:12:58 +000055 return false;
56 }
57
58 const int h = a.fBounds.height();
59 const char* aptr = (const char*)a.fImage;
60 const char* bptr = (const char*)b.fImage;
61 for (int y = 0; y < h; ++y) {
John Stilesc1c3c6d2020-08-15 23:22:53 -040062 if (0 != memcmp(aptr, bptr, wbytes)) {
mike@reedtribe.org95b85bd2011-11-23 03:12:58 +000063 return false;
64 }
65 aptr += wbytes;
66 bptr += wbytes;
67 }
68 return true;
69}
70
71static void copyToMask(const SkRegion& rgn, SkMask* mask) {
reed@google.coma052aca2011-11-23 19:43:46 +000072 mask->fFormat = SkMask::kA8_Format;
73
mike@reedtribe.org95b85bd2011-11-23 03:12:58 +000074 if (rgn.isEmpty()) {
mike@reedtribe.org95b85bd2011-11-23 03:12:58 +000075 mask->fBounds.setEmpty();
76 mask->fRowBytes = 0;
halcanary96fcdcc2015-08-27 07:41:13 -070077 mask->fImage = nullptr;
mike@reedtribe.org95b85bd2011-11-23 03:12:58 +000078 return;
79 }
80
81 mask->fBounds = rgn.getBounds();
82 mask->fRowBytes = mask->fBounds.width();
mike@reedtribe.org95b85bd2011-11-23 03:12:58 +000083 mask->fImage = SkMask::AllocImage(mask->computeImageSize());
84 sk_bzero(mask->fImage, mask->computeImageSize());
85
commit-bot@chromium.orgfa9e5fa2014-02-13 22:00:04 +000086 SkImageInfo info = SkImageInfo::Make(mask->fBounds.width(),
87 mask->fBounds.height(),
88 kAlpha_8_SkColorType,
89 kPremul_SkAlphaType);
mike@reedtribe.org95b85bd2011-11-23 03:12:58 +000090 SkBitmap bitmap;
commit-bot@chromium.org00f8d6c2014-05-29 15:57:20 +000091 bitmap.installPixels(info, mask->fImage, mask->fRowBytes);
mike@reedtribe.org95b85bd2011-11-23 03:12:58 +000092
93 // canvas expects its coordinate system to always be 0,0 in the top/left
94 // so we translate the rgn to match that before drawing into the mask.
95 //
96 SkRegion tmpRgn(rgn);
97 tmpRgn.translate(-rgn.getBounds().fLeft, -rgn.getBounds().fTop);
98
99 SkCanvas canvas(bitmap);
100 canvas.clipRegion(tmpRgn);
101 canvas.drawColor(SK_ColorBLACK);
102}
103
Michael Ludwig181bb972021-09-03 12:18:23 -0400104static void copyToMask(const SkRasterClip& rc, SkMask* mask) {
105 if (rc.isBW()) {
106 copyToMask(rc.bwRgn(), mask);
107 } else {
108 rc.aaRgn().copyToMask(mask);
109 }
110}
111
112static bool operator==(const SkRasterClip& a, const SkRasterClip& b) {
113 if (a.isEmpty() && b.isEmpty()) {
114 return true;
115 } else if (a.isEmpty() != b.isEmpty() || a.isBW() != b.isBW() || a.isRect() != b.isRect()) {
116 return false;
117 }
118
119 SkMask mask0, mask1;
120 copyToMask(a, &mask0);
121 copyToMask(b, &mask1);
122 return mask0 == mask1;
123}
124
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000125static SkIRect rand_rect(SkRandom& rand, int n) {
mike@reedtribe.org95b85bd2011-11-23 03:12:58 +0000126 int x = rand.nextS() % n;
127 int y = rand.nextS() % n;
128 int w = rand.nextU() % n;
129 int h = rand.nextU() % n;
130 return SkIRect::MakeXYWH(x, y, w, h);
131}
132
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000133static void make_rand_rgn(SkRegion* rgn, SkRandom& rand) {
mike@reedtribe.org95b85bd2011-11-23 03:12:58 +0000134 int count = rand.nextU() % 20;
135 for (int i = 0; i < count; ++i) {
136 rgn->op(rand_rect(rand, 100), SkRegion::kXOR_Op);
137 }
138}
139
reed@google.coma052aca2011-11-23 19:43:46 +0000140static bool operator==(const SkRegion& rgn, const SkAAClip& aaclip) {
141 SkMask mask0, mask1;
142
143 copyToMask(rgn, &mask0);
144 aaclip.copyToMask(&mask1);
145 bool eq = (mask0 == mask1);
146
147 SkMask::FreeImage(mask0.fImage);
148 SkMask::FreeImage(mask1.fImage);
149 return eq;
150}
151
152static bool equalsAAClip(const SkRegion& rgn) {
153 SkAAClip aaclip;
154 aaclip.setRegion(rgn);
155 return rgn == aaclip;
156}
157
158static void setRgnToPath(SkRegion* rgn, const SkPath& path) {
159 SkIRect ir;
160 path.getBounds().round(&ir);
161 rgn->setPath(path, SkRegion(ir));
162}
163
mike@reedtribe.org95b85bd2011-11-23 03:12:58 +0000164// aaclip.setRegion should create idential masks to the region
165static void test_rgn(skiatest::Reporter* reporter) {
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000166 SkRandom rand;
mike@reedtribe.org95b85bd2011-11-23 03:12:58 +0000167 for (int i = 0; i < 1000; i++) {
168 SkRegion rgn;
169 make_rand_rgn(&rgn, rand);
reed@google.coma052aca2011-11-23 19:43:46 +0000170 REPORTER_ASSERT(reporter, equalsAAClip(rgn));
171 }
172
173 {
174 SkRegion rgn;
175 SkPath path;
176 path.addCircle(0, 0, SkIntToScalar(30));
177 setRgnToPath(&rgn, path);
178 REPORTER_ASSERT(reporter, equalsAAClip(rgn));
179
180 path.reset();
181 path.moveTo(0, 0);
182 path.lineTo(SkIntToScalar(100), 0);
183 path.lineTo(SkIntToScalar(100 - 20), SkIntToScalar(20));
184 path.lineTo(SkIntToScalar(20), SkIntToScalar(20));
185 setRgnToPath(&rgn, path);
186 REPORTER_ASSERT(reporter, equalsAAClip(rgn));
mike@reedtribe.org95b85bd2011-11-23 03:12:58 +0000187 }
188}
189
reed@google.com12e15252011-10-26 15:19:36 +0000190static void imoveTo(SkPath& path, int x, int y) {
191 path.moveTo(SkIntToScalar(x), SkIntToScalar(y));
192}
193
194static void icubicTo(SkPath& path, int x0, int y0, int x1, int y1, int x2, int y2) {
195 path.cubicTo(SkIntToScalar(x0), SkIntToScalar(y0),
196 SkIntToScalar(x1), SkIntToScalar(y1),
197 SkIntToScalar(x2), SkIntToScalar(y2));
198}
199
reed@google.comd8676d22011-10-26 18:01:25 +0000200static void test_path_bounds(skiatest::Reporter* reporter) {
reed@google.com209c4152011-10-26 15:03:48 +0000201 SkPath path;
202 SkAAClip clip;
203 const int height = 40;
204 const SkScalar sheight = SkIntToScalar(height);
205
206 path.addOval(SkRect::MakeWH(sheight, sheight));
207 REPORTER_ASSERT(reporter, sheight == path.getBounds().height());
Michael Ludwig8c9c1852021-09-14 13:16:42 -0400208 clip.setPath(path, path.getBounds().roundOut(), true);
reed@google.com209c4152011-10-26 15:03:48 +0000209 REPORTER_ASSERT(reporter, height == clip.getBounds().height());
210
211 // this is the trimmed height of this cubic (with aa). The critical thing
212 // for this test is that it is less than height, which represents just
213 // the bounds of the path's control-points.
214 //
215 // This used to fail until we tracked the MinY in the BuilderBlitter.
216 //
217 const int teardrop_height = 12;
218 path.reset();
reed@google.com12e15252011-10-26 15:19:36 +0000219 imoveTo(path, 0, 20);
220 icubicTo(path, 40, 40, 40, 0, 0, 20);
reed@google.com209c4152011-10-26 15:03:48 +0000221 REPORTER_ASSERT(reporter, sheight == path.getBounds().height());
Michael Ludwig8c9c1852021-09-14 13:16:42 -0400222 clip.setPath(path, path.getBounds().roundOut(), true);
reed@google.com209c4152011-10-26 15:03:48 +0000223 REPORTER_ASSERT(reporter, teardrop_height == clip.getBounds().height());
224}
225
reed@google.comd8676d22011-10-26 18:01:25 +0000226static void test_empty(skiatest::Reporter* reporter) {
Michael Ludwig181bb972021-09-03 12:18:23 -0400227 SkAAClip clip;
reed@google.comd8676d22011-10-26 18:01:25 +0000228
Michael Ludwig181bb972021-09-03 12:18:23 -0400229 REPORTER_ASSERT(reporter, clip.isEmpty());
230 REPORTER_ASSERT(reporter, clip.getBounds().isEmpty());
reed@google.comd8676d22011-10-26 18:01:25 +0000231
Michael Ludwig181bb972021-09-03 12:18:23 -0400232 clip.translate(10, 10, &clip); // should have no effect on empty
233 REPORTER_ASSERT(reporter, clip.isEmpty());
234 REPORTER_ASSERT(reporter, clip.getBounds().isEmpty());
reed@google.comd8676d22011-10-26 18:01:25 +0000235
236 SkIRect r = { 10, 10, 40, 50 };
Michael Ludwig181bb972021-09-03 12:18:23 -0400237 clip.setRect(r);
238 REPORTER_ASSERT(reporter, !clip.isEmpty());
239 REPORTER_ASSERT(reporter, !clip.getBounds().isEmpty());
240 REPORTER_ASSERT(reporter, clip.getBounds() == r);
reed@google.comd8676d22011-10-26 18:01:25 +0000241
Michael Ludwig181bb972021-09-03 12:18:23 -0400242 clip.setEmpty();
243 REPORTER_ASSERT(reporter, clip.isEmpty());
244 REPORTER_ASSERT(reporter, clip.getBounds().isEmpty());
reed@google.comd8676d22011-10-26 18:01:25 +0000245
246 SkMask mask;
Michael Ludwig181bb972021-09-03 12:18:23 -0400247 clip.copyToMask(&mask);
halcanary96fcdcc2015-08-27 07:41:13 -0700248 REPORTER_ASSERT(reporter, nullptr == mask.fImage);
reed@google.comd8676d22011-10-26 18:01:25 +0000249 REPORTER_ASSERT(reporter, mask.fBounds.isEmpty());
250}
251
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000252static void rand_irect(SkIRect* r, int N, SkRandom& rand) {
reed@google.comd8676d22011-10-26 18:01:25 +0000253 r->setXYWH(0, 0, rand.nextU() % N, rand.nextU() % N);
254 int dx = rand.nextU() % (2*N);
255 int dy = rand.nextU() % (2*N);
256 // use int dx,dy to make the subtract be signed
257 r->offset(N - dx, N - dy);
258}
259
260static void test_irect(skiatest::Reporter* reporter) {
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000261 SkRandom rand;
reed@google.comd8676d22011-10-26 18:01:25 +0000262
reed@google.comc9041912011-10-27 16:58:46 +0000263 for (int i = 0; i < 10000; i++) {
reed@google.comd8676d22011-10-26 18:01:25 +0000264 SkAAClip clip0, clip1;
265 SkRegion rgn0, rgn1;
266 SkIRect r0, r1;
267
268 rand_irect(&r0, 10, rand);
269 rand_irect(&r1, 10, rand);
270 clip0.setRect(r0);
271 clip1.setRect(r1);
272 rgn0.setRect(r0);
273 rgn1.setRect(r1);
Michael Ludwig8c9c1852021-09-14 13:16:42 -0400274 for (SkClipOp op : {SkClipOp::kDifference, SkClipOp::kIntersect}) {
275 SkAAClip clip2 = clip0; // leave clip0 unchanged for future iterations
reed@google.comd8676d22011-10-26 18:01:25 +0000276 SkRegion rgn2;
Michael Ludwig8c9c1852021-09-14 13:16:42 -0400277 bool nonEmptyAA = clip2.op(clip1, op);
278 bool nonEmptyBW = rgn2.op(rgn0, rgn1, (SkRegion::Op) op);
reed@google.comd8676d22011-10-26 18:01:25 +0000279 if (nonEmptyAA != nonEmptyBW || clip2.getBounds() != rgn2.getBounds()) {
halcanary7d571242016-02-24 17:59:16 -0800280 ERRORF(reporter, "%s %s "
281 "[%d %d %d %d] %s [%d %d %d %d] = BW:[%d %d %d %d] AA:[%d %d %d %d]\n",
282 nonEmptyAA == nonEmptyBW ? "true" : "false",
283 clip2.getBounds() == rgn2.getBounds() ? "true" : "false",
284 r0.fLeft, r0.fTop, r0.right(), r0.bottom(),
Michael Ludwig8c9c1852021-09-14 13:16:42 -0400285 op == SkClipOp::kDifference ? "DIFF" : "INTERSECT",
halcanary7d571242016-02-24 17:59:16 -0800286 r1.fLeft, r1.fTop, r1.right(), r1.bottom(),
287 rgn2.getBounds().fLeft, rgn2.getBounds().fTop,
288 rgn2.getBounds().right(), rgn2.getBounds().bottom(),
289 clip2.getBounds().fLeft, clip2.getBounds().fTop,
290 clip2.getBounds().right(), clip2.getBounds().bottom());
reed@google.comd8676d22011-10-26 18:01:25 +0000291 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000292
reed@google.com80cdb9a2012-02-16 18:56:17 +0000293 SkMask maskBW, maskAA;
294 copyToMask(rgn2, &maskBW);
295 clip2.copyToMask(&maskAA);
tomhudson@google.com0435f162012-03-15 18:16:39 +0000296 SkAutoMaskFreeImage freeBW(maskBW.fImage);
297 SkAutoMaskFreeImage freeAA(maskAA.fImage);
reed@google.com80cdb9a2012-02-16 18:56:17 +0000298 REPORTER_ASSERT(reporter, maskBW == maskAA);
reed@google.comd8676d22011-10-26 18:01:25 +0000299 }
300 }
301}
302
reed@google.com80cdb9a2012-02-16 18:56:17 +0000303static void test_path_with_hole(skiatest::Reporter* reporter) {
304 static const uint8_t gExpectedImage[] = {
305 0xFF, 0xFF, 0xFF, 0xFF,
306 0xFF, 0xFF, 0xFF, 0xFF,
307 0x00, 0x00, 0x00, 0x00,
308 0x00, 0x00, 0x00, 0x00,
309 0xFF, 0xFF, 0xFF, 0xFF,
310 0xFF, 0xFF, 0xFF, 0xFF,
311 };
312 SkMask expected;
Mike Reed92b33352019-08-24 19:39:13 -0400313 expected.fBounds.setWH(4, 6);
reed@google.com80cdb9a2012-02-16 18:56:17 +0000314 expected.fRowBytes = 4;
315 expected.fFormat = SkMask::kA8_Format;
316 expected.fImage = (uint8_t*)gExpectedImage;
317
318 SkPath path;
319 path.addRect(SkRect::MakeXYWH(0, 0,
320 SkIntToScalar(4), SkIntToScalar(2)));
321 path.addRect(SkRect::MakeXYWH(0, SkIntToScalar(4),
322 SkIntToScalar(4), SkIntToScalar(2)));
323
324 for (int i = 0; i < 2; ++i) {
325 SkAAClip clip;
Michael Ludwig8c9c1852021-09-14 13:16:42 -0400326 clip.setPath(path, path.getBounds().roundOut(), 1 == i);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000327
reed@google.com80cdb9a2012-02-16 18:56:17 +0000328 SkMask mask;
329 clip.copyToMask(&mask);
tomhudson@google.com0435f162012-03-15 18:16:39 +0000330 SkAutoMaskFreeImage freeM(mask.fImage);
331
reed@google.com80cdb9a2012-02-16 18:56:17 +0000332 REPORTER_ASSERT(reporter, expected == mask);
333 }
334}
335
reed202ab2a2014-08-07 11:48:10 -0700336static void test_really_a_rect(skiatest::Reporter* reporter) {
337 SkRRect rrect;
338 rrect.setRectXY(SkRect::MakeWH(100, 100), 5, 5);
339
340 SkPath path;
341 path.addRRect(rrect);
342
343 SkAAClip clip;
Michael Ludwig8c9c1852021-09-14 13:16:42 -0400344 clip.setPath(path, path.getBounds().roundOut(), true);
reed202ab2a2014-08-07 11:48:10 -0700345
346 REPORTER_ASSERT(reporter, clip.getBounds() == SkIRect::MakeWH(100, 100));
347 REPORTER_ASSERT(reporter, !clip.isRect());
348
349 // This rect should intersect the clip, but slice-out all of the "soft" parts,
350 // leaving just a rect.
351 const SkIRect ir = SkIRect::MakeLTRB(10, -10, 50, 90);
halcanary9d524f22016-03-29 09:03:52 -0700352
Michael Ludwig8c9c1852021-09-14 13:16:42 -0400353 clip.op(ir, SkClipOp::kIntersect);
reed202ab2a2014-08-07 11:48:10 -0700354
355 REPORTER_ASSERT(reporter, clip.getBounds() == SkIRect::MakeLTRB(10, 0, 50, 90));
356 // the clip recognized that that it is just a rect!
357 REPORTER_ASSERT(reporter, clip.isRect());
358}
359
reed@google.com18c464b2012-05-11 20:57:25 +0000360static void did_dx_affect(skiatest::Reporter* reporter, const SkScalar dx[],
361 size_t count, bool changed) {
362 SkIRect ir = { 0, 0, 10, 10 };
363
364 for (size_t i = 0; i < count; ++i) {
365 SkRect r;
366 r.set(ir);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000367
reed@google.com18c464b2012-05-11 20:57:25 +0000368 SkRasterClip rc0(ir);
369 SkRasterClip rc1(ir);
370 SkRasterClip rc2(ir);
371
Michael Ludwigebb451d2021-08-31 14:51:50 +0000372 rc0.op(r, SkMatrix::I(), SkClipOp::kIntersect, false);
reed@google.com18c464b2012-05-11 20:57:25 +0000373 r.offset(dx[i], 0);
Michael Ludwigebb451d2021-08-31 14:51:50 +0000374 rc1.op(r, SkMatrix::I(), SkClipOp::kIntersect, true);
reed@google.com18c464b2012-05-11 20:57:25 +0000375 r.offset(-2*dx[i], 0);
Michael Ludwigebb451d2021-08-31 14:51:50 +0000376 rc2.op(r, SkMatrix::I(), SkClipOp::kIntersect, true);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000377
reed@google.com18c464b2012-05-11 20:57:25 +0000378 REPORTER_ASSERT(reporter, changed != (rc0 == rc1));
379 REPORTER_ASSERT(reporter, changed != (rc0 == rc2));
380 }
381}
382
383static void test_nearly_integral(skiatest::Reporter* reporter) {
384 // All of these should generate equivalent rasterclips
rmistry@google.comd6176b02012-08-23 18:14:13 +0000385
reed@google.com18c464b2012-05-11 20:57:25 +0000386 static const SkScalar gSafeX[] = {
387 0, SK_Scalar1/1000, SK_Scalar1/100, SK_Scalar1/10,
388 };
389 did_dx_affect(reporter, gSafeX, SK_ARRAY_COUNT(gSafeX), false);
390
391 static const SkScalar gUnsafeX[] = {
392 SK_Scalar1/4, SK_Scalar1/3,
393 };
394 did_dx_affect(reporter, gUnsafeX, SK_ARRAY_COUNT(gUnsafeX), true);
395}
396
sugoi@google.com54f0d1b2013-02-27 19:17:41 +0000397static void test_regressions() {
reed@google.com9b0da232012-02-29 13:59:15 +0000398 // these should not assert in the debug build
399 // bug was introduced in rev. 3209
400 {
401 SkAAClip clip;
402 SkRect r;
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000403 r.fLeft = 129.892181f;
404 r.fTop = 10.3999996f;
405 r.fRight = 130.892181f;
406 r.fBottom = 20.3999996f;
Michael Ludwig8c9c1852021-09-14 13:16:42 -0400407 clip.setPath(SkPath::Rect(r), r.roundOut(), true);
reed@google.com9b0da232012-02-29 13:59:15 +0000408 }
409}
410
reed157f36d2014-10-15 07:05:09 -0700411// Building aaclip meant aa-scan-convert a path into a huge clip.
412// the old algorithm sized the supersampler to the size of the clip, which overflowed
413// its internal 16bit coordinates. The fix was to intersect the clip+path_bounds before
414// sizing the supersampler.
415//
416// Before the fix, the following code would assert in debug builds.
417//
418static void test_crbug_422693(skiatest::Reporter* reporter) {
reed157f36d2014-10-15 07:05:09 -0700419 SkRasterClip rc(SkIRect::MakeLTRB(-25000, -25000, 25000, 25000));
420 SkPath path;
421 path.addCircle(50, 50, 50);
Michael Ludwigebb451d2021-08-31 14:51:50 +0000422 rc.op(path, SkMatrix::I(), SkClipOp::kIntersect, true);
reed157f36d2014-10-15 07:05:09 -0700423}
424
Mike Reed9fc53622018-01-03 15:35:33 -0500425static void test_huge(skiatest::Reporter* reporter) {
426 SkAAClip clip;
427 int big = 0x70000000;
428 SkIRect r = { -big, -big, big, big };
429 SkASSERT(r.width() < 0 && r.height() < 0);
430
431 clip.setRect(r);
432}
433
mtklein@google.com014f2c42013-09-19 20:56:46 +0000434DEF_TEST(AAClip, reporter) {
reed@google.comd8676d22011-10-26 18:01:25 +0000435 test_empty(reporter);
436 test_path_bounds(reporter);
437 test_irect(reporter);
mike@reedtribe.org95b85bd2011-11-23 03:12:58 +0000438 test_rgn(reporter);
reed@google.com80cdb9a2012-02-16 18:56:17 +0000439 test_path_with_hole(reporter);
sugoi@google.com54f0d1b2013-02-27 19:17:41 +0000440 test_regressions();
reed@google.com18c464b2012-05-11 20:57:25 +0000441 test_nearly_integral(reporter);
reed202ab2a2014-08-07 11:48:10 -0700442 test_really_a_rect(reporter);
reed157f36d2014-10-15 07:05:09 -0700443 test_crbug_422693(reporter);
Mike Reed9fc53622018-01-03 15:35:33 -0500444 test_huge(reporter);
reed@google.com209c4152011-10-26 15:03:48 +0000445}