• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(&copy, 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 = &target;
81     if (target.config() != SkBitmap::kARGB_8888_Config) {
82         target.copyTo(&copy, SkBitmap::kARGB_8888_Config);
83         bm = &copy;
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