blob: 3bcf43746c331f1ddf2f6935a0ad9df2487b7556 [file] [log] [blame]
reed@android.com00dae862009-06-10 15:38:48 +00001#include "gm.h"
reed@android.comb9b9a182009-07-08 02:54:47 +00002#include "SkColorPriv.h"
reed@android.com8015dd82009-06-21 00:49:18 +00003#include "SkGraphics.h"
4#include "SkImageDecoder.h"
5#include "SkImageEncoder.h"
reed@google.com07700442010-12-20 19:46:07 +00006#include "SkStream.h"
7#include "SkRefCnt.h"
8
9#ifdef SK_SUPPORT_PDF
10 #include "SkPDFDevice.h"
11 #include "SkPDFDocument.h"
12#endif
reed@android.com00dae862009-06-10 15:38:48 +000013
14using namespace skiagm;
15
16// need to explicitly declare this, or we get some weird infinite loop llist
17template GMRegistry* GMRegistry::gHead;
18
19class Iter {
20public:
21 Iter() {
reed@android.comdd0ac282009-06-20 02:38:16 +000022 fReg = GMRegistry::Head();
reed@android.com00dae862009-06-10 15:38:48 +000023 }
24
reed@android.comdd0ac282009-06-20 02:38:16 +000025 GM* next() {
reed@android.com00dae862009-06-10 15:38:48 +000026 if (fReg) {
reed@android.comdd0ac282009-06-20 02:38:16 +000027 GMRegistry::Factory fact = fReg->factory();
reed@android.com00dae862009-06-10 15:38:48 +000028 fReg = fReg->next();
reed@android.comdd0ac282009-06-20 02:38:16 +000029 return fact(0);
reed@android.com00dae862009-06-10 15:38:48 +000030 }
31 return NULL;
32 }
33
34 static int Count() {
reed@android.comdd0ac282009-06-20 02:38:16 +000035 const GMRegistry* reg = GMRegistry::Head();
reed@android.com00dae862009-06-10 15:38:48 +000036 int count = 0;
37 while (reg) {
38 count += 1;
39 reg = reg->next();
40 }
41 return count;
42 }
43
44private:
45 const GMRegistry* fReg;
46};
47
reed@android.com8015dd82009-06-21 00:49:18 +000048static SkString make_name(const char shortName[], const char configName[]) {
49 SkString name(shortName);
50 name.appendf("_%s", configName);
51 return name;
52}
53
reed@google.com07700442010-12-20 19:46:07 +000054static SkString make_filename(const char path[], const SkString& name, const char suffix[]) {
reed@android.com8015dd82009-06-21 00:49:18 +000055 SkString filename(path);
56 if (filename.size() && filename[filename.size() - 1] != '/') {
57 filename.append("/");
reed@android.com00dae862009-06-10 15:38:48 +000058 }
reed@google.com07700442010-12-20 19:46:07 +000059 filename.appendf("%s.%s", name.c_str(), suffix);
reed@android.com8015dd82009-06-21 00:49:18 +000060 return filename;
61}
62
reed@android.comb9b9a182009-07-08 02:54:47 +000063/* since PNG insists on unpremultiplying our alpha, we take no precision chances
64 and force all pixels to be 100% opaque, otherwise on compare we may not get
65 a perfect match.
66 */
67static void force_all_opaque(const SkBitmap& bitmap) {
68 SkAutoLockPixels lock(bitmap);
69 for (int y = 0; y < bitmap.height(); y++) {
70 for (int x = 0; x < bitmap.width(); x++) {
71 *bitmap.getAddr32(x, y) |= (SK_A32_MASK << SK_A32_SHIFT);
72 }
73 }
74}
75
76static bool write_bitmap(const SkString& path, const SkBitmap& bitmap) {
77 SkBitmap copy;
78 bitmap.copyTo(&copy, SkBitmap::kARGB_8888_Config);
79 force_all_opaque(copy);
80 return SkImageEncoder::EncodeFile(path.c_str(), copy,
81 SkImageEncoder::kPNG_Type, 100);
82}
83
reed@android.com8015dd82009-06-21 00:49:18 +000084static void compare(const SkBitmap& target, const SkBitmap& base,
85 const SkString& name) {
reed@android.comb9b9a182009-07-08 02:54:47 +000086 SkBitmap copy;
87 const SkBitmap* bm = &target;
88 if (target.config() != SkBitmap::kARGB_8888_Config) {
89 target.copyTo(&copy, SkBitmap::kARGB_8888_Config);
90 bm = &copy;
91 }
92
93 force_all_opaque(*bm);
94
95 const int w = bm->width();
96 const int h = bm->height();
97 if (w != base.width() || h != base.height()) {
98 SkDebugf("---- dimensions mismatch for %s base [%d %d] current [%d %d]\n",
99 name.c_str(), base.width(), base.height(), w, h);
100 return;
101 }
102
103 SkAutoLockPixels bmLock(*bm);
104 SkAutoLockPixels baseLock(base);
105
106 for (int y = 0; y < h; y++) {
107 for (int x = 0; x < w; x++) {
108 SkPMColor c0 = *base.getAddr32(x, y);
109 SkPMColor c1 = *bm->getAddr32(x, y);
110 if (c0 != c1) {
111 SkDebugf("----- pixel mismatch for %s at [%d %d] base 0x%08X current 0x%08X\n",
112 name.c_str(), x, y, c0, c1);
113 return;
114 }
115 }
116 }
reed@android.com8015dd82009-06-21 00:49:18 +0000117}
reed@android.com00dae862009-06-10 15:38:48 +0000118
reed@google.com07700442010-12-20 19:46:07 +0000119static void write_pdf(GM* gm, const char writePath[]) {
120#ifdef SK_SUPPORT_PDF
121 SkISize size = gm->getISize();
122 SkPDFDevice* dev = new SkPDFDevice(size.width(), size.height());
123 SkAutoUnref aur(dev);
124
125 {
126 SkCanvas c(dev);
127 gm->draw(&c);
128 }
129
130 SkDynamicMemoryWStream output;
131 SkPDFDocument doc;
132 doc.appendPage(dev);
133 doc.emitPDF(&output);
134
135 SkString shortName(gm->shortName());
136 SkString path = make_filename(writePath, shortName, "pdf");
137 SkFILEWStream stream(path.c_str());
138 stream.write(output.getStream(), output.getOffset());
139#endif
140}
141
reed@android.com00dae862009-06-10 15:38:48 +0000142static const struct {
143 SkBitmap::Config fConfig;
144 bool fUsePicture;
145 const char* fName;
146} gRec[] = {
147 { SkBitmap::kARGB_8888_Config, false, "8888" },
148 { SkBitmap::kARGB_4444_Config, false, "4444" },
149 { SkBitmap::kRGB_565_Config, false, "565" },
reed@android.com00dae862009-06-10 15:38:48 +0000150};
151
152int main (int argc, char * const argv[]) {
153 SkAutoGraphics ag;
154
reed@android.com8015dd82009-06-21 00:49:18 +0000155 const char* writePath = NULL; // if non-null, where we write the originals
156 const char* readPath = NULL; // if non-null, were we read from to compare
157
158 char* const* stop = argv + argc;
159 for (++argv; argv < stop; ++argv) {
160 if (strcmp(*argv, "-w") == 0) {
161 argv++;
162 if (argv < stop && **argv) {
163 writePath = *argv;
164 }
165 } else if (strcmp(*argv, "-r") == 0) {
166 argv++;
167 if (argv < stop && **argv) {
168 readPath = *argv;
169 }
170 }
171 }
172
reed@android.com00dae862009-06-10 15:38:48 +0000173 Iter iter;
174 GM* gm;
reed@android.com00f883e2010-12-14 17:46:14 +0000175
176 if (readPath) {
177 fprintf(stderr, "reading from %s\n", readPath);
178 } else if (writePath) {
179 fprintf(stderr, "writing to %s\n", writePath);
180 }
181
reed@android.com00dae862009-06-10 15:38:48 +0000182 while ((gm = iter.next()) != NULL) {
183 SkISize size = gm->getISize();
reed@android.comb9b9a182009-07-08 02:54:47 +0000184 SkDebugf("creating... %s [%d %d]\n", gm->shortName(),
reed@android.com8015dd82009-06-21 00:49:18 +0000185 size.width(), size.height());
186
reed@android.com00dae862009-06-10 15:38:48 +0000187 SkBitmap bitmap;
reed@android.comdd0ac282009-06-20 02:38:16 +0000188 for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) {
reed@android.com00dae862009-06-10 15:38:48 +0000189 bitmap.setConfig(gRec[i].fConfig, size.width(), size.height());
190 bitmap.allocPixels();
191 bitmap.eraseColor(0);
192 SkCanvas canvas(bitmap);
193
194 gm->draw(&canvas);
reed@google.com07700442010-12-20 19:46:07 +0000195
reed@android.com8015dd82009-06-21 00:49:18 +0000196 SkString name = make_name(gm->shortName(), gRec[i].fName);
197
198 if (writePath) {
reed@google.com07700442010-12-20 19:46:07 +0000199 SkString path = make_filename(writePath, name, "png");
reed@android.comb9b9a182009-07-08 02:54:47 +0000200 bool success = write_bitmap(path, bitmap);
reed@android.com8015dd82009-06-21 00:49:18 +0000201 if (!success) {
202 fprintf(stderr, "FAILED to write %s\n", path.c_str());
203 }
reed@google.com07700442010-12-20 19:46:07 +0000204 write_pdf(gm, writePath);
reed@android.com8015dd82009-06-21 00:49:18 +0000205 } else if (readPath) {
reed@google.com07700442010-12-20 19:46:07 +0000206 SkString path = make_filename(readPath, name, "png");
reed@android.com8015dd82009-06-21 00:49:18 +0000207 SkBitmap orig;
208 bool success = SkImageDecoder::DecodeFile(path.c_str(), &orig,
209 SkBitmap::kARGB_8888_Config,
210 SkImageDecoder::kDecodePixels_Mode, NULL);
211 if (success) {
212 compare(bitmap, orig, name);
213 } else {
214 fprintf(stderr, "FAILED to read %s\n", path.c_str());
215 }
216 }
reed@android.com00dae862009-06-10 15:38:48 +0000217 }
218 SkDELETE(gm);
219 }
220 return 0;
221}
reed@android.comdd0ac282009-06-20 02:38:16 +0000222
223///////////////////////////////////////////////////////////////////////////////
224
225using namespace skiagm;
226
227GM::GM() {}
228GM::~GM() {}
229
230void GM::draw(SkCanvas* canvas) {
231 this->onDraw(canvas);
232}
233
234