• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 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 "SkBitmap.h"
9 #include "SkRect.h"
10 #include "SkTemplates.h"
11 #include "Test.h"
12 #include "sk_tool_utils.h"
13 
init_src(const SkBitmap & bitmap)14 static void init_src(const SkBitmap& bitmap) {
15     if (bitmap.getPixels()) {
16         bitmap.eraseColor(SK_ColorWHITE);
17     }
18 }
19 
20 struct Pair {
21     SkColorType fColorType;
22     const char* fValid;
23 };
24 
25 // Utility functions for copyPixelsTo()/copyPixelsFrom() tests.
26 // getPixel()
27 // setPixel()
28 // getSkConfigName()
29 // struct Coordinates
30 // reportCopyVerification()
31 // writeCoordPixels()
32 
33 // Helper struct to contain pixel locations, while avoiding need for STL.
34 struct Coordinates {
35 
36     const int length;
37     SkIPoint* const data;
38 
CoordinatesCoordinates39     explicit Coordinates(int _length): length(_length)
40                                      , data(new SkIPoint[length]) { }
41 
~CoordinatesCoordinates42     ~Coordinates(){
43         delete [] data;
44     }
45 
operator []Coordinates46     SkIPoint* operator[](int i) const {
47         // Use with care, no bounds checking.
48         return data + i;
49     }
50 };
51 
52 static const Pair gPairs[] = {
53     { kUnknown_SkColorType,     "0000000"  },
54     { kAlpha_8_SkColorType,     "0100000"  },
55     { kRGB_565_SkColorType,     "0101011"  },
56     { kARGB_4444_SkColorType,   "0101111"  },
57     { kN32_SkColorType,         "0101111"  },
58     { kRGBA_F16_SkColorType,    "0101011"  },
59 };
60 
61 static const int W = 20;
62 static const int H = 33;
63 
setup_src_bitmaps(SkBitmap * srcOpaque,SkBitmap * srcPremul,SkColorType ct)64 static void setup_src_bitmaps(SkBitmap* srcOpaque, SkBitmap* srcPremul,
65                               SkColorType ct) {
66     sk_sp<SkColorSpace> colorSpace = nullptr;
67     if (kRGBA_F16_SkColorType == ct) {
68         colorSpace = SkColorSpace::MakeSRGBLinear();
69     }
70 
71     srcOpaque->allocPixels(SkImageInfo::Make(W, H, ct, kOpaque_SkAlphaType, colorSpace));
72     srcPremul->allocPixels(SkImageInfo::Make(W, H, ct, kPremul_SkAlphaType, colorSpace));
73     init_src(*srcOpaque);
74     init_src(*srcPremul);
75 }
76 
DEF_TEST(BitmapCopy_extractSubset,reporter)77 DEF_TEST(BitmapCopy_extractSubset, reporter) {
78     for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
79         SkBitmap srcOpaque, srcPremul;
80         setup_src_bitmaps(&srcOpaque, &srcPremul, gPairs[i].fColorType);
81 
82         SkBitmap bitmap(srcOpaque);
83         SkBitmap subset;
84         SkIRect r;
85         // Extract a subset which has the same width as the original. This
86         // catches a bug where we cloned the genID incorrectly.
87         r.set(0, 1, W, 3);
88         bitmap.setIsVolatile(true);
89         // Relies on old behavior of extractSubset failing if colortype is unknown
90         if (kUnknown_SkColorType != bitmap.colorType() && bitmap.extractSubset(&subset, r)) {
91             REPORTER_ASSERT(reporter, subset.width() == W);
92             REPORTER_ASSERT(reporter, subset.height() == 2);
93             REPORTER_ASSERT(reporter, subset.alphaType() == bitmap.alphaType());
94             REPORTER_ASSERT(reporter, subset.isVolatile() == true);
95 
96             // Test copying an extracted subset.
97             for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) {
98                 SkBitmap copy;
99                 bool success = sk_tool_utils::copy_to(&copy, gPairs[j].fColorType, subset);
100                 if (!success) {
101                     // Skip checking that success matches fValid, which is redundant
102                     // with the code below.
103                     REPORTER_ASSERT(reporter, gPairs[i].fColorType != gPairs[j].fColorType);
104                     continue;
105                 }
106 
107                 // When performing a copy of an extracted subset, the gen id should
108                 // change.
109                 REPORTER_ASSERT(reporter, copy.getGenerationID() != subset.getGenerationID());
110 
111                 REPORTER_ASSERT(reporter, copy.width() == W);
112                 REPORTER_ASSERT(reporter, copy.height() == 2);
113             }
114         }
115 
116         bitmap = srcPremul;
117         bitmap.setIsVolatile(false);
118         if (bitmap.extractSubset(&subset, r)) {
119             REPORTER_ASSERT(reporter, subset.alphaType() == bitmap.alphaType());
120             REPORTER_ASSERT(reporter, subset.isVolatile() == false);
121         }
122     }
123 }
124 
125 #include "SkColorPriv.h"
126 #include "SkUtils.h"
127 
128 /**
129  *  Construct 4x4 pixels where we can look at a color and determine where it should be in the grid.
130  *  alpha = 0xFF, blue = 0x80, red = x, green = y
131  */
fill_4x4_pixels(SkPMColor colors[16])132 static void fill_4x4_pixels(SkPMColor colors[16]) {
133     for (int y = 0; y < 4; ++y) {
134         for (int x = 0; x < 4; ++x) {
135             colors[y*4+x] = SkPackARGB32(0xFF, x, y, 0x80);
136         }
137     }
138 }
139 
check_4x4_pixel(SkPMColor color,unsigned x,unsigned y)140 static bool check_4x4_pixel(SkPMColor color, unsigned x, unsigned y) {
141     SkASSERT(x < 4 && y < 4);
142     return  0xFF == SkGetPackedA32(color) &&
143             x    == SkGetPackedR32(color) &&
144             y    == SkGetPackedG32(color) &&
145             0x80 == SkGetPackedB32(color);
146 }
147 
148 /**
149  *  Fill with all zeros, which will never match any value from fill_4x4_pixels
150  */
clear_4x4_pixels(SkPMColor colors[16])151 static void clear_4x4_pixels(SkPMColor colors[16]) {
152     sk_memset32(colors, 0, 16);
153 }
154 
155 // Much of readPixels is exercised by copyTo testing, since readPixels is the backend for that
156 // method. Here we explicitly test subset copies.
157 //
DEF_TEST(BitmapReadPixels,reporter)158 DEF_TEST(BitmapReadPixels, reporter) {
159     const int W = 4;
160     const int H = 4;
161     const size_t rowBytes = W * sizeof(SkPMColor);
162     const SkImageInfo srcInfo = SkImageInfo::MakeN32Premul(W, H);
163     SkPMColor srcPixels[16];
164     fill_4x4_pixels(srcPixels);
165     SkBitmap srcBM;
166     srcBM.installPixels(srcInfo, srcPixels, rowBytes);
167 
168     SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(W, H);
169     SkPMColor dstPixels[16];
170 
171     const struct {
172         bool     fExpectedSuccess;
173         SkIPoint fRequestedSrcLoc;
174         SkISize  fRequestedDstSize;
175         // If fExpectedSuccess, check these, otherwise ignore
176         SkIPoint fExpectedDstLoc;
177         SkIRect  fExpectedSrcR;
178     } gRec[] = {
179         { true,  { 0, 0 }, { 4, 4 }, { 0, 0 }, { 0, 0, 4, 4 } },
180         { true,  { 1, 1 }, { 2, 2 }, { 0, 0 }, { 1, 1, 3, 3 } },
181         { true,  { 2, 2 }, { 4, 4 }, { 0, 0 }, { 2, 2, 4, 4 } },
182         { true,  {-1,-1 }, { 2, 2 }, { 1, 1 }, { 0, 0, 1, 1 } },
183         { false, {-1,-1 }, { 1, 1 }, { 0, 0 }, { 0, 0, 0, 0 } },
184     };
185 
186     for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
187         clear_4x4_pixels(dstPixels);
188 
189         dstInfo = dstInfo.makeWH(gRec[i].fRequestedDstSize.width(),
190                                  gRec[i].fRequestedDstSize.height());
191         bool success = srcBM.readPixels(dstInfo, dstPixels, rowBytes,
192                                         gRec[i].fRequestedSrcLoc.x(), gRec[i].fRequestedSrcLoc.y());
193 
194         REPORTER_ASSERT(reporter, gRec[i].fExpectedSuccess == success);
195         if (success) {
196             const SkIRect srcR = gRec[i].fExpectedSrcR;
197             const int dstX = gRec[i].fExpectedDstLoc.x();
198             const int dstY = gRec[i].fExpectedDstLoc.y();
199             // Walk the dst pixels, and check if we got what we expected
200             for (int y = 0; y < H; ++y) {
201                 for (int x = 0; x < W; ++x) {
202                     SkPMColor dstC = dstPixels[y*4+x];
203                     // get into src coordinates
204                     int sx = x - dstX + srcR.x();
205                     int sy = y - dstY + srcR.y();
206                     if (srcR.contains(sx, sy)) {
207                         REPORTER_ASSERT(reporter, check_4x4_pixel(dstC, sx, sy));
208                     } else {
209                         REPORTER_ASSERT(reporter, 0 == dstC);
210                     }
211                 }
212             }
213         }
214     }
215 }
216