Add standalone drawText for GrTextContext.

This unifies the interface between GrBitmapTextContext and
GrDistanceFieldTextContext so that they don't need special case code.
The future GrNVPRTextContext will also use this interface.

BUG=skia:2018
R=bsalomon@google.com, reed@google.com

Author: jvanverth@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@13227 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrBitmapTextContext.cpp b/src/gpu/GrBitmapTextContext.cpp
index 6e33d90..da887a5 100755
--- a/src/gpu/GrBitmapTextContext.cpp
+++ b/src/gpu/GrBitmapTextContext.cpp
@@ -18,16 +18,21 @@
 #include "SkStrokeRec.h"
 #include "effects/GrCustomCoordsTextureEffect.h"
 
+#include "SkAutoKern.h"
+#include "SkGlyphCache.h"
+#include "SkGpuDevice.h"
+#include "SkGr.h"
+
 static const int kGlyphCoordsAttributeIndex = 1;
 
 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
                 "Dump the contents of the font cache before every purge.");
 
-GrBitmapTextContext::GrBitmapTextContext(GrContext* context, const GrPaint& paint,
-                                         const SkPaint& skPaint) :
-                                         GrTextContext(context, paint, skPaint) {
-    fAutoMatrix.setIdentity(fContext, &fPaint);
-
+GrBitmapTextContext::GrBitmapTextContext(GrContext* context, 
+                                         const GrPaint& grPaint,
+                                         const SkPaint& skPaint, 
+                                         const SkDeviceProperties& properties)
+                                       : GrTextContext(context, grPaint, skPaint, properties) {
     fStrike = NULL;
 
     fCurrTexture = NULL;
@@ -107,6 +112,330 @@
     }
 }
 
