Skia Merge (revision 950)

This merge will allow us to now import the sample app
infrastructure in skia to do on device measurements.

Change-Id: Idcab6b1524f371521717cde61a6e98a12d897e6b
diff --git a/Android.mk b/Android.mk
index 26989b2..86210bc 100644
--- a/Android.mk
+++ b/Android.mk
@@ -262,6 +262,7 @@
   gpu/src/GrContext.cpp \
   gpu/src/GrDrawTarget.cpp \
   gpu/src/GrGLIndexBuffer.cpp	\
+  gpu/src/GrGLInterface.cpp \
   gpu/src/GrGLTexture.cpp \
   gpu/src/GrGLVertexBuffer.cpp \
   gpu/src/GrGpu.cpp \
diff --git a/gpu/include/GrAtlas.h b/gpu/include/GrAtlas.h
index 9526e0b..a933842 100644
--- a/gpu/include/GrAtlas.h
+++ b/gpu/include/GrAtlas.h
@@ -28,10 +28,11 @@
 
 class GrAtlas {
 public:
-    GrAtlas(GrAtlasMgr*, int plotX, int plotY);
+    GrAtlas(GrAtlasMgr*, int plotX, int plotY, GrMaskFormat);
 
     int getPlotX() const { return fPlot.fX; }
     int getPlotY() const { return fPlot.fY; }
+    GrMaskFormat getMaskFormat() const { return fMaskFormat; }
 
     GrTexture* texture() const { return fTexture; }
 
@@ -56,6 +57,7 @@
     GrRectanizer*   fRects;
     GrAtlasMgr*     fAtlasMgr;
     GrIPoint16      fPlot;
+    GrMaskFormat    fMaskFormat;
 
     friend class GrAtlasMgr;
 };
@@ -68,9 +70,12 @@
     ~GrAtlasMgr();
 
     GrAtlas* addToAtlas(GrAtlas*, int width, int height, const void*,
-                        GrIPoint16*);
+                        GrMaskFormat, GrIPoint16*);
 
-    GrTexture* getTexture() const { return fTexture; }
+    GrTexture* getTexture(GrMaskFormat format) const {
+        GrAssert((unsigned)format < kCount_GrMaskFormats);
+        return fTexture[format];
+    }
 
     // to be called by ~GrAtlas()
     void freePlot(int x, int y);
@@ -79,7 +84,7 @@
 
 private:
     GrGpu*      fGpu;
-    GrTexture*  fTexture;
+    GrTexture*  fTexture[kCount_GrMaskFormats];
     GrPlotMgr*  fPlotMgr;
 };
 
diff --git a/gpu/include/GrDrawTarget.h b/gpu/include/GrDrawTarget.h
index aef5937..35f912b 100644
--- a/gpu/include/GrDrawTarget.h
+++ b/gpu/include/GrDrawTarget.h
@@ -136,6 +136,7 @@
         uint32_t                fFlagBits;
         GrBlendCoeff            fSrcBlend;
         GrBlendCoeff            fDstBlend;
+        GrColor                 fBlendConstant;
         GrTexture*              fTextures[kNumStages];
         GrSamplerState          fSamplerStates[kNumStages];
         GrRenderTarget*         fRenderTarget;
@@ -359,6 +360,24 @@
     void setBlendFunc(GrBlendCoeff srcCoef, GrBlendCoeff dstCoef);
 
     /**
+     * Sets the blending function constant referenced by the following blending
+     * coeffecients:
+     *      kConstC_BlendCoeff
+     *      kIConstC_BlendCoeff
+     *      kConstA_BlendCoeff
+     *      kIConstA_BlendCoeff
+     *
+     * @param constant the constant to set
+     */
+    void setBlendConstant(GrColor constant) { fCurrDrawState.fBlendConstant = constant; }
+
+    /**
+     * Retrieves the last value set by setBlendConstant()
+     * @return the blending constant value
+     */
+    GrColor getBlendConstant() const { return fCurrDrawState.fBlendConstant; }
+
+    /**
      * Used to save and restore the GrGpu's drawing state
      */
     struct SavedDrawState {
diff --git a/gpu/include/GrFontScaler.h b/gpu/include/GrFontScaler.h
index 6baa56f..77730d7 100644
--- a/gpu/include/GrFontScaler.h
+++ b/gpu/include/GrFontScaler.h
@@ -33,6 +33,7 @@
 class GrFontScaler : public GrRefCnt {
 public:
     virtual const GrKey* getKey() = 0;
+    virtual GrMaskFormat getMaskFormat() = 0;
     virtual bool getPackedGlyphBounds(GrGlyph::PackedID, GrIRect* bounds) = 0;
     virtual bool getPackedGlyphImage(GrGlyph::PackedID, int width, int height,
                                      int rowBytes, void* image) = 0;
diff --git a/gpu/include/GrGLConfig.h b/gpu/include/GrGLConfig.h
index c467f99..0a86e72 100644
--- a/gpu/include/GrGLConfig.h
+++ b/gpu/include/GrGLConfig.h
@@ -1,5 +1,5 @@
 /*
-    Copyright 2010 Google Inc.
+    Copyright 2011 Google Inc.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -19,58 +19,9 @@
 #define GrGLConfig_DEFINED
 
 #include "GrTypes.h"
+#include "GrGLInterface.h"
 
-#if !defined(GR_GL_CUSTOM_SETUP)
-    #define GR_GL_CUSTOM_SETUP 0
-#endif
 /**
- * We need to pull in the right GL headers and determine whether we are
- * compiling for ES1, ES2, or desktop GL. (We allow ES1 and ES2 to both be
- * supported in the same build but not ESx and desktop). We also need to know
- * the platform-specific way to get extension function pointers (e.g.
- * eglGetProcAddress). The port specifies this info explicitly or we will infer
- * it from the GR_*_BUILD flag.
- *
- * To specify GL setup directly define GR_GL_CUSTOM_SETUP to 1 and define:
- *      GR_SUPPORT_GLDESKTOP or (GR_SUPPORT_GLES1 and/or GR_SUPPORT_GLES2) to 1
- *
- *      if GR_SUPPORT_GLDESKTOP is 1 then provide:
- *          1. The name of your GL header in GR_INCLUDE_GLDESKTOP
- *          2. If necessary, the name of a file that includes extension
- *             definitions in GR_INCLUDE_GLDESKTOPext.
- *      if GR_SUPPORT_GLES1 is 1 then provide:
- *          1. The name of your GL header in GR_INCLUDE_GLES1
- *          2. If necessary, the name of a file that includes extension
- *             definitions in GR_INCLUDE_GLES1ext.
- *      if GR_SUPPORT_GLES2 is 1 then provide:
- *          1. The name of your GL header in GR_INCLUDE_GLES2
- *          2. If necessary, the name of a file that includes extension
- *             definitions in GR_INCLUDE_GLES2ext.
- *
- *      Optionally, define GR_GL_FUNC to any qualifier needed on GL function
- *      pointer declarations (e.g. __stdcall).
- *
- *      Define GR_GL_PROC_ADDRESS to take a gl function and produce a
- *      function pointer. Two examples:
- *          1. Your platform doesn't require a proc address function, just take
- *             the address of the function:
- *             #define GR_GL_PROC_ADDRESS(X) &X
- *          2. Your platform uses eglGetProcAddress:
- *             #define GR_GL_PROC_ADDRESS eglGetProcAddress(#X)
- *
- *     Optionally define GR_GL_PROC_ADDRESS_HEADER to include any additional
- *     header necessary to use GR_GL_PROC_ADDRESS (e.g. <EGL/egl.h>)
- *
- * Alternatively, define GR_GL_CUSTOM_SETUP_HEADER (and not GR_GL_CUSTOM_SETUP)
- * to a header that can be included. This file should:
- *      1. Define the approprate GR_SUPPORT_GL* macro(s) to 1
- *      2. Includes all necessary GL headers.
- *      3. Optionally define GR_GL_FUNC.
- *      4. Define GR_GL_PROC_ADDRESS.
- *      5. Optionally define GR_GL_PROC_ADDRESS_HEADER
- *
- *------------------------------------------------------------------------------
- *
  * The following are optional defines that can be enabled at the compiler
  * command line, in a IDE project, in a GrUserConfig.h file, or in a GL custom
  * file (if one is in use). They don't require GR_GL_CUSTOM_SETUP or
@@ -93,122 +44,6 @@
  * when GR_GL_CHECK_ERROR is 1.  Defaults to 1.
  */
 
-#if GR_GL_CUSTOM_SETUP
-
-    #ifdef GR_SUPPORT_GLES1
-        #include GR_INCLUDE_GLES1
-        #if defined(GR_INCLUDE_GLES1ext)
-            #include GR_INCLUDE_GLES1ext
-        #endif
-    #endif
-
-    #ifdef GR_SUPPORT_GLES2
-        #include GR_INCLUDE_GLES2
-        #if defined(GR_INCLUDE_GLES2ext)
-            #include GR_INCLUDE_GLES2ext
-        #endif
-    #endif
-
-    #ifdef GR_SUPPORT_GLDESKTOP
-        #include GR_INCLUDE_GLDESKTOP
-        #if defined(GR_INCLUDE_GLDESKTOPext)
-            #include GR_INCLUDE_GLDESKTOPext
-        #endif
-    #endif
-
-#elif defined(GR_GL_CUSTOM_SETUP_HEADER)
-
-    #include GR_GL_CUSTOM_SETUP_HEADER
-
-#else
-    #undef GR_GL_FUNC
-    #undef GR_GL_PROC_ADDRESS
-    #undef GR_GL_PROC_ADDRESS_HEADER
-
-    #if GR_WIN32_BUILD
-        #define GR_SUPPORT_GLDESKTOP        1
-        // glew has to be included before gl
-        #include <GL/glew.h>
-        #include <GL/gl.h>
-        // remove stupid windows defines
-        #undef near
-        #undef far
-        #define GR_GL_FUNC __stdcall
-        #define GR_GL_PROC_ADDRESS(X)       wglGetProcAddress(#X)
-        #define GR_GL_PROC_ADDRESS_HEADER   <windows.h>
-    #elif GR_MAC_BUILD
-        #define GR_SUPPORT_GLDESKTOP        1
-        #include <OpenGL/gl.h>
-        #include <OpenGL/glext.h>
-        #define GR_GL_PROC_ADDRESS(X)       &X
-    #elif GR_IOS_BUILD
-        #define GR_SUPPORT_GLES1            1
-        #include <OpenGLES/ES1/gl.h>
-        #include <OpenGLES/ES1/glext.h>
-        #define GR_SUPPORT_GLES2            1
-        #include <OpenGLES/ES2/gl.h>
-        #include <OpenGLES/ES2/glext.h>
-        #define GR_GL_PROC_ADDRESS(X)       &X
-    #elif GR_ANDROID_BUILD
-        #ifndef GL_GLEXT_PROTOTYPES
-            #define GL_GLEXT_PROTOTYPES
-        #endif
-        #define GR_SUPPORT_GLES2            1
-        #include <GLES2/gl2.h>
-        #include <GLES2/gl2ext.h>
-        #define GR_GL_PROC_ADDRESS(X)       eglGetProcAddress(#X)
-        #define GR_GL_PROC_ADDRESS_HEADER   <EGL/egl.h>
-    #elif GR_QNX_BUILD
-        #ifndef GL_GLEXT_PROTOTYPES
-            #define GL_GLEXT_PROTOTYPES
-        #endif
-         #define GR_SUPPORT_GLES2           1
-        // This is needed by the QNX GLES2 headers
-        #define GL_API_EXT
-        #include <GLES2/gl2.h>
-        #include <GLES2/gl2ext.h>
-        #define GR_GL_PROC_ADDRESS(X)       eglGetProcAddress(#X)
-        #define GR_GL_PROC_ADDRESS_HEADER   <EGL/egl.h>
-    #elif GR_LINUX_BUILD
-        #ifndef GL_GLEXT_PROTOTYPES
-            #define GL_GLEXT_PROTOTYPES
-        #endif
-        #define GL_EXT_framebuffer_blit     0
-        #include <GL/gl.h>
-        #include <GL/glext.h>
-        #define GR_GL_PROC_ADDRESS(X)       &X
-        #define GR_SUPPORT_GLDESKTOP        1
-    #else
-        #error "unsupported GR_???_BUILD"
-    #endif
-
-#endif
-
-#if !defined(GR_SUPPORT_GLDESKTOP)
-    #define GR_SUPPORT_GLDESKTOP    0
-#endif
-#if !defined(GR_SUPPORT_GLES1)
-    #define GR_SUPPORT_GLES1        0
-#endif
-#if !defined(GR_SUPPORT_GLES2)
-    #define GR_SUPPORT_GLES2        0
-#endif
-
-#define GR_SUPPORT_GLES ((GR_SUPPORT_GLES1) || (GR_SUPPORT_GLES2))
-
-#if !GR_SUPPORT_GLES && !GR_SUPPORT_GLDESKTOP
-    #error "Either desktop or ES GL must be supported"
-#elif GR_SUPPORT_GLES && GR_SUPPORT_GLDESKTOP
-    #error "Cannot support both desktop and ES GL"
-#endif
-
-#if !defined(GR_GL_FUNC)
-    #define GR_GL_FUNC
-#endif
-
-#if !defined(GR_GL_PROC_ADDRESS)
-    #error "Must define GR_GL_PROC_ADDRESS"
-#endif
 
 #if !defined(GR_GL_LOG_CALLS)
     #define GR_GL_LOG_CALLS             0
@@ -249,7 +84,7 @@
     #error "unknown GR_TEXT_SCALAR type"
 #endif
 
-// Pick a pixel config for 32bit bitmaps. Our default is GL_RGBA (expect on
+// Pick a pixel config for 32bit bitmaps. Our default is GL_RGBA (except on
 // Windows where we match GDI's order).
 #ifndef GR_GL_32BPP_COLOR_FORMAT
     #if GR_WIN32_BUILD
@@ -259,67 +94,9 @@
     #endif
 #endif
 
-////////////////////////////////////////////////////////////////////////////////
-// Setup for opengl ES/desktop extensions
-// We make a struct of function pointers so that each GL context
-// can have it's own struct. (Some environments may have different proc
-// addresses for different contexts).
 
-extern "C" {
-struct GrGLExts {
-// FBO
-    GLvoid (GR_GL_FUNC *GenFramebuffers)(GLsizei n, GLuint *framebuffers);
-    GLvoid (GR_GL_FUNC *BindFramebuffer)(GLenum target, GLuint framebuffer);
-    GLvoid (GR_GL_FUNC *FramebufferTexture2D)(GLenum target, GLenum attachment,
-                                              GLenum textarget, GLuint texture,
-                                              GLint level);
-    GLenum (GR_GL_FUNC *CheckFramebufferStatus)(GLenum target);
-    GLvoid (GR_GL_FUNC *DeleteFramebuffers)(GLsizei n, const
-                                            GLuint *framebuffers);
-    GLvoid (GR_GL_FUNC *RenderbufferStorage)(GLenum target,
-                                             GLenum internalformat,
-                                             GLsizei width, GLsizei height);
-    GLvoid (GR_GL_FUNC *GenRenderbuffers)(GLsizei n, GLuint *renderbuffers);
-    GLvoid (GR_GL_FUNC *DeleteRenderbuffers)(GLsizei n,
-                                             const GLuint *renderbuffers);
-    GLvoid (GR_GL_FUNC *FramebufferRenderbuffer)(GLenum target,
-                                                 GLenum attachment,
-                                                 GLenum renderbuffertarget,
-                                                 GLuint renderbuffer);
-    GLvoid (GR_GL_FUNC *BindRenderbuffer)(GLenum target, GLuint renderbuffer);
-
-// Multisampling
-    // same prototype for ARB_FBO, EXT_FBO, GL 3.0, & Apple ES extension
-    GLvoid (GR_GL_FUNC *RenderbufferStorageMultisample)(GLenum target,
-                                                        GLsizei samples,
-                                                        GLenum internalformat,
-                                                        GLsizei width,
-                                                        GLsizei height);
-    // desktop: ext_fbo_blit, arb_fbo, gl 3.0
-    GLvoid (GR_GL_FUNC *BlitFramebuffer)(GLint srcX0, GLint srcY0,
-                                         GLint srcX1, GLint srcY1,
-                                         GLint dstX0, GLint dstY0,
-                                         GLint dstX1, GLint dstY1,
-                                         GLbitfield mask, GLenum filter);
-    // apple's es extension
-    GLvoid (GR_GL_FUNC *ResolveMultisampleFramebuffer)();
-
-    // IMG'e es extension
-    GLvoid (GR_GL_FUNC *FramebufferTexture2DMultisample)(GLenum target,
-                                                         GLenum attachment,
-                                                         GLenum textarget,
-                                                         GLuint texture,
-                                                         GLint level,
-                                                         GLsizei samples);
-
-// Buffer mapping (extension in ES).
-    GLvoid* (GR_GL_FUNC *MapBuffer)(GLenum target, GLenum access);
-    GLboolean (GR_GL_FUNC *UnmapBuffer)(GLenum target);
-};
-}
 
 // BGRA format
-
 #define GR_BGRA                     0x80E1
 
 // FBO / stencil formats
@@ -355,14 +132,12 @@
 // Palette texture
 #define GR_PALETTE8_RGBA8           0x8B91
 
-extern void GrGLInitExtensions(GrGLExts* exts);
-
 ////////////////////////////////////////////////////////////////////////////////
 
 extern void GrGLCheckErr(const char* location, const char* call);
 
 static inline void GrGLClearErr() {
-    while (GL_NO_ERROR != glGetError()) {}
+    while (GL_NO_ERROR != GrGLGetGLInterface()->fGetError()) {}
 }
 
 #if GR_GL_CHECK_ERROR
@@ -379,18 +154,8 @@
     #define GR_GL_LOG_CALLS_IMPL(X)
 #endif
 
-#define GR_GL(X)                 gl ## X; GR_GL_LOG_CALLS_IMPL(X); GR_GL_CHECK_ERROR_IMPL(X);
-#define GR_GL_NO_ERR(X)          GrGLClearErr(); gl ## X; GR_GL_LOG_CALLS_IMPL(X); GR_GL_CHECK_ERROR_IMPL(X);
-#define GR_GLEXT(exts, X)        exts. X; GR_GL_LOG_CALLS_IMPL(X); GR_GL_CHECK_ERROR_IMPL(X);
-#define GR_GLEXT_NO_ERR(exts, X) GrGLClearErr(); exts. X; GR_GL_LOG_CALLS_IMPL(X); GR_GL_CHECK_ERROR_IMPL(X);
-
-////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Helpers for glGetString()
- */
-bool has_gl_extension(const char* ext);
-void gl_version(int* major, int* minor);
+#define GR_GL(X)                 GrGLGetGLInterface()->f##X;; GR_GL_LOG_CALLS_IMPL(X); GR_GL_CHECK_ERROR_IMPL(X);
+#define GR_GL_NO_ERR(X)          GrGLGetGLInterface()->f##X;; GR_GL_LOG_CALLS_IMPL(X); GR_GL_CHECK_ERROR_IMPL(X);
 
 ////////////////////////////////////////////////////////////////////////////////
 
diff --git a/gpu/include/GrGLConfig_chrome.h b/gpu/include/GrGLConfig_chrome.h
index 6d5f21c..ff0d7b7 100644
--- a/gpu/include/GrGLConfig_chrome.h
+++ b/gpu/include/GrGLConfig_chrome.h
@@ -21,4 +21,14 @@
 // glGetError() forces a sync with gpu process on chrome
 #define GR_GL_CHECK_ERROR_START     0
 
+// Using the static vb precludes batching rect-to-rect draws
+// because there are matrix changes between each one.
+// Chrome was getting top performance on Windows with
+// batched rect-to-rect draws. But there seems to be some 
+// regression that now causes any dynamic VB data to perform
+// very poorly. In any event the static VB seems to get equal
+// perf to what batching was producing and it always seems to
+// be better on Linux.
+#define GR_STATIC_RECT_VB 1
+
 #endif
diff --git a/gpu/include/GrGLInterface.h b/gpu/include/GrGLInterface.h
new file mode 100644
index 0000000..0a41905
--- /dev/null
+++ b/gpu/include/GrGLInterface.h
@@ -0,0 +1,272 @@
+/*
+    Copyright 2011 Google Inc.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ */
+
+
+#ifndef GrGLInterface_DEFINED
+#define GrGLInterface_DEFINED
+
+#include "GrGLPlatformIncludes.h"
+
+#if !defined(GR_GL_FUNCTION_TYPE)
+    #define GR_GL_FUNCTION_TYPE
+#endif
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Helpers for glGetString()
+ */
+bool has_gl_extension(const char* ext);
+void gl_version(int* major, int* minor);
+
+////////////////////////////////////////////////////////////////////////////////
+
+/*
+ * Routines managing the global interface used to invoke OpenGL calls.
+ */
+struct GrGLInterface;
+extern GrGLInterface* GrGLGetGLInterface();
+extern void GrGLSetGLInterface(GrGLInterface* gl_interface);
+
+/*
+ * Populates the global GrGLInterface pointer with an instance pointing to the
+ * GL implementation linked with the executable.
+ */
+extern void GrGLSetDefaultGLInterface();
+
+extern "C" {
+/*
+ * The following interface exports the OpenGL entry points used by the system.
+ * Use of OpenGL calls is disallowed.  All calls should be invoked through
+ * the global instance of this struct, defined above.
+ *
+ * IMPORTANT NOTE: The OpenGL entry points exposed here include both core GL
+ * functions, and extensions.  The system assumes that the address of the
+ * extension pointer will be valid across contexts.
+ */
+struct GrGLInterface {
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLActiveTextureProc)(GLenum texture);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLAttachShaderProc)(GLuint program, GLuint shader);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBindAttribLocationProc)(GLuint program, GLuint index, const char* name);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBindBufferProc)(GLenum target, GLuint buffer);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBindTextureProc)(GLenum target, GLuint texture);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBlendColorProc)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBlendFuncProc)(GLenum sfactor, GLenum dfactor);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBufferDataProc)(GLenum target, GLsizei size, const void* data, GLenum usage);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBufferSubDataProc)(GLenum target, GLint offset, GLsizei size, const void* data);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLClearProc)(GLbitfield mask);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLClearColorProc)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLClearStencilProc)(GLint s);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLClientActiveTextureProc)(GLenum texture);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLColor4ubProc)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLColorMaskProc)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLColorPointerProc)(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLCompileShaderProc)(GLuint shader);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLCompressedTexImage2DProc)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
+    typedef GLuint (GR_GL_FUNCTION_TYPE *GrGLCreateProgramProc)(void);
+    typedef GLuint (GR_GL_FUNCTION_TYPE *GrGLCreateShaderProc)(GLenum type);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLCullFaceProc)(GLenum mode);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteBuffersProc)(GLsizei n, const GLuint* buffers);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteProgramProc)(GLuint program);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteShaderProc)(GLuint shader);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteTexturesProc)(GLsizei n, const GLuint* textures);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDepthMaskProc)(GLboolean flag);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDisableProc)(GLenum cap);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDisableClientStateProc)(GLenum array);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDisableVertexAttribArrayProc)(GLuint index);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDrawArraysProc)(GLenum mode, GLint first, GLsizei count);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDrawElementsProc)(GLenum mode, GLsizei count, GLenum type, const void* indices);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLEnableProc)(GLenum cap);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLEnableClientStateProc)(GLenum cap);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLEnableVertexAttribArrayProc)(GLuint index);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLFrontFaceProc)(GLenum mode);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGenBuffersProc)(GLsizei n, GLuint* buffers);
+    typedef GLenum (GR_GL_FUNCTION_TYPE *GrGLGetErrorProc)(void);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGenTexturesProc)(GLsizei n, GLuint* textures);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGetBufferParameterivProc)(GLenum target, GLenum pname, GLint* params);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGetIntegervProc)(GLenum pname, GLint* params);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGetProgramInfoLogProc)(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGetProgramivProc)(GLuint program, GLenum pname, GLint* params);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGetShaderInfoLogProc)(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGetShaderivProc)(GLuint shader, GLenum pname, GLint* params);
+    typedef const GLubyte* (GR_GL_FUNCTION_TYPE *GrGLGetStringProc)(GLenum name);
+    typedef GLint (GR_GL_FUNCTION_TYPE *GrGLGetUniformLocationProc)(GLuint program, const char* name);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLLineWidthProc)(GLfloat width);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLLinkProgramProc)(GLuint program);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLLoadMatrixfProc)(const GLfloat* m);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLMatrixModeProc)(GLenum mode);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLPixelStoreiProc)(GLenum pname, GLint param);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLPointSizeProc)(GLfloat size);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLReadPixelsProc)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLScissorProc)(GLint x, GLint y, GLsizei width, GLsizei height);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLShadeModelProc)(GLenum mode);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLShaderSourceProc)(GLuint shader, GLsizei count, const char** str, const GLint* length);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilFuncProc)(GLenum func, GLint ref, GLuint mask);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilFuncSeparateProc)(GLenum face, GLenum func, GLint ref, GLuint mask);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilMaskProc)(GLuint mask);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilMaskSeparateProc)(GLenum face, GLuint mask);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilOpProc)(GLenum fail, GLenum zfail, GLenum zpass);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLStencilOpSeparateProc)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLTexCoordPointerProc)(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLTexEnviProc)(GLenum target, GLenum pname, GLint param);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLTexImage2DProc)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLTexParameteriProc)(GLenum target, GLenum pname, GLint param);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLTexSubImage2DProc)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLUniform1fvProc)(GLint location, GLsizei count, const GLfloat* v);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLUniform1iProc)(GLint location, GLint x);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLUniform4fvProc)(GLint location, GLsizei count, const GLfloat* v);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLUniformMatrix3fvProc)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLUseProgramProc)(GLuint program);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLVertexAttrib4fvProc)(GLuint indx, const GLfloat* values);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLVertexAttribPointerProc)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLVertexPointerProc)(GLint size, GLenum type, GLsizei stride, const GLvoid* pointer);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLViewportProc)(GLint x, GLint y, GLsizei width, GLsizei height);
+
+    // FBO Extension Functions
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBindFramebufferProc)(GLenum target, GLuint framebuffer);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBindRenderbufferProc)(GLenum target, GLuint renderbuffer);
+    typedef GLenum (GR_GL_FUNCTION_TYPE *GrGLCheckFramebufferStatusProc)(GLenum target);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteFramebuffersProc)(GLsizei n, const GLuint *framebuffers);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLDeleteRenderbuffersProc)(GLsizei n, const GLuint *renderbuffers);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLFramebufferRenderbufferProc)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLFramebufferTexture2DProc)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGenFramebuffersProc)(GLsizei n, GLuint *framebuffers);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLGenRenderbuffersProc)(GLsizei n, GLuint *renderbuffers);
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLRenderbufferStorageProc)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+
+    // Multisampling Extension Functions
+    // same prototype for ARB_FBO, EXT_FBO, GL 3.0, & Apple ES extension
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLRenderbufferStorageMultisampleProc)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+    // desktop: ext_fbo_blit, arb_fbo, gl 3.0
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLBlitFramebufferProc)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+    // apple's es extension
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLResolveMultisampleFramebufferProc)();
+
+    // IMG'e es extension
+    typedef GLvoid (GR_GL_FUNCTION_TYPE *GrGLFramebufferTexture2DMultisampleProc)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples);
+
+    // Buffer mapping (extension in ES).
+    typedef GLvoid* (GR_GL_FUNCTION_TYPE *GrGLMapBufferProc)(GLenum target, GLenum access);
+    typedef GLboolean (GR_GL_FUNCTION_TYPE *GrGLUnmapBufferProc)(GLenum target);
+
+    GrGLActiveTextureProc fActiveTexture;
+    GrGLAttachShaderProc fAttachShader;
+    GrGLBindAttribLocationProc fBindAttribLocation;
+    GrGLBindBufferProc fBindBuffer;
+    GrGLBindTextureProc fBindTexture;
+    GrGLBlendFuncProc fBlendFunc;
+    GrGLBlendColorProc fBlendColor;
+    GrGLBufferDataProc fBufferData;
+    GrGLBufferSubDataProc fBufferSubData;
+    GrGLClearProc fClear;
+    GrGLClearColorProc fClearColor;
+    GrGLClearStencilProc fClearStencil;
+    GrGLClientActiveTextureProc fClientActiveTexture;
+    GrGLColor4ubProc fColor4ub;
+    GrGLColorMaskProc fColorMask;
+    GrGLColorPointerProc fColorPointer;
+    GrGLCompileShaderProc fCompileShader;
+    GrGLCompressedTexImage2DProc fCompressedTexImage2D;
+    GrGLCreateProgramProc fCreateProgram;
+    GrGLCreateShaderProc fCreateShader;
+    GrGLCullFaceProc fCullFace;
+    GrGLDeleteBuffersProc fDeleteBuffers;
+    GrGLDeleteProgramProc fDeleteProgram;
+    GrGLDeleteShaderProc fDeleteShader;
+    GrGLDeleteTexturesProc fDeleteTextures;
+    GrGLDepthMaskProc fDepthMask;
+    GrGLDisableProc fDisable;
+    GrGLDisableClientStateProc fDisableClientState;
+    GrGLDisableVertexAttribArrayProc fDisableVertexAttribArray;
+    GrGLDrawArraysProc fDrawArrays;
+    GrGLDrawElementsProc fDrawElements;
+    GrGLEnableProc fEnable;
+    GrGLEnableClientStateProc fEnableClientState;
+    GrGLEnableVertexAttribArrayProc fEnableVertexAttribArray;
+    GrGLFrontFaceProc fFrontFace;
+    GrGLGenBuffersProc fGenBuffers;
+    GrGLGenTexturesProc fGenTextures;
+    GrGLGetBufferParameterivProc fGetBufferParameteriv;
+    GrGLGetErrorProc fGetError;
+    GrGLGetIntegervProc fGetIntegerv;
+    GrGLGetProgramInfoLogProc fGetProgramInfoLog;
+    GrGLGetProgramivProc fGetProgramiv;
+    GrGLGetShaderInfoLogProc fGetShaderInfoLog;
+    GrGLGetShaderivProc fGetShaderiv;
+    GrGLGetStringProc fGetString;
+    GrGLGetUniformLocationProc fGetUniformLocation;
+    GrGLLineWidthProc fLineWidth;
+    GrGLLinkProgramProc fLinkProgram;
+    GrGLLoadMatrixfProc fLoadMatrixf;
+    GrGLMatrixModeProc fMatrixMode;
+    GrGLPixelStoreiProc fPixelStorei;
+    GrGLPointSizeProc fPointSize;
+    GrGLReadPixelsProc fReadPixels;
+    GrGLScissorProc fScissor;
+    GrGLShadeModelProc fShadeModel;
+    GrGLShaderSourceProc fShaderSource;
+    GrGLStencilFuncProc fStencilFunc;
+    GrGLStencilFuncSeparateProc fStencilFuncSeparate;
+    GrGLStencilMaskProc fStencilMask;
+    GrGLStencilMaskSeparateProc fStencilMaskSeparate;
+    GrGLStencilOpProc fStencilOp;
+    GrGLStencilOpSeparateProc fStencilOpSeparate;
+    GrGLTexCoordPointerProc fTexCoordPointer;
+    GrGLTexEnviProc fTexEnvi;
+    GrGLTexImage2DProc fTexImage2D;
+    GrGLTexParameteriProc fTexParameteri;
+    GrGLTexSubImage2DProc fTexSubImage2D;
+    GrGLUniform1fvProc fUniform1fv;
+    GrGLUniform1iProc fUniform1i;
+    GrGLUniform4fvProc fUniform4fv;
+    GrGLUniformMatrix3fvProc fUniformMatrix3fv;
+    GrGLUseProgramProc fUseProgram;
+    GrGLVertexAttrib4fvProc fVertexAttrib4fv;
+    GrGLVertexAttribPointerProc fVertexAttribPointer;
+    GrGLVertexPointerProc fVertexPointer;
+    GrGLViewportProc fViewport;
+
+    // FBO Extension Functions
+    GrGLBindFramebufferProc fBindFramebuffer;
+    GrGLBindRenderbufferProc fBindRenderbuffer;
+    GrGLCheckFramebufferStatusProc fCheckFramebufferStatus;
+    GrGLDeleteFramebuffersProc fDeleteFramebuffers;
+    GrGLDeleteRenderbuffersProc fDeleteRenderbuffers;
+    GrGLFramebufferRenderbufferProc fFramebufferRenderbuffer;
+    GrGLFramebufferTexture2DProc fFramebufferTexture2D;
+    GrGLGenFramebuffersProc fGenFramebuffers;
+    GrGLGenRenderbuffersProc fGenRenderbuffers;
+    GrGLRenderbufferStorageProc fRenderbufferStorage;
+
+    // Multisampling Extension Functions
+    // same prototype for ARB_FBO, EXT_FBO, GL 3.0, & Apple ES extension
+    GrGLRenderbufferStorageMultisampleProc fRenderbufferStorageMultisample;
+    // desktop: ext_fbo_blit, arb_fbo, gl 3.0
+    GrGLBlitFramebufferProc fBlitFramebuffer;
+    // apple's es extension
+    GrGLResolveMultisampleFramebufferProc fResolveMultisampleFramebuffer;
+
+    // IMG'e es extension
+    GrGLFramebufferTexture2DMultisampleProc fFramebufferTexture2DMultisample;
+
+    // Buffer mapping (extension in ES).
+    GrGLMapBufferProc fMapBuffer;
+    GrGLUnmapBufferProc fUnmapBuffer;
+};
+
+}  // extern "C"
+
+#endif
diff --git a/gpu/include/GrGLPlatformIncludes.h b/gpu/include/GrGLPlatformIncludes.h
new file mode 100644
index 0000000..978a992
--- /dev/null
+++ b/gpu/include/GrGLPlatformIncludes.h
@@ -0,0 +1,522 @@
+/*
+    Copyright 2011 Google Inc.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ */
+
+
+#ifndef GrGLPlatformIncludes_DEFINED
+#define GrGLPlatformIncludes_DEFINED
+
+#include "GrConfig.h"
+
+#if !defined(GR_GL_CUSTOM_SETUP)
+    #define GR_GL_CUSTOM_SETUP 0
+#endif
+
+/**
+ * We need to pull in the right GL headers and determine whether we are
+ * compiling for ES1, ES2, or desktop GL. (We allow ES1 and ES2 to both be
+ * supported in the same build but not ESx and desktop). We also need to know
+ * the platform-specific way to get extension function pointers (e.g.
+ * eglGetProcAddress). The port specifies this info explicitly or we will infer
+ * it from the GR_*_BUILD flag.
+ *
+ * To specify GL setup directly define GR_GL_CUSTOM_SETUP to 1 and define:
+ *      GR_SUPPORT_GLDESKTOP or (GR_SUPPORT_GLES1 and/or GR_SUPPORT_GLES2) to 1
+ *
+ *      if GR_SUPPORT_GLDESKTOP is 1 then provide:
+ *          1. The name of your GL header in GR_INCLUDE_GLDESKTOP
+ *          2. If necessary, the name of a file that includes extension
+ *             definitions in GR_INCLUDE_GLDESKTOPext.
+ *      if GR_SUPPORT_GLES1 is 1 then provide:
+ *          1. The name of your GL header in GR_INCLUDE_GLES1
+ *          2. If necessary, the name of a file that includes extension
+ *             definitions in GR_INCLUDE_GLES1ext.
+ *      if GR_SUPPORT_GLES2 is 1 then provide:
+ *          1. The name of your GL header in GR_INCLUDE_GLES2
+ *          2. If necessary, the name of a file that includes extension
+ *             definitions in GR_INCLUDE_GLES2ext.
+ *
+ *      Optionally, define GR_GL_FUNC to any qualifier needed on GL function
+ *      pointer declarations (e.g. __stdcall).
+ *
+ *      Define GR_GL_PROC_ADDRESS to take a gl function and produce a
+ *      function pointer. Two examples:
+ *          1. Your platform doesn't require a proc address function, just take
+ *             the address of the function:
+ *             #define GR_GL_PROC_ADDRESS(X) &X
+ *          2. Your platform uses eglGetProcAddress:
+ *             #define GR_GL_PROC_ADDRESS eglGetProcAddress(#X)
+ *
+ *     Optionally define GR_GL_PROC_ADDRESS_HEADER to include any additional
+ *     header necessary to use GR_GL_PROC_ADDRESS (e.g. <EGL/egl.h>)
+ *
+ * Alternatively, define GR_GL_CUSTOM_SETUP_HEADER (and not GR_GL_CUSTOM_SETUP)
+ * to a header that can be included. This file should:
+ *      1. Define the approprate GR_SUPPORT_GL* macro(s) to 1
+ *      2. Includes all necessary GL headers.
+ *      3. Optionally define GR_GL_FUNC.
+ *      4. Define GR_GL_PROC_ADDRESS.
+ *      5. Optionally define GR_GL_PROC_ADDRESS_HEADER
+ */
+
+#if GR_GL_CUSTOM_SETUP
+
+    #ifdef GR_SUPPORT_GLES1
+        #include GR_INCLUDE_GLES1
+        #if defined(GR_INCLUDE_GLES1ext)
+            #include GR_INCLUDE_GLES1ext
+        #endif
+    #endif
+
+    #ifdef GR_SUPPORT_GLES2
+        #include GR_INCLUDE_GLES2
+        #if defined(GR_INCLUDE_GLES2ext)
+            #include GR_INCLUDE_GLES2ext
+        #endif
+    #endif
+
+    #ifdef GR_SUPPORT_GLDESKTOP
+        #include GR_INCLUDE_GLDESKTOP
+        #if defined(GR_INCLUDE_GLDESKTOPext)
+            #include GR_INCLUDE_GLDESKTOPext
+        #endif
+    #endif
+
+#elif defined(GR_GL_CUSTOM_SETUP_HEADER)
+
+    #include GR_GL_CUSTOM_SETUP_HEADER
+
+#else
+    #undef GR_GL_FUNCTION_TYPE
+    #undef GR_GL_PROC_ADDRESS
+    #undef GR_GL_PROC_ADDRESS_HEADER
+
+    #if GR_WIN32_BUILD
+        #define GR_SUPPORT_GLDESKTOP        1
+        #include <Windows.h>
+        #include <GL/gl.h>
+        // remove stupid windows defines
+        #undef near
+        #undef far
+        #define GR_GL_EMIT_GL_CONSTANTS     1
+        #define GR_GL_FUNCTION_TYPE __stdcall
+        #define GR_GL_PROC_ADDRESS(X)       wglGetProcAddress(#X)
+        #define GR_GL_PROC_ADDRESS_HEADER   <windows.h>
+
+        // Force querying for the existence of these extensions on Windows
+        // builds.
+        #define GL_APPLE_framebuffer_multisample        1
+        #define GL_EXT_framebuffer_object               1
+        #define GL_IMG_multisampled_render_to_texture   1
+        #define GL_OES_mapbuffer                        1
+        #define GL_OES_mapbuffer                        1
+    #elif GR_MAC_BUILD
+        #define GR_SUPPORT_GLDESKTOP        1
+        #include <OpenGL/gl.h>
+        #include <OpenGL/glext.h>
+        #define GR_GL_PROC_ADDRESS(X)       &X
+    #elif GR_IOS_BUILD
+        #define GR_SUPPORT_GLES1            1
+        #include <OpenGLES/ES1/gl.h>
+        #include <OpenGLES/ES1/glext.h>
+        #define GR_SUPPORT_GLES2            1
+        #include <OpenGLES/ES2/gl.h>
+        #include <OpenGLES/ES2/glext.h>
+        #define GR_GL_PROC_ADDRESS(X)       &X
+    #elif GR_ANDROID_BUILD
+        #ifndef GL_GLEXT_PROTOTYPES
+            #define GL_GLEXT_PROTOTYPES
+        #endif
+        #define GR_SUPPORT_GLES2            1
+        #include <GLES2/gl2.h>
+        #include <GLES2/gl2ext.h>
+        #define GR_GL_PROC_ADDRESS(X)       eglGetProcAddress(#X)
+        #define GR_GL_PROC_ADDRESS_HEADER   <EGL/egl.h>
+    #elif GR_QNX_BUILD
+        #ifndef GL_GLEXT_PROTOTYPES
+            #define GL_GLEXT_PROTOTYPES
+        #endif
+         #define GR_SUPPORT_GLES2           1
+        // This is needed by the QNX GLES2 headers
+        #define GL_API_EXT
+        #include <GLES2/gl2.h>
+        #include <GLES2/gl2ext.h>
+        #define GR_GL_PROC_ADDRESS(X)       eglGetProcAddress(#X)
+        #define GR_GL_PROC_ADDRESS_HEADER   <EGL/egl.h>
+    #elif GR_LINUX_BUILD
+        #ifndef GL_GLEXT_PROTOTYPES
+            #define GL_GLEXT_PROTOTYPES
+        #endif
+        #include <GL/gl.h>
+        #include <GL/glext.h>
+        #define GR_GL_PROC_ADDRESS(X)       glXGetProcAddress(reinterpret_cast<const GLubyte*>(#X))
+        #define GR_SUPPORT_GLDESKTOP        1
+        #define GR_GL_PROC_ADDRESS_HEADER   <GL/glx.h>
+    #else
+        #error "unsupported GR_???_BUILD"
+    #endif
+
+#endif
+
+#if !defined(GR_SUPPORT_GLDESKTOP)
+    #define GR_SUPPORT_GLDESKTOP    0
+#endif
+#if !defined(GR_SUPPORT_GLES1)
+    #define GR_SUPPORT_GLES1        0
+#endif
+#if !defined(GR_SUPPORT_GLES2)
+    #define GR_SUPPORT_GLES2        0
+#endif
+
+#define GR_SUPPORT_GLES ((GR_SUPPORT_GLES1) || (GR_SUPPORT_GLES2))
+
+#if !GR_SUPPORT_GLES && !GR_SUPPORT_GLDESKTOP
+    #error "Either desktop or ES GL must be supported"
+#elif GR_SUPPORT_GLES && GR_SUPPORT_GLDESKTOP
+    #error "Cannot support both desktop and ES GL"
+#endif
+
+#if GR_WIN32_BUILD && GR_GL_EMIT_GL_CONSTANTS
+
+// The windows GL headers do not provide the constants used for extensions and
+// some versions of GL.  Define them here.
+
+// OpenGL 1.2 Defines
+#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12
+#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13
+#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22
+#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23
+#define GL_UNSIGNED_BYTE_3_3_2 0x8032
+#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
+#define GL_UNSIGNED_INT_8_8_8_8 0x8035
+#define GL_UNSIGNED_INT_10_10_10_2 0x8036
+#define GL_RESCALE_NORMAL 0x803A
+#define GL_TEXTURE_BINDING_3D 0x806A
+#define GL_PACK_SKIP_IMAGES 0x806B
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#define GL_TEXTURE_3D 0x806F
+#define GL_PROXY_TEXTURE_3D 0x8070
+#define GL_TEXTURE_DEPTH 0x8071
+#define GL_TEXTURE_WRAP_R 0x8072
+#define GL_MAX_3D_TEXTURE_SIZE 0x8073
+#define GL_BGR 0x80E0
+#define GL_BGRA 0x80E1
+#define GL_MAX_ELEMENTS_VERTICES 0x80E8
+#define GL_MAX_ELEMENTS_INDICES 0x80E9
+#define GL_CLAMP_TO_EDGE 0x812F
+#define GL_TEXTURE_MIN_LOD 0x813A
+#define GL_TEXTURE_MAX_LOD 0x813B
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
+#define GL_SINGLE_COLOR 0x81F9
+#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
+#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
+
+// OpenGL 1.3 Multi-Sample Constant Values
+#define GL_MULTISAMPLE 0x809D
+#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
+#define GL_SAMPLE_ALPHA_TO_ONE 0x809F
+#define GL_SAMPLE_COVERAGE 0x80A0
+#define GL_SAMPLE_BUFFERS 0x80A8
+#define GL_SAMPLES 0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
+#define GL_CLAMP_TO_BORDER 0x812D
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE4 0x84C4
+#define GL_TEXTURE5 0x84C5
+#define GL_TEXTURE6 0x84C6
+#define GL_TEXTURE7 0x84C7
+#define GL_TEXTURE8 0x84C8
+#define GL_TEXTURE9 0x84C9
+#define GL_TEXTURE10 0x84CA
+#define GL_TEXTURE11 0x84CB
+#define GL_TEXTURE12 0x84CC
+#define GL_TEXTURE13 0x84CD
+#define GL_TEXTURE14 0x84CE
+#define GL_TEXTURE15 0x84CF
+#define GL_TEXTURE16 0x84D0
+#define GL_TEXTURE17 0x84D1
+#define GL_TEXTURE18 0x84D2
+#define GL_TEXTURE19 0x84D3
+#define GL_TEXTURE20 0x84D4
+#define GL_TEXTURE21 0x84D5
+#define GL_TEXTURE22 0x84D6
+#define GL_TEXTURE23 0x84D7
+#define GL_TEXTURE24 0x84D8
+#define GL_TEXTURE25 0x84D9
+#define GL_TEXTURE26 0x84DA
+#define GL_TEXTURE27 0x84DB
+#define GL_TEXTURE28 0x84DC
+#define GL_TEXTURE29 0x84DD
+#define GL_TEXTURE30 0x84DE
+#define GL_TEXTURE31 0x84DF
+#define GL_ACTIVE_TEXTURE 0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1
+#define GL_MAX_TEXTURE_UNITS 0x84E2
+#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
+#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
+#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
+#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
+#define GL_SUBTRACT 0x84E7
+#define GL_COMPRESSED_ALPHA 0x84E9
+#define GL_COMPRESSED_LUMINANCE 0x84EA
+#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
+#define GL_COMPRESSED_INTENSITY 0x84EC
+#define GL_COMPRESSED_RGB 0x84ED
+#define GL_COMPRESSED_RGBA 0x84EE
+#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
+#define GL_NORMAL_MAP 0x8511
+#define GL_REFLECTION_MAP 0x8512
+#define GL_TEXTURE_CUBE_MAP 0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
+#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
+#define GL_COMBINE 0x8570
+#define GL_COMBINE_RGB 0x8571
+#define GL_COMBINE_ALPHA 0x8572
+#define GL_RGB_SCALE 0x8573
+#define GL_ADD_SIGNED 0x8574
+#define GL_INTERPOLATE 0x8575
+#define GL_CONSTANT 0x8576
+#define GL_PRIMARY_COLOR 0x8577
+#define GL_PREVIOUS 0x8578
+#define GL_SOURCE0_RGB 0x8580
+#define GL_SOURCE1_RGB 0x8581
+#define GL_SOURCE2_RGB 0x8582
+#define GL_SOURCE0_ALPHA 0x8588
+#define GL_SOURCE1_ALPHA 0x8589
+#define GL_SOURCE2_ALPHA 0x858A
+#define GL_OPERAND0_RGB 0x8590
+#define GL_OPERAND1_RGB 0x8591
+#define GL_OPERAND2_RGB 0x8592
+#define GL_OPERAND0_ALPHA 0x8598
+#define GL_OPERAND1_ALPHA 0x8599
+#define GL_OPERAND2_ALPHA 0x859A
+#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
+#define GL_TEXTURE_COMPRESSED 0x86A1
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
+#define GL_DOT3_RGB 0x86AE
+#define GL_DOT3_RGBA 0x86AF
+#define GL_MULTISAMPLE_BIT 0x20000000
+
+// OpenGL 1.4 Defines
+#define GL_CONSTANT_COLOR 0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#define GL_CONSTANT_ALPHA 0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#define GL_BLEND_DST_RGB 0x80C8
+#define GL_BLEND_SRC_RGB 0x80C9
+#define GL_BLEND_DST_ALPHA 0x80CA
+#define GL_BLEND_SRC_ALPHA 0x80CB
+#define GL_POINT_SIZE_MIN 0x8126
+#define GL_POINT_SIZE_MAX 0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128
+#define GL_POINT_DISTANCE_ATTENUATION 0x8129
+#define GL_GENERATE_MIPMAP 0x8191
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#define GL_DEPTH_COMPONENT16 0x81A5
+#define GL_DEPTH_COMPONENT24 0x81A6
+#define GL_DEPTH_COMPONENT32 0x81A7
+#define GL_MIRRORED_REPEAT 0x8370
+#define GL_FOG_COORDINATE_SOURCE 0x8450
+#define GL_FOG_COORDINATE 0x8451
+#define GL_FRAGMENT_DEPTH 0x8452
+#define GL_CURRENT_FOG_COORDINATE 0x8453
+#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454
+#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455
+#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456
+#define GL_FOG_COORDINATE_ARRAY 0x8457
+#define GL_COLOR_SUM 0x8458
+#define GL_CURRENT_SECONDARY_COLOR 0x8459
+#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
+#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
+#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
+#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
+#define GL_SECONDARY_COLOR_ARRAY 0x845E
+#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD
+#define GL_TEXTURE_FILTER_CONTROL 0x8500
+#define GL_TEXTURE_LOD_BIAS 0x8501
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#define GL_TEXTURE_DEPTH_SIZE 0x884A
+#define GL_DEPTH_TEXTURE_MODE 0x884B
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#define GL_COMPARE_R_TO_TEXTURE 0x884E
+
+// OpenGL 1.5 Defines
+#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE
+#define GL_FOG_COORD GL_FOG_COORDINATE
+#define GL_FOG_COORD_ARRAY GL_FOG_COORDINATE_ARRAY
+#define GL_SRC0_RGB GL_SOURCE0_RGB
+#define GL_FOG_COORD_ARRAY_POINTER GL_FOG_COORDINATE_ARRAY_POINTER
+#define GL_FOG_COORD_ARRAY_TYPE GL_FOG_COORDINATE_ARRAY_TYPE
+#define GL_SRC1_ALPHA GL_SOURCE1_ALPHA
+#define GL_CURRENT_FOG_COORD GL_CURRENT_FOG_COORDINATE
+#define GL_FOG_COORD_ARRAY_STRIDE GL_FOG_COORDINATE_ARRAY_STRIDE
+#define GL_SRC0_ALPHA GL_SOURCE0_ALPHA
+#define GL_SRC1_RGB GL_SOURCE1_RGB
+#define GL_FOG_COORD_ARRAY_BUFFER_BINDING GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING
+#define GL_SRC2_ALPHA GL_SOURCE2_ALPHA
+#define GL_SRC2_RGB GL_SOURCE2_RGB
+#define GL_BUFFER_SIZE 0x8764
+#define GL_BUFFER_USAGE 0x8765
+#define GL_QUERY_COUNTER_BITS 0x8864
+#define GL_CURRENT_QUERY 0x8865
+#define GL_QUERY_RESULT 0x8866
+#define GL_QUERY_RESULT_AVAILABLE 0x8867
+#define GL_ARRAY_BUFFER 0x8892
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#define GL_ARRAY_BUFFER_BINDING 0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
+#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
+#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
+#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
+#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
+#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
+#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
+#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
+#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
+#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
+#define GL_READ_ONLY 0x88B8
+#define GL_WRITE_ONLY 0x88B9
+#define GL_READ_WRITE 0x88BA
+#define GL_BUFFER_ACCESS 0x88BB
+#define GL_BUFFER_MAPPED 0x88BC
+#define GL_BUFFER_MAP_POINTER 0x88BD
+#define GL_STREAM_DRAW 0x88E0
+#define GL_STREAM_READ 0x88E1
+#define GL_STREAM_COPY 0x88E2
+#define GL_STATIC_DRAW 0x88E4
+#define GL_STATIC_READ 0x88E5
+#define GL_STATIC_COPY 0x88E6
+#define GL_DYNAMIC_DRAW 0x88E8
+#define GL_DYNAMIC_READ 0x88E9
+#define GL_DYNAMIC_COPY 0x88EA
+#define GL_SAMPLES_PASSED 0x8914
+
+// OpenGL 2.0 Defines
+#define GL_BLEND_EQUATION_RGB GL_BLEND_EQUATION
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642
+#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
+#define GL_STENCIL_BACK_FUNC 0x8800
+#define GL_STENCIL_BACK_FAIL 0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
+#define GL_MAX_DRAW_BUFFERS 0x8824
+#define GL_DRAW_BUFFER0 0x8825
+#define GL_DRAW_BUFFER1 0x8826
+#define GL_DRAW_BUFFER2 0x8827
+#define GL_DRAW_BUFFER3 0x8828
+#define GL_DRAW_BUFFER4 0x8829
+#define GL_DRAW_BUFFER5 0x882A
+#define GL_DRAW_BUFFER6 0x882B
+#define GL_DRAW_BUFFER7 0x882C
+#define GL_DRAW_BUFFER8 0x882D
+#define GL_DRAW_BUFFER9 0x882E
+#define GL_DRAW_BUFFER10 0x882F
+#define GL_DRAW_BUFFER11 0x8830
+#define GL_DRAW_BUFFER12 0x8831
+#define GL_DRAW_BUFFER13 0x8832
+#define GL_DRAW_BUFFER14 0x8833
+#define GL_DRAW_BUFFER15 0x8834
+#define GL_BLEND_EQUATION_ALPHA 0x883D
+#define GL_POINT_SPRITE 0x8861
+#define GL_COORD_REPLACE 0x8862
+#define GL_MAX_VERTEX_ATTRIBS 0x8869
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
+#define GL_MAX_TEXTURE_COORDS 0x8871
+#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A
+#define GL_MAX_VARYING_FLOATS 0x8B4B
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
+#define GL_SHADER_TYPE 0x8B4F
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_SAMPLER_1D_SHADOW 0x8B61
+#define GL_SAMPLER_2D_SHADOW 0x8B62
+#define GL_DELETE_STATUS 0x8B80
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_LINK_STATUS 0x8B82
+#define GL_VALIDATE_STATUS 0x8B83
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_ATTACHED_SHADERS 0x8B85
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B
+#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
+#define GL_CURRENT_PROGRAM 0x8B8D
+#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
+#define GL_LOWER_LEFT 0x8CA1
+#define GL_UPPER_LEFT 0x8CA2
+#define GL_STENCIL_BACK_REF 0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
+
+#endif  // GR_WIN32_BUILD
+
+#endif
diff --git a/gpu/include/GrTextStrike.h b/gpu/include/GrTextStrike.h
index abafa57..610222c 100644
--- a/gpu/include/GrTextStrike.h
+++ b/gpu/include/GrTextStrike.h
@@ -35,11 +35,13 @@
  */
 class GrTextStrike {
 public:
-    GrTextStrike(GrFontCache*, const GrKey* fontScalerKey, GrAtlasMgr*);
+    GrTextStrike(GrFontCache*, const GrKey* fontScalerKey, GrMaskFormat,
+                 GrAtlasMgr*);
     ~GrTextStrike();
 
     const GrKey* getFontScalerKey() const { return fFontScalerKey; }
     GrFontCache* getFontCache() const { return fFontCache; }
+    GrMaskFormat getMaskFormat() const { return fMaskFormat; }
 
     inline GrGlyph* getGlyph(GrGlyph::PackedID, GrFontScaler*);
     bool getGlyphAtlas(GrGlyph*, GrFontScaler*);
@@ -66,6 +68,8 @@
     GrAtlasMgr*     fAtlasMgr;
     GrAtlas*        fAtlas;     // linklist
 
+    GrMaskFormat fMaskFormat;
+
     GrGlyph* generateGlyph(GrGlyph::PackedID packed, GrFontScaler* scaler);
     // returns true if after the purge, the strike is empty
     bool purgeAtlasAtY(GrAtlas* atlas, int yCoord);
@@ -110,7 +114,7 @@
     GrGpu*      fGpu;
     GrAtlasMgr* fAtlasMgr;
 
-    
+
     GrTextStrike* generateStrike(GrFontScaler*, const Key&);
     inline void detachStrikeFromList(GrTextStrike*);
 };
