1 /* 2 * Copyright 2013 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 8 #include "SkDeviceLooper.h" 9 #include "SkRasterClip.h" 10 #include "Test.h" 11 12 static void make_pm(SkAutoPixmapStorage* pixmap, int w, int h) { 13 pixmap->alloc(SkImageInfo::Make(w, h, kAlpha_8_SkColorType, kPremul_SkAlphaType)); 14 } 15 16 static bool equal(const SkRasterClip& a, const SkRasterClip& b) { 17 if (a.isBW()) { 18 return b.isBW() && a.bwRgn() == b.bwRgn(); 19 } else { 20 return a.isAA() && a.aaRgn() == b.aaRgn(); 21 } 22 } 23 24 static const struct { 25 SkISize fDevSize; 26 SkIRect fRCBounds; 27 SkIRect fRect; 28 } gRec[] = { 29 { { 4000, 10 }, { 0, 0, 4000, 10 }, { 0, 0, 4000, 4000 } }, 30 { { 10, 4000 }, { 0, 0, 10, 4000 }, { 0, 0, 4000, 4000 } }, 31 // very large devce, small rect 32 { { 32000, 10 }, { 0, 0, 32000, 10 }, { 0, 0, 4000, 4000 } }, 33 { { 10, 32000 }, { 0, 0, 10, 32000 }, { 0, 0, 4000, 4000 } }, 34 // very large device, small clip 35 { { 32000, 10 }, { 0, 0, 4000, 10 }, { 0, 0, 32000, 32000 } }, 36 { { 10, 32000 }, { 0, 0, 10, 4000 }, { 0, 0, 32000, 32000 } }, 37 }; 38 39 static void test_simple(skiatest::Reporter* reporter) { 40 41 for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { 42 SkAutoPixmapStorage pmap; 43 make_pm(&pmap, gRec[i].fDevSize.width(), gRec[i].fDevSize.height()); 44 45 SkRasterClip rc(gRec[i].fRCBounds); 46 47 for (int aa = 0; aa <= 1; ++aa) { 48 SkDeviceLooper looper(pmap, rc, gRec[i].fRect, SkToBool(aa)); 49 50 bool valid = looper.next(); 51 REPORTER_ASSERT(reporter, valid); 52 if (valid) { 53 REPORTER_ASSERT(reporter, looper.getPixmap().width() == pmap.width()); 54 REPORTER_ASSERT(reporter, looper.getPixmap().height() == pmap.height()); 55 REPORTER_ASSERT(reporter, equal(looper.getRC(), rc)); 56 57 REPORTER_ASSERT(reporter, !looper.next()); 58 } 59 } 60 // test that a rect that doesn't intersect returns no loops 61 { 62 SkIRect r = rc.getBounds(); 63 r.offset(r.width(), 0); 64 SkDeviceLooper looper(pmap, rc, r, false); 65 REPORTER_ASSERT(reporter, !looper.next()); 66 } 67 } 68 } 69 70 // mask-bits are interpreted as the areas where the clip is visible 71 // [ 0x01 0x02 ] 72 // [ 0x04 0x08 ] 73 // 74 static void make_rgn(SkRegion* rgn, int w, int h, unsigned mask) { 75 SkASSERT(SkAlign2(w)); 76 SkASSERT(SkAlign2(h)); 77 w >>= 1; 78 h >>= 1; 79 const SkIRect baseR = SkIRect::MakeWH(w, h); 80 81 int bit = 1; 82 for (int y = 0; y <= 1; ++y) { 83 for (int x = 0; x <= 1; ++x) { 84 if (mask & bit) { 85 SkIRect r = baseR; 86 r.offset(x * w, y * h); 87 rgn->op(r, SkRegion::kUnion_Op); 88 } 89 bit <<= 1; 90 } 91 } 92 } 93 94 static void test_complex(skiatest::Reporter* reporter) { 95 // choose size values that will result in 4 quadrants, given fAA setting 96 const int BW_SIZE = 17 * 1000; 97 const int AA_SIZE = 7 * 1000; 98 99 struct { 100 SkISize fSize; 101 bool fAA; 102 } const gRec[] = { 103 { { BW_SIZE, BW_SIZE }, false }, 104 { { AA_SIZE, AA_SIZE }, true }, 105 }; 106 107 for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { 108 const int w = gRec[i].fSize.width(); 109 const int h = gRec[i].fSize.height(); 110 111 SkAutoPixmapStorage pmap; 112 make_pm(&pmap, w, h); 113 114 const SkIRect rect = SkIRect::MakeWH(w, h); 115 116 // mask-bits are interpreted as the areas where the clip is visible 117 // [ 0x01 0x02 ] 118 // [ 0x04 0x08 ] 119 // 120 for (int mask = 0; mask <= 15; ++mask) { 121 SkRegion rgn; 122 make_rgn(&rgn, w, h, mask); 123 124 SkRasterClip rc; 125 rc.op(rgn, SkRegion::kReplace_Op); 126 127 SkDeviceLooper looper(pmap, rc, rect, gRec[i].fAA); 128 while (looper.next()) { 129 REPORTER_ASSERT(reporter, !looper.getRC().isEmpty()); 130 } 131 } 132 } 133 } 134 135 DEF_TEST(DeviceLooper, reporter) { 136 test_simple(reporter); 137 test_complex(reporter); 138 } 139