+void GrBitmapTextContext::drawText(const char text[], size_t byteLength,
+                                   SkScalar x, SkScalar y) {
+    SkASSERT(byteLength == 0 || text != NULL);
+
+    // nothing to draw
+    if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) {
+        return;
+    }
+
+    SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+
+    SkAutoGlyphCache    autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix());
+    SkGlyphCache*       cache = autoCache.getCache();
+    GrFontScaler*       fontScaler = GetGrFontScaler(cache);
+
+    // transform our starting point
+    {
+        SkPoint loc;
+        fContext->getMatrix().mapXY(x, y, &loc);
+        x = loc.fX;
+        y = loc.fY;
+    }
+
+    // need to measure first
+    if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
+        SkVector    stop;
+
+        MeasureText(cache, glyphCacheProc, text, byteLength, &stop);
+
+        SkScalar    stopX = stop.fX;
+        SkScalar    stopY = stop.fY;
+
+        if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
+            stopX = SkScalarHalf(stopX);
+            stopY = SkScalarHalf(stopY);
+        }
+        x -= stopX;
+        y -= stopY;
+    }
+
+    const char* stop = text + byteLength;
+
+    SkAutoKern autokern;
+
+    SkFixed fxMask = ~0;
+    SkFixed fyMask = ~0;
+    SkFixed halfSampleX, halfSampleY;
+    if (cache->isSubpixel()) {
+        halfSampleX = halfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
+        SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(fContext->getMatrix());
+        if (kX_SkAxisAlignment == baseline) {
+            fyMask = 0;
+            halfSampleY = SK_FixedHalf;
+        } else if (kY_SkAxisAlignment == baseline) {
+            fxMask = 0;
+            halfSampleX = SK_FixedHalf;
+        }
+    } else {
+        halfSampleX = halfSampleY = SK_FixedHalf;
+    }
+
+    SkFixed fx = SkScalarToFixed(x) + halfSampleX;
+    SkFixed fy = SkScalarToFixed(y) + halfSampleY;
+    
+    GrContext::AutoMatrix  autoMatrix;
+    autoMatrix.setIdentity(fContext, &fPaint);
+    
+    while (text < stop) {
+        const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
+
+        fx += autokern.adjust(glyph);
+
+        if (glyph.fWidth) {
+            this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                          glyph.getSubXFixed(),
+                                          glyph.getSubYFixed()),
+                                  SkFixedFloorToFixed(fx),
+                                  SkFixedFloorToFixed(fy),
+                                  fontScaler);
+        }
+
+        fx += glyph.fAdvanceX;
+        fy += glyph.fAdvanceY;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Copied from SkDraw
+
+// last parameter is interpreted as SkFixed [x, y]
+// return the fixed position, which may be rounded or not by the caller
+//   e.g. subpixel doesn't round
+typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*);
+
+static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
+    dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY));
+}
+
+static void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
+    dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1),
+             SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1));
+}
+
+static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
+    dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX,
+             SkScalarToFixed(loc.fY) - glyph.fAdvanceY);
+}
+
+static AlignProc pick_align_proc(SkPaint::Align align) {
+    static const AlignProc gProcs[] = {
+        leftAlignProc, centerAlignProc, rightAlignProc
+    };
+
+    SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
+
+    return gProcs[align];
+}
+
+class BitmapTextMapState {
+public:
+    mutable SkPoint fLoc;
+
+    BitmapTextMapState(const SkMatrix& matrix, SkScalar y)
+        : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {}
+
+    typedef void (*Proc)(const BitmapTextMapState&, const SkScalar pos[]);
+
+    Proc pickProc(int scalarsPerPosition);
+
+private:
+    const SkMatrix&     fMatrix;
+    SkMatrix::MapXYProc fProc;
+    SkScalar            fY; // ignored by MapXYProc
+    // these are only used by Only... procs
+    SkScalar            fScaleX, fTransX, fTransformedY;
+
+    static void MapXProc(const BitmapTextMapState& state, const SkScalar pos[]) {
+        state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc);
+    }
+
+    static void MapXYProc(const BitmapTextMapState& state, const SkScalar pos[]) {
+        state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc);
+    }
+
+    static void MapOnlyScaleXProc(const BitmapTextMapState& state,
+                                  const SkScalar pos[]) {
+        state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX,
+                       state.fTransformedY);
+    }
+
+    static void MapOnlyTransXProc(const BitmapTextMapState& state,
+                                  const SkScalar pos[]) {
+        state.fLoc.set(*pos + state.fTransX, state.fTransformedY);
+    }
+};
+
+BitmapTextMapState::Proc BitmapTextMapState::pickProc(int scalarsPerPosition) {
+    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
+
+    if (1 == scalarsPerPosition) {
+        unsigned mtype = fMatrix.getType();
+        if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
+            return MapXProc;
+        } else {
+            fScaleX = fMatrix.getScaleX();
+            fTransX = fMatrix.getTranslateX();
+            fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) +
+                            fMatrix.getTranslateY();
+            return (mtype & SkMatrix::kScale_Mask) ?
+                        MapOnlyScaleXProc : MapOnlyTransXProc;
+        }
+    } else {
+        return MapXYProc;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void GrBitmapTextContext::drawPosText(const char text[], size_t byteLength,
+                                      const SkScalar pos[], SkScalar constY,
+                                      int scalarsPerPosition) {
+    SkASSERT(byteLength == 0 || text != NULL);
+    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
+
+    // nothing to draw
+    if (text == NULL || byteLength == 0/* || fRC->isEmpty()*/) {
+        return;
+    }
+
+    SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
+
+    SkAutoGlyphCache    autoCache(fSkPaint, &fDeviceProperties, &fContext->getMatrix());
+    SkGlyphCache*       cache = autoCache.getCache();
+    GrFontScaler*       fontScaler = GetGrFontScaler(cache);
+
+    // store original matrix before we reset, so we can use it to transform positions
+    SkMatrix ctm = fContext->getMatrix();
+    GrContext::AutoMatrix  autoMatrix;
+    autoMatrix.setIdentity(fContext, &fPaint);
+
+    const char*        stop = text + byteLength;
+    AlignProc          alignProc = pick_align_proc(fSkPaint.getTextAlign());
+    BitmapTextMapState       tms(ctm, constY);
+    BitmapTextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
+    SkFixed halfSampleX = 0, halfSampleY = 0;
+
+    if (cache->isSubpixel()) {
+        // maybe we should skip the rounding if linearText is set
+        SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(ctm);
+
+        SkFixed fxMask = ~0;
+        SkFixed fyMask = ~0;
+        if (kX_SkAxisAlignment == baseline) {
+            fyMask = 0;
+#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
+            halfSampleY = SK_FixedHalf;
+#endif
+        } else if (kY_SkAxisAlignment == baseline) {
+            fxMask = 0;
+#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
+            halfSampleX = SK_FixedHalf;
+#endif
+        }
+
+        if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
+            while (text < stop) {
+                tmsProc(tms, pos);
+                SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + halfSampleX;
+                SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + halfSampleY;
+
+                const SkGlyph& glyph = glyphCacheProc(cache, &text,
+                                                      fx & fxMask, fy & fyMask);
+
+                if (glyph.fWidth) {
+                    this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                                        glyph.getSubXFixed(),
+                                                        glyph.getSubYFixed()),
+                                          SkFixedFloorToFixed(fx),
+                                          SkFixedFloorToFixed(fy),
+                                          fontScaler);
+                }
+                pos += scalarsPerPosition;
+            }
+        } else {
+            while (text < stop) {
+                const char* currentText = text;
+                const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
+
+                if (metricGlyph.fWidth) {
+                    SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
+                    SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
+
+                    tmsProc(tms, pos);
+                    SkIPoint fixedLoc;
+                    alignProc(tms.fLoc, metricGlyph, &fixedLoc);
+
+                    SkFixed fx = fixedLoc.fX + halfSampleX;
+                    SkFixed fy = fixedLoc.fY + halfSampleY;
+
+                    // have to call again, now that we've been "aligned"
+                    const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
+                                                          fx & fxMask, fy & fyMask);
+                    // the assumption is that the metrics haven't changed
+                    SkASSERT(prevAdvX == glyph.fAdvanceX);
+                    SkASSERT(prevAdvY == glyph.fAdvanceY);
+                    SkASSERT(glyph.fWidth);
+
+                    this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                                        glyph.getSubXFixed(),
+                                                        glyph.getSubYFixed()),
+                                          SkFixedFloorToFixed(fx),
+                                          SkFixedFloorToFixed(fy),
+                                          fontScaler);
+                }
+                pos += scalarsPerPosition;
+            }
+        }
+    } else {    // not subpixel
+
+        if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
+            while (text < stop) {
+                // the last 2 parameters are ignored
+                const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+
+                if (glyph.fWidth) {
+                    tmsProc(tms, pos);
+
+                    SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + SK_FixedHalf; //halfSampleX;
+                    SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + SK_FixedHalf; //halfSampleY;
+                    this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                                        glyph.getSubXFixed(),
+                                                        glyph.getSubYFixed()),
+                                          SkFixedFloorToFixed(fx),
+                                          SkFixedFloorToFixed(fy),
+                                          fontScaler);
+                }
+                pos += scalarsPerPosition;
+            }
+        } else {
+            while (text < stop) {
+                // the last 2 parameters are ignored
+                const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+
+                if (glyph.fWidth) {
+                    tmsProc(tms, pos);
+
+                    SkIPoint fixedLoc;
+                    alignProc(tms.fLoc, glyph, &fixedLoc);
+
+                    SkFixed fx = fixedLoc.fX + SK_FixedHalf; //halfSampleX;
+                    SkFixed fy = fixedLoc.fY + SK_FixedHalf; //halfSampleY;
+                    this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                                        glyph.getSubXFixed(),
+                                                        glyph.getSubYFixed()),
+                                          SkFixedFloorToFixed(fx),
+                                          SkFixedFloorToFixed(fy),
+                                          fontScaler);
+                }
+                pos += scalarsPerPosition;
+            }
+        }
+    }
+}
+
 namespace {
 
 // position + texture coord
@@ -123,6 +452,7 @@
     if (NULL == fDrawTarget) {
         return;
     }
+
     if (NULL == fStrike) {
 #if SK_DISTANCEFIELD_FONTS
         fStrike = fContext->getFontCache()->getStrike(scaler, false);
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
index 4c9631e..afb203a 100755
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/src/gpu/GrDistanceFieldTextContext.cpp
@@ -13,6 +13,7 @@
 #include "GrIndexBuffer.h"
 #include "GrTextStrike.h"
 #include "GrTextStrike_impl.h"
+#include "SkGpuDevice.h"
 #include "SkPath.h"
 #include "SkRTConf.h"
 #include "SkStrokeRec.h"
@@ -25,10 +26,11 @@
 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
                 "Dump the contents of the font cache before every purge.");
 
-GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
+GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context, 
                                                        const GrPaint& grPaint,
-                                                       const SkPaint& skPaint)
-                                                     : GrTextContext(context, grPaint, skPaint) {
+                                                       const SkPaint& skPaint, 
+                                                       const SkDeviceProperties& properties)
+                                            : GrTextContext(context, grPaint, skPaint, properties) {
     fStrike = NULL;
 
     fCurrTexture = NULL;
@@ -283,19 +285,23 @@
 }
 
 void GrDistanceFieldTextContext::drawText(const char text[], size_t byteLength,
-                                          SkScalar x, SkScalar y, SkGlyphCache* cache,
-                                          GrFontScaler* fontScaler) {
+                                          SkScalar x, SkScalar y) {
     SkASSERT(byteLength == 0 || text != NULL);
 
-    // nothing to draw
-    if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
+    // nothing to draw or can't draw
+    if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/
+        || fSkPaint.getRasterizer()) {
         return;
     }
