1 #include "Test.h" 2 #include "SkBitmap.h" 3 #include "SkRect.h" 4 5 static const char* boolStr(bool value) { 6 return value ? "true" : "false"; 7 } 8 9 // these are in the same order as the SkBitmap::Config enum 10 static const char* gConfigName[] = { 11 "None", "A1", "A8", "Index8", "565", "4444", "8888", "RLE_Index8" 12 }; 13 14 static void report_opaqueness(skiatest::Reporter* reporter, const SkBitmap& src, 15 const SkBitmap& dst) { 16 SkString str; 17 str.printf("src %s opaque:%d, dst %s opaque:%d", 18 gConfigName[src.config()], src.isOpaque(), 19 gConfigName[dst.config()], dst.isOpaque()); 20 reporter->reportFailed(str); 21 } 22 23 static bool canHaveAlpha(SkBitmap::Config config) { 24 return config != SkBitmap::kRGB_565_Config; 25 } 26 27 // copyTo() should preserve isOpaque when it makes sense 28 static void test_isOpaque(skiatest::Reporter* reporter, const SkBitmap& src, 29 SkBitmap::Config dstConfig) { 30 SkBitmap bitmap(src); 31 SkBitmap dst; 32 33 // we need the lock so that we get a valid colorTable (when available) 34 SkAutoLockPixels alp(bitmap); 35 SkColorTable* ctable = bitmap.getColorTable(); 36 unsigned ctableFlags = ctable ? ctable->getFlags() : 0; 37 38 if (canHaveAlpha(bitmap.config()) && canHaveAlpha(dstConfig)) { 39 bitmap.setIsOpaque(false); 40 if (ctable) { 41 ctable->setFlags(ctableFlags & ~SkColorTable::kColorsAreOpaque_Flag); 42 } 43 REPORTER_ASSERT(reporter, bitmap.copyTo(&dst, dstConfig)); 44 REPORTER_ASSERT(reporter, dst.config() == dstConfig); 45 if (bitmap.isOpaque() != dst.isOpaque()) { 46 report_opaqueness(reporter, bitmap, dst); 47 } 48 } 49 50 bitmap.setIsOpaque(true); 51 if (ctable) { 52 ctable->setFlags(ctableFlags | SkColorTable::kColorsAreOpaque_Flag); 53 } 54 REPORTER_ASSERT(reporter, bitmap.copyTo(&dst, dstConfig)); 55 REPORTER_ASSERT(reporter, dst.config() == dstConfig); 56 if (bitmap.isOpaque() != dst.isOpaque()) { 57 report_opaqueness(reporter, bitmap, dst); 58 } 59 60 if (ctable) { 61 ctable->setFlags(ctableFlags); 62 } 63 } 64 65 static void init_src(const SkBitmap& bitmap) { 66 SkAutoLockPixels lock(bitmap); 67 if (bitmap.getPixels()) { 68 memset(bitmap.getPixels(), 4, bitmap.getSize()); 69 } 70 } 71 72 SkColorTable* init_ctable() { 73 static const SkColor colors[] = { 74 SK_ColorBLACK, SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE, SK_ColorWHITE 75 }; 76 return new SkColorTable(colors, SK_ARRAY_COUNT(colors)); 77 } 78 79 struct Pair { 80 SkBitmap::Config fConfig; 81 const char* fValid; 82 }; 83 84 static void TestBitmapCopy(skiatest::Reporter* reporter) { 85 static const Pair gPairs[] = { 86 { SkBitmap::kNo_Config, "00000000" }, 87 { SkBitmap::kA1_Config, "01000000" }, 88 { SkBitmap::kA8_Config, "00101110" }, 89 { SkBitmap::kIndex8_Config, "00111110" }, 90 { SkBitmap::kRGB_565_Config, "00101110" }, 91 { SkBitmap::kARGB_4444_Config, "00101110" }, 92 { SkBitmap::kARGB_8888_Config, "00101110" }, 93 // TODO: create valid RLE bitmap to test with 94 // { SkBitmap::kRLE_Index8_Config, "00101111" } 95 }; 96 97 const int W = 20; 98 const int H = 33; 99 100 for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) { 101 for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) { 102 SkBitmap src, dst; 103 SkColorTable* ct = NULL; 104 105 src.setConfig(gPairs[i].fConfig, W, H); 106 if (SkBitmap::kIndex8_Config == src.config() || 107 SkBitmap::kRLE_Index8_Config == src.config()) { 108 ct = init_ctable(); 109 } 110 src.allocPixels(ct); 111 SkSafeUnref(ct); 112 113 init_src(src); 114 bool success = src.copyTo(&dst, gPairs[j].fConfig); 115 bool expected = gPairs[i].fValid[j] != '0'; 116 if (success != expected) { 117 SkString str; 118 str.printf("SkBitmap::copyTo from %s to %s. expected %s returned %s", 119 gConfigName[i], gConfigName[j], boolStr(expected), 120 boolStr(success)); 121 reporter->reportFailed(str); 122 } 123 124 bool canSucceed = src.canCopyTo(gPairs[j].fConfig); 125 if (success != canSucceed) { 126 SkString str; 127 str.printf("SkBitmap::copyTo from %s to %s. returned %s canCopyTo %s", 128 gConfigName[i], gConfigName[j], boolStr(success), 129 boolStr(canSucceed)); 130 reporter->reportFailed(str); 131 } 132 133 if (success) { 134 REPORTER_ASSERT(reporter, src.width() == dst.width()); 135 REPORTER_ASSERT(reporter, src.height() == dst.height()); 136 REPORTER_ASSERT(reporter, dst.config() == gPairs[j].fConfig); 137 test_isOpaque(reporter, src, dst.config()); 138 if (src.config() == dst.config()) { 139 SkAutoLockPixels srcLock(src); 140 SkAutoLockPixels dstLock(dst); 141 REPORTER_ASSERT(reporter, src.readyToDraw()); 142 REPORTER_ASSERT(reporter, dst.readyToDraw()); 143 const char* srcP = (const char*)src.getAddr(0, 0); 144 const char* dstP = (const char*)dst.getAddr(0, 0); 145 REPORTER_ASSERT(reporter, srcP != dstP); 146 REPORTER_ASSERT(reporter, !memcmp(srcP, dstP, 147 src.getSize())); 148 } 149 // test extractSubset 150 { 151 SkBitmap subset; 152 SkIRect r; 153 r.set(1, 1, 2, 2); 154 if (src.extractSubset(&subset, r)) { 155 REPORTER_ASSERT(reporter, subset.width() == 1); 156 REPORTER_ASSERT(reporter, subset.height() == 1); 157 158 SkBitmap copy; 159 REPORTER_ASSERT(reporter, 160 subset.copyTo(©, subset.config())); 161 REPORTER_ASSERT(reporter, copy.width() == 1); 162 REPORTER_ASSERT(reporter, copy.height() == 1); 163 REPORTER_ASSERT(reporter, copy.rowBytes() <= 4); 164 165 SkAutoLockPixels alp0(subset); 166 SkAutoLockPixels alp1(copy); 167 // they should both have, or both not-have, a colortable 168 bool hasCT = subset.getColorTable() != NULL; 169 REPORTER_ASSERT(reporter, 170 (copy.getColorTable() != NULL) == hasCT); 171 } 172 } 173 } else { 174 // dst should be unchanged from its initial state 175 REPORTER_ASSERT(reporter, dst.config() == SkBitmap::kNo_Config); 176 REPORTER_ASSERT(reporter, dst.width() == 0); 177 REPORTER_ASSERT(reporter, dst.height() == 0); 178 } 179 } 180 } 181 } 182 183 #include "TestClassDef.h" 184 DEFINE_TESTCLASS("BitmapCopy", TestBitmapCopyClass, TestBitmapCopy) 185