merge with changes for GPU backend



git-svn-id: http://skia.googlecode.com/svn/trunk@637 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index b9753c8..ad5706b 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -98,12 +98,18 @@
     */
     SkDevice* setDevice(SkDevice* device);
 
-    /** Deprecated - Specify a bitmap for the canvas to draw into. This is a
-        helper method for setDevice(), and it creates a device for the bitmap by
-        calling createDevice(). The structure of the bitmap is copied into the
-        device.
-    */
-    virtual SkDevice* setBitmapDevice(const SkBitmap& bitmap);
+    /** May be overridden by subclasses. This returns a compatible device
+        for this canvas, with the specified config/width/height. If the device
+        is raster, the pixels will be allocated automatically.
+     */
+    virtual SkDevice* createDevice(SkBitmap::Config, int width, int height,
+                                   bool isOpaque, bool forLayer = false);
+
+    /**
+     *  Create a new raster device and make it current. This also returns
+     *  the new device.
+     */
+    SkDevice* setBitmapDevice(const SkBitmap& bitmap, bool forLayer = false);
 
     ///////////////////////////////////////////////////////////////////////////
 
@@ -692,16 +698,7 @@
     */
     const SkRegion& getTotalClip() const;
 
-    /** May be overridden by subclasses. This returns a compatible device
-        for this canvas, with the specified config/width/height. If isOpaque
-        is true, then the underlying bitmap is optimized to assume that every
-        pixel will be drawn to, and thus it does not need to clear the alpha
-        channel ahead of time (assuming the specified config supports per-pixel
-        alpha.) If isOpaque is false, then the bitmap should clear its alpha
-        channel.
-    */
-    virtual SkDevice* createDevice(SkBitmap::Config, int width, int height,
-                                   bool isOpaque, bool isForLayer);
+    void setExternalMatrix(const SkMatrix* = NULL);
 
     ///////////////////////////////////////////////////////////////////////////
 
@@ -737,7 +734,7 @@
         // in our constructor to ensure that fStorage is large enough
         // (though needs to be a compile-time-assert!). We use intptr_t to work
         // safely with 32 and 64 bit machines (to ensure the storage is enough)
-        intptr_t          fStorage[12];
+        intptr_t          fStorage[32];
         class SkDrawIter* fImpl;    // this points at fStorage
         SkPaint           fDefaultPaint;
         bool              fDone;
@@ -745,8 +742,8 @@
 
 protected:
     // all of the drawBitmap variants call this guy
-    virtual void commonDrawBitmap(const SkBitmap&, const SkMatrix& m,
-                                  const SkPaint& paint);
+    virtual void commonDrawBitmap(const SkBitmap&, const SkIRect*,
+                                  const SkMatrix&, const SkPaint& paint);
     
 private:
     class MCRec;
@@ -761,7 +758,7 @@
     SkDevice*   fLastDeviceToGainFocus;
     SkDeviceFactory* fDeviceFactory;
 
-    void prepareForDeviceDraw(SkDevice*);
+    void prepareForDeviceDraw(SkDevice*, const SkMatrix&, const SkRegion&);
     
     bool fDeviceCMDirty;            // cleared by updateDeviceCMCache()
     void updateDeviceCMCache();
@@ -769,7 +766,7 @@
     friend class SkDrawIter;    // needs setupDrawForLayerDevice()
 
     SkDevice* init(SkDevice*);
-    void internalDrawBitmap(const SkBitmap&, const SkMatrix& m,
+    void internalDrawBitmap(const SkBitmap&, const SkIRect*, const SkMatrix& m,
                                   const SkPaint* paint);
     void drawDevice(SkDevice*, int x, int y, const SkPaint*);
     // shared by save() and saveLayer()
@@ -807,6 +804,9 @@
         }
     }
     void computeLocalClipBoundsCompareType(EdgeType et) const;
+
+    SkMatrix    fExternalMatrix, fExternalInverse;
+    bool        fUseExternalMatrix;
 };
 
 /** Stack helper class to automatically call restoreToCount() on the canvas
diff --git a/include/core/SkChunkAlloc.h b/include/core/SkChunkAlloc.h
index 810e7b6..ba9e2c9 100644
--- a/include/core/SkChunkAlloc.h
+++ b/include/core/SkChunkAlloc.h
@@ -55,7 +55,14 @@
     size_t unalloc(void* ptr);
     
     size_t totalCapacity() const { return fTotalCapacity; }
-    
+
+    /**
+     *  Returns true if the specified address is within one of the chunks, and
+     *  has at least 1-byte following the address (i.e. if addr points to the
+     *  end of a chunk, then contains() will return false).
+     */
+    bool contains(const void* addr) const;
+
 private:
     struct Block;
     Block*  fBlock;
diff --git a/include/core/SkColorShader.h b/include/core/SkColorShader.h
index 7c5f941..44a6148 100644
--- a/include/core/SkColorShader.h
+++ b/include/core/SkColorShader.h
@@ -29,14 +29,16 @@
     /** Create a ColorShader that will inherit its color from the Paint
         at draw time.
     */
-    SkColorShader() : fFlags(0), fInheritColor(true) {}
+    SkColorShader();
 
     /** Create a ColorShader that ignores the color in the paint, and uses the
         specified color. Note: like all shaders, at draw time the paint's alpha
         will be respected, and is applied to the specified color.
     */
-    SkColorShader(SkColor c) : fColor(c), fFlags(0), fInheritColor(false) {}
-    
+    SkColorShader(SkColor c);
+
+    virtual ~SkColorShader();
+
     virtual uint32_t getFlags() { return fFlags; }
     virtual uint8_t getSpan16Alpha() const;
     virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
@@ -45,6 +47,10 @@
     virtual void shadeSpan16(int x, int y, uint16_t span[], int count);
     virtual void shadeSpanAlpha(int x, int y, uint8_t alpha[], int count);
 
+    virtual BitmapType asABitmap(SkBitmap* outTexture, 
+                                 SkMatrix* outMatrix,
+                                 TileMode xy[2], 
+                                 SkScalar* twoPointRadialParams);
 protected:
     SkColorShader(SkFlattenableReadBuffer& );
     virtual void flatten(SkFlattenableWriteBuffer& );
@@ -59,6 +65,9 @@
     uint16_t    fColor16;       // cached after setContext()
     SkBool8     fInheritColor;
 
+    // deferred allocation, used for asABitmap()
+    SkPixelRef* fAsABitmapPixelRef;
+
     typedef SkShader INHERITED;
 };
 
diff --git a/include/core/SkDescriptor.h b/include/core/SkDescriptor.h
index 8074cff..09397b7 100644
--- a/include/core/SkDescriptor.h
+++ b/include/core/SkDescriptor.h
@@ -120,13 +120,14 @@
         return true;
     }
 
+    uint32_t getChecksum() const { return fChecksum; }
+
     struct Entry {
         uint32_t fTag;
         uint32_t fLen;
     };
 
 #ifdef SK_DEBUG
-    uint32_t getChecksum() const { return fChecksum; }
     uint32_t getCount() const { return fCount; }
 #endif
 
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index 089d6e6..ec62033 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -37,26 +37,30 @@
 class SkDeviceFactory {
 public:
     virtual ~SkDeviceFactory();
-    virtual SkDevice* newDevice(SkBitmap::Config config, int width, int height,
-                                bool isOpaque, bool isForLayer) = 0;
+    virtual SkDevice* newDevice(SkCanvas*, SkBitmap::Config, int width,
+                                int height, bool isOpaque, bool isLayer) = 0;
 };
 
 class SkRasterDeviceFactory : public SkDeviceFactory {
 public:
-    virtual SkDevice* newDevice(SkBitmap::Config config, int width, int height,
-                                bool isOpaque, bool isForLayer);
+    virtual SkDevice* newDevice(SkCanvas*, SkBitmap::Config, int width,
+                                int height, bool isOpaque, bool isLayer);
 };
 
 class SkDevice : public SkRefCnt {
 public:
-    SkDevice();
-    /** Construct a new device, extracting the width/height/config/isOpaque
-        values from the bitmap.  Subclasses may override the destructor, which
-        is virtual, even though this class doesn't have one. SkRefCnt does.
-
+    SkDevice(SkCanvas*);
+    /** Construct a new device, extracting the width/height/config/isOpaque values from
+        the bitmap. If transferPixelOwnership is true, and the bitmap claims to own its
+        own pixels (getOwnsPixels() == true), then transfer this responsibility to the
+        device, and call setOwnsPixels(false) on the bitmap.
+        
+        Subclasses may override the destructor, which is virtual, even though this class
+        doesn't have one. SkRefCnt does.
+    
         @param bitmap   A copy of this bitmap is made and stored in the device
     */
-    SkDevice(const SkBitmap& bitmap);
+    SkDevice(SkCanvas*, const SkBitmap& bitmap, bool forOffscreen);
 
     virtual SkDeviceFactory* getDeviceFactory() {
         return SkNEW(SkRasterDeviceFactory);
@@ -112,6 +116,11 @@
     virtual void lockPixels();
     virtual void unlockPixels();
 
+    /** Return the device's associated texture, or NULL. If returned, it may be
+        drawn into another device
+     */
+    virtual SkGpuTexture* accessTexture() { return NULL; }
+
     /** Called with the correct matrix and clip before this device is drawn
         to using those settings. If your subclass overrides this, be sure to
         call through to the base class as well.
@@ -121,7 +130,24 @@
     /** Called when this device gains focus (i.e becomes the current device
         for drawing).
     */
-    virtual void gainFocus(SkCanvas*) {}
+    virtual void gainFocus(SkCanvas*, const SkMatrix&, const SkRegion&) {}
+    
+    /** Causes any deferred drawing to the device to be completed.
+     */
+    virtual void flush() {}
+
+    /**
+     *  Copy the pixels from the device into bitmap. Returns true on success.
+     *  If false is returned, then the bitmap parameter is left unchanged.
+     */
+    virtual bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap);
+
+    /**
+     *  Similar to draw sprite, this method will copy the pixels in bitmap onto
+     *  the device, with the top/left corner specified by (x, y). The pixel
+     *  values in the device are completely replaced: there is no blending.
+     */
+    virtual void writePixels(const SkBitmap& bitmap, int x, int y);
 
     /** These are called inside the per-device-layer loop for each draw call.
      When these are called, we have already applied any saveLayer operations,
@@ -134,8 +160,11 @@
     virtual void drawRect(const SkDraw&, const SkRect& r,
                           const SkPaint& paint);
     virtual void drawPath(const SkDraw&, const SkPath& path,
-                          const SkPaint& paint);
+                          const SkPaint& paint,
+                          const SkMatrix* prePathMatrix = NULL,
+                          bool pathIsMutable = false);
     virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
+                            const SkIRect* srcRectOrNull,
                             const SkMatrix& matrix, const SkPaint& paint);
     virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
                             int x, int y, const SkPaint& paint);
@@ -162,7 +191,15 @@
     */
     virtual void onAccessBitmap(SkBitmap*);
 
+    SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); }
+    // just for subclasses, to assign a custom pixelref
+    SkPixelRef* setPixelRef(SkPixelRef* pr, size_t offset) {
+        fBitmap.setPixelRef(pr, offset);
+        return pr;
+    }
+
 private:
+    SkCanvas* fCanvas;
     SkBitmap fBitmap;
 };
 
diff --git a/include/core/SkDraw.h b/include/core/SkDraw.h
index 5ed4aad..2c0fa49 100644
--- a/include/core/SkDraw.h
+++ b/include/core/SkDraw.h
@@ -33,12 +33,12 @@
 
 class SkDraw {
 public:
-    SkDraw() : fDevice(NULL), fBounder(NULL), fProcs(NULL) {}
+    SkDraw();
     SkDraw(const SkDraw& src);
 
     void    drawPaint(const SkPaint&) const;
     void    drawPoints(SkCanvas::PointMode, size_t count, const SkPoint[],
-                       const SkPaint&) const;
+                       const SkPaint&, bool forceUseDevice = false) const;
     void    drawRect(const SkRect&, const SkPaint&) const;
     /*  To save on mallocs, we allow a flag that tells us that srcPath is
         mutable, so that we don't have to make copies of it as we transform it.
@@ -83,12 +83,18 @@
     const SkBitmap* fBitmap;        // required
     const SkMatrix* fMatrix;        // required
     const SkRegion* fClip;          // required
+
     SkDevice*       fDevice;        // optional
     SkBounder*      fBounder;       // optional
     SkDrawProcs*    fProcs;         // optional
 
+    const SkMatrix* fMVMatrix;      // optional
+    const SkMatrix* fExtMatrix;     // optional
+
 #ifdef SK_DEBUG
-    void    validate(int width, int height) const;
+    void validate() const;
+#else
+    void validate() const {}
 #endif
 };
 
diff --git a/include/core/SkMallocPixelRef.h b/include/core/SkMallocPixelRef.h
index b6a013d..ca59a8c 100644
--- a/include/core/SkMallocPixelRef.h
+++ b/include/core/SkMallocPixelRef.h
@@ -25,13 +25,15 @@
 class SkMallocPixelRef : public SkPixelRef {
 public:
     /** Allocate the specified buffer for pixels. The memory is freed when the
-        last owner of this pixelref is gone.
+        last owner of this pixelref is gone. If addr is NULL, sk_malloc_throw()
+        is called to allocate it.
      */
     SkMallocPixelRef(void* addr, size_t size, SkColorTable* ctable);
     virtual ~SkMallocPixelRef();
     
     //! Return the allocation size for the pixels
     size_t getSize() const { return fSize; }
+    void* getAddr() const { return fStorage; }
 
     // overrides from SkPixelRef
     virtual void flatten(SkFlattenableWriteBuffer&) const;
@@ -57,4 +59,5 @@
     typedef SkPixelRef INHERITED;
 };
 
+
 #endif
diff --git a/include/core/SkMask.h b/include/core/SkMask.h
index 608010d..58a2493 100644
--- a/include/core/SkMask.h
+++ b/include/core/SkMask.h
@@ -44,8 +44,9 @@
            edges. kVerticalLCD_Format has an extra row at the top and bottom.
         */
 
-        kHorizontalLCD_Format, //!< 4 bytes/pixel: a/r/g/b
-        kVerticalLCD_Format, //!< 4 bytes/pixel: a/r/g/b
+        kHorizontalLCD_Format,  //!< 4 bytes/pixel: a/r/g/b
+        kVerticalLCD_Format,    //!< 4 bytes/pixel: a/r/g/b
+        kARGB32_Format,         //!< SkPMColor
     };
 
     enum {
diff --git a/include/core/SkMath.h b/include/core/SkMath.h
index 22ebd60..af19083 100644
--- a/include/core/SkMath.h
+++ b/include/core/SkMath.h
@@ -161,6 +161,13 @@
     return 32 - SkCLZ(value - 1);
 }
 
+/** Returns true if value is a power of 2. Does not explicitly check for
+    value <= 0.
+ */
+static inline bool SkIsPow2(int value) {
+    return (value & (value - 1)) == 0;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 /** SkMulS16(a, b) multiplies a * b, but requires that a and b are both int16_t.
diff --git a/include/core/SkPostConfig.h b/include/core/SkPostConfig.h
index cb6473c..57cc368 100644
--- a/include/core/SkPostConfig.h
+++ b/include/core/SkPostConfig.h
@@ -107,8 +107,16 @@
     #endif
 
     #ifndef SK_DEBUGBREAK
-        #define SK_DEBUGBREAK(cond)     do { if (!(cond)) DebugBreak(); } while (false)
+        #define SK_DEBUGBREAK(cond)     do { if (!(cond)) __debugbreak(); } while (false)
     #endif
+
+    #ifndef SK_A32_SHIFT
+        #define SK_A32_SHIFT 24
+        #define SK_R32_SHIFT 16
+        #define SK_G32_SHIFT 8
+        #define SK_B32_SHIFT 0
+    #endif
+
 #elif defined(SK_BUILD_FOR_MAC)
     #ifndef SK_DEBUGBREAK
         #define SK_DEBUGBREAK(cond)     do { if (!(cond)) SK_CRASH(); } while (false)
diff --git a/include/core/SkPreConfig.h b/include/core/SkPreConfig.h
index 0a5170c..dd1538a 100644
--- a/include/core/SkPreConfig.h
+++ b/include/core/SkPreConfig.h
@@ -17,9 +17,17 @@
 #ifndef SkPreConfig_DEFINED
 #define SkPreConfig_DEFINED
 
+#ifdef WEBKIT_VERSION_MIN_REQUIRED
+    #include "config.h"
+#endif
+
 //////////////////////////////////////////////////////////////////////
 
-#if !defined(SK_BUILD_FOR_PALM) && !defined(SK_BUILD_FOR_WINCE) && !defined(SK_BUILD_FOR_WIN32) && !defined(SK_BUILD_FOR_SYMBIAN) && !defined(SK_BUILD_FOR_UNIX) && !defined(SK_BUILD_FOR_MAC) && !defined(SK_BUILD_FOR_SDL)
+#if !defined(SK_BUILD_FOR_ANDROID_NDK) && !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_PALM) && !defined(SK_BUILD_FOR_WINCE) && !defined(SK_BUILD_FOR_WIN32) && !defined(SK_BUILD_FOR_SYMBIAN) && !defined(SK_BUILD_FOR_UNIX) && !defined(SK_BUILD_FOR_MAC) && !defined(SK_BUILD_FOR_SDL)
+
+    #ifdef __APPLE__
+        #include "TargetConditionals.h"
+    #endif
 
     #if defined(PALMOS_SDK_VERSION)
         #define SK_BUILD_FOR_PALM
@@ -31,6 +39,12 @@
         #define SK_BUILD_FOR_WIN32
     #elif defined(linux)
         #define SK_BUILD_FOR_UNIX
+    #elif TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
+        #define SK_BUILD_FOR_IOS
+    #elif defined(ANDROID_NDK)
+        #define SK_BUILD_FOR_ANDROID_NDK
+    #elif defined(ANROID)
+        #define SK_BUILD_FOR_ANDROID
     #else
         #define SK_BUILD_FOR_MAC
     #endif
diff --git a/include/core/SkRegion.h b/include/core/SkRegion.h
index 103e2cc..8d9ff01 100644
--- a/include/core/SkRegion.h
+++ b/include/core/SkRegion.h
@@ -263,7 +263,8 @@
         bool done() { return fDone; }
         void next();
         const SkIRect& rect() const { return fRect; }
-
+        // may return null
+        const SkRegion* rgn() const { return fRgn; }
     private:
         const SkRegion* fRgn;
         const RunType*  fRuns;
diff --git a/include/core/SkScalerContext.h b/include/core/SkScalerContext.h
index ab43b14..9617c57 100644
--- a/include/core/SkScalerContext.h
+++ b/include/core/SkScalerContext.h
@@ -44,11 +44,23 @@
 
     uint8_t     fMaskFormat;
     int8_t      fRsbDelta, fLsbDelta;  // used by auto-kerning
-    
+
+    void init(uint32_t id) {
+        fID             = id;
+        fImage          = NULL;
+        fPath           = NULL;
+#ifdef SK_GPU_AWARE_GLYPHCACHE
+        fGLCacheOffset  = SKGLYPH_GLCACHEOFFSET_INVALID;
+        fGLStrikePtr    = NULL;
+#endif
+    }
+
     unsigned rowBytes() const {
         unsigned rb = fWidth;
         if (SkMask::kBW_Format == fMaskFormat) {
             rb = (rb + 7) >> 3;
+		} else if (SkMask::kARGB32_Format == fMaskFormat) {
+			rb <<= 2;
         } else {
             rb = SkAlign4(rb);
         }
diff --git a/include/core/SkShader.h b/include/core/SkShader.h
index f3d4856..1cdbf17 100644
--- a/include/core/SkShader.h
+++ b/include/core/SkShader.h
@@ -145,12 +145,56 @@
     virtual void beginSession();
     virtual void endSession();
     
+    /**
+     Gives method bitmap should be read to implement a shader.
+     Also determines number and interpretation of "extra" parameters returned
+     by asABitmap
+     */
+    enum BitmapType {
+        kNone_BitmapType,   //<! Shader is not represented as a bitmap
+        kDefault_BitmapType,//<! Access bitmap using local coords transformed 
+                            //   by matrix. No extras
+        kRadial_BitmapType, //<! Access bitmap by transforming local coordinates 
+                            //   by the matrix and taking the distance of result 
+                            //   from  (0,0) as bitmap column. Bitmap is 1 pixel 
+                            //   tall. No extras
+        kSweep_BitmapType,  //<! Access bitmap by transforming local coordinates 
+                            //   by the matrix and taking the angle of result
+                            //   to (0,0) as bitmap x coord, where angle = 0 is
+                            //   bitmap left edge of bitmap = 2pi is the 
+                            //   right edge. Bitmap is 1 pixel tall. No extras
+        kTwoPointRadial_BitmapType
+                            //<! Matrix transforms to space where (0,0) is 
+                            //   the center of the starting circle.  The second
+                            //   circle will be centered (x, 0) where x  may be 
+                            //   0. The post-matrix space is normalized such 
+                            //   that 1 is the second radius - first radius.
+                            //   Three extra parameters are returned:
+                            //      0: x-offset of second circle center 
+                            //         to first.
+                            //      1: radius of first circle in post-matrix 
+                            //         space
+                            //      2: the second radius minus the first radius
+                            //         in pre-transformed space.        
+        
+    };
     /** Optional methods for shaders that can pretend to be a bitmap/texture
-        to play along with opengl. Default just returns false and ignores
-        the out parameters.
+        to play along with opengl. Default just returns kNone_BitmapType and 
+        ignores the out parameters.
+
+        @param outTexture if non-NULL will be the bitmap representing the shader
+                          after return.
+        @param outMatrix  if non-NULL will be the matrix to apply to vertices
+                          to access the bitmap after return.
+        @param xy         if non-NULL will be the tile modes that should be
+                          used to access the bitmap after return.
+        @param twoPointRadialParams Two extra return values needed for two point
+                                    radial bitmaps. The first is the x-offset of
+                                    the second point and the second is the radius
+                                    about the first point.
     */
-    virtual bool asABitmap(SkBitmap* outTexture, SkMatrix* outMatrix,
-                           TileMode xy[2]);
+    virtual BitmapType asABitmap(SkBitmap* outTexture, SkMatrix* outMatrix,
+                                 TileMode xy[2], SkScalar* twoPointRadialParams);
 
     //////////////////////////////////////////////////////////////////////////
     //  Factory methods for stock shaders
diff --git a/include/core/SkThread_platform.h b/include/core/SkThread_platform.h
index c2d0348..c6fd058 100644
--- a/include/core/SkThread_platform.h
+++ b/include/core/SkThread_platform.h
@@ -17,7 +17,7 @@
 #ifndef SkThread_platform_DEFINED
 #define SkThread_platform_DEFINED
 
-#ifdef ANDROID
+#if defined(ANDROID) && !defined(SK_BUILD_FOR_ANDROID_NDK)
 
 #include <utils/threads.h>
 #include <utils/Atomic.h>
diff --git a/include/core/SkUtils.h b/include/core/SkUtils.h
index 0700aeb..7cb2066 100644
--- a/include/core/SkUtils.h
+++ b/include/core/SkUtils.h
@@ -39,7 +39,7 @@
 typedef void (*SkMemset32Proc)(uint32_t dst[], uint32_t value, int count);
 SkMemset32Proc SkMemset32GetPlatformProc();
 
-#ifdef ANDROID
+#if defined(ANDROID) && !defined(SK_BUILD_FOR_ANDROID_NDK)
     #include "cutils/memory.h"
     
     #define sk_memset16(dst, value, count)    android_memset16(dst, value, (count) << 1)
diff --git a/include/pdf/SkPDFDevice.h b/include/pdf/SkPDFDevice.h
index b92dc3d..3ef234a 100644
--- a/include/pdf/SkPDFDevice.h
+++ b/include/pdf/SkPDFDevice.h
@@ -32,7 +32,7 @@
 class SkPDFStream;
 
 class SkPDFDeviceFactory : public SkDeviceFactory {
-    virtual SkDevice* newDevice(SkBitmap::Config config, int width, int height,
+    virtual SkDevice* newDevice(SkCanvas*, SkBitmap::Config, int width, int height,
                                 bool isOpaque, bool isForLayer);
 };
 
@@ -66,6 +66,10 @@
     */
     virtual void setMatrixClip(const SkMatrix&, const SkRegion&);
 
+    virtual bool readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
+        return false;
+    }
+
     /** These are called inside the per-device-layer loop for each draw call.
      When these are called, we have already applied any saveLayer operations,
      and are handling any looping from the paint, and any effects from the
@@ -79,6 +83,7 @@
     virtual void drawPath(const SkDraw&, const SkPath& path,
                           const SkPaint& paint);
     virtual void drawBitmap(const SkDraw&, const SkBitmap& bitmap,
+                            const SkIRect* srcRectOrNull,
                             const SkMatrix& matrix, const SkPaint& paint);
     virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap, int x, int y,
                             const SkPaint& paint);
diff --git a/include/utils/SkProxyCanvas.h b/include/utils/SkProxyCanvas.h
index 082e0fd..98ef778 100644
--- a/include/utils/SkProxyCanvas.h
+++ b/include/utils/SkProxyCanvas.h
@@ -22,10 +22,7 @@
     // overrides from SkCanvas
 
     virtual bool getViewport(SkIPoint* size) const;
-    virtual bool setViewport(int x, int y);
     
-    virtual SkDevice* setBitmapDevice(const SkBitmap& bitmap);
-
     virtual int save(SaveFlags flags = kMatrixClip_SaveFlag);
     virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
                           SaveFlags flags = kARGB_ClipLayer_SaveFlag);
diff --git a/include/utils/mac/SkCGUtils.h b/include/utils/mac/SkCGUtils.h
index 3b74b55..b1263f4 100644
--- a/include/utils/mac/SkCGUtils.h
+++ b/include/utils/mac/SkCGUtils.h
@@ -1,10 +1,18 @@
 #ifndef SkCGUtils_DEFINED
 #define SkCGUtils_DEFINED
 
-#include <Carbon/Carbon.h>
+#include "SkTypes.h"
+
+#ifdef SK_BUILD_FOR_MAC
+    #include <Carbon/Carbon.h>
+#else
+    #include <CoreGraphics/CoreGraphics.h>
+#endif
 
 class SkBitmap;
 
 CGImageRef SkCreateCGImageRef(const SkBitmap&);
 
+void SkCGDrawBitmap(CGContextRef, const SkBitmap&, float x, float y);
+
 #endif
diff --git a/include/views/SkEvent.h b/include/views/SkEvent.h
index 2b43f34..f6719d6 100644
--- a/include/views/SkEvent.h
+++ b/include/views/SkEvent.h
@@ -21,8 +21,6 @@
 #include "SkMetaData.h"
 #include "SkString.h"
 
-//class SkOSWindow;
-
 /** Unique 32bit id used to identify an instance of SkEventSink. When events are
     posted, they are posted to a specific sinkID. When it is time to dispatch the
     event, the sinkID is used to find the specific SkEventSink object. If it is found,
@@ -100,6 +98,9 @@
     */
     bool    findPtr(const char name[], void** value) const { return fMeta.findPtr(name, value); }
     bool    findBool(const char name[], bool* value) const { return fMeta.findBool(name, value); }
+    const void* findData(const char name[], size_t* byteCount = NULL) const {
+        return fMeta.findData(name, byteCount);
+    }
 
     /** Returns true if ethe event contains the named 32bit field, and if it equals the specified value */
     bool    hasS32(const char name[], int32_t value) const { return fMeta.hasS32(name, value); }
@@ -110,6 +111,9 @@
     /** Returns true if ethe event contains the named pointer field, and if it equals the specified value */
     bool    hasPtr(const char name[], void* value) const { return fMeta.hasPtr(name, value); }
     bool    hasBool(const char name[], bool value) const { return fMeta.hasBool(name, value); }
+    bool hasData(const char name[], const void* data, size_t byteCount) const {
+        return fMeta.hasData(name, data, byteCount);
+    }
 
     /** Add/replace the named 32bit field to the event. In XML use the subelement <data name=... s32=... /> */
     void    setS32(const char name[], int32_t value) { fMeta.setS32(name, value); }
@@ -124,6 +128,9 @@
     /** Add/replace the named pointer field to the event. There is no XML equivalent for this call */
     void    setPtr(const char name[], void* value) { fMeta.setPtr(name, value); }
     void    setBool(const char name[], bool value) { fMeta.setBool(name, value); }
+    void setData(const char name[], const void* data, size_t byteCount) {
+        fMeta.setData(name, data, byteCount);
+    }
 
     /** Return the underlying metadata object */
     SkMetaData&         getMetaData() { return fMeta; }
@@ -197,6 +204,12 @@
     */
     static void     ServiceQueueTimer();
 
+    /** Return the number of queued events. note that this value may be obsolete
+        upon return, since another thread may have called ProcessEvent() or
+        Post() after the count was made.
+     */
+    static int CountEventsOnQueue();
+
     ////////////////////////////////////////////////////
     /** Porting layer must implement these functions **/
     ////////////////////////////////////////////////////
diff --git a/include/views/SkMetaData.h b/include/views/SkMetaData.h
index 21739fe..9509710 100644
--- a/include/views/SkMetaData.h
+++ b/include/views/SkMetaData.h
@@ -35,6 +35,7 @@
     const char* findString(const char name[]) const;
     bool    findPtr(const char name[], void** value = NULL) const;
     bool    findBool(const char name[], bool* value = NULL) const;
+    const void* findData(const char name[], size_t* byteCount = NULL) const;
 
     bool    hasS32(const char name[], int32_t value) const
     {
@@ -62,6 +63,11 @@
         bool    v;
         return this->findBool(name, &v) && v == value;
     }
+    bool hasData(const char name[], const void* data, size_t byteCount) const {
+        size_t len;
+        const void* ptr = this->findData(name, &len);
+        return NULL != ptr && len == byteCount && !memcmp(ptr, data, len);
+    }
 
     void    setS32(const char name[], int32_t value);
     void    setScalar(const char name[], SkScalar value);
@@ -69,12 +75,15 @@
     void    setString(const char name[], const char value[]);
     void    setPtr(const char name[], void* value);
     void    setBool(const char name[], bool value);
+    // the data is copied from the input pointer.
+    void    setData(const char name[], const void* data, size_t byteCount);
 
     bool    removeS32(const char name[]);
     bool    removeScalar(const char name[]);
     bool    removeString(const char name[]);
     bool    removePtr(const char name[]);
     bool    removeBool(const char name[]);
+    bool    removeData(const char name[]);
 
     SkDEBUGCODE(static void UnitTest();)
 
@@ -84,6 +93,7 @@
         kString_Type,
         kPtr_Type,
         kBool_Type,
+        kData_Type,
 
         kTypeCount
     };
