SkiaExamples improvements.

Make it possible for a client to write a Hello World in less than 50 lines.

R=caryclark@google.com

Review URL: https://codereview.chromium.org/18574002

git-svn-id: http://skia.googlecode.com/svn/trunk@10319 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/experimental/SkiaExamples/BaseExample.cpp b/experimental/SkiaExamples/BaseExample.cpp
deleted file mode 100644
index 7e4116a..0000000
--- a/experimental/SkiaExamples/BaseExample.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- */
-
-#include "BaseExample.h"
-
-#include "gl/GrGLUtil.h"
-#include "gl/GrGLDefines.h"
-#include "gl/GrGLInterface.h"
-#include "SkApplication.h"
-#include "SkGpuDevice.h"
-#include "SkGraphics.h"
-
-void application_init() {
-    SkGraphics::Init();
-    SkEvent::Init();
-}
-
-void application_term() {
-    SkEvent::Term();
-    SkGraphics::Term();
-}
-
-BaseExample::BaseExample(void* hWnd, int argc, char** argv)
-    : INHERITED(hWnd) {}
-
-void BaseExample::tearDownBackend() {
-  if (kGPU_DeviceType == fType) {
-        SkSafeUnref(fContext);
-        fContext = NULL;
-
-        SkSafeUnref(fInterface);
-        fInterface = NULL;
-
-        SkSafeUnref(fRenderTarget);
-        fRenderTarget = NULL;
-
-        detach();
-    }
-}
-
-bool BaseExample::setupBackend(DeviceType type) {
-    fType = type;
-
-    this->setConfig(SkBitmap::kARGB_8888_Config);
-    this->setVisibleP(true);
-    this->setClipToBounds(false);
-
-    bool result = attach(kNativeGL_BackEndType, 0 /*msaa*/, &fAttachmentInfo);
-    if (false == result) {
-        SkDebugf("Not possible to create backend.\n");
-        detach();
-        return false;
-    }
-
-    fInterface = GrGLCreateNativeInterface();
-
-    SkASSERT(NULL != fInterface);
-
-    fContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fInterface);
-    SkASSERT(NULL != fContext);
-
-    setupRenderTarget();
-
-    return true;
-}
-
-void BaseExample::setupRenderTarget() {
-    GrBackendRenderTargetDesc desc;
-    desc.fWidth = SkScalarRound(width());
-    desc.fHeight = SkScalarRound(height());
-    desc.fConfig = kSkia8888_GrPixelConfig;
-    desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
-    desc.fSampleCnt = fAttachmentInfo.fSampleCount;
-    desc.fStencilBits = fAttachmentInfo.fStencilBits;
-
-    GrGLint buffer;
-    GR_GL_GetIntegerv(fInterface, GR_GL_FRAMEBUFFER_BINDING, &buffer);
-    desc.fRenderTargetHandle = buffer;
-
-    fRenderTarget = fContext->wrapBackendRenderTarget(desc);
-
-    fContext->setRenderTarget(fRenderTarget);
-}
-
-SkCanvas* BaseExample::createCanvas() {
-    if (fType == kGPU_DeviceType) {
-        if (NULL != fContext && NULL != fRenderTarget) {
-            SkAutoTUnref<SkDevice> device(new SkGpuDevice(fContext, fRenderTarget));
-            return new SkCanvas(device);
-        }
-        tearDownBackend();
-        setupBackend(kRaster_DeviceType);
-    }
-    return INHERITED::createCanvas();
-}
-
-void BaseExample::draw(SkCanvas* canvas) {
-    if (fType == kGPU_DeviceType) {
-
-        SkASSERT(NULL != fContext);
-        fContext->flush();
-    }
-    if (fType == kRaster_DeviceType) {
-        // need to send the raster bits to the (gpu) window
-        fContext->setRenderTarget(fRenderTarget);
-        const SkBitmap& bm = getBitmap();
-        fRenderTarget->writePixels(0, 0, bm.width(), bm.height(),
-                                      kSkia8888_GrPixelConfig,
-                                      bm.getPixels(),
-                                      bm.rowBytes());
-    }
-    INHERITED::present();
-}
-
-void BaseExample::onSizeChange() {
-    setupRenderTarget();
-}
-
-#ifdef SK_BUILD_FOR_WIN
-void BaseExample::onHandleInval(const SkIRect& rect) {
-    RECT winRect;
-    winRect.top = rect.top();
-    winRect.bottom = rect.bottom();
-    winRect.right = rect.right();
-    winRect.left = rect.left();
-    InvalidateRect((HWND)this->getHWND(), &winRect, false);
-}
-#endif
diff --git a/experimental/SkiaExamples/BaseExample.h b/experimental/SkiaExamples/BaseExample.h
deleted file mode 100644
index b9cc259..0000000
--- a/experimental/SkiaExamples/BaseExample.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2013 Google Inc.
- *
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- *
- */
-
-#ifndef BaseExample_DEFINED
-#define BaseExample_DEFINED
-
-#include "SkWindow.h"
-
-class GrContext;
-struct GrGLInterface;
-class GrRenderTarget;
-class SkCanvas;
-
-class BaseExample : public SkOSWindow {
-public:
-    enum DeviceType {
-        kRaster_DeviceType,
-        kGPU_DeviceType,
-    };
-    BaseExample(void* hWnd, int argc, char** argv);
-
-    // Changes the device type of the object.
-    bool setupBackend(DeviceType type);
-    void tearDownBackend();
-
-    DeviceType getDeviceType() const { return fType; }
-
-protected:
-    // Your class should override this method to do its thing.
-    virtual void draw(SkCanvas* canvas) SK_OVERRIDE;
-
-    virtual void onSizeChange() SK_OVERRIDE;
-
-#ifdef SK_BUILD_FOR_WIN
-    virtual void onHandleInval(const SkIRect&) SK_OVERRIDE;
-#endif
-
-    SkCanvas* createCanvas() SK_OVERRIDE;
-
-private:
-    void setupRenderTarget();
-
-    DeviceType fType;
-
-    GrContext* fContext;
-    GrRenderTarget* fRenderTarget;
-    AttachmentInfo fAttachmentInfo;
-    const GrGLInterface* fInterface;
-    typedef SkOSWindow INHERITED;
-};
-#endif
diff --git a/experimental/SkiaExamples/HelloSkiaExample.cpp b/experimental/SkiaExamples/HelloSkiaExample.cpp
index f25cd76..2424b76 100644
--- a/experimental/SkiaExamples/HelloSkiaExample.cpp
+++ b/experimental/SkiaExamples/HelloSkiaExample.cpp
@@ -7,7 +7,7 @@
  *
  */
 
