| /* | 
 |  * Copyright 2013 Google Inc. | 
 |  * | 
 |  * Use of this source code is governed by a BSD-style license that can be | 
 |  * found in the LICENSE file. | 
 |  */ | 
 |  | 
 | #include "SkDeviceLooper.h" | 
 | #include "SkRasterClip.h" | 
 | #include "Test.h" | 
 |  | 
 | static void make_bm(SkBitmap* bm, int w, int h) { | 
 |     bm->allocPixels(SkImageInfo::Make(w, h, kAlpha_8_SkColorType, | 
 |                                       kPremul_SkAlphaType)); | 
 | } | 
 |  | 
 | static bool equal(const SkRasterClip& a, const SkRasterClip& b) { | 
 |     if (a.isBW()) { | 
 |         return b.isBW() && a.bwRgn() == b.bwRgn(); | 
 |     } else { | 
 |         return a.isAA() && a.aaRgn() == b.aaRgn(); | 
 |     } | 
 | } | 
 |  | 
 | static const struct { | 
 |     SkISize fDevSize; | 
 |     SkIRect fRCBounds; | 
 |     SkIRect fRect; | 
 | } gRec[] = { | 
 |     { { 4000, 10 }, { 0, 0, 4000, 10 }, { 0, 0, 4000, 4000 } }, | 
 |     { { 10, 4000 }, { 0, 0, 10, 4000 }, { 0, 0, 4000, 4000 } }, | 
 |     // very large devce, small rect | 
 |     { { 32000, 10 }, { 0, 0, 32000, 10 }, { 0, 0, 4000, 4000 } }, | 
 |     { { 10, 32000 }, { 0, 0, 10, 32000 }, { 0, 0, 4000, 4000 } }, | 
 |     // very large device, small clip | 
 |     { { 32000, 10 }, { 0, 0, 4000, 10 }, { 0, 0, 32000, 32000 } }, | 
 |     { { 10, 32000 }, { 0, 0, 10, 4000 }, { 0, 0, 32000, 32000 } }, | 
 | }; | 
 |  | 
 | static void test_simple(skiatest::Reporter* reporter) { | 
 |  | 
 |     for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { | 
 |         SkBitmap bitmap; | 
 |         make_bm(&bitmap, gRec[i].fDevSize.width(), gRec[i].fDevSize.height()); | 
 |  | 
 |         SkRasterClip rc(gRec[i].fRCBounds); | 
 |  | 
 |         for (int aa = 0; aa <= 1; ++aa) { | 
 |             SkDeviceLooper looper(bitmap, rc, gRec[i].fRect, SkToBool(aa)); | 
 |  | 
 |             bool valid = looper.next(); | 
 |             REPORTER_ASSERT(reporter, valid); | 
 |             if (valid) { | 
 |                 REPORTER_ASSERT(reporter, looper.getBitmap().width() == bitmap.width()); | 
 |                 REPORTER_ASSERT(reporter, looper.getBitmap().height() == bitmap.height()); | 
 |                 REPORTER_ASSERT(reporter, equal(looper.getRC(), rc)); | 
 |  | 
 |                 REPORTER_ASSERT(reporter, !looper.next()); | 
 |             } | 
 |         } | 
 |         // test that a rect that doesn't intersect returns no loops | 
 |         { | 
 |             SkIRect r = rc.getBounds(); | 
 |             r.offset(r.width(), 0); | 
 |             SkDeviceLooper looper(bitmap, rc, r, false); | 
 |             REPORTER_ASSERT(reporter, !looper.next()); | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | // mask-bits are interpreted as the areas where the clip is visible | 
 | //  [ 0x01  0x02 ] | 
 | //  [ 0x04  0x08 ] | 
 | // | 
 | static void make_rgn(SkRegion* rgn, int w, int h, unsigned mask) { | 
 |     SkASSERT(SkAlign2(w)); | 
 |     SkASSERT(SkAlign2(h)); | 
 |     w >>= 1; | 
 |     h >>= 1; | 
 |     const SkIRect baseR = SkIRect::MakeWH(w, h); | 
 |  | 
 |     int bit = 1; | 
 |     for (int y = 0; y <= 1; ++y) { | 
 |         for (int x = 0; x <= 1; ++x) { | 
 |             if (mask & bit) { | 
 |                 SkIRect r = baseR; | 
 |                 r.offset(x * w, y * h); | 
 |                 rgn->op(r, SkRegion::kUnion_Op); | 
 |             } | 
 |             bit <<= 1; | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | static void test_complex(skiatest::Reporter* reporter) { | 
 |     // choose size values that will result in 4 quadrants, given fAA setting | 
 |     const int BW_SIZE = 17 * 1000; | 
 |     const int AA_SIZE = 7 * 1000; | 
 |  | 
 |     struct { | 
 |         SkISize fSize; | 
 |         bool    fAA; | 
 |     } const gRec[] = { | 
 |         { { BW_SIZE, BW_SIZE }, false }, | 
 |         { {  AA_SIZE, AA_SIZE }, true }, | 
 |     }; | 
 |  | 
 |     for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { | 
 |         const int w = gRec[i].fSize.width(); | 
 |         const int h = gRec[i].fSize.height(); | 
 |  | 
 |         SkBitmap bitmap; | 
 |         make_bm(&bitmap, w, h); | 
 |  | 
 |         const SkIRect rect = SkIRect::MakeWH(w, h); | 
 |  | 
 |         // mask-bits are interpreted as the areas where the clip is visible | 
 |         //  [ 0x01  0x02 ] | 
 |         //  [ 0x04  0x08 ] | 
 |         // | 
 |         for (int mask = 0; mask <= 15; ++mask) { | 
 |             SkRegion rgn; | 
 |             make_rgn(&rgn, w, h, mask); | 
 |  | 
 |             SkRasterClip rc; | 
 |             rc.op(rgn, SkRegion::kReplace_Op); | 
 |  | 
 |             SkDeviceLooper looper(bitmap, rc, rect, gRec[i].fAA); | 
 |             while (looper.next()) { | 
 |                 REPORTER_ASSERT(reporter, !looper.getRC().isEmpty()); | 
 |             } | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | DEF_TEST(DeviceLooper, reporter) { | 
 |     test_simple(reporter); | 
 |     test_complex(reporter); | 
 | } |