Adds ability to draw rects using a unit square vertex buffer. Useful when matrix/uniform changes are less expensive than sending new verts. 

Adds optional matrix parameters to GrContext drawRect and drawRectToRect so that non-axis-aligned matrices can be drawn using these functions.

codereview Issue 4105049

git-svn-id: http://skia.googlecode.com/svn/trunk@749 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrConfig.h b/gpu/include/GrConfig.h
index 7169e2e..b599a53 100644
--- a/gpu/include/GrConfig.h
+++ b/gpu/include/GrConfig.h
@@ -234,6 +234,12 @@
 #define GrAlwaysAssert(COND) GR_ALWAYSASSERT(COND)
 
 /**
+ * Crash from unrecoverable condition, optionally with a message.
+ */
+inline void GrCrash() { GrAlwaysAssert(false); }
+inline void GrCrash(const char* msg) { GrPrintf(msg); GrAlwaysAssert(false); }
+
+/**
  *  GR_DEBUGCODE compiles the code X in debug builds only 
  */
 #if !defined(GR_DEBUGCODE)
diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h
index db53b1a..ccc045e 100644
--- a/gpu/include/GrContext.h
+++ b/gpu/include/GrContext.h
@@ -233,21 +233,40 @@
 

     /**

      *  Draw the rect using a paint.

-     *  If strokeWidth < 0, then the rect is filled, else the rect is mitered

-     *  stroked based on strokeWidth. If strokeWidth == 0, then the stroke is

-     *  always a single pixel thick.

+     *  @param paint        describes how to color pixels.

+     *  @param strokeWidth  If strokeWidth < 0, then the rect is filled, else

+     *                      the rect is mitered stroked based on strokeWidth. If

+     *                      strokeWidth == 0, then the stroke is always a single 

+     *                      pixel thick.

+     *  @param matrix       Optional matrix applied to the rect. Applied before 

+     *                      context's matrix or the paint's matrix.

      *  The rects coords are used to access the paint (through texture matrix)

      */

-    void drawRect(const GrPaint& paint, const GrRect&, GrScalar strokeWidth = -1);

+    void drawRect(const GrPaint& paint, 

+                  const GrRect&, 

+                  GrScalar strokeWidth = -1,

+                  const GrMatrix* matrix = NULL);

 

     /**

      * Maps a rect of paint coordinates onto the a rect of destination

-     * coordinates. The srcRect is transformed by the paint's matrix and the

-     * dstRect is transformed by the context's matrix.

+     * coordinates. Each rect can optionally be transformed. The srcRect

+     * is stretched over the dstRect. The dstRect is transformed by the 

+     * context's matrix and the srcRect is transformed by the paint's matrix.

+     * Additional optional matrices can be provided by parameters.

+     *

+     * @param paint     describes how to color pixels.

+     * @param dstRect   the destination rect to draw.

+     * @param srcRect   rect of paint coordinates to be mapped onto dstRect

+     * @param dstMatrix Optional matrix to transform dstRect. Applied before

+     *                  context's matrix.

+     * @param srcMatrix Optional matrix to transform srcRect Applied before

+     *                  paint's matrix.

      */

     void drawRectToRect(const GrPaint& paint,

                         const GrRect& dstRect,

-                        const GrRect& srcRect);

+                        const GrRect& srcRect,

+                        const GrMatrix* dstMatrix = NULL,