diff --git a/gpu/include/GrTexture.h b/gpu/include/GrTexture.h
index 666aa57..0a65ff7 100644
--- a/gpu/include/GrTexture.h
+++ b/gpu/include/GrTexture.h
@@ -89,6 +89,7 @@
     };
     static size_t BytesPerPixel(PixelConfig);
     static bool PixelConfigIsOpaque(PixelConfig);
+    static bool PixelConfigIsAlphaOnly(PixelConfig);
 
 protected:
     GrTexture(int width,
diff --git a/gpu/include/GrTypes.h b/gpu/include/GrTypes.h
index f407e2f..cc78c3e 100644
--- a/gpu/include/GrTypes.h
+++ b/gpu/include/GrTypes.h
@@ -186,9 +186,33 @@
     kISA_BlendCoeff,     //<! one minus src alpha
     kDA_BlendCoeff,      //<! dst alpha
     kIDA_BlendCoeff,     //<! one minus dst alpha
+    kConstC_BlendCoeff,  //<! constant color
+    kIConstC_BlendCoeff, //<! one minus constant color
+    kConstA_BlendCoeff,  //<! constant color alpha
+    kIConstA_BlendCoeff, //<! one minus constant color alpha
+
+    kBlendCoeffCount
 };
 
 /**
+ *  Formats for masks, used by the font cache.
+ *  Important that these are 0-based.
+ */
+enum GrMaskFormat {
+    kA8_GrMaskFormat,   //!< 1-byte per pixel
+    kA565_GrMaskFormat  //!< 2-bytes per pixel
+};
+#define kCount_GrMaskFormats    2
+
+/**
+ *  Return the number of bytes-per-pixel for the specified mask format.
+ */
+static inline int GrMaskFormatBytesPerPixel(GrMaskFormat format) {
+    GrAssert((unsigned)format <= 1);
+    return (int)format + 1;
+}
+
+/**
  * Set Operations used to construct clips.
  */
 enum GrSetOp {
diff --git a/gpu/src/GrAtlas.cpp b/gpu/src/GrAtlas.cpp
index b55a029..ab99d9a 100644
--- a/gpu/src/GrAtlas.cpp
+++ b/gpu/src/GrAtlas.cpp
@@ -51,15 +51,17 @@
     static int gCounter;
 #endif
 
-GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY) {
+GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY, GrMaskFormat format) {
     fAtlasMgr = mgr;    // just a pointer, not an owner
     fNext = NULL;
-    fTexture = mgr->getTexture(); // we're not an owner, just a pointer
+    fTexture = mgr->getTexture(format); // we're not an owner, just a pointer
     fPlot.set(plotX, plotY);
 
     fRects = GrRectanizer::Factory(GR_ATLAS_WIDTH - BORDER,
                                    GR_ATLAS_HEIGHT - BORDER);
 
+    fMaskFormat = format;
+
 #if GR_DEBUG
     GrPrintf(" GrAtlas %p [%d %d] %d\n", this, plotX, plotY, gCounter);
     gCounter += 1;
@@ -82,6 +84,13 @@
     loc->fY += plot.fY * GR_ATLAS_HEIGHT;
 }
 
+static uint8_t* zerofill(uint8_t* ptr, int count) {
+    while (--count >= 0) {
+        *ptr++ = 0;
+    }
+    return ptr;
+}
+
 bool GrAtlas::addSubImage(int width, int height, const void* image,
                           GrIPoint16* loc) {
     if (!fRects->addRect(width + BORDER, height + BORDER, loc)) {
@@ -89,23 +98,26 @@
     }
 
     GrAutoSMalloc<1024> storage;
-    int srcW = width + 2*BORDER;
-    int srcH = height + 2*BORDER;
+    int dstW = width + 2*BORDER;
+    int dstH = height + 2*BORDER;
     if (BORDER) {
-        uint8_t* ptr = (uint8_t*)storage.realloc(srcW * srcH);
-        Gr_bzero(ptr, srcW);                // zero top row
-        ptr += srcW;
+        const int bpp = GrMaskFormatBytesPerPixel(fMaskFormat);
+        const size_t dstRB = dstW * bpp;
+        uint8_t* dst = (uint8_t*)storage.realloc(dstH * dstRB);
+        Gr_bzero(dst, dstRB);                // zero top row
+        dst += dstRB;
         for (int y = 0; y < height; y++) {
-            *ptr++ = 0;                     // zero left edge
-            memcpy(ptr, image, width); ptr += width;
-            *ptr++ = 0;                     // zero right edge
-            image = (const void*)((const char*)image + width);
+            dst = zerofill(dst, bpp);   // zero left edge
+            memcpy(dst, image, width * bpp);
+            dst += width * bpp;
+            dst = zerofill(dst, bpp);   // zero right edge
+            image = (const void*)((const char*)image + width * bpp);
         }
-        Gr_bzero(ptr, srcW);                // zero bottom row
+        Gr_bzero(dst, dstRB);                // zero bottom row
         image = storage.get();
     }
     adjustForPlot(loc, fPlot);
-    fTexture->uploadTextureData(loc->fX, loc->fY, srcW, srcH, image);
+    fTexture->uploadTextureData(loc->fX, loc->fY, dstW, dstH, image);
 
     // now tell the caller to skip the top/left BORDER
     loc->fX += BORDER;
@@ -118,19 +130,36 @@
 GrAtlasMgr::GrAtlasMgr(GrGpu* gpu) {
     fGpu = gpu;
     gpu->ref();
-    fTexture = NULL;
+    Gr_bzero(fTexture, sizeof(fTexture));
     fPlotMgr = new GrPlotMgr(GR_PLOT_WIDTH, GR_PLOT_HEIGHT);
 }
 
 GrAtlasMgr::~GrAtlasMgr() {
-    GrSafeUnref(fTexture);
+    for (size_t i = 0; i < GR_ARRAY_COUNT(fTexture); i++) {
+        GrSafeUnref(fTexture[i]);
+    }
     delete fPlotMgr;
     fGpu->unref();
 }
 
+static GrTexture::PixelConfig maskformat2pixelconfig(GrMaskFormat format) {
+    switch (format) {
+        case kA8_GrMaskFormat:
+            return GrTexture::kAlpha_8_PixelConfig;
+        case kA565_GrMaskFormat:
+            return GrTexture::kRGB_565_PixelConfig;
+        default:
+            GrAssert(!"unknown maskformat");
+    }
+    return GrTexture::kUnknown_PixelConfig;
+}
+
 GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas* atlas,
                                 int width, int height, const void* image,
+                                GrMaskFormat format,
                                 GrIPoint16* loc) {
+    GrAssert(NULL == atlas || atlas->getMaskFormat() == format);
+
     if (atlas && atlas->addSubImage(width, height, image, loc)) {
         return atlas;
     }
@@ -143,21 +172,23 @@
         return NULL;
     }
 
