OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 #include "Test.h" | 8 #include "Test.h" |
9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
10 #include "SkRect.h" | 10 #include "SkRect.h" |
11 | 11 |
12 static const char* boolStr(bool value) { | 12 static const char* boolStr(bool value) { |
13 return value ? "true" : "false"; | 13 return value ? "true" : "false"; |
14 } | 14 } |
15 | 15 |
16 // these are in the same order as the SkBitmap::Config enum | 16 // these are in the same order as the SkBitmap::Config enum |
17 static const char* gConfigName[] = { | 17 static const char* gConfigName[] = { |
18 "None", "A1", "A8", "Index8", "565", "4444", "8888", "RLE_Index8" | 18 "None", "A8", "Index8", "565", "4444", "8888" |
19 }; | 19 }; |
20 | 20 |
21 static void report_opaqueness(skiatest::Reporter* reporter, const SkBitmap& src, | 21 static void report_opaqueness(skiatest::Reporter* reporter, const SkBitmap& src, |
22 const SkBitmap& dst) { | 22 const SkBitmap& dst) { |
23 SkString str; | 23 SkString str; |
24 str.printf("src %s opaque:%d, dst %s opaque:%d", | 24 str.printf("src %s opaque:%d, dst %s opaque:%d", |
25 gConfigName[src.config()], src.isOpaque(), | 25 gConfigName[src.config()], src.isOpaque(), |
26 gConfigName[dst.config()], dst.isOpaque()); | 26 gConfigName[dst.config()], dst.isOpaque()); |
27 reporter->reportFailed(str); | 27 reporter->reportFailed(str); |
28 } | 28 } |
(...skipping 21 matching lines...) Expand all Loading... |
50 if (srcOpaque.isOpaque() != dst.isOpaque()) { | 50 if (srcOpaque.isOpaque() != dst.isOpaque()) { |
51 report_opaqueness(reporter, srcOpaque, dst); | 51 report_opaqueness(reporter, srcOpaque, dst); |
52 } | 52 } |
53 } | 53 } |
54 | 54 |
55 static void init_src(const SkBitmap& bitmap) { | 55 static void init_src(const SkBitmap& bitmap) { |
56 SkAutoLockPixels lock(bitmap); | 56 SkAutoLockPixels lock(bitmap); |
57 if (bitmap.getPixels()) { | 57 if (bitmap.getPixels()) { |
58 if (bitmap.getColorTable()) { | 58 if (bitmap.getColorTable()) { |
59 sk_bzero(bitmap.getPixels(), bitmap.getSize()); | 59 sk_bzero(bitmap.getPixels(), bitmap.getSize()); |
60 } else if (SkBitmap::kA1_Config == bitmap.config()) { | |
61 // The A1 config can have uninitialized bits at the | |
62 // end of each row if eraseColor is used | |
63 memset(bitmap.getPixels(), 0xff, bitmap.getSafeSize()); | |
64 } else { | 60 } else { |
65 bitmap.eraseColor(SK_ColorWHITE); | 61 bitmap.eraseColor(SK_ColorWHITE); |
66 } | 62 } |
67 } | 63 } |
68 } | 64 } |
69 | 65 |
70 static SkColorTable* init_ctable(SkAlphaType alphaType) { | 66 static SkColorTable* init_ctable(SkAlphaType alphaType) { |
71 static const SkColor colors[] = { | 67 static const SkColor colors[] = { |
72 SK_ColorBLACK, SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE | 68 SK_ColorBLACK, SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE |
73 }; | 69 }; |
(...skipping 11 matching lines...) Expand all Loading... |
85 // getSkConfigName() | 81 // getSkConfigName() |
86 // struct Coordinates | 82 // struct Coordinates |
87 // reportCopyVerification() | 83 // reportCopyVerification() |
88 // writeCoordPixels() | 84 // writeCoordPixels() |
89 | 85 |
90 // Utility function to read the value of a given pixel in bm. All | 86 // Utility function to read the value of a given pixel in bm. All |
91 // values converted to uint32_t for simplification of comparisons. | 87 // values converted to uint32_t for simplification of comparisons. |
92 static uint32_t getPixel(int x, int y, const SkBitmap& bm) { | 88 static uint32_t getPixel(int x, int y, const SkBitmap& bm) { |
93 uint32_t val = 0; | 89 uint32_t val = 0; |
94 uint16_t val16; | 90 uint16_t val16; |
95 uint8_t val8, shift; | 91 uint8_t val8; |
96 SkAutoLockPixels lock(bm); | 92 SkAutoLockPixels lock(bm); |
97 const void* rawAddr = bm.getAddr(x,y); | 93 const void* rawAddr = bm.getAddr(x,y); |
98 | 94 |
99 switch (bm.config()) { | 95 switch (bm.config()) { |
100 case SkBitmap::kARGB_8888_Config: | 96 case SkBitmap::kARGB_8888_Config: |
101 memcpy(&val, rawAddr, sizeof(uint32_t)); | 97 memcpy(&val, rawAddr, sizeof(uint32_t)); |
102 break; | 98 break; |
103 case SkBitmap::kARGB_4444_Config: | 99 case SkBitmap::kARGB_4444_Config: |
104 case SkBitmap::kRGB_565_Config: | 100 case SkBitmap::kRGB_565_Config: |
105 memcpy(&val16, rawAddr, sizeof(uint16_t)); | 101 memcpy(&val16, rawAddr, sizeof(uint16_t)); |
106 val = val16; | 102 val = val16; |
107 break; | 103 break; |
108 case SkBitmap::kA8_Config: | 104 case SkBitmap::kA8_Config: |
109 case SkBitmap::kIndex8_Config: | 105 case SkBitmap::kIndex8_Config: |
110 memcpy(&val8, rawAddr, sizeof(uint8_t)); | 106 memcpy(&val8, rawAddr, sizeof(uint8_t)); |
111 val = val8; | 107 val = val8; |
112 break; | 108 break; |
113 case SkBitmap::kA1_Config: | |
114 memcpy(&val8, rawAddr, sizeof(uint8_t)); | |
115 shift = x % 8; | |
116 val = (val8 >> shift) & 0x1 ; | |
117 break; | |
118 default: | 109 default: |
119 break; | 110 break; |
120 } | 111 } |
121 return val; | 112 return val; |
122 } | 113 } |
123 | 114 |
124 // Utility function to set value of any pixel in bm. | 115 // Utility function to set value of any pixel in bm. |
125 // bm.getConfig() specifies what format 'val' must be | 116 // bm.getConfig() specifies what format 'val' must be |
126 // converted to, but at present uint32_t can handle all formats. | 117 // converted to, but at present uint32_t can handle all formats. |
127 static void setPixel(int x, int y, uint32_t val, SkBitmap& bm) { | 118 static void setPixel(int x, int y, uint32_t val, SkBitmap& bm) { |
128 uint16_t val16; | 119 uint16_t val16; |
129 uint8_t val8, shift; | 120 uint8_t val8; |
130 SkAutoLockPixels lock(bm); | 121 SkAutoLockPixels lock(bm); |
131 void* rawAddr = bm.getAddr(x,y); | 122 void* rawAddr = bm.getAddr(x,y); |
132 | 123 |
133 switch (bm.config()) { | 124 switch (bm.config()) { |
134 case SkBitmap::kARGB_8888_Config: | 125 case SkBitmap::kARGB_8888_Config: |
135 memcpy(rawAddr, &val, sizeof(uint32_t)); | 126 memcpy(rawAddr, &val, sizeof(uint32_t)); |
136 break; | 127 break; |
137 case SkBitmap::kARGB_4444_Config: | 128 case SkBitmap::kARGB_4444_Config: |
138 case SkBitmap::kRGB_565_Config: | 129 case SkBitmap::kRGB_565_Config: |
139 val16 = val & 0xFFFF; | 130 val16 = val & 0xFFFF; |
140 memcpy(rawAddr, &val16, sizeof(uint16_t)); | 131 memcpy(rawAddr, &val16, sizeof(uint16_t)); |
141 break; | 132 break; |
142 case SkBitmap::kA8_Config: | 133 case SkBitmap::kA8_Config: |
143 case SkBitmap::kIndex8_Config: | 134 case SkBitmap::kIndex8_Config: |
144 val8 = val & 0xFF; | 135 val8 = val & 0xFF; |
145 memcpy(rawAddr, &val8, sizeof(uint8_t)); | 136 memcpy(rawAddr, &val8, sizeof(uint8_t)); |
146 break; | 137 break; |
147 case SkBitmap::kA1_Config: | |
148 shift = x % 8; // We assume we're in the right byte. | |
149 memcpy(&val8, rawAddr, sizeof(uint8_t)); | |
150 if (val & 0x1) // Turn bit on. | |
151 val8 |= (0x1 << shift); | |
152 else // Turn bit off. | |
153 val8 &= ~(0x1 << shift); | |
154 memcpy(rawAddr, &val8, sizeof(uint8_t)); | |
155 break; | |
156 default: | 138 default: |
157 // Ignore. | 139 // Ignore. |
158 break; | 140 break; |
159 } | 141 } |
160 } | 142 } |
161 | 143 |
162 // Utility to return string containing name of each format, to | 144 // Utility to return string containing name of each format, to |
163 // simplify diagnostic output. | 145 // simplify diagnostic output. |
164 static const char* getSkConfigName(const SkBitmap& bm) { | 146 static const char* getSkConfigName(const SkBitmap& bm) { |
165 switch (bm.config()) { | 147 switch (bm.config()) { |
166 case SkBitmap::kNo_Config: return "SkBitmap::kNo_Config"; | 148 case SkBitmap::kNo_Config: return "SkBitmap::kNo_Config"; |
167 case SkBitmap::kA1_Config: return "SkBitmap::kA1_Config"; | |
168 case SkBitmap::kA8_Config: return "SkBitmap::kA8_Config"; | 149 case SkBitmap::kA8_Config: return "SkBitmap::kA8_Config"; |
169 case SkBitmap::kIndex8_Config: return "SkBitmap::kIndex8_Config"; | 150 case SkBitmap::kIndex8_Config: return "SkBitmap::kIndex8_Config"; |
170 case SkBitmap::kRGB_565_Config: return "SkBitmap::kRGB_565_Config"; | 151 case SkBitmap::kRGB_565_Config: return "SkBitmap::kRGB_565_Config"; |
171 case SkBitmap::kARGB_4444_Config: return "SkBitmap::kARGB_4444_Config"; | 152 case SkBitmap::kARGB_4444_Config: return "SkBitmap::kARGB_4444_Config"; |
172 case SkBitmap::kARGB_8888_Config: return "SkBitmap::kARGB_8888_Config"; | 153 case SkBitmap::kARGB_8888_Config: return "SkBitmap::kARGB_8888_Config"; |
173 default: return "Unknown SkBitmap configuration."; | 154 default: return "Unknown SkBitmap configuration."; |
174 } | 155 } |
175 } | 156 } |
176 | 157 |
177 // Helper struct to contain pixel locations, while avoiding need for STL. | 158 // Helper struct to contain pixel locations, while avoiding need for STL. |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 } | 199 } |
219 | 200 |
220 // Writes unique pixel values at locations specified by coords. | 201 // Writes unique pixel values at locations specified by coords. |
221 static void writeCoordPixels(SkBitmap& bm, const Coordinates& coords) { | 202 static void writeCoordPixels(SkBitmap& bm, const Coordinates& coords) { |
222 for (int i = 0; i < coords.length; ++i) | 203 for (int i = 0; i < coords.length; ++i) |
223 setPixel(coords[i]->fX, coords[i]->fY, i, bm); | 204 setPixel(coords[i]->fX, coords[i]->fY, i, bm); |
224 } | 205 } |
225 | 206 |
226 static void TestBitmapCopy(skiatest::Reporter* reporter) { | 207 static void TestBitmapCopy(skiatest::Reporter* reporter) { |
227 static const Pair gPairs[] = { | 208 static const Pair gPairs[] = { |
228 { SkBitmap::kNo_Config, "00000000" }, | 209 { SkBitmap::kNo_Config, "0000000" }, |
229 { SkBitmap::kA1_Config, "01000000" }, | 210 { SkBitmap::kA8_Config, "0101010" }, |
230 { SkBitmap::kA8_Config, "00101010" }, | 211 { SkBitmap::kIndex8_Config, "0111010" }, |
231 { SkBitmap::kIndex8_Config, "00111010" }, | 212 { SkBitmap::kRGB_565_Config, "0101010" }, |
232 { SkBitmap::kRGB_565_Config, "00101010" }, | 213 { SkBitmap::kARGB_4444_Config, "0101110" }, |
233 { SkBitmap::kARGB_4444_Config, "00101110" }, | 214 { SkBitmap::kARGB_8888_Config, "0101110" }, |
234 { SkBitmap::kARGB_8888_Config, "00101110" }, | |
235 }; | 215 }; |
236 | 216 |
237 static const bool isExtracted[] = { | 217 static const bool isExtracted[] = { |
238 false, true | 218 false, true |
239 }; | 219 }; |
240 | 220 |
241 const int W = 20; | 221 const int W = 20; |
242 const int H = 33; | 222 const int H = 33; |
243 | 223 |
244 for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) { | 224 for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) { |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 str.printf("getSafeSize64() negative: %s", | 348 str.printf("getSafeSize64() negative: %s", |
369 getSkConfigName(tstSafeSize)); | 349 getSkConfigName(tstSafeSize)); |
370 reporter->reportFailed(str); | 350 reporter->reportFailed(str); |
371 } | 351 } |
372 bool sizeFail = false; | 352 bool sizeFail = false; |
373 // Compare against hand-computed values. | 353 // Compare against hand-computed values. |
374 switch (gPairs[i].fConfig) { | 354 switch (gPairs[i].fConfig) { |
375 case SkBitmap::kNo_Config: | 355 case SkBitmap::kNo_Config: |
376 break; | 356 break; |
377 | 357 |
378 case SkBitmap::kA1_Config: | |
379 if (safeSize.fHi != 0x470DE || | |
380 safeSize.fLo != 0x4DF82000) | |
381 sizeFail = true; | |
382 break; | |
383 | |
384 case SkBitmap::kA8_Config: | 358 case SkBitmap::kA8_Config: |
385 case SkBitmap::kIndex8_Config: | 359 case SkBitmap::kIndex8_Config: |
386 if (safeSize.fHi != 0x2386F2 || | 360 if (safeSize.fHi != 0x2386F2 || |
387 safeSize.fLo != 0x6FC10000) | 361 safeSize.fLo != 0x6FC10000) |
388 sizeFail = true; | 362 sizeFail = true; |
389 break; | 363 break; |
390 | 364 |
391 case SkBitmap::kRGB_565_Config: | 365 case SkBitmap::kRGB_565_Config: |
392 case SkBitmap::kARGB_4444_Config: | 366 case SkBitmap::kARGB_4444_Config: |
393 if (safeSize.fHi != 0x470DE4 || | 367 if (safeSize.fHi != 0x470DE4 || |
(...skipping 10 matching lines...) Expand all Loading... |
404 default: | 378 default: |
405 break; | 379 break; |
406 } | 380 } |
407 if (sizeFail) { | 381 if (sizeFail) { |
408 SkString str; | 382 SkString str; |
409 str.printf("getSafeSize64() wrong size: %s", | 383 str.printf("getSafeSize64() wrong size: %s", |
410 getSkConfigName(tstSafeSize)); | 384 getSkConfigName(tstSafeSize)); |
411 reporter->reportFailed(str); | 385 reporter->reportFailed(str); |
412 } | 386 } |
413 | 387 |
414 int subW, subH; | 388 int subW = 2; |
415 // Set sizes to be height = 2 to force the last row of the | 389 int subH = 2; |
416 // source to be used, thus verifying correct operation if | |
417 // the bitmap is an extracted subset. | |
418 if (gPairs[i].fConfig == SkBitmap::kA1_Config) { | |
419 // If one-bit per pixel, use 9 pixels to force more than | |
420 // one byte per row. | |
421 subW = 9; | |
422 subH = 2; | |
423 } else { | |
424 // All other configurations are at least one byte per pixel, | |
425 // and different configs will test copying different numbers | |
426 // of bytes. | |
427 subW = subH = 2; | |
428 } | |
429 | 390 |
430 // Create bitmap to act as source for copies and subsets. | 391 // Create bitmap to act as source for copies and subsets. |
431 SkBitmap src, subset; | 392 SkBitmap src, subset; |
432 SkColorTable* ct = NULL; | 393 SkColorTable* ct = NULL; |
433 if (isExtracted[copyCase]) { // A larger image to extract from. | 394 if (isExtracted[copyCase]) { // A larger image to extract from. |
434 src.setConfig(gPairs[i].fConfig, 2 * subW + 1, subH); | 395 src.setConfig(gPairs[i].fConfig, 2 * subW + 1, subH); |
435 } else { // Tests expect a 2x2 bitmap, so make smaller. | 396 } else { // Tests expect a 2x2 bitmap, so make smaller. |
436 src.setConfig(gPairs[i].fConfig, subW, subH); | 397 src.setConfig(gPairs[i].fConfig, subW, subH); |
437 } | 398 } |
438 if (SkBitmap::kIndex8_Config == src.config()) { | 399 if (SkBitmap::kIndex8_Config == src.config()) { |
439 ct = init_ctable(kPremul_SkAlphaType); | 400 ct = init_ctable(kPremul_SkAlphaType); |
440 } | 401 } |
441 | 402 |
442 src.allocPixels(ct); | 403 src.allocPixels(ct); |
443 SkSafeUnref(ct); | 404 SkSafeUnref(ct); |
444 | 405 |
445 // Either copy src or extract into 'subset', which is used | 406 // Either copy src or extract into 'subset', which is used |
446 // for subsequent calls to copyPixelsTo/From. | 407 // for subsequent calls to copyPixelsTo/From. |
447 bool srcReady = false; | 408 bool srcReady = false; |
448 if (isExtracted[copyCase]) { | 409 if (isExtracted[copyCase]) { |
449 // The extractedSubset() test case allows us to test copy- | 410 // The extractedSubset() test case allows us to test copy- |
450 // ing when src and dst mave possibly different strides. | 411 // ing when src and dst mave possibly different strides. |
451 SkIRect r; | 412 SkIRect r; |
452 if (gPairs[i].fConfig == SkBitmap::kA1_Config) | 413 r.set(1, 0, 1 + subW, subH); // 2x2 extracted bitmap |
453 // This config seems to need byte-alignment of | |
454 // extracted subset bits. | |
455 r.set(0, 0, subW, subH); | |
456 else | |
457 r.set(1, 0, 1 + subW, subH); // 2x2 extracted bitmap | |
458 | 414 |
459 srcReady = src.extractSubset(&subset, r); | 415 srcReady = src.extractSubset(&subset, r); |
460 } else { | 416 } else { |
461 srcReady = src.copyTo(&subset, src.config()); | 417 srcReady = src.copyTo(&subset, src.config()); |
462 } | 418 } |
463 | 419 |
464 // Not all configurations will generate a valid 'subset'. | 420 // Not all configurations will generate a valid 'subset'. |
465 if (srcReady) { | 421 if (srcReady) { |
466 | 422 |
467 // Allocate our target buffer 'buf' for all copies. | 423 // Allocate our target buffer 'buf' for all copies. |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 false); | 546 false); |
591 | 547 |
592 #endif | 548 #endif |
593 } | 549 } |
594 } // for (size_t copyCase ... | 550 } // for (size_t copyCase ... |
595 } | 551 } |
596 } | 552 } |
597 | 553 |
598 #include "TestClassDef.h" | 554 #include "TestClassDef.h" |
599 DEFINE_TESTCLASS("BitmapCopy", TestBitmapCopyClass, TestBitmapCopy) | 555 DEFINE_TESTCLASS("BitmapCopy", TestBitmapCopyClass, TestBitmapCopy) |
OLD | NEW |