more progress on golden-master test suite (not finished yet)



git-svn-id: http://skia.googlecode.com/svn/trunk@227 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/Makefile b/Makefile
index 7e12a14..91e92fd 100644
--- a/Makefile
+++ b/Makefile
@@ -131,6 +131,18 @@
 
 ##############################################################################
 
+GM_SRCS := gmmain.cpp xfermodes.cpp
+GM_SRCS := $(addprefix gm/, $(GM_SRCS))
+
+GM_OBJS := $(GM_SRCS:.cpp=.o)
+GM_OBJS := $(addprefix out/, $(GM_OBJS))
+
+gm: $(GM_OBJS) out/libskia.a
+	@echo "linking gm..."
+	$(HIDE)g++ $(GM_OBJS) out/libskia.a -o out/gm/gm $(LINKER_OPTS)
+
+##############################################################################
+
 .PHONY: clean
 clean:
 	$(HIDE)rm -rf out
@@ -140,6 +152,7 @@
 	@echo "Targets:"
 	@echo "    <default>: out/libskia.a"
 	@echo "    bench: out/bench/bench"
+	@echo "    gm: out/gm/gm"
 	@echo "    skimage: out/tools/skimage"
 	@echo "    tests: out/tests/tests"
 	@echo "    clean: removes entire out/ directory"
diff --git a/gm/gm.h b/gm/gm.h
index 1ad7240..23d98e1 100644
--- a/gm/gm.h
+++ b/gm/gm.h
@@ -1,11 +1,20 @@
 #ifndef skiagm_DEFINED
 #define skiagm_DEFINED
 
+#include "SkCanvas.h"
+#include "SkPaint.h"
 #include "SkRefCnt.h"