diff --git a/include/views/SkOSWindow_Mac.h b/include/views/SkOSWindow_Mac.h
index 98e76b0..3a26d5a 100644
--- a/include/views/SkOSWindow_Mac.h
+++ b/include/views/SkOSWindow_Mac.h
@@ -33,7 +33,12 @@
     static OSStatus EventHandler(EventHandlerCallRef inHandler,
                                  EventRef inEvent, void* userData);
 
-    void    doPaint(void* ctx);
+    void   doPaint(void* ctx);
+
+
+    bool attachGL(const SkBitmap* offscreen);
+    void detachGL();
+    void presentGL();
 
 protected:
     // overrides from SkEventSink
@@ -43,10 +48,12 @@
     // overrides from SkView
     virtual void onAddMenu(const SkOSMenu*);
     virtual void onSetTitle(const char[]);
+    
 
 private:
     void*   fHWND;
     void*   fHVIEW;
+    void*   fAGLCtx;
 
     typedef SkWindow INHERITED;
 };
diff --git a/include/views/SkOSWindow_Win.h b/include/views/SkOSWindow_Win.h
index 0a70f75..09f0c5c 100644
--- a/include/views/SkOSWindow_Win.h
+++ b/include/views/SkOSWindow_Win.h
@@ -22,12 +22,23 @@
 class SkOSWindow : public SkWindow {
 public:
     SkOSWindow(void* hwnd);
+    virtual ~SkOSWindow();
 
     void*   getHWND() const { return fHWND; }
     void    setSize(int width, int height);
     void    updateSize();
 
     static bool PostEvent(SkEvent* evt, SkEventSinkID, SkMSec delay);
+    
+    bool attachGL(const SkBitmap* offscreen);
+    void detachGL();
+    void presentGL();
+
+    bool attachD3D9();
+    void detachD3D9();
+    void presentD3D9();
+
+    void* d3d9Device() { return fD3D9Device; }
 
     bool wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
     static bool QuitOnDeactivate(HWND hWnd);
@@ -45,14 +56,23 @@
     // overrides from SkView
     virtual void onAddMenu(const SkOSMenu*);
 
+    virtual void onSetTitle(const char title[]);
+
 private:
-    void*   fHWND;
+    void*               fHWND;
+    
+    void                doPaint(void* ctx);
 
-    void    doPaint(void* ctx);
+    void*               fHGLRC;
 
-    HMENU   fMBar;
+    bool                fGLAttached;
 
-    typedef SkWindow INHERITED;
+    void*               fD3D9Device;
+    bool                fD3D9Attached;
+
+    HMENU               fMBar;
+
+    typedef SkWindow INHERITED; 
 };
 
 #endif
diff --git a/include/views/SkView.h b/include/views/SkView.h
index fc36d34..d3633db 100644
--- a/include/views/SkView.h
+++ b/include/views/SkView.h
@@ -38,6 +38,7 @@
         kFocusable_Shift,
         kFlexH_Shift,
         kFlexV_Shift,
+        kNoClip_Shift,
 
         kFlagShiftCount
     };
@@ -47,6 +48,7 @@
         kFocusable_Mask = 1 << kFocusable_Shift,    //!< set if the view can receive focus
         kFlexH_Mask     = 1 << kFlexH_Shift,        //!< set if the view's width is stretchable
         kFlexV_Mask     = 1 << kFlexV_Shift,        //!< set if the view's height is stretchable
+        kNoClip_Mask    = 1 << kNoClip_Shift,        //!< set if the view is not clipped to its bounds
 
         kAllFlagMasks   = (uint32_t)(0 - 1) >> (32 - kFlagShiftCount)
     };
@@ -66,10 +68,12 @@
     int         isVisible() const { return fFlags & kVisible_Mask; }
     int         isEnabled() const { return fFlags & kEnabled_Mask; }
     int         isFocusable() const { return fFlags & kFocusable_Mask; }
+    int         isClipToBounds() const { return !(fFlags & kNoClip_Mask); }
     /** Helper to set/clear the view's kVisible_Mask flag */
     void        setVisibleP(bool);
     void        setEnabledP(bool);
     void        setFocusableP(bool);
+    void        setClipToBounds(bool);
 
     /** Return the view's width */
     SkScalar    width() const { return fWidth; }
@@ -302,7 +306,7 @@
         Tyically this is only overridden by the by the "window". If your subclass does handle the
         request, return true so the request will not continue to propogate to the parent.
     */
-    virtual bool    handleInval(const SkRect&);
+    virtual bool    handleInval(const SkRect*);
     //! called once before all of the children are drawn (or clipped/translated)
     virtual SkCanvas* beforeChildren(SkCanvas* c) { return c; }
     //! called once after all of the children are drawn (or clipped/translated)
diff --git a/include/views/SkWindow.h b/include/views/SkWindow.h
index 1c8f9a3..5deefd5 100644
--- a/include/views/SkWindow.h
+++ b/include/views/SkWindow.h
@@ -19,6 +19,7 @@
 
 #include "SkView.h"
 #include "SkBitmap.h"
+#include "SkMatrix.h"
 #include "SkRegion.h"
 #include "SkEvent.h"
 #include "SkKey.h"
@@ -29,6 +30,8 @@
 #endif
 //#define USE_GX_SCREEN
 
+class SkCanvas;
+
 class SkOSMenu;
 
 class SkWindow : public SkView {
@@ -44,7 +47,13 @@
     void    eraseRGB(U8CPU r, U8CPU g, U8CPU b);
 
     bool    isDirty() const { return !fDirtyRgn.isEmpty(); }
-    bool    update(SkIRect* updateArea);
+    bool    update(SkIRect* updateArea, SkCanvas* = NULL);
+    // does not call through to onHandleInval(), but does force the fDirtyRgn
+    // to be wide open. Call before update() to ensure we redraw everything.
+    void    forceInvalAll();
+    // return the bounds of the dirty/inval rgn, or [0,0,0,0] if none
+    const SkIRect& getDirtyBounds() const { return fDirtyRgn.getBounds(); }
+
     bool    handleClick(int x, int y, Click::State);
     bool    handleChar(SkUnichar);
     bool    handleKey(SkKey);
@@ -56,6 +65,11 @@
     const char* getTitle() const { return fTitle.c_str(); }
     void    setTitle(const char title[]);
 
+    const SkMatrix& getMatrix() const { return fMatrix; }
+    void    setMatrix(const SkMatrix&);
+    void    preConcat(const SkMatrix&);
+    void    postConcat(const SkMatrix&);
+
 protected:
     virtual bool onEvent(const SkEvent&);
 
@@ -68,7 +82,7 @@
     virtual void onSetTitle(const char title[]) {}
 
     // overrides from SkView
-    virtual bool handleInval(const SkRect&);
+    virtual bool handleInval(const SkRect*);
     virtual bool onGetFocusView(SkView** focus) const;
     virtual bool onSetFocusView(SkView* focus);
 
@@ -84,6 +98,7 @@
     bool    fWaitingOnInval;
     
     SkString    fTitle;
+    SkMatrix    fMatrix;
 
     typedef SkView INHERITED;
 };
@@ -100,6 +115,8 @@
   #include "SkOSWindow_Unix.h"
 #elif defined(SK_BUILD_FOR_SDL)
     #include "SkOSWindow_SDL.h"
+#elif defined(SK_BUILD_FOR_IOS)
+    #include "SkOSWindow_iOS.h"
 #endif
 
 #endif
diff --git a/samplecode/SampleAll.cpp b/samplecode/SampleAll.cpp
index 7e83dec..bc24cd3 100644
--- a/samplecode/SampleAll.cpp
+++ b/samplecode/SampleAll.cpp
@@ -37,7 +37,7 @@
     unsigned g = SkGetPackedG32(c);
     unsigned b = SkGetPackedB32(c);
     
-    unsigned x = r * 5 + g * 7 + b * 4 >> 4;
+    unsigned x = (r * 5 + g * 7 + b * 4) >> 4;
     
     return SkPackARGB32(0, x, x, x) | (c & (SK_A32_MASK << SK_A32_SHIFT));
 }
