| 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 |