+#include "SkSize.h"
 #include "SkString.h"
 #include "SkTRegistry.h"
 
 namespace skiagm {
+	
+	static SkISize make_isize(int w, int h) {
+		SkISize sz;
+		sz.set(w, h);
+		return sz;
+	}
 
     class GM {
     public:
@@ -13,9 +22,11 @@
         virtual ~GM();
 		
 		void draw(SkCanvas*);
+		SkISize getISize() { return this->onISize(); }
 
 	protected:
 		virtual void onDraw(SkCanvas*) {}
+		virtual SkISize onISize() { return make_isize(0, 0); }
     };
 
     typedef SkTRegistry<GM*, void*> GMRegistry;
diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp
index 2234188..2417881 100644
--- a/gm/gmmain.cpp
+++ b/gm/gmmain.cpp
@@ -9,20 +9,20 @@
 class Iter {
 public:
     Iter() {
-        fReg = TestRegistry::Head();
+        fReg = GMRegistry::Head();
     }
 	
-    Test* next() {
+    GM* next() {
         if (fReg) {
-            TestRegistry::Factory fact = fReg->factory();
+            GMRegistry::Factory fact = fReg->factory();
             fReg = fReg->next();
-            return fact();
+            return fact(0);
         }
         return NULL;
     }
 	
     static int Count() {
-        const TestRegistry* reg = TestRegistry::Head();
+        const GMRegistry* reg = GMRegistry::Head();
         int count = 0;
         while (reg) {
             count += 1;
@@ -64,23 +64,39 @@
 
     while ((gm = iter.next()) != NULL) {
 		SkISize size = gm->getISize();
+		SkDebugf("---- gm %p [%d %d]\n", gm, size.width(), size.height());
 		SkBitmap bitmap;
-		for (size_t i = 0; i < SK_ARRAY_COUNT(gConfigs); i++) {
+		for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) {
 			bitmap.setConfig(gRec[i].fConfig, size.width(), size.height());
 			bitmap.allocPixels();
 			bitmap.eraseColor(0);
 			SkCanvas canvas(bitmap);
 
+			SkDebugf("------- drawing to %s config\n", gRec[i].fName);
 			gm->draw(&canvas);
-			
+#if 0
 			if (gRec[i].fUsePicture) {
 				SkPicture picture;
 				gm->draw(picture.beginRecording(size.width(), size.height(), 0));
 				canvas.drawPicture(picture);
 			} else {
 			}
+#endif
 		}
         SkDELETE(gm);
     }
     return 0;
 }
+
+///////////////////////////////////////////////////////////////////////////////
+
+using namespace skiagm;
+
+GM::GM() {}
+GM::~GM() {}
+
+void GM::draw(SkCanvas* canvas) {
+	this->onDraw(canvas);
+}
+
+
diff --git a/gm/xfermodes.cpp b/gm/xfermodes.cpp
new file mode 100644
index 0000000..18b0bbb
--- /dev/null
+++ b/gm/xfermodes.cpp
@@ -0,0 +1,172 @@
+#include "gm.h"
+#include "SkBitmap.h"
+#include "SkShader.h"
+#include "SkXfermode.h"
+
+namespace skiagm {
+
+static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst) {    
+    src->setConfig(SkBitmap::kARGB_8888_Config, w, h);
+    src->allocPixels();
+    src->eraseColor(0);
+
+    SkCanvas c(*src);
+    SkPaint p;
+    SkRect r;
+    SkScalar ww = SkIntToScalar(w);
+    SkScalar hh = SkIntToScalar(h);
+
+    p.setAntiAlias(true);
+    p.setColor(0xFFFFCC44);    
+    r.set(0, 0, ww*3/4, hh*3/4);
+    c.drawOval(r, p);
+    
+    dst->setConfig(SkBitmap::kARGB_8888_Config, w, h);
+    dst->allocPixels();
+    dst->eraseColor(0);
+    c.setBitmapDevice(*dst);
+
+    p.setColor(0xFF66AAFF);
+    r.set(ww/3, hh/3, ww*19/20, hh*19/20);
+    c.drawRect(r, p);
+}
+
+static uint16_t gBG[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF };
+
+class XfermodesGM : public GM {
+    SkBitmap    fBitmap;
+    SkBitmap    fBG;
+    SkBitmap    fSrcB, fDstB;
+
+    void draw_mode(SkCanvas* canvas, SkXfermode* mode, int alpha) {
+        SkPaint p;
+        
+        canvas->drawBitmap(fSrcB, 0, 0, &p);        
+        p.setAlpha(alpha);
+        p.setXfermode(mode);
+        canvas->drawBitmap(fDstB, 0, 0, &p);
+    }
+    
+public:
+	XfermodesGM() {
+        const int W = 64;
+        const int H = 64;
+        
+        fBitmap.setConfig(SkBitmap::kARGB_8888_Config, W, H);
+        fBitmap.allocPixels();
+        
+        fBG.setConfig(SkBitmap::kARGB_4444_Config, 2, 2, 4);
+        fBG.setPixels(gBG);
+        fBG.setIsOpaque(true);
+        
+        make_bitmaps(W, H, &fSrcB, &fDstB);
+    }
+    
+protected:
+	SkISize onISize() { return make_isize(400, 250); }
+
+    void drawBG(SkCanvas* canvas) {
+        canvas->drawColor(SK_ColorWHITE);
+        return;
+        SkShader* s = SkShader::CreateBitmapShader(fBG,
+                                                   SkShader::kRepeat_TileMode,
+                                                   SkShader::kRepeat_TileMode);
+        SkPaint p;
+        SkMatrix m;
+        
+        p.setShader(s)->unref();
+        m.setScale(SkIntToScalar(8), SkIntToScalar(8));
+        s->setLocalMatrix(m);
+        canvas->drawPaint(p);
+    }
+    
+    virtual void onDraw(SkCanvas* canvas) {
+        this->drawBG(canvas);
+        
+        const struct {
+            SkPorterDuff::Mode  fMode;
+            const char*         fLabel;
+        } gModes[] = {
+            { SkPorterDuff::kClear_Mode,    "Clear"     },
+            { SkPorterDuff::kSrc_Mode,      "Src"       },
+            { SkPorterDuff::kDst_Mode,      "Dst"       },
+            { SkPorterDuff::kSrcOver_Mode,  "SrcOver"   },
+            { SkPorterDuff::kDstOver_Mode,  "DstOver"   },
+            { SkPorterDuff::kSrcIn_Mode,    "SrcIn"     },
+            { SkPorterDuff::kDstIn_Mode,    "DstIn"     },
+            { SkPorterDuff::kSrcOut_Mode,   "SrcOut"    },
+            { SkPorterDuff::kDstOut_Mode,   "DstOut"    },
+            { SkPorterDuff::kSrcATop_Mode,  "SrcATop"   },
+            { SkPorterDuff::kDstATop_Mode,  "DstATop"   },
+            { SkPorterDuff::kXor_Mode,      "Xor"       },
+            { SkPorterDuff::kDarken_Mode,   "Darken"    },
+            { SkPorterDuff::kLighten_Mode,  "Lighten"   },
+            { SkPorterDuff::kMultiply_Mode, "Multiply"  },
+            { SkPorterDuff::kScreen_Mode,   "Screen"    }
+        };
+        
+        canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
+        
+        SkCanvas c(fBitmap);
+        const SkScalar w = SkIntToScalar(fBitmap.width());
+        const SkScalar h = SkIntToScalar(fBitmap.height());
+        SkShader* s = SkShader::CreateBitmapShader(fBG,
+                                                   SkShader::kRepeat_TileMode,
+                                                   SkShader::kRepeat_TileMode);
+        SkMatrix m;
+        m.setScale(SkIntToScalar(6), SkIntToScalar(6));
+        s->setLocalMatrix(m);
+        
+        SkPaint labelP;
+        labelP.setAntiAlias(true);
+        labelP.setTextAlign(SkPaint::kCenter_Align);
+
+        SkScalar x0 = 0;
+        for (int twice = 0; twice < 2; twice++) {
+            SkScalar x = x0, y = 0;
+            for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
+                SkXfermode* mode = SkPorterDuff::CreateXfermode(gModes[i].fMode);
+
+                fBitmap.eraseColor(0);
+                draw_mode(&c, mode, twice ? 0x88 : 0xFF);
+                mode->safeUnref();
+                
+                SkPaint p;
+                SkRect r;
+                r.set(x, y, x+w, y+h);
+                r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
+                p.setStyle(SkPaint::kStroke_Style);
+                canvas->drawRect(r, p);
+                p.setStyle(SkPaint::kFill_Style);
+                p.setShader(s);
+                r.inset(SK_ScalarHalf, SK_ScalarHalf);
+                canvas->drawRect(r, p);
+
+                canvas->drawBitmap(fBitmap, x, y, NULL);
+
+#if 1
+                canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel),
+                                 x + w/2, y - labelP.getTextSize()/2, labelP);
+#endif
+                x += w + SkIntToScalar(10);
+                if ((i & 3) == 3) {
+                    x = x0;
+                    y += h + SkIntToScalar(30);
+                }
+            }
+            x0 += SkIntToScalar(330);
+        }
+        s->unref();
+    }
+
+private:
+    typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new XfermodesGM; }
+static GMRegistry reg(MyFactory);
+
+}
+