2011-07-28 14:26:00 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2011 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
2013-12-12 21:11:12 +00:00
|
|
|
|
2019-04-23 17:05:21 +00:00
|
|
|
#include "include/core/SkPath.h"
|
|
|
|
#include "include/core/SkRegion.h"
|
|
|
|
#include "include/utils/SkRandom.h"
|
|
|
|
#include "src/core/SkAutoMalloc.h"
|
|
|
|
#include "tests/Test.h"
|
2010-07-13 18:35:14 +00:00
|
|
|
|
2012-11-07 01:57:32 +00:00
|
|
|
static void Union(SkRegion* rgn, const SkIRect& rect) {
|
|
|
|
rgn->op(rect, SkRegion::kUnion_Op);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define TEST_NO_INTERSECT(rgn, rect) REPORTER_ASSERT(reporter, !rgn.intersects(rect))
|
|
|
|
#define TEST_INTERSECT(rgn, rect) REPORTER_ASSERT(reporter, rgn.intersects(rect))
|
2012-11-07 03:39:46 +00:00
|
|
|
#define TEST_NO_CONTAINS(rgn, rect) REPORTER_ASSERT(reporter, !rgn.contains(rect))
|
2012-11-07 01:57:32 +00:00
|
|
|
|
|
|
|
// inspired by http://code.google.com/p/skia/issues/detail?id=958
|
|
|
|
//
|
|
|
|
static void test_fromchrome(skiatest::Reporter* reporter) {
|
|
|
|
SkRegion r;
|
|
|
|
Union(&r, SkIRect::MakeXYWH(0, 0, 1, 1));
|
|
|
|
TEST_NO_INTERSECT(r, SkIRect::MakeXYWH(0, 0, 0, 0));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 0, 2, 2));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(-1, 0, 2, 2));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(-1, -1, 2, 2));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(0, -1, 2, 2));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(-1, -1, 3, 3));
|
2012-11-08 02:03:56 +00:00
|
|
|
|
2012-11-07 01:57:32 +00:00
|
|
|
Union(&r, SkIRect::MakeXYWH(0, 0, 3, 3));
|
|
|
|
Union(&r, SkIRect::MakeXYWH(10, 0, 3, 3));
|
|
|
|
Union(&r, SkIRect::MakeXYWH(0, 10, 13, 3));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(-1, -1, 2, 2));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(2, -1, 2, 2));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(2, 2, 2, 2));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(-1, 2, 2, 2));
|
2012-11-08 02:03:56 +00:00
|
|
|
|
2012-11-07 01:57:32 +00:00
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(9, -1, 2, 2));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(12, -1, 2, 2));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(12, 2, 2, 2));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(9, 2, 2, 2));
|
2012-11-08 02:03:56 +00:00
|
|
|
|
2012-11-07 01:57:32 +00:00
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(0, -1, 13, 5));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(1, -1, 11, 5));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(2, -1, 9, 5));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(2, -1, 8, 5));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(3, -1, 8, 5));
|
2012-11-08 02:03:56 +00:00
|
|
|
|
2012-11-07 01:57:32 +00:00
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 1, 13, 1));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(1, 1, 11, 1));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(2, 1, 9, 1));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(2, 1, 8, 1));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(3, 1, 8, 1));
|
2012-11-08 02:03:56 +00:00
|
|
|
|
2012-11-07 01:57:32 +00:00
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 0, 13, 13));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 1, 13, 11));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 2, 13, 9));
|
|
|
|
TEST_INTERSECT(r, SkIRect::MakeXYWH(0, 2, 13, 8));
|
2012-11-08 02:03:56 +00:00
|
|
|
|
|
|
|
|
2012-11-07 01:57:32 +00:00
|
|
|
// These test SkRegion::contains(Rect) and SkRegion::contains(Region)
|
2012-11-08 02:03:56 +00:00
|
|
|
|
2012-11-07 01:57:32 +00:00
|
|
|
SkRegion container;
|
|
|
|
Union(&container, SkIRect::MakeXYWH(0, 0, 40, 20));
|
|
|
|
Union(&container, SkIRect::MakeXYWH(30, 20, 10, 20));
|
|
|
|
TEST_NO_CONTAINS(container, SkIRect::MakeXYWH(0, 0, 10, 39));
|
|
|
|
TEST_NO_CONTAINS(container, SkIRect::MakeXYWH(29, 0, 10, 39));
|
2012-11-07 14:23:42 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
SkRegion rgn;
|
|
|
|
Union(&rgn, SkIRect::MakeXYWH(0, 0, 10, 10));
|
|
|
|
Union(&rgn, SkIRect::MakeLTRB(5, 10, 20, 20));
|
|
|
|
TEST_INTERSECT(rgn, SkIRect::MakeXYWH(15, 0, 5, 11));
|
|
|
|
}
|
2012-11-07 01:57:32 +00:00
|
|
|
}
|
|
|
|
|
2012-04-30 16:28:04 +00:00
|
|
|
static void test_empties(skiatest::Reporter* reporter) {
|
|
|
|
SkRegion valid(SkIRect::MakeWH(10, 10));
|
|
|
|
SkRegion empty, empty2;
|
|
|
|
|
|
|
|
REPORTER_ASSERT(reporter, empty.isEmpty());
|
|
|
|
REPORTER_ASSERT(reporter, !valid.isEmpty());
|
|
|
|
|
|
|
|
// test intersects
|
|
|
|
REPORTER_ASSERT(reporter, !empty.intersects(empty2));
|
|
|
|
REPORTER_ASSERT(reporter, !valid.intersects(empty));
|
|
|
|
|
|
|
|
// test contains
|
|
|
|
REPORTER_ASSERT(reporter, !empty.contains(empty2));
|
|
|
|
REPORTER_ASSERT(reporter, !valid.contains(empty));
|
|
|
|
REPORTER_ASSERT(reporter, !empty.contains(valid));
|
2015-03-13 15:48:26 +00:00
|
|
|
|
|
|
|
SkPath emptyPath;
|
|
|
|
emptyPath.moveTo(1, 5);
|
|
|
|
emptyPath.close();
|
|
|
|
SkRegion openClip;
|
2019-08-24 23:39:13 +00:00
|
|
|
openClip.setRect({-16000, -16000, 16000, 16000});
|
2015-03-13 15:48:26 +00:00
|
|
|
empty.setPath(emptyPath, openClip); // should not assert
|
2012-04-30 16:28:04 +00:00
|
|
|
}
|
|
|
|
|
2012-04-28 20:09:19 +00:00
|
|
|
enum {
|
|
|
|
W = 256,
|
|
|
|
H = 256
|
|
|
|
};
|
|
|
|
|
2013-09-09 20:09:12 +00:00
|
|
|
static SkIRect randRect(SkRandom& rand) {
|
2012-04-28 20:09:19 +00:00
|
|
|
int x = rand.nextU() % W;
|
|
|
|
int y = rand.nextU() % H;
|
|
|
|
int w = rand.nextU() % W;
|
|
|
|
int h = rand.nextU() % H;
|
|
|
|
return SkIRect::MakeXYWH(x, y, w >> 1, h >> 1);
|
|
|
|
}
|
|
|
|
|
2013-09-09 20:09:12 +00:00
|
|
|
static void randRgn(SkRandom& rand, SkRegion* rgn, int n) {
|
2012-04-28 20:09:19 +00:00
|
|
|
rgn->setEmpty();
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
|
|
rgn->op(randRect(rand), SkRegion::kUnion_Op);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool slow_contains(const SkRegion& outer, const SkRegion& inner) {
|
|
|
|
SkRegion tmp;
|
|
|
|
tmp.op(outer, inner, SkRegion::kUnion_Op);
|
|
|
|
return outer == tmp;
|
|
|
|
}
|
|
|
|
|
2012-05-02 16:09:21 +00:00
|
|
|
static bool slow_contains(const SkRegion& outer, const SkIRect& r) {
|
|
|
|
SkRegion tmp;
|
|
|
|
tmp.op(outer, SkRegion(r), SkRegion::kUnion_Op);
|
|
|
|
return outer == tmp;
|
|
|
|
}
|
|
|
|
|
2012-04-28 20:09:19 +00:00
|
|
|
static bool slow_intersects(const SkRegion& outer, const SkRegion& inner) {
|
|
|
|
SkRegion tmp;
|
|
|
|
return tmp.op(outer, inner, SkRegion::kIntersect_Op);
|
|
|
|
}
|
|
|
|
|
2012-05-02 16:09:21 +00:00
|
|
|
static void test_contains_iter(skiatest::Reporter* reporter, const SkRegion& rgn) {
|
|
|
|
SkRegion::Iterator iter(rgn);
|
|
|
|
while (!iter.done()) {
|
|
|
|
SkIRect r = iter.rect();
|
|
|
|
REPORTER_ASSERT(reporter, rgn.contains(r));
|
|
|
|
r.inset(-1, -1);
|
|
|
|
REPORTER_ASSERT(reporter, !rgn.contains(r));
|
|
|
|
iter.next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-28 20:09:19 +00:00
|
|
|
static void contains_proc(skiatest::Reporter* reporter,
|
|
|
|
const SkRegion& a, const SkRegion& b) {
|
2012-05-02 16:09:21 +00:00
|
|
|
// test rgn
|
2012-04-28 20:09:19 +00:00
|
|
|
bool c0 = a.contains(b);
|
|
|
|
bool c1 = slow_contains(a, b);
|
|
|
|
REPORTER_ASSERT(reporter, c0 == c1);
|
2012-05-02 16:09:21 +00:00
|
|
|
|
|
|
|
// test rect
|
|
|
|
SkIRect r = a.getBounds();
|
|
|
|
r.inset(r.width()/4, r.height()/4);
|
|
|
|
c0 = a.contains(r);
|
|
|
|
c1 = slow_contains(a, r);
|
|
|
|
REPORTER_ASSERT(reporter, c0 == c1);
|
|
|
|
|
|
|
|
test_contains_iter(reporter, a);
|
|
|
|
test_contains_iter(reporter, b);
|
2012-04-28 20:09:19 +00:00
|
|
|
}
|
|
|
|
|
2012-05-02 16:52:12 +00:00
|
|
|
static void test_intersects_iter(skiatest::Reporter* reporter, const SkRegion& rgn) {
|
|
|
|
SkRegion::Iterator iter(rgn);
|
|
|
|
while (!iter.done()) {
|
|
|
|
SkIRect r = iter.rect();
|
|
|
|
REPORTER_ASSERT(reporter, rgn.intersects(r));
|
|
|
|
r.inset(-1, -1);
|
|
|
|
REPORTER_ASSERT(reporter, rgn.intersects(r));
|
|
|
|
iter.next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-04-28 20:09:19 +00:00
|
|
|
static void intersects_proc(skiatest::Reporter* reporter,
|
|
|
|
const SkRegion& a, const SkRegion& b) {
|
|
|
|
bool c0 = a.intersects(b);
|
|
|
|
bool c1 = slow_intersects(a, b);
|
|
|
|
REPORTER_ASSERT(reporter, c0 == c1);
|
2012-05-02 16:52:12 +00:00
|
|
|
|
|
|
|
test_intersects_iter(reporter, a);
|
|
|
|
test_intersects_iter(reporter, b);
|
2012-04-28 20:09:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void test_proc(skiatest::Reporter* reporter,
|
|
|
|
void (*proc)(skiatest::Reporter*,
|
|
|
|
const SkRegion& a, const SkRegion&)) {
|
2013-09-09 20:09:12 +00:00
|
|
|
SkRandom rand;
|
2012-04-28 20:09:19 +00:00
|
|
|
for (int i = 0; i < 10000; ++i) {
|
|
|
|
SkRegion outer;
|
|
|
|
randRgn(rand, &outer, 8);
|
|
|
|
SkRegion inner;
|
|
|
|
randRgn(rand, &inner, 2);
|
|
|
|
proc(reporter, outer, inner);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-09 20:09:12 +00:00
|
|
|
static void rand_rect(SkIRect* rect, SkRandom& rand) {
|
2010-07-13 18:35:14 +00:00
|
|
|
int bits = 6;
|
|
|
|
int shift = 32 - bits;
|
2019-08-24 23:39:13 +00:00
|
|
|
rect->setLTRB(rand.nextU() >> shift, rand.nextU() >> shift,
|
|
|
|
rand.nextU() >> shift, rand.nextU() >> shift);
|
2010-07-13 18:35:14 +00:00
|
|
|
rect->sort();
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool test_rects(const SkIRect rect[], int count) {
|
|
|
|
SkRegion rgn0, rgn1;
|
|
|
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
rgn0.op(rect[i], SkRegion::kUnion_Op);
|
|
|
|
}
|
|
|
|
rgn1.setRects(rect, count);
|
|
|
|
|
|
|
|
if (rgn0 != rgn1) {
|
|
|
|
SkDebugf("\n");
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
|
|
SkDebugf(" { %d, %d, %d, %d },\n",
|
|
|
|
rect[i].fLeft, rect[i].fTop,
|
|
|
|
rect[i].fRight, rect[i].fBottom);
|
|
|
|
}
|
|
|
|
SkDebugf("\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-12-12 21:11:12 +00:00
|
|
|
DEF_TEST(Region, reporter) {
|
2010-07-13 18:35:14 +00:00
|
|
|
const SkIRect r2[] = {
|
|
|
|
{ 0, 0, 1, 1 },
|
|
|
|
{ 2, 2, 3, 3 },
|
|
|
|
};
|
|
|
|
REPORTER_ASSERT(reporter, test_rects(r2, SK_ARRAY_COUNT(r2)));
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2010-07-13 18:35:14 +00:00
|
|
|
const SkIRect rects[] = {
|
|
|
|
{ 0, 0, 1, 2 },
|
|
|
|
{ 2, 1, 3, 3 },
|
|
|
|
{ 4, 0, 5, 1 },
|
|
|
|
{ 6, 0, 7, 4 },
|
|
|
|
};
|
|
|
|
REPORTER_ASSERT(reporter, test_rects(rects, SK_ARRAY_COUNT(rects)));
|
|
|
|
|
2013-09-09 20:09:12 +00:00
|
|
|
SkRandom rand;
|
2010-07-13 18:35:14 +00:00
|
|
|
for (int i = 0; i < 1000; i++) {
|
|
|
|
SkRegion rgn0, rgn1;
|
|
|
|
|
|
|
|
const int N = 8;
|
|
|
|
SkIRect rect[N];
|
|
|
|
for (int j = 0; j < N; j++) {
|
|
|
|
rand_rect(&rect[j], rand);
|
|
|
|
}
|
|
|
|
REPORTER_ASSERT(reporter, test_rects(rect, N));
|
|
|
|
}
|
2012-08-23 18:14:13 +00:00
|
|
|
|
2012-04-28 20:09:19 +00:00
|
|
|
test_proc(reporter, contains_proc);
|
|
|
|
test_proc(reporter, intersects_proc);
|
2012-04-30 16:28:04 +00:00
|
|
|
test_empties(reporter);
|
2012-11-07 01:57:32 +00:00
|
|
|
test_fromchrome(reporter);
|
2010-07-13 18:35:14 +00:00
|
|
|
}
|
2015-06-18 13:16:36 +00:00
|
|
|
|
|
|
|
// Test that writeToMemory reports the same number of bytes whether there was a
|
|
|
|
// buffer to write to or not.
|
|
|
|
static void test_write(const SkRegion& region, skiatest::Reporter* r) {
|
2015-08-27 14:41:13 +00:00
|
|
|
const size_t bytesNeeded = region.writeToMemory(nullptr);
|
2015-06-18 13:16:36 +00:00
|
|
|
SkAutoMalloc storage(bytesNeeded);
|
|
|
|
const size_t bytesWritten = region.writeToMemory(storage.get());
|
|
|
|
REPORTER_ASSERT(r, bytesWritten == bytesNeeded);
|
2017-02-16 17:42:24 +00:00
|
|
|
|
|
|
|
// Also check that the bytes are meaningful.
|
|
|
|
SkRegion copy;
|
|
|
|
REPORTER_ASSERT(r, copy.readFromMemory(storage.get(), bytesNeeded));
|
|
|
|
REPORTER_ASSERT(r, region == copy);
|
2015-06-18 13:16:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DEF_TEST(Region_writeToMemory, r) {
|
|
|
|
// Test an empty region.
|
|
|
|
SkRegion region;
|
|
|
|
REPORTER_ASSERT(r, region.isEmpty());
|
|
|
|
test_write(region, r);
|
|
|
|
|
|
|
|
// Test a rectangular region
|
2019-08-24 23:39:13 +00:00
|
|
|
bool nonEmpty = region.setRect({0, 0, 50, 50});
|
2015-06-18 13:16:36 +00:00
|
|
|
REPORTER_ASSERT(r, nonEmpty);
|
|
|
|
REPORTER_ASSERT(r, region.isRect());
|
|
|
|
test_write(region, r);
|
|
|
|
|
|
|
|
// Test a complex region
|
2019-08-24 23:39:13 +00:00
|
|
|
nonEmpty = region.op({50, 50, 100, 100}, SkRegion::kUnion_Op);
|
2015-06-18 13:16:36 +00:00
|
|
|
REPORTER_ASSERT(r, nonEmpty);
|
|
|
|
REPORTER_ASSERT(r, region.isComplex());
|
|
|
|
test_write(region, r);
|
2017-02-20 03:16:10 +00:00
|
|
|
|
|
|
|
SkRegion complexRegion;
|
|
|
|
Union(&complexRegion, SkIRect::MakeXYWH(0, 0, 1, 1));
|
|
|
|
Union(&complexRegion, SkIRect::MakeXYWH(0, 0, 3, 3));
|
|
|
|
Union(&complexRegion, SkIRect::MakeXYWH(10, 0, 3, 3));
|
|
|
|
Union(&complexRegion, SkIRect::MakeXYWH(0, 10, 13, 3));
|
|
|
|
test_write(complexRegion, r);
|
|
|
|
|
|
|
|
Union(&complexRegion, SkIRect::MakeXYWH(10, 20, 3, 3));
|
|
|
|
Union(&complexRegion, SkIRect::MakeXYWH(0, 20, 3, 3));
|
|
|
|
test_write(complexRegion, r);
|
2015-06-18 13:16:36 +00:00
|
|
|
}
|
2017-02-16 17:42:24 +00:00
|
|
|
|
|
|
|
DEF_TEST(Region_readFromMemory_bad, r) {
|
|
|
|
// These assume what our binary format is: conceivably we could change it
|
|
|
|
// and might need to remove or change some of these tests.
|
|
|
|
SkRegion region;
|
|
|
|
|
2017-02-20 03:16:10 +00:00
|
|
|
{
|
|
|
|
// invalid boundary rectangle
|
|
|
|
int32_t data[5] = {0, 4, 4, 8, 2};
|
|
|
|
REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
|
|
|
|
}
|
|
|
|
// Region Layout, Serialized Format:
|
|
|
|
// COUNT LEFT TOP RIGHT BOTTOM Y_SPAN_COUNT TOTAL_INTERVAL_COUNT
|
|
|
|
// Top ( Bottom Span_Interval_Count ( Left Right )* Sentinel )+ Sentinel
|
|
|
|
{
|
|
|
|
// Example of valid data
|
|
|
|
int32_t data[] = {9, 0, 0, 10, 10, 1, 2, 0, 10, 2, 0, 4, 6, 10,
|
|
|
|
2147483647, 2147483647};
|
|
|
|
REPORTER_ASSERT(r, 0 != region.readFromMemory(data, sizeof(data)));
|
|
|
|
}
|
2017-06-22 11:21:57 +00:00
|
|
|
{
|
|
|
|
// Example of valid data with 4 intervals
|
|
|
|
int32_t data[] = {19, 0, 0, 30, 30, 3, 4, 0, 10, 2, 0, 10, 20, 30,
|
|
|
|
2147483647, 20, 0, 2147483647, 30, 2, 0, 10, 20, 30,
|
|
|
|
2147483647, 2147483647};
|
|
|
|
REPORTER_ASSERT(r, 0 != region.readFromMemory(data, sizeof(data)));
|
|
|
|
}
|
2017-02-20 03:16:10 +00:00
|
|
|
{
|
|
|
|
// Short count
|
|
|
|
int32_t data[] = {8, 0, 0, 10, 10, 1, 2, 0, 10, 2, 0, 4, 6, 10,
|
|
|
|
2147483647, 2147483647};
|
|
|
|
REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
// bounds don't match
|
|
|
|
int32_t data[] = {9, 0, 0, 10, 11, 1, 2, 0, 10, 2, 0, 4, 6, 10,
|
|
|
|
2147483647, 2147483647};
|
|
|
|
REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
// bad yspan count
|
|
|
|
int32_t data[] = {9, 0, 0, 10, 10, 2, 2, 0, 10, 2, 0, 4, 6, 10,
|
|
|
|
2147483647, 2147483647};
|
|
|
|
REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
// bad int count
|
|
|
|
int32_t data[] = {9, 0, 0, 10, 10, 1, 3, 0, 10, 2, 0, 4, 6, 10,
|
|
|
|
2147483647, 2147483647};
|
|
|
|
REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
// bad final sentinal
|
|
|
|
int32_t data[] = {9, 0, 0, 10, 10, 1, 2, 0, 10, 2, 0, 4, 6, 10,
|
|
|
|
2147483647, -1};
|
|
|
|
REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
// bad row sentinal
|
|
|
|
int32_t data[] = {9, 0, 0, 10, 10, 1, 2, 0, 10, 2, 0, 4, 6, 10,
|
|
|
|
-1, 2147483647};
|
|
|
|
REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
|
|
|
|
}
|
2017-06-22 11:21:57 +00:00
|
|
|
{
|
|
|
|
// starts with empty yspan
|
|
|
|
int32_t data[] = {12, 0, 0, 10, 10, 2, 2, -5, 0, 0, 2147483647, 10,
|
|
|
|
2, 0, 4, 6, 10, 2147483647, 2147483647};
|
|
|
|
REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
// ends with empty yspan
|
|
|
|
int32_t data[] = {12, 0, 0, 10, 10, 2, 2, 0, 10, 2, 0, 4, 6, 10,
|
|
|
|
2147483647, 15, 0, 2147483647, 2147483647};
|
|
|
|
REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
// y intervals out of order
|
|
|
|
int32_t data[] = {19, 0, -20, 30, 10, 3, 4, 0, 10, 2, 0, 10, 20, 30,
|
|
|
|
2147483647, -20, 0, 2147483647, -10, 2, 0, 10, 20, 30,
|
|
|
|
2147483647, 2147483647};
|
|
|
|
REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
// x intervals out of order
|
|
|
|
int32_t data[] = {9, 0, 0, 10, 10, 1, 2, 0, 10, 2, 6, 10, 0, 4,
|
|
|
|
2147483647, 2147483647};
|
|
|
|
REPORTER_ASSERT(r, 0 == region.readFromMemory(data, sizeof(data)));
|
|
|
|
}
|
2017-02-16 17:42:24 +00:00
|
|
|
}
|
2018-01-16 18:29:18 +00:00
|
|
|
|
|
|
|
DEF_TEST(region_toobig, reporter) {
|
|
|
|
const int big = 1 << 30;
|
|
|
|
const SkIRect neg = SkIRect::MakeXYWH(-big, -big, 10, 10);
|
|
|
|
const SkIRect pos = SkIRect::MakeXYWH( big, big, 10, 10);
|
|
|
|
|
|
|
|
REPORTER_ASSERT(reporter, !neg.isEmpty());
|
|
|
|
REPORTER_ASSERT(reporter, !pos.isEmpty());
|
|
|
|
|
|
|
|
SkRegion negR(neg);
|
|
|
|
SkRegion posR(pos);
|
|
|
|
|
|
|
|
REPORTER_ASSERT(reporter, !negR.isEmpty());
|
|
|
|
REPORTER_ASSERT(reporter, !posR.isEmpty());
|
|
|
|
|
|
|
|
SkRegion rgn;
|
|
|
|
rgn.op(negR, posR, SkRegion::kUnion_Op);
|
|
|
|
|
|
|
|
// If we union those to rectangles, the resulting coordinates span more than int32_t, so
|
|
|
|
// we must mark the region as empty.
|
|
|
|
REPORTER_ASSERT(reporter, rgn.isEmpty());
|
|
|
|
}
|
|
|
|
|
2018-02-27 20:44:36 +00:00
|
|
|
DEF_TEST(region_inverse_union_skbug_7491, reporter) {
|
|
|
|
SkPath path;
|
2019-11-26 17:17:17 +00:00
|
|
|
path.setFillType(SkPathFillType::kInverseWinding);
|
2018-02-27 20:44:36 +00:00
|
|
|
path.moveTo(10, 20); path.lineTo(10, 30); path.lineTo(10.1f, 10); path.close();
|
|
|
|
|
|
|
|
SkRegion clip;
|
|
|
|
clip.op(SkIRect::MakeLTRB(10, 10, 15, 20), SkRegion::kUnion_Op);
|
|
|
|
clip.op(SkIRect::MakeLTRB(20, 10, 25, 20), SkRegion::kUnion_Op);
|
|
|
|
|
|
|
|
SkRegion rgn;
|
|
|
|
rgn.setPath(path, clip);
|
|
|
|
|
|
|
|
REPORTER_ASSERT(reporter, clip == rgn);
|
|
|
|
}
|
|
|
|
|
2018-05-23 14:08:53 +00:00
|
|
|
DEF_TEST(giant_path_region, reporter) {
|
|
|
|
const SkScalar big = 32767;
|
|
|
|
SkPath path;
|
|
|
|
path.moveTo(-big, 0);
|
|
|
|
path.quadTo(big, 0, big, big);
|
|
|
|
SkIRect ir = path.getBounds().round();
|
|
|
|
SkRegion rgn;
|
|
|
|
rgn.setPath(path, SkRegion(ir));
|
|
|
|
}
|
|
|
|
|
2018-06-22 20:42:57 +00:00
|
|
|
DEF_TEST(rrect_region_crbug_850350, reporter) {
|
2018-06-21 15:07:16 +00:00
|
|
|
SkMatrix m;
|
|
|
|
m.reset();
|
|
|
|
m[1] = 0.753662348f;
|
|
|
|
m[3] = 1.40079998E+20f;
|
|
|
|
|
|
|
|
const SkPoint corners[] = {
|
|
|
|
{ 2.65876e-19f, 0.0194088f },
|
|
|
|
{ 4896, 0.00114702f },
|
|
|
|
{ 0, 0 },
|
|
|
|
{ 0.00114702f, 0.00495333f },
|
|
|
|
};
|
|
|
|
SkRRect rrect;
|
|
|
|
rrect.setRectRadii({-8.72387e-31f, 1.29996e-38f, 4896, 1.125f}, corners);
|
|
|
|
|
|
|
|
SkPath path;
|
|
|
|
path.addRRect(rrect);
|
|
|
|
path.transform(m);
|
|
|
|
|
|
|
|
SkRegion rgn;
|
2018-06-22 20:42:57 +00:00
|
|
|
rgn.setPath(path, SkRegion{SkIRect{0, 0, 24, 24}});
|
2018-06-21 15:07:16 +00:00
|
|
|
}
|
|
|
|
|
2018-08-13 17:52:22 +00:00
|
|
|
DEF_TEST(region_bug_chromium_873051, reporter) {
|
|
|
|
SkRegion region;
|
|
|
|
REPORTER_ASSERT(reporter, region.setRect({0, 0, 0x7FFFFFFE, 0x7FFFFFFE}));
|
|
|
|
REPORTER_ASSERT(reporter, !region.setRect({0, 0, 0x7FFFFFFE, 0x7FFFFFFF}));
|
|
|
|
REPORTER_ASSERT(reporter, !region.setRect({0, 0, 0x7FFFFFFF, 0x7FFFFFFE}));
|
|
|
|
REPORTER_ASSERT(reporter, !region.setRect({0, 0, 0x7FFFFFFF, 0x7FFFFFFF}));
|
|
|
|
}
|
2018-08-28 14:51:06 +00:00
|
|
|
|
|
|
|
DEF_TEST(region_empty_iter, reporter) {
|
|
|
|
SkRegion::Iterator emptyIter;
|
|
|
|
REPORTER_ASSERT(reporter, !emptyIter.rewind());
|
|
|
|
REPORTER_ASSERT(reporter, emptyIter.done());
|
|
|
|
auto eRect = emptyIter.rect();
|
|
|
|
REPORTER_ASSERT(reporter, eRect.isEmpty());
|
|
|
|
REPORTER_ASSERT(reporter, SkIRect::MakeEmpty() == eRect);
|
|
|
|
REPORTER_ASSERT(reporter, !emptyIter.rgn());
|
|
|
|
|
|
|
|
SkRegion region;
|
|
|
|
SkRegion::Iterator resetIter;
|
|
|
|
resetIter.reset(region);
|
|
|
|
REPORTER_ASSERT(reporter, resetIter.rewind());
|
|
|
|
REPORTER_ASSERT(reporter, resetIter.done());
|
|
|
|
auto rRect = resetIter.rect();
|
|
|
|
REPORTER_ASSERT(reporter, rRect.isEmpty());
|
|
|
|
REPORTER_ASSERT(reporter, SkIRect::MakeEmpty() == rRect);
|
|
|
|
REPORTER_ASSERT(reporter, resetIter.rgn());
|
|
|
|
REPORTER_ASSERT(reporter, resetIter.rgn()->isEmpty());
|
|
|
|
|
|
|
|
SkRegion::Iterator iter(region);
|
|
|
|
REPORTER_ASSERT(reporter, iter.done());
|
|
|
|
auto iRect = iter.rect();
|
|
|
|
REPORTER_ASSERT(reporter, iRect.isEmpty());
|
|
|
|
REPORTER_ASSERT(reporter, SkIRect::MakeEmpty() == iRect);
|
|
|
|
REPORTER_ASSERT(reporter, iter.rgn());
|
|
|
|
REPORTER_ASSERT(reporter, iter.rgn()->isEmpty());
|
|
|
|
|
|
|
|
SkRegion::Cliperator clipIter(region, {0, 0, 100, 100});
|
|
|
|
REPORTER_ASSERT(reporter, clipIter.done());
|
|
|
|
auto cRect = clipIter.rect();
|
|
|
|
REPORTER_ASSERT(reporter, cRect.isEmpty());
|
|
|
|
REPORTER_ASSERT(reporter, SkIRect::MakeEmpty() == cRect);
|
|
|
|
|
|
|
|
SkRegion::Spanerator spanIter(region, 0, 0, 100);
|
|
|
|
int left = 0, right = 0;
|
|
|
|
REPORTER_ASSERT(reporter, !spanIter.next(&left, &right));
|
|
|
|
REPORTER_ASSERT(reporter, !left);
|
|
|
|
REPORTER_ASSERT(reporter, !right);
|
|
|
|
}
|