-    if (NULL == fTexture) {
+    GrAssert(0 == kA8_GrMaskFormat);
+    GrAssert(1 == kA565_GrMaskFormat);
+    if (NULL == fTexture[format]) {
         GrGpu::TextureDesc desc = {
-            GrGpu::kDynamicUpdate_TextureFlag, 
+            GrGpu::kDynamicUpdate_TextureFlag,
             GrGpu::kNone_AALevel,
-            GR_ATLAS_TEXTURE_WIDTH, 
+            GR_ATLAS_TEXTURE_WIDTH,
             GR_ATLAS_TEXTURE_HEIGHT,
-            GrTexture::kAlpha_8_PixelConfig
+            maskformat2pixelconfig(format)
         };
-        fTexture = fGpu->createTexture(desc, NULL, 0);
-        if (NULL == fTexture) {
+        fTexture[format] = fGpu->createTexture(desc, NULL, 0);
+        if (NULL == fTexture[format]) {
             return NULL;
         }
     }
 
-    GrAtlas* newAtlas = new GrAtlas(this, plot.fX, plot.fY);
+    GrAtlas* newAtlas = new GrAtlas(this, plot.fX, plot.fY, format);
     if (!newAtlas->addSubImage(width, height, image, loc)) {
         delete newAtlas;
         return NULL;
diff --git a/gpu/src/GrGLIndexBuffer.cpp b/gpu/src/GrGLIndexBuffer.cpp
index 2dc4154..9539c8a 100644
--- a/gpu/src/GrGLIndexBuffer.cpp
+++ b/gpu/src/GrGLIndexBuffer.cpp
@@ -1,5 +1,5 @@
 /*
-    Copyright 2010 Google Inc.
+    Copyright 2011 Google Inc.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -57,8 +57,7 @@
         // Let driver know it can discard the old data
         GR_GL(BufferData(GL_ELEMENT_ARRAY_BUFFER, size(), NULL,
                          dynamic() ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
-        fLockPtr = GR_GLEXT(fGL->extensions(),
-                            MapBuffer(GL_ELEMENT_ARRAY_BUFFER, GR_WRITE_ONLY));
+        fLockPtr = GR_GL(MapBuffer(GL_ELEMENT_ARRAY_BUFFER, GR_WRITE_ONLY));
 
         return fLockPtr;
     }
@@ -75,7 +74,7 @@
     GrAssert(fGL->supportsBufferLocking());
 
     bind();
-    GR_GLEXT(fGL->extensions(), UnmapBuffer(GL_ELEMENT_ARRAY_BUFFER));
+    GR_GL(UnmapBuffer(GL_ELEMENT_ARRAY_BUFFER));
     fLockPtr = NULL;
 }
 
diff --git a/gpu/src/GrGLInterface.cpp b/gpu/src/GrGLInterface.cpp
new file mode 100644
index 0000000..fa6aa92
--- /dev/null
+++ b/gpu/src/GrGLInterface.cpp
@@ -0,0 +1,351 @@
+/*
+    Copyright 2011 Google Inc.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+ */
+
+
+#include "GrGLInterface.h"
+#include "GrTypes.h"
+
+#include <stdio.h>
+
+#if defined(GR_GL_PROC_ADDRESS_HEADER)
+    #include GR_GL_PROC_ADDRESS_HEADER
+#endif
+
+#if !defined(GR_GL_PROC_ADDRESS)
+    #error "Must define GR_GL_PROC_ADDRESS"
+#endif
+
+#define GR_GL_GET_PROC(PROC_NAME) \
+    glBindings->f##PROC_NAME = \
+                reinterpret_cast<GrGLInterface::GrGL##PROC_NAME##Proc>( \
+                            GR_GL_PROC_ADDRESS(gl##PROC_NAME)); \
+    GrAssert(NULL != glBindings->f##PROC_NAME && \
+             "Missing GL binding: " #PROC_NAME);
+
+#define GR_GL_GET_PROC_SUFFIX(PROC_NAME, SUFFIX) \
+    glBindings->f##PROC_NAME = \
+                reinterpret_cast<GrGLInterface::GrGL##PROC_NAME##Proc>( \
+                        GR_GL_PROC_ADDRESS(gl##PROC_NAME##SUFFIX)); \
+    GrAssert(NULL != glBindings->f##PROC_NAME && \
+             "Missing GL binding: " #PROC_NAME);
+
+#define GR_GL_GET_PROC_SYMBOL(PROC_NAME) \
+    glBindings->f##PROC_NAME = reinterpret_cast<GrGLInterface::GrGL##PROC_NAME##Proc>(gl##PROC_NAME);
+
+namespace {
+
+void gl_version_from_string(int* major, int* minor,
+                            const char* versionString) {
+    if (NULL == versionString) {
+        GrAssert(0);
+        *major = 0;
+        *minor = 0;
+        return;
+    }
+#if GR_SUPPORT_GLDESKTOP
+    int n = sscanf(versionString, "%d.%d", major, minor);
+    if (n != 2) {
+        GrAssert(0);
+        *major = 0;
+        *minor = 0;
+        return;
+    }
+#else
+    char profile[2];
+    int n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
+                   major, minor);
+    bool ok = 4 == n;
+    if (!ok) {
+        int n = sscanf(versionString, "OpenGL ES %d.%d", major, minor);
+        ok = 2 == n;
+    }
+    if (!ok) {
+        GrAssert(0);
+        *major = 0;
+        *minor = 0;
+        return;
+    }
+#endif
+}
+
+bool has_gl_extension_from_string(const char* ext,
+                                  const char* extensionString) {
+    int extLength = strlen(ext);
+
+    while (true) {
+        int n = strcspn(extensionString, " ");
+        if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
+            return true;
+        }
+        if (0 == extensionString[n]) {
+            return false;
+        }
+        extensionString += n+1;
+    }
+
+    return false;
+}
+
+GrGLInterface* gGLInterface = NULL;
+
+void InitializeGLInterfaceExtensions(GrGLInterface* glBindings) {
+    int major, minor;
+    const char* versionString = reinterpret_cast<const char*>(
+                glBindings->fGetString(GL_VERSION));
+    const char* extensionString = reinterpret_cast<const char*>(
+                glBindings->fGetString(GL_EXTENSIONS));
+    gl_version_from_string(&major, &minor, versionString);
+
+    bool fboFound = false;
+#if GR_SUPPORT_GLDESKTOP
+    if (major >= 3 || has_gl_extension_from_string("GL_ARB_framebuffer_object",
+                                                   extensionString)) {
+        // GL_ARB_framebuffer_object doesn't use ARB suffix.
+        GR_GL_GET_PROC(GenFramebuffers);
+        GR_GL_GET_PROC(BindFramebuffer);
+        GR_GL_GET_PROC(FramebufferTexture2D);
+        GR_GL_GET_PROC(CheckFramebufferStatus);
+        GR_GL_GET_PROC(DeleteFramebuffers);
+        GR_GL_GET_PROC(RenderbufferStorage);
+        GR_GL_GET_PROC(GenRenderbuffers);
+        GR_GL_GET_PROC(DeleteRenderbuffers);
+        GR_GL_GET_PROC(FramebufferRenderbuffer);
+        GR_GL_GET_PROC(BindRenderbuffer);
+        GR_GL_GET_PROC(RenderbufferStorageMultisample);
+        GR_GL_GET_PROC(BlitFramebuffer);
+        fboFound = true;
+    }
+
+    #if GL_EXT_framebuffer_object && !GR_MAC_BUILD
+    if (!fboFound &&
+            has_gl_extension_from_string("GL_EXT_framebuffer_object",
+                                         extensionString)) {
+        GR_GL_GET_PROC_SUFFIX(GenFramebuffers, EXT);
+        GR_GL_GET_PROC_SUFFIX(BindFramebuffer, EXT);
+        GR_GL_GET_PROC_SUFFIX(FramebufferTexture2D, EXT);
+        GR_GL_GET_PROC_SUFFIX(CheckFramebufferStatus, EXT);
+        GR_GL_GET_PROC_SUFFIX(DeleteFramebuffers, EXT);
+        GR_GL_GET_PROC_SUFFIX(RenderbufferStorage, EXT);
+        GR_GL_GET_PROC_SUFFIX(GenRenderbuffers, EXT);
+        GR_GL_GET_PROC_SUFFIX(DeleteRenderbuffers, EXT);
+        GR_GL_GET_PROC_SUFFIX(FramebufferRenderbuffer, EXT);
+        GR_GL_GET_PROC_SUFFIX(BindRenderbuffer, EXT);
+        fboFound = true;
+
+        if (has_gl_extension_from_string("GL_EXT_framebuffer_multisample",
+                                         extensionString)) {
+            GR_GL_GET_PROC_SUFFIX(RenderbufferStorageMultisample, EXT);
+        }
+        if (has_gl_extension_from_string("GL_EXT_framebuffer_blit",
+                                         extensionString)) {
+            GR_GL_GET_PROC_SUFFIX(BlitFramebuffer, EXT);
+        }
+    }
+    #endif
+
+    // we assume we have at least GL 1.5 or higher (VBOs introduced in 1.5)
+    GrAssert((major == 1 && minor >= 5) || major >=2);
+    GR_GL_GET_PROC(MapBuffer);
+    GR_GL_GET_PROC(UnmapBuffer);
+#else // !GR_SUPPORT_GLDESKTOP
+    #if GR_SUPPORT_GLES2
+    if (!fboFound && major >= 2) {// ES 2.0 supports FBO
+        GR_GL_GET_PROC(GenFramebuffers);
+        GR_GL_GET_PROC(BindFramebuffer);
+        GR_GL_GET_PROC(FramebufferTexture2D);
+        GR_GL_GET_PROC(CheckFramebufferStatus);
+        GR_GL_GET_PROC(DeleteFramebuffers);
+        GR_GL_GET_PROC(RenderbufferStorage);
+        GR_GL_GET_PROC(GenRenderbuffers);
+        GR_GL_GET_PROC(DeleteRenderbuffers);
+        GR_GL_GET_PROC(FramebufferRenderbuffer);
+        GR_GL_GET_PROC(BindRenderbuffer);
+        fboFound = true;
+    }
+    #endif
+
+    #if GL_OES_mapbuffer
+    if (!fboFound &&
+            has_gl_extension_from_string("GL_OES_framebuffer_object",
+                                         extensionString)) {
+        GR_GL_GET_PROC_SUFFIX(GenFramebuffers, OES);
+        GR_GL_GET_PROC_SUFFIX(BindFramebuffer, OES);
+        GR_GL_GET_PROC_SUFFIX(FramebufferTexture2D, OES);
+        GR_GL_GET_PROC_SUFFIX(CheckFramebufferStatus, OES);
+        GR_GL_GET_PROC_SUFFIX(DeleteFramebuffers, OES);
+        GR_GL_GET_PROC_SUFFIX(RenderbufferStorage, OES);
+        GR_GL_GET_PROC_SUFFIX(GenRenderbuffers, OES);
+        GR_GL_GET_PROC_SUFFIX(DeleteRenderbuffers, OES);
+        GR_GL_GET_PROC_SUFFIX(FramebufferRenderbuffer, OES);
+        GR_GL_GET_PROC_SUFFIX(BindRenderbuffer, OES);
+        fboFound = true;
+    }
+    #endif
+
+    #if GL_APPLE_framebuffer_multisample
+    if (has_gl_extension_from_string("GL_APPLE_framebuffer_multisample",
+                                     extensionString)) {
+        GR_GL_GET_PROC_SUFFIX(ResolveMultisampleFramebuffer, APPLE);
+    }
+    #endif
+
+    #if GL_IMG_multisampled_render_to_texture
+    if (has_gl_extension_from_string(
+                "GL_IMG_multisampled_render_to_texture", extensionString)) {
+        GR_GL_GET_PROC_SUFFIX(FramebufferTexture2DMultisample, IMG);
+    }
+    #endif
+
+    #if GL_OES_mapbuffer
+    if (has_gl_extension_from_string("GL_OES_mapbuffer", extensionString)) {
+        GR_GL_GET_PROC_SUFFIX(MapBuffer, OES);
+        GR_GL_GET_PROC_SUFFIX(UnmapBuffer, OES);
+    }
+    #endif
+#endif  // !GR_SUPPORT_GLDESKTOP
+
+    if (!fboFound) {
+        // we require some form of FBO
+        GrAssert(!"No FBOs supported?");
+    }
+}
+
+void GrGLInitializeGLInterface(GrGLInterface* glBindings) {
+    Gr_bzero(glBindings, sizeof(GrGLInterface));
+
+#if GR_SUPPORT_GLDESKTOP || GR_SUPPORT_GLES1
+    // These entry points only exist on desktop GL implementations.
+    GR_GL_GET_PROC_SYMBOL(Color4ub);
+    GR_GL_GET_PROC_SYMBOL(ColorPointer);
+    GR_GL_GET_PROC_SYMBOL(DisableClientState);
+    GR_GL_GET_PROC_SYMBOL(EnableClientState);
+    GR_GL_GET_PROC_SYMBOL(LoadMatrixf);
+    GR_GL_GET_PROC_SYMBOL(MatrixMode);
+    GR_GL_GET_PROC_SYMBOL(PointSize);
+    GR_GL_GET_PROC_SYMBOL(ShadeModel);
+    GR_GL_GET_PROC_SYMBOL(TexCoordPointer);
+    GR_GL_GET_PROC_SYMBOL(TexEnvi);
+    GR_GL_GET_PROC_SYMBOL(VertexPointer);
+    GR_GL_GET_PROC(ClientActiveTexture);
+#endif
+
+    // The following gl entry points are part of GL 1.1, and will always be
+    // exported as symbols.
+    // Note that on windows, the wglGetProcAddress call will fail to retrieve
+    // these entry points.
+    GR_GL_GET_PROC_SYMBOL(BlendFunc);
+    GR_GL_GET_PROC_SYMBOL(Clear);
+    GR_GL_GET_PROC_SYMBOL(ClearColor);
+    GR_GL_GET_PROC_SYMBOL(ClearStencil);
+    GR_GL_GET_PROC_SYMBOL(ColorMask);
+    GR_GL_GET_PROC_SYMBOL(CullFace);
+    GR_GL_GET_PROC_SYMBOL(DeleteTextures);
+    GR_GL_GET_PROC_SYMBOL(DepthMask);
+    GR_GL_GET_PROC_SYMBOL(Disable);
+    GR_GL_GET_PROC_SYMBOL(DrawArrays);
+    GR_GL_GET_PROC_SYMBOL(DrawElements);
+    GR_GL_GET_PROC_SYMBOL(Enable);
+    GR_GL_GET_PROC_SYMBOL(FrontFace);
+    GR_GL_GET_PROC_SYMBOL(GenTextures);
+    GR_GL_GET_PROC_SYMBOL(GetError);
+    GR_GL_GET_PROC_SYMBOL(GetIntegerv);
+    GR_GL_GET_PROC_SYMBOL(GetString);
+    GR_GL_GET_PROC_SYMBOL(LineWidth);
+    GR_GL_GET_PROC_SYMBOL(PixelStorei);
+    GR_GL_GET_PROC_SYMBOL(ReadPixels);
+    GR_GL_GET_PROC_SYMBOL(Scissor);
+    GR_GL_GET_PROC_SYMBOL(StencilFunc);
+    GR_GL_GET_PROC_SYMBOL(StencilMask);
+    GR_GL_GET_PROC_SYMBOL(StencilOp);
+    GR_GL_GET_PROC_SYMBOL(TexImage2D);
+    GR_GL_GET_PROC_SYMBOL(TexParameteri);
+    GR_GL_GET_PROC_SYMBOL(TexSubImage2D);
+    GR_GL_GET_PROC_SYMBOL(Viewport);
+
+    // Capture the remaining entry points as gl extensions.
+    GR_GL_GET_PROC(ActiveTexture);
+    GR_GL_GET_PROC(AttachShader);
+    GR_GL_GET_PROC(BindAttribLocation);
+    GR_GL_GET_PROC(BindBuffer);
+    GR_GL_GET_PROC(BindTexture);
+    GR_GL_GET_PROC(BlendColor);
+    GR_GL_GET_PROC(BufferData);
+    GR_GL_GET_PROC(BufferSubData);
+    GR_GL_GET_PROC(CompileShader);
+    GR_GL_GET_PROC(CompressedTexImage2D);
+    GR_GL_GET_PROC(CreateProgram);
+    GR_GL_GET_PROC(CreateShader);
+    GR_GL_GET_PROC(DeleteBuffers);
+    GR_GL_GET_PROC(DeleteProgram);
+    GR_GL_GET_PROC(DeleteShader);
+    GR_GL_GET_PROC(DisableVertexAttribArray);
+    GR_GL_GET_PROC(EnableVertexAttribArray);
+    GR_GL_GET_PROC(GenBuffers);
+    GR_GL_GET_PROC(GetBufferParameteriv);
+    GR_GL_GET_PROC(GetProgramInfoLog);
+    GR_GL_GET_PROC(GetProgramiv);
+    GR_GL_GET_PROC(GetShaderInfoLog);
+    GR_GL_GET_PROC(GetShaderiv);
+    GR_GL_GET_PROC(GetUniformLocation);
+    GR_GL_GET_PROC(LinkProgram);
+    GR_GL_GET_PROC(ShaderSource);
+    GR_GL_GET_PROC(StencilFuncSeparate);
+    GR_GL_GET_PROC(StencilMaskSeparate);
+    GR_GL_GET_PROC(StencilOpSeparate);
+    GR_GL_GET_PROC(Uniform1fv);
+    GR_GL_GET_PROC(Uniform1i);
+    GR_GL_GET_PROC(Uniform4fv);
+    GR_GL_GET_PROC(UniformMatrix3fv);
+    GR_GL_GET_PROC(UseProgram);
+    GR_GL_GET_PROC(VertexAttrib4fv);
+    GR_GL_GET_PROC(VertexAttribPointer);
+
+    InitializeGLInterfaceExtensions(glBindings);
+}
+
+}  // unnamed namespace
+
+void GrGLSetGLInterface(GrGLInterface* gl_interface) {
+    gGLInterface = gl_interface;
+}
+
+GrGLInterface* GrGLGetGLInterface() {
+    return gGLInterface;
+}
+
+void GrGLSetDefaultGLInterface() {
+    static GrGLInterface gDefaultInterface;
+    static bool gDefaultInitialized = false;
+    GrAssert(!gDefaultInitialized);
+
+    if (!gDefaultInitialized) {
+        GrGLInitializeGLInterface(&gDefaultInterface);
+        GrGLSetGLInterface(&gDefaultInterface);
+    }
+}
+
+bool has_gl_extension(const char* ext) {
+    const char* glstr = reinterpret_cast<const char*>(
+                GrGLGetGLInterface()->fGetString(GL_EXTENSIONS));
+
+    return has_gl_extension_from_string(ext, glstr);
+}
+
+void gl_version(int* major, int* minor) {
+    const char* v = reinterpret_cast<const char*>(
+                GrGLGetGLInterface()->fGetString(GL_VERSION));
+    gl_version_from_string(major, minor, v);
+}
diff --git a/gpu/src/GrGLTexture.cpp b/gpu/src/GrGLTexture.cpp
index 1acb871..7488d0f 100644
--- a/gpu/src/GrGLTexture.cpp
+++ b/gpu/src/GrGLTexture.cpp
@@ -43,16 +43,16 @@
     fGL->notifyRenderTargetDelete(this);
     if (fOwnIDs) {
         if (fTexFBOID) {
-            GR_GLEXT(fGL->extensions(), DeleteFramebuffers(1, &fTexFBOID));
+            GR_GL(DeleteFramebuffers(1, &fTexFBOID));
         }
         if (fRTFBOID && fRTFBOID != fTexFBOID) {
-            GR_GLEXT(fGL->extensions(), DeleteFramebuffers(1, &fRTFBOID));
+            GR_GL(DeleteFramebuffers(1, &fRTFBOID));
         }
         if (fStencilRenderbufferID) {
-            GR_GLEXT(fGL->extensions(), DeleteRenderbuffers(1, &fStencilRenderbufferID));
+            GR_GL(DeleteRenderbuffers(1, &fStencilRenderbufferID));
         }
         if (fMSColorRenderbufferID) {
-            GR_GLEXT(fGL->extensions(), DeleteRenderbuffers(1, &fMSColorRenderbufferID));
+            GR_GL(DeleteRenderbuffers(1, &fMSColorRenderbufferID));
         }
     }
     GrSafeUnref(fTexIDObj);
diff --git a/gpu/src/GrGLUtil.cpp b/gpu/src/GrGLUtil.cpp
index e128d35..2cb887a 100644
--- a/gpu/src/GrGLUtil.cpp
+++ b/gpu/src/GrGLUtil.cpp
@@ -1,5 +1,5 @@
 /*
- Copyright 2010 Google Inc.
+ Copyright 2011 Google Inc.
 
  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
@@ -15,227 +15,9 @@
  */
 
 #include "GrGLConfig.h"
-#include "GrTypes.h"
-#include <stdio.h>
-
-bool has_gl_extension(const char* ext) {
-    const char* glstr = (const char*) glGetString(GL_EXTENSIONS);
-
-    int extLength = strlen(ext);
-
-    while (true) {
-        int n = strcspn(glstr, " ");
-        if (n == extLength && 0 == strncmp(ext, glstr, n)) {
-            return true;
-        }
-        if (0 == glstr[n]) {
-            return false;
-        }
-        glstr += n+1;
-    }
-}
-
-void gl_version(int* major, int* minor) {
-    const char* v = (const char*) glGetString(GL_VERSION);
-    if (NULL == v) {
-        GrAssert(0);
-        *major = 0;
-        *minor = 0;
-        return;
-    }
-#if GR_SUPPORT_GLDESKTOP
-    int n = sscanf(v, "%d.%d", major, minor);
-    if (n != 2) {
-        GrAssert(0);
-        *major = 0;
-        *minor = 0;
-        return;
-    }
-#else
-    char profile[2];
-    int n = sscanf(v, "OpenGL ES-%c%c %d.%d", profile, profile+1, major, minor);
-    bool ok = 4 == n;
-    if (!ok) {
-        int n = sscanf(v, "OpenGL ES %d.%d", major, minor);
-        ok = 2 == n;
-    }
-    if (!ok) {
-        GrAssert(0);
-        *major = 0;
-        *minor = 0;
-        return;
-    }
-#endif
-}
-
-#if defined(GR_GL_PROC_ADDRESS_HEADER)
-    #include GR_GL_PROC_ADDRESS_HEADER
-#endif
-
-typedef void (*glProc)(void);
-
-#define GET_PROC(EXT_STRUCT, PROC_NAME) \
-    *(GrTCast<glProc*>(&(EXT_STRUCT-> PROC_NAME))) = (glProc)GR_GL_PROC_ADDRESS((gl ## PROC_NAME)); \
-    GrAssert(NULL != EXT_STRUCT-> PROC_NAME)
-
-#define GET_SUFFIX_PROC(EXT_STRUCT, PROC_NAME, SUFFIX) \
-    *(GrTCast<glProc*>(&(EXT_STRUCT-> PROC_NAME))) = (glProc)GR_GL_PROC_ADDRESS((gl ## PROC_NAME ## SUFFIX)); \
-    GrAssert(NULL != EXT_STRUCT-> PROC_NAME)
-
-extern void GrGLInitExtensions(GrGLExts* exts) {
-    exts->GenFramebuffers                   = NULL;
-    exts->BindFramebuffer                   = NULL;
-    exts->FramebufferTexture2D              = NULL;
-    exts->CheckFramebufferStatus            = NULL;
-    exts->DeleteFramebuffers                = NULL;
-    exts->RenderbufferStorage               = NULL;
-    exts->GenRenderbuffers                  = NULL;
-    exts->DeleteRenderbuffers               = NULL;
-    exts->FramebufferRenderbuffer           = NULL;
-    exts->BindRenderbuffer                  = NULL;
-    exts->RenderbufferStorageMultisample    = NULL;
-    exts->BlitFramebuffer                   = NULL;
-    exts->ResolveMultisampleFramebuffer     = NULL;
-    exts->FramebufferTexture2DMultisample   = NULL;
-    exts->MapBuffer                         = NULL;
-    exts->UnmapBuffer                       = NULL;
-
-    GLint major, minor;
-    gl_version(&major, &minor);
-
-    bool fboFound = false;
-#if GR_SUPPORT_GLDESKTOP
-    #if defined(GL_VERSION_3_0) && GL_VERSION_3_0
-    if (!fboFound && major >= 3) { // all of ARB_fbo is in 3.x
-        exts->GenFramebuffers                   = glGenFramebuffers;
-        exts->BindFramebuffer                   = glBindFramebuffer;
-        exts->FramebufferTexture2D              = glFramebufferTexture2D;
-        exts->CheckFramebufferStatus            = glCheckFramebufferStatus;
-        exts->DeleteFramebuffers                = glDeleteFramebuffers;
-        exts->RenderbufferStorage               = glRenderbufferStorage;
-        exts->GenRenderbuffers                  = glGenRenderbuffers;
-        exts->DeleteRenderbuffers               = glDeleteRenderbuffers;
-        exts->FramebufferRenderbuffer           = glFramebufferRenderbuffer;
-        exts->BindRenderbuffer                  = glBindRenderbuffer;
-        exts->RenderbufferStorageMultisample    = glRenderbufferStorageMultisample;
-        exts->BlitFramebuffer                   = glBlitFramebuffer;
-        fboFound = true;
-    }
-    #endif
-    #if GL_ARB_framebuffer_object
-    if (!fboFound && has_gl_extension("GL_ARB_framebuffer_object")) {
-        // GL_ARB_framebuffer_object doesn't use ARB suffix.
-        GET_PROC(exts, GenFramebuffers);
-        GET_PROC(exts, BindFramebuffer);
-        GET_PROC(exts, FramebufferTexture2D);
-        GET_PROC(exts, CheckFramebufferStatus);
-        GET_PROC(exts, DeleteFramebuffers);
-        GET_PROC(exts, RenderbufferStorage);
-        GET_PROC(exts, GenRenderbuffers);
-        GET_PROC(exts, DeleteRenderbuffers);
-        GET_PROC(exts, FramebufferRenderbuffer);
-        GET_PROC(exts, BindRenderbuffer);
-        GET_PROC(exts, RenderbufferStorageMultisample);
-        GET_PROC(exts, BlitFramebuffer);
-        fboFound = true;
-    }
-    #endif
-    // Mac doesn't declare prototypes for EXT FBO extensions
-    #if GL_EXT_framebuffer_object && !GR_MAC_BUILD
-    if (!fboFound && has_gl_extension("GL_EXT_framebuffer_object")) {
-        GET_SUFFIX_PROC(exts, GenFramebuffers, EXT);
-        GET_SUFFIX_PROC(exts, BindFramebuffer, EXT);
-        GET_SUFFIX_PROC(exts, FramebufferTexture2D, EXT);
-        GET_SUFFIX_PROC(exts, CheckFramebufferStatus, EXT);
-        GET_SUFFIX_PROC(exts, DeleteFramebuffers, EXT);
-        GET_SUFFIX_PROC(exts, RenderbufferStorage, EXT);
-        GET_SUFFIX_PROC(exts, GenRenderbuffers, EXT);
-        GET_SUFFIX_PROC(exts, DeleteRenderbuffers, EXT);
-        GET_SUFFIX_PROC(exts, FramebufferRenderbuffer, EXT);
-        GET_SUFFIX_PROC(exts, BindRenderbuffer, EXT);
-        fboFound = true;
-        // check for fbo ms and fbo blit
-        #if GL_EXT_framebuffer_multisample
-        if (has_gl_extension("GL_EXT_framebuffer_multisample")) {
-            GET_SUFFIX_PROC(exts, RenderbufferStorageMultisample, EXT);
-        }
-        #endif
-        #if GL_EXT_framebuffer_blit
-        if (has_gl_extension("GL_EXT_framebuffer_blit")) {
-            GET_SUFFIX_PROC(exts, BlitFramebuffer, EXT);
-        }
-        #endif
-    }
-    #endif
-    if (!fboFound) {
-        // we require some form of FBO
-        GrAssert(!"No FBOs supported?");
-    }
-    // we assume we have at least GL 1.5 or higher (VBOs introduced in 1.5)
-    exts->MapBuffer     = glMapBuffer;
-    exts->UnmapBuffer   = glUnmapBuffer;
-#else // !GR_SUPPORT_GLDESKTOP
-    #if GR_SUPPORT_GLES2
-    if (!fboFound && major >= 2) {// ES 2.0 supports FBO
-        exts->GenFramebuffers                   = glGenFramebuffers;
-        exts->BindFramebuffer                   = glBindFramebuffer;
-        exts->FramebufferTexture2D              = glFramebufferTexture2D;
-        exts->CheckFramebufferStatus            = glCheckFramebufferStatus;
-        exts->DeleteFramebuffers                = glDeleteFramebuffers;
-        exts->RenderbufferStorage               = glRenderbufferStorage;
-        exts->GenRenderbuffers                  = glGenRenderbuffers;
-        exts->DeleteRenderbuffers               = glDeleteRenderbuffers;
-        exts->FramebufferRenderbuffer           = glFramebufferRenderbuffer;
-        exts->BindRenderbuffer                  = glBindRenderbuffer;
-        fboFound = true;
-    }
-    #endif
-    #if GL_OES_framebuffer_object
-    if (!fboFound && has_gl_extension("GL_OES_framebuffer_object")) {
-        GET_SUFFIX_PROC(exts, GenFramebuffers, OES);
-        GET_SUFFIX_PROC(exts, BindFramebuffer, OES);
-        GET_SUFFIX_PROC(exts, FramebufferTexture2D, OES);
-        GET_SUFFIX_PROC(exts, CheckFramebufferStatus, OES);
-        GET_SUFFIX_PROC(exts, DeleteFramebuffers, OES);
-        GET_SUFFIX_PROC(exts, RenderbufferStorage, OES);
-        GET_SUFFIX_PROC(exts, GenRenderbuffers, OES);
-        GET_SUFFIX_PROC(exts, DeleteRenderbuffers, OES);
-        GET_SUFFIX_PROC(exts, FramebufferRenderbuffer, OES);
-        GET_SUFFIX_PROC(exts, BindRenderbuffer, OES);
-    }
-    #endif
-
-    if (!fboFound) {
-        // we require some form of FBO
-        GrAssert(!"No FBOs supported?");
-    }
-
-    #if GL_APPLE_framebuffer_multisample
-    if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
-        GET_SUFFIX_PROC(exts, ResolveMultisampleFramebuffer, APPLE);
-    }
-    #endif
-
-    #if GL_IMG_multisampled_render_to_texture
-    if (has_gl_extension("GL_IMG_multisampled_render_to_texture")) {
-        GET_SUFFIX_PROC(exts, FramebufferTexture2DMultisample, IMG);
-    }
-    #endif
-
-    #if GL_OES_mapbuffer
-    if (has_gl_extension("GL_OES_mapbuffer")) {
-        GET_SUFFIX_PROC(exts, MapBuffer, OES);
-        GET_SUFFIX_PROC(exts, UnmapBuffer, OES);
-    }
-    #endif
-#endif // !GR_SUPPORT_GLDESKTOP
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
 
 void GrGLCheckErr(const char* location, const char* call) {
-    uint32_t err =  glGetError();
+    uint32_t err =  GrGLGetGLInterface()->fGetError();
     if (GL_NO_ERROR != err) {
         GrPrintf("---- glGetError %x", err);
         if (NULL != location) {
diff --git a/gpu/src/GrGLVertexBuffer.cpp b/gpu/src/GrGLVertexBuffer.cpp
index ec48936..69913bf 100644
--- a/gpu/src/GrGLVertexBuffer.cpp
+++ b/gpu/src/GrGLVertexBuffer.cpp
@@ -1,5 +1,5 @@
 /*
-    Copyright 2010 Google Inc.
+    Copyright 2011 Google Inc.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -57,8 +57,7 @@
         // Let driver know it can discard the old data
         GR_GL(BufferData(GL_ARRAY_BUFFER, size(), NULL,
                          dynamic() ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW));
-        fLockPtr = GR_GLEXT(fGL->extensions(),
-                            MapBuffer(GL_ARRAY_BUFFER, GR_WRITE_ONLY));
+        fLockPtr = GR_GL(MapBuffer(GL_ARRAY_BUFFER, GR_WRITE_ONLY));
         return fLockPtr;
     }
     return NULL;
@@ -74,7 +73,7 @@
     GrAssert(fGL->supportsBufferLocking());
 
     bind();
-    GR_GLEXT(fGL->extensions(), UnmapBuffer(GL_ARRAY_BUFFER));
+    GR_GL(UnmapBuffer(GL_ARRAY_BUFFER));
     fLockPtr = NULL;
 }
 
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index d41005b..2d763e2 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -56,6 +56,14 @@
     }
 }
 
+bool GrTexture::PixelConfigIsAlphaOnly(PixelConfig config) {
+    switch (config) {
+        case GrTexture::kAlpha_8_PixelConfig:
+            return true;
+        default:
+            return false;
+    }
+}
 
 ////////////////////////////////////////////////////////////////////////////////
 
diff --git a/gpu/src/GrGpuFactory.cpp b/gpu/src/GrGpuFactory.cpp
index 2298776..7c2db2b 100644
--- a/gpu/src/GrGpuFactory.cpp
+++ b/gpu/src/GrGpuFactory.cpp
@@ -1,5 +1,5 @@
 /*
-    Copyright 2010 Google Inc.
+    Copyright 2011 Google Inc.
 
     Licensed under the Apache License, Version 2.0 (the "License");
     you may not use this file except in compliance with the License.
@@ -36,6 +36,11 @@
 #include "GrGpu.h"
 
 GrGpu* GrGpu::Create(Engine engine, Platform3DContext context3D) {
+    // If no GL bindings have been installed, fall-back to calling the
+    // GL functions that have been linked with the executable.
+    if (!GrGLGetGLInterface())
+        GrGLSetDefaultGLInterface();
+
     GrGpu* gpu = NULL;
 
     switch (engine) {
diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp
index dc9b92d..f2a2a8f 100644
--- a/gpu/src/GrGpuGL.cpp
+++ b/gpu/src/GrGpuGL.cpp
@@ -45,8 +45,50 @@
     GL_ONE_MINUS_SRC_ALPHA,
     GL_DST_ALPHA,
     GL_ONE_MINUS_DST_ALPHA,
+    GL_CONSTANT_COLOR,
+    GL_ONE_MINUS_CONSTANT_COLOR,
+    GL_CONSTANT_ALPHA,
+    GL_ONE_MINUS_CONSTANT_ALPHA,
 };
 
+bool GrGpuGL::BlendCoefReferencesConstant(GrBlendCoeff coeff) {
+    static const bool gCoeffReferencesBlendConst[] = {
+        false,
+        false,
+        false,
+        false,
+        false,
+        false,
+        false,
+        false,
+        false,
+        false,
+        true,
+        true,
+        true,
+        true,
+    };
+    return gCoeffReferencesBlendConst[coeff];
+    GR_STATIC_ASSERT(kBlendCoeffCount == GR_ARRAY_COUNT(gCoeffReferencesBlendConst));
+}
+
+GR_STATIC_ASSERT(0 == kZero_BlendCoeff);
+GR_STATIC_ASSERT(1 == kOne_BlendCoeff);
+GR_STATIC_ASSERT(2 == kSC_BlendCoeff);
+GR_STATIC_ASSERT(3 == kISC_BlendCoeff);
+GR_STATIC_ASSERT(4 == kDC_BlendCoeff);
+GR_STATIC_ASSERT(5 == kIDC_BlendCoeff);
+GR_STATIC_ASSERT(6 == kSA_BlendCoeff);
+GR_STATIC_ASSERT(7 == kISA_BlendCoeff);
+GR_STATIC_ASSERT(8 == kDA_BlendCoeff);
+GR_STATIC_ASSERT(9 == kIDA_BlendCoeff);
+GR_STATIC_ASSERT(10 == kConstC_BlendCoeff);
+GR_STATIC_ASSERT(11 == kIConstC_BlendCoeff);
+GR_STATIC_ASSERT(12 == kConstA_BlendCoeff);
+GR_STATIC_ASSERT(13 == kIConstA_BlendCoeff);
+
+GR_STATIC_ASSERT(kBlendCoeffCount == GR_ARRAY_COUNT(gXfermodeCoeff2Blend));
+
 ///////////////////////////////////////////////////////////////////////////////
 
 void GrGpuGL::AdjustTextureMatrix(const GrGLTexture* texture,
@@ -103,8 +145,7 @@
 
 static bool gPrintStartupSpew;
 
-
-static bool fbo_test(GrGLExts exts, int w, int h) {
+static bool fbo_test(int w, int h) {
 
     GLint savedFBO;
     GLint savedTexUnit;
@@ -114,8 +155,8 @@
     GR_GL(ActiveTexture(GL_TEXTURE0 + SPARE_TEX_UNIT));
 
     GLuint testFBO;
-    GR_GLEXT(exts, GenFramebuffers(1, &testFBO));
-    GR_GLEXT(exts, BindFramebuffer(GR_FRAMEBUFFER, testFBO));
+    GR_GL(GenFramebuffers(1, &testFBO));
+    GR_GL(BindFramebuffer(GR_FRAMEBUFFER, testFBO));
     GLuint testRTTex;
     GR_GL(GenTextures(1, &testRTTex));
     GR_GL(BindTexture(GL_TEXTURE_2D, testRTTex));
@@ -125,14 +166,14 @@
     GR_GL(TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h,
                      0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
     GR_GL(BindTexture(GL_TEXTURE_2D, 0));
-    GR_GLEXT(exts, FramebufferTexture2D(GR_FRAMEBUFFER, GR_COLOR_ATTACHMENT0,
-                                        GL_TEXTURE_2D, testRTTex, 0));
-    GLenum status = GR_GLEXT(exts, CheckFramebufferStatus(GR_FRAMEBUFFER));
-    GR_GLEXT(exts, DeleteFramebuffers(1, &testFBO));
+    GR_GL(FramebufferTexture2D(GR_FRAMEBUFFER, GR_COLOR_ATTACHMENT0,
+                               GL_TEXTURE_2D, testRTTex, 0));
+    GLenum status = GR_GL(CheckFramebufferStatus(GR_FRAMEBUFFER));
+    GR_GL(DeleteFramebuffers(1, &testFBO));
     GR_GL(DeleteTextures(1, &testRTTex));
 
     GR_GL(ActiveTexture(savedTexUnit));
-    GR_GLEXT(exts, BindFramebuffer(GR_FRAMEBUFFER, savedFBO));
+    GR_GL(BindFramebuffer(GR_FRAMEBUFFER, savedFBO));
 
     return status == GR_FRAMEBUFFER_COMPLETE;
 }
@@ -142,16 +183,18 @@
     if (gPrintStartupSpew) {
         GrPrintf("------------------------- create GrGpuGL %p --------------\n",
                  this);
-        GrPrintf("------ VENDOR %s\n", glGetString(GL_VENDOR));
-        GrPrintf("------ RENDERER %s\n", glGetString(GL_RENDERER));
-        GrPrintf("------ VERSION %s\n", glGetString(GL_VERSION));
-        GrPrintf("------ EXTENSIONS\n %s \n", glGetString(GL_EXTENSIONS));
+        GrPrintf("------ VENDOR %s\n",
+                 GrGLGetGLInterface()->fGetString(GL_VENDOR));
+        GrPrintf("------ RENDERER %s\n",
+                 GrGLGetGLInterface()->fGetString(GL_RENDERER));
+        GrPrintf("------ VERSION %s\n",
+                 GrGLGetGLInterface()->fGetString(GL_VERSION));
+        GrPrintf("------ EXTENSIONS\n %s \n",
+                 GrGLGetGLInterface()->fGetString(GL_EXTENSIONS));
     }
 
     GrGLClearErr();
 
-    GrGLInitExtensions(&fExts);
-
     resetDirtyFlags();
 
     GLint maxTextureUnits;
@@ -329,7 +372,7 @@
 
     // sanity check to make sure we can at least create an FBO from a POT texture
 
-    bool simpleFBOSuccess = fbo_test(fExts, 128, 128);
+    bool simpleFBOSuccess = fbo_test(128, 128);
     if (gPrintStartupSpew) {
         if (!simpleFBOSuccess) {
             GrPrintf("FBO Sanity Test: FAILED\n");
@@ -348,7 +391,7 @@
      */
     bool fNPOTRenderTargetSupport = false;
     if (fNPOTTextureSupport) {
-        fNPOTRenderTargetSupport = fbo_test(fExts, 200, 200);
+        fNPOTRenderTargetSupport = fbo_test(200, 200);
     }
 
     if (gPrintStartupSpew) {
@@ -384,7 +427,7 @@
     for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? ++i : i *= 2) {
         GLuint w = maxRenderSize;
         GLuint h = i;
-        if (fbo_test(fExts, w, h)) {
+        if (fbo_test(w, h)) {
             if (gPrintStartupSpew) {
                 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
             }
@@ -405,7 +448,7 @@
     for (GLuint i = 1; i <= 256; fNPOTRenderTargetSupport ? i *= 2 : ++i) {
         GLuint w = i;
         GLuint h = maxRenderSize;
-        if (fbo_test(fExts, w, h)) {
+        if (fbo_test(w, h)) {
             if (gPrintStartupSpew) {
                 GrPrintf("\t[%d, %d]: PASSED\n", w, h);
             }
@@ -457,6 +500,10 @@
     // illegal values
     fHWDrawState.fSrcBlend = (GrBlendCoeff)-1;
     fHWDrawState.fDstBlend = (GrBlendCoeff)-1;
+
+    fHWDrawState.fBlendConstant = 0x00000000;
+    GR_GL(BlendColor(0,0,0,0));
+
     fHWDrawState.fColor = GrColor_ILLEGAL;
 
     fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix();
@@ -777,7 +824,7 @@
         GrAssert(NULL == srcData);
         glDesc.fOrientation =  GrGLTexture::kBottomUp_Orientation;
 
-        GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fTexFBOID));
+        GR_GL(GenFramebuffers(1, &rtIDs.fTexFBOID));
         GrAssert(rtIDs.fTexFBOID);
 
         // If we are using multisampling and any extension other than the IMG
@@ -785,16 +832,15 @@
         // the texture bound to the other. The IMG extension does an implicit
         // resolve.
         if (samples > 1 && kIMG_MSFBO != fMSFBOType && kNone_MSFBO != fMSFBOType) {
-            GR_GLEXT(fExts, GenFramebuffers(1, &rtIDs.fRTFBOID));
+            GR_GL(GenFramebuffers(1, &rtIDs.fRTFBOID));
             GrAssert(0 != rtIDs.fRTFBOID);
-            GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
+            GR_GL(GenRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
             GrAssert(0 != rtIDs.fMSColorRenderbufferID);
             if (!fboInternalFormat(desc.fFormat, &msColorRenderbufferFormat)) {
-                GR_GLEXT(fExts,
-                         DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
+                GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
                 GR_GL(DeleteTextures(1, &glDesc.fTextureID));
-                GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
-                GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
+                GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
+                GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
                 return return_null_texture();
             }
         } else {
@@ -802,7 +848,7 @@
         }
         int attempts = 1;
         if (!(kNoPathRendering_TextureFlag & desc.fFlags)) {
-            GR_GLEXT(fExts, GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
+            GR_GL(GenRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
             GrAssert(0 != rtIDs.fStencilRenderbufferID);
             attempts = GR_ARRAY_COUNT(gStencilFormats);
         }
@@ -815,21 +861,20 @@
         err = ~GL_NO_ERROR;
         for (int i = 0; i < attempts; ++i) {
             if (rtIDs.fStencilRenderbufferID) {
-                GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
-                                                 rtIDs.fStencilRenderbufferID));
+                GR_GL(BindRenderbuffer(GR_RENDERBUFFER,
+                                       rtIDs.fStencilRenderbufferID));
                 if (samples > 1) {
-                    GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
+                    GR_GL_NO_ERR(RenderbufferStorageMultisample(
                                                 GR_RENDERBUFFER,
                                                 samples,
                                                 gStencilFormats[i].fEnum,
                                                 glDesc.fAllocWidth,
                                                 glDesc.fAllocHeight));
                 } else {
-                    GR_GLEXT_NO_ERR(fExts, RenderbufferStorage(
-                                                GR_RENDERBUFFER,
-                                                gStencilFormats[i].fEnum,
-                                                glDesc.fAllocWidth,
-                                                glDesc.fAllocHeight));
+                    GR_GL_NO_ERR(RenderbufferStorage(GR_RENDERBUFFER,
+                                                     gStencilFormats[i].fEnum,
+                                                     glDesc.fAllocWidth,
+                                                     glDesc.fAllocHeight));
                 }
                 err = glGetError();
                 if (err != GL_NO_ERROR) {
@@ -838,9 +883,9 @@
             }
             if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
                 GrAssert(samples > 1);
-                GR_GLEXT(fExts, BindRenderbuffer(GR_RENDERBUFFER,
-                                                 rtIDs.fMSColorRenderbufferID));
-                GR_GLEXT_NO_ERR(fExts, RenderbufferStorageMultisample(
+                GR_GL(BindRenderbuffer(GR_RENDERBUFFER,
+                                       rtIDs.fMSColorRenderbufferID));
+                GR_GL_NO_ERR(RenderbufferStorageMultisample(
                                                    GR_RENDERBUFFER,
                                                    samples,
                                                    msColorRenderbufferFormat,
@@ -851,52 +896,50 @@
                     continue;
                 }
             }
-            GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fTexFBOID));
+            GR_GL(BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fTexFBOID));
 
 #if GR_COLLECT_STATS
             ++fStats.fRenderTargetChngCnt;
 #endif
             if (kIMG_MSFBO == fMSFBOType && samples > 1) {
-                GR_GLEXT(fExts, FramebufferTexture2DMultisample(
-                                                         GR_FRAMEBUFFER,
-                                                         GR_COLOR_ATTACHMENT0,
-                                                         GL_TEXTURE_2D,
-                                                         glDesc.fTextureID,
-                                                         0,
-                                                         samples));
+                GR_GL(FramebufferTexture2DMultisample(GR_FRAMEBUFFER,
+                                                      GR_COLOR_ATTACHMENT0,
+                                                      GL_TEXTURE_2D,
+                                                      glDesc.fTextureID,
+                                                      0,
+                                                      samples));
 
             } else {
-                GR_GLEXT(fExts, FramebufferTexture2D(GR_FRAMEBUFFER,
-                                                     GR_COLOR_ATTACHMENT0,
-                                                     GL_TEXTURE_2D,
-                                                     glDesc.fTextureID, 0));
+                GR_GL(FramebufferTexture2D(GR_FRAMEBUFFER,
+                                           GR_COLOR_ATTACHMENT0,
+                                           GL_TEXTURE_2D,
+                                           glDesc.fTextureID, 0));
             }
             if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
-                GLenum status = GR_GLEXT(fExts,
-                                         CheckFramebufferStatus(GR_FRAMEBUFFER));
+                GLenum status = GR_GL(CheckFramebufferStatus(GR_FRAMEBUFFER));
                 if (status != GR_FRAMEBUFFER_COMPLETE) {
                     GrPrintf("-- glCheckFramebufferStatus %x %d %d\n",
                              status, desc.fWidth, desc.fHeight);
                     continue;
                 }
-                GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fRTFBOID));
+                GR_GL(BindFramebuffer(GR_FRAMEBUFFER, rtIDs.fRTFBOID));
             #if GR_COLLECT_STATS
                 ++fStats.fRenderTargetChngCnt;
             #endif
-                GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
-                                                 GR_COLOR_ATTACHMENT0,
-                                                 GR_RENDERBUFFER,
-                                                 rtIDs.fMSColorRenderbufferID));
+                GR_GL(FramebufferRenderbuffer(GR_FRAMEBUFFER,
+                                              GR_COLOR_ATTACHMENT0,
+                                              GR_RENDERBUFFER,
+                                              rtIDs.fMSColorRenderbufferID));
 
             }
             if (rtIDs.fStencilRenderbufferID) {
                 // bind the stencil to rt fbo if present, othewise the tex fbo
-                GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
-                                                 GR_STENCIL_ATTACHMENT,
-                                                 GR_RENDERBUFFER,
-                                                 rtIDs.fStencilRenderbufferID));
+                GR_GL(FramebufferRenderbuffer(GR_FRAMEBUFFER,
+                                              GR_STENCIL_ATTACHMENT,
+                                              GR_RENDERBUFFER,
+                                              rtIDs.fStencilRenderbufferID));
             }
-            status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
+            status = GR_GL(CheckFramebufferStatus(GR_FRAMEBUFFER));
 
 #if GR_SUPPORT_GLDESKTOP
             // On some implementations you have to be bound as DEPTH_STENCIL.
@@ -904,16 +947,15 @@
             // buffer doesn't work.)
             if (rtIDs.fStencilRenderbufferID &&
                 status != GR_FRAMEBUFFER_COMPLETE) {
-                GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
-                                                        GR_STENCIL_ATTACHMENT,
-                                                        GR_RENDERBUFFER,
-                                                        0));
-                GR_GLEXT(fExts,
-                         FramebufferRenderbuffer(GR_FRAMEBUFFER,
-                                                 GR_DEPTH_STENCIL_ATTACHMENT,
-                                                 GR_RENDERBUFFER,
-                                                 rtIDs.fStencilRenderbufferID));
-                status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
+                GR_GL(FramebufferRenderbuffer(GR_FRAMEBUFFER,
+                                              GR_STENCIL_ATTACHMENT,
+                                              GR_RENDERBUFFER,
+                                              0));
+                GR_GL(FramebufferRenderbuffer(GR_FRAMEBUFFER,
+                                              GR_DEPTH_STENCIL_ATTACHMENT,
+                                              GR_RENDERBUFFER,
+                                              rtIDs.fStencilRenderbufferID));
+                status = GR_GL(CheckFramebufferStatus(GR_FRAMEBUFFER));
             }
 #endif
             if (status != GR_FRAMEBUFFER_COMPLETE) {
@@ -921,10 +963,10 @@
                          status, desc.fWidth, desc.fHeight);
 #if GR_SUPPORT_GLDESKTOP
                 if (rtIDs.fStencilRenderbufferID) {
-                    GR_GLEXT(fExts, FramebufferRenderbuffer(GR_FRAMEBUFFER,
-                                                     GR_DEPTH_STENCIL_ATTACHMENT,
-                                                     GR_RENDERBUFFER,
-                                                     0));
+                    GR_GL(FramebufferRenderbuffer(GR_FRAMEBUFFER,
+                                                  GR_DEPTH_STENCIL_ATTACHMENT,
+                                                  GR_RENDERBUFFER,
+                                                  0));
                 }
 #endif
                 continue;
@@ -942,18 +984,16 @@
         }
         if (failed) {
             if (rtIDs.fStencilRenderbufferID) {
-                GR_GLEXT(fExts,
-                         DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
+                GR_GL(DeleteRenderbuffers(1, &rtIDs.fStencilRenderbufferID));
             }
             if (rtIDs.fMSColorRenderbufferID) {
-                GR_GLEXT(fExts,
-                         DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
+                GR_GL(DeleteRenderbuffers(1, &rtIDs.fMSColorRenderbufferID));
             }
             if (rtIDs.fRTFBOID != rtIDs.fTexFBOID) {
-                GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fRTFBOID));
+                GR_GL(DeleteFramebuffers(1, &rtIDs.fRTFBOID));
             }
             if (rtIDs.fTexFBOID) {
-                GR_GLEXT(fExts, DeleteFramebuffers(1, &rtIDs.fTexFBOID));
+                GR_GL(DeleteFramebuffers(1, &rtIDs.fTexFBOID));
             }
             GR_GL(DeleteTextures(1, &glDesc.fTextureID));
             return return_null_texture();
@@ -1169,13 +1209,13 @@
 
     if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) {
         GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget;
-        GR_GLEXT(fExts, BindFramebuffer(GR_FRAMEBUFFER, rt->renderFBOID()));
+        GR_GL(BindFramebuffer(GR_FRAMEBUFFER, rt->renderFBOID()));
     #if GR_COLLECT_STATS
         ++fStats.fRenderTargetChngCnt;
     #endif
         rt->setDirty(true);
     #if GR_DEBUG
-        GLenum status = GR_GLEXT(fExts, CheckFramebufferStatus(GR_FRAMEBUFFER));
+        GLenum status = GR_GL(CheckFramebufferStatus(GR_FRAMEBUFFER));
         if (status != GR_FRAMEBUFFER_COMPLETE) {
             GrPrintf("-- glCheckFramebufferStatus %x\n", status);
         }
@@ -1287,9 +1327,9 @@
     if (NULL != rt && rt->needsResolve()) {
         GrAssert(kNone_MSFBO != fMSFBOType);
         GrAssert(rt->textureFBOID() != rt->renderFBOID());
-        GR_GLEXT(fExts, BindFramebuffer(GR_READ_FRAMEBUFFER,
+        GR_GL(BindFramebuffer(GR_READ_FRAMEBUFFER,
                                         rt->renderFBOID()));
-        GR_GLEXT(fExts, BindFramebuffer(GR_DRAW_FRAMEBUFFER,
+        GR_GL(BindFramebuffer(GR_DRAW_FRAMEBUFFER,
                                         rt->textureFBOID()));
     #if GR_COLLECT_STATS
         ++fStats.fRenderTargetChngCnt;
@@ -1305,11 +1345,11 @@
         if (kApple_MSFBO == fMSFBOType) {
             GR_GL(Enable(GL_SCISSOR_TEST));
             GR_GL(Scissor(left, bottom, right-left, top-bottom));
-            GR_GLEXT(fExts, ResolveMultisampleFramebuffer());
+            GR_GL(ResolveMultisampleFramebuffer());
             fHWBounds.fScissorRect.invalidate();
             fHWBounds.fScissorEnabled = true;
         } else {
-            GR_GLEXT(fExts, BlitFramebuffer(left, bottom, right, top,
+            GR_GL(BlitFramebuffer(left, bottom, right, top,
                                      left, bottom, right, top,
                                      GL_COLOR_BUFFER_BIT, GL_NEAREST));
         }
@@ -1621,6 +1661,19 @@
             fHWDrawState.fSrcBlend = fCurrDrawState.fSrcBlend;
             fHWDrawState.fDstBlend = fCurrDrawState.fDstBlend;
         }
+        if ((BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
+             BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) &&
+            fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) {
+
+            float c[] = {
+                GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f,
+                GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f,
+                GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f,
+                GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f
+            };
+            GR_GL(BlendColor(c[0], c[1], c[2], c[3]));
+            fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant;
+        }
     }
 
     if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) {
diff --git a/gpu/src/GrGpuGL.h b/gpu/src/GrGpuGL.h
index f9a6987..ea0c081 100644
--- a/gpu/src/GrGpuGL.h
+++ b/gpu/src/GrGpuGL.h
@@ -31,14 +31,6 @@
             GrGpuGL();
     virtual ~GrGpuGL();
 
-    /**
-     * Gets the struct containing the GL extensions for the context
-     * underlying the GrGpuGL
-     *
-     * @param struct containing extension function pointers
-     */
-    const GrGLExts& extensions() { return fExts; }
-
 protected:
     struct {
         size_t                  fVertexOffset;
@@ -72,8 +64,6 @@
         GrGLIRect   fViewportRect;
     } fHWBounds;
 
-    GrGLExts fExts;
-
     // GrGpu overrides
     // overrides from GrGpu
     virtual void resetContext();
@@ -142,6 +132,8 @@
     static bool TextureMatrixIsIdentity(const GrGLTexture* texture,
                                         const GrSamplerState& sampler);
 
+    static bool BlendCoefReferencesConstant(GrBlendCoeff coeff);
+
 private:
     // notify callbacks to update state tracking when related
     // objects are bound to GL or deleted outside of the class
diff --git a/gpu/src/GrGpuGLFixed.cpp b/gpu/src/GrGpuGLFixed.cpp
index 695b22c..afd9bb6 100644
--- a/gpu/src/GrGpuGLFixed.cpp
+++ b/gpu/src/GrGpuGLFixed.cpp
@@ -137,6 +137,14 @@
         }
     }
 
+#if GR_SUPPORT_GLES1
+    if (BlendCoefReferencesConstant(fCurrDrawState.fSrcBlend) ||
+        BlendCoefReferencesConstant(fCurrDrawState.fDstBlend)) {
+        uimpl("ES1 doesn't support blend constant");
+        return false;
+    }
+#endif
+
     if (!flushGLStateCommon(type)) {
         return false;
     }
diff --git a/gpu/src/GrTextContext.cpp b/gpu/src/GrTextContext.cpp
index 6819bde..2230af2 100644
--- a/gpu/src/GrTextContext.cpp
+++ b/gpu/src/GrTextContext.cpp
@@ -46,6 +46,25 @@
         int nIndices = fCurrVertex + (fCurrVertex >> 1);
         GrAssert(fCurrTexture);
         fDrawTarget->setTexture(TEXT_STAGE, fCurrTexture);
+
+        if (!GrTexture::PixelConfigIsAlphaOnly(fCurrTexture->config())) {
+            if (kOne_BlendCoeff != fPaint.fSrcBlendCoeff ||
+                kISA_BlendCoeff != fPaint.fDstBlendCoeff ||
+                NULL != fPaint.getTexture()) {
+                GrPrintf("LCD Text will not draw correctly.\n");
+            }
+            // setup blend so that we get mask * paintColor + (1-mask)*dstColor
+            fDrawTarget->setBlendConstant(fPaint.fColor);
+            fDrawTarget->setBlendFunc(kConstC_BlendCoeff, kISC_BlendCoeff);
+            // don't modulate by the paint's color in the frag since we're
+            // already doing it via the blend const.
+            fDrawTarget->setColor(0xffffffff);
+        } else {
+            // set back to normal in case we took LCD path previously.
+            fDrawTarget->setBlendFunc(fPaint.fSrcBlendCoeff, fPaint.fDstBlendCoeff);
+            fDrawTarget->setColor(fPaint.fColor);
+        }
+
         fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
 
         fDrawTarget->drawIndexed(kTriangles_PrimitiveType,
diff --git a/gpu/src/GrTextStrike.cpp b/gpu/src/GrTextStrike.cpp
index c2d81d5..6cdb61c 100644
--- a/gpu/src/GrTextStrike.cpp
+++ b/gpu/src/GrTextStrike.cpp
@@ -41,7 +41,8 @@
     if (NULL == fAtlasMgr) {
         fAtlasMgr = new GrAtlasMgr(fGpu);
     }
-    GrTextStrike* strike = new GrTextStrike(this, scaler->getKey(), fAtlasMgr);
+    GrTextStrike* strike = new GrTextStrike(this, scaler->getKey(),
+                                            scaler->getMaskFormat(), fAtlasMgr);
     fCache.insert(key, strike);
 
     if (fHead) {
@@ -131,6 +132,7 @@
  */
 
 GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key,
+                           GrMaskFormat format,
                            GrAtlasMgr* atlasMgr) : fPool(64) {
     fFontScalerKey = key;
     fFontScalerKey->ref();
@@ -139,6 +141,8 @@
     fAtlasMgr = atlasMgr;   // no need to ref, it won't go away before we do
     fAtlas = NULL;
 
+    fMaskFormat = format;
+
 #if GR_DEBUG
     GrPrintf(" GrTextStrike %p %d\n", this, gCounter);
     gCounter += 1;
@@ -180,17 +184,20 @@
     }
 
     GrAutoRef ar(scaler);
-    
-    size_t size = glyph->fBounds.area();
+
+    int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat);
+    size_t size = glyph->fBounds.area() * bytesPerPixel;
     GrAutoSMalloc<1024> storage(size);
     if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(),
-                                     glyph->height(), glyph->width(),
+                                     glyph->height(),
+                                     glyph->width() * bytesPerPixel,
                                      storage.get())) {
         return false;
     }
 
     GrAtlas* atlas = fAtlasMgr->addToAtlas(fAtlas, glyph->width(),
                                            glyph->height(), storage.get(),
+                                           fMaskFormat,
                                            &glyph->fAtlasLocation);
     if (NULL == atlas) {
         return false;
diff --git a/gpu/src/gr_files.mk b/gpu/src/gr_files.mk
index d0f41e7..8aeddc9 100644
--- a/gpu/src/gr_files.mk
+++ b/gpu/src/gr_files.mk
@@ -5,6 +5,7 @@
     GrContext.cpp \
     GrDrawTarget.cpp \
     GrGLIndexBuffer.cpp	\
+    GrGLInterface.cpp \
     GrGLTexture.cpp \
     GrGLVertexBuffer.cpp \
     GrGpu.cpp \
diff --git a/include/config/SkUserConfig.h b/include/config/SkUserConfig.h
new file mode 100644
index 0000000..13169ca
--- /dev/null
+++ b/include/config/SkUserConfig.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SkUserConfig_DEFINED
+#define SkUserConfig_DEFINED
+
+/*  SkTypes.h, the root of the public header files, does the following trick:
+
+    #include "SkPreConfig.h"
+    #include "SkUserConfig.h"
+    #include "SkPostConfig.h"
+
+    SkPreConfig.h runs first, and it is responsible for initializing certain
+    skia defines.
+
+    SkPostConfig.h runs last, and its job is to just check that the final
+    defines are consistent (i.e. that we don't have mutually conflicting
+    defines).
+
+    SkUserConfig.h (this file) runs in the middle. It gets to change or augment
+    the list of flags initially set in preconfig, and then postconfig checks
+    that everything still makes sense.
+
+    Below are optional defines that add, subtract, or change default behavior
+    in Skia. Your port can locally edit this file to enable/disable flags as
+    you choose, or these can be delared on your command line (i.e. -Dfoo).
+
+    By default, this include file will always default to having all of the flags
+    commented out, so including it will have no effect.
+*/
+
+///////////////////////////////////////////////////////////////////////////////
+
+/*  Scalars (the fractional value type in skia) can be implemented either as
+    floats or 16.16 integers (fixed). Exactly one of these two symbols must be
+    defined.
+*/
+//#define SK_SCALAR_IS_FLOAT
+//#define SK_SCALAR_IS_FIXED
+
+
+/*  Somewhat independent of how SkScalar is implemented, Skia also wants to know
+    if it can use floats at all. Naturally, if SK_SCALAR_IS_FLOAT is defined,
+    then so muse SK_CAN_USE_FLOAT, but if scalars are fixed, SK_CAN_USE_FLOAT
+    can go either way.
+ */
+//#define SK_CAN_USE_FLOAT
+
+/*  For some performance-critical scalar operations, skia will optionally work
+    around the standard float operators if it knows that the CPU does not have
+    native support for floats. If your environment uses software floating point,
+    define this flag.
+ */
+//#define SK_SOFTWARE_FLOAT
+
+
+/*  Skia has lots of debug-only code. Often this is just null checks or other
+    parameter checking, but sometimes it can be quite intrusive (e.g. check that
+    each 32bit pixel is in premultiplied form). This code can be very useful
+    during development, but will slow things down in a shipping product.
+
+    By default, these mutually exclusive flags are defined in SkPreConfig.h,
+    based on the presence or absence of NDEBUG, but that decision can be changed
+    here.
+ */
+//#define SK_DEBUG
+//#define SK_RELEASE
+
+
+/*  If, in debugging mode, Skia needs to stop (presumably to invoke a debugger)
+    it will call SK_CRASH(). If this is not defined it, it is defined in
+    SkPostConfig.h to write to an illegal address
+ */
+//#define SK_CRASH() *(int *)(uintptr_t)0 = 0
+
+
+/*  preconfig will have attempted to determine the endianness of the system,
+    but you can change these mutually exclusive flags here.
+ */
+//#define SK_CPU_BENDIAN
+//#define SK_CPU_LENDIAN
+
+
+/*  Some compilers don't support long long for 64bit integers. If yours does
+    not, define this to the appropriate type.
+ */
+//#define SkLONGLONG int64_t
+
+
+/*  Some envorinments do not suport writable globals (eek!). If yours does not,
+    define this flag.
+ */
+//#define SK_USE_RUNTIME_GLOBALS
+
+
+/*  To write debug messages to a console, skia will call SkDebugf(...) following
+    printf conventions (e.g. const char* format, ...). If you want to redirect
+    this to something other than printf, define yours here
+ */
+//#define SkDebugf(...)  MyFunction(__VA_ARGS__)
+
+/*  To enable additional blitters (and fontscaler code) to support separate
+    alpha channels for R G B channels, define SK_SUPPORT_LCDTEXT
+ */
+//#define SK_SUPPORT_LCDTEXT
+
+/*  If zlib is available and you want to support the flate compression
+    algorithm (used in PDF generation), define SK_ZLIB_INCLUDE to be the
+    include path.
+ */
+//#define SK_ZLIB_INCLUDE <zlib.h>
+
+/*  Define this to allow PDF scalars above 32k.  The PDF/A spec doesn't allow
+    them, but modern PDF interpreters should handle them just fine.
+ */
+//#define SK_ALLOW_LARGE_PDF_SCALARS
+
+/*  Define this to remove dimension checks on bitmaps. Not all blits will be
+    correct yet, so this is mostly for debugging the implementation.
+ */
+//#define SK_ALLOW_OVER_32K_BITMAPS
+
+/*  If SK_DEBUG is defined, then you can optionally define SK_SUPPORT_UNITTEST
+    which will run additional self-tests at startup. These can take a long time,
+    so this flag is optional.
+ */
+#ifdef SK_DEBUG
+//#define SK_SUPPORT_UNITTEST
+#endif
+
+#endif
+
diff --git a/include/core/SkBitmap.h b/include/core/SkBitmap.h
index 1d21a2f..349489e 100644
--- a/include/core/SkBitmap.h
+++ b/include/core/SkBitmap.h
@@ -40,7 +40,7 @@
     Bitmaps can be drawn into a SkCanvas, but they are also used to specify the target
     of a SkCanvas' drawing operations.
 */
-class SkBitmap {
+class SK_API SkBitmap {
 public:
     class Allocator;
 
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h
index 5aecacb..0a1b393 100644
--- a/include/core/SkCanvas.h
+++ b/include/core/SkCanvas.h
@@ -51,7 +51,7 @@
     color, typeface, textSize, strokeWidth, shader (e.g. gradients, patterns),
     etc.
 */
-class SkCanvas : public SkRefCnt {
+class SK_API SkCanvas : public SkRefCnt {
 public:
     /** Construct a canvas with the given device factory.
         @param factory  Specify the factory for generating additional devices.
@@ -758,7 +758,7 @@
         call made on the canvas. Ownership of all pointers in the iterator stays
         with the canvas, so none of them should be modified or deleted.
     */
-    class LayerIter /*: SkNoncopyable*/ {
+    class SK_API LayerIter /*: SkNoncopyable*/ {
     public:
         /** Initialize iterator with canvas, and set values for 1st device */
         LayerIter(SkCanvas*, bool skipEmptyClips);
diff --git a/include/core/SkClipStack.h b/include/core/SkClipStack.h
index db42e4d..850a3f0 100644
--- a/include/core/SkClipStack.h
+++ b/include/core/SkClipStack.h
@@ -7,7 +7,7 @@
 struct SkRect;
 class SkPath;
 
-class SkClipStack {
+class SK_API SkClipStack {
 public:
     SkClipStack();
     ~SkClipStack() {}
diff --git a/include/core/SkColor.h b/include/core/SkColor.h
index c17068f..6b86e7e 100644
--- a/include/core/SkColor.h
+++ b/include/core/SkColor.h
@@ -152,12 +152,12 @@
 
 /** Return a SkPMColor value from unpremultiplied 8 bit component values
 */
-SkPMColor SkPreMultiplyARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
+SK_API SkPMColor SkPreMultiplyARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
 /** Return a SkPMColor value from a SkColor value. This is done by multiplying the color
     components by the color's alpha, and by arranging the bytes in a configuration
     dependent order, to match the format of kARGB32 bitmaps.
 */
-SkPMColor SkPreMultiplyColor(SkColor c);
+SK_API SkPMColor SkPreMultiplyColor(SkColor c);
 
 /** Define a function pointer type for combining two premultiplied colors
 */
diff --git a/include/core/SkColorPriv.h b/include/core/SkColorPriv.h
index bd407da..f9e02a2 100644
--- a/include/core/SkColorPriv.h
+++ b/include/core/SkColorPriv.h
@@ -234,7 +234,7 @@
            (g << SK_G32_SHIFT) | (b << SK_B32_SHIFT);
 }
 
-extern const uint32_t gMask_00FF00FF;
+SK_API extern const uint32_t gMask_00FF00FF;
 
 static inline uint32_t SkAlphaMulQ(uint32_t c, unsigned scale) {
     uint32_t mask = gMask_00FF00FF;
diff --git a/include/core/SkColorShader.h b/include/core/SkColorShader.h
index f7251ff..b7537e1 100644
--- a/include/core/SkColorShader.h
+++ b/include/core/SkColorShader.h
@@ -24,7 +24,7 @@
     accomplished by just using the color field on the paint, but if an
     actual shader object is needed, this provides that feature.
 */
-class SkColorShader : public SkShader {
+class SK_API SkColorShader : public SkShader {
 public:
     /** Create a ColorShader that will inherit its color from the Paint
         at draw time.
diff --git a/include/core/SkDeque.h b/include/core/SkDeque.h
index 92d5153..8bf8b5b 100644
--- a/include/core/SkDeque.h
+++ b/include/core/SkDeque.h
@@ -19,7 +19,7 @@
 
 #include "SkTypes.h"
 
-class SkDeque : SkNoncopyable {
+class SK_API SkDeque : SkNoncopyable {
 public:
     explicit SkDeque(size_t elemSize);
     SkDeque(size_t elemSize, void* storage, size_t storageSize);
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index 55d823b..2f95015 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -49,7 +49,7 @@
                                 int height, bool isOpaque, bool isLayer);
 };
 
-class SkDevice : public SkRefCnt {
+class SK_API SkDevice : public SkRefCnt {
 public:
     SkDevice(SkCanvas*);
     /** Construct a new device, extracting the width/height/config/isOpaque values from
@@ -214,6 +214,21 @@
 
     SkRefDict& getRefDict() { return fRefDict; }
 
+    struct TextFlags {
+        uint32_t            fFlags;     // SkPaint::getFlags()
+        SkPaint::Hinting    fHinting;
+    };
+
+    /**
+     *  Device may filter the text flags for drawing text here. If it wants to
+     *  make a change to the specified values, it should write them into the
+     *  textflags parameter (output) and return true. If the paint is fine as
+     *  is, then ignore the textflags parameter and return false.
+     *
+     *  The baseclass SkDevice filters based on its depth and blitters.
+     */
+    virtual bool filterTextFlags(const SkPaint& paint, TextFlags*);
+
 protected:
     /** Update as needed the pixel value in the bitmap, so that the caller can access
         the pixels directly. Note: only the pixels field should be altered. The config/width/height/rowbytes
diff --git a/include/core/SkDrawLooper.h b/include/core/SkDrawLooper.h
index 333fb41..87eb5cb 100644
--- a/include/core/SkDrawLooper.h
+++ b/include/core/SkDrawLooper.h
@@ -32,7 +32,7 @@
     invoked multiple times (hence the name loop-er), allow it to perform effects
     like shadows or frame/fills, that require more than one pass.
 */
-class SkDrawLooper : public SkFlattenable {
+class SK_API SkDrawLooper : public SkFlattenable {
 public:
     /** Called right before something is being drawn to the specified canvas
         with the specified paint. Subclass that want to modify either parameter
diff --git a/include/core/SkFlattenable.h b/include/core/SkFlattenable.h
index 6958462..ad4062f 100644
--- a/include/core/SkFlattenable.h
+++ b/include/core/SkFlattenable.h
@@ -33,7 +33,7 @@
  into a data stream for either transport or as part of the key to the
  font cache.
  */
-class SkFlattenable : public SkRefCnt {
+class SK_API SkFlattenable : public SkRefCnt {
 public:
     typedef SkFlattenable* (*Factory)(SkFlattenableReadBuffer&);
     
diff --git a/include/core/SkFloatBits.h b/include/core/SkFloatBits.h
index 1628f6e..288f2d8 100644
--- a/include/core/SkFloatBits.h
+++ b/include/core/SkFloatBits.h
@@ -51,17 +51,17 @@
 /** Given the bit representation of a float, return its floor as an int.
     If the value is out of range, or NaN, return return +/- SK_MaxS32
  */
-int32_t SkFloatBits_toIntFloor(int32_t floatBits);
+SK_API int32_t SkFloatBits_toIntFloor(int32_t floatBits);
 
 /** Given the bit representation of a float, return it rounded to an int.
     If the value is out of range, or NaN, return return +/- SK_MaxS32
  */
-int32_t SkFloatBits_toIntRound(int32_t floatBits);
+SK_API int32_t SkFloatBits_toIntRound(int32_t floatBits);
 
 /** Given the bit representation of a float, return its ceiling as an int.
     If the value is out of range, or NaN, return return +/- SK_MaxS32
  */
-int32_t SkFloatBits_toIntCeil(int32_t floatBits);
+SK_API int32_t SkFloatBits_toIntCeil(int32_t floatBits);
 
 
 #ifdef SK_CAN_USE_FLOAT
diff --git a/include/core/SkGeometry.h b/include/core/SkGeometry.h
index a209783..d4b13fb 100644
--- a/include/core/SkGeometry.h
+++ b/include/core/SkGeometry.h
@@ -90,7 +90,7 @@
     convert it into the cubic fitting the same curve. The new cubic
     curve is returned in dst[0..3].
 */
-void SkConvertQuadToCubic(const SkPoint src[3], SkPoint dst[4]);
+SK_API void SkConvertQuadToCubic(const SkPoint src[3], SkPoint dst[4]);
 
 ////////////////////////////////////////////////////////////////////////////////////////
 
diff --git a/include/core/SkMask.h b/include/core/SkMask.h
index 4d48376..ebb870f 100644
--- a/include/core/SkMask.h
+++ b/include/core/SkMask.h
@@ -142,8 +142,7 @@
     };
 
     static bool FormatIsLCD(Format fm) {
-        return kHorizontalLCD_Format == fm || kVerticalLCD_Format == fm ||
-               kLCD16_Format == fm;
+        return kHorizontalLCD_Format == fm || kVerticalLCD_Format == fm;
     }
 };
 
diff --git a/include/core/SkMatrix.h b/include/core/SkMatrix.h
index 5c82d78..5ba9223 100644
--- a/include/core/SkMatrix.h
+++ b/include/core/SkMatrix.h
@@ -28,7 +28,7 @@
     using either reset() - to construct an identity matrix, or one of the set
     functions (e.g. setTranslate, setRotate, etc.).
 */
-class SkMatrix {
+class SK_API SkMatrix {
 public:
     /** Enum of bit fields for the mask return by getType().
         Use this to identify the complexity of the matrix.
diff --git a/include/core/SkPaint.h b/include/core/SkPaint.h
index 3c847de..eec11cf 100644
--- a/include/core/SkPaint.h
+++ b/include/core/SkPaint.h
@@ -48,7 +48,7 @@
     The SkPaint class holds the style and color information about how to draw
     geometries, text and bitmaps.
 */
-class SkPaint {
+class SK_API SkPaint {
 public:
     SkPaint();
     SkPaint(const SkPaint& paint);
@@ -56,12 +56,11 @@
 
     SkPaint& operator=(const SkPaint&);
 
-    friend int operator==(const SkPaint& a, const SkPaint& b);
-    friend int operator!=(const SkPaint& a, const SkPaint& b)
-    {
+    SK_API friend int operator==(const SkPaint& a, const SkPaint& b);
+    friend int operator!=(const SkPaint& a, const SkPaint& b) {
         return !(a == b);
     }
-    
+
     void flatten(SkFlattenableWriteBuffer&) const;
     void unflatten(SkFlattenableReadBuffer&);
 
@@ -86,13 +85,11 @@
         kFull_Hinting          = 3,
     };
 
-    Hinting getHinting() const
-    {
+    Hinting getHinting() const {
         return static_cast<Hinting>(fHinting);
     }
 
-    void setHinting(Hinting hintingLevel)
-    {
+    void setHinting(Hinting hintingLevel) {
         if ((unsigned) hintingLevel != fHinting) {
             fGenerationID++;
             fHinting = hintingLevel;
@@ -133,34 +130,31 @@
     /** Helper for getFlags(), returning true if kAntiAlias_Flag bit is set
         @return true if the antialias bit is set in the paint's flags.
         */
-    bool isAntiAlias() const
-    {
+    bool isAntiAlias() const {
         return SkToBool(this->getFlags() & kAntiAlias_Flag);
     }
-    
+
     /** Helper for setFlags(), setting or clearing the kAntiAlias_Flag bit
         @param aa   true to enable antialiasing, false to disable it
         */
     void setAntiAlias(bool aa);
-    
+
     /** Helper for getFlags(), returning true if kDither_Flag bit is set
         @return true if the dithering bit is set in the paint's flags.
         */
-    bool isDither() const
-    {
+    bool isDither() const {
         return SkToBool(this->getFlags() & kDither_Flag);
     }
-    
+
     /** Helper for setFlags(), setting or clearing the kDither_Flag bit
         @param dither   true to enable dithering, false to disable it
         */
     void setDither(bool dither);
-    
+
     /** Helper for getFlags(), returning true if kLinearText_Flag bit is set
         @return true if the lineartext bit is set in the paint's flags
     */
-    bool isLinearText() const
-    {
+    bool isLinearText() const {
         return SkToBool(this->getFlags() & kLinearText_Flag);
     }
 
@@ -173,19 +167,17 @@
     /** Helper for getFlags(), returning true if kSubpixelText_Flag bit is set
         @return true if the lineartext bit is set in the paint's flags
     */
-    bool isSubpixelText() const
-    {
+    bool isSubpixelText() const {
         return SkToBool(this->getFlags() & kSubpixelText_Flag);
     }
-    
+
     /** Helper for setFlags(), setting or clearing the kSubpixelText_Flag
        bit @param subpixelText true to set the subpixelText bit in the paint's flags,
                                false to clear it.
     */
     void setSubpixelText(bool subpixelText);
 
-    bool isLCDRenderText() const
-    {
+    bool isLCDRenderText() const {
         return SkToBool(this->getFlags() & kLCDRenderText_Flag);
     }
 
@@ -195,8 +187,7 @@
     */
     void setLCDRenderText(bool subpixelRender);
 
-    bool isEmbeddedBitmapText() const
-    {
+    bool isEmbeddedBitmapText() const {
         return SkToBool(this->getFlags() & kEmbeddedBitmapText_Flag);
     }
 
@@ -206,8 +197,7 @@
     */
     void setEmbeddedBitmapText(bool useEmbeddedBitmapText);
 
-    bool isAutohinted() const
-    {
+    bool isAutohinted() const {
         return SkToBool(this->getFlags() & kAutoHinting_Flag);
     }
 
@@ -221,8 +211,7 @@
     /** Helper for getFlags(), returning true if kUnderlineText_Flag bit is set
         @return true if the underlineText bit is set in the paint's flags.
     */
-    bool isUnderlineText() const
-    {
+    bool isUnderlineText() const {
         return SkToBool(this->getFlags() & kUnderlineText_Flag);
     }
 
@@ -235,8 +224,7 @@
     /** Helper for getFlags(), returns true if kStrikeThruText_Flag bit is set
         @return true if the strikeThruText bit is set in the paint's flags.
     */
-    bool    isStrikeThruText() const
-    {
+    bool isStrikeThruText() const {
         return SkToBool(this->getFlags() & kStrikeThruText_Flag);
     }
 
@@ -249,8 +237,7 @@
     /** Helper for getFlags(), returns true if kFakeBoldText_Flag bit is set
         @return true if the kFakeBoldText_Flag bit is set in the paint's flags.
     */
-    bool isFakeBoldText() const
-    {
+    bool isFakeBoldText() const {
         return SkToBool(this->getFlags() & kFakeBoldText_Flag);
     }
 
@@ -263,8 +250,7 @@
     /** Helper for getFlags(), returns true if kDevKernText_Flag bit is set
         @return true if the kernText bit is set in the paint's flags.
     */
-    bool isDevKernText() const
-    {
+    bool isDevKernText() const {
         return SkToBool(this->getFlags() & kDevKernText_Flag);
     }
 
@@ -274,17 +260,16 @@
     */
     void setDevKernText(bool devKernText);
 
-    bool isFilterBitmap() const
-    {
+    bool isFilterBitmap() const {
         return SkToBool(this->getFlags() & kFilterBitmap_Flag);
     }
-    
+
     void setFilterBitmap(bool filterBitmap);
 
     /** Styles apply to rect, oval, path, and text.
         Bitmaps are always drawn in "fill", and lines are always drawn in
         "stroke".
-     
+
         Note: strokeandfill implicitly draws the result with
         SkPath::kWinding_FillType, so if the original path is even-odd, the
         results may not appear the same as if it was drawn twice, filled and
@@ -331,7 +316,7 @@
         @return the alpha component of the paint's color.
         */
     uint8_t getAlpha() const { return SkToU8(SkColorGetA(fColor)); }
-    
+
     /** Helper to setColor(), that only assigns the color's alpha value,
         leaving its r,g,b values unchanged.
         @param a    set the alpha component (0..255) of the paint's color.
@@ -347,7 +332,7 @@
     */
     void setARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b);
 
-    /** Return the width for stroking. 
+    /** Return the width for stroking.
         <p />
         A value of 0 strokes in hairline mode.
         Hairlines always draw 1-pixel wide, regardless of the matrix.
@@ -356,7 +341,7 @@
     */
     SkScalar getStrokeWidth() const { return fWidth; }
 
-    /** Set the width for stroking. 
+    /** Set the width for stroking.
         Pass 0 to stroke in hairline mode.
         Hairlines always draw 1-pixel wide, regardless of the matrix.
         @param width set the paint's stroke width, used whenever the paint's
@@ -457,12 +442,12 @@
         effects in the paint (e.g. stroking). If needed, it uses the storage
         rect parameter. It returns the adjusted bounds that can then be used
         for quickReject tests.
-     
+
         The returned rect will either be orig or storage, thus the caller
         should not rely on storage being set to the result, but should always
         use the retured value. It is legal for orig and storage to be the same
         rect.
-        
+
         e.g.
         if (paint.canComputeFastBounds()) {
             SkRect r, storage;
@@ -495,7 +480,7 @@
         @return         shader
     */
     SkShader* setShader(SkShader* shader);
-    
+
     /** Get the paint's colorfilter. If there is a colorfilter, its reference
         count is not changed.
         @return the paint's colorfilter (or NULL)
@@ -616,8 +601,24 @@
     */
     SkRasterizer* setRasterizer(SkRasterizer* rasterizer);
 
+    /**
+     *  Return the paint's SkDrawLooper (if any). Does not affect the looper's
+     *  reference count.
+     */
     SkDrawLooper* getLooper() const { return fLooper; }
-    SkDrawLooper* setLooper(SkDrawLooper*);
+
+    /**
+     *  Set or clear the looper object.
+     *  <p />
+     *  Pass NULL to clear any previous looper.
+     *  As a convenience, the parameter passed is also returned.
+     *  If a previous looper exists in the paint, its reference count is
+     *  decremented. If looper is not NULL, its reference count is
+     *  incremented.
+     *  @param looper May be NULL. The new looper to be installed in the paint.
+     *  @return looper
+     */
+    SkDrawLooper* setLooper(SkDrawLooper* looper);
 
     enum Align {
         kLeft_Align,
@@ -626,10 +627,12 @@
 
         kAlignCount
     };
+
     /** Return the paint's Align value for drawing text.
         @return the paint's Align value for drawing text.
     */
     Align   getTextAlign() const { return (Align)fTextAlign; }
+
     /** Set the paint's text alignment.
         @param align set the paint's Align value for drawing text.
     */
@@ -679,11 +682,8 @@
         kUTF16_TextEncoding,    //!< the text parameters are UTF16
         kGlyphID_TextEncoding   //!< the text parameters are glyph indices
     };
-    
-    TextEncoding getTextEncoding() const
-    {
-        return (TextEncoding)fTextEncoding;
-    }
+
+    TextEncoding getTextEncoding() const { return (TextEncoding)fTextEncoding; }
 
     void setTextEncoding(TextEncoding encoding);
 
@@ -698,11 +698,11 @@
         SkScalar    fXMax;      //!< The maximum bounding box x value for all glyphs
         SkScalar    fXHeight;   //!< the height of an 'x' in px, or 0 if no 'x' in face
     };
-    
+
     /** Return the recommend spacing between lines (which will be
         fDescent - fAscent + fLeading).
         If metrics is not null, return in it the font metrics for the
-        typeface/pointsize/etc. currently set in the paint. 
+        typeface/pointsize/etc. currently set in the paint.
         @param metrics      If not null, returns the font metrics for the
                             current typeface/pointsize/etc setting in this
                             paint.
@@ -711,7 +711,7 @@
         @param return the recommended spacing between lines
     */
     SkScalar getFontMetrics(FontMetrics* metrics, SkScalar scale = 0) const;
-    
+
     /** Return the recommend line spacing. This will be
         fDescent - fAscent + fLeading
     */
@@ -745,8 +745,7 @@
         want to have the text converted into glyph IDs, call textToGlyphs
         instead.
     */
-    int countText(const void* text, size_t byteLength) const
-    {
+    int countText(const void* text, size_t byteLength) const {
         return this->textToGlyphs(text, byteLength, NULL);
     }
 
@@ -759,19 +758,18 @@
                             by this value
         @return             The advance width of the text
     */
-    SkScalar    measureText(const void* text, size_t length,
-                            SkRect* bounds, SkScalar scale = 0) const;
+    SkScalar measureText(const void* text, size_t length,
+                         SkRect* bounds, SkScalar scale = 0) const;
 
     /** Return the width of the text.
         @param text         Address of the text
         @param length       Number of bytes of text to measure
         @return The width of the text
     */
-    SkScalar measureText(const void* text, size_t length) const
-    {
+    SkScalar measureText(const void* text, size_t length) const {
         return this->measureText(text, length, NULL, 0);
     }
-    
+
     /** Specify the direction the text buffer should be processed in breakText()
     */
     enum TextBufferDirection {
diff --git a/include/core/SkPath.h b/include/core/SkPath.h
index eb5ff6d..51afad7 100644
--- a/include/core/SkPath.h
+++ b/include/core/SkPath.h
@@ -30,7 +30,7 @@
     The SkPath class encapsulates compound (multiple contour) geometric paths
     consisting of straight line segments, quadratic curves, and cubic curves.
 */
-class SkPath {
+class SK_API SkPath {
 public:
     SkPath();
     SkPath(const SkPath&);
@@ -514,7 +514,7 @@
     /** Iterate through all of the segments (lines, quadratics, cubics) of
         each contours in a path.
     */
-    class Iter {
+    class SK_API Iter {
     public:
                 Iter();
                 Iter(const SkPath&, bool forceClose);
diff --git a/include/core/SkPathEffect.h b/include/core/SkPathEffect.h
index f97adb7..eb1cc23 100644
--- a/include/core/SkPathEffect.h
+++ b/include/core/SkPathEffect.h
@@ -29,7 +29,7 @@
 
     Dashing is implemented as a subclass of SkPathEffect.
 */
-class SkPathEffect : public SkFlattenable {
+class SK_API SkPathEffect : public SkFlattenable {
 public:
     //  This method is not exported to java.
     SkPathEffect() {}
diff --git a/include/core/SkPoint.h b/include/core/SkPoint.h
index 79ca58c..c89f080 100644
--- a/include/core/SkPoint.h
+++ b/include/core/SkPoint.h
@@ -140,7 +140,7 @@
     }
 };
 
-struct SkPoint {
+struct SK_API SkPoint {
     SkScalar    fX, fY;
 
     static SkPoint Make(SkScalar x, SkScalar y) {
diff --git a/include/core/SkPreConfig.h b/include/core/SkPreConfig.h
index f907578..daf2041 100644
--- a/include/core/SkPreConfig.h
+++ b/include/core/SkPreConfig.h
@@ -96,5 +96,21 @@
     #define SK_CPU_HAS_CONDITIONAL_INSTR
 #endif
 
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(SKIA_IMPLEMENTATION)
+    #define SKIA_IMPLEMENTATION 0
+#endif
+ 
+#if defined(WIN32) && defined(SKIA_DLL)
+    #if SKIA_IMPLEMENTATION
+        #define SK_API __declspec(dllexport)
+    #else
+        #define SK_API __declspec(dllimport)
+    #endif
+#else
+    #define SK_API
+#endif
+
 #endif
 
diff --git a/include/core/SkRect.h b/include/core/SkRect.h
index 114d1f9..53c61ea 100644
--- a/include/core/SkRect.h
+++ b/include/core/SkRect.h
@@ -24,7 +24,7 @@
 
     SkIRect holds four 32 bit integer coordinates for a rectangle
 */
-struct SkIRect {
+struct SK_API SkIRect {
     int32_t fLeft, fTop, fRight, fBottom;
 
     static SkIRect MakeEmpty() {
@@ -267,7 +267,7 @@
 
 /** \struct SkRect
 */
-struct SkRect {
+struct SK_API SkRect {
     SkScalar    fLeft, fTop, fRight, fBottom;
 
     static SkRect MakeEmpty() {
diff --git a/include/core/SkRefCnt.h b/include/core/SkRefCnt.h
index b9b2c98..36f4249 100644
--- a/include/core/SkRefCnt.h
+++ b/include/core/SkRefCnt.h
@@ -29,7 +29,7 @@
     explicitly (or via the object going out of scope on the stack or calling
     delete) if getRefCnt() > 1.
 */
-class SkRefCnt : SkNoncopyable {
+class SK_API SkRefCnt : SkNoncopyable {
 public:
     /** Default construct, initializing the reference count to 1.
     */
diff --git a/include/core/SkRefDict.h b/include/core/SkRefDict.h
index 3ee27d9..0c4b025 100644
--- a/include/core/SkRefDict.h
+++ b/include/core/SkRefDict.h
@@ -23,7 +23,7 @@
  *  A dictionary of string,refcnt pairs. The dictionary is also an owner of the
  *  refcnt objects while they are contained.
  */
-class SkRefDict : SkNoncopyable {
+class SK_API SkRefDict : SkNoncopyable {
 public:
     SkRefDict();
     ~SkRefDict();
diff --git a/include/core/SkRegion.h b/include/core/SkRegion.h
index 7ddf087..4cda2cd 100644
--- a/include/core/SkRegion.h
+++ b/include/core/SkRegion.h
@@ -34,7 +34,7 @@
     The SkRegion class encapsulates the geometric region used to specify
     clipping areas for drawing.
 */
-class SkRegion {
+class SK_API SkRegion {
 public:
     typedef int32_t RunType;
     enum {
@@ -258,7 +258,7 @@
     /** Returns the sequence of rectangles, sorted in Y and X, that make up
         this region.
     */
-    class Iterator {
+    class SK_API Iterator {
     public:
         Iterator() : fRgn(NULL), fDone(true) {}
         Iterator(const SkRegion&);
@@ -281,7 +281,7 @@
     /** Returns the sequence of rectangles, sorted in Y and X, that make up
         this region intersected with the specified clip rectangle.
     */
-    class Cliperator {
+    class SK_API Cliperator {
     public:
         Cliperator(const SkRegion&, const SkIRect& clip);
         bool            done() { return fDone; }
diff --git a/include/core/SkScalerContext.h b/include/core/SkScalerContext.h
index 584b86b..55dfcef 100644
--- a/include/core/SkScalerContext.h
+++ b/include/core/SkScalerContext.h
@@ -222,6 +222,10 @@
     SkScalerContext(const SkDescriptor* desc);
     virtual ~SkScalerContext();
 
+    SkMask::Format getMaskFormat() const {
+        return (SkMask::Format)fRec.fMaskFormat;
+    }
+
     // remember our glyph offset/base
     void setBaseGlyphCount(unsigned baseGlyphCount) {
         fBaseGlyphCount = baseGlyphCount;
diff --git a/include/core/SkShader.h b/include/core/SkShader.h
index c59cc59..d837284 100644
--- a/include/core/SkShader.h
+++ b/include/core/SkShader.h
@@ -32,7 +32,7 @@
     any object (other than a bitmap) that is drawn with that paint will get its color(s) from the
     shader.
 */
-class SkShader : public SkFlattenable {
+class SK_API SkShader : public SkFlattenable {
 public:
             SkShader();
     virtual ~SkShader();
diff --git a/include/core/SkTDArray.h b/include/core/SkTDArray.h
index 954bcf8..c64d773 100644
--- a/include/core/SkTDArray.h
+++ b/include/core/SkTDArray.h
@@ -19,7 +19,7 @@
 
 #include "SkTypes.h"
 
-template <typename T> class SkTDArray {
+template <typename T> class SK_API SkTDArray {
 public:
     SkTDArray() {
         fReserve = fCount = 0;
diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h
index f4b9507..c3b0f50 100644
--- a/include/core/SkTypeface.h
+++ b/include/core/SkTypeface.h
@@ -32,7 +32,7 @@
 
     Typeface objects are immutable, and so they can be shared between threads.
 */
-class SkTypeface : public SkRefCnt {
+class SK_API SkTypeface : public SkRefCnt {
 public:
     /** Style specifies the intrinsic style attributes of a given typeface
     */
diff --git a/include/core/SkTypes.h b/include/core/SkTypes.h
index 93f054e..1290935 100644
--- a/include/core/SkTypes.h
+++ b/include/core/SkTypes.h
@@ -59,7 +59,7 @@
     return null (if SK_MALLOC_TEMP bit is clear) or call sk_throw()
     (if SK_MALLOC_TEMP bit is set). To free the memory, call sk_free().
 */
-extern void* sk_malloc_flags(size_t size, unsigned flags);
+SK_API extern void* sk_malloc_flags(size_t size, unsigned flags);
 /** Same as sk_malloc(), but hard coded to pass SK_MALLOC_THROW as the flag
 */
 extern void* sk_malloc_throw(size_t size);
@@ -69,7 +69,7 @@
 extern void* sk_realloc_throw(void* buffer, size_t size);
 /** Free memory returned by sk_malloc(). It is safe to pass null.
 */
-extern void  sk_free(void*);
+SK_API extern void  sk_free(void*);
 
 // bzero is safer than memset, but we can't rely on it, so... sk_bzero()
 static inline void sk_bzero(void* buffer, size_t size) {
@@ -152,12 +152,12 @@
 typedef uint8_t SkBool8;
 
 #ifdef SK_DEBUG
-    int8_t      SkToS8(long);
-    uint8_t     SkToU8(size_t);
-    int16_t     SkToS16(long);
-    uint16_t    SkToU16(size_t);
-    int32_t     SkToS32(long);
-    uint32_t    SkToU32(size_t);
+    SK_API int8_t      SkToS8(long);
+    SK_API uint8_t     SkToU8(size_t);
+    SK_API int16_t     SkToS16(long);
+    SK_API uint16_t    SkToU16(size_t);
+    SK_API int32_t     SkToS32(long);
+    SK_API uint32_t    SkToU32(size_t);
 #else
     #define SkToS8(x)   ((int8_t)(x))
     #define SkToU8(x)   ((uint8_t)(x))
@@ -337,7 +337,7 @@
 SkNoncopyable is the base class for objects that may do not want to
 be copied. It hides its copy-constructor and its assignment-operator.
 */
-class SkNoncopyable {
+class SK_API SkNoncopyable {
 public:
     SkNoncopyable() {}
 
diff --git a/include/core/SkUnPreMultiply.h b/include/core/SkUnPreMultiply.h
index 4bdb980..44ea50e 100644
--- a/include/core/SkUnPreMultiply.h
+++ b/include/core/SkUnPreMultiply.h
@@ -22,7 +22,7 @@
 
 #include "SkColor.h"
 
-class SkUnPreMultiply {
+class SK_API SkUnPreMultiply {
 public:
     typedef uint32_t Scale;
     
diff --git a/include/core/SkXfermode.h b/include/core/SkXfermode.h
index 714468c..e954633 100644
--- a/include/core/SkXfermode.h
+++ b/include/core/SkXfermode.h
@@ -28,7 +28,7 @@
     specified in the Modes enum. When an SkXfermode is assigned to an SkPaint,
     then objects drawn with that paint have the xfermode applied.
 */
-class SkXfermode : public SkFlattenable {
+class SK_API SkXfermode : public SkFlattenable {
 public:
     SkXfermode() {}
 
diff --git a/include/effects/SkBlurDrawLooper.h b/include/effects/SkBlurDrawLooper.h
index e7af5c2..101d24e 100644
--- a/include/effects/SkBlurDrawLooper.h
+++ b/include/effects/SkBlurDrawLooper.h
@@ -28,7 +28,7 @@
     the original object in its original position.
     should there be an option to just draw the shadow/blur layer? webkit?
 */
-class SkBlurDrawLooper : public SkDrawLooper {
+class SK_API SkBlurDrawLooper : public SkDrawLooper {
 public:
     enum BlurFlags {
         kNone_BlurFlag = 0x00,
diff --git a/include/effects/SkCornerPathEffect.h b/include/effects/SkCornerPathEffect.h
index a459478..823de3f 100644
--- a/include/effects/SkCornerPathEffect.h
+++ b/include/effects/SkCornerPathEffect.h
@@ -24,7 +24,7 @@
     SkCornerPathEffect is a subclass of SkPathEffect that can turn sharp corners
     into various treatments (e.g. rounded corners)
 */
-class SkCornerPathEffect : public SkPathEffect {
+class SK_API SkCornerPathEffect : public SkPathEffect {
 public:
     /** radius must be > 0 to have an effect. It specifies the distance from each corner
         that should be "rounded".
diff --git a/include/effects/SkDashPathEffect.h b/include/effects/SkDashPathEffect.h
index cc414e3..145f67d 100644
--- a/include/effects/SkDashPathEffect.h
+++ b/include/effects/SkDashPathEffect.h
@@ -23,7 +23,7 @@
 
     SkDashPathEffect is a subclass of SkPathEffect that implements dashing
 */
-class SkDashPathEffect : public SkPathEffect {
+class SK_API SkDashPathEffect : public SkPathEffect {
 public:
     /** The intervals array must contain an even number of entries (>=2), with the even
         indices specifying the "on" intervals, and the odd indices specifying the "off"
diff --git a/include/effects/SkGradientShader.h b/include/effects/SkGradientShader.h
index c800c66..5623be4 100644
--- a/include/effects/SkGradientShader.h
+++ b/include/effects/SkGradientShader.h
@@ -26,7 +26,7 @@
     SkGradientShader hosts factories for creating subclasses of SkShader that
     render linear and radial gradients.
 */
-class SkGradientShader {
+class SK_API SkGradientShader {
 public:
     /** Returns a shader that generates a linear gradient between the two
         specified points.
diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h
index 3fed99a..8852803 100644
--- a/include/gpu/SkGpuDevice.h
+++ b/include/gpu/SkGpuDevice.h
@@ -109,6 +109,7 @@
                               const SkPaint& paint);
     virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
                             const SkPaint&);
+    virtual bool filterTextFlags(const SkPaint& paint, TextFlags*);
 
     virtual void flush() { fContext->flush(false); }
 
diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h
index 6f5ebfe..7221213 100644
--- a/include/gpu/SkGr.h
+++ b/include/gpu/SkGr.h
@@ -231,7 +231,7 @@
     SkGrRegionIterator() {}
     SkGrRegionIterator(const SkRegion& region) { this->reset(region); }
 
-    void reset(const SkRegion& region) { 
+    void reset(const SkRegion& region) {
         fRegion = &region;
         fIter.reset(region);
     }
@@ -275,6 +275,7 @@
 
     // overrides
     virtual const GrKey* getKey();
+    virtual GrMaskFormat getMaskFormat();
     virtual bool getPackedGlyphBounds(GrGlyph::PackedID, GrIRect* bounds);
     virtual bool getPackedGlyphImage(GrGlyph::PackedID, int width, int height,
                                      int rowBytes, void* image);
diff --git a/include/ports/SkTypeface_win.h b/include/ports/SkTypeface_win.h
index 95a7b8c..88678d1 100644
--- a/include/ports/SkTypeface_win.h
+++ b/include/ports/SkTypeface_win.h
@@ -25,7 +25,7 @@
  *  corresponding typeface for the specified logfont. The caller is responsible
  *  for calling unref() when it is finished.
  */
-extern SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT&);
+SK_API extern SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT&);
 
 #endif
 
diff --git a/src/core/SkBitmapProcState_filter.h b/src/core/SkBitmapProcState_filter.h
index 7b9b3e5..d187983 100644
--- a/src/core/SkBitmapProcState_filter.h
+++ b/src/core/SkBitmapProcState_filter.h
@@ -111,7 +111,7 @@
     SkASSERT((unsigned)y <= 0xF);
     
     int xy = x * y;
-    uint32_t mask = gMask_00FF00FF; //0xFF00FF;
+    static const uint32_t mask = gMask_00FF00FF; //0xFF00FF;
     
     int scale = 256 - 16*y - 16*x + xy;
     uint32_t lo = (a00 & mask) * scale;
@@ -141,7 +141,7 @@
     SkASSERT(alphaScale <= 256);
     
     int xy = x * y;
-    uint32_t mask = gMask_00FF00FF; //0xFF00FF;
+    static const uint32_t mask = gMask_00FF00FF; //0xFF00FF;
     
     int scale = 256 - 16*y - 16*x + xy;
     uint32_t lo = (a00 & mask) * scale;
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 2b7d588..a31623e 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1352,12 +1352,42 @@
     ITER_END
 }
 
+class SkDeviceFilteredPaint {
+public:
+    SkDeviceFilteredPaint(SkDevice* device, const SkPaint& paint) {
+        SkDevice::TextFlags flags;
+        if (device->filterTextFlags(paint, &flags)) {
+            SkPaint* newPaint = new (fStorage) SkPaint(paint);
+            newPaint->setFlags(flags.fFlags);
+            newPaint->setHinting(flags.fHinting);
+            fPaint = newPaint;
+        } else {
+            fPaint = &paint;
+        }
+    }
+
+    ~SkDeviceFilteredPaint() {
+        if (reinterpret_cast<SkPaint*>(fStorage) == fPaint) {
+            fPaint->~SkPaint();
+        }
+    }
+
+    const SkPaint& paint() const { return *fPaint; }
+
+private:
+    // points to either fStorage or the caller's paint
+    const SkPaint*  fPaint;
+    // we rely on the fPaint above to ensure proper alignment of fStorage
+    char            fStorage[sizeof(SkPaint)];
+};
+
 void SkCanvas::drawText(const void* text, size_t byteLength,
                         SkScalar x, SkScalar y, const SkPaint& paint) {
     ITER_BEGIN(paint, SkDrawFilter::kText_Type)
 
     while (iter.next()) {
-        iter.fDevice->drawText(iter, text, byteLength, x, y, paint);
+        SkDeviceFilteredPaint dfp(iter.fDevice, paint);
+        iter.fDevice->drawText(iter, text, byteLength, x, y, dfp.paint());
     }
 
     ITER_END
@@ -1368,8 +1398,9 @@
     ITER_BEGIN(paint, SkDrawFilter::kText_Type)
 
     while (iter.next()) {
+        SkDeviceFilteredPaint dfp(iter.fDevice, paint);
         iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
-                                  paint);
+                                  dfp.paint());
     }
 
     ITER_END
@@ -1381,8 +1412,9 @@
     ITER_BEGIN(paint, SkDrawFilter::kText_Type)
 
     while (iter.next()) {
+        SkDeviceFilteredPaint dfp(iter.fDevice, paint);
         iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
-                                  paint);
+                                  dfp.paint());
     }
 
     ITER_END
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index 619a371..8231848 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -178,6 +178,32 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+bool SkDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
+    if (!paint.isLCDRenderText()) {
+        // we're cool with the paint as is
+        return false;
+    }
+
+    if (SkBitmap::kARGB_8888_Config != fBitmap.config() ||
+        paint.getShader() ||
+        paint.getXfermode() || // unless its srcover
+        paint.getMaskFilter() ||
+        paint.getRasterizer() ||
+        paint.getColorFilter() ||
+        paint.getPathEffect() ||
+        paint.isFakeBoldText() ||
+        paint.getStyle() != SkPaint::kFill_Style) {
+        // turn off lcd
+        flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
+        flags->fHinting = paint.getHinting();
+        return true;
+    }
+    // we're cool with the paint as is
+    return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 SkDevice* SkRasterDeviceFactory::newDevice(SkCanvas* canvas,
                                            SkBitmap::Config config, int width,
                                            int height, bool isOpaque,
diff --git a/src/core/SkGlyphCache.h b/src/core/SkGlyphCache.h
index d6b4fd6..92e3795 100644
--- a/src/core/SkGlyphCache.h
+++ b/src/core/SkGlyphCache.h
@@ -2,16 +2,16 @@
 **
 ** Copyright 2006, The Android Open Source Project
 **
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
 **
-**     http://www.apache.org/licenses/LICENSE-2.0 
+**     http://www.apache.org/licenses/LICENSE-2.0
 **
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
 
@@ -47,17 +47,17 @@
     */
     const SkGlyph& getUnicharAdvance(SkUnichar);
     const SkGlyph& getGlyphIDAdvance(uint16_t);
-    
+
     /** Returns a glyph with all fields valid except fImage and fPath, which
         may be null. If they are null, call findImage or findPath for those.
         If they are not null, then they are valid.
-        
+
         This call is potentially slower than the matching ...Advance call. If
         you only need the fAdvance/fDevKern fields, call those instead.
     */
     const SkGlyph& getUnicharMetrics(SkUnichar);
     const SkGlyph& getGlyphIDMetrics(uint16_t);
-    
+
     /** These are variants that take the device position of the glyph. Call
         these only if you are drawing in subpixel mode. Passing 0, 0 is
         effectively the same as calling the variants w/o the extra params, tho
@@ -65,13 +65,13 @@
     */
     const SkGlyph& getUnicharMetrics(SkUnichar, SkFixed x, SkFixed y);
     const SkGlyph& getGlyphIDMetrics(uint16_t, SkFixed x, SkFixed y);
-    
+
     /** Return the glyphID for the specified Unichar. If the char has already
         been seen, use the existing cache entry. If not, ask the scalercontext
         to compute it for us.
     */
     uint16_t unicharToGlyph(SkUnichar);
-    
+
     /** Map the glyph to its Unicode equivalent. Unmappable glyphs map to
         a character code of zero.
     */
@@ -98,6 +98,10 @@
 
     const SkDescriptor& getDescriptor() const { return *fDesc; }
 
+    SkMask::Format getMaskFormat() const {
+        return fScalerContext->getMaskFormat();
+    }
+
     /*  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
@@ -106,7 +110,7 @@
         this glyphcache in any way, since it may be in the process of being
         deleted.
     */
-    
+
     //! If the proc is found, return true and set *dataPtr to its data
     bool getAuxProcData(void (*auxProc)(void*), void** dataPtr) const;
     //! Add a proc/data pair to the glyphcache. proc should be non-null
@@ -120,7 +124,7 @@
         deadlock.
     */
     static void VisitAllCaches(bool (*proc)(SkGlyphCache*, void*), void* ctx);
-    
+
     /** Find a matching cache entry, and call proc() with it. If none is found
         create a new one. If the proc() returns true, detach the cache and
         return it, otherwise leave it and return NULL.
@@ -128,7 +132,7 @@
     static SkGlyphCache* VisitCache(const SkDescriptor* desc,
                                     bool (*proc)(const SkGlyphCache*, void*),
                                     void* context);
-    
+
     /** Given a strike that was returned by either VisitCache() or DetachCache()
         add it back into the global cache list (after which the caller should
         not reference it anymore.
@@ -184,11 +188,11 @@
     private:
         const SkGlyphCache* fCache;
     };
-        
+
 private:
     SkGlyphCache(const SkDescriptor*);
     ~SkGlyphCache();
-    
+
     enum MetricsType {
         kJustAdvance_MetricsType,
         kFull_MetricsType
@@ -208,7 +212,7 @@
         }
         fPrev = fNext = NULL;
     }
-    
+
     void attachToHead(SkGlyphCache** head) {
         SkASSERT(NULL == fPrev && NULL == fNext);
         if (*head) {
@@ -232,7 +236,7 @@
     SkTDArray<SkGlyph*> fGlyphArray;
     SkChunkAlloc        fGlyphAlloc;
     SkChunkAlloc        fImageAlloc;
-    
+
     int fMetricsCount, fAdvanceCount;
 
     struct CharGlyphRec {
@@ -241,7 +245,7 @@
     };
     // no reason to use the same kHashCount as fGlyphHash, but we do for now
     CharGlyphRec    fCharToGlyphHash[kHashCount];
-    
+
     enum {
         // shift so that the top bits fall into kHashBits region
         kShiftForHashIndex = SkGlyph::kSubShift +
@@ -252,7 +256,7 @@
     static inline unsigned ID2HashIndex(uint32_t id) {
         return (id ^ (id >> kShiftForHashIndex)) & kHashMask;
     }
-    
+
     // used to track (approx) how much ram is tied-up in this cache
     size_t  fMemoryUsed;
 
@@ -302,7 +306,7 @@
     }
 private:
     SkGlyphCache*   fCache;
-    
+
     static bool DetachProc(const SkGlyphCache*, void*);
 };
 
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index fa886c8..5c0f922 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1254,33 +1254,12 @@
     buffer->flatten(desc->addEntry(tag, buffer->size(), NULL));
 }
 
-static bool canSupportLCD16(const SkPaint& paint) {
-#if 0
-    return  !paint.getShader() &&
-            !paint.getXfermode() && // unless its srcover
-            !paint.getMaskFilter() &&
-            !paint.getRasterizer() &&
-            !paint.getColorFilter() &&
-            !paint.getPathEffect() &&
-            !paint.isFakeBoldText() &&
-            paint.getStyle() == SkPaint::kFill_Style;
-#else
-    // disable for now, while we test more
-    return false;
-#endif
-}
-
 static SkMask::Format computeMaskFormat(const SkPaint& paint) {
     uint32_t flags = paint.getFlags();
 
     // Antialiasing being disabled trumps all other settings.
-    if (!(flags & SkPaint::kAntiAlias_Flag))
+    if (!(flags & SkPaint::kAntiAlias_Flag)) {
         return SkMask::kBW_Format;
-
-    if (flags & SkPaint::kLCDRenderText_Flag) {
-        if (canSupportLCD16(paint)) {
-            return SkMask::kLCD16_Format;
-        }
     }
 
 #if defined(SK_SUPPORT_LCDTEXT)
@@ -1288,6 +1267,10 @@
         return SkFontHost::GetSubpixelOrientation() == SkFontHost::kHorizontal_LCDOrientation ?
                    SkMask::kHorizontalLCD_Format : SkMask::kVerticalLCD_Format;
     }
+#else
+    if (flags & SkPaint::kLCDRenderText_Flag) {
+        return SkMask::kLCD16_Format;
+    }
 #endif
 
     return SkMask::kA8_Format;
diff --git a/src/core/core_files.mk b/src/core/core_files.mk
new file mode 100644
index 0000000..252644e
--- /dev/null
+++ b/src/core/core_files.mk
@@ -0,0 +1,99 @@
+SOURCE := \
+    Sk64.cpp \
+    SkAdvancedTypefaceMetrics.cpp \
+    SkAlphaRuns.cpp \
+    SkBitmap.cpp \
+    SkBitmapProcShader.cpp \
+    SkBitmapProcState.cpp \
+    SkBitmapProcState_matrixProcs.cpp \
+    SkBitmapSampler.cpp \
+    SkBitmap_scroll.cpp \
+    SkBlitRow_D16.cpp \
+    SkBlitRow_D32.cpp \
+    SkBlitRow_D4444.cpp \
+    SkBlitter.cpp \
+    SkBlitter_4444.cpp \
+    SkBlitter_A1.cpp \
+    SkBlitter_A8.cpp \
+    SkBlitter_ARGB32.cpp \
+    SkBlitter_ARGB32_Subpixel.cpp \
+    SkBlitter_RGB16.cpp \
+    SkBlitter_Sprite.cpp \
+    SkBuffer.cpp \
+    SkCanvas.cpp \
+    SkChunkAlloc.cpp \
+    SkClipStack.cpp \
+    SkColor.cpp \
+    SkColorFilter.cpp \
+    SkColorTable.cpp \
+    SkConcaveToTriangles.cpp \
+    SkComposeShader.cpp \
+    SkCordic.cpp \
+    SkCubicClipper.cpp \
+    SkDebug.cpp \
+    SkDeque.cpp \
+    SkDevice.cpp \
+    SkDither.cpp \
+    SkDraw.cpp \
+    SkEdge.cpp \
+    SkEdgeBuilder.cpp \
+    SkEdgeClipper.cpp \
+    SkFilterProc.cpp \
+    SkFlate.cpp \
+    SkFlattenable.cpp \
+    SkFloat.cpp \
+    SkFloatBits.cpp \
+    SkFontHost.cpp \
+    SkGeometry.cpp \
+    SkGlobals.cpp \
+    SkGlyphCache.cpp \
+    SkGraphics.cpp \
+    SkLineClipper.cpp \
+    SkMMapStream.cpp \
+    SkMallocPixelRef.cpp \
+    SkMask.cpp \
+    SkMaskFilter.cpp \
+    SkMath.cpp \
+    SkMatrix.cpp \
+    SkMemory_stdlib.cpp \
+    SkPackBits.cpp \
+    SkPaint.cpp \
+    SkPath.cpp \
+    SkPathEffect.cpp \
+    SkPathHeap.cpp \
+    SkPathMeasure.cpp \
+    SkPicture.cpp \
+    SkPictureFlat.cpp \
+    SkPicturePlayback.cpp \
+    SkPictureRecord.cpp \
+    SkPixelRef.cpp \
+    SkPoint.cpp \
+    SkPtrRecorder.cpp \
+    SkQuadClipper.cpp \
+    SkRasterizer.cpp \
+    SkRect.cpp \
+    SkRefDict.cpp \
+    SkRegion.cpp \
+    SkRegion_rects.cpp \
+    SkRegion_path.cpp \
+    SkScalar.cpp \
+    SkScalerContext.cpp \
+    SkScan.cpp \
+    SkScan_AntiPath.cpp \
+    SkScan_Antihair.cpp \
+    SkScan_Hairline.cpp \
+    SkScan_Path.cpp \
+    SkShader.cpp \
+    SkShape.cpp \
+    SkSpriteBlitter_ARGB32.cpp \
+    SkSpriteBlitter_RGB16.cpp \
+    SkStream.cpp \
+    SkString.cpp \
+    SkStroke.cpp \
+    SkStrokerPriv.cpp \
+    SkTSearch.cpp \
+    SkTypeface.cpp \
+    SkUnPreMultiply.cpp \
+    SkUtils.cpp \
+    SkWriter32.cpp \
+    SkXfermode.cpp
diff --git a/src/effects/SkBlurDrawLooper.cpp b/src/effects/SkBlurDrawLooper.cpp
index 901a4d3..9585112 100644
--- a/src/effects/SkBlurDrawLooper.cpp
+++ b/src/effects/SkBlurDrawLooper.cpp
@@ -31,8 +31,11 @@
 
     if (flags & kOverrideColor_BlurFlag)
     {
+        // Set alpha to 1 for the override since transparency will already
+        // be baked into the blurred mask.
+        SkColor opaqueColor = SkColorSetA(color, 255);
         //The SrcIn xfer mode will multiply 'color' by the incoming alpha
-        fColorFilter = SkColorFilter::CreateModeFilter(color, SkXfermode::kSrcIn_Mode);
+        fColorFilter = SkColorFilter::CreateModeFilter(opaqueColor, SkXfermode::kSrcIn_Mode);
     }
     else
     {
diff --git a/src/effects/effects_files.mk b/src/effects/effects_files.mk
new file mode 100644
index 0000000..00d9e7d
--- /dev/null
+++ b/src/effects/effects_files.mk
@@ -0,0 +1,25 @@
+SOURCE := \
+	Sk1DPathEffect.cpp \
+	Sk2DPathEffect.cpp \
+    SkBitmapCache.cpp \
+	SkTransparentShader.cpp \
+	SkAvoidXfermode.cpp \
+	SkBlurDrawLooper.cpp \
+	SkBlurMask.cpp \
+	SkBlurMaskFilter.cpp \
+	SkColorFilters.cpp \
+	SkColorMatrixFilter.cpp \
+	SkCornerPathEffect.cpp \
+	SkDashPathEffect.cpp \
+	SkDiscretePathEffect.cpp \
+	SkEmbossMask.cpp \
+	SkEmbossMaskFilter.cpp \
+	SkGradientShader.cpp \
+    SkGroupShape.cpp \
+	SkKernel33MaskFilter.cpp \
+	SkLayerDrawLooper.cpp \
+	SkLayerRasterizer.cpp \
+	SkPaintFlagsDrawFilter.cpp \
+	SkPixelXorXfermode.cpp \
+	SkPorterDuff.cpp \
+    SkRectShape.cpp
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 91a6319..3707b67 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1181,6 +1181,31 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
+bool SkGpuDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
+    if (!paint.isLCDRenderText()) {
+        // we're cool with the paint as is
+        return false;
+    }
+
+    if (paint.getShader() ||
+        paint.getXfermode() || // unless its srcover
+        paint.getMaskFilter() ||
+        paint.getRasterizer() ||
+        paint.getColorFilter() ||
+        paint.getPathEffect() ||
+        paint.isFakeBoldText() ||
+        paint.getStyle() != SkPaint::kFill_Style) {
+        // turn off lcd
+        flags->fFlags = paint.getFlags() & ~SkPaint::kLCDRenderText_Flag;
+        flags->fHinting = paint.getHinting();
+        return true;
+    }
+    // we're cool with the paint as is
+    return false;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 SkGpuDevice::TexCache* SkGpuDevice::lockCachedTexture(const SkBitmap& bitmap,
                                                   const GrSamplerState& sampler,
                                                   GrTexture** texture,
diff --git a/src/gpu/SkGrFontScaler.cpp b/src/gpu/SkGrFontScaler.cpp
index 3d57aa8..16e44b9 100644
--- a/src/gpu/SkGrFontScaler.cpp
+++ b/src/gpu/SkGrFontScaler.cpp
@@ -83,6 +83,19 @@
     GrSafeUnref(fKey);
 }
 
+GrMaskFormat SkGrFontScaler::getMaskFormat() {
+    SkMask::Format format = fStrike->getMaskFormat();
+    switch (format) {
+        case SkMask::kA8_Format:
+            return kA8_GrMaskFormat;
+        case SkMask::kLCD16_Format:
+            return kA565_GrMaskFormat;
+        default:
+            GrAssert(!"unsupported SkMask::Format");
+            return kA8_GrMaskFormat;
+    }
+}
+
 const GrKey* SkGrFontScaler::getKey() {
     if (NULL == fKey) {
         fKey = new SkGrDescKey(fStrike->getDescriptor());
@@ -117,8 +130,9 @@
     if (srcRB == dstRB) {
         memcpy(dst, src, dstRB * height);
     } else {
+        const int bbp = GrMaskFormatBytesPerPixel(this->getMaskFormat());
         for (int y = 0; y < height; y++) {
-            memcpy(dst, src, width);
+            memcpy(dst, src, width * bbp);
             src = (const char*)src + srcRB;
             dst = (char*)dst + dstRB;
         }
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
index 5dc38b8..7cecb7f 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -39,10 +39,7 @@
 // In the past, FT_GlyphSlot_Own_Bitmap was defined in this header file.
 #include FT_SYNTHESIS_H
 #include FT_XFREE86_H
-
-#if defined(SK_SUPPORT_LCDTEXT)
 #include FT_LCD_FILTER_H
-#endif
 
 #ifdef   FT_ADVANCES_H
 #include FT_ADVANCES_H
@@ -95,15 +92,18 @@
 static bool
 InitFreetype() {
     FT_Error err = FT_Init_FreeType(&gFTLibrary);
-    if (err)
+    if (err) {
         return false;
+    }
 
-#if defined(SK_SUPPORT_LCDTEXT)
     // Setup LCD filtering. This reduces colour fringes for LCD rendered
     // glyphs.
+//#ifdef ANDROID
+//    gLCDSupport = false;
+//#else
     err = FT_Library_SetLcdFilter(gFTLibrary, FT_LCD_FILTER_DEFAULT);
     gLCDSupport = err == 0;
-#endif
+//#endif
     gLCDSupportValid = true;
 
     return true;
@@ -523,7 +523,7 @@
         FT_Done_FreeType(gFTLibrary);
     }
 
-    if (!gLCDSupport && rec->isLCD()) {
+    if (!gLCDSupport && (rec->isLCD() || SkMask::kLCD16_Format == rec->fMaskFormat)) {
         // If the runtime Freetype library doesn't support LCD mode, we disable
         // it here.
         rec->fMaskFormat = SkMask::kA8_Format;
@@ -646,10 +646,12 @@
                     break;
                 }
                 loadFlags = FT_LOAD_TARGET_NORMAL;
-                if (SkMask::kHorizontalLCD_Format == fRec.fMaskFormat)
+                if (SkMask::kHorizontalLCD_Format == fRec.fMaskFormat ||
+                        SkMask::kLCD16_Format == fRec.fMaskFormat) {
                     loadFlags = FT_LOAD_TARGET_LCD;
-                else if (SkMask::kVerticalLCD_Format == fRec.fMaskFormat)
+                } else if (SkMask::kVerticalLCD_Format == fRec.fMaskFormat) {
                     loadFlags = FT_LOAD_TARGET_LCD_V;
+                }
                 break;
             default:
                 SkDebugf("---------- UNKNOWN hinting %d\n", fRec.getHinting());
@@ -915,6 +917,26 @@
 using namespace skia_freetype_support;
 #endif
 
+static void copyFT2LCD16(const SkGlyph& glyph, const FT_Bitmap& bitmap) {
+    SkASSERT(glyph.fWidth * 3 == bitmap.width - 6);
+    SkASSERT(glyph.fHeight == bitmap.rows);
+
+    const uint8_t* src = bitmap.buffer + 3;
+    uint16_t* dst = reinterpret_cast<uint16_t*>(glyph.fImage);
+    size_t dstRB = glyph.rowBytes();
+    int width = glyph.fWidth;
+
+    for (int y = 0; y < glyph.fHeight; y++) {
+        const uint8_t* triple = src;
+        for (int x = 0; x < width; x++) {
+            dst[x] = SkPackRGB16(triple[0] >> 3, triple[1] >> 2, triple[2] >> 3);
+            triple += 3;
+        }
+        src += bitmap.pitch;
+        dst = (uint16_t*)((char*)dst + dstRB);
+    }
+}
+
 void SkScalerContext_FreeType::generateImage(const SkGlyph& glyph) {
     SkAutoMutexAcquire  ac(gFTMutex);
 
@@ -982,16 +1004,21 @@
             }
 #endif
 
-            target.width = glyph.fWidth;
-            target.rows = glyph.fHeight;
-            target.pitch = glyph.rowBytes();
-            target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage);
-            target.pixel_mode = compute_pixel_mode(
-                                            (SkMask::Format)fRec.fMaskFormat);
-            target.num_grays = 256;
+            if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
+                FT_Render_Glyph(fFace->glyph, FT_RENDER_MODE_LCD);
+                copyFT2LCD16(glyph, fFace->glyph->bitmap);
+            } else {
+                target.width = glyph.fWidth;
+                target.rows = glyph.fHeight;
+                target.pitch = glyph.rowBytes();
+                target.buffer = reinterpret_cast<uint8_t*>(glyph.fImage);
+                target.pixel_mode = compute_pixel_mode(
+                                                (SkMask::Format)fRec.fMaskFormat);
+                target.num_grays = 256;
 
-            memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
-            FT_Outline_Get_Bitmap(gFTLibrary, outline, &target);
+                memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight);
+                FT_Outline_Get_Bitmap(gFTLibrary, outline, &target);
+            }
         } break;
 
         case FT_GLYPH_FORMAT_BITMAP: {
diff --git a/src/ports/SkFontHost_simple.cpp b/src/ports/SkFontHost_simple.cpp
index 6df6c44..60334e7 100644
--- a/src/ports/SkFontHost_simple.cpp
+++ b/src/ports/SkFontHost_simple.cpp
@@ -26,9 +26,14 @@
 
 #define FONT_CACHE_MEMORY_BUDGET    (768 * 1024)
 
-#define SK_FONT_FILE_PREFIX          "/skimages/"
+#ifdef SK_BUILD_FOR_MAC
+    #define SK_FONT_FILE_PREFIX     "/Library/Fonts/"
+#else
+    #define SK_FONT_FILE_PREFIX          "/skimages/"
+#endif
 
-SkTypeface::Style find_name_and_style(SkStream* stream, SkString* name);
+SkTypeface::Style find_name_and_attributes(SkStream* stream, SkString* name,
+                                           bool* isFixedWidth);
 
 static void GetFullPathForSysFonts(SkString* full, const char name[]) {
     full->set(SK_FONT_FILE_PREFIX);
@@ -47,7 +52,7 @@
 struct NameFamilyPair {
     const char* fName;      // we own this
     FamilyRec*  fFamily;    // we don't own this, we just reference it
-    
+
     void construct(const char name[], FamilyRec* family) {
         fName = strdup(name);
         fFamily = family;   // we don't own this, so just record the referene
@@ -70,7 +75,7 @@
 struct FamilyRec {
     FamilyRec*  fNext;
     SkTypeface* fFaces[4];
-    
+
     FamilyRec()
     {
         fNext = gFamilyHead;
@@ -143,7 +148,7 @@
     FamilyRec* family = find_family(face);
     SkASSERT(family->fFaces[face->style()] == face);
     family->fFaces[face->style()] = NULL;
-    
+
     for (int i = 0; i < 4; i++) {
         if (family->fFaces[i] != NULL) {    // family is non-empty
             return NULL;
@@ -177,7 +182,7 @@
 static SkTypeface* find_typeface(const char name[], SkTypeface::Style style) {
     NameFamilyPair* list = gNameList.begin();
     int             count = gNameList.count();
-    
+
     int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
 
     if (index >= 0) {
@@ -198,7 +203,7 @@
 
     NameFamilyPair* list = gNameList.begin();
     int             count = gNameList.count();
-    
+
     int index = SkStrLCSearch(&list[0].fName, count, name, sizeof(list[0]));
 
     if (index < 0) {
@@ -216,7 +221,7 @@
 #endif
 
     SkTDArray<NameFamilyPair>& list = gNameList;
-    
+
     // must go backwards when removing
     for (int i = list.count() - 1; i >= 0; --i) {
         NameFamilyPair* pair = &list[i];
@@ -234,9 +239,9 @@
     FamilyTypeface(Style style, bool sysFont, SkTypeface* familyMember)
     : SkTypeface(style, sk_atomic_inc(&gUniqueFontID) + 1) {
         fIsSysFont = sysFont;
-        
+
         SkAutoMutexAcquire  ac(gFamilyMutex);
-        
+
         FamilyRec* rec = NULL;
         if (familyMember) {
             rec = find_family(familyMember);
@@ -246,10 +251,10 @@
         }
         rec->fFaces[style] = this;
     }
-    
+
     virtual ~FamilyTypeface() {
         SkAutoMutexAcquire  ac(gFamilyMutex);
-        
+
         // remove us from our family. If the family is now empty, we return
         // that and then remove that family from the name list
         FamilyRec* family = remove_from_family(this);
@@ -258,16 +263,16 @@
             detach_and_delete_family(family);
         }
     }
-    
+
     bool isSysFont() const { return fIsSysFont; }
-    
+
     virtual SkStream* openStream() = 0;
     virtual const char* getUniqueString() const = 0;
     virtual const char* getFilePath() const = 0;
-    
+
 private:
     bool    fIsSysFont;
-    
+
     typedef SkTypeface INHERITED;
 };
 
@@ -285,7 +290,7 @@
     virtual ~StreamTypeface() {
         fStream->unref();
     }
-    
+
     // overrides
     virtual SkStream* openStream() {
         // we just ref our existing stream, since the caller will call unref()
@@ -298,7 +303,7 @@
 
 private:
     SkStream* fStream;
-    
+
     typedef FamilyTypeface INHERITED;
 };
 
@@ -308,14 +313,14 @@
                  const char path[])
     : INHERITED(style, sysFont, familyMember) {
         SkString fullpath;
-        
+
         if (sysFont) {
             GetFullPathForSysFonts(&fullpath, path);
             path = fullpath.c_str();
         }
         fPath.set(path);
     }
-    
+
     // overrides
     virtual SkStream* openStream() {
         SkStream* stream = SkNEW_ARGS(SkMMAPStream, (fPath.c_str()));
@@ -345,7 +350,7 @@
 
 private:
     SkString fPath;
-    
+
     typedef FamilyTypeface INHERITED;
 };
 
@@ -354,18 +359,19 @@
 
 static bool get_name_and_style(const char path[], SkString* name,
                                SkTypeface::Style* style, bool isExpected) {
+    bool            isFixedWidth;
     SkString        fullpath;
     GetFullPathForSysFonts(&fullpath, path);
 
     SkMMAPStream stream(fullpath.c_str());
     if (stream.getLength() > 0) {
-        *style = find_name_and_style(&stream, name);
+        *style = find_name_and_attributes(&stream, name, &isFixedWidth);
         return true;
     }
     else {
         SkFILEStream stream(fullpath.c_str());
         if (stream.getLength() > 0) {
-            *style = find_name_and_style(&stream, name);
+            *style = find_name_and_attributes(&stream, name, &isFixedWidth);
             return true;
         }
     }
@@ -403,6 +409,8 @@
     null for the list. The names list must be NULL-terminated
 */
 static const FontInitRec gSystemFonts[] = {
+    { "Arial.ttf",              gSansNames  },
+    { "Times.ttf",              gSerifNames  },
     { "samplefont.ttf",              gSansNames  },
 };
 
@@ -429,7 +437,7 @@
     if (NULL != gDefaultNormal) {
         return;
     }
-    
+
     const FontInitRec* rec = gSystemFonts;
     SkTypeface* firstInFamily = NULL;
     int fallbackCount = 0;
@@ -439,7 +447,7 @@
         if (rec[i].fNames != NULL) {
             firstInFamily = NULL;
         }
-        
+
         SkString name;
         SkTypeface::Style style;
 
@@ -515,7 +523,7 @@
         SkString str;
         str.resize(len);
         stream->read(str.writable_str(), len);
-        
+
         const FontInitRec* rec = gSystemFonts;
         for (size_t i = 0; i < SK_ARRAY_COUNT(gSystemFonts); i++) {
             if (strcmp(rec[i].fFileName, str.c_str()) == 0) {
@@ -541,10 +549,10 @@
     load_system_fonts();
 
     SkAutoMutexAcquire  ac(gFamilyMutex);
-    
+
     // clip to legal style bits
     style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
-    
+
     SkTypeface* tf = NULL;
 
     if (NULL != familyFace) {
@@ -565,13 +573,13 @@
 
 bool SkFontHost::ValidFontID(uint32_t fontID) {
     SkAutoMutexAcquire  ac(gFamilyMutex);
-    
+
     return find_from_uniqueID(fontID) != NULL;
 }
 
 SkStream* SkFontHost::OpenStream(uint32_t fontID) {
     SkAutoMutexAcquire  ac(gFamilyMutex);
-    
+
     FamilyTypeface* tf = (FamilyTypeface*)find_from_uniqueID(fontID);
     SkStream* stream = tf ? tf->openStream() : NULL;
 
@@ -582,12 +590,13 @@
     return stream;
 }
 
-// static
+#if 0
 SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
         uint32_t fontID, bool perGlyphInfo) {
     SkASSERT(!"SkFontHost::GetAdvancedTypefaceMetrics unimplemented");
     return NULL;
 }
+#endif
 
 size_t SkFontHost::GetFileName(SkFontID fontID, char path[], size_t length,
                                int32_t* index) {
@@ -633,9 +642,11 @@
     if (NULL == stream || stream->getLength() <= 0) {
         return NULL;
     }
-    
+
+    bool     isFixedWidth;
     SkString name;
-    SkTypeface::Style style = find_name_and_style(stream, &name);
+    SkTypeface::Style style = find_name_and_attributes(stream, &name,
+                                                       &isFixedWidth);
 
     return SkNEW_ARGS(StreamTypeface, (style, false, NULL, stream));
 }
diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp
index a20f001..a4f430c 100644
--- a/src/ports/SkFontHost_win.cpp
+++ b/src/ports/SkFontHost_win.cpp
@@ -1,804 +1,894 @@
-/*

- ** Copyright 2006, The Android Open Source Project

- **

- ** Licensed under the Apache License, Version 2.0 (the "License");

- ** you may not use this file except in compliance with the License.

- ** You may obtain a copy of the License at

- **

- **     http://www.apache.org/licenses/LICENSE-2.0

- **

- ** Unless required by applicable law or agreed to in writing, software

- ** distributed under the License is distributed on an "AS IS" BASIS,

- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- ** See the License for the specific language governing permissions and

- ** limitations under the License.

- */

-

-#include "SkString.h"

-//#include "SkStream.h"

-

-#include "SkEndian.h"

-#include "SkFontHost.h"

-#include "SkDescriptor.h"

-#include "SkAdvancedTypefaceMetrics.h"

-#include "SkStream.h"

-#include "SkThread.h"

-#include "SkTypeface_win.h"

-#include "SkUtils.h"

-

-#ifdef WIN32

-#include "windows.h"

-#include "tchar.h"

-#include "Usp10.h"

-

-// client3d has to undefine this for now

-#define CAN_USE_LOGFONT_NAME

-

-using namespace skia_advanced_typeface_metrics_utils;

-

-static SkMutex gFTMutex;

-

-static const uint16_t BUFFERSIZE = (16384 - 32);

-static uint8_t glyphbuf[BUFFERSIZE];

-

-// Give 1MB font cache budget

-#define FONT_CACHE_MEMORY_BUDGET    (1024 * 1024)

-

-/**

- *	Since LOGFONT wants its textsize as an int, and we support fractional sizes,

- *  and since we have a cache of LOGFONTs for our tyepfaces, we always set the

- *  lfHeight to a canonical size, and then we use the 2x2 matrix to achieve the

- *  actual requested size.

- */

-static const int gCanonicalTextSize = 64;

-

-static void make_canonical(LOGFONT* lf) {

-	lf->lfHeight = -gCanonicalTextSize;

-}

-

-static inline FIXED SkFixedToFIXED(SkFixed x) {

-    return *(FIXED*)(&x);

-}

-

-static inline FIXED SkScalarToFIXED(SkScalar x) {

-    return SkFixedToFIXED(SkScalarToFixed(x));

-}

-

-static unsigned calculateGlyphCount(HDC hdc) {

-    // The 'maxp' table stores the number of glyphs at offset 4, in 2 bytes.

-    const DWORD maxpTag = *(DWORD*) "maxp";

-    uint16_t glyphs;

-    if (GetFontData(hdc, maxpTag, 4, &glyphs, sizeof(glyphs)) != GDI_ERROR) {

-        return SkEndian_SwapBE16(glyphs);

-    }

-    

-    // Binary search for glyph count.

-    static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};

-    int32_t max = SK_MaxU16 + 1;

-    int32_t min = 0;

-    GLYPHMETRICS gm;

-    while (min < max) {

-        int32_t mid = min + ((max - min) / 2);

-        if (GetGlyphOutlineW(hdc, mid, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0,

-                             NULL, &mat2) == GDI_ERROR) {

-            max = mid;

-        } else {

-            min = mid + 1;

-        }

-    }

-    SkASSERT(min == max);

-    return min;

-}

-

-static SkTypeface::Style GetFontStyle(const LOGFONT& lf) {

-    int style = SkTypeface::kNormal;

-    if (lf.lfWeight == FW_SEMIBOLD || lf.lfWeight == FW_DEMIBOLD || lf.lfWeight == FW_BOLD)

-        style |= SkTypeface::kBold;

-    if (lf.lfItalic)

-        style |= SkTypeface::kItalic;

-

-    return (SkTypeface::Style)style;

-}

-

-// have to do this because SkTypeface::SkTypeface() is protected

-class LogFontTypeface : public SkTypeface {

-private:

-    static SkMutex                  gMutex;

-    static LogFontTypeface*         gHead;

-    static int32_t                  gCurrId;

-

-    LogFontTypeface*                fNext;

-    LOGFONT                         fLogFont;

-

-public:

-

-    LogFontTypeface(Style style, const LOGFONT& logFont) :

-      SkTypeface(style, sk_atomic_inc(&gCurrId)+1), // 0 id is reserved so add 1

-      fLogFont(logFont)

-    {

-		make_canonical(&fLogFont);

-

-        SkAutoMutexAcquire am(gMutex);

-        fNext = gHead;

-        gHead = this;

-    }

-

-    const LOGFONT& logFont() const { return fLogFont; }

-

-    virtual ~LogFontTypeface() {

-        SkAutoMutexAcquire am(gMutex);

-        if (gHead == this) {

-            gHead = fNext;

-            return;

-        }

-

-        LogFontTypeface* prev = gHead;

-        SkASSERT(prev);

-        while (prev->fNext != this) {

-            prev = prev->fNext;

-            SkASSERT(prev);

-        }

-        prev->fNext = fNext;

-    }

-

-    static LogFontTypeface* FindById(uint32_t id){

-        SkASSERT(gHead);

-        LogFontTypeface* curr = gHead;

-        while (curr->uniqueID() != id) {

-            curr = curr->fNext;

-            SkASSERT(curr);

-        }

-        return curr;

-    }

-

-    static LogFontTypeface* FindByLogFont(const LOGFONT& lf)

-    {

-		LOGFONT canonical = lf;

-		make_canonical(&canonical);

-

-        LogFontTypeface* curr = gHead;

-        while (curr && memcmp(&curr->fLogFont, &canonical, sizeof(LOGFONT))) {

-            curr = curr->fNext;

-        }

-        return curr;

-    }

-};

-

-LogFontTypeface* LogFontTypeface::gHead;

-int32_t LogFontTypeface::gCurrId;

-SkMutex LogFontTypeface::gMutex;

-

-static const LOGFONT& get_default_font() {

-    static LOGFONT gDefaultFont;

-    // don't hardcode on Windows, Win2000, XP, Vista, and international all have different default

-    // and the user could change too

-

-

-//  lfMessageFont is garbage on my XP, so skip for now

-#if 0

-    if (gDefaultFont.lfFaceName[0] != 0) {

-        return gDefaultFont;

-    }

-

-    NONCLIENTMETRICS ncm;

-    ncm.cbSize = sizeof(NONCLIENTMETRICS);

-    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);

-

-    //memcpy(&gDefaultFont, &(ncm.lfMessageFont), sizeof(LOGFONT));

-#endif

-

-    return gDefaultFont;

-}

-

-SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& lf) {

-    LogFontTypeface* ptypeface = LogFontTypeface::FindByLogFont(lf);

-

-    if (NULL == ptypeface) {

-        SkTypeface::Style style = GetFontStyle(lf);

-        ptypeface = new LogFontTypeface(style, lf);

-    } else {

-	    ptypeface->ref();

-	}

-    return ptypeface;

-}

-

-uint32_t SkFontHost::NextLogicalFont(uint32_t fontID) {

-  // Zero means that we don't have any fallback fonts for this fontID.

-  // This function is implemented on Android, but doesn't have much

-  // meaning here.

-  return 0;

-}

-

-class SkScalerContext_Windows : public SkScalerContext {

-public:

-    SkScalerContext_Windows(const SkDescriptor* desc);

-    virtual ~SkScalerContext_Windows();

-

-protected:

-    virtual unsigned generateGlyphCount();

-    virtual uint16_t generateCharToGlyph(SkUnichar uni);

-    virtual void generateAdvance(SkGlyph* glyph);

-    virtual void generateMetrics(SkGlyph* glyph);

-    virtual void generateImage(const SkGlyph& glyph);

-    virtual void generatePath(const SkGlyph& glyph, SkPath* path);

-    virtual void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY);

-    //virtual SkDeviceContext getDC() {return ddc;}

-private:

-	SkScalar	 fScale;	// to get from canonical size to real size

-    MAT2         fMat22;

-    HDC          fDDC;

-    HFONT        fSavefont;

-    HFONT        fFont;

-    SCRIPT_CACHE fSC;

-    int          fGlyphCount;

-};

-

-SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc)

-        : SkScalerContext(desc), fDDC(0), fFont(0), fSavefont(0), fSC(0)

-        , fGlyphCount(-1) {

-    SkAutoMutexAcquire  ac(gFTMutex);

-

-	fScale = fRec.fTextSize / gCanonicalTextSize;

-    fMat22.eM11 = SkScalarToFIXED(SkScalarMul(fScale, fRec.fPost2x2[0][0]));

-    fMat22.eM12 = SkScalarToFIXED(SkScalarMul(fScale, -fRec.fPost2x2[0][1]));

-    fMat22.eM21 = SkScalarToFIXED(SkScalarMul(fScale, fRec.fPost2x2[1][0]));

-    fMat22.eM22 = SkScalarToFIXED(SkScalarMul(fScale, -fRec.fPost2x2[1][1]));

-

-    fDDC = ::CreateCompatibleDC(NULL);

-    SetBkMode(fDDC, TRANSPARENT);

-

-    // Scaling by the DPI is inconsistent with how Skia draws elsewhere

-    //SkScalar height = -(fRec.fTextSize * GetDeviceCaps(ddc, LOGPIXELSY) / 72);

-    LOGFONT lf = LogFontTypeface::FindById(fRec.fFontID)->logFont();

-    lf.lfHeight = -gCanonicalTextSize;

-    fFont = CreateFontIndirect(&lf);

-    fSavefont = (HFONT)SelectObject(fDDC, fFont);

-}

-

-SkScalerContext_Windows::~SkScalerContext_Windows() {

-    if (fDDC) {

-        ::SelectObject(fDDC, fSavefont);

-        ::DeleteDC(fDDC);

-    }

-    if (fFont) {

-        ::DeleteObject(fFont);

-    }

-    if (fSC) {

-        ::ScriptFreeCache(&fSC);

-    }

-}

-

-unsigned SkScalerContext_Windows::generateGlyphCount() {

-    if (fGlyphCount < 0) {

-        fGlyphCount = calculateGlyphCount(fDDC);

-    }

-    return fGlyphCount;

-}

-

-uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {

-    uint16_t index = 0;

-    WCHAR c[2];

-    // TODO(ctguil): Support characters that generate more than one glyph.

-    if (SkUTF16_FromUnichar(uni, (uint16_t*)c) == 1) {

-        // Type1 fonts fail with uniscribe API. Use GetGlyphIndices for plane 0.

-        SkAssertResult(GetGlyphIndicesW(fDDC, c, 1, &index, 0));

-    } else {

-        // Use uniscribe to detemine glyph index for non-BMP characters.

-        // Need to add extra item to SCRIPT_ITEM to work around a bug in older

-        // windows versions. https://bugzilla.mozilla.org/show_bug.cgi?id=366643

-        SCRIPT_ITEM si[2 + 1];

-        int items;

-        SkAssertResult(

-            SUCCEEDED(ScriptItemize(c, 2, 2, NULL, NULL, si, &items)));

-

-        WORD log[2];

-        SCRIPT_VISATTR vsa;

-        int glyphs;

-        SkAssertResult(SUCCEEDED(ScriptShape(

-            fDDC, &fSC, c, 2, 1, &si[0].a, &index, log, &vsa, &glyphs)));

-    }

-    return index;

-}

-

-void SkScalerContext_Windows::generateAdvance(SkGlyph* glyph) {

-    this->generateMetrics(glyph);

-}

-

-void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {

-

-    SkASSERT(fDDC);

-

-    GLYPHMETRICS gm;

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

-

-    glyph->fRsbDelta = 0;

-    glyph->fLsbDelta = 0;

-

-    // Note: need to use GGO_GRAY8_BITMAP instead of GGO_METRICS because GGO_METRICS returns a smaller

-    // BlackBlox; we need the bigger one in case we need the image.  fAdvance is the same.

-    uint32_t ret = GetGlyphOutlineW(fDDC, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);

-

-    if (GDI_ERROR != ret) {

-        if (ret == 0) {

-            // for white space, ret is zero and gmBlackBoxX, gmBlackBoxY are 1 incorrectly!

-            gm.gmBlackBoxX = gm.gmBlackBoxY = 0;

-        }

-        glyph->fWidth   = gm.gmBlackBoxX;

-        glyph->fHeight  = gm.gmBlackBoxY;

-        glyph->fTop     = SkToS16(gm.gmptGlyphOrigin.y - gm.gmBlackBoxY);

-        glyph->fLeft    = SkToS16(gm.gmptGlyphOrigin.x);

-        glyph->fAdvanceX = SkIntToFixed(gm.gmCellIncX);

-        glyph->fAdvanceY = -SkIntToFixed(gm.gmCellIncY);

-    } else {

-        glyph->fWidth = 0;

-    }

-

-#if 0

-    char buf[1024];

-    sprintf(buf, "generateMetrics: id:%d, w=%d, h=%d, font:%s, fh:%d\n", glyph->fID, glyph->fWidth, glyph->fHeight, lf.lfFaceName, lf.lfHeight);

-    OutputDebugString(buf);

-#endif

-}

-

-void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) {

-// Note: This code was borrowed from generateLineHeight, which has a note

-// stating that it may be incorrect.

-    if (!(mx || my))

-      return;

-

-    SkASSERT(fDDC);

-

-    OUTLINETEXTMETRIC otm;

-

-    uint32_t ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);

-    if (sizeof(otm) != ret) {

-      return;

-    }

-

-    if (mx) {

-        mx->fTop = -fScale * otm.otmTextMetrics.tmAscent;

-		mx->fAscent = -fScale * otm.otmAscent;

-		mx->fDescent = -fScale * otm.otmDescent;

-		mx->fBottom = fScale * otm.otmTextMetrics.tmDescent;

-		mx->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading

-								 + otm.otmTextMetrics.tmExternalLeading);

-    }

-

-    if (my) {

-		my->fTop = -fScale * otm.otmTextMetrics.tmAscent;

-		my->fAscent = -fScale * otm.otmAscent;

-		my->fDescent = -fScale * otm.otmDescent;

-		my->fBottom = fScale * otm.otmTextMetrics.tmDescent;

-		my->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading

-								 + otm.otmTextMetrics.tmExternalLeading);

-    }

-}

-

-void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {

-

-    SkAutoMutexAcquire  ac(gFTMutex);

-

-    SkASSERT(fDDC);

-

-    GLYPHMETRICS gm;

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

-

-#if 0

-    char buf[1024];

-    sprintf(buf, "generateImage: id:%d, w=%d, h=%d, font:%s,fh:%d\n", glyph.fID, glyph.fWidth, glyph.fHeight, lf.lfFaceName, lf.lfHeight);

-    OutputDebugString(buf);

-#endif

-

-    uint32_t bytecount = 0;

-    uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);

-    if (GDI_ERROR != total_size && total_size > 0) {

-        uint8_t *pBuff = new uint8_t[total_size];

-        if (NULL != pBuff) {

-            total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, total_size, pBuff, &fMat22);

-

-            SkASSERT(total_size != GDI_ERROR);

-

-            SkASSERT(glyph.fWidth == gm.gmBlackBoxX);

-            SkASSERT(glyph.fHeight == gm.gmBlackBoxY);

-

-            uint8_t* dst = (uint8_t*)glyph.fImage;

-            uint32_t pitch = (gm.gmBlackBoxX + 3) & ~0x3;

-            if (pitch != glyph.rowBytes()) {

-                SkASSERT(false); // glyph.fImage has different rowsize!?

-            }

-

-            for (int32_t y = gm.gmBlackBoxY - 1; y >= 0; y--) {

-                uint8_t* src = pBuff + pitch * y;

-

-                for (uint32_t x = 0; x < gm.gmBlackBoxX; x++) {

-                    if (*src > 63) {

-                        *dst = 0xFF;

-                    }

-                    else {

-                        *dst = *src << 2; // scale to 0-255

-                    }

-                    dst++;

-                    src++;

-                    bytecount++;

-                }

-                memset(dst, 0, glyph.rowBytes() - glyph.fWidth);

-                dst += glyph.rowBytes() - glyph.fWidth;

-            }

-

-            delete[] pBuff;

-        }

-    }

-

-    SkASSERT(GDI_ERROR != total_size && total_size >= 0);

-

-}

-

-void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {

-

-    SkAutoMutexAcquire  ac(gFTMutex);

-

-    SkASSERT(&glyph && path);

-    SkASSERT(fDDC);

-

-    path->reset();

-

-#if 0

-    char buf[1024];

-    sprintf(buf, "generatePath: id:%d, w=%d, h=%d, font:%s,fh:%d\n", glyph.fID, glyph.fWidth, glyph.fHeight, lf.lfFaceName, lf.lfHeight);

-    OutputDebugString(buf);

-#endif

-

-    GLYPHMETRICS gm;

-    uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22);

-

-    if (GDI_ERROR != total_size) {

-

-        const uint8_t* cur_glyph = glyphbuf;

-        const uint8_t* end_glyph = glyphbuf + total_size;

-

-        while(cur_glyph < end_glyph) {

-            const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;

-

-            const uint8_t* end_poly = cur_glyph + th->cb;

-            const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);

-

-            path->moveTo(SkFixedToScalar(*(SkFixed*)(&th->pfxStart.x)), SkFixedToScalar(*(SkFixed*)(&th->pfxStart.y)));

-

-            while(cur_poly < end_poly) {

-                const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;

-

-                if (pc->wType == TT_PRIM_LINE) {

-                    for (uint16_t i = 0; i < pc->cpfx; i++) {

-                        path->lineTo(SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].x)), SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].y)));

-                    }

-                }

-

-                if (pc->wType == TT_PRIM_QSPLINE) {

-                    for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline

-                        POINTFX pnt_b = pc->apfx[u];    // B is always the current point

-                        POINTFX pnt_c = pc->apfx[u+1];

-

-                        if (u < pc->cpfx - 2) {          // If not on last spline, compute C

-                            pnt_c.x = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.x), *(SkFixed*)(&pnt_c.x)));

-                            pnt_c.y = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.y), *(SkFixed*)(&pnt_c.y)));

-                        }

-

-                        path->quadTo(SkFixedToScalar(*(SkFixed*)(&pnt_b.x)), SkFixedToScalar(*(SkFixed*)(&pnt_b.y)), SkFixedToScalar(*(SkFixed*)(&pnt_c.x)), SkFixedToScalar(*(SkFixed*)(&pnt_c.y)));

-                    }

-                }

-                cur_poly += sizeof(uint16_t) * 2 + sizeof(POINTFX) * pc->cpfx;

-            }

-            cur_glyph += th->cb;

-            path->close();

-        }

-    }

-    else {

-        SkASSERT(false);

-    }

-    //char buf[1024];

-    //sprintf(buf, "generatePath: count:%d\n", count);

-    //OutputDebugString(buf);

-}

-

-void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {

-    SkASSERT(!"SkFontHost::Serialize unimplemented");

-}

-

-SkTypeface* SkFontHost::Deserialize(SkStream* stream) {

-    SkASSERT(!"SkFontHost::Deserialize unimplemented");

-    return NULL;

-}

-

-static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) {

-    // Initialize the MAT2 structure to the identify transformation matrix.

-    static const MAT2 mat2 = {SkScalarToFIXED(1), SkScalarToFIXED(0),

-                        SkScalarToFIXED(0), SkScalarToFIXED(1)};

-    int flags = GGO_METRICS | GGO_GLYPH_INDEX;

-    GLYPHMETRICS gm;

-    if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, NULL, &mat2)) {

-        return false;

-    }

-    SkASSERT(advance);

-    *advance = gm.gmCellIncX;

-    return true;

-}

-

-// static

-SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(

-        uint32_t fontID, bool perGlyphInfo) {

-    SkAutoMutexAcquire ac(gFTMutex);

-    LogFontTypeface* rec = LogFontTypeface::FindById(fontID);

-    LOGFONT lf = rec->logFont();

-    SkAdvancedTypefaceMetrics* info = NULL;

-

-    HDC hdc = CreateCompatibleDC(NULL);

-    HFONT font = CreateFontIndirect(&lf);

-    HFONT savefont = (HFONT)SelectObject(hdc, font);

-    HFONT designFont = NULL;

-

-    // To request design units, create a logical font whose height is specified

-    // as unitsPerEm.

-    OUTLINETEXTMETRIC otm;

-    if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm) ||

-        !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) {

-        goto Error;

-    }

-    lf.lfHeight = -SkToS32(otm.otmEMSquare);

-    designFont = CreateFontIndirect(&lf);

-    SelectObject(hdc, designFont);

-    if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) {

-        goto Error;

-    }

-    const unsigned glyphCount = calculateGlyphCount(hdc);

-

-    info = new SkAdvancedTypefaceMetrics;

-    info->fEmSize = otm.otmEMSquare;

-    info->fMultiMaster = false;

-    info->fLastGlyphID = SkToU16(glyphCount - 1);

-    info->fStyle = 0;

-#ifdef UNICODE

-    // Get the buffer size needed first.

-    size_t str_len = WideCharToMultiByte(CP_UTF8, 0, lf.lfFaceName, -1, NULL,

-                                         0, NULL, NULL);

-    // Allocate a buffer (str_len already has terminating null accounted for).

-    char *familyName = new char[str_len];

-    // Now actually convert the string.

-    WideCharToMultiByte(CP_UTF8, 0, lf.lfFaceName, -1, familyName, str_len,

-                          NULL, NULL);

-    info->fFontName.set(familyName);

-    delete [] familyName;

-#else

-    info->fFontName.set(lf.lfFaceName);

-#endif

-

-    if (otm.otmTextMetrics.tmPitchAndFamily & TMPF_TRUETYPE) {

-        info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;

-    } else {

-        info->fType = SkAdvancedTypefaceMetrics::kOther_Font;

-        info->fItalicAngle = 0;

-        info->fAscent = 0;

-        info->fDescent = 0;

-        info->fStemV = 0;

-        info->fCapHeight = 0;

-        info->fBBox = SkIRect::MakeEmpty();

-        return info;

-    }

-    

-    // If this bit is clear the font is a fixed pitch font.

-    if (!(otm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {

-        info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;

-    }

-    if (otm.otmTextMetrics.tmItalic) {

-        info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;

-    }

-    // Setting symbolic style by default for now.

-    info->fStyle |= SkAdvancedTypefaceMetrics::kSymbolic_Style;

-    if (otm.otmTextMetrics.tmPitchAndFamily & FF_ROMAN) {

-        info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;

-    } else if (otm.otmTextMetrics.tmPitchAndFamily & FF_SCRIPT) {

-            info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;

-    }

-

-    // The main italic angle of the font, in tenths of a degree counterclockwise

-    // from vertical.

-    info->fItalicAngle = otm.otmItalicAngle / 10;

-    info->fAscent = SkToS16(otm.otmTextMetrics.tmAscent);

-    info->fDescent = SkToS16(-otm.otmTextMetrics.tmDescent);

-    // TODO(ctguil): Use alternate cap height calculation.

-    // MSDN says otmsCapEmHeight is not support but it is returning a value on

-    // my Win7 box.

-    info->fCapHeight = otm.otmsCapEmHeight;

-    info->fBBox =

-        SkIRect::MakeLTRB(otm.otmrcFontBox.left, otm.otmrcFontBox.top,

-                          otm.otmrcFontBox.right, otm.otmrcFontBox.bottom);

-

-    // Figure out a good guess for StemV - Min width of i, I, !, 1.

-    // This probably isn't very good with an italic font.

-    int16_t min_width = SHRT_MAX;

-    info->fStemV = 0;

-    char stem_chars[] = {'i', 'I', '!', '1'};

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

-        ABC abcWidths;

-        if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {

-            int16_t width = abcWidths.abcB;

-            if (width > 0 && width < min_width) {

-                min_width = width;

-                info->fStemV = min_width;

-            }

-        }

-    }

-

-    // If bit 1 is set, the font may not be embedded in a document.

-    // If bit 1 is clear, the font can be embedded.

-    // If bit 2 is set, the embedding is read-only.

-    if (otm.otmfsType & 0x1) {

-        info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;

-    } else if (perGlyphInfo) {

-        info->fGlyphWidths.reset(

-            getAdvanceData(hdc, glyphCount, &getWidthAdvance));

-    }

-

-Error:

-    SelectObject(hdc, savefont);

-    DeleteObject(designFont);

-    DeleteObject(font);

-    DeleteDC(hdc);

-

-    return info;

-}

-

-SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {

-

-    //Should not be used on Windows, keep linker happy

-    SkASSERT(false);

-    return SkCreateTypefaceFromLOGFONT(get_default_font());

-}

-

-SkStream* SkFontHost::OpenStream(SkFontID uniqueID) {

-    SkAutoMutexAcquire ac(gFTMutex);

-    LogFontTypeface* rec = LogFontTypeface::FindById(uniqueID);

-

-    HDC hdc = ::CreateCompatibleDC(NULL);

-    HFONT font = CreateFontIndirect(&rec->logFont());

-    HFONT savefont = (HFONT)SelectObject(hdc, font);

-

-    size_t bufferSize = GetFontData(hdc, 0, 0, NULL, 0);

-    SkMemoryStream* stream = new SkMemoryStream(bufferSize);

-    if (!GetFontData(hdc, 0, 0, (void*)stream->getMemoryBase(), bufferSize)) {

-        delete stream;

-        stream = NULL;

-    }

-

-    SelectObject(hdc, savefont);

-    DeleteObject(font);

-    DeleteDC(hdc);

-

-    return stream;

-}

-

-SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {

-    return SkNEW_ARGS(SkScalerContext_Windows, (desc));

-}

-

-/** Return the closest matching typeface given either an existing family

- (specified by a typeface in that family) or by a familyName, and a

- requested style.

- 1) If familyFace is null, use famillyName.

- 2) If famillyName is null, use familyFace.

- 3) If both are null, return the default font that best matches style

- This MUST not return NULL.

- */

-

-SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,

-                                       const char familyName[],

-                                       const void* data, size_t bytelength,

-                                       SkTypeface::Style style) {

-

-    static SkTypeface* gDefaultTypeface;

-    SkAutoMutexAcquire  ac(gFTMutex);

-

-#ifndef CAN_USE_LOGFONT_NAME

-    familyName = NULL;

-    familyFace = NULL;

-#endif

-

-    // clip to legal style bits

-    style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);

-

-    SkTypeface* tf = NULL;

-    if (NULL == familyFace && NULL == familyName) {

-        LOGFONT lf = get_default_font();

-        lf.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ;

-        lf.lfItalic = ((style & SkTypeface::kItalic) != 0);

-        // hack until we figure out if SkTypeface should cache this itself

-        if (style == SkTypeface::kNormal) {

-            if (NULL == gDefaultTypeface) {

-                gDefaultTypeface = SkCreateTypefaceFromLOGFONT(lf);

-            }

-            tf = gDefaultTypeface;

-            tf->ref();

-        } else {

-            tf = SkCreateTypefaceFromLOGFONT(lf);

-        }

-    } else {

-#ifdef CAN_USE_LOGFONT_NAME

-        LOGFONT lf;

-        if (NULL != familyFace) {

-            uint32_t id = familyFace->uniqueID();

-            LogFontTypeface* rec = LogFontTypeface::FindById(id);

-            if (!rec) {

-                SkASSERT(false);

-                lf = get_default_font();

-            }

-            else {

-                lf = rec->logFont();

-            }

-        }

-        else {

-            memset(&lf, 0, sizeof(LOGFONT));

-

-            lf.lfHeight = -11; // default

-            lf.lfQuality = PROOF_QUALITY;

-            lf.lfCharSet = DEFAULT_CHARSET;

-

-#ifdef UNICODE

-            // Get the buffer size needed first.

-            size_t str_len = ::MultiByteToWideChar(CP_UTF8, 0, familyName,

-                                                   -1, NULL, 0);

-            // Allocate a buffer (str_len already has terminating null

-            // accounted for).

-            wchar_t *wideFamilyName = new wchar_t[str_len];

-            // Now actually convert the string.

-            ::MultiByteToWideChar(CP_UTF8, 0, familyName, -1,

-                                  wideFamilyName, str_len);

-            ::wcsncpy(lf.lfFaceName, wideFamilyName, LF_FACESIZE);

-            delete [] wideFamilyName;

-#else

-            ::strncpy(lf.lfFaceName, familyName, LF_FACESIZE);

-#endif

-            lf.lfFaceName[LF_FACESIZE-1] = '\0';

-        }

-

-        // use the style desired

-        lf.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ;

-        lf.lfItalic = ((style & SkTypeface::kItalic) != 0);

-        tf = SkCreateTypefaceFromLOGFONT(lf);

-#endif

-    }

-

-    if (NULL == tf) {

-        tf = SkCreateTypefaceFromLOGFONT(get_default_font());

-    }

-    return tf;

-}

-

-size_t SkFontHost::ShouldPurgeFontCache(size_t sizeAllocatedSoFar) {

-    if (sizeAllocatedSoFar > FONT_CACHE_MEMORY_BUDGET)

-        return sizeAllocatedSoFar - FONT_CACHE_MEMORY_BUDGET;

-    else

-        return 0;   // nothing to do

-}

-

-int SkFontHost::ComputeGammaFlag(const SkPaint& paint) {

-    return 0;

-}

-

-void SkFontHost::GetGammaTables(const uint8_t* tables[2]) {

-    tables[0] = NULL;   // black gamma (e.g. exp=1.4)

-    tables[1] = NULL;   // white gamma (e.g. exp= 1/1.4)

-}

-

-SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {

-    printf("SkFontHost::CreateTypefaceFromFile unimplemented");

-    return NULL;

-}

-

-void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {

-    // We don't control the hinting nor ClearType settings here

-    rec->setHinting(SkPaint::kNormal_Hinting);

-    if (SkMask::FormatIsLCD((SkMask::Format)rec->fMaskFormat)) {

-        rec->fMaskFormat = SkMask::kA8_Format;

-    }

-}

-

-#endif // WIN32

+/*
+ ** Copyright 2006, The Android Open Source Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ **     http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+
+#include "SkString.h"
+//#include "SkStream.h"
+
+#include "SkEndian.h"
+#include "SkFontHost.h"
+#include "SkDescriptor.h"
+#include "SkAdvancedTypefaceMetrics.h"
+#include "SkStream.h"
+#include "SkThread.h"
+#include "SkTypeface_win.h"
+#include "SkUtils.h"
+
+#ifdef WIN32
+#include "windows.h"
+#include "tchar.h"
+#include "Usp10.h"
+
+// client3d has to undefine this for now
+#define CAN_USE_LOGFONT_NAME
+
+using namespace skia_advanced_typeface_metrics_utils;
+
+static SkMutex gFTMutex;
+
+static const uint16_t BUFFERSIZE = (16384 - 32);
+static uint8_t glyphbuf[BUFFERSIZE];
+
+// Give 1MB font cache budget
+#define FONT_CACHE_MEMORY_BUDGET    (1024 * 1024)
+
+/**
+ *	Since LOGFONT wants its textsize as an int, and we support fractional sizes,
+ *  and since we have a cache of LOGFONTs for our tyepfaces, we always set the
+ *  lfHeight to a canonical size, and then we use the 2x2 matrix to achieve the
+ *  actual requested size.
+ */
+static const int gCanonicalTextSize = 64;
+
+static void make_canonical(LOGFONT* lf) {
+	lf->lfHeight = -gCanonicalTextSize;
+}
+
+static inline FIXED SkFixedToFIXED(SkFixed x) {
+    return *(FIXED*)(&x);
+}
+
+static inline FIXED SkScalarToFIXED(SkScalar x) {
+    return SkFixedToFIXED(SkScalarToFixed(x));
+}
+
+static unsigned calculateGlyphCount(HDC hdc) {
+    // The 'maxp' table stores the number of glyphs at offset 4, in 2 bytes.
+    const DWORD maxpTag = *(DWORD*) "maxp";
+    uint16_t glyphs;
+    if (GetFontData(hdc, maxpTag, 4, &glyphs, sizeof(glyphs)) != GDI_ERROR) {
+        return SkEndian_SwapBE16(glyphs);
+    }
+    
+    // Binary search for glyph count.
+    static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
+    int32_t max = SK_MaxU16 + 1;
+    int32_t min = 0;
+    GLYPHMETRICS gm;
+    while (min < max) {
+        int32_t mid = min + ((max - min) / 2);
+        if (GetGlyphOutlineW(hdc, mid, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0,
+                             NULL, &mat2) == GDI_ERROR) {
+            max = mid;
+        } else {
+            min = mid + 1;
+        }
+    }
+    SkASSERT(min == max);
+    return min;
+}
+
+static SkTypeface::Style GetFontStyle(const LOGFONT& lf) {
+    int style = SkTypeface::kNormal;
+    if (lf.lfWeight == FW_SEMIBOLD || lf.lfWeight == FW_DEMIBOLD || lf.lfWeight == FW_BOLD)
+        style |= SkTypeface::kBold;
+    if (lf.lfItalic)
+        style |= SkTypeface::kItalic;
+
+    return (SkTypeface::Style)style;
+}
+
+// have to do this because SkTypeface::SkTypeface() is protected
+class LogFontTypeface : public SkTypeface {
+private:
+    static SkMutex                  gMutex;
+    static LogFontTypeface*         gHead;
+    static int32_t                  gCurrId;
+
+    LogFontTypeface*                fNext;
+    LOGFONT                         fLogFont;
+
+public:
+
+    LogFontTypeface(Style style, const LOGFONT& logFont) :
+      SkTypeface(style, sk_atomic_inc(&gCurrId)+1), // 0 id is reserved so add 1
+      fLogFont(logFont)
+    {
+		make_canonical(&fLogFont);
+
+        SkAutoMutexAcquire am(gMutex);
+        fNext = gHead;
+        gHead = this;
+    }
+
+    const LOGFONT& logFont() const { return fLogFont; }
+
+    virtual ~LogFontTypeface() {
+        SkAutoMutexAcquire am(gMutex);
+        if (gHead == this) {
+            gHead = fNext;
+            return;
+        }
+
+        LogFontTypeface* prev = gHead;
+        SkASSERT(prev);
+        while (prev->fNext != this) {
+            prev = prev->fNext;
+            SkASSERT(prev);
+        }
+        prev->fNext = fNext;
+    }
+
+    static LogFontTypeface* FindById(uint32_t id){
+        SkASSERT(gHead);
+        LogFontTypeface* curr = gHead;
+        while (curr->uniqueID() != id) {
+            curr = curr->fNext;
+            SkASSERT(curr);
+        }
+        return curr;
+    }
+
+    static LogFontTypeface* FindByLogFont(const LOGFONT& lf)
+    {
+		LOGFONT canonical = lf;
+		make_canonical(&canonical);
+
+        LogFontTypeface* curr = gHead;
+        while (curr && memcmp(&curr->fLogFont, &canonical, sizeof(LOGFONT))) {
+            curr = curr->fNext;
+        }
+        return curr;
+    }
+};
+
+LogFontTypeface* LogFontTypeface::gHead;
+int32_t LogFontTypeface::gCurrId;
+SkMutex LogFontTypeface::gMutex;
+
+static const LOGFONT& get_default_font() {
+    static LOGFONT gDefaultFont;
+    // don't hardcode on Windows, Win2000, XP, Vista, and international all have different default
+    // and the user could change too
+
+
+//  lfMessageFont is garbage on my XP, so skip for now
+#if 0
+    if (gDefaultFont.lfFaceName[0] != 0) {
+        return gDefaultFont;
+    }
+
+    NONCLIENTMETRICS ncm;
+    ncm.cbSize = sizeof(NONCLIENTMETRICS);
+    SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
+
+    //memcpy(&gDefaultFont, &(ncm.lfMessageFont), sizeof(LOGFONT));
+#endif
+
+    return gDefaultFont;
+}
+
+SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& lf) {
+    LogFontTypeface* ptypeface = LogFontTypeface::FindByLogFont(lf);
+
+    if (NULL == ptypeface) {
+        SkTypeface::Style style = GetFontStyle(lf);
+        ptypeface = new LogFontTypeface(style, lf);
+    } else {
+	    ptypeface->ref();
+	}
+    return ptypeface;
+}
+
+uint32_t SkFontHost::NextLogicalFont(uint32_t fontID) {
+  // Zero means that we don't have any fallback fonts for this fontID.
+  // This function is implemented on Android, but doesn't have much
+  // meaning here.
+  return 0;
+}
+
+class SkScalerContext_Windows : public SkScalerContext {
+public:
+    SkScalerContext_Windows(const SkDescriptor* desc);
+    virtual ~SkScalerContext_Windows();
+
+protected:
+    virtual unsigned generateGlyphCount();
+    virtual uint16_t generateCharToGlyph(SkUnichar uni);
+    virtual void generateAdvance(SkGlyph* glyph);
+    virtual void generateMetrics(SkGlyph* glyph);
+    virtual void generateImage(const SkGlyph& glyph);
+    virtual void generatePath(const SkGlyph& glyph, SkPath* path);
+    virtual void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY);
+    //virtual SkDeviceContext getDC() {return ddc;}
+private:
+	SkScalar	 fScale;	// to get from canonical size to real size
+    MAT2         fMat22;
+    XFORM        fXform;
+    HDC          fDDC;
+    HFONT        fSavefont;
+    HFONT        fFont;
+    SCRIPT_CACHE fSC;
+    int          fGlyphCount;
+};
+
+static float mul2float(SkScalar a, SkScalar b) {
+    return SkScalarToFloat(SkScalarMul(a, b));
+}
+
+static FIXED float2FIXED(float x) {
+    return SkFixedToFIXED(SkFloatToFixed(x));
+}
+
+SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc)
+        : SkScalerContext(desc), fDDC(0), fFont(0), fSavefont(0), fSC(0)
+        , fGlyphCount(-1) {
+    SkAutoMutexAcquire  ac(gFTMutex);
+
+	fScale = fRec.fTextSize / gCanonicalTextSize;
+
+    fXform.eM11 = mul2float(fScale, fRec.fPost2x2[0][0]);
+    fXform.eM12 = mul2float(fScale, fRec.fPost2x2[1][0]);
+    fXform.eM21 = mul2float(fScale, fRec.fPost2x2[0][1]);
+    fXform.eM22 = mul2float(fScale, fRec.fPost2x2[1][1]);
+    fXform.eDx = 0;
+    fXform.eDy = 0;
+
+    fMat22.eM11 = float2FIXED(fXform.eM11);
+    fMat22.eM12 = float2FIXED(fXform.eM12);
+    fMat22.eM21 = float2FIXED(-fXform.eM21);
+    fMat22.eM22 = float2FIXED(-fXform.eM22);
+
+    fDDC = ::CreateCompatibleDC(NULL);
+    SetBkMode(fDDC, TRANSPARENT);
+
+    // Scaling by the DPI is inconsistent with how Skia draws elsewhere
+    //SkScalar height = -(fRec.fTextSize * GetDeviceCaps(ddc, LOGPIXELSY) / 72);
+    LOGFONT lf = LogFontTypeface::FindById(fRec.fFontID)->logFont();
+    lf.lfHeight = -gCanonicalTextSize;
+    fFont = CreateFontIndirect(&lf);
+    fSavefont = (HFONT)SelectObject(fDDC, fFont);
+}
+
+SkScalerContext_Windows::~SkScalerContext_Windows() {
+    if (fDDC) {
+        ::SelectObject(fDDC, fSavefont);
+        ::DeleteDC(fDDC);
+    }
+    if (fFont) {
+        ::DeleteObject(fFont);
+    }
+    if (fSC) {
+        ::ScriptFreeCache(&fSC);
+    }
+}
+
+unsigned SkScalerContext_Windows::generateGlyphCount() {
+    if (fGlyphCount < 0) {
+        fGlyphCount = calculateGlyphCount(fDDC);
+    }
+    return fGlyphCount;
+}
+
+uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {
+    uint16_t index = 0;
+    WCHAR c[2];
+    // TODO(ctguil): Support characters that generate more than one glyph.
+    if (SkUTF16_FromUnichar(uni, (uint16_t*)c) == 1) {
+        // Type1 fonts fail with uniscribe API. Use GetGlyphIndices for plane 0.
+        SkAssertResult(GetGlyphIndicesW(fDDC, c, 1, &index, 0));
+    } else {
+        // Use uniscribe to detemine glyph index for non-BMP characters.
+        // Need to add extra item to SCRIPT_ITEM to work around a bug in older
+        // windows versions. https://bugzilla.mozilla.org/show_bug.cgi?id=366643
+        SCRIPT_ITEM si[2 + 1];
+        int items;
+        SkAssertResult(
+            SUCCEEDED(ScriptItemize(c, 2, 2, NULL, NULL, si, &items)));
+
+        WORD log[2];
+        SCRIPT_VISATTR vsa;
+        int glyphs;
+        SkAssertResult(SUCCEEDED(ScriptShape(
+            fDDC, &fSC, c, 2, 1, &si[0].a, &index, log, &vsa, &glyphs)));
+    }
+    return index;
+}
+
+void SkScalerContext_Windows::generateAdvance(SkGlyph* glyph) {
+    this->generateMetrics(glyph);
+}
+
+void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {
+
+    SkASSERT(fDDC);
+
+    GLYPHMETRICS gm;
+    memset(&gm, 0, sizeof(gm));
+
+    glyph->fRsbDelta = 0;
+    glyph->fLsbDelta = 0;
+
+    // Note: need to use GGO_GRAY8_BITMAP instead of GGO_METRICS because GGO_METRICS returns a smaller
+    // BlackBlox; we need the bigger one in case we need the image.  fAdvance is the same.
+    uint32_t ret = GetGlyphOutlineW(fDDC, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
+
+    if (GDI_ERROR != ret) {
+        if (ret == 0) {
+            // for white space, ret is zero and gmBlackBoxX, gmBlackBoxY are 1 incorrectly!
+            gm.gmBlackBoxX = gm.gmBlackBoxY = 0;
+        }
+        glyph->fWidth   = gm.gmBlackBoxX;
+        glyph->fHeight  = gm.gmBlackBoxY;
+        glyph->fTop     = SkToS16(gm.gmptGlyphOrigin.y - gm.gmBlackBoxY);
+        glyph->fLeft    = SkToS16(gm.gmptGlyphOrigin.x);
+        glyph->fAdvanceX = SkIntToFixed(gm.gmCellIncX);
+        glyph->fAdvanceY = -SkIntToFixed(gm.gmCellIncY);
+
+        // we outset by 1 in all dimensions, since the lcd image may bleed outside
+        // of the computed bounds returned by GetGlyphOutline.
+        // This was deduced by trial and error for small text (e.g. 8pt), so there
+        // maybe a more precise way to make this adjustment...
+        if (SkMask::kLCD16_Format == fRec.fMaskFormat) {
+            glyph->fWidth += 2;
+            glyph->fHeight += 2;
+            glyph->fTop -= 1;
+            glyph->fLeft -= 1;
+        }
+    } else {
+        glyph->fWidth = 0;
+    }
+}
+
+void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) {
+// Note: This code was borrowed from generateLineHeight, which has a note
+// stating that it may be incorrect.
+    if (!(mx || my))
+      return;
+
+    SkASSERT(fDDC);
+
+    OUTLINETEXTMETRIC otm;
+
+    uint32_t ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
+    if (sizeof(otm) != ret) {
+      return;
+    }
+
+    if (mx) {
+        mx->fTop = -fScale * otm.otmTextMetrics.tmAscent;
+		mx->fAscent = -fScale * otm.otmAscent;
+		mx->fDescent = -fScale * otm.otmDescent;
+		mx->fBottom = fScale * otm.otmTextMetrics.tmDescent;
+		mx->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading
+								 + otm.otmTextMetrics.tmExternalLeading);
+    }
+
+    if (my) {
+		my->fTop = -fScale * otm.otmTextMetrics.tmAscent;
+		my->fAscent = -fScale * otm.otmAscent;
+		my->fDescent = -fScale * otm.otmDescent;
+		my->fBottom = fScale * otm.otmTextMetrics.tmDescent;
+		my->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading
+								 + otm.otmTextMetrics.tmExternalLeading);
+    }
+}
+
+#include "SkColorPriv.h"
+
+static inline uint16_t rgb_to_lcd16(uint32_t rgb) {
+    int r = (rgb >> 16) & 0xFF;
+    int g = (rgb >>  8) & 0xFF;
+    int b = (rgb >>  0) & 0xFF;
+
+    // invert, since we draw black-on-white, but we want the original
+    // src mask values.
+    r = 255 - r;
+    g = 255 - g;
+    b = 255 - b;
+    return SkPackRGB16(SkR32ToR16(r), SkG32ToG16(g), SkB32ToB16(b));
+}
+
+void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
+
+    SkAutoMutexAcquire  ac(gFTMutex);
+
+    SkASSERT(fDDC);
+
+    if (SkMask::kLCD16_Format == fRec.fMaskFormat) {
+        HDC dc = CreateCompatibleDC(0);
+        void* bits = 0;
+        BITMAPINFO info;
+        sk_bzero(&info, sizeof(info));
+        info.bmiHeader.biSize = sizeof(info.bmiHeader);
+        info.bmiHeader.biWidth = glyph.fWidth;
+        info.bmiHeader.biHeight = glyph.fHeight;
+        info.bmiHeader.biPlanes = 1;
+        info.bmiHeader.biBitCount = 32;
+        info.bmiHeader.biCompression = BI_RGB;
+        HBITMAP bm = CreateDIBSection(dc, &info, DIB_RGB_COLORS, &bits, 0, 0);
+        SelectObject(dc, bm);
+
+        // erase to white
+        size_t srcRB = glyph.fWidth << 2;
+        size_t size = glyph.fHeight * srcRB;
+        memset(bits, 0xFF, size);
+
+        SetBkMode(dc, TRANSPARENT);
+        SetTextAlign(dc, TA_LEFT | TA_BASELINE);
+        SetGraphicsMode(dc, GM_ADVANCED);
+
+        XFORM xform = fXform;
+        xform.eDx = (float)-glyph.fLeft;
+        xform.eDy = (float)-glyph.fTop;
+        SetWorldTransform(dc, &xform);
+
+        HGDIOBJ prevFont = SelectObject(dc, fFont);
+        COLORREF color = SetTextColor(dc, 0); // black
+        SkASSERT(color != CLR_INVALID);
+        uint16_t glyphID = glyph.getGlyphID();
+        ExtTextOut(dc, 0, 0, ETO_GLYPH_INDEX, NULL, (LPCWSTR)&glyphID, 1, NULL);
+        GdiFlush();
+
+        // downsample from rgba to rgb565
+        int width = glyph.fWidth;
+        size_t dstRB = glyph.rowBytes();
+        const uint32_t* src = (const uint32_t*)bits;
+        // gdi's bitmap is upside-down, so we reverse dst walking in Y
+        uint16_t* dst = (uint16_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
+        for (int y = 0; y < glyph.fHeight; y++) {
+            for (int i = 0; i < width; i++) {
+                dst[i] = rgb_to_lcd16(src[i]);
+            }
+            src = (const uint32_t*)((const char*)src + srcRB);
+            dst = (uint16_t*)((char*)dst - dstRB);
+        }
+
+        DeleteDC(dc);
+        DeleteObject(bm);
+        return;
+    }
+
+    GLYPHMETRICS gm;
+    memset(&gm, 0, sizeof(gm));
+    uint32_t bytecount = 0;
+    uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
+    if (GDI_ERROR != total_size && total_size > 0) {
+        uint8_t *pBuff = new uint8_t[total_size];
+        if (NULL != pBuff) {
+            total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, total_size, pBuff, &fMat22);
+
+            SkASSERT(total_size != GDI_ERROR);
+
+            SkASSERT(glyph.fWidth == gm.gmBlackBoxX);
+            SkASSERT(glyph.fHeight == gm.gmBlackBoxY);
+
+            uint8_t* dst = (uint8_t*)glyph.fImage;
+            uint32_t pitch = (gm.gmBlackBoxX + 3) & ~0x3;
+            if (pitch != glyph.rowBytes()) {
+                SkASSERT(false); // glyph.fImage has different rowsize!?
+            }
+
+            for (int32_t y = gm.gmBlackBoxY - 1; y >= 0; y--) {
+                uint8_t* src = pBuff + pitch * y;
+
+                for (uint32_t x = 0; x < gm.gmBlackBoxX; x++) {
+                    if (*src > 63) {
+                        *dst = 0xFF;
+                    }
+                    else {
+                        *dst = *src << 2; // scale to 0-255
+                    }
+                    dst++;
+                    src++;
+                    bytecount++;
+                }
+                memset(dst, 0, glyph.rowBytes() - glyph.fWidth);
+                dst += glyph.rowBytes() - glyph.fWidth;
+            }
+
+            delete[] pBuff;
+        }
+    }
+
+    SkASSERT(GDI_ERROR != total_size && total_size >= 0);
+
+}
+
+void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
+
+    SkAutoMutexAcquire  ac(gFTMutex);
+
+    SkASSERT(&glyph && path);
+    SkASSERT(fDDC);
+
+    path->reset();
+
+#if 0
+    char buf[1024];
+    sprintf(buf, "generatePath: id:%d, w=%d, h=%d, font:%s,fh:%d\n", glyph.fID, glyph.fWidth, glyph.fHeight, lf.lfFaceName, lf.lfHeight);
+    OutputDebugString(buf);
+#endif
+
+    GLYPHMETRICS gm;
+    uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22);
+
+    if (GDI_ERROR != total_size) {
+
+        const uint8_t* cur_glyph = glyphbuf;
+        const uint8_t* end_glyph = glyphbuf + total_size;
+
+        while(cur_glyph < end_glyph) {
+            const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
+
+            const uint8_t* end_poly = cur_glyph + th->cb;
+            const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
+
+            path->moveTo(SkFixedToScalar(*(SkFixed*)(&th->pfxStart.x)), SkFixedToScalar(*(SkFixed*)(&th->pfxStart.y)));
+
+            while(cur_poly < end_poly) {
+                const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
+
+                if (pc->wType == TT_PRIM_LINE) {
+                    for (uint16_t i = 0; i < pc->cpfx; i++) {
+                        path->lineTo(SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].x)), SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].y)));
+                    }
+                }
+
+                if (pc->wType == TT_PRIM_QSPLINE) {
+                    for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
+                        POINTFX pnt_b = pc->apfx[u];    // B is always the current point
+                        POINTFX pnt_c = pc->apfx[u+1];
+
+                        if (u < pc->cpfx - 2) {          // If not on last spline, compute C
+                            pnt_c.x = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.x), *(SkFixed*)(&pnt_c.x)));
+                            pnt_c.y = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.y), *(SkFixed*)(&pnt_c.y)));
+                        }
+
+                        path->quadTo(SkFixedToScalar(*(SkFixed*)(&pnt_b.x)), SkFixedToScalar(*(SkFixed*)(&pnt_b.y)), SkFixedToScalar(*(SkFixed*)(&pnt_c.x)), SkFixedToScalar(*(SkFixed*)(&pnt_c.y)));
+                    }
+                }
+                cur_poly += sizeof(uint16_t) * 2 + sizeof(POINTFX) * pc->cpfx;
+            }
+            cur_glyph += th->cb;
+            path->close();
+        }
+    }
+    else {
+        SkASSERT(false);
+    }
+    //char buf[1024];
+    //sprintf(buf, "generatePath: count:%d\n", count);
+    //OutputDebugString(buf);
+}
+
+void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
+    SkASSERT(!"SkFontHost::Serialize unimplemented");
+}
+
+SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
+    SkASSERT(!"SkFontHost::Deserialize unimplemented");
+    return NULL;
+}
+
+static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) {
+    // Initialize the MAT2 structure to the identify transformation matrix.
+    static const MAT2 mat2 = {SkScalarToFIXED(1), SkScalarToFIXED(0),
+                        SkScalarToFIXED(0), SkScalarToFIXED(1)};
+    int flags = GGO_METRICS | GGO_GLYPH_INDEX;
+    GLYPHMETRICS gm;
+    if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, NULL, &mat2)) {
+        return false;
+    }
+    SkASSERT(advance);
+    *advance = gm.gmCellIncX;
+    return true;
+}
+
+// static
+SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
+        uint32_t fontID, bool perGlyphInfo) {
+    SkAutoMutexAcquire ac(gFTMutex);
+    LogFontTypeface* rec = LogFontTypeface::FindById(fontID);
+    LOGFONT lf = rec->logFont();
+    SkAdvancedTypefaceMetrics* info = NULL;
+
+    HDC hdc = CreateCompatibleDC(NULL);
+    HFONT font = CreateFontIndirect(&lf);
+    HFONT savefont = (HFONT)SelectObject(hdc, font);
+    HFONT designFont = NULL;
+
+    // To request design units, create a logical font whose height is specified
+    // as unitsPerEm.
+    OUTLINETEXTMETRIC otm;
+    if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm) ||
+        !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) {
+        goto Error;
+    }
+    lf.lfHeight = -SkToS32(otm.otmEMSquare);
+    designFont = CreateFontIndirect(&lf);
+    SelectObject(hdc, designFont);
+    if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) {
+        goto Error;
+    }
+    const unsigned glyphCount = calculateGlyphCount(hdc);
+
+    info = new SkAdvancedTypefaceMetrics;
+    info->fEmSize = otm.otmEMSquare;
+    info->fMultiMaster = false;
+    info->fLastGlyphID = SkToU16(glyphCount - 1);
+    info->fStyle = 0;
+#ifdef UNICODE
+    // Get the buffer size needed first.
+    size_t str_len = WideCharToMultiByte(CP_UTF8, 0, lf.lfFaceName, -1, NULL,
+                                         0, NULL, NULL);
+    // Allocate a buffer (str_len already has terminating null accounted for).
+    char *familyName = new char[str_len];
+    // Now actually convert the string.
+    WideCharToMultiByte(CP_UTF8, 0, lf.lfFaceName, -1, familyName, str_len,
+                          NULL, NULL);
+    info->fFontName.set(familyName);
+    delete [] familyName;
+#else
+    info->fFontName.set(lf.lfFaceName);
+#endif
+
+    if (otm.otmTextMetrics.tmPitchAndFamily & TMPF_TRUETYPE) {
+        info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
+    } else {
+        info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
+        info->fItalicAngle = 0;
+        info->fAscent = 0;
+        info->fDescent = 0;
+        info->fStemV = 0;
+        info->fCapHeight = 0;
+        info->fBBox = SkIRect::MakeEmpty();
+        return info;
+    }
+    
+    // If this bit is clear the font is a fixed pitch font.
+    if (!(otm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
+        info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
+    }
+    if (otm.otmTextMetrics.tmItalic) {
+        info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
+    }
+    // Setting symbolic style by default for now.
+    info->fStyle |= SkAdvancedTypefaceMetrics::kSymbolic_Style;
+    if (otm.otmTextMetrics.tmPitchAndFamily & FF_ROMAN) {
+        info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
+    } else if (otm.otmTextMetrics.tmPitchAndFamily & FF_SCRIPT) {
+            info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
+    }
+
+    // The main italic angle of the font, in tenths of a degree counterclockwise
+    // from vertical.
+    info->fItalicAngle = otm.otmItalicAngle / 10;
+    info->fAscent = SkToS16(otm.otmTextMetrics.tmAscent);
+    info->fDescent = SkToS16(-otm.otmTextMetrics.tmDescent);
+    // TODO(ctguil): Use alternate cap height calculation.
+    // MSDN says otmsCapEmHeight is not support but it is returning a value on
+    // my Win7 box.
+    info->fCapHeight = otm.otmsCapEmHeight;
+    info->fBBox =
+        SkIRect::MakeLTRB(otm.otmrcFontBox.left, otm.otmrcFontBox.top,
+                          otm.otmrcFontBox.right, otm.otmrcFontBox.bottom);
+
+    // Figure out a good guess for StemV - Min width of i, I, !, 1.
+    // This probably isn't very good with an italic font.
+    int16_t min_width = SHRT_MAX;
+    info->fStemV = 0;
+    char stem_chars[] = {'i', 'I', '!', '1'};
+    for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
+        ABC abcWidths;
+        if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
+            int16_t width = abcWidths.abcB;
+            if (width > 0 && width < min_width) {
+                min_width = width;
+                info->fStemV = min_width;
+            }
+        }
+    }
+
+    // If bit 1 is set, the font may not be embedded in a document.
+    // If bit 1 is clear, the font can be embedded.
+    // If bit 2 is set, the embedding is read-only.
+    if (otm.otmfsType & 0x1) {
+        info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
+    } else if (perGlyphInfo) {
+        info->fGlyphWidths.reset(
+            getAdvanceData(hdc, glyphCount, &getWidthAdvance));
+    }
+
+Error:
+    SelectObject(hdc, savefont);
+    DeleteObject(designFont);
+    DeleteObject(font);
+    DeleteDC(hdc);
+
+    return info;
+}
+
+SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
+
+    //Should not be used on Windows, keep linker happy
+    SkASSERT(false);
+    return SkCreateTypefaceFromLOGFONT(get_default_font());
+}
+
+SkStream* SkFontHost::OpenStream(SkFontID uniqueID) {
+    SkAutoMutexAcquire ac(gFTMutex);
+    LogFontTypeface* rec = LogFontTypeface::FindById(uniqueID);
+
+    HDC hdc = ::CreateCompatibleDC(NULL);
+    HFONT font = CreateFontIndirect(&rec->logFont());
+    HFONT savefont = (HFONT)SelectObject(hdc, font);
+
+    size_t bufferSize = GetFontData(hdc, 0, 0, NULL, 0);
+    SkMemoryStream* stream = new SkMemoryStream(bufferSize);
+    if (!GetFontData(hdc, 0, 0, (void*)stream->getMemoryBase(), bufferSize)) {
+        delete stream;
+        stream = NULL;
+    }
+
+    SelectObject(hdc, savefont);
+    DeleteObject(font);
+    DeleteDC(hdc);
+
+    return stream;
+}
+
+SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) {
+    return SkNEW_ARGS(SkScalerContext_Windows, (desc));
+}
+
+/** Return the closest matching typeface given either an existing family
+ (specified by a typeface in that family) or by a familyName, and a
+ requested style.
+ 1) If familyFace is null, use famillyName.
+ 2) If famillyName is null, use familyFace.
+ 3) If both are null, return the default font that best matches style
+ This MUST not return NULL.
+ */
+
+SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
+                                       const char familyName[],
+                                       const void* data, size_t bytelength,
+                                       SkTypeface::Style style) {
+
+    static SkTypeface* gDefaultTypeface;
+    SkAutoMutexAcquire  ac(gFTMutex);
+
+#ifndef CAN_USE_LOGFONT_NAME
+    familyName = NULL;
+    familyFace = NULL;
+#endif
+
+    // clip to legal style bits
+    style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);
+
+    SkTypeface* tf = NULL;
+    if (NULL == familyFace && NULL == familyName) {
+        LOGFONT lf = get_default_font();
+        lf.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ;
+        lf.lfItalic = ((style & SkTypeface::kItalic) != 0);
+        // hack until we figure out if SkTypeface should cache this itself
+        if (style == SkTypeface::kNormal) {
+            if (NULL == gDefaultTypeface) {
+                gDefaultTypeface = SkCreateTypefaceFromLOGFONT(lf);
+            }
+            tf = gDefaultTypeface;
+            tf->ref();
+        } else {
+            tf = SkCreateTypefaceFromLOGFONT(lf);
+        }
+    } else {
+#ifdef CAN_USE_LOGFONT_NAME
+        LOGFONT lf;
+        if (NULL != familyFace) {
+            uint32_t id = familyFace->uniqueID();
+            LogFontTypeface* rec = LogFontTypeface::FindById(id);
+            if (!rec) {
+                SkASSERT(false);
+                lf = get_default_font();
+            }
+            else {
+                lf = rec->logFont();
+            }
+        }
+        else {
+            memset(&lf, 0, sizeof(LOGFONT));
+
+            lf.lfHeight = -11; // default
+            lf.lfQuality = PROOF_QUALITY;
+            lf.lfCharSet = DEFAULT_CHARSET;
+
+#ifdef UNICODE
+            // Get the buffer size needed first.
+            size_t str_len = ::MultiByteToWideChar(CP_UTF8, 0, familyName,
+                                                   -1, NULL, 0);
+            // Allocate a buffer (str_len already has terminating null
+            // accounted for).
+            wchar_t *wideFamilyName = new wchar_t[str_len];
+            // Now actually convert the string.
+            ::MultiByteToWideChar(CP_UTF8, 0, familyName, -1,
+                                  wideFamilyName, str_len);
+            ::wcsncpy(lf.lfFaceName, wideFamilyName, LF_FACESIZE);
+            delete [] wideFamilyName;
+#else
+            ::strncpy(lf.lfFaceName, familyName, LF_FACESIZE);
+#endif
+            lf.lfFaceName[LF_FACESIZE-1] = '\0';
+        }
+
+        // use the style desired
+        lf.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ;
+        lf.lfItalic = ((style & SkTypeface::kItalic) != 0);
+        tf = SkCreateTypefaceFromLOGFONT(lf);
+#endif
+    }
+
+    if (NULL == tf) {
+        tf = SkCreateTypefaceFromLOGFONT(get_default_font());
+    }
+    return tf;
+}
+
+size_t SkFontHost::ShouldPurgeFontCache(size_t sizeAllocatedSoFar) {
+    if (sizeAllocatedSoFar > FONT_CACHE_MEMORY_BUDGET)
+        return sizeAllocatedSoFar - FONT_CACHE_MEMORY_BUDGET;
+    else
+        return 0;   // nothing to do
+}
+
+int SkFontHost::ComputeGammaFlag(const SkPaint& paint) {
+    return 0;
+}
+
+void SkFontHost::GetGammaTables(const uint8_t* tables[2]) {
+    tables[0] = NULL;   // black gamma (e.g. exp=1.4)
+    tables[1] = NULL;   // white gamma (e.g. exp= 1/1.4)
+}
+
+SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
+    printf("SkFontHost::CreateTypefaceFromFile unimplemented");
+    return NULL;
+}
+
+void SkFontHost::FilterRec(SkScalerContext::Rec* rec) {
+    // We don't control the hinting nor ClearType settings here
+    rec->setHinting(SkPaint::kNormal_Hinting);
+
+    // we do support LCD16
+    if (SkMask::kLCD16_Format == rec->fMaskFormat) {
+        return;
+    }
+
+    if (SkMask::FormatIsLCD((SkMask::Format)rec->fMaskFormat)) {
+        rec->fMaskFormat = SkMask::kA8_Format;
+    }
+}
+
+#endif // WIN32
diff --git a/src/utils/utils_files.mk b/src/utils/utils_files.mk
new file mode 100644
index 0000000..68cc587
--- /dev/null
+++ b/src/utils/utils_files.mk
@@ -0,0 +1,15 @@
+SOURCE := \
+	SkCamera.cpp \
+	SkColorMatrix.cpp \
+	SkCullPoints.cpp \
+	SkDumpCanvas.cpp \
+	SkInterpolator.cpp \
+    SkLayer.cpp \
+	SkNinePatch.cpp \
+    SkNWayCanvas.cpp \
+    SkParse.cpp \
+    SkParseColor.cpp \
+    SkParsePath.cpp \
+	SkProxyCanvas.cpp \
+	SkSfntUtils.cpp \
+	SkUnitMappers.cpp
diff --git a/tests/tests_files.mk b/tests/tests_files.mk
new file mode 100644
index 0000000..5280502
--- /dev/null
+++ b/tests/tests_files.mk
@@ -0,0 +1,31 @@
+SOURCE := \
+    BitmapCopyTest.cpp \
+    BitmapGetColorTest.cpp \
+    BlitRowTest.cpp \
+    ClipCubicTest.cpp \
+    ClipStackTest.cpp \
+    ClipperTest.cpp \
+    DequeTest.cpp \
+    FillPathTest.cpp \
+    FlateTest.cpp \
+    GeometryTest.cpp \
+    InfRectTest.cpp \
+    MathTest.cpp \
+    MatrixTest.cpp \
+    PackBitsTest.cpp \
+    PaintTest.cpp \
+    ParsePathTest.cpp \
+    PathMeasureTest.cpp \
+    PathTest.cpp \
+    RefDictTest.cpp \
+    RegionTest.cpp \
+    Sk64Test.cpp \
+    skia_test.cpp \
+    SortTest.cpp \
+    SrcOverTest.cpp \
+    StreamTest.cpp \
+    StringTest.cpp \
+    Test.cpp \
+    TestSize.cpp \
+    UtilsTest.cpp \
+    XfermodeTest.cpp