| 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" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 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 } |
| 29 | 29 |
| 30 static bool canHaveAlpha(SkBitmap::Config config) { | 30 static bool canHaveAlpha(SkBitmap::Config config) { |
| 31 return config != SkBitmap::kRGB_565_Config; | 31 return config != SkBitmap::kRGB_565_Config; |
| 32 } | 32 } |
| 33 | 33 |
| 34 // copyTo() should preserve isOpaque when it makes sense | 34 // copyTo() should preserve isOpaque when it makes sense |
| 35 static void test_isOpaque(skiatest::Reporter* reporter, const SkBitmap& src, | 35 static void test_isOpaque(skiatest::Reporter* reporter, |
| 36 const SkBitmap& srcOpaque, const SkBitmap& srcPremul, |
| 36 SkBitmap::Config dstConfig) { | 37 SkBitmap::Config dstConfig) { |
| 37 SkBitmap bitmap(src); | |
| 38 SkBitmap dst; | 38 SkBitmap dst; |
| 39 | 39 |
| 40 // we need the lock so that we get a valid colorTable (when available) | 40 if (canHaveAlpha(srcPremul.config()) && canHaveAlpha(dstConfig)) { |
| 41 SkAutoLockPixels alp(bitmap); | 41 REPORTER_ASSERT(reporter, srcPremul.copyTo(&dst, dstConfig)); |
| 42 SkColorTable* ctable = bitmap.getColorTable(); | |
| 43 unsigned ctableFlags = ctable ? ctable->getFlags() : 0; | |
| 44 | |
| 45 if (canHaveAlpha(bitmap.config()) && canHaveAlpha(dstConfig)) { | |
| 46 bitmap.setIsOpaque(false); | |
| 47 if (ctable) { | |
| 48 ctable->setFlags(ctableFlags & ~SkColorTable::kColorsAreOpaque_Flag)
; | |
| 49 } | |
| 50 REPORTER_ASSERT(reporter, bitmap.copyTo(&dst, dstConfig)); | |
| 51 REPORTER_ASSERT(reporter, dst.config() == dstConfig); | 42 REPORTER_ASSERT(reporter, dst.config() == dstConfig); |
| 52 if (bitmap.isOpaque() != dst.isOpaque()) { | 43 if (srcPremul.isOpaque() != dst.isOpaque()) { |
| 53 report_opaqueness(reporter, bitmap, dst); | 44 report_opaqueness(reporter, srcPremul, dst); |
| 54 } | 45 } |
| 55 } | 46 } |
| 56 | 47 |
| 57 bitmap.setIsOpaque(true); | 48 REPORTER_ASSERT(reporter, srcOpaque.copyTo(&dst, dstConfig)); |
| 58 if (ctable) { | |
| 59 ctable->setFlags(ctableFlags | SkColorTable::kColorsAreOpaque_Flag); | |
| 60 } | |
| 61 REPORTER_ASSERT(reporter, bitmap.copyTo(&dst, dstConfig)); | |
| 62 REPORTER_ASSERT(reporter, dst.config() == dstConfig); | 49 REPORTER_ASSERT(reporter, dst.config() == dstConfig); |
| 63 if (bitmap.isOpaque() != dst.isOpaque()) { | 50 if (srcOpaque.isOpaque() != dst.isOpaque()) { |
| 64 report_opaqueness(reporter, bitmap, dst); | 51 report_opaqueness(reporter, srcOpaque, dst); |
| 65 } | |
| 66 | |
| 67 if (ctable) { | |
| 68 ctable->setFlags(ctableFlags); | |
| 69 } | 52 } |
| 70 } | 53 } |
| 71 | 54 |
| 72 static void init_src(const SkBitmap& bitmap, const SkColorTable* ct) { | 55 static void init_src(const SkBitmap& bitmap) { |
| 73 SkAutoLockPixels lock(bitmap); | 56 SkAutoLockPixels lock(bitmap); |
| 74 if (bitmap.getPixels()) { | 57 if (bitmap.getPixels()) { |
| 75 if (ct) { | 58 if (bitmap.getColorTable()) { |
| 76 sk_bzero(bitmap.getPixels(), bitmap.getSize()); | 59 sk_bzero(bitmap.getPixels(), bitmap.getSize()); |
| 77 } else { | 60 } else { |
| 78 bitmap.eraseColor(SK_ColorWHITE); | 61 bitmap.eraseColor(SK_ColorWHITE); |
| 79 } | 62 } |
| 80 } | 63 } |
| 81 } | 64 } |
| 82 | 65 |
| 83 static SkColorTable* init_ctable() { | 66 static SkColorTable* init_ctable(SkAlphaType alphaType) { |
| 84 static const SkColor colors[] = { | 67 static const SkColor colors[] = { |
| 85 SK_ColorBLACK, SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE | 68 SK_ColorBLACK, SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE |
| 86 }; | 69 }; |
| 87 return new SkColorTable(colors, SK_ARRAY_COUNT(colors)); | 70 return new SkColorTable(colors, SK_ARRAY_COUNT(colors), alphaType); |
| 88 } | 71 } |
| 89 | 72 |
| 90 struct Pair { | 73 struct Pair { |
| 91 SkBitmap::Config fConfig; | 74 SkBitmap::Config fConfig; |
| 92 const char* fValid; | 75 const char* fValid; |
| 93 }; | 76 }; |
| 94 | 77 |
| 95 // Utility functions for copyPixelsTo()/copyPixelsFrom() tests. | 78 // Utility functions for copyPixelsTo()/copyPixelsFrom() tests. |
| 96 // getPixel() | 79 // getPixel() |
| 97 // setPixel() | 80 // setPixel() |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 | 232 |
| 250 static const bool isExtracted[] = { | 233 static const bool isExtracted[] = { |
| 251 false, true | 234 false, true |
| 252 }; | 235 }; |
| 253 | 236 |
| 254 const int W = 20; | 237 const int W = 20; |
| 255 const int H = 33; | 238 const int H = 33; |
| 256 | 239 |
| 257 for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) { | 240 for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) { |
| 258 for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) { | 241 for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) { |
| 259 SkBitmap src, dst; | 242 SkBitmap srcOpaque, srcPremul, dst; |
| 260 SkColorTable* ct = NULL; | 243 |
| 244 { |
| 245 SkColorTable* ctOpaque = NULL; |
| 246 SkColorTable* ctPremul = NULL; |
| 261 | 247 |
| 262 src.setConfig(gPairs[i].fConfig, W, H); | 248 srcOpaque.setConfig(gPairs[i].fConfig, W, H); |
| 263 if (SkBitmap::kIndex8_Config == src.config()) { | 249 srcPremul.setConfig(gPairs[i].fConfig, W, H); |
| 264 ct = init_ctable(); | 250 if (SkBitmap::kIndex8_Config == gPairs[i].fConfig) { |
| 251 ctOpaque = init_ctable(kOpaque_SkAlphaType); |
| 252 ctPremul = init_ctable(kPremul_SkAlphaType); |
| 253 } |
| 254 srcOpaque.allocPixels(ctOpaque); |
| 255 srcPremul.allocPixels(ctPremul); |
| 256 SkSafeUnref(ctOpaque); |
| 257 SkSafeUnref(ctPremul); |
| 258 |
| 259 srcOpaque.setIsOpaque(true); |
| 260 srcPremul.setIsOpaque(false); |
| 265 } | 261 } |
| 266 src.allocPixels(ct); | 262 init_src(srcOpaque); |
| 267 SkSafeUnref(ct); | 263 init_src(srcPremul); |
| 268 | 264 |
| 269 init_src(src, ct); | 265 bool success = srcPremul.copyTo(&dst, gPairs[j].fConfig); |
| 270 bool success = src.copyTo(&dst, gPairs[j].fConfig); | |
| 271 bool expected = gPairs[i].fValid[j] != '0'; | 266 bool expected = gPairs[i].fValid[j] != '0'; |
| 272 if (success != expected) { | 267 if (success != expected) { |
| 273 SkString str; | 268 SkString str; |
| 274 str.printf("SkBitmap::copyTo from %s to %s. expected %s returned
%s", | 269 str.printf("SkBitmap::copyTo from %s to %s. expected %s returned
%s", |
| 275 gConfigName[i], gConfigName[j], boolStr(expected), | 270 gConfigName[i], gConfigName[j], boolStr(expected), |
| 276 boolStr(success)); | 271 boolStr(success)); |
| 277 reporter->reportFailed(str); | 272 reporter->reportFailed(str); |
| 278 } | 273 } |
| 279 | 274 |
| 280 bool canSucceed = src.canCopyTo(gPairs[j].fConfig); | 275 bool canSucceed = srcPremul.canCopyTo(gPairs[j].fConfig); |
| 281 if (success != canSucceed) { | 276 if (success != canSucceed) { |
| 282 SkString str; | 277 SkString str; |
| 283 str.printf("SkBitmap::copyTo from %s to %s. returned %s canCopyT
o %s", | 278 str.printf("SkBitmap::copyTo from %s to %s. returned %s canCopyT
o %s", |
| 284 gConfigName[i], gConfigName[j], boolStr(success), | 279 gConfigName[i], gConfigName[j], boolStr(success), |
| 285 boolStr(canSucceed)); | 280 boolStr(canSucceed)); |
| 286 reporter->reportFailed(str); | 281 reporter->reportFailed(str); |
| 287 } | 282 } |
| 288 | 283 |
| 289 if (success) { | 284 if (success) { |
| 290 REPORTER_ASSERT(reporter, src.width() == dst.width()); | 285 REPORTER_ASSERT(reporter, srcPremul.width() == dst.width()); |
| 291 REPORTER_ASSERT(reporter, src.height() == dst.height()); | 286 REPORTER_ASSERT(reporter, srcPremul.height() == dst.height()); |
| 292 REPORTER_ASSERT(reporter, dst.config() == gPairs[j].fConfig); | 287 REPORTER_ASSERT(reporter, dst.config() == gPairs[j].fConfig); |
| 293 test_isOpaque(reporter, src, dst.config()); | 288 test_isOpaque(reporter, srcOpaque, srcPremul, dst.config()); |
| 294 if (src.config() == dst.config()) { | 289 if (srcPremul.config() == dst.config()) { |
| 295 SkAutoLockPixels srcLock(src); | 290 SkAutoLockPixels srcLock(srcPremul); |
| 296 SkAutoLockPixels dstLock(dst); | 291 SkAutoLockPixels dstLock(dst); |
| 297 REPORTER_ASSERT(reporter, src.readyToDraw()); | 292 REPORTER_ASSERT(reporter, srcPremul.readyToDraw()); |
| 298 REPORTER_ASSERT(reporter, dst.readyToDraw()); | 293 REPORTER_ASSERT(reporter, dst.readyToDraw()); |
| 299 const char* srcP = (const char*)src.getAddr(0, 0); | 294 const char* srcP = (const char*)srcPremul.getAddr(0, 0); |
| 300 const char* dstP = (const char*)dst.getAddr(0, 0); | 295 const char* dstP = (const char*)dst.getAddr(0, 0); |
| 301 REPORTER_ASSERT(reporter, srcP != dstP); | 296 REPORTER_ASSERT(reporter, srcP != dstP); |
| 302 REPORTER_ASSERT(reporter, !memcmp(srcP, dstP, | 297 REPORTER_ASSERT(reporter, !memcmp(srcP, dstP, |
| 303 src.getSize())); | 298 srcPremul.getSize())); |
| 304 REPORTER_ASSERT(reporter, src.getGenerationID() == dst.getGe
nerationID()); | 299 REPORTER_ASSERT(reporter, srcPremul.getGenerationID() == dst
.getGenerationID()); |
| 305 } else { | 300 } else { |
| 306 REPORTER_ASSERT(reporter, src.getGenerationID() != dst.getGe
nerationID()); | 301 REPORTER_ASSERT(reporter, srcPremul.getGenerationID() != dst
.getGenerationID()); |
| 307 } | 302 } |
| 308 // test extractSubset | 303 // test extractSubset |
| 309 { | 304 { |
| 310 SkBitmap bitmap(src); | 305 SkBitmap bitmap(srcOpaque); |
| 311 SkBitmap subset; | 306 SkBitmap subset; |
| 312 SkIRect r; | 307 SkIRect r; |
| 313 r.set(1, 1, 2, 2); | 308 r.set(1, 1, 2, 2); |
| 314 bitmap.setIsOpaque(true); | |
| 315 bitmap.setIsVolatile(true); | 309 bitmap.setIsVolatile(true); |
| 316 if (bitmap.extractSubset(&subset, r)) { | 310 if (bitmap.extractSubset(&subset, r)) { |
| 317 REPORTER_ASSERT(reporter, subset.width() == 1); | 311 REPORTER_ASSERT(reporter, subset.width() == 1); |
| 318 REPORTER_ASSERT(reporter, subset.height() == 1); | 312 REPORTER_ASSERT(reporter, subset.height() == 1); |
| 319 REPORTER_ASSERT(reporter, | 313 REPORTER_ASSERT(reporter, |
| 320 subset.isOpaque() == bitmap.isOpaque()); | 314 subset.isOpaque() == bitmap.isOpaque()); |
| 321 REPORTER_ASSERT(reporter, | 315 REPORTER_ASSERT(reporter, |
| 322 subset.isVolatile() == true); | 316 subset.isVolatile() == true); |
| 323 | 317 |
| 324 SkBitmap copy; | 318 SkBitmap copy; |
| 325 REPORTER_ASSERT(reporter, | 319 REPORTER_ASSERT(reporter, |
| 326 subset.copyTo(©, subset.config())); | 320 subset.copyTo(©, subset.config())); |
| 327 REPORTER_ASSERT(reporter, copy.width() == 1); | 321 REPORTER_ASSERT(reporter, copy.width() == 1); |
| 328 REPORTER_ASSERT(reporter, copy.height() == 1); | 322 REPORTER_ASSERT(reporter, copy.height() == 1); |
| 329 REPORTER_ASSERT(reporter, copy.rowBytes() <= 4); | 323 REPORTER_ASSERT(reporter, copy.rowBytes() <= 4); |
| 330 | 324 |
| 331 SkAutoLockPixels alp0(subset); | 325 SkAutoLockPixels alp0(subset); |
| 332 SkAutoLockPixels alp1(copy); | 326 SkAutoLockPixels alp1(copy); |
| 333 // they should both have, or both not-have, a colortable | 327 // they should both have, or both not-have, a colortable |
| 334 bool hasCT = subset.getColorTable() != NULL; | 328 bool hasCT = subset.getColorTable() != NULL; |
| 335 REPORTER_ASSERT(reporter, | 329 REPORTER_ASSERT(reporter, |
| 336 (copy.getColorTable() != NULL) == hasCT); | 330 (copy.getColorTable() != NULL) == hasCT); |
| 337 } | 331 } |
| 338 bitmap.setIsOpaque(false); | 332 |
| 333 bitmap = srcPremul; |
| 339 bitmap.setIsVolatile(false); | 334 bitmap.setIsVolatile(false); |
| 340 if (bitmap.extractSubset(&subset, r)) { | 335 if (bitmap.extractSubset(&subset, r)) { |
| 341 REPORTER_ASSERT(reporter, | 336 REPORTER_ASSERT(reporter, |
| 342 subset.isOpaque() == bitmap.isOpaque()); | 337 subset.isOpaque() == bitmap.isOpaque()); |
| 343 REPORTER_ASSERT(reporter, | 338 REPORTER_ASSERT(reporter, |
| 344 subset.isVolatile() == false); | 339 subset.isVolatile() == false); |
| 345 } | 340 } |
| 346 } | 341 } |
| 347 } else { | 342 } else { |
| 348 // dst should be unchanged from its initial state | 343 // dst should be unchanged from its initial state |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 | 429 |
| 435 // Create bitmap to act as source for copies and subsets. | 430 // Create bitmap to act as source for copies and subsets. |
| 436 SkBitmap src, subset; | 431 SkBitmap src, subset; |
| 437 SkColorTable* ct = NULL; | 432 SkColorTable* ct = NULL; |
| 438 if (isExtracted[copyCase]) { // A larger image to extract from. | 433 if (isExtracted[copyCase]) { // A larger image to extract from. |
| 439 src.setConfig(gPairs[i].fConfig, 2 * subW + 1, subH); | 434 src.setConfig(gPairs[i].fConfig, 2 * subW + 1, subH); |
| 440 } else { // Tests expect a 2x2 bitmap, so make smaller. | 435 } else { // Tests expect a 2x2 bitmap, so make smaller. |
| 441 src.setConfig(gPairs[i].fConfig, subW, subH); | 436 src.setConfig(gPairs[i].fConfig, subW, subH); |
| 442 } | 437 } |
| 443 if (SkBitmap::kIndex8_Config == src.config()) { | 438 if (SkBitmap::kIndex8_Config == src.config()) { |
| 444 ct = init_ctable(); | 439 ct = init_ctable(kPremul_SkAlphaType); |
| 445 } | 440 } |
| 446 | 441 |
| 447 src.allocPixels(ct); | 442 src.allocPixels(ct); |
| 448 SkSafeUnref(ct); | 443 SkSafeUnref(ct); |
| 449 | 444 |
| 450 // Either copy src or extract into 'subset', which is used | 445 // Either copy src or extract into 'subset', which is used |
| 451 // for subsequent calls to copyPixelsTo/From. | 446 // for subsequent calls to copyPixelsTo/From. |
| 452 bool srcReady = false; | 447 bool srcReady = false; |
| 453 if (isExtracted[copyCase]) { | 448 if (isExtracted[copyCase]) { |
| 454 // The extractedSubset() test case allows us to test copy- | 449 // The extractedSubset() test case allows us to test copy- |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 596 false); | 591 false); |
| 597 | 592 |
| 598 #endif | 593 #endif |
| 599 } | 594 } |
| 600 } // for (size_t copyCase ... | 595 } // for (size_t copyCase ... |
| 601 } | 596 } |
| 602 } | 597 } |
| 603 | 598 |
| 604 #include "TestClassDef.h" | 599 #include "TestClassDef.h" |
| 605 DEFINE_TESTCLASS("BitmapCopy", TestBitmapCopyClass, TestBitmapCopy) | 600 DEFINE_TESTCLASS("BitmapCopy", TestBitmapCopyClass, TestBitmapCopy) |
| OLD | NEW |