+                        const GrMatrix* srcMatrix = NULL);

 

     /**

      * Path filling rules

diff --git a/gpu/include/GrDrawTarget.h b/gpu/include/GrDrawTarget.h
index 862559e..e7f37f1 100644
--- a/gpu/include/GrDrawTarget.h
+++ b/gpu/include/GrDrawTarget.h
@@ -238,7 +238,7 @@
      * requirements. The texture matrix is applied both when the texture
      * coordinates are explicit and when vertex positions are used as texture
      * coordinates. In the latter case the texture matrix is applied to the
-     * pre-modelview position values.
+     * pre-view-matrix position values.
      *
      * @param stage the stage for which to set a matrix.
      * @param m     the matrix used to transform the texture coordinates.
@@ -246,6 +246,25 @@
     void setTextureMatrix(int stage, const GrMatrix& m);
 
     /**
+     *  Multiplies the current texture matrix for a stage by a matrix
+     *
+     *  After this call T' = T*m where T is the old tex matrix,
+     *  m is the parameter to this function, and T' is the new tex matrix.
+     *  (We consider positions to be column vectors so tex cood vector t is
+     *  transformed by matrix X as t' = X*t.)
+     *
+     *  @param m the matrix used to modify the texture matrix matrix.
+     */
+    void concatTextureMatrix(int stage, const GrMatrix& m);
+
+    /**
+     * Retrieves the current texture matrix for a stage
+     * @param stage     index of stage
+     * @return the stage's current texture matrix.
+     */
+    const GrMatrix& getTextureMatrix(int stage) const;
+
+    /**
      * Sets the matrix applied to veretx positions.
      *
      * In the post-view-matrix space the rectangle [0,w]x[0,h]
@@ -264,11 +283,28 @@
      *  (We consider positions to be column vectors so position vector p is
      *  transformed by matrix X as p' = X*p.)
      *
-     *  @param m the matrix used to modify the modelview matrix.
+     *  @param m the matrix used to modify the view matrix.
      */
     void concatViewMatrix(const GrMatrix& m);
 
     /**
+     * Retrieves the current view matrix
+     * @return the current view matrix.
+     */
+    const GrMatrix& getViewMatrix() const;
+
+    /**
+     *  Retrieves the inverse of the current view matrix.
+     *
+     *  If the current view matrix is invertible, return true, and if matrix
+     *  is non-null, copy the inverse into it. If the current view matrix is
+     *  non-invertible, return false and ignore the matrix parameter.
+     *
+     * @param matrix if not null, will receive a copy of the current inverse.
+     */
+    bool getViewInverse(GrMatrix* matrix) const;
+
+    /**
      *  Sets color for next draw to a premultiplied-alpha color.
      *
      *  @param the color to set.
@@ -332,23 +368,6 @@
     void setBlendFunc(BlendCoeff srcCoef, BlendCoeff dstCoef);
 
     /**
-     * Retrieves the current view matrix
-     * return the current view matrix.
-     */
-    const GrMatrix& getViewMatrix() const;
-
-    /**
-     *  Retrieves the inverse of the current view matrix.
-     *
-     *  If the current view matrix is invertible, return true, and if matrix
-     *  is non-null, copy the inverse into it. If the current view matrix is
-     *  non-invertible, return false and ignore the matrix parameter.
-     *
-     * @param matrix if not null, will receive a copy of the current inverse.
-     */
-    bool getViewInverse(GrMatrix* matrix) const;
-
-    /**
      * Used to save and restore the GrGpu's drawing state
      */
     struct SavedDrawState {
@@ -612,6 +631,39 @@
     };
 
     ///////////////////////////////////////////////////////////////////////////
