Add factory class for generating various flavors of GrTextContext.

This is the first pass of making Gr*TextContext more generic and easily
subclassed. The next stage will be making GrBitmapTextContext and
GrDistanceFieldTextContext more similar by moving the SkDraw loop into
each subclass.

BUG=skia:2018

Committed: http://code.google.com/p/skia/source/detail?r=13142

R=bsalomon@google.com, reed@google.com

Author: jvanverth@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@13165 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/gpu/GrTextContext.h b/include/gpu/GrTextContext.h
index b367cf2..e2d7d9b 100644
--- a/include/gpu/GrTextContext.h
+++ b/include/gpu/GrTextContext.h
@@ -12,6 +12,8 @@
 #include "GrGlyph.h"
 #include "GrPaint.h"
 
+#include "SkPostConfig.h"
+
 class GrContext;
 class GrDrawTarget;
 class GrFontScaler;
@@ -21,20 +23,91 @@
  */
 class GrTextContext {
 public:
+    virtual ~GrTextContext() {}
     virtual void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top,
                                  GrFontScaler*) = 0;
 
 protected:
-    GrTextContext(GrContext*, const GrPaint&);
-    virtual ~GrTextContext() {}
+    GrTextContext(GrContext*, const GrPaint&, const SkPaint&);
 
     GrPaint                fPaint;
+    SkPaint                fSkPaint;
     GrContext*             fContext;
     GrDrawTarget*          fDrawTarget;
 
     SkIRect                fClipRect;
+};
+
+/*
+ * These classes wrap the creation of a single text context for a given GPU device. The
+ * assumption is that we'll only be using one text context at a time for that device.
+ */
+class GrTextContextManager {
+public:
+    virtual ~GrTextContextManager() {}
+    virtual GrTextContext* create(GrContext* context, const GrPaint& grPaint,
+                                  const SkPaint& skPaint) = 0;
+};
+
+template <class TextContextClass>
+class GrTTextContextManager : public GrTextContextManager {
+private:
+    class ManagedTextContext : public TextContextClass {
+    public:
+        ~ManagedTextContext() {}
+        
+        ManagedTextContext(GrContext* context,
+                           const GrPaint& grPaint,
+                           const SkPaint& skPaint,
+                           GrTTextContextManager<TextContextClass>* manager) :
+        TextContextClass(context, grPaint, skPaint) {
+            fManager = manager;
+        }
+
+        static void operator delete(void* ptr) {
+            if (ptr == NULL) {
+                return;
+            }
+            ManagedTextContext* context = reinterpret_cast<ManagedTextContext*>(ptr);
+            context->fManager->recycle(context);
+        }
+
+        static void operator delete(void*, void*) {
+        }
+
+        GrTTextContextManager<TextContextClass>* fManager;
+    };
+    
+public:
+    GrTTextContextManager() {
+        fAllocation = sk_malloc_throw(sizeof(ManagedTextContext));
+        fUsed = false;
+    }
+
+    ~GrTTextContextManager() {
+        SkASSERT(!fUsed);
+        sk_free(fAllocation);
+    }
+
+    GrTextContext* create(GrContext* context, const GrPaint& grPaint,
+                          const SkPaint& skPaint) {
+        // add check for usePath here?
+        SkASSERT(!fUsed);
+        ManagedTextContext* obj = SkNEW_PLACEMENT_ARGS(fAllocation, ManagedTextContext,
+                                                       (context, grPaint, skPaint, this));
+        fUsed = true;
+        return obj;
+    }
 
 private:
+    void recycle(GrTextContext* textContext) {
+        SkASSERT((void*)textContext == fAllocation);
+        SkASSERT(fUsed);
+        fUsed = false;
+    }
+
+    void* fAllocation;
+    bool  fUsed;
 };
 
 #endif