-#include "BaseExample.h"
+#include "SkExample.h"
 
 #include "SkApplication.h"
 #include "SkDraw.h"
@@ -15,98 +15,96 @@
 #include "SkGraphics.h"
 #include "SkUnitMappers.h"
 
-class HelloSkia : public BaseExample {
-    public:
-        HelloSkia(void* hWnd, int argc, char** argv)
-            : INHERITED(hWnd, argc, argv)
-        {
-            fBGColor = SK_ColorWHITE;
-            fRotationAngle = SkIntToScalar(0);
+class HelloSkia : public SkExample {
+public:
+    HelloSkia(SkExampleWindow* window) : SkExample(window) {
+        fName = "HelloSkia";
+        fBGColor = SK_ColorWHITE;
+        fRotationAngle = SkIntToScalar(0);
 
-            setupBackend(kGPU_DeviceType);
-            // Another option is software rendering:
-            // setupBackend(kRaster_DeviceType);
-        }
+        fWindow->setupBackend(SkExampleWindow::kGPU_DeviceType);
+        // Another option is software rendering:
+        // setupBackend(SkExampleWindow::kRaster_DeviceType);
+    }
 
-    protected:
-        virtual void draw(SkCanvas* canvas) SK_OVERRIDE {
-            // Clear background
-            canvas->drawColor(fBGColor);
+protected:
+    void draw(SkCanvas* canvas) {
+        // Clear background
+        canvas->drawColor(fBGColor);
 
-            SkPaint paint;
-            paint.setColor(SK_ColorRED);
+        SkPaint paint;
+        paint.setColor(SK_ColorRED);
 
-            // Draw a rectangle with blue paint
-            SkRect rect = {
+        // Draw a rectangle with blue paint
+        SkRect rect = {
                 SkIntToScalar(10), SkIntToScalar(10),
                 SkIntToScalar(128), SkIntToScalar(128)
-            };
-            canvas->drawRect(rect, paint);
+        };
+        canvas->drawRect(rect, paint);
 
-            // Set up a linear gradient and draw a circle
-            {
-                SkPoint linearPoints[] = {
+        // Set up a linear gradient and draw a circle
+        {
+            SkPoint linearPoints[] = {
                     {SkIntToScalar(0), SkIntToScalar(0)},
                     {SkIntToScalar(300), SkIntToScalar(300)}
-                };
-                SkColor linearColors[] = {SK_ColorGREEN, SK_ColorBLACK};
+            };
+            SkColor linearColors[] = {SK_ColorGREEN, SK_ColorBLACK};
 
-                SkUnitMapper* linearMapper = new SkDiscreteMapper(100);
-                SkAutoUnref lm_deleter(linearMapper);
+            SkUnitMapper* linearMapper = new SkDiscreteMapper(100);
+            SkAutoUnref lm_deleter(linearMapper);
 
-                SkShader* shader = SkGradientShader::CreateLinear(
-                        linearPoints, linearColors, NULL, 2,
-                        SkShader::kMirror_TileMode, linearMapper);
-                SkAutoUnref shader_deleter(shader);
+            SkShader* shader = SkGradientShader::CreateLinear(
+                    linearPoints, linearColors, NULL, 2,
+                    SkShader::kMirror_TileMode, linearMapper);
+            SkAutoUnref shader_deleter(shader);
 
-                paint.setShader(shader);
-                paint.setFlags(SkPaint::kAntiAlias_Flag);
+            paint.setShader(shader);
+            paint.setFlags(SkPaint::kAntiAlias_Flag);
 
-                canvas->drawCircle(SkIntToScalar(200), SkIntToScalar(200),
-                                   SkIntToScalar(64), paint);
+            canvas->drawCircle(SkIntToScalar(200), SkIntToScalar(200),
+                    SkIntToScalar(64), paint);
 
-                // Detach shader
-                paint.setShader(NULL);
-            }
-
-
-            // Draw a message with a nice black paint.
-            paint.setFlags(
-                    SkPaint::kAntiAlias_Flag |
-                    SkPaint::kSubpixelText_Flag |  // ... avoid waggly text when rotating.
-                    SkPaint::kUnderlineText_Flag);
-            paint.setColor(SK_ColorBLACK);
-            paint.setTextSize(SkIntToScalar(20));
-
-            canvas->save();
-
-            static const char message[] = "Hello Skia!!!";
-
-            // Translate and rotate
-            canvas->translate(SkIntToScalar(300), SkIntToScalar(300));
-            fRotationAngle += SkDoubleToScalar(0.2);
-            if (fRotationAngle > SkDoubleToScalar(360.0)) {
-                fRotationAngle -= SkDoubleToScalar(360.0);
-            }
-            canvas->rotate(fRotationAngle);
-
-            // Draw the text:
-            canvas->drawText(message, strlen(message), SkIntToScalar(0), SkIntToScalar(0), paint);
-
-            canvas->restore();
-
-            // Invalidate the window to force a redraw. Poor man's animation mechanism.
-            this->inval(NULL);
-
-            INHERITED::draw(canvas);
+            // Detach shader
+            paint.setShader(NULL);
         }
 
-    private:
-        SkScalar fRotationAngle;
-        SkColor fBGColor;
-        typedef BaseExample INHERITED;
+        // Draw a message with a nice black paint.
+        paint.setFlags(
+                SkPaint::kAntiAlias_Flag |
+                SkPaint::kSubpixelText_Flag |  // ... avoid waggly text when rotating.
+                SkPaint::kUnderlineText_Flag);
+        paint.setColor(SK_ColorBLACK);
+        paint.setTextSize(SkIntToScalar(20));
+
+        canvas->save();
+
+        static const char message[] = "Hello Skia!!!";
+
+        // Translate and rotate
+        canvas->translate(SkIntToScalar(300), SkIntToScalar(300));
+        fRotationAngle += SkDoubleToScalar(0.2);
+        if (fRotationAngle > SkDoubleToScalar(360.0)) {
+            fRotationAngle -= SkDoubleToScalar(360.0);
+        }
+        canvas->rotate(fRotationAngle);
+
+        // Draw the text:
+        canvas->drawText(message, strlen(message), SkIntToScalar(0), SkIntToScalar(0), paint);
+
+        canvas->restore();
+
+        // Invalidate the window to force a redraw. Poor man's animation mechanism.
+        this->fWindow->inval(NULL);
+    }
+
+private:
+    SkScalar fRotationAngle;
+    SkColor fBGColor;
 };
 
-SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
-    return new HelloSkia(hwnd, argc, argv);
+static SkExample* MyFactory(SkExampleWindow* window) {
+    return new HelloSkia(window);
 }
+
+// Register this class as a Skia Example.
+SkExample::Registry registry(MyFactory);
diff --git a/experimental/SkiaExamples/SkExample.cpp b/experimental/SkiaExamples/SkExample.cpp
new file mode 100644
index 0000000..387276a
--- /dev/null
+++ b/experimental/SkiaExamples/SkExample.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ */
+
+#include "SkExample.h"
+
+#include "gl/GrGLUtil.h"
+#include "gl/GrGLDefines.h"
+#include "gl/GrGLInterface.h"
+#include "SkApplication.h"
+#include "SkCommandLineFlags.h"
+#include "SkGpuDevice.h"
+#include "SkGraphics.h"
+
+DEFINE_string2(match, m, NULL, "[~][^]substring[$] [...] of test name to run.\n" \
+                               "Multiple matches may be separated by spaces.\n" \
+                               "~ causes a matching test to always be skipped\n" \
+                               "^ requires the start of the test to match\n" \
+                               "$ requires the end of the test to match\n" \
+                               "^ and $ requires an exact match\n" \
+                               "If a test does not match any list entry,\n" \
+                               "it is skipped unless some list entry starts with ~");
+
+void application_init() {
+    SkGraphics::Init();
+    SkEvent::Init();
+}
+
+void application_term() {
+    SkEvent::Term();
+    SkGraphics::Term();
+}
+
+SkExampleWindow::SkExampleWindow(void* hwnd)
+    : INHERITED(hwnd) {
+    fRegistry = SkExample::Registry::Head();
+    fCurrExample = fRegistry->factory()(this);
+
+    if (FLAGS_match.count()) {
+        for(int i = 0; i < FLAGS_match.count(); ++i) {
+            fMatchStrs.push(FLAGS_match[i]);
+        }
+        // Start with the a matching sample if possible.
+        bool found = this->findNextMatch();
+        if (!found) {
+            SkDebugf("No matching SkExample found.\n");
+        }
+    }
+}
+
+void SkExampleWindow::tearDownBackend() {
+  if (kGPU_DeviceType == fType) {
+        SkSafeUnref(fContext);
+        fContext = NULL;
+
+        SkSafeUnref(fInterface);
+        fInterface = NULL;
+
+        SkSafeUnref(fRenderTarget);
+        fRenderTarget = NULL;
+
+        detach();
+    }
+}
+
+bool SkExampleWindow::setupBackend(DeviceType type) {
+    fType = type;
+
+    this->setConfig(SkBitmap::kARGB_8888_Config);
+    this->setVisibleP(true);
+    this->setClipToBounds(false);
+
+    bool result = attach(kNativeGL_BackEndType, 0 /*msaa*/, &fAttachmentInfo);
+    if (false == result) {
+        SkDebugf("Not possible to create backend.\n");
+        detach();
+        return false;
+    }
+
+    fInterface = GrGLCreateNativeInterface();
+
+    SkASSERT(NULL != fInterface);
+
+    fContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fInterface);
+    SkASSERT(NULL != fContext);
+
+    setupRenderTarget();
+
+    return true;
+}
+
+void SkExampleWindow::setupRenderTarget() {
+    GrBackendRenderTargetDesc desc;
+    desc.fWidth = SkScalarRound(width());
+    desc.fHeight = SkScalarRound(height());
+    desc.fConfig = kSkia8888_GrPixelConfig;
+    desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
+    desc.fSampleCnt = fAttachmentInfo.fSampleCount;
+    desc.fStencilBits = fAttachmentInfo.fStencilBits;
+
+    GrGLint buffer;
+    GR_GL_GetIntegerv(fInterface, GR_GL_FRAMEBUFFER_BINDING, &buffer);
+    desc.fRenderTargetHandle = buffer;
+
+    fRenderTarget = fContext->wrapBackendRenderTarget(desc);
+
+    fContext->setRenderTarget(fRenderTarget);
+}
+
+SkCanvas* SkExampleWindow::createCanvas() {
+    if (fType == kGPU_DeviceType) {
+        if (NULL != fContext && NULL != fRenderTarget) {
+            SkAutoTUnref<SkDevice> device(new SkGpuDevice(fContext, fRenderTarget));
+            return new SkCanvas(device);
+        }
+        tearDownBackend();
+        setupBackend(kRaster_DeviceType);
+    }
+    return INHERITED::createCanvas();
+}
+
+void SkExampleWindow::draw(SkCanvas* canvas) {
+    if (NULL != fCurrExample) {
+        fCurrExample->draw(canvas);
+    }
+    if (fType == kGPU_DeviceType) {
+
+        SkASSERT(NULL != fContext);
+        fContext->flush();
+    }
+    if (fType == kRaster_DeviceType) {
+        // need to send the raster bits to the (gpu) window
+        fContext->setRenderTarget(fRenderTarget);
+        const SkBitmap& bm = getBitmap();
+        fRenderTarget->writePixels(0, 0, bm.width(), bm.height(),
+                                      kSkia8888_GrPixelConfig,
+                                      bm.getPixels(),
+                                      bm.rowBytes());
+    }
+    INHERITED::present();
+}
+
+void SkExampleWindow::onSizeChange() {
+    setupRenderTarget();
+}
+
+#ifdef SK_BUILD_FOR_WIN
+void SkExampleWindow::onHandleInval(const SkIRect& rect) {
+    RECT winRect;
+    winRect.top = rect.top();
+    winRect.bottom = rect.bottom();
+    winRect.right = rect.right();
+    winRect.left = rect.left();
+    InvalidateRect((HWND)this->getHWND(), &winRect, false);
+}
+#endif
+
+bool SkExampleWindow::findNextMatch() {
+    bool found = false;
+    // Avoid infinite loop by knowing where we started.
+    const SkExample::Registry* begin = fRegistry;
+    while (!found) {
+        fRegistry = fRegistry->next();
+        if (NULL == fRegistry) {  // Reached the end of the registered samples. GOTO head.
+            fRegistry = SkExample::Registry::Head();
+        }
+        SkExample* next = fRegistry->factory()(this);
+        if (!SkCommandLineFlags::ShouldSkip(fMatchStrs, next->getName().c_str())) {
+            fCurrExample = next;
+            found = true;
+        }
+        if (begin == fRegistry) {  // We looped through every sample without finding anything.
+            break;
+        }
+    }
+    return found;
+}
+
+bool SkExampleWindow::onHandleChar(SkUnichar unichar) {
+    if ('n' == unichar) {
+        bool found = findNextMatch();
+        if (!found) {
+            SkDebugf("No SkExample that matches your query\n");
+        }
+    }
+    return true;
+}
+
+SkOSWindow* create_sk_window(void* hwnd, int argc, char** argv) {
+    SkCommandLineFlags::Parse(argc, argv);
+    return new SkExampleWindow(hwnd);
+}
diff --git a/experimental/SkiaExamples/SkExample.h b/experimental/SkiaExamples/SkExample.h
new file mode 100644
index 0000000..05b2ccd
--- /dev/null
+++ b/experimental/SkiaExamples/SkExample.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ */
+
+#ifndef SkExample_DEFINED
+#define SkExample_DEFINED
+
+#include "SkWindow.h"
+#include "SkTRegistry.h"
+
+class GrContext;
+struct GrGLInterface;
+class GrRenderTarget;
+class SkCanvas;
+class SkExampleWindow;
+
+class SkExample : public SkNoncopyable {
+public:
+    SkExample(SkExampleWindow* window) : fWindow(window) {}
+
+    // Your class should override this method to do its thing.
+    virtual void draw(SkCanvas* canvas) = 0;
+
+    SkString getName() { return fName; };
+    // Use this public registry to tell the world about your sample.
+    typedef SkTRegistry<SkExample*, SkExampleWindow*> Registry;
+
+protected:
+    SkExampleWindow* fWindow;
+    SkString fName;
+};
+
+class SkExampleWindow : public SkOSWindow {
+public:
+    enum DeviceType {
+        kRaster_DeviceType,
+        kGPU_DeviceType,
+    };
+    SkExampleWindow(void* hwnd);
+
+    // Changes the device type of the object.
+    bool setupBackend(DeviceType type);
+    void tearDownBackend();
+
+    DeviceType getDeviceType() const { return fType; }
+
+protected:
+    virtual void draw(SkCanvas* canvas) SK_OVERRIDE;
+
+    virtual void onSizeChange() SK_OVERRIDE;
+
+#ifdef SK_BUILD_FOR_WIN
+    virtual void onHandleInval(const SkIRect&) SK_OVERRIDE;
+#endif
+
+    SkCanvas* createCanvas() SK_OVERRIDE;
+
+private:
+    bool findNextMatch();  // Set example to the first one that matches FLAGS_match.
+    void setupRenderTarget();
+    bool onHandleChar(SkUnichar unichar) SK_OVERRIDE;
+
+    DeviceType fType;
+
+    SkExample* fCurrExample;
+    const SkExample::Registry* fRegistry;
+    SkTDArray<const char*> fMatchStrs;
+    GrContext* fContext;
+    GrRenderTarget* fRenderTarget;
+    AttachmentInfo fAttachmentInfo;
+    const GrGLInterface* fInterface;
+
+    typedef SkOSWindow INHERITED;
+};
+
+#endif
+
diff --git a/gyp/SkiaExamples.gyp b/gyp/SkiaExamples.gyp
deleted file mode 100644
index 8f26a8a..0000000
--- a/gyp/SkiaExamples.gyp
+++ /dev/null
@@ -1,76 +0,0 @@
-{
-  'targets' : [
-  {
-    'target_name': 'SkiaExamples',
-      'type': 'executable',
-      'mac_bundle' : 1,
-      'include_dirs' : [],
-      'includes': [],
-      'sources': [
-        '../experimental/SkiaExamples/HelloSkiaExample.cpp',
-        '../experimental/SkiaExamples/BaseExample.h',
-        '../experimental/SkiaExamples/BaseExample.cpp',
-      ],
-      'dependencies': [
-        'skia_lib.gyp:skia_lib',
-      'views.gyp:views',
-      'xml.gyp:xml',
-      ],
-      'conditions' : [
-        [ 'skia_gpu == 1', {
-          'include_dirs' : [
-            '../src/gpu',  #gl/GrGLUtil.h
-            ]
-        }],
-      [ 'skia_os == "win"', {
-        'sources' : [
-          '../src/views/win/SkOSWindow_Win.cpp',
-          '../src/views/win/skia_win.cpp',
-          ],
-        },
-      ],
-
-      [ 'skia_os == "mac"', {
-        'sources': [
-
-# SkiaExamples specific files
-        '../experimental/SkiaExamples/SkiaExamples-Info.plist',
-        '../experimental/SkiaExamples/SkExampleNSView.h',
-        '../experimental/SkiaExamples/SkExampleNSView.mm',
-
-# Mac files
-        '../src/views/mac/SampleAppDelegate.h',
-        '../src/views/mac/SampleAppDelegate.mm',
-        '../src/views/mac/SkEventNotifier.mm',
-        '../src/views/mac/skia_mac.mm',
-        '../src/views/mac/SkNSView.h',
-        '../src/views/mac/SkNSView.mm',
-        '../src/views/mac/SkOptionsTableView.h',
-        '../src/views/mac/SkOptionsTableView.mm',
-        '../src/views/mac/SkOSWindow_Mac.mm',
-        '../src/views/mac/SkTextFieldCell.h',
-        '../src/views/mac/SkTextFieldCell.m',
-        ],
-      'include_dirs' : [
-        '../src/views/mac/'
-        ],
-      'link_settings': {
-      },
-      'xcode_settings' : {
-        'INFOPLIST_FILE' : '../experimental/SkiaExamples/SkiaExamples-Info.plist',
-      },
-      'mac_bundle_resources' : [
-        '../experimental/SkiaExamples/SkiaExamples.xib'
-        ],
-      }
-    ],
-      ],
-  }
-  ],
-}
-
-# Local Variables:
-# tab-width:2
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=2 shiftwidth=2:
diff --git a/gyp/experimental.gyp b/gyp/experimental.gyp
index 09711ac..5552b4c 100644
--- a/gyp/experimental.gyp
+++ b/gyp/experimental.gyp
@@ -18,6 +18,75 @@
         ],
       },
     },