@@ -346,7 +346,7 @@
 static void test_math()
 {
     float x;
-    const float PI = 3.141593;
+    const float PI = 3.141593f;
     
     for (x = 0; x < 1; x += 0.05f)
         printf("atan(%g) = %g\n", x, atanf(x) * 180/PI);
diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp
index 2bd1fe0..b9e7b48 100644
--- a/samplecode/SampleApp.cpp
+++ b/samplecode/SampleApp.cpp
@@ -1,6 +1,7 @@
+#include <OpenGL/gl.h>
+
 #include "SkCanvas.h"
 #include "SkDevice.h"
-#include "SkGLCanvas.h"
 #include "SkGraphics.h"
 #include "SkImageEncoder.h"
 #include "SkPaint.h"
@@ -11,19 +12,33 @@
 
 #include "SampleCode.h"
 
+#ifdef SUPPORT_GPU
+    #include "SkGpuCanvas.h"
+    #include "GrContext.h"
+
+    #ifdef SK_SUPPORT_GL
+        #include "GrGLConfig.h"
+    #elif defined(SK_SUPPORT_D3D9)
+        #include <d3d9.h>
+    #endif
+#else
+    typedef SkCanvas SkGpuCanvas;
+    class GrContext;
+#endif
+
+//#define DEFAULT_TO_GPU
+
 extern SkView* create_overview(int, const SkViewFactory[]);
 
 #define SK_SUPPORT_GL
-
-#ifdef SK_SUPPORT_GL
-#include <AGL/agl.h>
-#include <OpenGL/gl.h>
-#endif
+//#define SK_SUPPORT_D3D9
 
 #define ANIMATING_EVENTTYPE "nextSample"
 #define ANIMATING_DELAY     750
 
-#define USE_OFFSCREEN
+#if !defined(SK_BUILD_FOR_WIN32)
+//#define USE_OFFSCREEN
+#endif
 
 SkViewRegister* SkViewRegister::gHead;
 SkViewRegister::SkViewRegister(SkViewFactory fact) : fFact(fact) {
@@ -37,69 +52,65 @@
     gHead = this;
 }
 
-#ifdef SK_SUPPORT_GL
-static AGLContext   gAGLContext;
-
-static void init_gl(WindowRef wref) {
-    GLint major, minor;
-    
-    aglGetVersion(&major, &minor);
-    SkDebugf("---- agl version %d %d\n", major, minor);
-    
-    const GLint pixelAttrs[] = {
-        AGL_RGBA,
-        AGL_DEPTH_SIZE, 32,
-        AGL_OFFSCREEN,
-        AGL_NONE
-    };
-    
-    AGLPixelFormat format = aglCreatePixelFormat(pixelAttrs);
-    SkDebugf("----- agl format %p\n", format);
-    gAGLContext = aglCreateContext(format, NULL);
-    SkDebugf("----- agl context %p\n", gAGLContext);
-    aglDestroyPixelFormat(format);
-
-    aglEnable(gAGLContext, GL_BLEND);
-    aglEnable(gAGLContext, GL_LINE_SMOOTH);
-    aglEnable(gAGLContext, GL_POINT_SMOOTH);
-    aglEnable(gAGLContext, GL_POLYGON_SMOOTH);
-    
-    aglSetCurrentContext(gAGLContext);
-}
-
-static void setup_offscreen_gl(const SkBitmap& offscreen, WindowRef wref) {
-    GLboolean success = true;
-
-#ifdef USE_OFFSCREEN
-    success = aglSetOffScreen(gAGLContext,
-                                        offscreen.width(),
-                                        offscreen.height(),
-                                        offscreen.rowBytes(),
-                                        offscreen.getPixels());
-#else
-    success = aglSetWindowRef(gAGLContext, wref);
+#if defined(SK_SUPPORT_GL) && defined(SK_SUPPORT_D3D9)
+    #error "choose either GL or D3D9"
 #endif
 
-    GLenum err = aglGetError();
-    if (err) {
-        SkDebugf("---- setoffscreen %d %d %s [%d %d]\n", success, err,
-                 aglErrorString(err), offscreen.width(), offscreen.height());
+#if defined(SK_SUPPORT_GL)
+    #define SK_USE_SHADERS
+#endif
+
+static GrContext* get_global_grctx(SkOSWindow* oswin) {
+#ifdef SUPPORT_GPU
+    // should be pthread-local at least
+    static GrContext* ctx;
+    if (NULL == ctx) {
+#if defined(SK_SUPPORT_GL)
+    #if defined(SK_USE_SHADERS)
+        ctx = GrContext::Create(GrGpu::kOpenGL_Shaders_Engine, NULL);
+    #else
+        ctx = GrContext::Create(GrGpu::kOpenGL_Fixed_Engine, NULL);
+    #endif
+#elif defined(SK_SUPPORT_D3D9)
+        if (oswin->d3d9Device()) {
+            ctx = GrContext::Create(GrGpu::kDirect3D9_Engine, 
+                                    (IDirect3DDevice9*) oswin->d3d9Device());
+        }
+#endif
     }
-    
-    glEnable(GL_BLEND);
-    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-    glHint(GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
-    glEnable(GL_TEXTURE_2D);
-
-    glClearColor(0, 0, 0, 0);
-    glClear(GL_COLOR_BUFFER_BIT);
-}
+    return ctx;
+#else
+    return NULL;
 #endif
+}
 
 //////////////////////////////////////////////////////////////////////////////
 
+static const char gCharEvtName[] = "SampleCode_Char_Event";
+static const char gKeyEvtName[] = "SampleCode_Key_Event";
 static const char gTitleEvtName[] = "SampleCode_Title_Event";
 static const char gPrefSizeEvtName[] = "SampleCode_PrefSize_Event";
+static const char gFastTextEvtName[] = "SampleCode_FastText_Event";
+
+bool SampleCode::CharQ(const SkEvent& evt, SkUnichar* outUni) {
+    if (evt.isType(gCharEvtName, sizeof(gCharEvtName) - 1)) {
+        if (outUni) {
+            *outUni = evt.getFast32();
+        }
+        return true;
+    }
+    return false;
+}
+
+bool SampleCode::KeyQ(const SkEvent& evt, SkKey* outKey) {
+    if (evt.isType(gKeyEvtName, sizeof(gKeyEvtName) - 1)) {
+        if (outKey) {
+            *outKey = (SkKey)evt.getFast32();
+        }
+        return true;
+    }
+    return false;
+}
 
 bool SampleCode::TitleQ(const SkEvent& evt) {
     return evt.isType(gTitleEvtName, sizeof(gTitleEvtName) - 1);
@@ -122,20 +133,40 @@
     evt->setScalars(gPrefSizeEvtName, 2, size);
 }
 
+bool SampleCode::FastTextQ(const SkEvent& evt) {
+    return evt.isType(gFastTextEvtName, sizeof(gFastTextEvtName) - 1);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 static SkMSec gAnimTime;
+static SkMSec gAnimTimePrev;
+
 SkMSec SampleCode::GetAnimTime() { return gAnimTime; }
+SkMSec SampleCode::GetAnimTimeDelta() { return gAnimTime - gAnimTimePrev; }
+SkScalar SampleCode::GetAnimSecondsDelta() {
+    return SkDoubleToScalar(GetAnimTimeDelta() / 1000.0);
+}
 
 SkScalar SampleCode::GetAnimScalar(SkScalar speed, SkScalar period) {
-    SkScalar seconds = SkFloatToScalar(gAnimTime / 1000.0f);
-    SkScalar value = SkScalarMul(speed, seconds);
+    // since gAnimTime can be up to 32 bits, we can't convert it to a float
+    // or we'll lose the low bits. Hence we use doubles for the intermediate
+    // calculations
+    double seconds = (double)gAnimTime / 1000.0;
+    double value = SkScalarToDouble(speed) * seconds;
     if (period) {
-        value = SkScalarMod(value, period);
+        value = ::fmod(value, SkScalarToDouble(period));
     }
-    return value;
+    return SkDoubleToScalar(value);
 }
 
 //////////////////////////////////////////////////////////////////////////////
 
+static SkView* curr_view(SkWindow* wind) {
+    SkView::F2BIter iter(wind);
+    return iter.next();
+}
+
 class SampleWindow : public SkOSWindow {
     SkTDArray<SkViewFactory> fSamples;
 public:
@@ -156,6 +187,7 @@
     virtual void afterChild(SkView* child, SkCanvas* canvas);
     
 	virtual bool onEvent(const SkEvent& evt);
+    virtual bool onQuery(SkEvent* evt);
 
 #if 0
 	virtual bool handleChar(SkUnichar uni);
@@ -171,13 +203,13 @@
     int fCurrIndex;
     
     SkPicture* fPicture;
-    SkGLCanvas* fGLCanvas;
+    SkGpuCanvas* fGpuCanvas;
     SkPath fClipPath;
     
     enum CanvasType {
         kRaster_CanvasType,
         kPicture_CanvasType,
-        kOpenGL_CanvasType
+        kGPU_CanvasType
     };
     CanvasType fCanvasType;
 
@@ -187,6 +219,7 @@
     bool fAnimating;
     bool fRotate;
     bool fScale;
+    bool fRequestGrabImage;
     
     int fScrollTestX, fScrollTestY;
     
@@ -210,33 +243,35 @@
 SampleWindow::CanvasType SampleWindow::cycle_canvastype(CanvasType ct) {
     static const CanvasType gCT[] = {
         kPicture_CanvasType,
-        kOpenGL_CanvasType,
+        kGPU_CanvasType,
         kRaster_CanvasType
     };
     return gCT[ct];
 }
 
 SampleWindow::SampleWindow(void* hwnd) : INHERITED(hwnd) {
-#ifdef SK_SUPPORT_GL
-    init_gl((WindowRef)hwnd);
-#endif
-
     fPicture = NULL;
-    fGLCanvas = NULL;
+    fGpuCanvas = NULL;
 
+#ifdef DEFAULT_TO_GPU
+    fCanvasType = kGPU_CanvasType;
+#else
     fCanvasType = kRaster_CanvasType;
+#endif
     fUseClip = false;
     fNClip = false;
     fRepeatDrawing = false;
     fAnimating = false;
     fRotate = false;
     fScale = false;
+    fRequestGrabImage = false;
 
     fScrollTestX = fScrollTestY = 0;
 
 //	this->setConfig(SkBitmap::kRGB_565_Config);
 	this->setConfig(SkBitmap::kARGB_8888_Config);
 	this->setVisibleP(true);
+    this->setClipToBounds(false);
 
     {
         const SkViewRegister* reg = SkViewRegister::Head();
@@ -251,7 +286,7 @@
 
 SampleWindow::~SampleWindow() {
     delete fPicture;
-    delete fGLCanvas;
+    delete fGpuCanvas;
 }
 
 static SkBitmap capture_bitmap(SkCanvas* canvas) {
@@ -284,6 +319,7 @@
 
 void SampleWindow::draw(SkCanvas* canvas) {
     // update the animation time
+    gAnimTimePrev = gAnimTime;
     gAnimTime = SkTime::GetMSecs();
 
     if (fNClip) {
@@ -346,11 +382,17 @@
 }
 
 SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) {
+    SkIPoint viewport;
+    bool alreadyGPU = canvas->getViewport(&viewport);
+    
+    if (kGPU_CanvasType != fCanvasType) {
 #ifdef SK_SUPPORT_GL
-#ifndef USE_OFFSCREEN
-    aglSetWindowRef(gAGLContext, NULL);
-#endif
-#endif
+        detachGL();
+#elif defined(SK_SUPPORT_D3D9)
+        detachD3D9();
+#endif   
+    }
+    
     switch (fCanvasType) {
         case kRaster_CanvasType:
             canvas = this->INHERITED::beforeChildren(canvas);
@@ -359,20 +401,35 @@
             fPicture = new SkPicture;
             canvas = fPicture->beginRecording(9999, 9999);
             break;
-#ifdef SK_SUPPORT_GL
-        case kOpenGL_CanvasType: {
-            //SkGLCanvas::DeleteAllTextures();  // just for testing
-            SkDevice* device = canvas->getDevice();
-            const SkBitmap& bitmap = device->accessBitmap(true);
-            // first clear the raster bitmap, so we don't see any leftover bits
-            bitmap.eraseColor(0);
-            // now setup our glcanvas
-            setup_offscreen_gl(bitmap, (WindowRef)this->getHWND());
-            fGLCanvas = new SkGLCanvas;
-            fGLCanvas->setViewport(bitmap.width(), bitmap.height());
-            canvas = fGLCanvas;
+#ifdef SUPPORT_GPU
+        case kGPU_CanvasType:
+            if (!alreadyGPU) {
+                SkDevice* device = canvas->getDevice();
+                const SkBitmap& bitmap = device->accessBitmap(true);            
+#ifdef SK_SUPPORT_GL                
+    #ifdef USE_OFFSCREEN
+                // first clear the raster bitmap, so we don't see any leftover bits
+                bitmap.eraseColor(0);
+                // now setup our glcanvas
+                attachGL(&bitmap);
+    #else
+                attachGL(NULL);
+    #endif
+                glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+#elif defined(SK_SUPPORT_D3D9)
+                // now setup our canvas
+                attachD3D9();           
+#endif
+                SkBitmap viewport;
+                viewport.setConfig(SkBitmap::kARGB_8888_Config, bitmap.width(), bitmap.height());
+                fGpuCanvas = new SkGpuCanvas(get_global_grctx(this));
+                fGpuCanvas->setBitmapDevice(viewport);
+                canvas = fGpuCanvas;
+                
+            } else {
+                canvas = this->INHERITED::beforeChildren(canvas);
+            }
             break;
-        }
 #endif
     }
 
@@ -395,6 +452,22 @@
 }
 
 void SampleWindow::afterChildren(SkCanvas* orig) {
+    if (fRequestGrabImage) {
+        fRequestGrabImage = false;
+        
+        SkCanvas* canvas = fGpuCanvas ? fGpuCanvas : orig;
+        SkDevice* device = canvas->getDevice();
+        SkBitmap bitmap;
+        SkIRect bounds = { 0, 0, this->width(), this->height() };
+        if (device->readPixels(bounds, &bitmap)) {
+            static int gSampleGrabCounter;
+            SkString name;
+            name.printf("sample_grab_%d", gSampleGrabCounter++);
+            SkImageEncoder::EncodeFile(name.c_str(), bitmap,
+                                       SkImageEncoder::kPNG_Type, 100);
+        }
+    }
+
     switch (fCanvasType) {
         case kRaster_CanvasType:
             break;
@@ -419,19 +492,27 @@
             fPicture = NULL;
             break;
 #ifdef SK_SUPPORT_GL
-        case kOpenGL_CanvasType:
-            glFlush();
-            delete fGLCanvas;
-            fGLCanvas = NULL;
+        case kGPU_CanvasType:
+            delete fGpuCanvas;
+            fGpuCanvas = NULL;
+            presentGL();
 #ifdef USE_OFFSCREEN
             reverseRedAndBlue(orig->getDevice()->accessBitmap(true));
 #endif
             break;
+#elif defined(SK_SUPPORT_D3D9)
+        case kGPU_CanvasType: {
+            delete fGpuCanvas;
+            fGpuCanvas = NULL;
+            presentD3D9();
+            break;
+        }
 #endif
+
     }
     
 //    if ((fScrollTestX | fScrollTestY) != 0)
-    {
+    if (false) {
         const SkBitmap& bm = orig->getDevice()->accessBitmap(true);
         int dx = fScrollTestX * 7;
         int dy = fScrollTestY * 7;
@@ -501,6 +582,27 @@
     return this->INHERITED::onEvent(evt);
 }
 
+bool SampleWindow::onQuery(SkEvent* query) {
+    if (query->isType("get-slide-count")) {
+        query->setFast32(fSamples.count());
+        return true;
+    }
+    if (query->isType("get-slide-title")) {
+        SkView* view = fSamples[query->getFast32()]();
+        SkEvent evt(gTitleEvtName);
+        if (view->doQuery(&evt)) {
+            query->setString("title", evt.findString(gTitleEvtName));
+        }
+        SkSafeUnref(view);
+        return true;
+    }
+    if (query->isType("use-fast-text")) {
+        SkEvent evt(gFastTextEvtName);
+        return curr_view(this)->doQuery(&evt);
+    }
+    return this->INHERITED::onQuery(query);
+}
+
 static void cleanup_for_filename(SkString* name) {
     char* str = name->writable_str();
     for (size_t i = 0; i < name->size(); i++) {
@@ -514,6 +616,17 @@
 }
 
 bool SampleWindow::onHandleChar(SkUnichar uni) {
+    {
+        SkView* view = curr_view(this);
+        if (view) {
+            SkEvent evt(gCharEvtName);
+            evt.setFast32(uni);
+            if (view->doQuery(&evt)) {
+                return true;
+            }
+        }
+    }
+    
     int dx = 0xFF;
     int dy = 0xFF;
 
@@ -573,6 +686,13 @@
             this->inval(NULL);
             this->updateTitle();
             return true;
+        case 'd':
+            SkGraphics::SetFontCacheUsed(0);
+            return true;
+        case 'g':
+            fRequestGrabImage = true;
+            this->inval(NULL);
+            break;
         default:
             break;
     }
@@ -583,6 +703,17 @@
 #include "SkDumpCanvas.h"
 
 bool SampleWindow::onHandleKey(SkKey key) {
+    {
+        SkView* view = curr_view(this);
+        if (view) {
+            SkEvent evt(gKeyEvtName);
+            evt.setFast32(key);
+            if (view->doQuery(&evt)) {
+                return true;
+            }
+        }
+    }
+
     switch (key) {
         case kRight_SkKey:
             if (this->nextSample()) {
@@ -604,7 +735,7 @@
             this->updateTitle();
             return true;
         case kOK_SkKey:
-            if (true) {
+            if (false) {
                 SkDebugfDumper dumper;
                 SkDumpCanvas dc(&dumper);
                 this->draw(&dc);
@@ -635,6 +766,7 @@
         view = create_overview(fSamples.count(), fSamples.begin());
     }
     view->setVisibleP(true);
+    view->setClipToBounds(false);
     this->attachChildToFront(view)->unref();
     view->setSize(this->width(), this->height());
 
@@ -728,7 +860,108 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+template <typename T> void SkTBSort(T array[], int count) {
+    for (int i = 1; i < count - 1; i++) {
+        bool didSwap = false;
+        for (int j = count - 1; j > i; --j) {
+            if (array[j] < array[j-1]) {
+                T tmp(array[j-1]);
+                array[j-1] = array[j];
+                array[j] = tmp;
+                didSwap = true;
+            }
+        }
+        if (!didSwap) {
+            break;
+        }
+    }
+    
+    for (int k = 0; k < count - 1; k++) {
+        SkASSERT(!(array[k+1] < array[k]));
+    }
+}
+
+#include "SkRandom.h"
+
+static void rand_rect(SkIRect* rect, SkRandom& rand) {
+    int bits = 8;
+    int shift = 32 - bits;
+    rect->set(rand.nextU() >> shift, rand.nextU() >> shift,
+              rand.nextU() >> shift, rand.nextU() >> shift);
+    rect->sort();
+}
+
+static void dumpRect(const SkIRect& r) {
+    SkDebugf(" { %d, %d, %d, %d },\n",
+             r.fLeft, r.fTop,
+             r.fRight, r.fBottom);
+}
+
+static void test_rects(const SkIRect rect[], int count) {
+    SkRegion rgn0, rgn1;
+
+    for (int i = 0; i < count; i++) {
+        rgn0.op(rect[i], SkRegion::kUnion_Op);
+     //   dumpRect(rect[i]);
+    }
+    rgn1.setRects(rect, count);
+
+    if (rgn0 != rgn1) {
+        SkDebugf("\n");
+        for (int i = 0; i < count; i++) {
+            dumpRect(rect[i]);
+        }
+        SkDebugf("\n");
+    }
+}
+
+static void test() {
+    size_t i;
+
+    const SkIRect r0[] = {
+        { 0, 0, 1, 1 },
+        { 2, 2, 3, 3 },
+    };
+    const SkIRect r1[] = {
+        { 0, 0, 1, 3 },
+        { 1, 1, 2, 2 },
+        { 2, 0, 3, 3 },
+    };
+    const SkIRect r2[] = {
+        { 0, 0, 1, 2 },
+        { 2, 1, 3, 3 },
+        { 4, 0, 5, 1 },
+        { 6, 0, 7, 4 },
+    };
+
+    static const struct {
+        const SkIRect* fRects;
+        int            fCount;
+    } gRecs[] = {
+        { r0, SK_ARRAY_COUNT(r0) },
+        { r1, SK_ARRAY_COUNT(r1) },
+        { r2, SK_ARRAY_COUNT(r2) },
+    };
+
+    for (i = 0; i < SK_ARRAY_COUNT(gRecs); i++) {
+        test_rects(gRecs[i].fRects, gRecs[i].fCount);
+    }
+    
+    SkRandom rand;
+    for (i = 0; i < 10000; i++) {
+        SkRegion rgn0, rgn1;
+
+        const int N = 8;
+        SkIRect rect[N];
+        for (int j = 0; j < N; j++) {
+            rand_rect(&rect[j], rand);
+        }
+        test_rects(rect, N);
+    }
+}
+
 SkOSWindow* create_sk_window(void* hwnd) {
+//    test();
 	return new SampleWindow(hwnd);
 }
 
diff --git a/samplecode/SampleBitmapRect.cpp b/samplecode/SampleBitmapRect.cpp
index 0d981d6..0c1cd7a 100644
--- a/samplecode/SampleBitmapRect.cpp
+++ b/samplecode/SampleBitmapRect.cpp
@@ -75,12 +75,12 @@
         for (size_t i = 0; i < SK_ARRAY_COUNT(src); i++) {
             SkRect srcR;
             srcR.set(src[i]);
-            
+
             canvas->drawBitmap(fBitmap, 0, 0, &paint);
             canvas->drawBitmapRect(fBitmap, &src[i], dstR, &paint);
 
-            canvas->drawRect(srcR, paint);
             canvas->drawRect(dstR, paint);
+            canvas->drawRect(srcR, paint);
             
             canvas->translate(160, 0);
         }
diff --git a/samplecode/SampleCamera.cpp b/samplecode/SampleCamera.cpp
index 4d50b5a..c71cc43 100644
--- a/samplecode/SampleCamera.cpp
+++ b/samplecode/SampleCamera.cpp
@@ -9,22 +9,46 @@
 #include "SkShader.h"
 #include "SkUtils.h"
 #include "SkRandom.h"
+#include "SkImageDecoder.h"
 
 class CameraView : public SkView {
+    SkTDArray<SkShader*> fShaders;
+    int     fShaderIndex;
+    bool    fFrontFace;
 public:
-	CameraView()
-    {
+	CameraView() {
         fRX = fRY = fRZ = 0;
+        fShaderIndex = 0;
+        fFrontFace = false;
+
+        for (int i = 0;; i++) {
+            SkString str;
+            str.printf("/skimages/elephant%d.jpeg", i);
+            SkBitmap bm;
+            if (SkImageDecoder::DecodeFile(str.c_str(), &bm)) {
+                SkShader* s = SkShader::CreateBitmapShader(bm,
+                                                           SkShader::kClamp_TileMode,
+                                                           SkShader::kClamp_TileMode);
+                
+                SkRect src = { 0, 0, bm.width(), bm.height() };
+                SkRect dst = { -150, -150, 150, 150 };
+                SkMatrix matrix;
+                matrix.setRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
+                s->setLocalMatrix(matrix);
+                *fShaders.append() = s;
+            } else {
+                break;
+            }
+        }
     }
     
-    virtual ~CameraView()
-    {
+    virtual ~CameraView() {
+        fShaders.unrefAll();
     }
 
 protected:
     // overrides from SkEventSink
-    virtual bool onQuery(SkEvent* evt)
-    {
+    virtual bool onQuery(SkEvent* evt) {
         if (SampleCode::TitleQ(*evt))
         {
             SampleCode::TitleR(evt, "Camera");
@@ -32,69 +56,54 @@
         }
         return this->INHERITED::onQuery(evt);
     }
-    
-    void drawBG(SkCanvas* canvas)
-    {
+
+    void drawBG(SkCanvas* canvas) {
         canvas->drawColor(0xFFDDDDDD);
     }
     
-    virtual void onDraw(SkCanvas* canvas)
-    {
+    virtual void onDraw(SkCanvas* canvas) {
         this->drawBG(canvas);
 
         canvas->translate(this->width()/2, this->height()/2);
 
         Sk3DView    view;
-        view.rotateX(SkIntToScalar(fRX));
-        view.rotateY(SkIntToScalar(fRY));
+        view.rotateX(fRX);
+        view.rotateY(fRY);
         view.applyToCanvas(canvas);
         
         SkPaint paint;
         SkScalar rad = SkIntToScalar(50);
         SkScalar dim = rad*2;
-
-        if (view.dotWithNormal(0, 0, SK_Scalar1) < 0) {
-            paint.setColor(SK_ColorRED);
+        if (fShaders.count() > 0) {
+            bool frontFace = view.dotWithNormal(0, 0, SK_Scalar1) < 0;
+            if (frontFace != fFrontFace) {
+                fFrontFace = frontFace;
+                fShaderIndex = (fShaderIndex + 1) % fShaders.count();
+            }
+        
+            paint.setAntiAlias(true);
+            paint.setShader(fShaders[fShaderIndex]);
+#if 0
+            canvas->drawCircle(0, 0, rad, paint);
+            canvas->drawCircle(-dim, -dim, rad, paint);
+            canvas->drawCircle(-dim,  dim, rad, paint);
+            canvas->drawCircle( dim, -dim, rad, paint);
+            canvas->drawCircle( dim,  dim, rad, paint);
+#else
+            SkRect r = { -150, -150, 150, 150 };
+            canvas->drawRoundRect(r, 30, 30, paint);
+#endif
         }
         
-        paint.setAntiAlias(true);
-
-#if 0
-        SkEmbossMaskFilter::Light light;
-        light.fDirection[0] = SK_Scalar1;
-        light.fDirection[1] = SK_Scalar1;
-        light.fDirection[2] = SK_Scalar1;
-        light.fAmbient = 180;
-        light.fSpecular = 16 * 2;
-        paint.setMaskFilter(new SkEmbossMaskFilter(light, SkIntToScalar(4)));
-#endif
-
-        canvas->drawCircle(0, 0, rad, paint);
-        canvas->drawCircle(-dim, -dim, rad, paint);
-        canvas->drawCircle(-dim,  dim, rad, paint);
-        canvas->drawCircle( dim, -dim, rad, paint);
-        canvas->drawCircle( dim,  dim, rad, paint);
-        
-        fRY += 1;
-        if (fRY >= 360)
+        fRY += SampleCode::GetAnimSecondsDelta() * 90;
+        if (fRY >= SkIntToScalar(360)) {
             fRY = 0;
+        }
         this->inval(NULL);
     }
 
-    virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) 
-    {
-        SkScalar angle = SkScalarDiv(this->height()/2 - y, this->height());
-        fRX = SkScalarRound(angle * 180);
-        return this->INHERITED::onFindClickHandler(x, y);
-    }
-    
-    virtual bool onClick(Click* click) 
-    {
-        return this->INHERITED::onClick(click);
-    }
-    
 private:
-    int fRX, fRY, fRZ;
+    SkScalar fRX, fRY, fRZ;
     typedef SkView INHERITED;
 };
 
diff --git a/samplecode/SampleCircle.cpp b/samplecode/SampleCircle.cpp
index b250f29..8f0436b 100644
--- a/samplecode/SampleCircle.cpp
+++ b/samplecode/SampleCircle.cpp
@@ -19,9 +19,9 @@
 
 class CircleView : public SkView {
 public:
-    static const SkScalar ANIM_DX = SK_Scalar1 / 67;
-    static const SkScalar ANIM_DY = SK_Scalar1 / 29;
-    static const SkScalar ANIM_RAD = SK_Scalar1 / 19;
+    static const SkScalar ANIM_DX;
+    static const SkScalar ANIM_DY;
+    static const SkScalar ANIM_RAD;
     SkScalar fDX, fDY, fRAD;
 
     CircleView() {
@@ -97,7 +97,7 @@
 
     virtual void onDraw(SkCanvas* canvas) {
         this->drawBG(canvas);
-        
+
         SkPaint paint;
         paint.setAntiAlias(true);
         paint.setStyle(SkPaint::kStroke_Style);
@@ -127,16 +127,16 @@
             canvas->translate(dx, 0);
             canvas->translate(SK_ScalarHalf, SK_ScalarHalf);
             drawSix(canvas, dx, dy);
-        }
         
-        fDX += ANIM_DX;
-        fDY += ANIM_DY;
-        fRAD += ANIM_RAD;
-        fN += 1;
-        if (fN > 40) {
-            fN = 3;
+            fDX += ANIM_DX;
+            fDY += ANIM_DY;
+            fRAD += ANIM_RAD;
+            fN += 1;
+            if (fN > 40) {
+                fN = 3;
+            }
+            this->inval(NULL);
         }
-        this->inval(NULL);
     }
     
 private:
@@ -144,9 +144,9 @@
     typedef SkView INHERITED;
 };
 
-const SkScalar CircleView::ANIM_DX;
-const SkScalar CircleView::ANIM_DY;
-const SkScalar CircleView::ANIM_RAD;
+const SkScalar CircleView::ANIM_DX(SK_Scalar1 / 67);
+const SkScalar CircleView::ANIM_DY(SK_Scalar1 / 29);
+const SkScalar CircleView::ANIM_RAD(SK_Scalar1 / 19);
 
 //////////////////////////////////////////////////////////////////////////////
 
diff --git a/samplecode/SampleCode.h b/samplecode/SampleCode.h
index c901af3..058985a 100644
--- a/samplecode/SampleCode.h
+++ b/samplecode/SampleCode.h
@@ -2,16 +2,24 @@
 #define SampleCode_DEFINED
 
 #include "SkEvent.h"
+#include "SkKey.h"
 
 class SampleCode {
 public:
+    static bool KeyQ(const SkEvent&, SkKey* outKey);
+    static bool CharQ(const SkEvent&, SkUnichar* outUni);
+
     static bool TitleQ(const SkEvent&);
     static void TitleR(SkEvent*, const char title[]);
     
     static bool PrefSizeQ(const SkEvent&);
     static void PrefSizeR(SkEvent*, SkScalar width, SkScalar height);
-    
+
+    static bool FastTextQ(const SkEvent&);
+
     static SkMSec GetAnimTime();
+    static SkMSec GetAnimTimeDelta();
+    static SkScalar GetAnimSecondsDelta();
     static SkScalar GetAnimScalar(SkScalar speedPerSec, SkScalar period = 0);
 };
 
diff --git a/samplecode/SampleDrawLooper.cpp b/samplecode/SampleDrawLooper.cpp
index 1a7a870..7ea7b75 100644
--- a/samplecode/SampleDrawLooper.cpp
+++ b/samplecode/SampleDrawLooper.cpp
@@ -6,8 +6,6 @@
 #include "SkLayerDrawLooper.h"
 #include "SkBlurMaskFilter.h"
 
-#include <pthread.h>
-
 #define WIDTH   200
 #define HEIGHT  200
 
diff --git a/samplecode/SampleGM.cpp b/samplecode/SampleGM.cpp
index 095dfe6..d85cad1 100644
--- a/samplecode/SampleGM.cpp
+++ b/samplecode/SampleGM.cpp
@@ -6,13 +6,6 @@
 
 using namespace skiagm;
 
-GM::GM() {}
-GM::~GM() {}
-
-void GM::draw(SkCanvas* canvas) {
-	this->onDraw(canvas);
-}
-
 // need to explicitly declare this, or we get some weird infinite loop llist
 template GMRegistry* GMRegistry::gHead;
 
@@ -82,3 +75,15 @@
 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);
+}
+
+
diff --git a/samplecode/SampleGradients.cpp b/samplecode/SampleGradients.cpp
index f3705bc..8c65fe0 100644
--- a/samplecode/SampleGradients.cpp
+++ b/samplecode/SampleGradients.cpp
@@ -130,7 +130,6 @@
         SkShader::TileMode tm = SkShader::kClamp_TileMode;
         SkRect r = { 0, 0, SkIntToScalar(100), SkIntToScalar(100) };
         SkPaint paint;
-        paint.setAntiAlias(true);
         paint.setDither(true);
 
         canvas->save();
@@ -138,10 +137,10 @@
         for (size_t i = 0; i < SK_ARRAY_COUNT(gGradData); i++) {
             canvas->save();
             for (size_t j = 0; j < SK_ARRAY_COUNT(gGradMakers); j++) {
-                SkShader* shader = gGradMakers[j](pts, gGradData[i], tm, NULL);
-                paint.setShader(shader);
+                SkShader* shader;
+                shader = gGradMakers[j](pts, gGradData[i], tm, NULL);
+                paint.setShader(shader)->unref();
                 canvas->drawRect(r, paint);
-                shader->unref();
                 canvas->translate(0, SkIntToScalar(120));
             }
             canvas->restore();
@@ -151,6 +150,7 @@
         
         canvas->translate(0, SkIntToScalar(370));
      //   test_alphagradients(canvas);
+        this->inval(NULL);
     }
     
 private:
diff --git a/samplecode/SampleLayers.cpp b/samplecode/SampleLayers.cpp
index ae8bd33..f1e8dd8 100644
--- a/samplecode/SampleLayers.cpp
+++ b/samplecode/SampleLayers.cpp
@@ -161,7 +161,7 @@
             SkPaint p;
             canvas->saveLayer(&r, &p);
             canvas->drawColor(0xFFFF0000);
-            p.setAlpha(1);  // or 0
+            p.setAlpha(0);  // or 0
             p.setXfermodeMode(SkXfermode::kSrc_Mode);
             canvas->drawOval(r, p);
             canvas->restore();
diff --git a/samplecode/SampleLines.cpp b/samplecode/SampleLines.cpp
index a0238b0..4d05a9a 100644
--- a/samplecode/SampleLines.cpp
+++ b/samplecode/SampleLines.cpp
@@ -82,11 +82,11 @@
         r.set(x, y, x + SkIntToScalar(100), y + SkIntToScalar(100));
         
         SkPaint paint;
-        paint.setAntiAlias(true);
+     //   paint.setAntiAlias(true);
         paint.setStyle(SkPaint::kStroke_Style);
         paint.setStrokeWidth(SkScalarHalf(SkIntToScalar(3)));
         paint.setColor(0xFFFF8800);
-        paint.setColor(0xFFFFFFFF);
+     //   paint.setColor(0xFFFFFFFF);
         canvas->drawRect(r, paint);
     }
     
diff --git a/samplecode/SampleMipMap.cpp b/samplecode/SampleMipMap.cpp
index 07227e5..6e0efe0 100644
--- a/samplecode/SampleMipMap.cpp
+++ b/samplecode/SampleMipMap.cpp
@@ -31,7 +31,7 @@
 class MipMapView : public SkView {
     SkBitmap fBitmap;
     enum {
-        N = 90
+        N = 64
     };
 public:
     MipMapView() {
@@ -44,7 +44,7 @@
     // overrides from SkEventSink
     virtual bool onQuery(SkEvent* evt) {
         if (SampleCode::TitleQ(*evt)) {
-            SampleCode::TitleR(evt, "MapMaps");
+            SampleCode::TitleR(evt, "MipMaps");
             return true;
         }
         return this->INHERITED::onQuery(evt);
diff --git a/samplecode/SamplePatch.cpp b/samplecode/SamplePatch.cpp
index 3f898bc..fb70dba 100644
--- a/samplecode/SamplePatch.cpp
+++ b/samplecode/SamplePatch.cpp
@@ -35,7 +35,7 @@
     SkBitmap    bm;
     
 //    SkImageDecoder::DecodeFile("/skimages/progressivejpg.jpg", &bm);
-    SkImageDecoder::DecodeFile("/skimages/beach.jpg", &bm);
+    SkImageDecoder::DecodeFile("/skimages/logo.png", &bm);
     size->set(bm.width(), bm.height());
     return SkShader::CreateBitmapShader(bm, SkShader::kClamp_TileMode,
                                         SkShader::kClamp_TileMode);
@@ -279,77 +279,6 @@
         SkPaint paint;
         paint.setDither(true);
         paint.setFilterBitmap(true);
-
-        if (false) {
-            SkPath p;
-            p.moveTo(0, 0);
-            p.lineTo(SkIntToScalar(30000), SkIntToScalar(30000));
-            paint.setStyle(SkPaint::kStroke_Style);
-            paint.setStrokeWidth(SkIntToScalar(4));
-            paint.setAntiAlias(true);
-            canvas->scale(SkIntToScalar(3), SkIntToScalar(3));
-            canvas->drawPath(p, paint);
-            return;
-        }
-        
-        if (false) {
-            for (int dy = -1; dy <= 2; dy++) {
-                canvas->save();
-                if (dy == 2) {
-                    canvas->translate(0, SK_Scalar1/2);
-                } else {
-                    canvas->translate(0, SkIntToScalar(dy)/100);
-                }
-            
-                SkBitmap bm;
-                bm.setConfig(SkBitmap::kARGB_8888_Config, 20, 20);
-                bm.allocPixels();
-                SkCanvas c(bm);
-                SkRect r = { 0, 0, 20*SK_Scalar1, SK_Scalar1 };
-                for (int y = 0; y < 20; y++) {
-                    SkPaint p;
-                    p.setARGB(0xFF, y*5&0xFF, y*13&0xFF, y*29&0xFF);
-                    c.drawRect(r, p);
-                    r.offset(0, SK_Scalar1);
-                }
-                SkIRect src;
-                SkRect  dst;
-                
-                static const int srcPts[] = {
-                 //   2, 0, 15, 2,
-                    2, 2, 15, 16,
-                    17, 2, 2, 16,
-                    19, 2, 1, 16,
-                //    2, 18, 15, 2
-                };
-                static const double dstPts[] = {
-                //    7, 262 15, 24.5,
-                    7, 286.5, 15, 16,
-                    22, 286.5, 5, 16,
-                    27, 286.5, 1, 16,
-                 //   7, 302.5, 15, 24.5
-                };
-                
-                SkPaint p;
-//                p.setFilterBitmap(true);
-                const int* s = srcPts;
-                const double* d = dstPts;
-                for (int i = 0; i < 3; i++) {
-                    src.set(s[0], s[1], s[0]+s[2], s[1]+s[3]);
-                    dst.set(SkDoubleToScalar(d[0]),
-                            SkDoubleToScalar(d[1]),
-                            SkDoubleToScalar(d[0]+d[2]),
-                            SkDoubleToScalar(d[1]+d[3]));
-                    canvas->drawBitmapRect(bm, &src, dst, &p);
-                    canvas->translate(SkDoubleToScalar(1), 0);
-                    s += 4;
-                    d += 4;
-                }
-                canvas->restore();
-                canvas->translate(SkIntToScalar(32), 0);
-            }
-            return;
-        }
         
         canvas->translate(SkIntToScalar(20), 0);
 
@@ -370,8 +299,7 @@
         paint.setShader(NULL);
         paint.setAntiAlias(true);
         paint.setStrokeWidth(SkIntToScalar(5));
-        canvas->drawPoints(SkCanvas::kPoints_PointMode, SK_ARRAY_COUNT(fPts),
-                           fPts, paint);
+        canvas->drawPoints(SkCanvas::kPoints_PointMode, SK_ARRAY_COUNT(fPts), fPts, paint);
         
         canvas->translate(0, SkIntToScalar(300));
         
diff --git a/samplecode/SamplePath.cpp b/samplecode/SamplePath.cpp
index 1eb4222..2c8e8c2 100644
--- a/samplecode/SamplePath.cpp
+++ b/samplecode/SamplePath.cpp
@@ -1,3 +1,4 @@
+
 #include "SampleCode.h"
 #include "SkView.h"
 #include "SkCanvas.h"
@@ -44,7 +45,12 @@
     SkParsePath::FromSVGString(str, &path);
     
     {
+#ifdef SK_BUILD_FOR_WIN
+        // windows doesn't have strtof
+        float x = (float)strtod("9.94099e+07", NULL);
+#else
         float x = strtof("9.94099e+07", NULL);
+#endif
         int ix = (int)x;
         int fx = (int)(x * 65536);
         int ffx = SkScalarToFixed(x);
diff --git a/samplecode/SamplePathEffects.cpp b/samplecode/SamplePathEffects.cpp
index 42f50a3..1ba775f 100644
--- a/samplecode/SamplePathEffects.cpp
+++ b/samplecode/SamplePathEffects.cpp
@@ -13,15 +13,6 @@
 #include "SkColorPriv.h"
 #include "SkPixelXorXfermode.h"
 
-static void test_grow(SkPath* path)
-{
-    for (int i = 0; i < 100000; i++)
-    {
-        path->lineTo(i, i);
-        path->lineTo(i, i*2);
-    }
-}
-
 #define CORNER_RADIUS   12
 static SkScalar gPhase;
 
@@ -29,8 +20,7 @@
     4, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4
 };
 
-static SkPathEffect* make_pe(int flags)
-{
+static SkPathEffect* make_pe(int flags) {
     if (flags == 1)
         return new SkCornerPathEffect(SkIntToScalar(CORNER_RADIUS));
 
@@ -54,8 +44,7 @@
     return pe;
 }
 
-static SkPathEffect* make_warp_pe()
-{
+static SkPathEffect* make_warp_pe() {
     SkPath  path;
     path.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
     for (unsigned i = 2; i < SK_ARRAY_COUNT(gXY); i += 2)
@@ -79,8 +68,7 @@
 
 class testrast : public SkLayerRasterizer {
 public:
-    testrast()
-    {
+    testrast() {
         SkPaint paint;
         paint.setAntiAlias(true);
 
@@ -106,8 +94,7 @@
     SkPath  fPath;
     SkPoint fClickPt;
 public:
-	PathEffectView()
-    {
+	PathEffectView() {
         SkRandom    rand;
         int         steps = 20;
         SkScalar    dist = SkIntToScalar(400);
@@ -115,8 +102,7 @@
         SkScalar    y = SkIntToScalar(50);
         
         fPath.moveTo(x, y);
-        for (int i = 0; i < steps; i++)
-        {
+        for (int i = 0; i < steps; i++) {
             x += dist/steps;
             SkScalar tmpY = y + SkIntToScalar(rand.nextS() % 25);
             if (i == steps/2) {
@@ -139,39 +125,22 @@
 	
 protected:
     // overrides from SkEventSink
-    virtual bool onQuery(SkEvent* evt)
-    {
-            if (SampleCode::TitleQ(*evt))
-            {
-                SampleCode::TitleR(evt, "PathEffects");
-                return true;
-            }
-            return this->INHERITED::onQuery(evt);
+    virtual bool onQuery(SkEvent* evt) {
+        if (SampleCode::TitleQ(*evt)) {
+            SampleCode::TitleR(evt, "PathEffects");
+            return true;
+        }
+        return this->INHERITED::onQuery(evt);
     }
     
-    void drawBG(SkCanvas* canvas)
-    {
+    void drawBG(SkCanvas* canvas) {
         canvas->drawColor(0xFFDDDDDD);
-
-#if 0
-        SkPath path;
-        test_grow(&path);
-        SkPaint p;
-        
-        p.setAntiAlias(true);
-        p.setStyle(SkPaint::kStroke_Style);
-        p.setStrokeWidth(SK_Scalar1);
-        canvas->drawPath(path, p);
-        path.close();
-#endif
     }
     
-    virtual void onDraw(SkCanvas* canvas)
-    {
+    virtual void onDraw(SkCanvas* canvas) {
         this->drawBG(canvas);
         
-        if (true)
-        {
+        if (false) {
             canvas->drawColor(SK_ColorWHITE);
             
             SkPixelXorXfermode  mode(SK_ColorWHITE);
@@ -188,11 +157,12 @@
          //   return;
         }
         
-        gPhase -= SK_Scalar1;
+        gPhase -= SampleCode::GetAnimSecondsDelta() * 40;
         this->inval(NULL);
         
         SkPaint paint;
         
+#if 0
         paint.setAntiAlias(true);
         paint.setStyle(SkPaint::kStroke_Style);
         paint.setStrokeWidth(SkIntToScalar(5));
@@ -202,6 +172,7 @@
         paint.setColor(SK_ColorWHITE);
         paint.setPathEffect(make_pe(1))->unref();
         canvas->drawPath(fPath, paint);
+#endif
         
         canvas->translate(0, SkIntToScalar(50));
         
@@ -221,40 +192,6 @@
         paint.setPathEffect(make_warp_pe())->unref();
         paint.setRasterizer(new testrast)->unref();
         canvas->drawPath(fPath, paint);
-        
-        {
-            SkRect  oval;
-            
-            oval.set(SkIntToScalar(50), SkIntToScalar(100),
-                     SkIntToScalar(150), SkIntToScalar(150));
-            canvas->drawRoundRect(oval, SkIntToScalar(8), SkIntToScalar(8), paint);
-        }
-        
-        {
-            SkRect  bounds;
-            SkPaint paint;
-            
-            paint.setAntiAlias(true);
-            paint.setAlpha(0x80);
-            paint.setColorFilter(
-                SkColorFilter::CreateModeFilter(
-                    SkColorSetARGB(0x44, 0, 0xFF, 0), SkXfermode::kSrcATop_Mode))->unref();
-            
-            bounds.set(SkIntToScalar(10), SkIntToScalar(10), SkIntToScalar(150), SkIntToScalar(70));
-            canvas->saveLayer(&bounds, &paint,
-                              (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag));
-            
-            paint.setColorFilter(NULL);
-            paint.setColor(SK_ColorRED);
-            canvas->drawOval(bounds, paint);
-
-            paint.setColor(SK_ColorBLUE);
-            paint.setAlpha(0x80);
-            bounds.inset(SkIntToScalar(10), SkIntToScalar(10));
-            canvas->drawOval(bounds, paint);
-            
-            canvas->restore();
-        }
     }
     
 private:
diff --git a/samplecode/SamplePoints.cpp b/samplecode/SamplePoints.cpp
index 57e45c9..db2e6b7 100644
--- a/samplecode/SamplePoints.cpp
+++ b/samplecode/SamplePoints.cpp
@@ -85,7 +85,7 @@
         p3.setColor(SK_ColorWHITE);
         
      //   fAA = !fAA;
-        fAA = true;
+        fAA = false;
         p0.setAntiAlias(fAA);
         p1.setAntiAlias(fAA);
         p2.setAntiAlias(fAA);
diff --git a/samplecode/SampleRegion.cpp b/samplecode/SampleRegion.cpp
index 6259000..8777050 100644
--- a/samplecode/SampleRegion.cpp
+++ b/samplecode/SampleRegion.cpp
@@ -8,6 +8,11 @@
 #include "SkUtils.h"
 #include "SkImageDecoder.h"
 
+#ifdef SK_BUILD_FOR_WIN
+// windows doesn't have roundf
+inline float roundf(float x) { return (x-floor(x))>0.5 ? ceil(x) : floor(x); }
+#endif
+
 #ifdef SK_DEBUG
 static void make_rgn(SkRegion* rgn, int left, int top, int right, int bottom,
                      size_t count, int32_t runs[]) {
@@ -232,13 +237,7 @@
         canvas->drawPaint(paint);
     }
 
-    virtual void onDraw(SkCanvas* canvas)
-    {
-        if (true) {
-            SkRect r = { 0, 0, 1 << 30, 1 << 30 };
-            bool open = canvas->clipRect(r);
-            SkDebugf("---- giant clip is %d\n", open);
-        }
+    virtual void onDraw(SkCanvas* canvas) {
         this->drawBG(canvas);
         
         if (false) {
diff --git a/samplecode/SampleShapes.cpp b/samplecode/SampleShapes.cpp
index b92614b..30ff3fd 100644
--- a/samplecode/SampleShapes.cpp
+++ b/samplecode/SampleShapes.cpp
@@ -5,6 +5,8 @@
 #include "SkStream.h"
 #include "SkView.h"
 
+#define DO_AA   false
+
 #include "SkRectShape.h"
 #include "SkGroupShape.h"
 
@@ -21,6 +23,7 @@
     if (red) {
         s->paint().setColor(SK_ColorRED);
     }
+    s->paint().setAntiAlias(DO_AA);
     return s;
 }
 
@@ -28,6 +31,7 @@
     SkRectShape* s = new SkRectShape;
     s->setOval(make_rect(10, 10, 90, 90));
     s->paint().setColor(SK_ColorBLUE);
+    s->paint().setAntiAlias(DO_AA);
     return s;
 }
 
@@ -36,6 +40,7 @@
     s->setRRect(make_rect(10, 10, 90, 90),
                 SkIntToScalar(20), SkIntToScalar(20));
     s->paint().setColor(SK_ColorGREEN);
+    s->paint().setAntiAlias(DO_AA);
     return s;
 }
 
@@ -83,7 +88,7 @@
     }
     
     void drawpicture(SkCanvas* canvas, SkPicture& pict) {
-#if 1
+#if 0
         SkDynamicMemoryWStream ostream;
         pict.serialize(&ostream);
 
@@ -99,13 +104,21 @@
     virtual void onDraw(SkCanvas* canvas) {
         this->drawBG(canvas);
         
-        SkScalar angle = SampleCode::GetAnimScalar(SkIntToScalar(360)/2,
+        SkScalar angle = SampleCode::GetAnimScalar(SkIntToScalar(180),
                                                    SkIntToScalar(360));
 
         SkMatrix saveM = *fMatrixRefs[3];
         SkScalar c = SkIntToScalar(50);
         fMatrixRefs[3]->preRotate(angle, c, c);
         
+        const SkScalar dx = 350;
+        const SkScalar dy = 500;
+        const int N = 1;
+        for (int v = -N; v <= N; v++) {
+            for (int h = -N; h <= N; h++) {
+                SkAutoCanvasRestore acr(canvas, true);
+                canvas->translate(h * dx, v * dy);
+        
         SkMatrix matrix;
      
         SkGroupShape* gs = new SkGroupShape;
@@ -121,18 +134,21 @@
 #if 0
         canvas->drawShape(gs);
 #else
-        SkPicture pict;
-        SkCanvas* cv = pict.beginRecording(1000, 1000);
+        SkPicture* pict = new SkPicture;
+        SkCanvas* cv = pict->beginRecording(1000, 1000);
         cv->scale(SK_ScalarHalf, SK_ScalarHalf);
         cv->drawShape(gs);
         cv->translate(SkIntToScalar(680), SkIntToScalar(480));
         cv->scale(-SK_Scalar1, SK_Scalar1);
         cv->drawShape(gs);
-        pict.endRecording();
+        pict->endRecording();
         
-        drawpicture(canvas, pict);
+        drawpicture(canvas, *pict);
+        pict->unref();
 #endif
 
+        }}
+
         *fMatrixRefs[3] = saveM;
         this->inval(NULL);
 }
diff --git a/samplecode/SampleSlides.cpp b/samplecode/SampleSlides.cpp
index 2029967..f57cb5a 100644
--- a/samplecode/SampleSlides.cpp
+++ b/samplecode/SampleSlides.cpp
@@ -330,7 +330,8 @@
                                           SK_ARRAY_COUNT(colors), SkShader::kMirror_TileMode, NULL);
 }
 
-struct Rec {
+class Rec {
+public:
     SkCanvas::VertexMode    fMode;
     int                     fCount;
     SkPoint*                fVerts;
@@ -426,13 +427,14 @@
     
     SkShader* fShader0 = make_shader0(&size);
     SkShader* fShader1 = make_shader1(size);
-    
+
+    SkAutoUnref aur0(fShader0);
+    SkAutoUnref aur1(fShader1);
+
     make_strip(&fRecs[0], size.fX, size.fY);
     make_fan(&fRecs[1], size.fX, size.fY);
     make_tris(&fRecs[2]);
 
-
-
     SkPaint paint;
     paint.setDither(true);
     paint.setFilterBitmap(true);
diff --git a/samplecode/SampleTestGL.cpp b/samplecode/SampleTestGL.cpp
index c5938ba..a0dfea3 100644
--- a/samplecode/SampleTestGL.cpp
+++ b/samplecode/SampleTestGL.cpp
@@ -50,7 +50,7 @@
     "    float u = uv.x;"
     "    float v = uv.y;"
     "    if (u*u > v) {"
-"    gl_FragColor = vec4(1.0, 0, 0, 1.0);"
+"    gl_FragColor = vec4(0.0, 0, 0, 0.0);"
     "    } else {"
     "    gl_FragColor = vec4(0, 1.0, 0, 1.0);"
     "}"
diff --git a/samplecode/SampleText.cpp b/samplecode/SampleText.cpp
index 14b3d80..abd88be 100644
--- a/samplecode/SampleText.cpp
+++ b/samplecode/SampleText.cpp
@@ -225,7 +225,7 @@
 #ifdef SK_DEBUG
     #define REPEAT_COUNT    1
 #else
-    #define REPEAT_COUNT    5000
+    #define REPEAT_COUNT    5
 #endif
 
 static int count_char_points(const SkPaint& paint, char c)
diff --git a/samplecode/SampleTextOnPath.cpp b/samplecode/SampleTextOnPath.cpp
index aec8fd6..6657d5e 100644
--- a/samplecode/SampleTextOnPath.cpp
+++ b/samplecode/SampleTextOnPath.cpp
@@ -16,7 +16,7 @@
 #include "SkTypeface.h"
 #include "SkAvoidXfermode.h"
 
-#define REPEAT_COUNT    1
+#define REPEAT_COUNT    0
 
 static const char gText[] = "Hamburgefons";
 
@@ -48,13 +48,13 @@
     for (int i = 0; i < 100; i++) {
         rand_text(text, rand, 256);
         paint.getTextWidths(text, count, widths, NULL);
-        SkScalar tw0 = sum_widths(widths, count);
+        SkDEBUGCODE(SkScalar tw0 = sum_widths(widths, count);)
         paint.getTextWidths(text, count, widths, rects);
-        SkScalar tw1 = sum_widths(widths, count);
+        SkDEBUGCODE(SkScalar tw1 = sum_widths(widths, count);)
         SkASSERT(tw0 == tw1);
 
-        SkScalar w0 = paint.measureText(text, count, NULL);
-        SkScalar w1 = paint.measureText(text, count, &bounds);
+        SkDEBUGCODE(SkScalar w0 = paint.measureText(text, count, NULL);)
+        SkDEBUGCODE(SkScalar w1 = paint.measureText(text, count, &bounds);)
         SkASSERT(w0 == w1);
         SkASSERT(w0 == tw0);
         
@@ -175,12 +175,12 @@
     paint.setAntiAlias(true);
     
     paint.setStyle(SkPaint::kStroke_Style);
-    canvas->drawPath(path, paint);
+ //   canvas->drawPath(path, paint);
     paint.setStyle(SkPaint::kFill_Style);
     paint.setTextSize(SkIntToScalar(48));
     paint.setTextAlign(SkPaint::kRight_Align);
     
-    const char* text = "Android";
+    const char* text = "Reflection";
     size_t      len = strlen(text);
     SkScalar    pathLen = getpathlen(path);
 
@@ -211,7 +211,8 @@
         r.set(SkIntToScalar(100), SkIntToScalar(100),
               SkIntToScalar(300), SkIntToScalar(300));
         fPath.addOval(r);
-        
+        fPath.offset(SkIntToScalar(200), 0);
+
         fHOffset = SkIntToScalar(50);
     }
 
@@ -278,12 +279,10 @@
         
         paint.setColor(SK_ColorGREEN);
         paint.setStyle(SkPaint::kStroke_Style);
-        canvas->drawPath(fPath, paint);
+//        canvas->drawPath(fPath, paint);
         
-        canvas->translate(SkIntToScalar(200), 0);
+        canvas->translate(0, SkIntToScalar(100));
         test_textpathmatrix(canvas);
-
-        test_bitmap_blur(canvas);
         
         if (REPEAT_COUNT > 1)
             this->inval(NULL);
diff --git a/samplecode/SampleTiling.cpp b/samplecode/SampleTiling.cpp
index 759c17c..87aeae4 100644
--- a/samplecode/SampleTiling.cpp
+++ b/samplecode/SampleTiling.cpp
@@ -8,6 +8,7 @@
 #include "SkUtils.h"
 #include "SkColorPriv.h"
 #include "SkColorFilter.h"
+#include "SkPicture.h"
 #include "SkTypeface.h"
 
 // effects
@@ -55,6 +56,7 @@
 static const int gHeight = 32;
 
 class TilingView : public SkView {
+    SkPicture           fTextPicture;
     SkBlurDrawLooper    fLooper;
 public:
 	TilingView()
@@ -97,19 +99,26 @@
         SkScalar y = SkIntToScalar(24);
         SkScalar x = SkIntToScalar(10);
 
-        for (int kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) {
-            for (int ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) {
-                SkPaint p;
-                SkString str;
-                p.setAntiAlias(true);
-                p.setDither(true);
-                p.setLooper(&fLooper);
-                str.printf("[%s,%s]", gModeNames[kx], gModeNames[ky]);
+        SkCanvas* textCanvas = NULL;
+        if (fTextPicture.width() == 0) {
+            textCanvas = fTextPicture.beginRecording(1000, 1000);
+        }
 
-                p.setTextAlign(SkPaint::kCenter_Align);
-                canvas->drawText(str.c_str(), str.size(), x + r.width()/2, y, p);
-                
-                x += r.width() * 4 / 3;
+        if (textCanvas) {
+            for (int kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) {
+                for (int ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) {
+                    SkPaint p;
+                    SkString str;
+                    p.setAntiAlias(true);
+                    p.setDither(true);
+                    p.setLooper(&fLooper);
+                    str.printf("[%s,%s]", gModeNames[kx], gModeNames[ky]);
+
+                    p.setTextAlign(SkPaint::kCenter_Align);
+                    textCanvas->drawText(str.c_str(), str.size(), x + r.width()/2, y, p);
+                    
+                    x += r.width() * 4 / 3;
+                }
             }
         }
         
@@ -132,22 +141,20 @@
                         x += r.width() * 4 / 3;
                     }
                 }
-                {
+                if (textCanvas) {
                     SkPaint p;
                     SkString str;
                     p.setAntiAlias(true);
                     p.setLooper(&fLooper);
                     str.printf("%s, %s", gConfigNames[i], gFilterNames[j]);
-                    canvas->drawText(str.c_str(), str.size(), x, y + r.height() * 2 / 3, p);
+                    textCanvas->drawText(str.c_str(), str.size(), x, y + r.height() * 2 / 3, p);
                 }
 
                 y += r.height() * 4 / 3;
             }
         }
-        
-    #ifdef SK_RELEASE
-        this->inval(NULL);
-    #endif
+
+        canvas->drawPicture(fTextPicture);
     }
     
     virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
diff --git a/samplecode/SampleTinyBitmap.cpp b/samplecode/SampleTinyBitmap.cpp
index 1563c7a..ffbff25 100644
--- a/samplecode/SampleTinyBitmap.cpp
+++ b/samplecode/SampleTinyBitmap.cpp
@@ -48,6 +48,10 @@
     }
     
     void drawBG(SkCanvas* canvas) {
+        SkIPoint size;
+        if (canvas->getViewport(&size)) {
+            SkDebugf("");
+        }
         canvas->drawColor(0xFFDDDDDD);
     }
     
diff --git a/samplecode/SampleVertices.cpp b/samplecode/SampleVertices.cpp
index 96c9849..96fa0da 100644
--- a/samplecode/SampleVertices.cpp
+++ b/samplecode/SampleVertices.cpp
@@ -22,7 +22,7 @@
 static SkShader* make_shader0(SkIPoint* size) {
     SkBitmap    bm;
     
-    SkImageDecoder::DecodeFile("/skimages/logo.gif", &bm);
+    SkImageDecoder::DecodeFile("/skimages/logo.png", &bm);
     size->set(bm.width(), bm.height());
     return SkShader::CreateBitmapShader(bm, SkShader::kClamp_TileMode,
                                         SkShader::kClamp_TileMode);
diff --git a/samplecode/SampleXfermodes.cpp b/samplecode/SampleXfermodes.cpp
index 7fecec6..a85bee2 100644
--- a/samplecode/SampleXfermodes.cpp
+++ b/samplecode/SampleXfermodes.cpp
@@ -23,6 +23,7 @@
 #include "SkColorPriv.h"
 #include "SkImageDecoder.h"
 
+#if 0
 static int newscale(U8CPU a, U8CPU b, int shift) {
     unsigned prod = a * b + (1 << (shift - 1));
     return (prod + (prod >> shift)) >> shift;
@@ -73,6 +74,7 @@
     p.setARGB(0xFF, rgb, rgb, rgb);
     canvas->drawRect(rect, p);
 }
+#endif
 
 static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst) {    
     src->setConfig(SkBitmap::kARGB_8888_Config, w, h);
@@ -103,27 +105,26 @@
 static uint16_t gBG[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF };
 
 class XfermodesView : public SkView {
-    SkBitmap    fBitmap;
     SkBitmap    fBG;
     SkBitmap    fSrcB, fDstB;
 
-    void draw_mode(SkCanvas* canvas, SkXfermode* mode, int alpha) {
+    void draw_mode(SkCanvas* canvas, SkXfermode* mode, int alpha,
+                   SkScalar x, SkScalar y) {
         SkPaint p;
-        
-        canvas->drawBitmap(fSrcB, 0, 0, &p);        
+
+        canvas->drawBitmap(fSrcB, x, y, &p);        
         p.setAlpha(alpha);
         p.setXfermode(mode);
-        canvas->drawBitmap(fDstB, 0, 0, &p);
+        canvas->drawBitmap(fDstB, x, y, &p);
     }
     
 public:
+    const static int W = 64;
+    const static int H = 64;
 	XfermodesView() {
         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);
@@ -143,42 +144,13 @@
 
     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) {
+        canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
+
         this->drawBG(canvas);
         
-        if (false) {
-            test_srcover565(canvas);
-        }
-        
-        if (false) {
-            SkPaint paint;
-            paint.setFlags(0x43);
-            paint.setTextSize(SkIntToScalar(128));
-            SkMatrix matrix;
-            matrix.reset();
-            matrix.set(0, 0x0019d049);
-            matrix.set(2, 0x712cf400);
-            matrix.set(4, 0x0019c96f);
-            matrix.set(5, 0xF8d76598);
-            canvas->concat(matrix);
-            canvas->drawText("HamburgefonsHamburgefonsHamburgefonsHamburgefons",
-                             48, 0, 0, paint);
-            return;
-        }
-
         const struct {
             SkXfermode::Mode  fMode;
             const char*         fLabel;
@@ -209,12 +181,9 @@
             { SkXfermode::kDifference_Mode,   "Difference"    },
             { SkXfermode::kExclusion_Mode,    "Exclusion"     },
         };
-        
-        canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
-        
-        SkCanvas c(fBitmap);
-        const SkScalar w = SkIntToScalar(fBitmap.width());
-        const SkScalar h = SkIntToScalar(fBitmap.height());
+
+        const SkScalar w = SkIntToScalar(W);
+        const SkScalar h = SkIntToScalar(H);
         SkShader* s = SkShader::CreateBitmapShader(fBG,
                                                    SkShader::kRepeat_TileMode,
                                                    SkShader::kRepeat_TileMode);
@@ -233,27 +202,29 @@
             SkScalar x = x0, y = 0;
             for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
                 SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
-
-                fBitmap.eraseColor(0);
-                draw_mode(&c, mode, twice ? 0x88 : 0xFF);
-                SkSafeUnref(mode);
-                
-                SkPaint p;
+                SkAutoUnref aur(mode);
                 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);
+
+                SkPaint p;
                 p.setStyle(SkPaint::kFill_Style);
                 p.setShader(s);
-                r.inset(SK_ScalarHalf, SK_ScalarHalf);
+                canvas->drawRect(r, p);
+                
+                canvas->saveLayer(&r, NULL, SkCanvas::kARGB_ClipLayer_SaveFlag);
+         //       canvas->save();
+                draw_mode(canvas, mode, twice ? 0x88 : 0xFF, r.fLeft, r.fTop);
+                canvas->restore();
+
+                r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
+                p.setStyle(SkPaint::kStroke_Style);
+                p.setShader(NULL);
                 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 % W) == W - 1) {
                     x = x0;
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index 3c7be4c..1eaa46d 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -44,8 +44,10 @@
     this->INHERITED::endSession();
 }
 
-bool SkBitmapProcShader::asABitmap(SkBitmap* texture, SkMatrix* texM,
-                                   TileMode xy[]) {
+SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture, 
+                                                   SkMatrix* texM, 
+                                                   TileMode xy[],
+                                                   SkScalar* twoPointRadialParams) {
     if (texture) {
         *texture = fRawBitmap;
     }
@@ -56,7 +58,7 @@
         xy[0] = (TileMode)fState.fTileModeX;
         xy[1] = (TileMode)fState.fTileModeY;
     }
-    return true;
+    return kDefault_BitmapType;
 }
 
 void SkBitmapProcShader::flatten(SkFlattenableWriteBuffer& buffer) {
@@ -82,7 +84,7 @@
 
     fState.fOrigBitmap = fRawBitmap;
     fState.fOrigBitmap.lockPixels();
-    if (!fState.fOrigBitmap.readyToDraw()) {
+    if (!fState.fOrigBitmap.getTexture() && !fState.fOrigBitmap.readyToDraw()) {
         fState.fOrigBitmap.unlockPixels();
         return false;
     }
diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h
index 09d53af..88598fc 100644
--- a/src/core/SkBitmapProcShader.h
+++ b/src/core/SkBitmapProcShader.h
@@ -32,7 +32,8 @@
     virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count);
     virtual void beginSession();
     virtual void endSession();
-    virtual bool asABitmap(SkBitmap*, SkMatrix*, TileMode*);
+    virtual BitmapType asABitmap(SkBitmap*, SkMatrix*, TileMode*, 
+                                 SkScalar* twoPointRadialParams);
 
     static bool CanDo(const SkBitmap&, TileMode tx, TileMode ty);
 
diff --git a/src/core/SkBlitter_ARGB32.cpp b/src/core/SkBlitter_ARGB32.cpp
index 905ab6b..88b9491 100644
--- a/src/core/SkBlitter_ARGB32.cpp
+++ b/src/core/SkBlitter_ARGB32.cpp
@@ -40,6 +40,32 @@
 
 //////////////////////////////////////////////////////////////////////////////////////
 
+static void SkARGB32_Blit32(const SkBitmap& device, const SkMask& mask,
+							const SkIRect& clip, SkPMColor srcColor) {
+	U8CPU alpha = SkGetPackedA32(srcColor);
+	unsigned flags = SkBlitRow::kSrcPixelAlpha_Flag32;
+	if (alpha != 255) {
+		flags |= SkBlitRow::kGlobalAlpha_Flag32;
+	}
+	SkBlitRow::Proc32 proc = SkBlitRow::Factory32(flags);
+
+    int x = clip.fLeft;
+    int y = clip.fTop;
+    int width = clip.width();
+    int height = clip.height();
+	
+    SkPMColor*		 dstRow = device.getAddr32(x, y);
+    const SkPMColor* srcRow = reinterpret_cast<const SkPMColor*>(mask.getAddr(x, y));
+
+    do {
+		proc(dstRow, srcRow, width, alpha);
+        dstRow = (SkPMColor*)((char*)dstRow + device.rowBytes());
+        srcRow = (const SkPMColor*)((const char*)srcRow + mask.fRowBytes);
+    } while (--height != 0);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////
+
 SkARGB32_Blitter::SkARGB32_Blitter(const SkBitmap& device, const SkPaint& paint)
         : INHERITED(device) {
     uint32_t color = paint.getColor();
@@ -156,6 +182,9 @@
     if (mask.fFormat == SkMask::kBW_Format) {
         SkARGB32_BlendBW(fDevice, mask, clip, fPMColor, SkAlpha255To256(255 - fSrcA));
         return;
+    } else if (SkMask::kARGB32_Format == mask.fFormat) {
+		SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
+		return;
     }
 
     int x = clip.fLeft;
@@ -188,7 +217,10 @@
     if (mask.fFormat == SkMask::kBW_Format) {
         SkARGB32_BlitBW(fDevice, mask, clip, fPMColor);
         return;
-    }
+    } else if (SkMask::kARGB32_Format == mask.fFormat) {
+		SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
+		return;
+	}
 
     int x = clip.fLeft;
     int y = clip.fTop;
@@ -306,6 +338,8 @@
         SkPMColor black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT);
 
         SkARGB32_BlitBW(fDevice, mask, clip, black);
+    } else if (SkMask::kARGB32_Format == mask.fFormat) {
+		SkARGB32_Blit32(fDevice, mask, clip, fPMColor);
     } else {
 #if defined(SK_SUPPORT_LCDTEXT)
         const bool      lcdMode = mask.fFormat == SkMask::kHorizontalLCD_Format;
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 5a855bb..0e36c91 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -74,6 +74,9 @@
     const SkMatrix*     fMatrix;
 	SkPaint*			fPaint;	// may be null (in the future)
     int16_t             fX, fY; // relative to base matrix/clip
+    // optional, related to canvas' external matrix
+    const SkMatrix*     fMVMatrix;
+    const SkMatrix*     fExtMatrix;
 
 	DeviceCM(SkDevice* device, int x, int y, const SkPaint* paint)
             : fNext(NULL) {
@@ -132,8 +135,18 @@
             SkASSERT(deviceR.contains(fClip.getBounds()));
         }
 #endif
+        // default is to assume no external matrix
+        fMVMatrix = NULL;
+        fExtMatrix = NULL;
     }
-    
+
+    // can only be called after calling updateMC()
+    void updateExternalMatrix(const SkMatrix& extM, const SkMatrix& extI) {
+        fMVMatrixStorage.setConcat(extI, *fMatrix);
+        fMVMatrix = &fMVMatrixStorage;
+        fExtMatrix = &extM; // assumes extM has long life-time (owned by canvas)
+    }
+
     void translateClip() {
         if (fX | fY) {
             fClip.translate(fX, fY);
@@ -141,7 +154,7 @@
     }
 
 private:
-    SkMatrix    fMatrixStorage;
+    SkMatrix    fMatrixStorage, fMVMatrixStorage;
 };
 
 /*  This is the record we keep for each save/restore level in the stack.
@@ -240,16 +253,17 @@
             fLayerX = rec->fX;
             fLayerY = rec->fY;
             fPaint  = rec->fPaint;
-            SkDEBUGCODE(this->validate(fDevice->width(), fDevice->height());)
+            fMVMatrix = rec->fMVMatrix;
+            fExtMatrix = rec->fExtMatrix;
+            SkDEBUGCODE(this->validate();)
 
             fCurrLayer = rec->fNext;
             if (fBounder) {
                 fBounder->setClip(fClip);
             }
-
             // fCurrLayer may be NULL now
 
-            fCanvas->prepareForDeviceDraw(fDevice);
+            fCanvas->prepareForDeviceDraw(fDevice, *fMatrix, *fClip);
             return true;
         }
         return false;
@@ -401,6 +415,8 @@
     fMCRec->fTopLayer = fMCRec->fLayer;
     fMCRec->fNext = NULL;
 
+    fUseExternalMatrix = false;
+
     return this->setDevice(device);
 }
 
@@ -427,7 +443,7 @@
         : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
     inc_canvas();
 
-    SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap));
+    SkDevice* device = SkNEW_ARGS(SkDevice, (this, bitmap, false));
     fDeviceFactory = device->getDeviceFactory();
     this->init(device)->unref();
 }
@@ -527,8 +543,8 @@
     return device;
 }
 
-SkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap) {
-    SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (bitmap)));
+SkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap, bool forLayer) {
+    SkDevice* device = this->setDevice(SkNEW_ARGS(SkDevice, (this, bitmap, forLayer)));
     device->unref();
     return device;
 }
@@ -546,8 +562,9 @@
 bool SkCanvas::setViewport(int width, int height) {
     if ((getDevice()->getDeviceCapabilities() & SkDevice::kGL_Capability) == 0)
         return false;
-    this->setDevice(createDevice(SkBitmap::kARGB_8888_Config, width, height,
-                                 false, false))->unref();
+
+    this->setDevice(this->createDevice(SkBitmap::kARGB_8888_Config, width, height,
+                                       false, false))->unref();
     return true;
 }
 
@@ -559,21 +576,30 @@
         
         if (NULL == layer->fNext) {   // only one layer
             layer->updateMC(totalMatrix, totalClip, NULL);
+            if (fUseExternalMatrix) {
+                layer->updateExternalMatrix(fExternalMatrix,
+                                            fExternalInverse);
+            }
         } else {
             SkRegion clip;
             clip = totalClip;  // make a copy
             do {
                 layer->updateMC(totalMatrix, clip, &clip);
+                if (fUseExternalMatrix) {
+                    layer->updateExternalMatrix(fExternalMatrix,
+                                                fExternalInverse);
+                }
             } while ((layer = layer->fNext) != NULL);
         }
         fDeviceCMDirty = false;
     }
 }
 
-void SkCanvas::prepareForDeviceDraw(SkDevice* device) {
+void SkCanvas::prepareForDeviceDraw(SkDevice* device, const SkMatrix& matrix,
+                                    const SkRegion& clip) {
     SkASSERT(device);
     if (fLastDeviceToGainFocus != device) {
-        device->gainFocus(this);
+        device->gainFocus(this, matrix, clip);
         fLastDeviceToGainFocus = device;
     }
 }
@@ -651,6 +677,9 @@
 
     SkIRect         ir;
     const SkIRect&  clipBounds = this->getTotalClip().getBounds();
+    if (clipBounds.isEmpty()) {
+        return count;
+    }
 
     if (NULL != bounds) {
         SkRect r;
@@ -760,7 +789,7 @@
             bitmap.width() > 32767 || bitmap.height() > 32767;
 }
 
-void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap,
+void SkCanvas::internalDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
                                 const SkMatrix& matrix, const SkPaint* paint) {
     if (reject_bitmap(bitmap)) {
         return;
@@ -768,9 +797,9 @@
 
     if (NULL == paint) {
         SkPaint tmpPaint;
-        this->commonDrawBitmap(bitmap, matrix, tmpPaint);
+        this->commonDrawBitmap(bitmap, srcRect, matrix, tmpPaint);
     } else {
-        this->commonDrawBitmap(bitmap, matrix, *paint);
+        this->commonDrawBitmap(bitmap, srcRect, matrix, *paint);
     }
 }
 
@@ -1023,13 +1052,30 @@
     return *fMCRec->fRegion;
 }
 
-///////////////////////////////////////////////////////////////////////////////
+void SkCanvas::setExternalMatrix(const SkMatrix* matrix) {
+    if (NULL == matrix || matrix->isIdentity()) {
+        if (fUseExternalMatrix) {
+            fDeviceCMDirty = true;
+        }
+        fUseExternalMatrix = false;
+    } else {
+        fUseExternalMatrix = true;
+        fDeviceCMDirty = true;  // |= (fExternalMatrix != *matrix)
+        
+        fExternalMatrix = *matrix;
+        matrix->invert(&fExternalInverse);
+    }
+    
+    static bool gUseExt;
+    if (gUseExt != fUseExternalMatrix && false) {
+        gUseExt = fUseExternalMatrix;
+        printf("---- fUseExternalMatrix = %d\n", fUseExternalMatrix);
+    }
+}
 
-SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width,
-                                 int height, bool isOpaque, bool isForLayer) {
-
-    return fDeviceFactory->newDevice(config, width, height, isOpaque,
-                                     isForLayer);
+SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width, int height,
+                                 bool isOpaque, bool forLayer) {
+    return fDeviceFactory->newDevice(this, config, width, height, isOpaque, forLayer);
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -1116,7 +1162,7 @@
         
     SkMatrix matrix;
     matrix.setTranslate(x, y);
-    this->internalDrawBitmap(bitmap, matrix, paint);
+    this->internalDrawBitmap(bitmap, NULL, matrix, paint);
 }
 
 void SkCanvas::drawBitmapRect(const SkBitmap& bitmap, const SkIRect* src,
@@ -1130,15 +1176,7 @@
         return;
     }
     
-    SkBitmap        tmp;    // storage if we need a subset of bitmap
     const SkBitmap* bitmapPtr = &bitmap;
-
-    if (NULL != src) {
-        if (!bitmap.extractSubset(&tmp, *src)) {
-            return;     // extraction failed
-        }
-        bitmapPtr = &tmp;
-    }
     
     SkMatrix matrix;
     SkRect tmpSrc;
@@ -1159,23 +1197,32 @@
                    SkIntToScalar(bitmap.height()));
     }
     matrix.setRectToRect(tmpSrc, dst, SkMatrix::kFill_ScaleToFit);
-    this->internalDrawBitmap(*bitmapPtr, matrix, paint);
+
+    // ensure that src is "valid" before we pass it to our internal routines
+    // and to SkDevice. i.e. sure it is contained inside the original bitmap.
+    SkIRect tmpISrc;
+    if (src) {
+        tmpISrc.set(0, 0, bitmap.width(), bitmap.height());
+        tmpISrc.intersect(*src);
+        src = &tmpISrc;
+    }
+    this->internalDrawBitmap(*bitmapPtr, src, matrix, paint);
 }
 
 void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
                                 const SkPaint* paint) {
     SkDEBUGCODE(bitmap.validate();)
-    this->internalDrawBitmap(bitmap, matrix, paint);
+    this->internalDrawBitmap(bitmap, NULL, matrix, paint);
 }
 
-void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
-                                const SkPaint& paint) {
+void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
+                                const SkMatrix& matrix, const SkPaint& paint) {
     SkDEBUGCODE(bitmap.validate();)
 
     ITER_BEGIN(paint, SkDrawFilter::kBitmap_Type)
 
     while (iter.next()) {
-        iter.fDevice->drawBitmap(iter, bitmap, matrix, paint);
+        iter.fDevice->drawBitmap(iter, bitmap, srcRect, matrix, paint);
     }
 
     ITER_END
diff --git a/src/core/SkChunkAlloc.cpp b/src/core/SkChunkAlloc.cpp
index 90a0c2a..e0c03a8 100644
--- a/src/core/SkChunkAlloc.cpp
+++ b/src/core/SkChunkAlloc.cpp
@@ -49,6 +49,11 @@
         }
         return block;
     }
+
+    bool contains(const void* addr) const {
+        const char* ptr = reinterpret_cast<const char*>(addr);
+        return ptr >= (const char*)(this + 1) && ptr < fFreePtr;
+    }
 };
 
 SkChunkAlloc::SkChunkAlloc(size_t minSize)
@@ -139,3 +144,14 @@
     return bytes;
 }
 
+bool SkChunkAlloc::contains(const void* addr) const {
+    const Block* block = fBlock;
+    while (block) {
+        if (block->contains(addr)) {
+            return true;
+        }
+        block = block->fNext;
+    }
+    return false;
+}
+
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 12efaac..8df0e41 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -4,9 +4,20 @@
 
 SkDeviceFactory::~SkDeviceFactory() {}
 
-SkDevice::SkDevice() {}
+SkDevice::SkDevice(SkCanvas* canvas) : fCanvas(canvas) {}
 
-SkDevice::SkDevice(const SkBitmap& bitmap) : fBitmap(bitmap) {}
+SkDevice::SkDevice(SkCanvas* canvas, const SkBitmap& bitmap, bool isForLayer)
+        : fCanvas(canvas), fBitmap(bitmap) {
+    // auto-allocate if we're for offscreen drawing
+    if (isForLayer) {
+        if (NULL == fBitmap.getPixels() && NULL == fBitmap.pixelRef()) {
+            fBitmap.allocPixels();   
+            if (!fBitmap.isOpaque()) {
+                fBitmap.eraseColor(0);
+            }
+        }
+    }
+}
 
 void SkDevice::lockPixels() {
     fBitmap.lockPixels();
@@ -47,6 +58,39 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+bool SkDevice::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
+    const SkBitmap& src = this->accessBitmap(false);
+
+    SkIRect bounds;
+    bounds.set(0, 0, src.width(), src.height());
+    if (!bounds.intersect(srcRect)) {
+        return false;
+    }
+
+    SkBitmap subset;
+    if (!src.extractSubset(&subset, bounds)) {
+        return false;
+    }
+
+    SkBitmap tmp;
+    if (!subset.copyTo(&tmp, SkBitmap::kARGB_8888_Config)) {
+        return false;
+    }
+
+    tmp.swap(*bitmap);
+    return true;
+}
+
+void SkDevice::writePixels(const SkBitmap& bitmap, int x, int y) {
+    SkPaint paint;
+    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+
+    SkCanvas canvas(this);
+    canvas.drawSprite(bitmap, x, y, &paint);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 void SkDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
     draw.drawPaint(paint);
 }
@@ -62,13 +106,24 @@
 }
 
 void SkDevice::drawPath(const SkDraw& draw, const SkPath& path,
-                            const SkPaint& paint) {
-    draw.drawPath(path, paint);
+                        const SkPaint& paint, const SkMatrix* prePathMatrix,
+                        bool pathIsMutable) {
+    draw.drawPath(path, paint, prePathMatrix, pathIsMutable);
 }
 
 void SkDevice::drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
-                              const SkMatrix& matrix, const SkPaint& paint) {
-    draw.drawBitmap(bitmap, matrix, paint);
+                          const SkIRect* srcRect,
+                          const SkMatrix& matrix, const SkPaint& paint) {
+    SkBitmap        tmp;    // storage if we need a subset of bitmap
+    const SkBitmap* bitmapPtr = &bitmap;
+    
+    if (srcRect) {
+        if (!bitmap.extractSubset(&tmp, *srcRect)) {
+            return;     // extraction failed
+        }
+        bitmapPtr = &tmp;
+    }
+    draw.drawBitmap(*bitmapPtr, matrix, paint);
 }
 
 void SkDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
@@ -109,16 +164,15 @@
     draw.drawSprite(device->accessBitmap(false), x, y, paint);
 }
 
-SkDevice* SkRasterDeviceFactory::newDevice(SkBitmap::Config config, int width,
+///////////////////////////////////////////////////////////////////////////////
+
+SkDevice* SkRasterDeviceFactory::newDevice(SkCanvas* canvas,
+                                           SkBitmap::Config config, int width,
                                            int height, bool isOpaque,
                                            bool isForLayer) {
     SkBitmap bitmap;
     bitmap.setConfig(config, width, height);
     bitmap.setIsOpaque(isOpaque);
 
-    bitmap.allocPixels();
-    if (!bitmap.isOpaque())
-        bitmap.eraseARGB(0, 0, 0, 0);
-
-    return SkNEW_ARGS(SkDevice, (bitmap));
+    return SkNEW_ARGS(SkDevice, (canvas, bitmap, isForLayer));
 }
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index eff2b32..a117ab7 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -143,6 +143,10 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+SkDraw::SkDraw() {
+    sk_bzero(this, sizeof(*this));
+}
+
 SkDraw::SkDraw(const SkDraw& src) {
     memcpy(this, &src, sizeof(*this));
 }
@@ -276,7 +280,7 @@
 }
 
 void SkDraw::drawPaint(const SkPaint& paint) const {
-    SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+    SkDEBUGCODE(this->validate();)
 
     if (fClip->isEmpty()) {
         return;
@@ -540,7 +544,8 @@
 #define MAX_DEV_PTS     32
 
 void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
-                        const SkPoint pts[], const SkPaint& paint) const {
+                        const SkPoint pts[], const SkPaint& paint,
+                        bool forceUseDevice) const {
     // if we're in lines mode, force count to be even
     if (SkCanvas::kLines_PointMode == mode) {
         count &= ~(size_t)1;
@@ -563,7 +568,7 @@
     }
 
     SkASSERT(pts != NULL);
-    SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+    SkDEBUGCODE(this->validate();)
     
      // nothing to draw
     if (fClip->isEmpty() ||
@@ -572,7 +577,7 @@
     }
 
     PtProcRec rec;
-    if (rec.init(mode, paint, fMatrix, fClip)) {
+    if (!forceUseDevice && rec.init(mode, paint, fMatrix, fClip)) {
         SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
 
         SkPoint             devPts[MAX_DEV_PTS];
@@ -614,7 +619,12 @@
                         preMatrix.setTranslate(pts[i].fX, pts[i].fY);
                         // pass true for the last point, since we can modify
                         // then path then
-                        this->drawPath(path, paint, &preMatrix, (count-1) == i);
+                        if (fDevice) {
+                            fDevice->drawPath(*this, path, paint, &preMatrix,
+                                              (count-1) == i);
+                        } else {
+                            this->drawPath(path, paint, &preMatrix, (count-1) == i);
+                        }
                     }
                 } else {
                     SkRect  r;
@@ -624,7 +634,11 @@
                         r.fTop = pts[i].fY - radius;
                         r.fRight = r.fLeft + width;
                         r.fBottom = r.fTop + width;
-                        this->drawRect(r, paint);
+                        if (fDevice) {
+                            fDevice->drawRect(*this, r, paint);
+                        } else {
+                            this->drawRect(r, paint);
+                        }
                     }
                 }
                 break;
@@ -639,7 +653,11 @@
                 for (size_t i = 0; i < count; i += inc) {
                     path.moveTo(pts[i]);
                     path.lineTo(pts[i+1]);
-                    this->drawPath(path, p, NULL, true);
+                    if (fDevice) {
+                        fDevice->drawPath(*this, path, p, NULL, true);
+                    } else {
+                        this->drawPath(path, p, NULL, true);
+                    }
                     path.rewind();
                 }
                 break;
@@ -657,7 +675,7 @@
 }
 
 void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const {
-    SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+    SkDEBUGCODE(this->validate();)
 
     // nothing to draw
     if (fClip->isEmpty() ||
@@ -799,7 +817,7 @@
 
 void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& paint,
                       const SkMatrix* prePathMatrix, bool pathIsMutable) const {
-    SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+    SkDEBUGCODE(this->validate();)
 
     // nothing to draw
     if (fClip->isEmpty() ||
@@ -846,7 +864,8 @@
     // can we approximate a thin (but not hairline) stroke with an alpha-modulated
     // hairline? Only if the matrix scales evenly in X and Y, and the device-width is
     // less than a pixel
-    if (paint.getStyle() == SkPaint::kStroke_Style && paint.getXfermode() == NULL) {
+    if (paint.isAntiAlias() &&
+        paint.getStyle() == SkPaint::kStroke_Style && paint.getXfermode() == NULL) {
         SkScalar width = paint.getStrokeWidth();
         if (width > 0 && map_radius(*matrix, &width)) {
             int scale = (int)SkScalarMul(width, 256);
@@ -1024,7 +1043,7 @@
 
 void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
                         const SkPaint& paint) const {
-    SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+    SkDEBUGCODE(this->validate();)
 
     // nothing to draw
     if (fClip->isEmpty() ||
@@ -1116,7 +1135,7 @@
 
 void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
                         const SkPaint& paint) const {
-    SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+    SkDEBUGCODE(this->validate();)
     
     // nothing to draw
     if (fClip->isEmpty() ||
@@ -1207,7 +1226,7 @@
 void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
                               SkScalar x, SkScalar y,
                               const SkPaint& paint) const {
-    SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+    SkDEBUGCODE(this->validate();)
 
     SkTextToPathIter iter(text, byteLength, paint, true, true);
 
@@ -1220,7 +1239,12 @@
 
     while ((iterPath = iter.next(&xpos)) != NULL) {
         matrix.postTranslate(xpos - prevXPos, 0);
-        this->drawPath(*iterPath, iter.getPaint(), &matrix, false);
+        const SkPaint& pnt = iter.getPaint();
+        if (fDevice) {
+            fDevice->drawPath(*this, *iterPath, pnt, &matrix, false);
+        } else {
+            this->drawPath(*iterPath, pnt, &matrix, false);
+        }
         prevXPos = xpos;
     }
 }
@@ -1275,7 +1299,10 @@
 //////////////////////////////////////////////////////////////////////////////
 
 static void D1G_NoBounder_RectClip(const SkDraw1Glyph& state,
-								   const SkGlyph& glyph, int left, int top) {
+                                   SkFixed fx, SkFixed fy,
+                                   const SkGlyph& glyph) {
+    int left = SkFixedFloor(fx);
+    int top = SkFixedFloor(fy);
     SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
 	SkASSERT(state.fClip->isRect());
 	SkASSERT(NULL == state.fBounder);
@@ -1316,7 +1343,10 @@
 }
 
 static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state,
-								  const SkGlyph& glyph, int left, int top) {
+                                  SkFixed fx, SkFixed fy,
+								  const SkGlyph& glyph) {
+    int left = SkFixedFloor(fx);
+    int top = SkFixedFloor(fy);
     SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
 	SkASSERT(!state.fClip->isRect());
 	SkASSERT(NULL == state.fBounder);
@@ -1350,7 +1380,10 @@
 }
 
 static void D1G_Bounder(const SkDraw1Glyph& state,
-						const SkGlyph& glyph, int left, int top) {
+                        SkFixed fx, SkFixed fy,
+						const SkGlyph& glyph) {
+    int left = SkFixedFloor(fx);
+    int top = SkFixedFloor(fy);
     SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
 
     SkMask  mask;
@@ -1435,7 +1468,7 @@
                       SkScalar x, SkScalar y, const SkPaint& paint) const {
     SkASSERT(byteLength == 0 || text != NULL);
 
-    SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+    SkDEBUGCODE(this->validate();)
 
     // nothing to draw
     if (text == NULL || byteLength == 0 ||
@@ -1470,14 +1503,25 @@
 
     SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
 
-    SkAutoGlyphCache    autoCache(paint, fMatrix);
+    const SkMatrix* matrix = fMatrix;
+    SkFixed finalFYMask = ~0xFFFF;  // trunc fy;
+    if (fProcs && fProcs->fD1GProc) {
+        // only support the fMVMatrix (for now) for the GPU case, which also
+        // sets the fD1GProc
+        if (fMVMatrix) {
+            matrix = fMVMatrix;
+            finalFYMask = ~0;  // don't truncate
+        }
+    }
+
+    SkAutoGlyphCache    autoCache(paint, matrix);
     SkGlyphCache*       cache = autoCache.getCache();
-    SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
+    SkAutoBlitterChoose blitter(*fBitmap, *matrix, paint);
     
     // transform our starting point
     {
         SkPoint loc;
-        fMatrix->mapXY(x, y, &loc);
+        matrix->mapXY(x, y, &loc);
         x = loc.fX;
         y = loc.fY;
     }
@@ -1503,30 +1547,33 @@
     SkFixed fy = SkScalarToFixed(y);
     const char* stop = text + byteLength;
 
+    SkFixed fxMask = ~0;
+    SkFixed fyMask = ~0;
     if (paint.isSubpixelText()) {
-        RoundBaseline roundBaseline = computeRoundBaseline(*fMatrix);
+        RoundBaseline roundBaseline = computeRoundBaseline(*matrix);
         if (kRound_Y_Baseline == roundBaseline) {
-            fy = (fy + 0x8000) & ~0xFFFF;
+            fyMask = 0;
+//            fy = (fy + 0x8000) & ~0xFFFF;
         } else if (kRound_X_Baseline == roundBaseline) {
-            fx = (fx + 0x8000) & ~0xFFFF;
+            fxMask = 0;
         }
-    } else {
-        // apply the bias here, so we don't have to add 1/2 in the loop
-        fx += SK_Fixed1/2;
-        fy += SK_Fixed1/2;
     }
+    // apply the bias here, so we don't have to add 1/2 in the loop
+    fx += SK_FixedHalf;
+    fy += SK_FixedHalf;
+    fy &= finalFYMask;
 
     SkAutoKern          autokern;
 	SkDraw1Glyph        d1g;
 	SkDraw1Glyph::Proc  proc = d1g.init(this, blitter.get(), cache);
 
     while (text < stop) {
-        const SkGlyph& glyph  = glyphCacheProc(cache, &text, fx, fy);
+        const SkGlyph& glyph  = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
 
         fx += autokern.adjust(glyph);
 
         if (glyph.fWidth) {
-			proc(d1g, glyph, SkFixedFloor(fx), SkFixedFloor(fy));
+			proc(d1g, fx, fy, glyph);
         }
         fx += glyph.fAdvanceX;
         fy += glyph.fAdvanceY;
@@ -1636,7 +1683,7 @@
     SkASSERT(byteLength == 0 || text != NULL);
     SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
 
-    SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
+    SkDEBUGCODE(this->validate();)
 
     // nothing to draw
     if (text == NULL || byteLength == 0 ||
@@ -1652,39 +1699,52 @@
         return;
     }
 
+    const SkMatrix* matrix = fMatrix;
+    if (fProcs && fProcs->fD1GProc) {
+        // only support the fMVMatrix (for now) for the GPU case, which also
+        // sets the fD1GProc
+        if (fMVMatrix) {
+            matrix = fMVMatrix;
+        }
+    }
+    
     SkDrawCacheProc     glyphCacheProc = paint.getDrawCacheProc();
-    SkAutoGlyphCache    autoCache(paint, fMatrix);
+    SkAutoGlyphCache    autoCache(paint, matrix);
     SkGlyphCache*       cache = autoCache.getCache();
-    SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
+    SkAutoBlitterChoose blitter(*fBitmap, *matrix, paint);
     
     const char*        stop = text + byteLength;
     AlignProc          alignProc = pick_align_proc(paint.getTextAlign());
 	SkDraw1Glyph	   d1g;
 	SkDraw1Glyph::Proc  proc = d1g.init(this, blitter.get(), cache);
-    TextMapState       tms(*fMatrix, constY);
+    TextMapState       tms(*matrix, constY);
     TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
 
     if (paint.isSubpixelText()) {
         // maybe we should skip the rounding if linearText is set
-        RoundBaseline roundBaseline = computeRoundBaseline(*fMatrix);
+        RoundBaseline roundBaseline = computeRoundBaseline(*matrix);
 
         if (SkPaint::kLeft_Align == paint.getTextAlign()) {
             while (text < stop) {
+                
                 tmsProc(tms, pos);
                 
                 SkFixed fx = SkScalarToFixed(tms.fLoc.fX);
                 SkFixed fy = SkScalarToFixed(tms.fLoc.fY);
+                SkFixed fxMask = ~0;
+                SkFixed fyMask = ~0;
 
                 if (kRound_Y_Baseline == roundBaseline) {
-                    fy = (fy + 0x8000) & ~0xFFFF;
+                    fyMask = 0;
                 } else if (kRound_X_Baseline == roundBaseline) {
-                    fx = (fx + 0x8000) & ~0xFFFF;
+                    fxMask = 0;
                 }
                 
-                const SkGlyph& glyph = glyphCacheProc(cache, &text, fx, fy);
+                const SkGlyph& glyph = glyphCacheProc(cache, &text,
+                                                      fx & fxMask, fy & fyMask);
                 
                 if (glyph.fWidth) {
-                    proc(d1g, glyph, SkFixedFloor(fx), SkFixedFloor(fy));
+                    proc(d1g, fx, fy, glyph);
                 }
                 pos += scalarsPerPosition;
             }
@@ -1697,6 +1757,8 @@
                     SkDEBUGCODE(SkFixed prevAdvY = glyph->fAdvanceY;)
 
                     SkFixed fx, fy;
+                    SkFixed fxMask = ~0;
+                    SkFixed fyMask = ~0;
                     tmsProc(tms, pos);
                     
                     {
@@ -1706,19 +1768,19 @@
                         fy = fixedLoc.fY;
 
                         if (kRound_Y_Baseline == roundBaseline) {
-                            fy = (fy + 0x8000) & ~0xFFFF;
+                            fyMask = 0;
                         } else if (kRound_X_Baseline == roundBaseline) {
-                            fx = (fx + 0x8000) & ~0xFFFF;
+                            fxMask = 0;
                         }
                     }
                     
                     // have to call again, now that we've been "aligned"
-                    glyph = &glyphCacheProc(cache, &text, fx, fy);
+                    glyph = &glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
                     // the assumption is that the advance hasn't changed
                     SkASSERT(prevAdvX == glyph->fAdvanceX);
                     SkASSERT(prevAdvY == glyph->fAdvanceY);
                     
-                    proc(d1g, *glyph, SkFixedFloor(fx), SkFixedFloor(fy));
+                    proc(d1g, fx, fy, *glyph);
                 }
                 pos += scalarsPerPosition;
             }
@@ -1734,8 +1796,8 @@
                 SkIPoint fixedLoc;
                 alignProc(tms.fLoc, glyph, &fixedLoc);
                 
-                proc(d1g, glyph,
-                     SkFixedRound(fixedLoc.fX), SkFixedRound(fixedLoc.fY));
+                proc(d1g, fixedLoc.fX + SK_FixedHalf,
+                     fixedLoc.fY + SK_FixedHalf, glyph);
             }
             pos += scalarsPerPosition;
         }
@@ -1863,7 +1925,11 @@
             m.postConcat(*matrix);
         }
         morphpath(&tmp, *iterPath, meas, m);
-        this->drawPath(tmp, iter.getPaint());
+        if (fDevice) {
+            fDevice->drawPath(*this, tmp, iter.getPaint(), NULL, true);
+        } else {
+            this->drawPath(tmp, iter.getPaint(), NULL, true);
+        }
     }
 }
 
@@ -2232,7 +2298,7 @@
 
 #ifdef SK_DEBUG
 
-void SkDraw::validate(int width, int height) const {
+void SkDraw::validate() const {
     SkASSERT(fBitmap != NULL);
     SkASSERT(fMatrix != NULL);
     SkASSERT(fClip != NULL);
@@ -2240,8 +2306,11 @@
     const SkIRect&  cr = fClip->getBounds();
     SkIRect         br;
 
-    br.set(0, 0, width, height);
+    br.set(0, 0, fBitmap->width(), fBitmap->height());
     SkASSERT(cr.isEmpty() || br.contains(cr));
+
+    // assert that both are null, or both are not-null
+    SkASSERT(!fMVMatrix == !fExtMatrix);
 }
 
 #endif
diff --git a/src/core/SkDrawProcs.h b/src/core/SkDrawProcs.h
index d64c088..7d69465 100644
--- a/src/core/SkDrawProcs.h
+++ b/src/core/SkDrawProcs.h
@@ -13,7 +13,9 @@
 	SkGlyphCache*	fCache;
 	SkIRect			fClipBounds;
 	
-	typedef void (*Proc)(const SkDraw1Glyph&, const SkGlyph&, int x, int y);
+    // The fixed x,y have been pre-rounded (i.e. 1/2 has already been added),
+    // so the impls need just trunc down to an int
+	typedef void (*Proc)(const SkDraw1Glyph&, SkFixed x, SkFixed y, const SkGlyph&);
 	
 	Proc init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache);
 };
diff --git a/src/core/SkGlyphCache.cpp b/src/core/SkGlyphCache.cpp
index c744dfe..199ac14 100644
--- a/src/core/SkGlyphCache.cpp
+++ b/src/core/SkGlyphCache.cpp
@@ -96,22 +96,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 #ifdef SK_DEBUG
-class AutoCheckForNull {
-public:
-    AutoCheckForNull(const SkTDArray<SkGlyph*>& array) : fArray(array) {
-        for (int i = 0; i < array.count(); i++)
-            SkASSERT(array[i]);
-    }
-    ~AutoCheckForNull() {
-        const SkTDArray<SkGlyph*>& array = fArray;
-        for (int i = 0; i < array.count(); i++) {
-            SkASSERT(array[i]);
-        }
-    }
-private:
-    const SkTDArray<SkGlyph*>& fArray;
-};
-#define VALIDATE()  AutoCheckForNull acfn(fGlyphArray)
+#define VALIDATE()  AutoValidate av(this)
 #else
 #define VALIDATE()
 #endif
@@ -288,9 +273,7 @@
 
     glyph = (SkGlyph*)fGlyphAlloc.alloc(sizeof(SkGlyph),
                                         SkChunkAlloc::kThrow_AllocFailType);
-    glyph->fID = id;
-    glyph->fImage = NULL;
-    glyph->fPath = NULL;
+    glyph->init(id);
     *fGlyphArray.insert(hi) = glyph;
     
     if (kJustAdvance_MetricsType == mtype) {
@@ -519,6 +502,9 @@
     cache = SkNEW_ARGS(SkGlyphCache, (desc));
 
 FOUND_IT:
+
+    AutoValidate av(cache);
+
     if (proc(cache, context)) {   // stay detached
         if (insideMutex) {
             SkASSERT(globals.fTotalMemoryUsed >= cache->fMemoryUsed);
@@ -549,6 +535,7 @@
     SkAutoMutexAcquire    ac(globals.fMutex);
 
     globals.validate();
+    cache->validate();
 
     // if we have a fixed budget for our cache, do a purge here
     {
@@ -664,3 +651,19 @@
     return bytesFreed;
 }
 
+///////////////////////////////////////////////////////////////////////////////
+#ifdef SK_DEBUG
+
+void SkGlyphCache::validate() const {
+    int count = fGlyphArray.count();
+    for (int i = 0; i < count; i++) {
+        const SkGlyph* glyph = fGlyphArray[i];
+        SkASSERT(glyph);
+        SkASSERT(fGlyphAlloc.contains(glyph));
+        if (glyph->fImage) {
+            SkASSERT(fImageAlloc.contains(glyph->fImage));
+        }
+    }
+}
+
+#endif
diff --git a/src/core/SkGlyphCache.h b/src/core/SkGlyphCache.h
index cc81ed6..16330f8 100644
--- a/src/core/SkGlyphCache.h
+++ b/src/core/SkGlyphCache.h
@@ -91,7 +91,9 @@
     const SkPaint::FontMetrics& getFontMetricsY() const {
         return fFontMetricsY;
     }
-    
+
+    const SkDescriptor& getDescriptor() const { return *fDesc; }
+
     /*  AuxProc/Data allow a client to associate data with this cache entry.
         Multiple clients can use this, as their data is keyed with a function
         pointer. In addition to serving as a key, the function pointer is called
@@ -154,6 +156,31 @@
     */
     static bool SetCacheUsed(size_t bytesUsed);
 
+#ifdef SK_DEBUG
+    void validate() const;
+#else
+    void validate() const {}
+#endif
+
+    class AutoValidate : SkNoncopyable {
+    public:
+        AutoValidate(const SkGlyphCache* cache) : fCache(cache) {
+            if (fCache) {
+                fCache->validate();
+            }
+        }
+        ~AutoValidate() {
+            if (fCache) {
+                fCache->validate();
+            }
+        }
+        void forget() {
+            fCache = NULL;
+        }
+    private:
+        const SkGlyphCache* fCache;
+    };
+        
 private:
     SkGlyphCache(const SkDescriptor*);
     ~SkGlyphCache();
diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp
index e85c6ec..f2d1708 100644
--- a/src/core/SkMatrix.cpp
+++ b/src/core/SkMatrix.cpp
@@ -1595,8 +1595,10 @@
 }
 
 uint32_t SkMatrix::unflatten(const void* buffer) {
-    memcpy(fMat, buffer, 9 * sizeof(SkScalar));
-    this->setTypeMask(kUnknown_Mask);
+    if (buffer) {
+        memcpy(fMat, buffer, 9 * sizeof(SkScalar));
+        this->setTypeMask(kUnknown_Mask);
+    }
     return 9 * sizeof(SkScalar);
 }
 
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 88d924b..d4c5b83 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1209,6 +1209,11 @@
     return h;
 }
 
+static SkScalar sk_relax(SkScalar x) {
+    int n = sk_float_round2int(x * 1024);
+    return n / 1024.0f;
+}
+
 void SkScalerContext::MakeRec(const SkPaint& paint,
                               const SkMatrix* deviceMatrix, Rec* rec)
 {
@@ -1222,10 +1227,10 @@
 
     if (deviceMatrix)
     {
-        rec->fPost2x2[0][0] = deviceMatrix->getScaleX();
-        rec->fPost2x2[0][1] = deviceMatrix->getSkewX();
-        rec->fPost2x2[1][0] = deviceMatrix->getSkewY();
-        rec->fPost2x2[1][1] = deviceMatrix->getScaleY();
+        rec->fPost2x2[0][0] = sk_relax(deviceMatrix->getScaleX());
+        rec->fPost2x2[0][1] = sk_relax(deviceMatrix->getSkewX());
+        rec->fPost2x2[1][0] = sk_relax(deviceMatrix->getSkewY());
+        rec->fPost2x2[1][1] = sk_relax(deviceMatrix->getScaleY());
     }
     else
     {
diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp
index b149be9..983f1ad 100644
--- a/src/core/SkScalerContext.cpp
+++ b/src/core/SkScalerContext.cpp
@@ -344,7 +344,9 @@
         }
     }
 
-    glyph->fMaskFormat = fRec.fMaskFormat;
+	if (SkMask::kARGB32_Format != glyph->fMaskFormat) {
+		glyph->fMaskFormat = fRec.fMaskFormat;
+	}
 
     if (fMaskFilter) {
         SkMask      src, dst;
@@ -668,9 +670,14 @@
     }
 };
 
+extern SkScalerContext* SkCreateColorScalerContext(const SkDescriptor* desc);
+
 SkScalerContext* SkScalerContext::Create(const SkDescriptor* desc)
 {
-    SkScalerContext* c = SkFontHost::CreateScalerContext(desc);
+	SkScalerContext* c = NULL;  //SkCreateColorScalerContext(desc);
+	if (NULL == c) {
+		c = SkFontHost::CreateScalerContext(desc);
+	}
     if (NULL == c) {
         c = SkNEW_ARGS(SkScalerContext_Empty, (desc));
     }
diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp
index 34dc32e..7b3a024 100644
--- a/src/core/SkShader.cpp
+++ b/src/core/SkShader.cpp
@@ -17,6 +17,7 @@
 
 #include "SkShader.h"
 #include "SkPaint.h"
+#include "SkMallocPixelRef.h"
 
 SkShader::SkShader() : fLocalMatrix(NULL) {
     SkDEBUGCODE(fInSession = false;)
@@ -195,8 +196,9 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-bool SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) {
-    return false;
+SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, 
+                                         TileMode*, SkScalar*) {
+    return kNone_BitmapType;
 }
 
 SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
@@ -209,9 +211,28 @@
 #include "SkColorShader.h"
 #include "SkUtils.h"
 
+SkColorShader::SkColorShader() {
+    fFlags = 0;
+    fInheritColor = true;
+    fAsABitmapPixelRef = NULL;
+}
+
+SkColorShader::SkColorShader(SkColor c) {
+    fFlags = 0;
+    fColor = c;
+    fInheritColor = false;
+    fAsABitmapPixelRef = NULL;
+}
+
+SkColorShader::~SkColorShader() {
+    SkSafeUnref(fAsABitmapPixelRef);
+}
+
 SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) {
     fFlags = 0; // computed in setContext
-    fInheritColor = b.readU8(); 
+    fAsABitmapPixelRef = NULL;
+
+    fInheritColor = b.readU8();
     if (fInheritColor) {
         return;
     }
@@ -285,3 +306,28 @@
     memset(alpha, SkGetPackedA32(fPMColor), count);
 }
 
+// if we had a asAColor method, that would be more efficient...
+SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix,
+                                              TileMode modes[], 
+                                              SkScalar* twoPointRadialParams) {
+    // we cache the pixelref, since its generateID is used in the texture cache
+    if (NULL == fAsABitmapPixelRef) {
+        SkPMColor* storage = (SkPMColor*)sk_malloc_throw(sizeof(SkPMColor));
+        *storage = fPMColor;
+        fAsABitmapPixelRef = new SkMallocPixelRef(storage, sizeof(SkPMColor),
+                                                  NULL);
+    }
+        
+    if (bitmap) {
+        bitmap->setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
+        bitmap->setPixelRef(fAsABitmapPixelRef);
+    }
+    if (matrix) {
+        matrix->reset();
+    }
+    if (modes) {
+        modes[0] = modes[1] = SkShader::kRepeat_TileMode;
+    }
+    return kDefault_BitmapType;
+}
+
diff --git a/src/core/SkStroke.cpp b/src/core/SkStroke.cpp
index 1fb25a6..c35400b 100644
--- a/src/core/SkStroke.cpp
+++ b/src/core/SkStroke.cpp
@@ -633,6 +633,10 @@
 
     if (fDoFill) {
         dst->addPath(src);
+    } else {
+        if (src.countPoints() == 2) {
+            dst->setIsConvex(true);
+        }
     }
 }
 
diff --git a/include/utils/SkTextFormatParams.h b/src/core/SkTextFormatParams.h
similarity index 100%
rename from include/utils/SkTextFormatParams.h
rename to src/core/SkTextFormatParams.h
diff --git a/src/core/SkUtils.cpp b/src/core/SkUtils.cpp
index a88233f..9fb85c2 100644
--- a/src/core/SkUtils.cpp
+++ b/src/core/SkUtils.cpp
@@ -124,7 +124,7 @@
     }
 }
 
-#ifndef ANDROID
+#if !defined(ANDROID) || defined(SK_BUILD_FOR_ANDROID_NDK)
 static void sk_memset16_stub(uint16_t dst[], uint16_t value, int count)
 {
     SkMemset16Proc proc = SkMemset16GetPlatformProc();
diff --git a/src/core/core_files.mk b/src/core/core_files.mk
index af7b876..235fa76 100644
--- a/src/core/core_files.mk
+++ b/src/core/core_files.mk
@@ -72,6 +72,7 @@
     SkRect.cpp \
     SkRefCnt.cpp \
     SkRegion.cpp \
+    SkRegion_rects.cpp \
     SkRegion_path.cpp \
     SkScalar.cpp \
     SkScalerContext.cpp \
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index cc65413..9aefd0a 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -118,16 +118,23 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-SkDevice* SkPDFDeviceFactory::newDevice(SkBitmap::Config config,
-                                        int width, int height,
-                                        bool isOpaque, bool isForLayer) {
+SkDevice* SkPDFDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config,
+                                        int width, int height, bool isOpaque,
+                                        bool /*isForLayer*/) {
     return SkNEW_ARGS(SkPDFDevice, (width, height));
 }
 
+static inline SkBitmap makeABitmap(int width, int height) {
+    SkBitmap bitmap;
+    bitmap.setConfig(SkBitmap::kNo_Config, width, height);
+    return bitmap;
+}
+
 SkPDFDevice::SkPDFDevice(int width, int height)
     : fWidth(width),
       fHeight(height),
-      fGraphicStackIndex(0) {
+      fGraphicStackIndex(0),
+      SkDevice(NULL, makeABitmap(width, height), false) {
     fGraphicStack[0].fColor = SK_ColorBLACK;
     fGraphicStack[0].fTextSize = SK_ScalarNaN;  // This has no default value.
     fGraphicStack[0].fTextScaleX = SK_Scalar1;
@@ -271,7 +278,10 @@
 }
 
 void SkPDFDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap,
+                             const SkIRect* srcRect,
                              const SkMatrix& matrix, const SkPaint& paint) {
+    // TODO: respect srcRect if present
+
     SkMatrix transform = matrix;
     transform.postConcat(fGraphicStack[fGraphicStackIndex].fTransform);
     internalDrawBitmap(transform, bitmap, paint);
diff --git a/src/pdf/pdf_files.mk b/src/pdf/pdf_files.mk
index 8d721eb..149e802 100644
--- a/src/pdf/pdf_files.mk
+++ b/src/pdf/pdf_files.mk
@@ -8,4 +8,4 @@
     SkPDFImage.cpp \
     SkPDFPage.cpp \
     SkPDFStream.cpp \
-    SkPDFTypes.cpp \
+    SkPDFTypes.cpp
diff --git a/src/utils/SkProxyCanvas.cpp b/src/utils/SkProxyCanvas.cpp
index c643c82..d462d01 100644
--- a/src/utils/SkProxyCanvas.cpp
+++ b/src/utils/SkProxyCanvas.cpp
@@ -18,14 +18,6 @@
     return fProxy->getViewport(size);
 }
 
-bool SkProxyCanvas::setViewport(int x, int y) {
-    return fProxy->setViewport(x, y);
-}
-
-SkDevice* SkProxyCanvas::setBitmapDevice(const SkBitmap& bitmap) {
-    return fProxy->setBitmapDevice(bitmap);
-}
-
 int SkProxyCanvas::save(SaveFlags flags) {
     return fProxy->save(flags);
 }
@@ -163,8 +155,8 @@
     return fProxy->setDrawFilter(filter);
 }
 
-SkDevice* SkProxyCanvas::createDevice(SkBitmap::Config config, int width,
-                                int height, bool isOpaque, bool isForLayer) {
+SkDevice* SkProxyCanvas::createDevice(SkBitmap::Config config, int width, int height,
+                                      bool isOpaque, bool isForLayer) {
     return fProxy->createDevice(config, width, height, isOpaque, isForLayer);
 }
 
diff --git a/src/utils/mac/SkCreateCGImageRef.cpp b/src/utils/mac/SkCreateCGImageRef.cpp
index 5c96e21..2169bc0 100644
--- a/src/utils/mac/SkCreateCGImageRef.cpp
+++ b/src/utils/mac/SkCreateCGImageRef.cpp
@@ -26,22 +26,19 @@
             *bitsPerComponent = 8;
 #if defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 0, 8, 16) \
  || defined(SK_CPU_BENDIAN) && HAS_ARGB_SHIFTS(0, 24, 16, 8)
-            *info = kCGBitmapByteOrder32Big |
-                    kCGImageAlphaPremultipliedLast;
+            *info = kCGBitmapByteOrder32Big;
 #elif defined(SK_CPU_LENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0) \
    || defined(SK_CPU_BENDIAN) && HAS_ARGB_SHIFTS(24, 16, 8, 0)
             // Matches the CGBitmapInfo that Apple recommends for best
             // performance, used by google chrome.
-            *info = kCGBitmapByteOrder32Host |
-                    kCGImageAlphaPremultipliedFirst;
+            *info = kCGBitmapByteOrder32Little;
 #else
 // ...add more formats as required...
 #warning Cannot convert SkBitmap to CGImageRef with these shiftmasks. \
             This will probably not work.
             // Legacy behavior. Perhaps turn this into an error at some
             // point.
-            *info = kCGBitmapByteOrder32Big |
-                    kCGImageAlphaPremultipliedLast;
+            *info = kCGBitmapByteOrder32Big;
 #endif
             break;
 #if 0
@@ -59,6 +56,10 @@
             return NULL;
     }
 
+    if (!bm.isOpaque()) {
+        *info |= kCGImageAlphaPremultipliedLast;
+    }
+
     SkBitmap* copy;
     if (upscaleTo32) {
         copy = new SkBitmap;
@@ -93,7 +94,7 @@
     CGDataProviderRef dataRef = CGDataProviderCreateWithData(bitmap, bitmap->getPixels(), s,
 															 SkBitmap_ReleaseInfo);
 
-    CGColorSpaceRef space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+    CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
     CGImageRef ref = CGImageCreate(w, h, bitsPerComponent,
                                    bitmap->bytesPerPixel() * 8,
                                    bitmap->rowBytes(), space, info, dataRef,
@@ -103,4 +104,23 @@
     return ref;
 }
 
+void SkCGDrawBitmap(CGContextRef cg, const SkBitmap& bm, float x, float y) {
+    CGImageRef img = SkCreateCGImageRef(bm);
+
+    if (img) {
+        CGRect r = CGRectMake(0, 0, bm.width(), bm.height());
+        
+        CGContextSaveGState(cg);
+        CGContextTranslateCTM(cg, x, r.size.height + y);
+        CGContextScaleCTM(cg, 1, -1);
+        
+        CGContextDrawImage(cg, r, img);
+        
+        CGContextRestoreGState(cg);
+        
+        CGImageRelease(img);
+    }
+}
+
+
 
diff --git a/src/utils/mac/SkOSWindow_Mac.cpp b/src/utils/mac/SkOSWindow_Mac.cpp
index eb07e2a..6828a95 100644
--- a/src/utils/mac/SkOSWindow_Mac.cpp
+++ b/src/utils/mac/SkOSWindow_Mac.cpp
@@ -2,6 +2,8 @@
 
 #if defined(SK_BUILD_FOR_MAC) && !defined(SK_USE_WXWIDGETS)
 
+#include <AGL/agl.h>
+
 #include <Carbon/Carbon.h>
 #include "SkCGUtils.h"
 
@@ -82,7 +84,7 @@
     pos->offset = 0;
 }
 
-SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd)
+SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd), fAGLCtx(NULL)
 {
 	OSStatus    result;
     WindowRef   wr = (WindowRef)hWnd;
@@ -450,5 +452,79 @@
 	}
 }
 
+AGLContext create_gl(WindowRef wref, bool offscreen)
+{
+    GLint major, minor;
+    AGLContext ctx;
+    
+    aglGetVersion(&major, &minor);
+    SkDebugf("---- agl version %d %d\n", major, minor);
+    
+    const GLint pixelAttrs[] = {
+        AGL_RGBA,
+        AGL_STENCIL_SIZE, 8,
+        AGL_SAMPLE_BUFFERS_ARB, 1,
+		AGL_MULTISAMPLE,
+		AGL_SAMPLES_ARB, 2,        
+		(offscreen ? AGL_OFFSCREEN : AGL_ACCELERATED),
+        (offscreen ? AGL_NONE : AGL_DOUBLEBUFFER),
+        AGL_NONE
+    };
+    AGLPixelFormat format = aglChoosePixelFormat(NULL, 0, pixelAttrs);
+    //AGLPixelFormat format = aglCreatePixelFormat(pixelAttrs);
+    SkDebugf("----- agl format %p\n", format);
+    ctx = aglCreateContext(format, NULL);
+    SkDebugf("----- agl context %p\n", ctx);
+    aglDestroyPixelFormat(format);
+
+    static const GLint interval = 1;
+    aglSetInteger(ctx, AGL_SWAP_INTERVAL, &interval);
+    aglSetCurrentContext(ctx);
+    return ctx;
+}
+
+bool SkOSWindow::attachGL(const SkBitmap* offscreen)
+{
+    if (NULL == fAGLCtx) {
+        fAGLCtx = create_gl((WindowRef)fHWND, NULL != offscreen);
+        if (NULL == fAGLCtx) {
+            return false;
+        }
+    }
+
+    GLboolean success = true;
+
+    if (offscreen) {
+        success = aglSetOffScreen((AGLContext)fAGLCtx,
+                                    offscreen->width(),
+                                    offscreen->height(),
+                                    offscreen->rowBytes(),
+                                    offscreen->getPixels());
+    } else {
+        success = aglSetWindowRef((AGLContext)fAGLCtx, (WindowRef)fHWND);
+    }
+
+    GLenum err = aglGetError();
+    if (err) {
+        SkDebugf("---- setoffscreen %d %d %s [%d %d]\n", success, err,
+                 aglErrorString(err), offscreen->width(), offscreen->height());
+    }
+    
+    if (success) {
+        glClearColor(0, 0, 0, 0);
+        glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+    }
+    return success;
+}
+
+void SkOSWindow::detachGL() {
+    aglSetWindowRef((AGLContext)fAGLCtx, NULL);
+}
+
+void SkOSWindow::presentGL() {
+    aglSwapBuffers((AGLContext)fAGLCtx);
+    glFlush();
+}
+
 #endif
 
diff --git a/src/utils/win/SkOSWindow_Win.cpp b/src/utils/win/SkOSWindow_Win.cpp
index 376c3bd..26993be 100644
--- a/src/utils/win/SkOSWindow_Win.cpp
+++ b/src/utils/win/SkOSWindow_Win.cpp
@@ -1,213 +1,569 @@
-#include "SkTypes.h"

-

-#if defined(SK_BUILD_FOR_WIN)

-

-#include "SkWindow.h"

-#include "SkCanvas.h"

-#include "SkOSMenu.h"

-#include "SkTime.h"

-

-#include "SkGraphics.h"

-

-static SkOSWindow* gCurrOSWin;

-

-SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd) {

-}

-

-static SkKey winToskKey(WPARAM vk) {

-	static const struct {

-		WPARAM	fVK;

-		SkKey	fKey;

-	} gPair[] = {

-		{ VK_BACK,	kBack_SkKey },

-		{ VK_CLEAR,	kBack_SkKey },

-		{ VK_RETURN, kOK_SkKey },

-		{ VK_UP,	 kUp_SkKey },

-		{ VK_DOWN,	 kDown_SkKey },

-		{ VK_LEFT,	 kLeft_SkKey },

-		{ VK_RIGHT,	 kRight_SkKey }

-	};

-	for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {

-		if (gPair[i].fVK == vk) {

-			return gPair[i].fKey;

-		}

-	}

-	return kNONE_SkKey;

-}

-

-bool SkOSWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {

-	switch (message) {

-		case WM_KEYDOWN: {

-			SkKey key = winToskKey(wParam);

-			if (kNONE_SkKey != key) {

-				this->handleKey(key);

-				return true;

-			}

-		} break;

-		case WM_KEYUP: {

-			SkKey key = winToskKey(wParam);

-			if (kNONE_SkKey != key) {

-				this->handleKeyUp(key);

-				return true;

-			}

-		} break;

-		case WM_UNICHAR:

-			this->handleChar(lParam);

-			return true;

-		case WM_SIZE:

-			this->resize(lParam & 0xFFFF, lParam >> 16);

-			break;

-		case WM_PAINT: {

-			PAINTSTRUCT ps;

-			HDC hdc = BeginPaint(hWnd, &ps);

-			this->doPaint(hdc);

-			EndPaint(hWnd, &ps);

-			return true;

-		} break;

-	}

-	return false;

-}

-

-void SkOSWindow::doPaint(void* ctx) {

-	this->update(NULL);

-

-	HDC hdc = (HDC)ctx;

-    const SkBitmap& bitmap = this->getBitmap();

-

-	BITMAPINFO bmi;

-	memset(&bmi, 0, sizeof(bmi));

-	bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);

-	bmi.bmiHeader.biWidth       = bitmap.width();

-	bmi.bmiHeader.biHeight      = -bitmap.height(); // top-down image 

-	bmi.bmiHeader.biPlanes      = 1;

-	bmi.bmiHeader.biBitCount    = 32;

-	bmi.bmiHeader.biCompression = BI_RGB;

-	bmi.bmiHeader.biSizeImage   = 0;

-

-	// 

-	// Do the SetDIBitsToDevice. 

-	// 

-	bitmap.lockPixels();

-	int iRet = SetDIBitsToDevice(hdc,

-		0, 0,

-		bitmap.width(), bitmap.height(),

-		0, 0,

-		0, bitmap.height(),

-		bitmap.getPixels(),

-		&bmi,

-		DIB_RGB_COLORS);

-	bitmap.unlockPixels();

-}

-

-#if 0

-void SkOSWindow::updateSize()

-{

-	RECT	r;

-	GetWindowRect((HWND)this->getHWND(), &r);

-	this->resize(r.right - r.left, r.bottom - r.top);

-}

-#endif

-

-void SkOSWindow::onHandleInval(const SkIRect& r) {

-	RECT rect;

-	rect.left = r.fLeft;

-	rect.top = r.fTop;

-	rect.right = r.fRight;

-	rect.bottom = r.fBottom;

-	InvalidateRect((HWND)this->getHWND(), &rect, false);

-}

-

-void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)

-{

-}

-

-

-enum {

-	SK_MacReturnKey		= 36,

-	SK_MacDeleteKey		= 51,

-	SK_MacEndKey		= 119,

-	SK_MacLeftKey		= 123,

-	SK_MacRightKey		= 124,

-	SK_MacDownKey		= 125,

-	SK_MacUpKey			= 126,

-    

-    SK_Mac0Key          = 0x52,

-    SK_Mac1Key          = 0x53,

-    SK_Mac2Key          = 0x54,

-    SK_Mac3Key          = 0x55,

-    SK_Mac4Key          = 0x56,

-    SK_Mac5Key          = 0x57,

-    SK_Mac6Key          = 0x58,

-    SK_Mac7Key          = 0x59,

-    SK_Mac8Key          = 0x5b,

-    SK_Mac9Key          = 0x5c

-};

-	

-static SkKey raw2key(uint32_t raw)

-{

-	static const struct {

-		uint32_t  fRaw;

-		SkKey   fKey;

-	} gKeys[] = {

-		{ SK_MacUpKey,		kUp_SkKey		},

-		{ SK_MacDownKey,	kDown_SkKey		},

-		{ SK_MacLeftKey,	kLeft_SkKey		},

-		{ SK_MacRightKey,   kRight_SkKey	},

-		{ SK_MacReturnKey,  kOK_SkKey		},

-		{ SK_MacDeleteKey,  kBack_SkKey		},

-		{ SK_MacEndKey,		kEnd_SkKey		},

-        { SK_Mac0Key,       k0_SkKey        },

-        { SK_Mac1Key,       k1_SkKey        },

-        { SK_Mac2Key,       k2_SkKey        },

-        { SK_Mac3Key,       k3_SkKey        },

-        { SK_Mac4Key,       k4_SkKey        },

-        { SK_Mac5Key,       k5_SkKey        },

-        { SK_Mac6Key,       k6_SkKey        },

-        { SK_Mac7Key,       k7_SkKey        },

-        { SK_Mac8Key,       k8_SkKey        },

-        { SK_Mac9Key,       k9_SkKey        }

-	};

-	

-	for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)

-		if (gKeys[i].fRaw == raw)

-			return gKeys[i].fKey;

-	return kNONE_SkKey;

-}

-

-///////////////////////////////////////////////////////////////////////////////////////

-

-void SkEvent::SignalNonEmptyQueue()

-{

-//	post_skmacevent();

-//	SkDebugf("signal nonempty\n");

-}

-

-//static void sk_timer_proc(TMTask* rec)

-//{

-//	SkEvent::ServiceQueueTimer();

-//	SkDebugf("timer task fired\n");

-//}

-

-void SkEvent::SignalQueueTimer(SkMSec delay)

-{

-#if 0

-	if (gTMTaskPtr)

-	{

-		RemoveTimeTask((QElem*)gTMTaskPtr);

-		DisposeTimerUPP(gTMTaskPtr->tmAddr);

-		gTMTaskPtr = nil;

-	}

-	if (delay)

-	{

-		gTMTaskPtr = &gTMTaskRec;

-		memset(gTMTaskPtr, 0, sizeof(gTMTaskRec));

-		gTMTaskPtr->tmAddr = NewTimerUPP(sk_timer_proc);

-		OSErr err = InstallTimeTask((QElem*)gTMTaskPtr);

-//		SkDebugf("installtimetask of %d returned %d\n", delay, err);

-		PrimeTimeTask((QElem*)gTMTaskPtr, delay);

-	}

-#endif

-}

-

-#endif

-

+#include "SkTypes.h"
+
+#if defined(SK_BUILD_FOR_WIN)
+
+#include <GL/glew.h>
+#include <GL/wglew.h>
+#include <GL/gl.h>
+#include <d3d9.h>
+#include <WindowsX.h>
+#include "SkWindow.h"
+#include "SkCanvas.h"
+#include "SkOSMenu.h"
+#include "SkTime.h"
+#include "SkUtils.h"
+
+#include "SkGraphics.h"
+
+#define INVALIDATE_DELAY_MS 200
+
+static SkOSWindow* gCurrOSWin;
+static HWND gEventTarget;
+
+#define WM_EVENT_CALLBACK (WM_USER+0)
+
+void post_skwinevent()
+{
+    PostMessage(gEventTarget, WM_EVENT_CALLBACK, 0, 0);
+}
+
+SkOSWindow::SkOSWindow(void* hWnd) : fHWND(hWnd), 
+                                     fHGLRC(NULL),
+                                     fGLAttached(false),
+                                     fD3D9Device(NULL),
+                                     fD3D9Attached(FALSE) {
+    gEventTarget = (HWND)hWnd;
+}
+
+SkOSWindow::~SkOSWindow() {
+    if (NULL != fD3D9Device) {
+        ((IDirect3DDevice9*)fD3D9Device)->Release();
+    }
+    if (NULL != fHGLRC) {
+        wglDeleteContext((HGLRC)fHGLRC);
+    }
+}
+
+static SkKey winToskKey(WPARAM vk) {
+	static const struct {
+		WPARAM	fVK;
+		SkKey	fKey;
+	} gPair[] = {
+		{ VK_BACK,	kBack_SkKey },
+		{ VK_CLEAR,	kBack_SkKey },
+		{ VK_RETURN, kOK_SkKey },
+		{ VK_UP,	 kUp_SkKey },
+		{ VK_DOWN,	 kDown_SkKey },
+		{ VK_LEFT,	 kLeft_SkKey },
+		{ VK_RIGHT,	 kRight_SkKey }
+	};
+	for (size_t i = 0; i < SK_ARRAY_COUNT(gPair); i++) {
+		if (gPair[i].fVK == vk) {
+			return gPair[i].fKey;
+		}
+	}
+	return kNONE_SkKey;
+}
+
+bool SkOSWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
+	switch (message) {
+		case WM_KEYDOWN: {
+			SkKey key = winToskKey(wParam);
+			if (kNONE_SkKey != key) {
+				this->handleKey(key);
+				return true;
+			}
+		} break;
+		case WM_KEYUP: {
+			SkKey key = winToskKey(wParam);
+			if (kNONE_SkKey != key) {
+				this->handleKeyUp(key);
+				return true;
+			}
+		} break;
+		case WM_UNICHAR:
+			this->handleChar(wParam);
+            return true; 
+        case WM_CHAR: {
+            this->handleChar(SkUTF8_ToUnichar((char*)&wParam));
+            return true;
+        } break;
+		case WM_SIZE:
+			this->resize(lParam & 0xFFFF, lParam >> 16);
+			break;
+		case WM_PAINT: {
+			PAINTSTRUCT ps;
+			HDC hdc = BeginPaint(hWnd, &ps);
+			this->doPaint(hdc);
+			EndPaint(hWnd, &ps);
+			return true;
+            } break;
+
+        case WM_TIMER: {
+            RECT* rect = (RECT*)wParam;
+            InvalidateRect(hWnd, rect, FALSE);
+            KillTimer(hWnd, (UINT_PTR)rect);
+            delete rect;
+            return true;
+        } break;
+    
+        case WM_LBUTTONDOWN: 
+            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kDown_State);
+            return true;
+                    
+        case WM_MOUSEMOVE:
+            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kMoved_State);
+            return true;
+
+        case WM_LBUTTONUP:
+            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), Click::kUp_State);
+            return true;
+
+        case WM_EVENT_CALLBACK:
+            if (SkEvent::ProcessEvent()) {
+                post_skwinevent();
+            }
+            return true;
+	}
+	return false;
+}
+
+void SkOSWindow::doPaint(void* ctx) {
+	this->update(NULL);
+
+    if (!fGLAttached && !fD3D9Attached)
+    {
+	    HDC hdc = (HDC)ctx;
+        const SkBitmap& bitmap = this->getBitmap();
+
+	    BITMAPINFO bmi;
+	    memset(&bmi, 0, sizeof(bmi));
+	    bmi.bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
+	    bmi.bmiHeader.biWidth       = bitmap.width();
+	    bmi.bmiHeader.biHeight      = -bitmap.height(); // top-down image 
+	    bmi.bmiHeader.biPlanes      = 1;
+	    bmi.bmiHeader.biBitCount    = 32;
+	    bmi.bmiHeader.biCompression = BI_RGB;
+	    bmi.bmiHeader.biSizeImage   = 0;
+
+	    // 
+	    // Do the SetDIBitsToDevice. 
+	    // 
+	    bitmap.lockPixels();
+	    int iRet = SetDIBitsToDevice(hdc,
+		    0, 0,
+		    bitmap.width(), bitmap.height(),
+		    0, 0,
+		    0, bitmap.height(),
+		    bitmap.getPixels(),
+		    &bmi,
+		    DIB_RGB_COLORS);
+	    bitmap.unlockPixels();
+    }
+}
+
+#if 0
+void SkOSWindow::updateSize()
+{
+	RECT	r;
+	GetWindowRect((HWND)this->getHWND(), &r);
+	this->resize(r.right - r.left, r.bottom - r.top);
+}
+#endif
+
+void SkOSWindow::onHandleInval(const SkIRect& r) {
+	RECT* rect = new RECT;
+	rect->left    = r.fLeft;
+	rect->top     = r.fTop;
+	rect->right   = r.fRight;
+	rect->bottom  = r.fBottom;
+    SetTimer((HWND)fHWND, (UINT_PTR)rect, INVALIDATE_DELAY_MS, NULL);
+}
+
+void SkOSWindow::onAddMenu(const SkOSMenu* sk_menu)
+{
+}
+
+void SkOSWindow::onSetTitle(const char title[]){
+    SetWindowTextA((HWND)fHWND, title);
+}
+
+enum {
+	SK_MacReturnKey		= 36,
+	SK_MacDeleteKey		= 51,
+	SK_MacEndKey		= 119,
+	SK_MacLeftKey		= 123,
+	SK_MacRightKey		= 124,
+	SK_MacDownKey		= 125,
+	SK_MacUpKey			= 126,
+    
+    SK_Mac0Key          = 0x52,
+    SK_Mac1Key          = 0x53,
+    SK_Mac2Key          = 0x54,
+    SK_Mac3Key          = 0x55,
+    SK_Mac4Key          = 0x56,
+    SK_Mac5Key          = 0x57,
+    SK_Mac6Key          = 0x58,
+    SK_Mac7Key          = 0x59,
+    SK_Mac8Key          = 0x5b,
+    SK_Mac9Key          = 0x5c
+};
+	
+static SkKey raw2key(uint32_t raw)
+{
+	static const struct {
+		uint32_t  fRaw;
+		SkKey   fKey;
+	} gKeys[] = {
+		{ SK_MacUpKey,		kUp_SkKey		},
+		{ SK_MacDownKey,	kDown_SkKey		},
+		{ SK_MacLeftKey,	kLeft_SkKey		},
+		{ SK_MacRightKey,   kRight_SkKey	},
+		{ SK_MacReturnKey,  kOK_SkKey		},
+		{ SK_MacDeleteKey,  kBack_SkKey		},
+		{ SK_MacEndKey,		kEnd_SkKey		},
+        { SK_Mac0Key,       k0_SkKey        },
+        { SK_Mac1Key,       k1_SkKey        },
+        { SK_Mac2Key,       k2_SkKey        },
+        { SK_Mac3Key,       k3_SkKey        },
+        { SK_Mac4Key,       k4_SkKey        },
+        { SK_Mac5Key,       k5_SkKey        },
+        { SK_Mac6Key,       k6_SkKey        },
+        { SK_Mac7Key,       k7_SkKey        },
+        { SK_Mac8Key,       k8_SkKey        },
+        { SK_Mac9Key,       k9_SkKey        }
+	};
+	
+	for (unsigned i = 0; i < SK_ARRAY_COUNT(gKeys); i++)
+		if (gKeys[i].fRaw == raw)
+			return gKeys[i].fKey;
+	return kNONE_SkKey;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////
+
+void SkEvent::SignalNonEmptyQueue()
+{
+	post_skwinevent();
+	//SkDebugf("signal nonempty\n");
+}
+
+static UINT_PTR gTimer;
+
+VOID CALLBACK sk_timer_proc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
+{
+	SkEvent::ServiceQueueTimer();
+	//SkDebugf("timer task fired\n");
+}
+
+void SkEvent::SignalQueueTimer(SkMSec delay)
+{
+	if (gTimer)
+	{
+        KillTimer(NULL, gTimer);
+	    gTimer = NULL;
+    }
+	if (delay)
+	{     
+        gTimer = SetTimer(NULL, 0, delay, sk_timer_proc);
+        //SkDebugf("SetTimer of %d returned %d\n", delay, gTimer);
+	}
+}
+
+static HWND create_dummy()
+{
+	HMODULE module = GetModuleHandle(NULL);
+	HWND dummy;
+	RECT windowRect;
+	windowRect.left = 0;
+	windowRect.right = 8;
+	windowRect.top = 0;
+	windowRect.bottom = 8;
+
+	WNDCLASS wc;
+
+	wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+	wc.lpfnWndProc = (WNDPROC) DefWindowProc;
+	wc.cbClsExtra = 0;
+	wc.cbWndExtra = 0;
+	wc.hInstance = module;
+	wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
+	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+	wc.hbrBackground = NULL;
+	wc.lpszMenuName = NULL;
+	wc.lpszClassName = L"DummyWindow";
+
+	if(!RegisterClass(&wc))
+	{
+		return 0;
+	}
+
+	DWORD style, exStyle;
+	exStyle = WS_EX_CLIENTEDGE;
+	style = WS_SYSMENU;
+
+	AdjustWindowRectEx(&windowRect, style, false, exStyle);
+
+	if(!(dummy = CreateWindowEx(exStyle,
+		L"DummyWindow",
+		L"Dummy Window",
+		WS_CLIPSIBLINGS | WS_CLIPCHILDREN | style,
+		0, 0,
+		windowRect.right-windowRect.left,
+		windowRect.bottom-windowRect.top,
+		NULL, NULL,
+		module,
+		NULL)))
+	{
+		UnregisterClass(L"Dummy Window", module);
+		return NULL;
+	}
+	ShowWindow(dummy, SW_HIDE);
+
+	return dummy;
+}
+
+void kill_dummy(HWND dummy) {
+    DestroyWindow(dummy);
+    HMODULE module = GetModuleHandle(NULL);
+    UnregisterClass(L"Dummy Window", module);
+}
+
+HGLRC create_gl(HWND hwnd) {
+    HDC hdc;    
+    HDC prevHDC;
+    HGLRC prevGLRC, glrc;
+    PIXELFORMATDESCRIPTOR pfd;
+
+    static bool glewInitialized;
+ 
+    prevGLRC = wglGetCurrentContext();
+    prevHDC  = wglGetCurrentDC();
+
+    int format = 0;
+
+    // glew must be initialized after a context has been created and made current
+    // and we need glew already be initialized to get wglChoosePixelFormatEXT :(
+    // Even worse: SetPixelFormat needs to be called before the context is created
+    // But SetPixelFormat is only allowed to succeed once per-window. So we need to
+    // create a dummy window for glew in order for it to call wglGetProcAddress() to 
+    // get wglChoosePixelFormatARB(). This is a Windows problem, not a glew problem.
+    if (!glewInitialized) {
+        ZeroMemory(&pfd, sizeof(pfd));
+        pfd.nSize = sizeof(pfd);
+        pfd.nVersion = 1;
+        pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
+        pfd.iPixelType = PFD_TYPE_RGBA;
+        pfd.cColorBits  = 32;
+        pfd.cDepthBits  = 0;
+        pfd.cStencilBits = 8;
+        pfd.iLayerType = PFD_MAIN_PLANE;
+        HWND dummy = create_dummy();
+        SkASSERT(NULL != dummy);
+        hdc = GetDC(dummy);
+        format = ChoosePixelFormat(hdc, &pfd);
+        SetPixelFormat(hdc, format, &pfd);
+        glrc = wglCreateContext(hdc);
+        SkASSERT(glrc);
+        wglMakeCurrent(hdc, glrc);
+
+        GLenum err;
+        err = glewInit();
+        SkASSERT(GLEW_OK == err);
+        SkASSERT(GLEW_EXT_bgra);
+        SkASSERT(GLEW_EXT_framebuffer_object);
+        SkASSERT(WGLEW_ARB_pixel_format);
+        glewInitialized = true;
+        wglMakeCurrent(hdc, NULL);
+        wglDeleteContext(glrc);
+        glrc = 0;
+        kill_dummy(dummy);
+    }
+    
+    hdc = GetDC(hwnd);
+    format = 0;
+
+    GLint iattrs[] = {
+        WGL_DRAW_TO_WINDOW_ARB, TRUE,
+        WGL_DOUBLE_BUFFER_ARB, TRUE,
+        WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
+        WGL_SUPPORT_OPENGL_ARB, TRUE,
+        WGL_COLOR_BITS_ARB, 24,
+        WGL_STENCIL_BITS_ARB, 8,
+        WGL_SAMPLE_BUFFERS_ARB, TRUE,
+        WGL_SAMPLES_ARB, 0,
+        0,0
+    };
+    for (int samples = 16; samples > 1; --samples) {
+        iattrs[15] = samples;
+        GLfloat fattrs[] = {0,0};
+        GLuint num;
+        int formats[64];
+        wglChoosePixelFormatARB(hdc, iattrs, fattrs, 64, formats, &num);
+        num = min(num,64);
+        for (GLuint i = 0; i < num; ++i) {            
+            DescribePixelFormat(hdc, formats[i], sizeof(pfd), &pfd);
+            if (SetPixelFormat(hdc, formats[i], &pfd)) {
+                format = formats[i];
+                break;
+            }
+        }
+    }
+    if (0 == format) {
+        iattrs[12] = iattrs[13] = 0;
+        GLfloat fattrs[] = {0,0};
+        GLuint num;
+        wglChoosePixelFormatARB(hdc, iattrs, fattrs, 1, &format, &num);
+        DescribePixelFormat(hdc, format, sizeof(pfd), &pfd);
+        BOOL set = SetPixelFormat(hdc, format, &pfd);
+        SkASSERT(TRUE == set);
+    }
+    
+    glrc = wglCreateContext(hdc);
+    SkASSERT(glrc);    
+
+    wglMakeCurrent(prevHDC, prevGLRC);
+    return glrc;
+}
+
+bool SkOSWindow::attachGL(const SkBitmap* offscreen) {
+    if (offscreen) {
+        printf("windows doesn't support rendering to SkBitmap");
+    }
+    if (NULL == fHGLRC) {
+        fHGLRC = create_gl((HWND)fHWND);
+        if (NULL == fHGLRC) {
+            return false;
+        }
+    }
+    if (wglMakeCurrent(GetDC((HWND)fHWND), (HGLRC)fHGLRC)) {
+        glClearColor(0, 0, 0, 0);
+        glClear(GL_COLOR_BUFFER_BIT);
+        fGLAttached = true;
+        return true;
+    }
+    return false;
+}
+
+void SkOSWindow::detachGL() {
+    wglMakeCurrent(GetDC((HWND)fHWND), 0);
+    fGLAttached = false;
+}
+
+void SkOSWindow::presentGL() {
+    glFlush();
+    SwapBuffers(GetDC((HWND)fHWND));
+    glClearColor(0,0,0,0);
+    glClearStencil(0);
+    glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+}
+
+IDirect3DDevice9* create_d3d9_device(HWND hwnd) {
+    HRESULT hr;
+
+    IDirect3D9* d3d9;
+    d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
+    if (NULL == d3d9) {
+        return NULL;
+    }
+    D3DDEVTYPE devType = D3DDEVTYPE_HAL;
+    //D3DDEVTYPE devType = D3DDEVTYPE_REF;
+    DWORD qLevels;
+    DWORD qLevelsDepth;
+    D3DMULTISAMPLE_TYPE type;
+    for (type = D3DMULTISAMPLE_16_SAMPLES; 
+         type >= D3DMULTISAMPLE_NONMASKABLE; --(*(DWORD*)&type)) {
+        hr = d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, 
+                                              devType, D3DFMT_D24S8, TRUE,
+                                              type, &qLevels);
+        qLevels = (hr == D3D_OK) ? qLevels : 0;
+        hr = d3d9->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, 
+                                              devType, D3DFMT_A8R8G8B8, TRUE,
+                                              type, &qLevelsDepth);
+        qLevelsDepth = (hr == D3D_OK) ? qLevelsDepth : 0;
+        qLevels = min(qLevels,qLevelsDepth);
+        if (qLevels > 0) {
+            break;
+        }
+    }
+    qLevels = 0;
+    IDirect3DDevice9* d3d9Device;
+    D3DPRESENT_PARAMETERS pres;
+    memset(&pres, 0, sizeof(pres));
+    pres.EnableAutoDepthStencil = TRUE;
+    pres.AutoDepthStencilFormat = D3DFMT_D24S8;
+    pres.BackBufferCount = 2;
+    pres.BackBufferFormat = D3DFMT_A8R8G8B8;
+    pres.BackBufferHeight = 0;
+    pres.BackBufferWidth = 0;
+    if (qLevels > 0) {
+        pres.MultiSampleType = type;
+        pres.MultiSampleQuality = qLevels-1;
+    } else {
+        pres.MultiSampleType = D3DMULTISAMPLE_NONE;
+        pres.MultiSampleQuality = 0;
+    }
+    pres.SwapEffect = D3DSWAPEFFECT_DISCARD;
+    pres.Windowed = TRUE;
+    pres.hDeviceWindow = hwnd;
+    pres.PresentationInterval = 1;
+    pres.Flags = 0;
+    hr = d3d9->CreateDevice(D3DADAPTER_DEFAULT,
+                            devType,
+                            hwnd, 
+                            D3DCREATE_HARDWARE_VERTEXPROCESSING, 
+                            &pres, 
+                            &d3d9Device);    
+    D3DERR_INVALIDCALL;
+    if (SUCCEEDED(hr)) {
+        d3d9Device->Clear(0, NULL, D3DCLEAR_TARGET, 0xFFFFFFFF, 0, 0);
+        return d3d9Device;
+    }
+    return NULL;
+}
+
+// This needs some improvement. D3D doesn't have the same notion of attach/detach
+// as GL. However, just allowing GDI to write to the window after creating the 
+// D3D device seems to work. 
+// We need to handle resizing. On XP and earlier Reset() will trash all our textures
+// so we would need to inform the SkGpu/caches or just recreate them. On Vista+ we
+// could use an IDirect3DDevice9Ex and call ResetEx() to resize without trashing
+// everything. Currently we do nothing and the D3D9 image gets stretched/compressed
+// when resized.
+
+bool SkOSWindow::attachD3D9() {
+    if (NULL == fD3D9Device) {
+        fD3D9Device = (void*) create_d3d9_device((HWND)fHWND);
+    }
+    if (NULL != fD3D9Device) {
+        ((IDirect3DDevice9*)fD3D9Device)->BeginScene();
+        fD3D9Attached = true;
+    }
+    return fD3D9Attached;
+}
+
+void SkOSWindow::detachD3D9() {
+    if (NULL != fD3D9Device) {
+        ((IDirect3DDevice9*)fD3D9Device)->EndScene();
+    }
+    fD3D9Attached = false;
+}
+
+void SkOSWindow::presentD3D9() {
+    if (NULL != fD3D9Device) {
+        HRESULT hr;
+        hr = ((IDirect3DDevice9*)fD3D9Device)->EndScene();
+        SkASSERT(SUCCEEDED(hr));
+        hr = ((IDirect3DDevice9*)d3d9Device())->Present(NULL, NULL, NULL, NULL);
+        SkASSERT(SUCCEEDED(hr));
+        hr = ((IDirect3DDevice9*)fD3D9Device)->Clear(0,NULL,D3DCLEAR_TARGET | 
+                                                     D3DCLEAR_STENCIL, 0x0, 0, 
+                                                     0);
+        SkASSERT(SUCCEEDED(hr));
+        hr = ((IDirect3DDevice9*)fD3D9Device)->BeginScene();
+        SkASSERT(SUCCEEDED(hr));
+    }
+}
+
+
+#endif
\ No newline at end of file
diff --git a/src/views/SkEvent.cpp b/src/views/SkEvent.cpp
index 67549b4..ec4a7b4 100644
--- a/src/views/SkEvent.cpp
+++ b/src/views/SkEvent.cpp
@@ -536,6 +536,21 @@
     SkEvent::SignalQueueTimer(time);
 }
 
+int SkEvent::CountEventsOnQueue() {
+    SkEvent_Globals& globals = *(SkEvent_Globals*)SkGlobals::Find(SK_Event_GlobalsTag, create_globals);
+    globals.fEventMutex.acquire();
+    
+    int count = 0;
+    const SkEvent* evt = globals.fEventQHead;
+    while (evt) {
+        count += 1;
+        evt = evt->fNextEvent;
+    }
+    globals.fEventMutex.release();
+
+    return count;
+}
+
 ////////////////////////////////////////////////////////////////
 
 void SkEvent::Init()
diff --git a/src/views/SkMetaData.cpp b/src/views/SkMetaData.cpp
index c366bd3..c871efb 100644
--- a/src/views/SkMetaData.cpp
+++ b/src/views/SkMetaData.cpp
@@ -89,6 +89,10 @@
     (void)this->set(name, &value, sizeof(bool), kBool_Type, 1);
 }
 
+void SkMetaData::setData(const char name[], const void* data, size_t byteCount) {
+    (void)this->set(name, data, sizeof(char), kData_Type, byteCount);
+}
+
 void* SkMetaData::set(const char name[], const void* data, size_t dataSize, Type type, int count)
 {
     SkASSERT(name);
@@ -129,6 +133,9 @@
     case kBool_Type:
         rec->fData.fBool = *(const bool*)rec->data();
         break;
+    case kData_Type:
+        rec->fData.fPtr = rec->data();
+        break;
     default:
         SkASSERT(!"bad type");
         break;
@@ -213,6 +220,18 @@
     return false;
 }
 
+const void* SkMetaData::findData(const char name[], size_t* length) const {
+    const Rec* rec = this->find(name, kData_Type);
+    if (rec) {
+        SkASSERT(rec->fDataLen == sizeof(char));
+        if (length) {
+            *length = rec->fDataCount;
+        }
+        return rec->data();
+    }
+    return NULL;
+}
+
 const SkMetaData::Rec* SkMetaData::find(const char name[], Type type) const
 {
     const Rec* rec = fRec;
@@ -272,6 +291,10 @@
     return this->remove(name, kBool_Type);
 }
 
+bool SkMetaData::removeData(const char name[]) {
+    return this->remove(name, kData_Type);
+}
+
 ///////////////////////////////////////////////////////////////////////////////////
 
 SkMetaData::Iter::Iter(const SkMetaData& metadata)
diff --git a/src/views/SkTextBox.cpp b/src/views/SkTextBox.cpp
index df7de98..0e31ac6 100644
--- a/src/views/SkTextBox.cpp
+++ b/src/views/SkTextBox.cpp
@@ -16,7 +16,7 @@
 */
 
 #include "SkTextBox.h"
-#include "../src/core/SkGlyphCache.h"
+#include "../core/SkGlyphCache.h"
 #include "SkUtils.h"
 #include "SkAutoKern.h"
 
diff --git a/src/views/SkView.cpp b/src/views/SkView.cpp
index 652eb85..7969d3d 100644
--- a/src/views/SkView.cpp
+++ b/src/views/SkView.cpp
@@ -49,6 +49,10 @@
 	this->setFlags(SkSetClearShift(fFlags, pred, kFocusable_Shift));
 }
 
+void SkView::setClipToBounds(bool pred) {
+    this->setFlags(SkSetClearShift(fFlags, !pred, kNoClip_Shift));
+}
+
 void SkView::setSize(SkScalar width, SkScalar height)
 {
 	width = SkMaxScalar(0, width);
@@ -87,12 +91,16 @@
 	{
 		SkRect	r;
 		r.set(fLoc.fX, fLoc.fY, fLoc.fX + fWidth, fLoc.fY + fHeight);
-		if (canvas->quickReject(r, SkCanvas::kBW_EdgeType))
-			return;
+		if (this->isClipToBounds() &&
+            canvas->quickReject(r, SkCanvas::kBW_EdgeType)) {
+                return;
+        }
 
 		SkAutoCanvasRestore	as(canvas, true);
 
-		canvas->clipRect(r);
+        if (this->isClipToBounds()) {
+            canvas->clipRect(r);
+        }
 		canvas->translate(fLoc.fX, fLoc.fY);
 
         if (fParent) {
@@ -119,37 +127,36 @@
 	}
 }
 
-void SkView::inval(SkRect* rect)
-{
-	if (!this->isVisible())
-		return;
-
-	SkRect	bounds;
-
-	this->getLocalBounds(&bounds);
-	if (rect && !bounds.intersect(*rect))
-		return;
-
-	rect = &bounds;
+void SkView::inval(SkRect* rect) {
 	SkView*	view = this;
+    SkRect storage;
 
-	for (;;)
-	{
-		if (view->handleInval(bounds))
-			break;
+	for (;;) {
+        if (!view->isVisible()) {
+            return;
+        }
+        if (view->isClipToBounds()) {
+            SkRect bounds;
+            view->getLocalBounds(&bounds);
+            if (rect && !bounds.intersect(*rect)) {
+                return;
+            }
+            storage = bounds;
+            rect = &storage;
+        }
+        if (view->handleInval(rect)) {
+            return;
+        }
 
-		SkRect	parentR;
 		SkView* parent = view->fParent;
+        if (parent == NULL) {
+            return;
+        }
 
-		if (parent == NULL || !parent->isVisible())
-			break;
-
-		bounds.offset(view->fLoc.fX, view->fLoc.fY);
-		parent->getLocalBounds(&parentR);
-		if (!bounds.intersect(parentR))
-			return;
-
-		view = parent;
+        if (rect) {
+            rect->offset(view->fLoc.fX, view->fLoc.fY);
+        }
+        view = parent;
 	}
 }
 
@@ -456,7 +463,7 @@
 	return false;
 }
 
-bool SkView::handleInval(const SkRect& r) {
+bool SkView::handleInval(const SkRect*) {
 	return false;
 }
 
diff --git a/src/views/SkWindow.cpp b/src/views/SkWindow.cpp
index b63b81a..dbc1eea 100644
--- a/src/views/SkWindow.cpp
+++ b/src/views/SkWindow.cpp
@@ -1,5 +1,6 @@
 #include "SkWindow.h"
 #include "SkCanvas.h"
+#include "SkDevice.h"
 #include "SkOSMenu.h"
 #include "SkSystemEventTypes.h"
 #include "SkTime.h"
@@ -48,6 +49,8 @@
 #else
 	fConfig = SkBitmap::kARGB_8888_Config;
 #endif
+
+    fMatrix.reset();
 }
 
 SkWindow::~SkWindow()
@@ -57,6 +60,25 @@
 	fMenus.deleteAll();
 }
 
+void SkWindow::setMatrix(const SkMatrix& matrix) {
+    if (fMatrix != matrix) {
+        fMatrix = matrix;
+        this->inval(NULL);
+    }
+}
+
+void SkWindow::preConcat(const SkMatrix& matrix) {
+    SkMatrix m;
+    m.setConcat(fMatrix, matrix);
+    this->setMatrix(m);
+}
+
+void SkWindow::postConcat(const SkMatrix& matrix) {
+    SkMatrix m;
+    m.setConcat(matrix, fMatrix);
+    this->setMatrix(m);
+}
+
 void SkWindow::setConfig(SkBitmap::Config config)
 {
 	this->resize(fBitmap.width(), fBitmap.height(), config);
@@ -72,6 +94,7 @@
 		fConfig = config;
 		fBitmap.setConfig(config, width, height);
 		fBitmap.allocPixels();
+        fBitmap.setIsOpaque(true);
 
 		this->setSize(SkIntToScalar(width), SkIntToScalar(height));
 		this->inval(NULL);
@@ -88,25 +111,31 @@
 	fBitmap.eraseRGB(r, g, b);
 }
 
-bool SkWindow::handleInval(const SkRect& r)
+bool SkWindow::handleInval(const SkRect* localR)
 {
 	SkIRect	ir;
 
-	r.round(&ir);
+    if (localR) {
+        SkRect devR;
+        SkMatrix inverse;
+        if (!fMatrix.invert(&inverse)) {
+            return false;
+        }
+        fMatrix.mapRect(&devR, *localR);
+        devR.round(&ir);
+    } else {
+        ir.set(0, 0, this->width(), this->height());
+    }
 	fDirtyRgn.op(ir, SkRegion::kUnion_Op);
 
-#ifdef SK_BUILD_FOR_WIN32xxxx
-	if (!fWaitingOnInval)
-	{
-		fWaitingOnInval = true;
-		(new SkEvent(SK_EventDelayInval))->post(this->getSinkID(), 10);
-	}
-#else
 	this->onHandleInval(ir);
-#endif
 	return true;
 }
 
+void SkWindow::forceInvalAll() {
+    fDirtyRgn.setRect(0, 0, this->width(), this->height());
+}
+
 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
 	#include <windows.h>
 	#include <gx.h>
@@ -117,7 +146,7 @@
 extern bool gEnableControlledThrow;
 #endif
 
-bool SkWindow::update(SkIRect* updateArea)
+bool SkWindow::update(SkIRect* updateArea, SkCanvas* canvas)
 {
 	if (!fDirtyRgn.isEmpty())
 	{
@@ -134,37 +163,49 @@
 		bm.setPixels(buffer);
 #endif
 
-		SkCanvas	canvas(bm);
+		SkCanvas	rasterCanvas;
+        SkDevice*   device;
 
-		canvas.clipRegion(fDirtyRgn);
+        if (NULL == canvas) {
+            canvas = &rasterCanvas;
+            device = new SkDevice(canvas, bm, false);
+            canvas->setDevice(device)->unref();
+        } else {
+            canvas->setBitmapDevice(bm);
+        }
+
+		canvas->clipRegion(fDirtyRgn);
 		if (updateArea)
 			*updateArea = fDirtyRgn.getBounds();
 
+        SkAutoCanvasRestore acr(canvas, true);
+        canvas->concat(fMatrix);
+
 		// empty this now, so we can correctly record any inval calls that
 		// might be made during the draw call.
 		fDirtyRgn.setEmpty();
 
 #ifdef TEST_BOUNDER
 		test_bounder	b(bm);
-		canvas.setBounder(&b);
+		canvas->setBounder(&b);
 #endif
 #ifdef SK_SIMULATE_FAILED_MALLOC
 		gEnableControlledThrow = true;
 #endif
 #ifdef SK_BUILD_FOR_WIN32
-		try {
-			this->draw(&canvas);
-		}
-		catch (...) {
-		}
+		//try {
+			this->draw(canvas);
+		//}
+		//catch (...) {
+		//}
 #else
-		this->draw(&canvas);
+		this->draw(canvas);
 #endif
 #ifdef SK_SIMULATE_FAILED_MALLOC
 		gEnableControlledThrow = false;
 #endif
 #ifdef TEST_BOUNDER
-		canvas.setBounder(NULL);
+		canvas->setBounder(NULL);
 #endif
 
 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
diff --git a/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj b/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj
index 72b7187..f830b66 100644
--- a/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj
+++ b/xcode/sampleapp/SampleApp.xcodeproj/project.pbxproj
@@ -25,19 +25,11 @@
 		0001FB78110E33CC00C1D647 /* SampleTestGL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00A729630FD93ED600D5051F /* SampleTestGL.cpp */; };
 		0001FB87110E35E500C1D647 /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0001FB86110E35E500C1D647 /* AGL.framework */; };
 		0001FB8A110E35FA00C1D647 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0001FB89110E35FA00C1D647 /* OpenGL.framework */; };
-		0001FB94110E362F00C1D647 /* SkGL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0001FB8D110E362F00C1D647 /* SkGL.cpp */; };
-		0001FB96110E362F00C1D647 /* SkGLDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0001FB8F110E362F00C1D647 /* SkGLDevice.cpp */; };
-		0001FB97110E362F00C1D647 /* SkGLDevice_FBO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0001FB90110E362F00C1D647 /* SkGLDevice_FBO.cpp */; };
-		0001FB98110E362F00C1D647 /* SkGLState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0001FB91110E362F00C1D647 /* SkGLState.cpp */; };
-		0001FB99110E362F00C1D647 /* SkGLTextCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0001FB92110E362F00C1D647 /* SkGLTextCache.cpp */; };
-		0001FB9A110E362F00C1D647 /* SkTextureCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0001FB93110E362F00C1D647 /* SkTextureCache.cpp */; };
 		001B871E1042184D00C84ED4 /* Forth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 001B871D1042184D00C84ED4 /* Forth.cpp */; };
 		0021F3A21120B29C0062682F /* SkStaticTextView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0021F3A11120B29C0062682F /* SkStaticTextView.cpp */; };
 		0021F3D31120B61F0062682F /* SampleUnitMapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00995E1510A079D80054AD6D /* SampleUnitMapper.cpp */; };
 		00244D1B10642BBA00B8F4D8 /* SampleStrokePath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0009E21F1057E96800B0DE6F /* SampleStrokePath.cpp */; };
 		00244D97106A539500B8F4D8 /* SampleXfermodes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 007A7CB20F01658C00A2D6EE /* SampleXfermodes.cpp */; };
