| /* |
| * 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_pm(SkAutoPixmapStorage* pixmap, int w, int h) { |
| pixmap->alloc(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) { |
| SkAutoPixmapStorage pmap; |
| make_pm(&pmap, gRec[i].fDevSize.width(), gRec[i].fDevSize.height()); |
| |
| SkRasterClip rc(gRec[i].fRCBounds); |
| |
| for (int aa = 0; aa <= 1; ++aa) { |
| SkDeviceLooper looper(pmap, rc, gRec[i].fRect, SkToBool(aa)); |
| |
| bool valid = looper.next(); |
| REPORTER_ASSERT(reporter, valid); |
| if (valid) { |
| REPORTER_ASSERT(reporter, looper.getPixmap().width() == pmap.width()); |
| REPORTER_ASSERT(reporter, looper.getPixmap().height() == pmap.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(pmap, 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(); |
| |
| SkAutoPixmapStorage pmap; |
| make_pm(&pmap, 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(pmap, rc, rect, gRec[i].fAA); |
| while (looper.next()) { |
| REPORTER_ASSERT(reporter, !looper.getRC().isEmpty()); |
| } |
| } |
| } |
| } |
| |
| DEF_TEST(DeviceLooper, reporter) { |
| test_simple(reporter); |
| test_complex(reporter); |
| } |