-
+    
     SkScalar sizeRatio = fTextRatio;
 
     SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
 
+    SkAutoGlyphCache    autoCache(fSkPaint, &fDeviceProperties, NULL);
+    SkGlyphCache*       cache = autoCache.getCache();
+    GrFontScaler*       fontScaler = GetGrFontScaler(cache);
+    
     // need to measure first
     // TODO - generate positions and pre-load cache as well?
     const char* stop = text + byteLength;
@@ -348,19 +354,23 @@
 
 void GrDistanceFieldTextContext::drawPosText(const char text[], size_t byteLength,
                                              const SkScalar pos[], SkScalar constY,
-                                             int scalarsPerPosition,
-                                             SkGlyphCache* cache, GrFontScaler* fontScaler) {
+                                             int scalarsPerPosition) {
 
     SkASSERT(byteLength == 0 || text != NULL);
     SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
 
     // nothing to draw
-    if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/) {
+    if (text == NULL || byteLength == 0 /* no raster clip? || fRC->isEmpty()*/
+        || fSkPaint.getRasterizer()) {
         return;
     }
 
     SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
 
+    SkAutoGlyphCache    autoCache(fSkPaint, &fDeviceProperties, NULL);
+    SkGlyphCache*       cache = autoCache.getCache();
+    GrFontScaler*       fontScaler = GetGrFontScaler(cache);
+    
     const char*        stop = text + byteLength;
 
     if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp
index 77e98d2..ab9ef85 100644
--- a/src/gpu/GrTextContext.cpp
+++ b/src/gpu/GrTextContext.cpp
@@ -5,12 +5,17 @@
  * found in the LICENSE file.
  */
 
-
 #include "GrTextContext.h"
+#include "GrContext.h"
+
+#include "SkAutoKern.h"
+#include "SkGlyphCache.h"
+#include "SkGr.h"
 
 GrTextContext::GrTextContext(GrContext* context, const GrPaint& paint,
-                             const SkPaint& skPaint) : fPaint(paint), fSkPaint(skPaint) {
-    fContext = context;
+                             const SkPaint& skPaint, const SkDeviceProperties& properties) : 
+                            fContext(context), fPaint(paint), fSkPaint(skPaint),
+                            fDeviceProperties(properties) {
 
     const GrClipData* clipData = context->getClip();
 
@@ -24,5 +29,47 @@
 
     devConservativeBound.roundOut(&fClipRect);
 
-    fDrawTarget = fContext->getTextTarget();
+    fDrawTarget = context->getTextTarget();
 }
+
+//*** change to output positions?
+void GrTextContext::MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
+                                const char text[], size_t byteLength, SkVector* stopVector) {
+    SkFixed     x = 0, y = 0;
+    const char* stop = text + byteLength;
+    
+    SkAutoKern  autokern;
+    
+    while (text < stop) {
+        // don't need x, y here, since all subpixel variants will have the
+        // same advance
+        const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
+        
+        x += autokern.adjust(glyph) + glyph.fAdvanceX;
+        y += glyph.fAdvanceY;
+    }
+    stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
+    
+    SkASSERT(text == stop);
+}
+
+static void GlyphCacheAuxProc(void* data) {
+    GrFontScaler* scaler = (GrFontScaler*)data;
+    SkSafeUnref(scaler);
+}
+
+GrFontScaler* GrTextContext::GetGrFontScaler(SkGlyphCache* cache) {
+    void* auxData;
+    GrFontScaler* scaler = NULL;
+    
+    if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
+        scaler = (GrFontScaler*)auxData;
+    }
+    if (NULL == scaler) {
+        scaler = SkNEW_ARGS(SkGrFontScaler, (cache));
+        cache->setAuxProc(GlyphCacheAuxProc, scaler);
+    }
+    
+    return scaler;
+}
+
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 73eb65b..f52385a 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1766,58 +1766,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-static void GlyphCacheAuxProc(void* data) {
-    GrFontScaler* scaler = (GrFontScaler*)data;
-    SkSafeUnref(scaler);
-}
-
-static GrFontScaler* get_gr_font_scaler(SkGlyphCache* cache) {
-    void* auxData;
-    GrFontScaler* scaler = NULL;
-    if (cache->getAuxProcData(GlyphCacheAuxProc, &auxData)) {
-        scaler = (GrFontScaler*)auxData;
-    }
-    if (NULL == scaler) {
-        scaler = SkNEW_ARGS(SkGrFontScaler, (cache));
-        cache->setAuxProc(GlyphCacheAuxProc, scaler);
-    }
-    return scaler;
-}
-
-static void SkGPU_Draw1Glyph(const SkDraw1Glyph& state,
-                             SkFixed fx, SkFixed fy,
-                             const SkGlyph& glyph) {
-    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
-
-    GrSkDrawProcs* procs = static_cast<GrSkDrawProcs*>(state.fDraw->fProcs);
-
-    if (NULL == procs->fFontScaler) {
-        procs->fFontScaler = get_gr_font_scaler(state.fCache);
-    }
-
-    procs->fTextContext->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
-                                                       glyph.getSubXFixed(),
-                                                       glyph.getSubYFixed()),
-                                         SkFixedFloorToFixed(fx),
-                                         SkFixedFloorToFixed(fy),
-                                         procs->fFontScaler);
-}
-
-SkDrawProcs* SkGpuDevice::initDrawForText(GrTextContext* context) {
-
-    // deferred allocation
-    if (NULL == fDrawProcs) {
-        fDrawProcs = SkNEW(GrSkDrawProcs);
-        fDrawProcs->fD1GProc = SkGPU_Draw1Glyph;
-        fDrawProcs->fContext = fContext;
-    }
-
-    // init our (and GL's) state
-    fDrawProcs->fTextContext = context;
-    fDrawProcs->fFontScaler = NULL;
-    return fDrawProcs;
-}
-
 void SkGpuDevice::drawText(const SkDraw& draw, const void* text,
                           size_t byteLength, SkScalar x, SkScalar y,
                           const SkPaint& paint) {
@@ -1825,8 +1773,7 @@
 
     if (SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix())) {
         draw.drawText_asPaths((const char*)text, byteLength, x, y, paint);
-#if SK_DISTANCEFIELD_FONTS
-    } else if (!paint.getRasterizer()) {
+    } else {
         GrPaint grPaint;
         if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
             return;
@@ -1834,27 +1781,10 @@
 
         SkDEBUGCODE(this->validate();)
 
-        SkAutoTDelete<GrTextContext> context(fTextContextManager->create(fContext, grPaint, paint));
-        GrDistanceFieldTextContext* dfContext =
-                                            static_cast<GrDistanceFieldTextContext*>(context.get());
-
-        SkAutoGlyphCache    autoCache(dfContext->getSkPaint(), &this->fLeakyProperties, NULL);
-        SkGlyphCache*       cache = autoCache.getCache();
-        GrFontScaler*       fontScaler = get_gr_font_scaler(cache);
-
-        dfContext->drawText((const char *)text, byteLength, x, y, cache, fontScaler);
-#endif
-    } else {
-        SkDraw myDraw(draw);
-
-        GrPaint grPaint;
-        if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
-            return;
-        }
-
-        SkAutoTDelete<GrTextContext> context(fTextContextManager->create(fContext, grPaint, paint));
-        myDraw.fProcs = this->initDrawForText(context.get());
-        this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint);
+        SkAutoTDelete<GrTextContext> ctx(fTextContextManager->create(this->context(), 
+                                                                     grPaint, paint,
+                                                                     this->getDeviceProperties()));
+        ctx->drawText((const char *)text, byteLength, x, y);
     }
 }
 