-		00244DBB106A61B700B8F4D8 /* SampleGM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00244DBA106A61B700B8F4D8 /* SampleGM.cpp */; };
-		00244DCD106A630100B8F4D8 /* bitmapfilters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00244DC7106A630100B8F4D8 /* bitmapfilters.cpp */; };
 		00244DE2106A681600B8F4D8 /* SampleShaders.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 007A7CA80F01658C00A2D6EE /* SampleShaders.cpp */; };
 		00281C751083CF7E00BCCB06 /* libAnimator.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00281C711083CF6600BCCB06 /* libAnimator.a */; };
 		00281D071084ED1200BCCB06 /* SkXMLParser_expat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00281D061084ED1200BCCB06 /* SkXMLParser_expat.cpp */; };
@@ -102,6 +94,13 @@
 		275E802311AAC3330051C03A /* SampleVertices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 007A7CB10F01658C00A2D6EE /* SampleVertices.cpp */; };
 		2762F66D0FCCCABE002BD8B4 /* SkFlipPixelRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2762F66B0FCCCABE002BD8B4 /* SkFlipPixelRef.cpp */; };
 		2762F66E0FCCCABE002BD8B4 /* SkPageFlipper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2762F66C0FCCCABE002BD8B4 /* SkPageFlipper.cpp */; };