+    {
+      'target_name': 'SkiaExamples',
+      'type': 'executable',
+      'mac_bundle' : 1,
+      'include_dirs' : [
+        '../tools/flags',
+        ],
+      'includes': [],
+       'sources': [
+         '../experimental/SkiaExamples/SkExample.h',
+         '../experimental/SkiaExamples/SkExample.cpp',
+         '../experimental/SkiaExamples/HelloSkiaExample.cpp',
+       ],
+       'dependencies': [
+         'skia_lib.gyp:skia_lib',
+         'views.gyp:views',
+         'xml.gyp:xml',
+         'flags.gyp:flags'
+       ],
+       'conditions' : [
+         [ 'skia_gpu == 1', {
+           'include_dirs' : [
+             '../src/gpu',  #gl/GrGLUtil.h
+             ]
+         }],
+        [ 'skia_os == "win"', {
+         'sources' : [
+           '../src/views/win/SkOSWindow_Win.cpp',
+           '../src/views/win/skia_win.cpp',
+           ],
+          },
+        ],
+
+        [ 'skia_os == "mac"', {
+          'sources': [
+
+# SkiaExamples specific files
+          '../experimental/SkiaExamples/SkiaExamples-Info.plist',
+          '../experimental/SkiaExamples/SkExampleNSView.h',
+          '../experimental/SkiaExamples/SkExampleNSView.mm',
+
+# Mac files
+          '../src/views/mac/SampleAppDelegate.h',
+          '../src/views/mac/SampleAppDelegate.mm',
+          '../src/views/mac/SkEventNotifier.mm',
+          '../src/views/mac/skia_mac.mm',
+          '../src/views/mac/SkNSView.h',
+          '../src/views/mac/SkNSView.mm',
+          '../src/views/mac/SkOptionsTableView.h',
+          '../src/views/mac/SkOptionsTableView.mm',
+          '../src/views/mac/SkOSWindow_Mac.mm',
+          '../src/views/mac/SkTextFieldCell.h',
+          '../src/views/mac/SkTextFieldCell.m',
+          ],
+        'include_dirs' : [
+          '../src/views/mac/'
+          ],
+        'link_settings': {
+        },
+        'xcode_settings' : {
+          'INFOPLIST_FILE' : '../experimental/SkiaExamples/SkiaExamples-Info.plist',
+        },
+        'mac_bundle_resources' : [
+          '../experimental/SkiaExamples/SkiaExamples.xib'
+          ],
+        }
+      ],
+     ],
+    }
   ],
 }