@@ -1868,8 +1798,7 @@
         // this guy will just call our drawPath()
         draw.drawPosText_asPaths((const char*)text, byteLength, pos, constY,
                          scalarsPerPos, paint);
-#if SK_DISTANCEFIELD_FONTS
-    } else if (!paint.getRasterizer()) {
+    } else {
         GrPaint grPaint;
         if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
             return;
@@ -1877,29 +1806,10 @@
 
         SkDEBUGCODE(this->validate();)
 
-        SkAutoTDelete<GrTextContext> context(fTextContextManager->create(fContext, grPaint, paint));
-        GrDistanceFieldTextContext* dfContext =
-                                            static_cast<GrDistanceFieldTextContext*>(context.get());
-
-        SkAutoGlyphCache    autoCache(dfContext->getSkPaint(), &this->fLeakyProperties, NULL);
-        SkGlyphCache*       cache = autoCache.getCache();
-        GrFontScaler*       fontScaler = get_gr_font_scaler(cache);
-
-        dfContext->drawPosText((const char *)text, byteLength, pos, constY, scalarsPerPos,
-                            cache, fontScaler);
-#endif
-    } else {
-        SkDraw myDraw(draw);
-
-        GrPaint grPaint;
-        if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
-            return;
-        }
-
-        SkAutoTDelete<GrTextContext> context(fTextContextManager->create(fContext, grPaint, paint));
-        myDraw.fProcs = this->initDrawForText(context.get());
-        this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY,
-                                        scalarsPerPos, paint);
+        SkAutoTDelete<GrTextContext> ctx(fTextContextManager->create(this->context(), 
+                                                                     grPaint, paint,
+                                                                     this->getDeviceProperties()));
+        ctx->drawPosText((const char *)text, byteLength, pos, constY, scalarsPerPos);
     }
 }