+		27C4624B12BFB2C700DBB1F6 /* bitmapfilters.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27C4624512BFB2C700DBB1F6 /* bitmapfilters.cpp */; };
+		27C4624C12BFB2C700DBB1F6 /* filltypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27C4624612BFB2C700DBB1F6 /* filltypes.cpp */; };
+		27C4624D12BFB2C700DBB1F6 /* gradients.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27C4624712BFB2C700DBB1F6 /* gradients.cpp */; };
+		27C4624E12BFB2C700DBB1F6 /* shapes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27C4624812BFB2C700DBB1F6 /* shapes.cpp */; };
+		27C4624F12BFB2C700DBB1F6 /* tilemodes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27C4624912BFB2C700DBB1F6 /* tilemodes.cpp */; };
+		27C4625012BFB2C700DBB1F6 /* xfermodes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27C4624A12BFB2C700DBB1F6 /* xfermodes.cpp */; };
+		27C4625512BFB2F300DBB1F6 /* SampleGM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27C4625412BFB2F300DBB1F6 /* SampleGM.cpp */; };
 		27CAAB65119B303E0017B155 /* SkSVGCircle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27CAAB30119B303E0017B155 /* SkSVGCircle.cpp */; };
 		27CAAB66119B303E0017B155 /* SkSVGClipPath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27CAAB32119B303E0017B155 /* SkSVGClipPath.cpp */; };
 		27CAAB67119B303E0017B155 /* SkSVGDefs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27CAAB34119B303E0017B155 /* SkSVGDefs.cpp */; };
