Home | History | Annotate | Download | only in tests
      1 
      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  */
      8 #include "Test.h"
      9 #include "SkRegion.h"
     10 #include "SkRandom.h"
     11 
     12 static 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 //
     22 static 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     {
     72         SkRegion rgn;
     73         Union(&rgn, SkIRect::MakeXYWH(0, 0, 10, 10));
     74         Union(&rgn, SkIRect::MakeLTRB(5, 10, 20, 20));
     75         TEST_INTERSECT(rgn, SkIRect::MakeXYWH(15, 0, 5, 11));
     76     }
     77 }
     78 
     79 static void test_empties(skiatest::Reporter* reporter) {
     80     SkRegion valid(SkIRect::MakeWH(10, 10));
     81     SkRegion empty, empty2;
     82 
     83     REPORTER_ASSERT(reporter, empty.isEmpty());
     84     REPORTER_ASSERT(reporter, !valid.isEmpty());
     85 
     86     // test intersects
     87     REPORTER_ASSERT(reporter, !empty.intersects(empty2));
     88     REPORTER_ASSERT(reporter, !valid.intersects(empty));
     89 
     90     // test contains
     91     REPORTER_ASSERT(reporter, !empty.contains(empty2));
     92     REPORTER_ASSERT(reporter, !valid.contains(empty));
     93     REPORTER_ASSERT(reporter, !empty.contains(valid));
     94 }
     95 
     96 enum {
     97     W = 256,
     98     H = 256
     99 };
    100 
    101 static SkIRect randRect(SkRandom& rand) {
    102     int x = rand.nextU() % W;
    103     int y = rand.nextU() % H;
    104     int w = rand.nextU() % W;
    105     int h = rand.nextU() % H;
    106     return SkIRect::MakeXYWH(x, y, w >> 1, h >> 1);
    107 }
    108 
    109 static void randRgn(SkRandom& rand, SkRegion* rgn, int n) {
    110     rgn->setEmpty();
    111     for (int i = 0; i < n; ++i) {
    112         rgn->op(randRect(rand), SkRegion::kUnion_Op);
    113     }
    114 }
    115 
    116 static bool slow_contains(const SkRegion& outer, const SkRegion& inner) {
    117     SkRegion tmp;
    118     tmp.op(outer, inner, SkRegion::kUnion_Op);
    119     return outer == tmp;
    120 }
    121 
    122 static bool slow_contains(const SkRegion& outer, const SkIRect& r) {
    123     SkRegion tmp;
    124     tmp.op(outer, SkRegion(r), SkRegion::kUnion_Op);
    125     return outer == tmp;
    126 }
    127 
    128 static bool slow_intersects(const SkRegion& outer, const SkRegion& inner) {
    129     SkRegion tmp;
    130     return tmp.op(outer, inner, SkRegion::kIntersect_Op);
    131 }
    132 
    133 static void test_contains_iter(skiatest::Reporter* reporter, const SkRegion& rgn) {
    134     SkRegion::Iterator iter(rgn);
    135     while (!iter.done()) {
    136         SkIRect r = iter.rect();
    137         REPORTER_ASSERT(reporter, rgn.contains(r));
    138         r.inset(-1, -1);
    139         REPORTER_ASSERT(reporter, !rgn.contains(r));
    140         iter.next();
    141     }
    142 }
    143 
    144 static void contains_proc(skiatest::Reporter* reporter,
    145                           const SkRegion& a, const SkRegion& b) {
    146     // test rgn
    147     bool c0 = a.contains(b);
    148     bool c1 = slow_contains(a, b);
    149     REPORTER_ASSERT(reporter, c0 == c1);
    150 
    151     // test rect
    152     SkIRect r = a.getBounds();
    153     r.inset(r.width()/4, r.height()/4);
    154     c0 = a.contains(r);
    155     c1 = slow_contains(a, r);
    156     REPORTER_ASSERT(reporter, c0 == c1);
    157 
    158     test_contains_iter(reporter, a);
    159     test_contains_iter(reporter, b);
    160 }
    161 
    162 static void test_intersects_iter(skiatest::Reporter* reporter, const SkRegion& rgn) {
    163     SkRegion::Iterator iter(rgn);
    164     while (!iter.done()) {
    165         SkIRect r = iter.rect();
    166         REPORTER_ASSERT(reporter, rgn.intersects(r));
    167         r.inset(-1, -1);
    168         REPORTER_ASSERT(reporter, rgn.intersects(r));
    169         iter.next();
    170     }
    171 }
    172 
    173 static void intersects_proc(skiatest::Reporter* reporter,
    174                           const SkRegion& a, const SkRegion& b) {
    175     bool c0 = a.intersects(b);
    176     bool c1 = slow_intersects(a, b);
    177     REPORTER_ASSERT(reporter, c0 == c1);
    178 
    179     test_intersects_iter(reporter, a);
    180     test_intersects_iter(reporter, b);
    181 }
    182 
    183 static void test_proc(skiatest::Reporter* reporter,
    184                       void (*proc)(skiatest::Reporter*,
    185                                    const SkRegion& a, const SkRegion&)) {
    186     SkRandom rand;
    187     for (int i = 0; i < 10000; ++i) {
    188         SkRegion outer;
    189         randRgn(rand, &outer, 8);
    190         SkRegion inner;
    191         randRgn(rand, &inner, 2);
    192         proc(reporter, outer, inner);
    193     }
    194 }
    195 
    196 static void rand_rect(SkIRect* rect, SkRandom& rand) {
    197     int bits = 6;
    198     int shift = 32 - bits;
    199     rect->set(rand.nextU() >> shift, rand.nextU() >> shift,
    200               rand.nextU() >> shift, rand.nextU() >> shift);
    201     rect->sort();
    202 }
    203 
    204 static bool test_rects(const SkIRect rect[], int count) {
    205     SkRegion rgn0, rgn1;
    206 
    207     for (int i = 0; i < count; i++) {
    208         rgn0.op(rect[i], SkRegion::kUnion_Op);
    209     }
    210     rgn1.setRects(rect, count);
    211 
    212     if (rgn0 != rgn1) {
    213         SkDebugf("\n");
    214         for (int i = 0; i < count; i++) {
    215             SkDebugf(" { %d, %d, %d, %d },\n",
    216                      rect[i].fLeft, rect[i].fTop,
    217                      rect[i].fRight, rect[i].fBottom);
    218         }
    219         SkDebugf("\n");
    220         return false;
    221     }
    222     return true;
    223 }
    224 
    225 static void TestRegion(skiatest::Reporter* reporter) {
    226     const SkIRect r2[] = {
    227         { 0, 0, 1, 1 },
    228         { 2, 2, 3, 3 },
    229     };
    230     REPORTER_ASSERT(reporter, test_rects(r2, SK_ARRAY_COUNT(r2)));
    231 
    232     const SkIRect rects[] = {
    233         { 0, 0, 1, 2 },
    234         { 2, 1, 3, 3 },
    235         { 4, 0, 5, 1 },
    236         { 6, 0, 7, 4 },
    237     };
    238     REPORTER_ASSERT(reporter, test_rects(rects, SK_ARRAY_COUNT(rects)));
    239 
    240     SkRandom rand;
    241     for (int i = 0; i < 1000; i++) {
    242         SkRegion rgn0, rgn1;
    243 
    244         const int N = 8;
    245         SkIRect rect[N];
    246         for (int j = 0; j < N; j++) {
    247             rand_rect(&rect[j], rand);
    248         }
    249         REPORTER_ASSERT(reporter, test_rects(rect, N));
    250     }
    251 
    252     test_proc(reporter, contains_proc);
    253     test_proc(reporter, intersects_proc);
    254     test_empties(reporter);
    255     test_fromchrome(reporter);
    256 }
    257 
    258 #include "TestClassDef.h"
    259 DEFINE_TESTCLASS("Region", RegionTestClass, TestRegion)
    260