Import all GMs as Samples.

Review URL: http://codereview.appspot.com/5332043/



git-svn-id: http://skia.googlecode.com/svn/trunk@2564 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/samplecode/GMSampleView.h b/samplecode/GMSampleView.h
new file mode 100644
index 0000000..08acfcc
--- /dev/null
+++ b/samplecode/GMSampleView.h
@@ -0,0 +1,50 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#ifndef GMSampleView_DEFINED
+#define GMSampleView_DEFINED
+
+#include "SampleCode.h"
+#include "gm.h"
+
+class GMSampleView : public SampleView {
+private:
+    typedef skiagm::GM GM;
+
+public:
+    GMSampleView(GM* gm)
+    : fGM(gm) {}
+    
+    virtual ~GMSampleView() {
+        delete fGM;
+    }
+    
+protected:
+    virtual bool onQuery(SkEvent* evt) {
+        if (SampleCode::TitleQ(*evt)) {
+            SampleCode::TitleR(evt, fGM->shortName());
+            return true;
+        }
+        return this->INHERITED::onQuery(evt);
+    }
+    
+    virtual void onDrawContent(SkCanvas* canvas) {
+        fGM->drawContent(canvas);
+    }
+
+    virtual void onDrawBackground(SkCanvas* canvas) {
+        fGM->drawBackground(canvas);
+    }
+
+private:
+    GM* fGM;
+    typedef SampleView INHERITED;
+};
+
+#endif
diff --git a/samplecode/OverView.cpp b/samplecode/OverView.cpp
index 1a6d9e9..fc4a9ef 100644
--- a/samplecode/OverView.cpp
+++ b/samplecode/OverView.cpp
@@ -20,7 +20,7 @@
 }
 class OverView : public SkView {
 public:
-    OverView(int count, const SkViewFactory factories[]);
+    OverView(int count, const SkViewFactory* factories[]);
     virtual ~OverView();
     
 protected:
@@ -61,17 +61,16 @@
 
 private:
     int             fCount;
-    const SkViewFactory*  fFactories;
+    const SkViewFactory**  fFactories;
 
     typedef SkView INHERITED;
 };
 