@@ -131,6 +130,16 @@
 		27CAAB7F119B303E0017B155 /* SkSVGUse.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27CAAB62119B303E0017B155 /* SkSVGUse.cpp */; };
 		27CAAB96119B321A0017B155 /* SkXMLWriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27CAAB95119B321A0017B155 /* SkXMLWriter.cpp */; };
 		27D0F3C311BD2012001B8EBE /* SampleText.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 000630AC10F4E8EF00BC2C23 /* SampleText.cpp */; };
+		27E79E3512BC13C700BC0E57 /* SkPDFCatalog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27E79E2B12BC13C700BC0E57 /* SkPDFCatalog.cpp */; };
+		27E79E3612BC13C700BC0E57 /* SkPDFDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27E79E2C12BC13C700BC0E57 /* SkPDFDevice.cpp */; };
+		27E79E3712BC13C700BC0E57 /* SkPDFDocument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27E79E2D12BC13C700BC0E57 /* SkPDFDocument.cpp */; };
+		27E79E3812BC13C700BC0E57 /* SkPDFFont.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27E79E2E12BC13C700BC0E57 /* SkPDFFont.cpp */; };
+		27E79E3912BC13C700BC0E57 /* SkPDFFormXObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27E79E2F12BC13C700BC0E57 /* SkPDFFormXObject.cpp */; };
+		27E79E3A12BC13C700BC0E57 /* SkPDFGraphicState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27E79E3012BC13C700BC0E57 /* SkPDFGraphicState.cpp */; };
+		27E79E3B12BC13C700BC0E57 /* SkPDFImage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27E79E3112BC13C700BC0E57 /* SkPDFImage.cpp */; };
+		27E79E3C12BC13C700BC0E57 /* SkPDFPage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27E79E3212BC13C700BC0E57 /* SkPDFPage.cpp */; };
+		27E79E3D12BC13C700BC0E57 /* SkPDFStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27E79E3312BC13C700BC0E57 /* SkPDFStream.cpp */; };
+		27E79E3E12BC13C700BC0E57 /* SkPDFTypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27E79E3412BC13C700BC0E57 /* SkPDFTypes.cpp */; };
 		27EC817811982E1300481B56 /* SampleTextAlpha.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 007A7CAC0F01658C00A2D6EE /* SampleTextAlpha.cpp */; };
 		8D0C4E8D0486CD37000505A6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */; };
 		8D0C4E8E0486CD37000505A6 /* main.nib in Resources */ = {isa = PBXBuildFile; fileRef = 02345980000FD03B11CA0E72 /* main.nib */; };
