blob: 2ae7b0af50f422b5b6e182c3c92f7046848d25e4 [file] [log] [blame]
reed@android.com42263962009-05-01 04:00:01 +00001#include "Test.h"
2#include "SkBitmap.h"
reed@android.com311c82d2009-05-05 23:13:23 +00003#include "SkRect.h"
reed@android.com42263962009-05-01 04:00:01 +00004
5static const char* boolStr(bool value) {
6 return value ? "true" : "false";
7}
8
9// these are in the same order as the SkBitmap::Config enum
10static const char* gConfigName[] = {
11 "None", "A1", "A8", "Index8", "565", "4444", "8888", "RLE_Index8"
12};
13
reed@android.comcafc9f92009-08-22 03:44:57 +000014static 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
23static bool canHaveAlpha(SkBitmap::Config config) {
24 return config != SkBitmap::kRGB_565_Config;
25}
26
27// copyTo() should preserve isOpaque when it makes sense
28static 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
reed@android.com42263962009-05-01 04:00:01 +000065static void init_src(const SkBitmap& bitmap) {
weita@google.comf9ab99a2009-05-03 18:23:30 +000066 SkAutoLockPixels lock(bitmap);
reed@android.com42263962009-05-01 04:00:01 +000067 if (bitmap.getPixels()) {
68 memset(bitmap.getPixels(), 4, bitmap.getSize());
69 }
70}
71
72SkColorTable* 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
79struct Pair {
80 SkBitmap::Config fConfig;
81 const char* fValid;
82};
83
84static void TestBitmapCopy(skiatest::Reporter* reporter) {
85 static const Pair gPairs[] = {
86 { SkBitmap::kNo_Config, "00000000" },
weita@google.comf9ab99a2009-05-03 18:23:30 +000087 { SkBitmap::kA1_Config, "01000000" },
reed@android.com42263962009-05-01 04:00:01 +000088 { 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" },
reed@android.comfbaa88d2009-05-06 17:44:34 +000093// TODO: create valid RLE bitmap to test with
94 // { SkBitmap::kRLE_Index8_Config, "00101111" }
reed@android.com42263962009-05-01 04:00:01 +000095 };
weita@google.comf9ab99a2009-05-03 18:23:30 +000096
reed@android.com42263962009-05-01 04:00:01 +000097 const int W = 20;
98 const int H = 33;
weita@google.comf9ab99a2009-05-03 18:23:30 +000099
reed@android.com42263962009-05-01 04:00:01 +0000100 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;
weita@google.comf9ab99a2009-05-03 18:23:30 +0000104
reed@android.com42263962009-05-01 04:00:01 +0000105 src.setConfig(gPairs[i].fConfig, W, H);
reed@android.comfbaa88d2009-05-06 17:44:34 +0000106 if (SkBitmap::kIndex8_Config == src.config() ||
107 SkBitmap::kRLE_Index8_Config == src.config()) {
reed@android.com42263962009-05-01 04:00:01 +0000108 ct = init_ctable();
109 }
110 src.allocPixels(ct);
111 ct->safeRef();
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 }
reed@android.comfbaa88d2009-05-06 17:44:34 +0000123
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 }
weita@google.comf9ab99a2009-05-03 18:23:30 +0000132
reed@android.com42263962009-05-01 04:00:01 +0000133 if (success) {
134 REPORTER_ASSERT(reporter, src.width() == dst.width());
135 REPORTER_ASSERT(reporter, src.height() == dst.height());
weita@google.comf9ab99a2009-05-03 18:23:30 +0000136 REPORTER_ASSERT(reporter, dst.config() == gPairs[j].fConfig);
reed@android.comcafc9f92009-08-22 03:44:57 +0000137 test_isOpaque(reporter, src, dst.config());
reed@android.com42263962009-05-01 04:00:01 +0000138 if (src.config() == dst.config()) {
weita@google.comf9ab99a2009-05-03 18:23:30 +0000139 SkAutoLockPixels srcLock(src);
reed@android.com42263962009-05-01 04:00:01 +0000140 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 }
reed@android.com311c82d2009-05-05 23:13:23 +0000149 // 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(&copy, 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 }
reed@android.com42263962009-05-01 04:00:01 +0000173 } 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"
184DEFINE_TESTCLASS("BitmapCopy", TestBitmapCopyClass, TestBitmapCopy)