1 #include "gm.h"
2 #include "SkColorPriv.h"
3 #include "SkGraphics.h"
4 #include "SkImageDecoder.h"
5 #include "SkImageEncoder.h"
6
7 using namespace skiagm;
8
9 // need to explicitly declare this, or we get some weird infinite loop llist
10 template GMRegistry* GMRegistry::gHead;
11
12 class Iter {
13 public:
Iter()14 Iter() {
15 fReg = GMRegistry::Head();
16 }
17
next()18 GM* next() {
19 if (fReg) {
20 GMRegistry::Factory fact = fReg->factory();
21 fReg = fReg->next();
22 return fact(0);
23 }
24 return NULL;
25 }
26
Count()27 static int Count() {
28 const GMRegistry* reg = GMRegistry::Head();
29 int count = 0;
30 while (reg) {
31 count += 1;
32 reg = reg->next();
33 }
34 return count;
35 }
36
37 private:
38 const GMRegistry* fReg;
39 };
40
make_name(const char shortName[],const char configName[])41 static SkString make_name(const char shortName[], const char configName[]) {
42 SkString name(shortName);
43 name.appendf("_%s", configName);
44 return name;
45 }
46
make_filename(const char path[],const SkString & name)47 static SkString make_filename(const char path[], const SkString& name) {
48 SkString filename(path);
49 if (filename.size() && filename[filename.size() - 1] != '/') {
50 filename.append("/");
51 }
52 filename.appendf("%s.png", name.c_str());
53 return filename;
54 }
55
56 /* since PNG insists on unpremultiplying our alpha, we take no precision chances
57 and force all pixels to be 100% opaque, otherwise on compare we may not get
58 a perfect match.
59 */
force_all_opaque(const SkBitmap & bitmap)60 static void force_all_opaque(const SkBitmap& bitmap) {
61 SkAutoLockPixels lock(bitmap);
62 for (int y = 0; y < bitmap.height(); y++) {
63 for (int x = 0; x < bitmap.width(); x++) {
64 *bitmap.getAddr32(x, y) |= (SK_A32_MASK << SK_A32_SHIFT);
65 }
66 }
67 }
68
write_bitmap(const SkString & path,const SkBitmap & bitmap)69 static bool write_bitmap(const SkString& path, const SkBitmap& bitmap) {
70 SkBitmap copy;
71 bitmap.copyTo(©, SkBitmap::kARGB_8888_Config);
72 force_all_opaque(copy);
73 return SkImageEncoder::EncodeFile(path.c_str(), copy,
74 SkImageEncoder::kPNG_Type, 100);
75 }
76
compare(const SkBitmap & target,const SkBitmap & base,const SkString & name)77 static void compare(const SkBitmap& target, const SkBitmap& base,
78 const SkString& name) {
79 SkBitmap copy;
80 const SkBitmap* bm = ⌖
81 if (target.config() != SkBitmap::kARGB_8888_Config) {
82 target.copyTo(©, SkBitmap::kARGB_8888_Config);
83 bm = ©
84 }
85
86 force_all_opaque(*bm);
87
88 const int w = bm->width();
89 const int h = bm->height();
90 if (w != base.width() || h != base.height()) {
91 SkDebugf("---- dimensions mismatch for %s base [%d %d] current [%d %d]\n",
92 name.c_str(), base.width(), base.height(), w, h);
93 return;
94 }
95
96 SkAutoLockPixels bmLock(*bm);
97 SkAutoLockPixels baseLock(base);
98
99 for (int y = 0; y < h; y++) {
100 for (int x = 0; x < w; x++) {
101 SkPMColor c0 = *base.getAddr32(x, y);
102 SkPMColor c1 = *bm->getAddr32(x, y);
103 if (c0 != c1) {
104 SkDebugf("----- pixel mismatch for %s at [%d %d] base 0x%08X current 0x%08X\n",
105 name.c_str(), x, y, c0, c1);
106 return;
107 }
108 }
109 }
110 }
111
112 static const struct {
113 SkBitmap::Config fConfig;
114 bool fUsePicture;
115 const char* fName;
116 } gRec[] = {
117 { SkBitmap::kARGB_8888_Config, false, "8888" },
118 { SkBitmap::kARGB_4444_Config, false, "4444" },
119 { SkBitmap::kRGB_565_Config, false, "565" },
120 };
121
main(int argc,char * const argv[])122 int main (int argc, char * const argv[]) {
123 SkAutoGraphics ag;
124
125 const char* writePath = NULL; // if non-null, where we write the originals
126 const char* readPath = NULL; // if non-null, were we read from to compare
127
128 char* const* stop = argv + argc;
129 for (++argv; argv < stop; ++argv) {
130 if (strcmp(*argv, "-w") == 0) {
131 argv++;
132 if (argv < stop && **argv) {
133 writePath = *argv;
134 }
135 } else if (strcmp(*argv, "-r") == 0) {
136 argv++;
137 if (argv < stop && **argv) {
138 readPath = *argv;
139 }
140 }
141 }
142
143 Iter iter;
144 GM* gm;
145
146 while ((gm = iter.next()) != NULL) {
147 SkISize size = gm->getISize();
148 SkDebugf("creating... %s [%d %d]\n", gm->shortName(),
149 size.width(), size.height());
150
151 SkBitmap bitmap;
152 for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) {
153 bitmap.setConfig(gRec[i].fConfig, size.width(), size.height());
154 bitmap.allocPixels();
155 bitmap.eraseColor(0);
156 SkCanvas canvas(bitmap);
157
158 gm->draw(&canvas);
159
160 SkString name = make_name(gm->shortName(), gRec[i].fName);
161
162 if (writePath) {
163 SkString path = make_filename(writePath, name);
164 bool success = write_bitmap(path, bitmap);
165 if (!success) {
166 fprintf(stderr, "FAILED to write %s\n", path.c_str());
167 }
168 } else if (readPath) {
169 SkString path = make_filename(readPath, name);
170 SkBitmap orig;
171 bool success = SkImageDecoder::DecodeFile(path.c_str(), &orig,
172 SkBitmap::kARGB_8888_Config,
173 SkImageDecoder::kDecodePixels_Mode, NULL);
174 if (success) {
175 compare(bitmap, orig, name);
176 } else {
177 fprintf(stderr, "FAILED to read %s\n", path.c_str());
178 }
179 }
180 }
181 SkDELETE(gm);
182 }
183 return 0;
184 }
185
186 ///////////////////////////////////////////////////////////////////////////////
187
188 using namespace skiagm;
189
GM()190 GM::GM() {}
~GM()191 GM::~GM() {}
192
draw(SkCanvas * canvas)193 void GM::draw(SkCanvas* canvas) {
194 this->onDraw(canvas);
195 }
196
197
198