-SkView* create_overview(int count, const SkViewFactory factories[]);
-SkView* create_overview(int count, const SkViewFactory factories[]) {
+SkView* create_overview(int count, const SkViewFactory* factories[]) {
     return SkNEW_ARGS(OverView, (count, factories));
 };
 
-OverView::OverView(int count, const SkViewFactory factories[]) {
+OverView::OverView(int count, const SkViewFactory* factories[]) {
     fCount = count;
     fFactories = factories;
 }
@@ -89,7 +88,7 @@
     SkScalar locX = 0;
     SkScalar locY = 0;
     for (int i = 0; i < fCount; i++) {
-        SkView* view = fFactories[i]();
+        SkView* view = (*fFactories[i])();
         view->setVisibleP(true);
         this->attachChildToBack(view)->unref();
         view->setLoc(locX, locY);
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index b0d471d..7947e74 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -56,7 +56,7 @@
 #define USE_ARROWS_FOR_ZOOM true
 //#define DEFAULT_TO_GPU
 
-extern SkView* create_overview(int, const SkViewFactory[]);
+extern SkView* create_overview(int, const SkViewFactory*[]);
 extern bool is_overview(SkView* view);
 extern SkView* create_transition(SkView*, SkView*, int);
 extern bool is_transition(SkView* view);
@@ -240,18 +240,75 @@
 }
 //////////////////
 
-SkViewRegister* SkViewRegister::gHead;
-SkViewRegister::SkViewRegister(SkViewFactory fact) : fFact(fact) {
-    static bool gOnce;
-    if (!gOnce) {
-        gHead = NULL;
-        gOnce = true;
-    }
+SkFuncViewFactory::SkFuncViewFactory(SkViewCreateFunc func)
+    : fCreateFunc(func) {
+}
 
+SkView* SkFuncViewFactory::operator() () const SK_OVERRIDE {
+    return (*fCreateFunc)();
+}
+
+#include "GMSampleView.h"
+
+SkGMSampleViewFactory::SkGMSampleViewFactory(GMFactoryFunc func)
+    : fFunc(func) {
+}
+
+SkView* SkGMSampleViewFactory::operator() () const {
+    return new GMSampleView(fFunc(NULL));
+}
+
+SkViewRegister* SkViewRegister::gHead;
+SkViewRegister::SkViewRegister(SkViewFactory* fact) : fFact(fact) {
+    fFact->ref();
     fChain = gHead;
     gHead = this;
 }
 
+SkViewRegister::SkViewRegister(SkViewCreateFunc func) {
+    fFact = new SkFuncViewFactory(func);
+    fChain = gHead;
+    gHead = this;
+}
+
+SkViewRegister::SkViewRegister(GMFactoryFunc func) {
+    fFact = new SkGMSampleViewFactory(func);
+    fChain = gHead;
+    gHead = this;
+}
+
+class AutoUnrefArray {
+public:
+    AutoUnrefArray() {}
+    ~AutoUnrefArray() {
+        int count = fObjs.count();
+        for (int i = 0; i < count; ++i) {
+            fObjs[i]->unref();
+        }
+    }
+    SkRefCnt*& push_back() { return *fObjs.append(); }
+    
+private:
+    SkTDArray<SkRefCnt*> fObjs;
+};
+
+// registers GMs as Samples
+// This can't be performed during static initialization because it could be
+// run before GMRegistry has been fully built.
+void SkGMRegistyToSampleRegistry() {
+    static bool gOnce;
+    static AutoUnrefArray fRegisters; 
+
+    if (!gOnce) {
+        const skiagm::GMRegistry* gmreg = skiagm::GMRegistry::Head();
+        while (gmreg) {
+            fRegisters.push_back() = new SkViewRegister(gmreg->factory());
+            gmreg = gmreg->next();
+        }
+        gOnce = true;
+    }
+}
+
 #if 0
 #include <CoreFoundation/CoreFoundation.h>
 #include <CoreFoundation/CFURLAccess.h>
@@ -416,6 +473,11 @@
     return gSampleWindow ? gSampleWindow->getGrContext() : NULL;
 }
 
+// some GMs rely on having a skiagm::GetGr function defined
+namespace skiagm {
+    GrContext* GetGr() { return SampleCode::GetGr(); }
+}
+
 //////////////////////////////////////////////////////////////////////////////
 
 static SkView* curr_view(SkWindow* wind) {
@@ -570,6 +632,7 @@
     this->setVisibleP(true);
     this->setClipToBounds(false);
 
+    SkGMRegistyToSampleRegistry();
     {
         const SkViewRegister* reg = SkViewRegister::Head();
         while (reg) {
@@ -591,7 +654,7 @@
             fprintf(stderr, "Unknown sample \"%s\"\n", argv[1]);
         }
     }
-    this->loadView(fSamples[fCurrIndex]());
+    this->loadView((*fSamples[fCurrIndex])());
     
     fPDFData = NULL;
 
@@ -1158,26 +1221,26 @@
 
 bool SampleWindow::previousSample() {
     fCurrIndex = (fCurrIndex - 1 + fSamples.count()) % fSamples.count();
-    this->loadView(create_transition(curr_view(this), fSamples[fCurrIndex](), 
+    this->loadView(create_transition(curr_view(this), (*fSamples[fCurrIndex])(), 
                                      fTransitionPrev));
     return true;
 }
 
 bool SampleWindow::nextSample() {
     fCurrIndex = (fCurrIndex + 1) % fSamples.count();
-    this->loadView(create_transition(curr_view(this), fSamples[fCurrIndex](), 
+    this->loadView(create_transition(curr_view(this), (*fSamples[fCurrIndex])(), 
                                      fTransitionNext));
     return true;
 }
 
 bool SampleWindow::goToSample(int i) {
     fCurrIndex = (i) % fSamples.count();
-    this->loadView(create_transition(curr_view(this),fSamples[fCurrIndex](), 6));
+    this->loadView(create_transition(curr_view(this),(*fSamples[fCurrIndex])(), 6));
     return true;
 }
 
 SkString SampleWindow::getSampleTitle(int i) {
-    SkView* view = fSamples[i]();
+    SkView* view = (*fSamples[i])();
     SkString title;
     SampleCode::RequestTitle(view, &title);
     view->unref();
@@ -1288,7 +1351,7 @@
         return true;
     }
     if (query->isType("get-slide-title")) {
-        SkView* view = fSamples[query->getFast32()]();
+        SkView* view = (*fSamples[query->getFast32()])();
         SkEvent evt(gTitleEvtName);
         if (view->doQuery(&evt)) {
             query->setString("title", evt.findString(gTitleEvtName));
diff --git a/samplecode/SampleApp.h b/samplecode/SampleApp.h
index dba022a..0f1a2af 100644
--- a/samplecode/SampleApp.h
+++ b/samplecode/SampleApp.h
@@ -30,7 +30,7 @@
 class SkData;
 
 class SampleWindow : public SkOSWindow {
-    SkTDArray<SkViewFactory> fSamples;
+    SkTDArray<const SkViewFactory*> fSamples;
 public:
     enum DeviceType {
         kRaster_DeviceType,
diff --git a/samplecode/SampleCode.h b/samplecode/SampleCode.h
index d6c7929..197e0f1 100644
--- a/samplecode/SampleCode.h
+++ b/samplecode/SampleCode.h
@@ -5,6 +5,8 @@
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
+
+
 #ifndef SampleCode_DEFINED
 #define SampleCode_DEFINED
 
@@ -39,19 +41,59 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-typedef SkView* (*SkViewFactory)();
-
-class SkViewRegister : SkNoncopyable {
+// interface that constructs SkViews
+class SkViewFactory : public SkRefCnt {
 public:
-    explicit SkViewRegister(SkViewFactory);
+    virtual SkView* operator() () const = 0;
+};
+
+typedef SkView* (*SkViewCreateFunc)();
+
+// wraps SkViewCreateFunc in SkViewFactory interface
+class SkFuncViewFactory : public SkViewFactory {
+public:
+    SkFuncViewFactory(SkViewCreateFunc func);
+    virtual SkView* operator() () const SK_OVERRIDE;
+    
+private:
+    SkViewCreateFunc fCreateFunc;
+};
+
+namespace skiagm {
+class GM;
+}
+
+// factory function that creates a skiagm::GM
+typedef skiagm::GM* (*GMFactoryFunc)(void*);
+
+// Takes a GM factory function and implements the SkViewFactory interface 
+// by making the GM and wrapping it in a GMSampleView. GMSampleView bridges
+// the SampleView interface to skiagm::GM.
+class SkGMSampleViewFactory : public SkViewFactory {
+public:
+    SkGMSampleViewFactory(GMFactoryFunc func);
+    virtual SkView* operator() () const SK_OVERRIDE;
+private:
+    GMFactoryFunc fFunc;
+};
+
+class SkViewRegister : public SkRefCnt {
+public:
+    explicit SkViewRegister(SkViewFactory*);
+    explicit SkViewRegister(SkViewCreateFunc);
+    explicit SkViewRegister(GMFactoryFunc);
+
+    ~SkViewRegister() {
+        fFact->unref();
+    }
     
     static const SkViewRegister* Head() { return gHead; }
     
     SkViewRegister* next() const { return fChain; }
-    SkViewFactory   factory() const { return fFact; }
+    const SkViewFactory*   factory() const { return fFact; }
     
 private:
-    SkViewFactory   fFact;
+    SkViewFactory*  fFact;
     SkViewRegister* fChain;
     
     static SkViewRegister* gHead;
diff --git a/samplecode/SampleGM.cpp b/samplecode/SampleGM.cpp
deleted file mode 100644
index 2d172af..0000000
--- a/samplecode/SampleGM.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-#include "SampleCode.h"
-#include "SkView.h"
-#include "SkCanvas.h"
-
-#include "gm.h"
-
-using namespace skiagm;
-
-// need to explicitly declare this, or we get some weird infinite loop llist
-template GMRegistry* GMRegistry::gHead;
-
-class Iter {
-public:
-    Iter() {
-        fReg = GMRegistry::Head();
-    }
-	
-    void reset() {
-        fReg = GMRegistry::Head();
-    }
-        
-    GM* next() {
-        if (fReg) {
-            GMRegistry::Factory fact = fReg->factory();
-            fReg = fReg->next();
-            return fact(0);
-        }
-        return NULL;
-    }
-	
-    static int Count() {
-        const GMRegistry* reg = GMRegistry::Head();
-        int count = 0;
-        while (reg) {
-            count += 1;
-            reg = reg->next();
-        }
-        return count;
-    }
-	
-private:
-    const GMRegistry* fReg;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-class GMView : public SampleView {
-    Iter fIter;
-    GM*  fGM;
-public:
-	GMView() {
-        fGM = fIter.next();
-        this->postNextGM();
-        
-        this->setBGColor(0xFFDDDDDD);
-    }
-
-    virtual ~GMView() {
-        delete fGM;
-    }
-
-protected:
-    // overrides from SkEventSink
-    virtual bool onQuery(SkEvent* evt) {
-        if (SampleCode::TitleQ(*evt)) {
-            SampleCode::TitleR(evt, "GM");
-            return true;
-        }
-        return this->INHERITED::onQuery(evt);
-    }
-
-    virtual bool onEvent(const SkEvent& evt) {
-        if (evt.isType("next-gm")) {
-            delete fGM;
-            if (!(fGM = fIter.next())) {
-                fIter.reset();
-                fGM = fIter.next();
-            }
-            this->inval(NULL);
-            this->postNextGM();
-            return true;
-        }
-        return this->INHERITED::onEvent(evt);
-    }
-
-    virtual void onDrawContent(SkCanvas* canvas) {
-        fGM->draw(canvas);
-    }
-    
-private:
-    void postNextGM() {
-        (new SkEvent("next-gm", this->getSinkID()))->postDelay(1500);
-    }
-
-    typedef SampleView INHERITED;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-static SkView* MyFactory() { return new GMView; }
-static SkViewRegister reg(MyFactory);
-
-///////////////////////////////////////////////////////////////////////////////
-
-using namespace skiagm;
-
-GM::GM() {}
-GM::~GM() {}
-
-void GM::draw(SkCanvas* canvas) {
-	this->onDraw(canvas);
-}
-
-