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 
make_pm(SkAutoPixmapStorage * pixmap,int w,int h)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 
equal(const SkRasterClip & a,const SkRasterClip & b)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 
test_simple(skiatest::Reporter * reporter)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 //
make_rgn(SkRegion * rgn,int w,int h,unsigned mask)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 
test_complex(skiatest::Reporter * reporter)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 
DEF_TEST(DeviceLooper,reporter)135 DEF_TEST(DeviceLooper, reporter) {
136     test_simple(reporter);
137     test_complex(reporter);
138 }
139