@@ -216,23 +225,10 @@
 		00003CA30EFC235F000FF73A /* SkXMLParser_empty.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkXMLParser_empty.cpp; path = ../../src/ports/SkXMLParser_empty.cpp; sourceTree = SOURCE_ROOT; };
 		0001FB86110E35E500C1D647 /* AGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AGL.framework; path = /System/Library/Frameworks/AGL.framework; sourceTree = "<absolute>"; };
 		0001FB89110E35FA00C1D647 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; sourceTree = "<absolute>"; };
-		0001FB8D110E362F00C1D647 /* SkGL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkGL.cpp; path = ../../src/gl/SkGL.cpp; sourceTree = SOURCE_ROOT; };
-		0001FB8F110E362F00C1D647 /* SkGLDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkGLDevice.cpp; path = ../../src/gl/SkGLDevice.cpp; sourceTree = SOURCE_ROOT; };
-		0001FB90110E362F00C1D647 /* SkGLDevice_FBO.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkGLDevice_FBO.cpp; path = ../../src/gl/SkGLDevice_FBO.cpp; sourceTree = SOURCE_ROOT; };
-		0001FB91110E362F00C1D647 /* SkGLState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkGLState.cpp; path = ../../src/gl/SkGLState.cpp; sourceTree = SOURCE_ROOT; };
-		0001FB92110E362F00C1D647 /* SkGLTextCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkGLTextCache.cpp; path = ../../src/gl/SkGLTextCache.cpp; sourceTree = SOURCE_ROOT; };
-		0001FB93110E362F00C1D647 /* SkTextureCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkTextureCache.cpp; path = ../../src/gl/SkTextureCache.cpp; sourceTree = SOURCE_ROOT; };
 		000630AC10F4E8EF00BC2C23 /* SampleText.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleText.cpp; path = ../../samplecode/SampleText.cpp; sourceTree = SOURCE_ROOT; };
 		0009E21F1057E96800B0DE6F /* SampleStrokePath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleStrokePath.cpp; path = ../../samplecode/SampleStrokePath.cpp; sourceTree = SOURCE_ROOT; };
 		001B871D1042184D00C84ED4 /* Forth.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Forth.cpp; path = ../../forth/Forth.cpp; sourceTree = SOURCE_ROOT; };
 		0021F3A11120B29C0062682F /* SkStaticTextView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkStaticTextView.cpp; path = ../../src/views/SkStaticTextView.cpp; sourceTree = SOURCE_ROOT; };
-		00244DBA106A61B700B8F4D8 /* SampleGM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleGM.cpp; path = ../../samplecode/SampleGM.cpp; sourceTree = SOURCE_ROOT; };
-		00244DC7106A630100B8F4D8 /* bitmapfilters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bitmapfilters.cpp; path = ../../gm/bitmapfilters.cpp; sourceTree = SOURCE_ROOT; };
-		00244DC8106A630100B8F4D8 /* filltypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = filltypes.cpp; path = ../../gm/filltypes.cpp; sourceTree = SOURCE_ROOT; };
-		00244DC9106A630100B8F4D8 /* gradients.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = gradients.cpp; path = ../../gm/gradients.cpp; sourceTree = SOURCE_ROOT; };
-		00244DCA106A630100B8F4D8 /* shapes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = shapes.cpp; path = ../../gm/shapes.cpp; sourceTree = SOURCE_ROOT; };
-		00244DCB106A630100B8F4D8 /* tilemodes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tilemodes.cpp; path = ../../gm/tilemodes.cpp; sourceTree = SOURCE_ROOT; };
-		00244DCC106A630100B8F4D8 /* xfermodes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = xfermodes.cpp; path = ../../gm/xfermodes.cpp; sourceTree = SOURCE_ROOT; };
 		00281C661083CF5100BCCB06 /* SkTextBox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkTextBox.cpp; path = ../../src/views/SkTextBox.cpp; sourceTree = SOURCE_ROOT; };
 		00281C691083CF6600BCCB06 /* Animator.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Animator.xcodeproj; path = ../Animator/Animator.xcodeproj; sourceTree = SOURCE_ROOT; };
 		00281C771083CFA100BCCB06 /* SampleAnimator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleAnimator.cpp; path = ../../samplecode/SampleAnimator.cpp; sourceTree = SOURCE_ROOT; };
@@ -313,6 +309,13 @@
 		2762F6790FCCCB01002BD8B4 /* SampleTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleTests.cpp; path = ../../samplecode/SampleTests.cpp; sourceTree = SOURCE_ROOT; };
 		2794C04E0FE72903009AD112 /* SampleMipMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleMipMap.cpp; path = ../../samplecode/SampleMipMap.cpp; sourceTree = SOURCE_ROOT; };
 		27A34E8B119892DD00860515 /* SampleTextBox.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleTextBox.cpp; path = ../../samplecode/SampleTextBox.cpp; sourceTree = SOURCE_ROOT; };
+		27C4624512BFB2C700DBB1F6 /* bitmapfilters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bitmapfilters.cpp; path = ../../gm/bitmapfilters.cpp; sourceTree = SOURCE_ROOT; };
+		27C4624612BFB2C700DBB1F6 /* filltypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = filltypes.cpp; path = ../../gm/filltypes.cpp; sourceTree = SOURCE_ROOT; };
+		27C4624712BFB2C700DBB1F6 /* gradients.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = gradients.cpp; path = ../../gm/gradients.cpp; sourceTree = SOURCE_ROOT; };
+		27C4624812BFB2C700DBB1F6 /* shapes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = shapes.cpp; path = ../../gm/shapes.cpp; sourceTree = SOURCE_ROOT; };
+		27C4624912BFB2C700DBB1F6 /* tilemodes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tilemodes.cpp; path = ../../gm/tilemodes.cpp; sourceTree = SOURCE_ROOT; };
+		27C4624A12BFB2C700DBB1F6 /* xfermodes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = xfermodes.cpp; path = ../../gm/xfermodes.cpp; sourceTree = SOURCE_ROOT; };
+		27C4625412BFB2F300DBB1F6 /* SampleGM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleGM.cpp; path = ../../samplecode/SampleGM.cpp; sourceTree = SOURCE_ROOT; };
 		27CAAB2F119B303E0017B155 /* SkSVG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkSVG.cpp; path = ../../src/svg/SkSVG.cpp; sourceTree = SOURCE_ROOT; };
 		27CAAB30119B303E0017B155 /* SkSVGCircle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkSVGCircle.cpp; path = ../../src/svg/SkSVGCircle.cpp; sourceTree = SOURCE_ROOT; };
 		27CAAB31119B303E0017B155 /* SkSVGCircle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SkSVGCircle.h; path = ../../src/svg/SkSVGCircle.h; sourceTree = SOURCE_ROOT; };
@@ -368,7 +371,16 @@
 		27CAAB63119B303E0017B155 /* SkSVGUse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SkSVGUse.h; path = ../../src/svg/SkSVGUse.h; sourceTree = SOURCE_ROOT; };
 		27CAAB95119B321A0017B155 /* SkXMLWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkXMLWriter.cpp; path = ../../src/xml/SkXMLWriter.cpp; sourceTree = SOURCE_ROOT; };
 		27CAAB9B119B32670017B155 /* SampleSVG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleSVG.cpp; path = ../../samplecode/SampleSVG.cpp; sourceTree = SOURCE_ROOT; };
-		27CAB350119C9C4C0017B155 /* colorfont.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; name = colorfont.xml; path = /colorfont.xml; sourceTree = "<absolute>"; };
+		27E79E2B12BC13C700BC0E57 /* SkPDFCatalog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkPDFCatalog.cpp; path = ../../src/pdf/SkPDFCatalog.cpp; sourceTree = SOURCE_ROOT; };
+		27E79E2C12BC13C700BC0E57 /* SkPDFDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkPDFDevice.cpp; path = ../../src/pdf/SkPDFDevice.cpp; sourceTree = SOURCE_ROOT; };
+		27E79E2D12BC13C700BC0E57 /* SkPDFDocument.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkPDFDocument.cpp; path = ../../src/pdf/SkPDFDocument.cpp; sourceTree = SOURCE_ROOT; };
+		27E79E2E12BC13C700BC0E57 /* SkPDFFont.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkPDFFont.cpp; path = ../../src/pdf/SkPDFFont.cpp; sourceTree = SOURCE_ROOT; };
+		27E79E2F12BC13C700BC0E57 /* SkPDFFormXObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkPDFFormXObject.cpp; path = ../../src/pdf/SkPDFFormXObject.cpp; sourceTree = SOURCE_ROOT; };
+		27E79E3012BC13C700BC0E57 /* SkPDFGraphicState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkPDFGraphicState.cpp; path = ../../src/pdf/SkPDFGraphicState.cpp; sourceTree = SOURCE_ROOT; };
+		27E79E3112BC13C700BC0E57 /* SkPDFImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkPDFImage.cpp; path = ../../src/pdf/SkPDFImage.cpp; sourceTree = SOURCE_ROOT; };
+		27E79E3212BC13C700BC0E57 /* SkPDFPage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkPDFPage.cpp; path = ../../src/pdf/SkPDFPage.cpp; sourceTree = SOURCE_ROOT; };
+		27E79E3312BC13C700BC0E57 /* SkPDFStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkPDFStream.cpp; path = ../../src/pdf/SkPDFStream.cpp; sourceTree = SOURCE_ROOT; };
+		27E79E3412BC13C700BC0E57 /* SkPDFTypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkPDFTypes.cpp; path = ../../src/pdf/SkPDFTypes.cpp; sourceTree = SOURCE_ROOT; };
 		32DBCF6D0370B57F00C91783 /* CICarbonSample_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CICarbonSample_Prefix.pch; sourceTree = "<group>"; };
 		4A9504C8FFE6A3BC11CA0CBA /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = "<absolute>"; };
 		4A9504CAFFE6A41611CA0CBA /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = /System/Library/Frameworks/CoreServices.framework; sourceTree = "<absolute>"; };
@@ -399,11 +411,11 @@
 		00003C610EFC2287000FF73A /* samples */ = {
 			isa = PBXGroup;
 			children = (
+				27C4625412BFB2F300DBB1F6 /* SampleGM.cpp */,
 				003EE651111239D5001AB759 /* SampleWarp.cpp */,
 				27A34E8B119892DD00860515 /* SampleTextBox.cpp */,
 				000630AC10F4E8EF00BC2C23 /* SampleText.cpp */,
 				00281C771083CFA100BCCB06 /* SampleAnimator.cpp */,
-				27CAB350119C9C4C0017B155 /* colorfont.xml */,
 				27CAAB9B119B32670017B155 /* SampleSVG.cpp */,
 				0086CBF010A8661F00C8BF27 /* SampleAvoid.cpp */,
 				00A729630FD93ED600D5051F /* SampleTestGL.cpp */,
@@ -416,7 +428,6 @@
 				007A7CA40F01658C00A2D6EE /* SamplePicture.cpp */,
 				00D6B5CB0F72DC4300C466B9 /* SampleFuzz.cpp */,
 				00C55DA00F8552DC000CAC09 /* SampleGradients.cpp */,
-				00244DBA106A61B700B8F4D8 /* SampleGM.cpp */,
 				009490310FB0A5B90063C792 /* SampleLayerMask.cpp */,
 				003145310FB9B48F00B10956 /* SampleShapes.cpp */,
 				009CC9180F65918A002185BE /* SampleFontScalerTest.cpp */,
@@ -499,32 +510,6 @@
 			name = Products;
 			sourceTree = "<group>";
 		};
-		0001FB8C110E360A00C1D647 /* opengl */ = {
-			isa = PBXGroup;
-			children = (
-				0001FB8D110E362F00C1D647 /* SkGL.cpp */,
-				0001FB8F110E362F00C1D647 /* SkGLDevice.cpp */,
-				0001FB90110E362F00C1D647 /* SkGLDevice_FBO.cpp */,
-				0001FB91110E362F00C1D647 /* SkGLState.cpp */,
-				0001FB92110E362F00C1D647 /* SkGLTextCache.cpp */,
-				0001FB93110E362F00C1D647 /* SkTextureCache.cpp */,
-			);
-			name = opengl;
-			sourceTree = "<group>";
-		};
-		00244DC5106A62E600B8F4D8 /* gm */ = {
-			isa = PBXGroup;
-			children = (
-				00244DC7106A630100B8F4D8 /* bitmapfilters.cpp */,
-				00244DC8106A630100B8F4D8 /* filltypes.cpp */,
-				00244DC9106A630100B8F4D8 /* gradients.cpp */,
-				00244DCA106A630100B8F4D8 /* shapes.cpp */,
-				00244DCB106A630100B8F4D8 /* tilemodes.cpp */,
-				00244DCC106A630100B8F4D8 /* xfermodes.cpp */,
-			);
-			name = gm;
-			sourceTree = "<group>";
-		};
 		00281C6A1083CF6600BCCB06 /* Products */ = {
 			isa = PBXGroup;
 			children = (
@@ -568,9 +553,9 @@
 		20286C29FDCF999611CA2CEA /* CICarbonSample */ = {
 			isa = PBXGroup;
 			children = (
+				27C4624412BFB2AA00DBB1F6 /* GM */,
+				27E79E2A12BC13AD00BC0E57 /* PDF */,
 				27CAAB2E119B30240017B155 /* SVG */,
-				0001FB8C110E360A00C1D647 /* opengl */,
-				00244DC5106A62E600B8F4D8 /* gm */,
 				001B871D1042184D00C84ED4 /* Forth.cpp */,
 				00ED55F2104A10EB00F51FF8 /* StdWords.cpp */,
 				00EB4592104DBB18002B413E /* ForthTests.cpp */,
@@ -639,6 +624,19 @@
 			name = images;
 			sourceTree = "<group>";
 		};
+		27C4624412BFB2AA00DBB1F6 /* GM */ = {
+			isa = PBXGroup;
+			children = (
+				27C4624512BFB2C700DBB1F6 /* bitmapfilters.cpp */,
+				27C4624612BFB2C700DBB1F6 /* filltypes.cpp */,
+				27C4624712BFB2C700DBB1F6 /* gradients.cpp */,
+				27C4624812BFB2C700DBB1F6 /* shapes.cpp */,
+				27C4624912BFB2C700DBB1F6 /* tilemodes.cpp */,
+				27C4624A12BFB2C700DBB1F6 /* xfermodes.cpp */,
+			);
+			name = GM;
+			sourceTree = "<group>";
+		};
 		27CAAB2E119B30240017B155 /* SVG */ = {
 			isa = PBXGroup;
 			children = (
@@ -700,6 +698,23 @@
 			name = SVG;
 			sourceTree = "<group>";
 		};
+		27E79E2A12BC13AD00BC0E57 /* PDF */ = {
+			isa = PBXGroup;
+			children = (
+				27E79E2B12BC13C700BC0E57 /* SkPDFCatalog.cpp */,
+				27E79E2C12BC13C700BC0E57 /* SkPDFDevice.cpp */,
+				27E79E2D12BC13C700BC0E57 /* SkPDFDocument.cpp */,
+				27E79E2E12BC13C700BC0E57 /* SkPDFFont.cpp */,
+				27E79E2F12BC13C700BC0E57 /* SkPDFFormXObject.cpp */,
+				27E79E3012BC13C700BC0E57 /* SkPDFGraphicState.cpp */,
+				27E79E3112BC13C700BC0E57 /* SkPDFImage.cpp */,
+				27E79E3212BC13C700BC0E57 /* SkPDFPage.cpp */,
+				27E79E3312BC13C700BC0E57 /* SkPDFStream.cpp */,
+				27E79E3412BC13C700BC0E57 /* SkPDFTypes.cpp */,
+			);
+			name = PDF;
+			sourceTree = "<group>";
+		};
 /* End PBXGroup section */
 
 /* Begin PBXNativeTarget section */
@@ -732,7 +747,14 @@
 			isa = PBXProject;
 			buildConfigurationList = 01E2163D09EDAC6600E66AF8 /* Build configuration list for PBXProject "SampleApp" */;
 			compatibilityVersion = "Xcode 2.4";
+			developmentRegion = English;
 			hasScannedForEncodings = 1;
+			knownRegions = (
+				English,
+				Japanese,
+				French,
+				German,
+			);
 			mainGroup = 20286C29FDCF999611CA2CEA /* CICarbonSample */;
 			projectDirPath = "";
 			projectReferences = (
@@ -865,8 +887,6 @@
 				009887F1106142FC0020D19B /* SampleNinePatch.cpp in Sources */,
 				00244D1B10642BBA00B8F4D8 /* SampleStrokePath.cpp in Sources */,
 				00244D97106A539500B8F4D8 /* SampleXfermodes.cpp in Sources */,
-				00244DBB106A61B700B8F4D8 /* SampleGM.cpp in Sources */,
-				00244DCD106A630100B8F4D8 /* bitmapfilters.cpp in Sources */,
 				00244DE2106A681600B8F4D8 /* SampleShaders.cpp in Sources */,
 				00281D071084ED1200BCCB06 /* SkXMLParser_expat.cpp in Sources */,
 				009230D8109F111F00AD3F12 /* OverView.cpp in Sources */,
@@ -883,12 +903,6 @@
 				0061BCC910D696730079EBE5 /* SampleTiling.cpp in Sources */,
 				0061BCD910D951AA0079EBE5 /* SkTextBox.cpp in Sources */,
 				0001FB78110E33CC00C1D647 /* SampleTestGL.cpp in Sources */,
-				0001FB94110E362F00C1D647 /* SkGL.cpp in Sources */,
-				0001FB96110E362F00C1D647 /* SkGLDevice.cpp in Sources */,
-				0001FB97110E362F00C1D647 /* SkGLDevice_FBO.cpp in Sources */,
-				0001FB98110E362F00C1D647 /* SkGLState.cpp in Sources */,
-				0001FB99110E362F00C1D647 /* SkGLTextCache.cpp in Sources */,
-				0001FB9A110E362F00C1D647 /* SkTextureCache.cpp in Sources */,
 				0021F3A21120B29C0062682F /* SkStaticTextView.cpp in Sources */,
 				0021F3D31120B61F0062682F /* SampleUnitMapper.cpp in Sources */,
 				27EC817811982E1300481B56 /* SampleTextAlpha.cpp in Sources */,
@@ -925,6 +939,23 @@
 				275E801611AAC2FF0051C03A /* SampleShapes.cpp in Sources */,
 				275E802311AAC3330051C03A /* SampleVertices.cpp in Sources */,
 				27D0F3C311BD2012001B8EBE /* SampleText.cpp in Sources */,
+				27E79E3512BC13C700BC0E57 /* SkPDFCatalog.cpp in Sources */,
+				27E79E3612BC13C700BC0E57 /* SkPDFDevice.cpp in Sources */,
+				27E79E3712BC13C700BC0E57 /* SkPDFDocument.cpp in Sources */,
+				27E79E3812BC13C700BC0E57 /* SkPDFFont.cpp in Sources */,
+				27E79E3912BC13C700BC0E57 /* SkPDFFormXObject.cpp in Sources */,
+				27E79E3A12BC13C700BC0E57 /* SkPDFGraphicState.cpp in Sources */,
+				27E79E3B12BC13C700BC0E57 /* SkPDFImage.cpp in Sources */,
+				27E79E3C12BC13C700BC0E57 /* SkPDFPage.cpp in Sources */,
+				27E79E3D12BC13C700BC0E57 /* SkPDFStream.cpp in Sources */,
+				27E79E3E12BC13C700BC0E57 /* SkPDFTypes.cpp in Sources */,
+				27C4624B12BFB2C700DBB1F6 /* bitmapfilters.cpp in Sources */,
+				27C4624C12BFB2C700DBB1F6 /* filltypes.cpp in Sources */,
+				27C4624D12BFB2C700DBB1F6 /* gradients.cpp in Sources */,
+				27C4624E12BFB2C700DBB1F6 /* shapes.cpp in Sources */,
+				27C4624F12BFB2C700DBB1F6 /* tilemodes.cpp in Sources */,
+				27C4625012BFB2C700DBB1F6 /* xfermodes.cpp in Sources */,
+				27C4625512BFB2F300DBB1F6 /* SampleGM.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};