/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "Test.h" #include "SkRegion.h" #include "SkRandom.h" 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)); } enum { W = 256, H = 256 }; static SkIRect randRect(SkRandom& rand) { 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); } static void randRgn(SkRandom& rand, SkRegion* rgn, int n) { 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; } static bool slow_contains(const SkRegion& outer, const SkIRect& r) { SkRegion tmp; tmp.op(outer, SkRegion(r), SkRegion::kUnion_Op); return outer == tmp; } static bool slow_intersects(const SkRegion& outer, const SkRegion& inner) { SkRegion tmp; return tmp.op(outer, inner, SkRegion::kIntersect_Op); } 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(); } } static void contains_proc(skiatest::Reporter* reporter, const SkRegion& a, const SkRegion& b) { // test rgn bool c0 = a.contains(b); bool c1 = slow_contains(a, b); REPORTER_ASSERT(reporter, c0 == c1); // 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); } 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(); } } 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); test_intersects_iter(reporter, a); test_intersects_iter(reporter, b); } static void test_proc(skiatest::Reporter* reporter, void (*proc)(skiatest::Reporter*, const SkRegion& a, const SkRegion&)) { SkRandom rand; for (int i = 0; i < 10000; ++i) { SkRegion outer; randRgn(rand, &outer, 8); SkRegion inner; randRgn(rand, &inner, 2); proc(reporter, outer, inner); } } static void rand_rect(SkIRect* rect, SkRandom& rand) { int bits = 6; int shift = 32 - bits; rect->set(rand.nextU() >> shift, rand.nextU() >> shift, rand.nextU() >> shift, rand.nextU() >> shift); 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; } static void TestRegion(skiatest::Reporter* reporter) { const SkIRect r2[] = { { 0, 0, 1, 1 }, { 2, 2, 3, 3 }, }; REPORTER_ASSERT(reporter, test_rects(r2, SK_ARRAY_COUNT(r2))); 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))); SkRandom rand; 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)); } test_proc(reporter, contains_proc); test_proc(reporter, intersects_proc); test_empties(reporter); } #include "TestClassDef.h" DEFINE_TESTCLASS("Region", RegionTestClass, TestRegion)