Home | History | Annotate | Download | only in gm
      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:
     14     Iter() {
     15         fReg = GMRegistry::Head();
     16     }
     17 
     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 
     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 
     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 
     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  */
     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 
     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 
     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 
    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 
    190 GM::GM() {}
    191 GM::~GM() {}
    192 
    193 void GM::draw(SkCanvas* canvas) {
    194 	this->onDraw(canvas);
    195 }
    196 
    197 
    198