+    
+    class AutoViewMatrixRestore : ::GrNoncopyable {
+    public:
+        AutoViewMatrixRestore() {
+            fDrawTarget = NULL;
+        }
+
+        AutoViewMatrixRestore(GrDrawTarget* target) 
+            : fDrawTarget(target), fMatrix(fDrawTarget->getViewMatrix()) {
+            GrAssert(NULL != target);
+        }
+
+        void set(GrDrawTarget* target) {
+            GrAssert(NULL != target);
+            if (NULL != fDrawTarget) {
+                fDrawTarget->setViewMatrix(fMatrix);
+            }
+            fDrawTarget = target;
+            fMatrix = target->getViewMatrix();
+        }
+
+        ~AutoViewMatrixRestore() {
+            if (NULL != fDrawTarget) {
+                fDrawTarget->setViewMatrix(fMatrix);
+            }
+        }
+
+    private:
+        GrDrawTarget*       fDrawTarget;
+        GrMatrix            fMatrix;
+    };
+
+    ///////////////////////////////////////////////////////////////////////////
 
     class AutoReleaseGeometry : ::GrNoncopyable {
     public:
diff --git a/gpu/include/GrGpu.h b/gpu/include/GrGpu.h
index 62f68ca..5a9281e 100644
--- a/gpu/include/GrGpu.h
+++ b/gpu/include/GrGpu.h
@@ -321,6 +321,11 @@
     int maxQuadsInIndexBuffer() const;
 
     /**
+     * Returns a vertex buffer with four position-only vertices [(0,0), (1,0), (1,1), (0,1)]
+     */
+    const GrVertexBuffer* unitSquareVertexBuffer() const;
+
+    /**
      * Ensures that the current render target is actually set in the
      * underlying 3D API. Used when client wants to use 3D API to directly
      * render to the RT.
@@ -426,6 +431,9 @@
     mutable GrIndexBuffer* fQuadIndexBuffer; // mutable so it can be
                                              // created on-demand
 
+    mutable GrVertexBuffer* fUnitSquareVertexBuffer; // mutable so it can be
+                                                     // created on-demand
+
     static const int MAX_VERTEX_SIZE = GR_CT_MAX(2*sizeof(GrPoint) + sizeof(GrColor),
                                                  2*sizeof(GrGpuTextVertex));
     static const int VERTEX_STORAGE = 16 * MAX_VERTEX_SIZE;
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 9b94b7a..bcccc4e 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -24,6 +24,7 @@
 #include "GrIndexBuffer.h"

 

 #define DEFER_TEXT_RENDERING 1

+#define USE_STATIC_RECT_VB   0

 

 static const size_t MAX_TEXTURE_CACHE_COUNT = 128;

 static const size_t MAX_TEXTURE_CACHE_BYTES = 8 * 1024 * 1024;

@@ -332,25 +333,31 @@
 

 void GrContext::drawRect(const GrPaint& paint,

                          const GrRect& rect,

-                         GrScalar width) {

+                         GrScalar width,

+                         const GrMatrix* matrix) {

 

-    GrVertexLayout layout = (NULL != paint.getTexture()) ?

+    bool textured = NULL != paint.getTexture();

+    GrVertexLayout layout = (textured) ?

                             GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :

                             0;

 

-    static const int worstCaseVertCount = 10;

-    GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, worstCaseVertCount, 0);

-    if (!geo.succeeded()) {

-        return;

-    }

-

     this->prepareToDraw(paint);

 

-    int vertCount;

-    GrDrawTarget::PrimitiveType primType;

-    GrPoint* vertex = geo.positions();

-

     if (width >= 0) {

+        // TODO: consider making static vertex buffers for these cases.

+        // Hairline could be done by just adding closing vertex to 

+        // unitSquareVertexBuffer()

+        static const int worstCaseVertCount = 10;

+        GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, worstCaseVertCount, 0);

+

+        if (!geo.succeeded()) {

+            return;

+        }

+

+        GrDrawTarget::PrimitiveType primType;

+        int vertCount;

+        GrPoint* vertex = geo.positions();

+

         if (width > 0) {

             vertCount = 10;

             primType = GrDrawTarget::kTriangleStrip_PrimitiveType;

@@ -365,44 +372,111 @@
             vertex[3].set(rect.fLeft, rect.fBottom);

             vertex[4].set(rect.fLeft, rect.fTop);

         }

-    } else {

-        vertCount = 4;

-        primType = GrDrawTarget::kTriangleFan_PrimitiveType;

-        vertex->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);

-    }

 

-    fGpu->drawNonIndexed(primType, 0, vertCount);

+        GrDrawTarget::AutoViewMatrixRestore avmr;

+        if (NULL != matrix) {

+            avmr.set(fGpu);

+            fGpu->concatViewMatrix(*matrix);

+            fGpu->concatTextureMatrix(0, *matrix);

+        }

+

+        fGpu->drawNonIndexed(primType, 0, vertCount);

+    } else {

+        #if USE_STATIC_RECT_VB

+            fGpu->setVertexSourceToBuffer(fGpu->unitSquareVertexBuffer(), layout);

+            GrDrawTarget::AutoViewMatrixRestore avmr(fGpu);

+            GrMatrix m;

+            m.setAll(rect.width(), 0,             rect.fLeft,

+                     0,            rect.height(), rect.fTop,

+                     0,            0,             GrMatrix::I()[8]);

+            

+            if (NULL != matrix) {

+                m.postConcat(*matrix);

+            }

+

+            fGpu->concatViewMatrix(m);

+        

+            if (textured) {

+                fGpu->concatTextureMatrix(0, m);

+            }

+        #else

+            GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, 4, 0);

+            GrPoint* vertex = geo.positions();

+            vertex->setRectFan(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);

+

+            GrDrawTarget::AutoViewMatrixRestore avmr;

+            if (NULL != matrix) {

+                avmr.set(fGpu);

+                fGpu->concatViewMatrix(*matrix);

+                fGpu->concatTextureMatrix(0, *matrix);

+            }

+        #endif

+

+        fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, 4);

+    }

 }

 

 void GrContext::drawRectToRect(const GrPaint& paint,

                                const GrRect& dstRect,

-                               const GrRect& srcRect) {

+                               const GrRect& srcRect,

+                               const GrMatrix* dstMatrix,

+                               const GrMatrix* srcMatrix) {

 

     if (NULL == paint.getTexture()) {

-        drawRect(paint, dstRect);

-        return;

-    }

-

-    GrVertexLayout layout = GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);

-    static const int VCOUNT = 4;

-

-    GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, VCOUNT, 0);

-    if (!geo.succeeded()) {

+        drawRect(paint, dstRect, -1, dstMatrix);

         return;

     }

 

     this->prepareToDraw(paint);

 

-    GrPoint* vertex = (GrPoint*) geo.vertices();

+#if USE_STATIC_RECT_VB

+    GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);

+    GrDrawTarget::AutoViewMatrixRestore avmr(fGpu);

 

-    vertex[0].setRectFan(dstRect.fLeft, dstRect.fTop,

-                         dstRect.fRight, dstRect.fBottom,

-                         2 * sizeof(GrPoint));

-    vertex[1].setRectFan(srcRect.fLeft, srcRect.fTop,

-                         srcRect.fRight, srcRect.fBottom,

-                         2 * sizeof(GrPoint));

+    GrMatrix m;

 

-    fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, VCOUNT);

+    m.setAll(dstRect.width(), 0,                dstRect.fLeft,

+             0,               dstRect.height(), dstRect.fTop,

+             0,               0,                GrMatrix::I()[8]);

+    if (NULL != dstMatrix) {

+        m.postConcat(*dstMatrix);

+    }

+    fGpu->concatViewMatrix(m);

+

+    m.setAll(srcRect.width(), 0,                srcRect.fLeft,

+             0,               srcRect.height(), srcRect.fTop,

+             0,               0,                GrMatrix::I()[8]);

+    if (NULL != srcMatrix) {

+        m.postConcat(*srcMatrix);

+    }

+    fGpu->concatTextureMatrix(0, m);

+

+    fGpu->setVertexSourceToBuffer(fGpu->unitSquareVertexBuffer(), layout);

+#else

+    GrVertexLayout layout = GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);

+

+    GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, 4, 0);

+    GrPoint* pos = geo.positions();

+    GrPoint* tex = pos + 1;

+    static const size_t stride = 2 * sizeof(GrPoint);

+    pos[0].setRectFan(dstRect.fLeft, dstRect.fTop, 

+                      dstRect.fRight, dstRect.fBottom,

+                      stride);

+    tex[0].setRectFan(srcRect.fLeft, srcRect.fTop, 

+                      srcRect.fRight, srcRect.fBottom,

+                      stride);

+

+    GrDrawTarget::AutoViewMatrixRestore avmr;

+    if (NULL != dstMatrix) {

+        avmr.set(fGpu);

+        fGpu->concatViewMatrix(*dstMatrix);

+    }

+    if (NULL != srcMatrix) {

+        fGpu->concatTextureMatrix(0, *srcMatrix);

+    }

+

+#endif

+    fGpu->drawNonIndexed(GrDrawTarget::kTriangleFan_PrimitiveType, 0, 4);

 }

 

 void GrContext::drawVertices(const GrPaint& paint,

diff --git a/gpu/src/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp
index 0101ecd..96afe2f 100644
--- a/gpu/src/GrDrawTarget.cpp
+++ b/gpu/src/GrDrawTarget.cpp
@@ -358,6 +358,16 @@
     fCurrDrawState.fTextureMatrices[stage] = m;
 }
 
+void GrDrawTarget::concatTextureMatrix(int stage, const GrMatrix& m) {
+    GrAssert(stage >= 0 && stage < kNumStages);
+    fCurrDrawState.fTextureMatrices[stage].preConcat(m);
+}
+
+const GrMatrix& GrDrawTarget::getTextureMatrix(int stage) const {
+    GrAssert(stage >= 0 && stage < kNumStages);
+    return fCurrDrawState.fTextureMatrices[stage];
+}
+
 void GrDrawTarget::setStencilPass(StencilPass pass) {
     fCurrDrawState.fStencilPass = pass;
 }
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index d8bbcd2..3624747 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -21,6 +21,7 @@
 #include "GrTextureCache.h"
 #include "GrClipIterator.h"
 #include "GrIndexBuffer.h"
+#include "GrVertexBuffer.h"
 
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -57,7 +58,8 @@
 
 GrGpu::GrGpu() : f8bitPaletteSupport(false),
                  fNPOTTextureSupport(kNone_NPOTTextureType),
-                 fQuadIndexBuffer(NULL) {
+                 fQuadIndexBuffer(NULL),
+                 fUnitSquareVertexBuffer(NULL) {
 #if GR_DEBUG
 //    gr_run_unittests();
 #endif
@@ -65,9 +67,8 @@
 }
 
 GrGpu::~GrGpu() {
-    if (NULL != fQuadIndexBuffer) {
-        fQuadIndexBuffer->unref();
-    }
+    GrSafeUnref(fQuadIndexBuffer);
+    GrSafeUnref(fUnitSquareVertexBuffer);
 }
 
 void GrGpu::resetContext() {
@@ -155,7 +156,7 @@
                 if (!fQuadIndexBuffer->updateData(indices, SIZE)) {
                     fQuadIndexBuffer->unref();
                     fQuadIndexBuffer = NULL;
-                    GrAssert(!"Can't get indices into buffer!");
+                    GrCrash("Can't get indices into buffer!");
                 }
                 GrFree(indices);
             }
@@ -165,6 +166,31 @@
     return fQuadIndexBuffer;
 }
 
+const GrVertexBuffer* GrGpu::unitSquareVertexBuffer() const {
+    if (NULL == fUnitSquareVertexBuffer) {
+
+        static const GrPoint DATA[] = {
+            GrPoint(0,         0),
+            GrPoint(GR_Scalar1,0),
+            GrPoint(GR_Scalar1,GR_Scalar1),
+            GrPoint(0,         GR_Scalar1)
+        };
+        static const size_t SIZE = sizeof(DATA);
+
+        GrGpu* me = const_cast<GrGpu*>(this);
+        fUnitSquareVertexBuffer = me->createVertexBuffer(SIZE, false);
+        if (NULL != fUnitSquareVertexBuffer) {
+            if (!fUnitSquareVertexBuffer->updateData(DATA, SIZE)) {
+                fUnitSquareVertexBuffer->unref();
+                fUnitSquareVertexBuffer = NULL;
+                GrCrash("Can't get vertices into buffer!");
+            }
+        }
+    }
+
+    return fUnitSquareVertexBuffer;
+}
+
 int GrGpu::maxQuadsInIndexBuffer() const {
     return (NULL == this->quadIndexBuffer()) ? 0 : MAX_QUADS;
 }
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index dca146e..3afd46c 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -512,7 +512,10 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+#if 0 // not currently being used so don't compile,
+
 // can be used for positions or texture coordinates
+
 class SkRectFanSource {
 public:
     SkRectFanSource(const SkRect& rect) : fRect(rect) {}
@@ -575,6 +578,8 @@
     const SkMatrix& fMatrix;
 };
 
+#endif
+
 ///////////////////////////////////////////////////////////////////////////////
 
 void SkGpuDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) {
@@ -821,23 +826,16 @@
 
     grPaint->setTexture(texture);
     grPaint->fTextureMatrix.setIdentity();
+    GrRect dstRect(0, 0, GrIntToScalar(srcRect.width()), GrIntToScalar(srcRect.height()));
+    GrRect paintRect(GrIntToScalar(srcRect.fLeft)   / texture->allocWidth(),
+                     GrIntToScalar(srcRect.fTop)    / texture->allocHeight(),
+                     GrIntToScalar(srcRect.fRight)  / texture->allocWidth(),
+                     GrIntToScalar(srcRect.fBottom) / texture->allocHeight());
 
-    SkRect paintRect;
-    paintRect.set(SkFixedToScalar((srcRect.fLeft << 16)  / texture->allocWidth()),
-                  SkFixedToScalar((srcRect.fTop << 16)   / texture->allocHeight()),
-                  SkFixedToScalar((srcRect.fRight << 16) / texture->allocWidth()),
-                  SkFixedToScalar((srcRect.fBottom << 16)/ texture->allocHeight()));
+    GrMatrix grMat;
+    SkGr::SkMatrix2GrMatrix(m, &grMat);
 
-    SkRect dstRect;
-    dstRect.set(SkIntToScalar(0),SkIntToScalar(0),
-                SkIntToScalar(srcRect.width()), SkIntToScalar(srcRect.height()));
-
-    SkRectFanSource texSrc(paintRect);
-    fContext->drawCustomVertices(*grPaint,
-                                 GrDrawTarget::kTriangleFan_PrimitiveType,
-                                 SkMatRectFanSource(dstRect, m),
-                                 &texSrc);
-
+    fContext->drawRectToRect(*grPaint, dstRect, paintRect, &grMat);
 }
 
 void SkGpuDevice::drawSprite(const SkDraw& draw, const SkBitmap& bitmap,
diff --git a/vs/SampleApp/SampleApp.vcxproj b/vs/SampleApp/SampleApp.vcxproj
index bca142a..5acf7da 100644
--- a/vs/SampleApp/SampleApp.vcxproj
+++ b/vs/SampleApp/SampleApp.vcxproj
@@ -55,7 +55,7 @@
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>

       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>

       <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>..\..\include\core;..\..\include\xml;..\..\include\utils;..\..\include\config;..\..\include\views;..\..\src\core;..\..\include\images;..\..\include\effects;..\..\include\gpu;..\..\gpu\include</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>..\..\include\core;..\..\include\xml;..\..\include\utils;..\..\include\config;..\..\include\views;..\..\src\core;..\..\include\images;..\..\include\effects;..\..\include\gpu;..\..\include\pdf;..\..\gpu\include</AdditionalIncludeDirectories>

     </ClCompile>

     <Link>

       <SubSystem>Windows</SubSystem>

@@ -73,7 +73,7 @@
       <FunctionLevelLinking>true</FunctionLevelLinking>

       <IntrinsicFunctions>true</IntrinsicFunctions>

       <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>..\..\include\core;..\..\include\xml;..\..\include\utils;..\..\include\config;..\..\include\views;..\..\src\core;..\..\include\images;..\..\include\effects;..\..\include\gpu;..\..\gpu\include</AdditionalIncludeDirectories>

+      <AdditionalIncludeDirectories>..\..\include\core;..\..\include\xml;..\..\include\utils;..\..\include\config;..\..\include\views;..\..\src\core;..\..\include\images;..\..\include\effects;..\..\include\gpu;..\..\include\pdf;..\..\gpu\include</AdditionalIncludeDirectories>

       <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>

     </ClCompile>

     <Link>

@@ -245,7 +245,6 @@
     <ClCompile Include="..\..\samplecode\SampleCamera.cpp" />

     <ClCompile Include="..\..\samplecode\SampleCircle.cpp" />

     <ClCompile Include="..\..\samplecode\SampleCull.cpp" />

-    <ClCompile Include="..\..\samplecode\SampleDecode.cpp" />

     <ClCompile Include="..\..\samplecode\SampleDither.cpp" />

     <ClCompile Include="..\..\samplecode\SampleDitherBitmap.cpp" />

     <ClCompile Include="..\..\samplecode\SampleDrawLooper.cpp" />

@@ -330,6 +329,7 @@
     <ClCompile Include="..\..\src\core\SkEdgeBuilder.cpp" />

     <ClCompile Include="..\..\src\core\SkEdgeClipper.cpp" />

     <ClCompile Include="..\..\src\core\SkFilterProc.cpp" />

+    <ClCompile Include="..\..\src\core\SkFlate.cpp" />

     <ClCompile Include="..\..\src\core\SkFlattenable.cpp" />

     <ClCompile Include="..\..\src\core\SkFloat.cpp" />

     <ClCompile Include="..\..\src\core\SkFloatBits.cpp" />

@@ -363,6 +363,7 @@
     <ClCompile Include="..\..\src\core\SkRasterizer.cpp" />

     <ClCompile Include="..\..\src\core\SkRect.cpp" />

     <ClCompile Include="..\..\src\core\SkRefCnt.cpp" />

+    <ClCompile Include="..\..\src\core\SkRefDict.cpp" />

     <ClCompile Include="..\..\src\core\SkRegion.cpp" />

     <ClCompile Include="..\..\src\core\SkRegion_path.cpp" />

     <ClCompile Include="..\..\src\core\SkScalar.cpp" />

@@ -425,6 +426,16 @@
     <ClCompile Include="..\..\src\opts\SkBitmapProcState_opts_SSE2.cpp" />

     <ClCompile Include="..\..\src\opts\SkBlitRow_opts_SSE2.cpp" />

     <ClCompile Include="..\..\src\opts\SkUtils_opts_SSE2.cpp" />

+    <ClCompile Include="..\..\src\pdf\SkPDFCatalog.cpp" />

+    <ClCompile Include="..\..\src\pdf\SkPDFDevice.cpp" />

+    <ClCompile Include="..\..\src\pdf\SkPDFDocument.cpp" />

+    <ClCompile Include="..\..\src\pdf\SkPDFFont.cpp" />

+    <ClCompile Include="..\..\src\pdf\SkPDFFormXObject.cpp" />

+    <ClCompile Include="..\..\src\pdf\SkPDFGraphicState.cpp" />

+    <ClCompile Include="..\..\src\pdf\SkPDFImage.cpp" />

+    <ClCompile Include="..\..\src\pdf\SkPDFPage.cpp" />

+    <ClCompile Include="..\..\src\pdf\SkPDFStream.cpp" />

+    <ClCompile Include="..\..\src\pdf\SkPDFTypes.cpp" />

     <ClCompile Include="..\..\src\ports\SkDebug_stdio.cpp" />

     <ClCompile Include="..\..\src\ports\SkFontHost_win.cpp" />

     <ClCompile Include="..\..\src\ports\SkGlobals_global.cpp" />