Rearrange code in TextContexts to be more consistent and match style guide.

Review URL: https://codereview.chromium.org/641613003
diff --git a/src/gpu/GrBitmapTextContext.cpp b/src/gpu/GrBitmapTextContext.cpp
index c9cdf2c..9478d04 100755
--- a/src/gpu/GrBitmapTextContext.cpp
+++ b/src/gpu/GrBitmapTextContext.cpp
@@ -67,99 +67,13 @@
 }
 
 GrBitmapTextContext::~GrBitmapTextContext() {
-    this->flushGlyphs();
+    this->flush();
 }
 
 bool GrBitmapTextContext::canDraw(const SkPaint& paint) {
     return !SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix());
 }
 
-static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
-    unsigned r = SkColorGetR(c);
-    unsigned g = SkColorGetG(c);
-    unsigned b = SkColorGetB(c);
-    return GrColorPackRGBA(r, g, b, 0xff);
-}
-
-void GrBitmapTextContext::flushGlyphs() {
-    if (NULL == fDrawTarget) {
-        return;
-    }
-
-    GrDrawState* drawState = fDrawTarget->drawState();
-    GrDrawState::AutoRestoreEffects are(drawState);
-    drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget());
-
-    if (fCurrVertex > 0) {
-        // setup our sampler state for our text texture/atlas
-        SkASSERT(SkIsAlign4(fCurrVertex));
-        SkASSERT(fCurrTexture);
-        GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode);
-
-        uint32_t textureUniqueID = fCurrTexture->getUniqueID();
-        
-        if (textureUniqueID != fEffectTextureUniqueID) {
-            fCachedGeometryProcessor.reset(GrCustomCoordsTextureEffect::Create(fCurrTexture,
-                                                                               params));
-            fEffectTextureUniqueID = textureUniqueID;
-        }
-
-        // This effect could be stored with one of the cache objects (atlas?)
-        drawState->setGeometryProcessor(fCachedGeometryProcessor.get());
-        SkASSERT(fStrike);
-        switch (fStrike->getMaskFormat()) {
-            // Color bitmap text
-            case kARGB_GrMaskFormat:
-                SkASSERT(!drawState->hasColorVertexAttribute());
-                drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
-                drawState->setColor(0xffffffff);
-                break;
-            // LCD text
-            case kA888_GrMaskFormat:
-            case kA565_GrMaskFormat: {
-                if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
-                    kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
-                    fPaint.numColorStages()) {
-                    GrPrintf("LCD Text will not draw correctly.\n");
-                }
-                SkASSERT(!drawState->hasColorVertexAttribute());
-                // We don't use the GrPaint's color in this case because it's been premultiplied by
-                // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
-                // the mask texture color. The end result is that we get
-                //            mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
-                int a = SkColorGetA(fSkPaint.getColor());
-                // paintAlpha
-                drawState->setColor(SkColorSetARGB(a, a, a, a));
-                // paintColor
-                drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor()));
-                drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
-                break;
-            }
-            // Grayscale/BW text
-            case kA8_GrMaskFormat:
-                // set back to normal in case we took LCD path previously.
-                drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
-                // We're using per-vertex color.
-                SkASSERT(drawState->hasColorVertexAttribute());
-                break;
-            default:
-                SkFAIL("Unexepected mask format.");
-        }
-        int nGlyphs = fCurrVertex / 4;
-        fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
-        fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
-                                          nGlyphs,
-                                          4, 6, &fVertexBounds);
-
-        fDrawTarget->resetVertexSource();
-        fVertices = NULL;
-        fMaxVertices = 0;
-        fCurrVertex = 0;
-        fVertexBounds.setLargestInverted();
-        SkSafeSetNull(fCurrTexture);
-    }
-}
-
 inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPaint) {
     GrTextContext::init(paint, skPaint);
 
@@ -172,12 +86,6 @@
     fMaxVertices = 0;
 }
 
-inline void GrBitmapTextContext::finish() {
-    this->flushGlyphs();
-
-    GrTextContext::finish();
-}
-
 void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
                                    const char text[], size_t byteLength,
                                    SkScalar x, SkScalar y) {
@@ -254,12 +162,12 @@
         fx += autokern.adjust(glyph);
 
         if (glyph.fWidth) {
-            this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
-                                          glyph.getSubXFixed(),
-                                          glyph.getSubYFixed()),
-                                  SkFixedFloorToFixed(fx),
-                                  SkFixedFloorToFixed(fy),
-                                  fontScaler);
+            this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                            glyph.getSubXFixed(),
+                                            glyph.getSubYFixed()),
+                              SkFixedFloorToFixed(fx),
+                              SkFixedFloorToFixed(fy),
+                              fontScaler);
         }
 
         fx += glyph.fAdvanceX;
@@ -328,12 +236,12 @@
                                                       fx & fxMask, fy & fyMask);
 
                 if (glyph.fWidth) {
-                    this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
-                                                        glyph.getSubXFixed(),
-                                                        glyph.getSubYFixed()),
-                                          SkFixedFloorToFixed(fx),
-                                          SkFixedFloorToFixed(fy),
-                                          fontScaler);
+                    this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                                    glyph.getSubXFixed(),
+                                                    glyph.getSubYFixed()),
+                                      SkFixedFloorToFixed(fx),
+                                      SkFixedFloorToFixed(fy),
+                                      fontScaler);
                 }
                 pos += scalarsPerPosition;
             }
@@ -361,12 +269,12 @@
                     SkASSERT(prevAdvY == glyph.fAdvanceY);
                     SkASSERT(glyph.fWidth);
 
-                    this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
-                                                        glyph.getSubXFixed(),
-                                                        glyph.getSubYFixed()),
-                                          SkFixedFloorToFixed(fx),
-                                          SkFixedFloorToFixed(fy),
-                                          fontScaler);
+                    this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                                    glyph.getSubXFixed(),
+                                                    glyph.getSubYFixed()),
+                                      SkFixedFloorToFixed(fx),
+                                      SkFixedFloorToFixed(fy),
+                                      fontScaler);
                 }
                 pos += scalarsPerPosition;
             }
@@ -384,12 +292,12 @@
 
                     SkFixed fx = SkScalarToFixed(tmsLoc.fX) + SK_FixedHalf; //halfSampleX;
                     SkFixed fy = SkScalarToFixed(tmsLoc.fY) + SK_FixedHalf; //halfSampleY;
-                    this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
-                                                        glyph.getSubXFixed(),
-                                                        glyph.getSubYFixed()),
-                                          SkFixedFloorToFixed(fx),
-                                          SkFixedFloorToFixed(fy),
-                                          fontScaler);
+                    this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                                    glyph.getSubXFixed(),
+                                                    glyph.getSubYFixed()),
+                                      SkFixedFloorToFixed(fx),
+                                      SkFixedFloorToFixed(fy),
+                                      fontScaler);
                 }
                 pos += scalarsPerPosition;
             }
@@ -407,12 +315,12 @@
 
                     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);
+                    this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                                    glyph.getSubXFixed(),
+                                                    glyph.getSubYFixed()),
+                                      SkFixedFloorToFixed(fx),
+                                      SkFixedFloorToFixed(fy),
+                                      fontScaler);
                 }
                 pos += scalarsPerPosition;
             }
@@ -422,9 +330,9 @@
     this->finish();
 }
 
-void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
-                                          SkFixed vx, SkFixed vy,
-                                          GrFontScaler* scaler) {
+void GrBitmapTextContext::appendGlyph(GrGlyph::PackedID packed,
+                                      SkFixed vx, SkFixed vy,
+                                      GrFontScaler* scaler) {
     if (NULL == fDrawTarget) {
         return;
     }
@@ -474,7 +382,7 @@
             }
 
             // flush any accumulated draws to allow us to free up a plot
-            this->flushGlyphs();
+            this->flush();
             fContext->flush();
 
             // we should have an unused plot now
@@ -518,7 +426,7 @@
     SkASSERT(texture);
 
     if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
-        this->flushGlyphs();
+        this->flush();
         fCurrTexture = texture;
         fCurrTexture->ref();
     }
@@ -538,7 +446,7 @@
         }
         bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL);
         if (flush) {
-            this->flushGlyphs();
+            this->flush();
             fContext->flush();
             if (useColorVerts) {
                 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
@@ -607,3 +515,96 @@
     }
     fCurrVertex += 4;
 }
+
+static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
+    unsigned r = SkColorGetR(c);
+    unsigned g = SkColorGetG(c);
+    unsigned b = SkColorGetB(c);
+    return GrColorPackRGBA(r, g, b, 0xff);
+}
+
+void GrBitmapTextContext::flush() {
+    if (NULL == fDrawTarget) {
+        return;
+    }
+
+    GrDrawState* drawState = fDrawTarget->drawState();
+    GrDrawState::AutoRestoreEffects are(drawState);
+    drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget());
+
+    if (fCurrVertex > 0) {
+        // setup our sampler state for our text texture/atlas
+        SkASSERT(SkIsAlign4(fCurrVertex));
+        SkASSERT(fCurrTexture);
+        GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode);
+
+        uint32_t textureUniqueID = fCurrTexture->getUniqueID();
+
+        if (textureUniqueID != fEffectTextureUniqueID) {
+            fCachedGeometryProcessor.reset(GrCustomCoordsTextureEffect::Create(fCurrTexture,
+                                                                               params));
+            fEffectTextureUniqueID = textureUniqueID;
+        }
+
+        // This effect could be stored with one of the cache objects (atlas?)
+        drawState->setGeometryProcessor(fCachedGeometryProcessor.get());
+        SkASSERT(fStrike);
+        switch (fStrike->getMaskFormat()) {
+                // Color bitmap text
+            case kARGB_GrMaskFormat:
+                SkASSERT(!drawState->hasColorVertexAttribute());
+                drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
+                drawState->setColor(0xffffffff);
+                break;
+                // LCD text
+            case kA888_GrMaskFormat:
+            case kA565_GrMaskFormat: {
+                if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
+                    kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
+                    fPaint.numColorStages()) {
+                    GrPrintf("LCD Text will not draw correctly.\n");
+                }
+                SkASSERT(!drawState->hasColorVertexAttribute());
+                // We don't use the GrPaint's color in this case because it's been premultiplied by
+                // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
+                // the mask texture color. The end result is that we get
+                //            mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
+                int a = SkColorGetA(fSkPaint.getColor());
+                // paintAlpha
+                drawState->setColor(SkColorSetARGB(a, a, a, a));
+                // paintColor
+                drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor()));
+                drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
+                break;
+            }
+                // Grayscale/BW text
+            case kA8_GrMaskFormat:
+                // set back to normal in case we took LCD path previously.
+                drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
+                // We're using per-vertex color.
+                SkASSERT(drawState->hasColorVertexAttribute());
+                break;
+            default:
+                SkFAIL("Unexepected mask format.");
+        }
+        int nGlyphs = fCurrVertex / 4;
+        fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
+        fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
+                                          nGlyphs,
+                                          4, 6, &fVertexBounds);
+
+        fDrawTarget->resetVertexSource();
+        fVertices = NULL;
+        fMaxVertices = 0;
+        fCurrVertex = 0;
+        fVertexBounds.setLargestInverted();
+        SkSafeSetNull(fCurrTexture);
+    }
+}
+
+inline void GrBitmapTextContext::finish() {
+    this->flush();
+
+    GrTextContext::finish();
+}
+
diff --git a/src/gpu/GrBitmapTextContext.h b/src/gpu/GrBitmapTextContext.h
index c136270..4bff399 100644
--- a/src/gpu/GrBitmapTextContext.h
+++ b/src/gpu/GrBitmapTextContext.h
@@ -21,6 +21,8 @@
     GrBitmapTextContext(GrContext*, const SkDeviceProperties&);
     virtual ~GrBitmapTextContext();
 
+    virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE;
+
     virtual void drawText(const GrPaint&, const SkPaint&, const char text[], size_t byteLength,
                           SkScalar x, SkScalar y) SK_OVERRIDE;
     virtual void drawPosText(const GrPaint&, const SkPaint&,
@@ -28,16 +30,7 @@
                              const SkScalar pos[], int scalarsPerPosition,
                              const SkPoint& offset) SK_OVERRIDE;
 
-    virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE;
-
 private:
-    GrTextStrike*          fStrike;
-
-    void init(const GrPaint&, const SkPaint&);
-    void drawPackedGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*);
-    void flushGlyphs();                 // automatically called by destructor
-    void finish();
-
     enum {
         kMinRequestedGlyphs      = 1,
         kDefaultRequestedGlyphs  = 64,
@@ -45,6 +38,7 @@
         kDefaultRequestedVerts   = kDefaultRequestedGlyphs * 4,
     };
 
+    GrTextStrike*                     fStrike;
     void*                             fVertices;
     int32_t                           fMaxVertices;
     GrTexture*                        fCurrTexture;
@@ -53,6 +47,12 @@
     uint32_t                          fEffectTextureUniqueID;
     int                               fCurrVertex;
     SkRect                            fVertexBounds;
+
+    void init(const GrPaint&, const SkPaint&);
+    void appendGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*);
+    void flush();                 // automatically called by destructor
+    void finish();
+
 };
 
 #endif
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
index b565dd6..baba10d 100755
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/src/gpu/GrDistanceFieldTextContext.cpp
@@ -81,7 +81,7 @@
 }
 
 GrDistanceFieldTextContext::~GrDistanceFieldTextContext() {
-    this->flushGlyphs();
+    this->flush();
     SkSafeSetNull(fGammaTexture);
 }
 
@@ -114,337 +114,6 @@
     return rec.getFormat() != SkMask::kARGB32_Format;
 }
 
-static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
-    unsigned r = SkColorGetR(c);
-    unsigned g = SkColorGetG(c);
-    unsigned b = SkColorGetB(c);
-    return GrColorPackRGBA(r, g, b, 0xff);
-}
-
-void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColor) {
-    GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
-    GrTextureParams gammaParams(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
-    
-    uint32_t textureUniqueID = fCurrTexture->getUniqueID();
-    const SkMatrix& ctm = fContext->getMatrix();
-    
-    // set up any flags
-    uint32_t flags = 0;
-    flags |= ctm.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
-    flags |= fUseLCDText ? kUseLCD_DistanceFieldEffectFlag : 0;
-    flags |= fUseLCDText && ctm.rectStaysRect() ?
-    kRectToRect_DistanceFieldEffectFlag : 0;
-    bool useBGR = SkPixelGeometryIsBGR(fDeviceProperties.fPixelGeometry);
-    flags |= fUseLCDText && useBGR ? kBGR_DistanceFieldEffectFlag : 0;
-    
-    // see if we need to create a new effect
-    if (textureUniqueID != fEffectTextureUniqueID ||
-        filteredColor != fEffectColor ||
-        flags != fEffectFlags) {
-        if (fUseLCDText) {
-            GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
-            fCachedGeometryProcessor.reset(
-                    GrDistanceFieldLCDTextureEffect::Create(fCurrTexture,
-                                                            params,
-                                                            fGammaTexture,
-                                                            gammaParams,
-                                                            colorNoPreMul,
-                                                            flags));
-        } else {
-#ifdef SK_GAMMA_APPLY_TO_A8
-            U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDeviceProperties.getGamma(),
-                                                                filteredColor);
-            fCachedGeometryProcessor.reset(
-                    GrDistanceFieldTextureEffect::Create(fCurrTexture,
-                                                         params,
-                                                         fGammaTexture,
-                                                         gammaParams,
-                                                         lum/255.f,
-                                                         flags));
-#else
-            fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create(fCurrTexture,
-                                                                                params, flags));
-#endif
-        }
-        fEffectTextureUniqueID = textureUniqueID;
-        fEffectColor = filteredColor;
-        fEffectFlags = flags;
-    }
-    
-}
-
-void GrDistanceFieldTextContext::flushGlyphs() {
-    if (NULL == fDrawTarget) {
-        return;
-    }
-
-    GrDrawState* drawState = fDrawTarget->drawState();
-    GrDrawState::AutoRestoreEffects are(drawState);
-
-    drawState->setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTarget());
-
-    if (fCurrVertex > 0) {
-        // setup our sampler state for our text texture/atlas
-        SkASSERT(SkIsAlign4(fCurrVertex));
-
-        // get our current color
-        SkColor filteredColor;
-        SkColorFilter* colorFilter = fSkPaint.getColorFilter();
-        if (colorFilter) {
-            filteredColor = colorFilter->filterColor(fSkPaint.getColor());
-        } else {
-            filteredColor = fSkPaint.getColor();
-        }
-        this->setupCoverageEffect(filteredColor);
-       
-        // Effects could be stored with one of the cache objects (atlas?)
-        drawState->setGeometryProcessor(fCachedGeometryProcessor.get());
-        
-        // Set draw state
-        if (fUseLCDText) {
-            GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
-            if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
-                kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
-                fPaint.numColorStages()) {
-                GrPrintf("LCD Text will not draw correctly.\n");
-            }
-            SkASSERT(!drawState->hasColorVertexAttribute());
-            // We don't use the GrPaint's color in this case because it's been premultiplied by
-            // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
-            // the mask texture color. The end result is that we get
-            //            mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
-            int a = SkColorGetA(fSkPaint.getColor());
-            // paintAlpha
-            drawState->setColor(SkColorSetARGB(a, a, a, a));
-            // paintColor
-            drawState->setBlendConstant(colorNoPreMul);
-            drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
-        } else {
-            // set back to normal in case we took LCD path previously.
-            drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
-            // We're using per-vertex color.
-            SkASSERT(drawState->hasColorVertexAttribute());
-        }
-        int nGlyphs = fCurrVertex / 4;
-        fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
-        fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
-                                          nGlyphs,
-                                          4, 6, &fVertexBounds);
-        fDrawTarget->resetVertexSource();
-        fVertices = NULL;
-        fMaxVertices = 0;
-        fCurrVertex = 0;
-        SkSafeSetNull(fCurrTexture);
-        fVertexBounds.setLargestInverted();
-    }
-}
-
-void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
-                                                 SkFixed vx, SkFixed vy,
-                                                 GrFontScaler* scaler) {
-    if (NULL == fDrawTarget) {
-        return;
-    }
-    
-    if (NULL == fStrike) {
-        fStrike = fContext->getFontCache()->getStrike(scaler, true);
-    }
-    
-    GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
-    if (NULL == glyph || glyph->fBounds.isEmpty()) {
-        return;
-    }
-
-    SkScalar sx = SkFixedToScalar(vx);
-    SkScalar sy = SkFixedToScalar(vy);
-/*
-    // not valid, need to find a different solution for this
-    vx += SkIntToFixed(glyph->fBounds.fLeft);
-    vy += SkIntToFixed(glyph->fBounds.fTop);
-
-    // keep them as ints until we've done the clip-test
-    GrFixed width = glyph->fBounds.width();
-    GrFixed height = glyph->fBounds.height();
-
-    // check if we clipped out
-    if (true || NULL == glyph->fPlot) {
-        int x = vx >> 16;
-        int y = vy >> 16;
-        if (fClipRect.quickReject(x, y, x + width, y + height)) {
-//            SkCLZ(3);    // so we can set a break-point in the debugger
-            return;
-        }
-    }
-*/
-    if (NULL == glyph->fPlot) {
-        if (!fStrike->glyphTooLargeForAtlas(glyph)) {
-            if (fStrike->addGlyphToAtlas(glyph, scaler)) {
-                goto HAS_ATLAS;
-            }
-
-            // try to clear out an unused plot before we flush
-            if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
-                fStrike->addGlyphToAtlas(glyph, scaler)) {
-                goto HAS_ATLAS;
-            }
-
-            if (c_DumpFontCache) {
-#ifdef SK_DEVELOPER
-                fContext->getFontCache()->dump();
-#endif
-            }
-
-            // before we purge the cache, we must flush any accumulated draws
-            this->flushGlyphs();
-            fContext->flush();
-
-            // we should have an unused plot now
-            if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
-                fStrike->addGlyphToAtlas(glyph, scaler)) {
-                goto HAS_ATLAS;
-            }
-        }
-
-        if (NULL == glyph->fPath) {
-            SkPath* path = SkNEW(SkPath);
-            if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
-                // flag the glyph as being dead?
-                delete path;
-                return;
-            }
-            glyph->fPath = path;
-        }
-
-        GrContext::AutoMatrix am;
-        SkMatrix ctm;
-        ctm.setScale(fTextRatio, fTextRatio);
-        ctm.postTranslate(sx, sy);
-        GrPaint tmpPaint(fPaint);
-        am.setPreConcat(fContext, ctm, &tmpPaint);
-        GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
-        fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo);
-        return;
-    }
-
-HAS_ATLAS:
-    SkASSERT(glyph->fPlot);
-    GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
-    glyph->fPlot->setDrawToken(drawToken);
-
-    GrTexture* texture = glyph->fPlot->texture();
-    SkASSERT(texture);
-
-    if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
-        this->flushGlyphs();
-        fCurrTexture = texture;
-        fCurrTexture->ref();
-    }
-
-    bool useColorVerts = !fUseLCDText;
-    
-    if (NULL == fVertices) {
-        // If we need to reserve vertices allow the draw target to suggest
-        // a number of verts to reserve and whether to perform a flush.
-        fMaxVertices = kMinRequestedVerts;
-        if (useColorVerts) {
-            fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
-                                                    SK_ARRAY_COUNT(gTextVertexWithColorAttribs),
-                                                    kTextVAColorSize);
-        } else {
-            fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
-                                                    SK_ARRAY_COUNT(gTextVertexAttribs),
-                                                    kTextVASize);
-        }
-        bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL);
-        if (flush) {
-            this->flushGlyphs();
-            fContext->flush();
-            if (useColorVerts) {
-                fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
-                                                    SK_ARRAY_COUNT(gTextVertexWithColorAttribs),
-                                                    kTextVAColorSize);
-            } else {
-                fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
-                                                    SK_ARRAY_COUNT(gTextVertexAttribs),
-                                                    kTextVASize);
-            }
-        }
-        fMaxVertices = kDefaultRequestedVerts;
-        // ignore return, no point in flushing again.
-        fDrawTarget->geometryHints(&fMaxVertices, NULL);
-        
-        int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads();
-        if (fMaxVertices < kMinRequestedVerts) {
-            fMaxVertices = kDefaultRequestedVerts;
-        } else if (fMaxVertices > maxQuadVertices) {
-            // don't exceed the limit of the index buffer
-            fMaxVertices = maxQuadVertices;
-        }
-        bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices,
-                                                               0,
-                                                               &fVertices,
-                                                               NULL);
-        GrAlwaysAssert(success);
-    }
-    
-    SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset);
-    SkScalar dy = SkIntToScalar(glyph->fBounds.fTop + SK_DistanceFieldInset);
-    SkScalar width = SkIntToScalar(glyph->fBounds.width() - 2*SK_DistanceFieldInset);
-    SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2*SK_DistanceFieldInset);
-
-    SkScalar scale = fTextRatio;
-    dx *= scale;
-    dy *= scale;
-    sx += dx;
-    sy += dy;
-    width *= scale;
-    height *= scale;
-    
-    SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX + SK_DistanceFieldInset);
-    SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY + SK_DistanceFieldInset);
-    SkFixed tw = SkIntToFixed(glyph->fBounds.width() - 2*SK_DistanceFieldInset);
-    SkFixed th = SkIntToFixed(glyph->fBounds.height() - 2*SK_DistanceFieldInset);
-
-    SkRect r;
-    r.fLeft = sx;
-    r.fTop = sy;
-    r.fRight = sx + width;
-    r.fBottom = sy + height;
-
-    fVertexBounds.joinNonEmptyArg(r);
-
-    size_t vertSize = fUseLCDText ? (2 * sizeof(SkPoint))
-                                  : (2 * sizeof(SkPoint) + sizeof(GrColor));
-
-    SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexStride());
-
-    SkPoint* positions = reinterpret_cast<SkPoint*>(
-        reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex);
-    positions->setRectFan(r.fLeft, r.fTop, r.fRight, r.fBottom, vertSize);
-
-    // The texture coords are last in both the with and without color vertex layouts.
-    SkPoint* textureCoords = reinterpret_cast<SkPoint*>(
-            reinterpret_cast<intptr_t>(positions) + vertSize  - sizeof(SkPoint));
-    textureCoords->setRectFan(SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx)),
-                              SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty)),
-                              SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx + tw)),
-                              SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty + th)),
-                              vertSize);
-    if (useColorVerts) {
-        if (0xFF == GrColorUnpackA(fPaint.getColor())) {
-            fDrawTarget->drawState()->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
-        }
-        // color comes after position.
-        GrColor* colors = reinterpret_cast<GrColor*>(positions + 1);
-        for (int i = 0; i < 4; ++i) {
-            *colors = fPaint.getColor();
-            colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(colors) + vertSize);
-        }
-    }
-
-    fCurrVertex += 4;
-}
-
 inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint& skPaint) {
     GrTextContext::init(paint, skPaint);
 
@@ -488,12 +157,6 @@
 
 }
 
-inline void GrDistanceFieldTextContext::finish() {
-    this->flushGlyphs();
-
-    GrTextContext::finish();
-}
-
 static void setup_gamma_texture(GrContext* context, const SkGlyphCache* cache,
                                 const SkDeviceProperties& deviceProperties,
                                 GrTexture** gammaTexture) {
@@ -594,12 +257,12 @@
         const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
 
         if (glyph.fWidth) {
-            this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
-                                                glyph.getSubXFixed(),
-                                                glyph.getSubYFixed()),
-                                  fx,
-                                  fy,
-                                  fontScaler);
+            this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                            glyph.getSubXFixed(),
+                                            glyph.getSubYFixed()),
+                              fx,
+                              fy,
+                              fontScaler);
         }
 
         fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale);
@@ -643,12 +306,12 @@
                 SkScalar x = offset.x() + pos[0];
                 SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0);
 
-                this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
-                                                    glyph.getSubXFixed(),
-                                                    glyph.getSubYFixed()),
-                                      SkScalarToFixed(x),
-                                      SkScalarToFixed(y),
-                                      fontScaler);
+                this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                                glyph.getSubXFixed(),
+                                                glyph.getSubYFixed()),
+                                  SkScalarToFixed(x),
+                                  SkScalarToFixed(y),
+                                  fontScaler);
             }
             pos += scalarsPerPosition;
         }
@@ -662,12 +325,12 @@
                 SkScalar x = offset.x() + pos[0];
                 SkScalar y = offset.y() + (2 == scalarsPerPosition ? pos[1] : 0);
 
-                this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
-                                                    glyph.getSubXFixed(),
-                                                    glyph.getSubYFixed()),
-                                      SkScalarToFixed(x) - (glyph.fAdvanceX >> alignShift),
-                                      SkScalarToFixed(y) - (glyph.fAdvanceY >> alignShift),
-                                      fontScaler);
+                this->appendGlyph(GrGlyph::Pack(glyph.getGlyphID(),
+                                                glyph.getSubXFixed(),
+                                                glyph.getSubYFixed()),
+                                  SkScalarToFixed(x) - (glyph.fAdvanceX >> alignShift),
+                                  SkScalarToFixed(y) - (glyph.fAdvanceY >> alignShift),
+                                  fontScaler);
             }
             pos += scalarsPerPosition;
         }
@@ -675,3 +338,335 @@
 
     this->finish();
 }
+
+static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
+    unsigned r = SkColorGetR(c);
+    unsigned g = SkColorGetG(c);
+    unsigned b = SkColorGetB(c);
+    return GrColorPackRGBA(r, g, b, 0xff);
+}
+
+void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColor) {
+    GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
+    GrTextureParams gammaParams(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
+    
+    uint32_t textureUniqueID = fCurrTexture->getUniqueID();
+    const SkMatrix& ctm = fContext->getMatrix();
+    
+    // set up any flags
+    uint32_t flags = 0;
+    flags |= ctm.isSimilarity() ? kSimilarity_DistanceFieldEffectFlag : 0;
+    flags |= fUseLCDText ? kUseLCD_DistanceFieldEffectFlag : 0;
+    flags |= fUseLCDText && ctm.rectStaysRect() ?
+    kRectToRect_DistanceFieldEffectFlag : 0;
+    bool useBGR = SkPixelGeometryIsBGR(fDeviceProperties.fPixelGeometry);
+    flags |= fUseLCDText && useBGR ? kBGR_DistanceFieldEffectFlag : 0;
+    
+    // see if we need to create a new effect
+    if (textureUniqueID != fEffectTextureUniqueID ||
+        filteredColor != fEffectColor ||
+        flags != fEffectFlags) {
+        if (fUseLCDText) {
+            GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
+            fCachedGeometryProcessor.reset(GrDistanceFieldLCDTextureEffect::Create(fCurrTexture,
+                                                                                   params,
+                                                                                   fGammaTexture,
+                                                                                   gammaParams,
+                                                                                   colorNoPreMul,
+                                                                                   flags));
+        } else {
+#ifdef SK_GAMMA_APPLY_TO_A8
+            U8CPU lum = SkColorSpaceLuminance::computeLuminance(fDeviceProperties.getGamma(),
+                                                                filteredColor);
+            fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create(fCurrTexture,
+                                                                                params,
+                                                                                fGammaTexture,
+                                                                                gammaParams,
+                                                                                lum/255.f,
+                                                                                flags));
+#else
+            fCachedGeometryProcessor.reset(GrDistanceFieldTextureEffect::Create(fCurrTexture,
+                                                                                params, flags));
+#endif
+        }
+        fEffectTextureUniqueID = textureUniqueID;
+        fEffectColor = filteredColor;
+        fEffectFlags = flags;
+    }
+    
+}
+
+void GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed,
+                                             SkFixed vx, SkFixed vy,
+                                             GrFontScaler* scaler) {
+    if (NULL == fDrawTarget) {
+        return;
+    }
+
+    if (NULL == fStrike) {
+        fStrike = fContext->getFontCache()->getStrike(scaler, true);
+    }
+
+    GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
+    if (NULL == glyph || glyph->fBounds.isEmpty()) {
+        return;
+    }
+
+    SkScalar sx = SkFixedToScalar(vx);
+    SkScalar sy = SkFixedToScalar(vy);
+/*
+    // not valid, need to find a different solution for this
+    vx += SkIntToFixed(glyph->fBounds.fLeft);
+    vy += SkIntToFixed(glyph->fBounds.fTop);
+
+    // keep them as ints until we've done the clip-test
+    GrFixed width = glyph->fBounds.width();
+    GrFixed height = glyph->fBounds.height();
+
+    // check if we clipped out
+    if (true || NULL == glyph->fPlot) {
+        int x = vx >> 16;
+        int y = vy >> 16;
+        if (fClipRect.quickReject(x, y, x + width, y + height)) {
+//            SkCLZ(3);    // so we can set a break-point in the debugger
+            return;
+        }
+    }
+*/
+    if (NULL == glyph->fPlot) {
+        if (!fStrike->glyphTooLargeForAtlas(glyph)) {
+            if (fStrike->addGlyphToAtlas(glyph, scaler)) {
+                goto HAS_ATLAS;
+            }
+
+            // try to clear out an unused plot before we flush
+            if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+                fStrike->addGlyphToAtlas(glyph, scaler)) {
+                goto HAS_ATLAS;
+            }
+
+            if (c_DumpFontCache) {
+#ifdef SK_DEVELOPER
+                fContext->getFontCache()->dump();
+#endif
+            }
+
+            // before we purge the cache, we must flush any accumulated draws
+            this->flush();
+            fContext->flush();
+
+            // we should have an unused plot now
+            if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+                fStrike->addGlyphToAtlas(glyph, scaler)) {
+                goto HAS_ATLAS;
+            }
+        }
+
+        if (NULL == glyph->fPath) {
+            SkPath* path = SkNEW(SkPath);
+            if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
+                // flag the glyph as being dead?
+                delete path;
+                return;
+            }
+            glyph->fPath = path;
+        }
+
+        GrContext::AutoMatrix am;
+        SkMatrix ctm;
+        ctm.setScale(fTextRatio, fTextRatio);
+        ctm.postTranslate(sx, sy);
+        GrPaint tmpPaint(fPaint);
+        am.setPreConcat(fContext, ctm, &tmpPaint);
+        GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
+        fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo);
+        return;
+    }
+
+HAS_ATLAS:
+    SkASSERT(glyph->fPlot);
+    GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
+    glyph->fPlot->setDrawToken(drawToken);
+
+    GrTexture* texture = glyph->fPlot->texture();
+    SkASSERT(texture);
+
+    if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
+        this->flush();
+        fCurrTexture = texture;
+        fCurrTexture->ref();
+    }
+
+    bool useColorVerts = !fUseLCDText;
+
+    if (NULL == fVertices) {
+        // If we need to reserve vertices allow the draw target to suggest
+        // a number of verts to reserve and whether to perform a flush.
+        fMaxVertices = kMinRequestedVerts;
+        if (useColorVerts) {
+            fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
+                SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize);
+        } else {
+            fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
+                SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
+        }
+        bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL);
+        if (flush) {
+            this->flush();
+            fContext->flush();
+            if (useColorVerts) {
+                fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
+                    SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize);
+            } else {
+                fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
+                    SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
+            }
+        }
+        fMaxVertices = kDefaultRequestedVerts;
+        // ignore return, no point in flushing again.
+        fDrawTarget->geometryHints(&fMaxVertices, NULL);
+        
+        int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads();
+        if (fMaxVertices < kMinRequestedVerts) {
+            fMaxVertices = kDefaultRequestedVerts;
+        } else if (fMaxVertices > maxQuadVertices) {
+            // don't exceed the limit of the index buffer
+            fMaxVertices = maxQuadVertices;
+        }
+        bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices,
+                                                               0,
+                                                               &fVertices,
+                                                               NULL);
+        GrAlwaysAssert(success);
+    }
+
+    SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset);
+    SkScalar dy = SkIntToScalar(glyph->fBounds.fTop + SK_DistanceFieldInset);
+    SkScalar width = SkIntToScalar(glyph->fBounds.width() - 2*SK_DistanceFieldInset);
+    SkScalar height = SkIntToScalar(glyph->fBounds.height() - 2*SK_DistanceFieldInset);
+
+    SkScalar scale = fTextRatio;
+    dx *= scale;
+    dy *= scale;
+    sx += dx;
+    sy += dy;
+    width *= scale;
+    height *= scale;
+
+    SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX + SK_DistanceFieldInset);
+    SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY + SK_DistanceFieldInset);
+    SkFixed tw = SkIntToFixed(glyph->fBounds.width() - 2*SK_DistanceFieldInset);
+    SkFixed th = SkIntToFixed(glyph->fBounds.height() - 2*SK_DistanceFieldInset);
+
+    SkRect r;
+    r.fLeft = sx;
+    r.fTop = sy;
+    r.fRight = sx + width;
+    r.fBottom = sy + height;
+
+    fVertexBounds.joinNonEmptyArg(r);
+
+    size_t vertSize = fUseLCDText ? (2 * sizeof(SkPoint))
+                                  : (2 * sizeof(SkPoint) + sizeof(GrColor));
+    
+    SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexStride());
+
+    SkPoint* positions = reinterpret_cast<SkPoint*>(
+                               reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex);
+    positions->setRectFan(r.fLeft, r.fTop, r.fRight, r.fBottom, vertSize);
+
+    // The texture coords are last in both the with and without color vertex layouts.
+    SkPoint* textureCoords = reinterpret_cast<SkPoint*>(
+                               reinterpret_cast<intptr_t>(positions) + vertSize  - sizeof(SkPoint));
+    textureCoords->setRectFan(SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx)),
+                              SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty)),
+                              SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx + tw)),
+                              SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty + th)),
+                              vertSize);
+    if (useColorVerts) {
+        if (0xFF == GrColorUnpackA(fPaint.getColor())) {
+            fDrawTarget->drawState()->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
+        }
+        // color comes after position.
+        GrColor* colors = reinterpret_cast<GrColor*>(positions + 1);
+        for (int i = 0; i < 4; ++i) {
+            *colors = fPaint.getColor();
+            colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(colors) + vertSize);
+        }
+    }
+
+    fCurrVertex += 4;
+}
+
+void GrDistanceFieldTextContext::flush() {
+    if (NULL == fDrawTarget) {
+        return;
+    }
+
+    GrDrawState* drawState = fDrawTarget->drawState();
+    GrDrawState::AutoRestoreEffects are(drawState);
+
+    drawState->setFromPaint(fPaint, fContext->getMatrix(), fContext->getRenderTarget());
+
+    if (fCurrVertex > 0) {
+        // setup our sampler state for our text texture/atlas
+        SkASSERT(SkIsAlign4(fCurrVertex));
+
+        // get our current color
+        SkColor filteredColor;
+        SkColorFilter* colorFilter = fSkPaint.getColorFilter();
+        if (colorFilter) {
+            filteredColor = colorFilter->filterColor(fSkPaint.getColor());
+        } else {
+            filteredColor = fSkPaint.getColor();
+        }
+        this->setupCoverageEffect(filteredColor);
+
+        // Effects could be stored with one of the cache objects (atlas?)
+        drawState->setGeometryProcessor(fCachedGeometryProcessor.get());
+
+        // Set draw state
+        if (fUseLCDText) {
+            GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredColor);
+            if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
+                kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
+                fPaint.numColorStages()) {
+                GrPrintf("LCD Text will not draw correctly.\n");
+            }
+            SkASSERT(!drawState->hasColorVertexAttribute());
+            // We don't use the GrPaint's color in this case because it's been premultiplied by
+            // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by
+            // the mask texture color. The end result is that we get
+            //            mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
+            int a = SkColorGetA(fSkPaint.getColor());
+            // paintAlpha
+            drawState->setColor(SkColorSetARGB(a, a, a, a));
+            // paintColor
+            drawState->setBlendConstant(colorNoPreMul);
+            drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
+        } else {
+            // set back to normal in case we took LCD path previously.
+            drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
+            // We're using per-vertex color.
+            SkASSERT(drawState->hasColorVertexAttribute());
+        }
+        int nGlyphs = fCurrVertex / 4;
+        fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
+        fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
+                                          nGlyphs,
+                                          4, 6, &fVertexBounds);
+        fDrawTarget->resetVertexSource();
+        fVertices = NULL;
+        fMaxVertices = 0;
+        fCurrVertex = 0;
+        SkSafeSetNull(fCurrTexture);
+        fVertexBounds.setLargestInverted();
+    }
+}
+
+inline void GrDistanceFieldTextContext::finish() {
+    this->flush();
+
+    GrTextContext::finish();
+}
+
diff --git a/src/gpu/GrDistanceFieldTextContext.h b/src/gpu/GrDistanceFieldTextContext.h
index 0b08b59..d628e3e 100644
--- a/src/gpu/GrDistanceFieldTextContext.h
+++ b/src/gpu/GrDistanceFieldTextContext.h
@@ -21,6 +21,8 @@
     GrDistanceFieldTextContext(GrContext*, const SkDeviceProperties&, bool enable);
     virtual ~GrDistanceFieldTextContext();
 
+    virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE;
+
     virtual void drawText(const GrPaint&, const SkPaint&, const char text[], size_t byteLength,
                           SkScalar x, SkScalar y) SK_OVERRIDE;
     virtual void drawPosText(const GrPaint&, const SkPaint&,
@@ -28,26 +30,7 @@
                              const SkScalar pos[], int scalarsPerPosition,
                              const SkPoint& offset) SK_OVERRIDE;
 
-    virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE;
-
 private:
-    GrTextStrike*                      fStrike;
-    SkScalar                           fTextRatio;
-    bool                               fUseLCDText;
-    bool                               fEnableDFRendering;
-    SkAutoTUnref<GrGeometryProcessor>  fCachedGeometryProcessor;
-    // Used to check whether fCachedEffect is still valid.
-    uint32_t                fEffectTextureUniqueID;
-    SkColor                 fEffectColor;
-    uint32_t                fEffectFlags;
-    GrTexture*              fGammaTexture;
-
-    void init(const GrPaint&, const SkPaint&);
-    void drawPackedGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*);
-    void flushGlyphs();                 // automatically called by destructor
-    void setupCoverageEffect(const SkColor& filteredColor);
-    void finish();
-
     enum {
         kMinRequestedGlyphs      = 1,
         kDefaultRequestedGlyphs  = 64,
@@ -55,11 +38,27 @@
         kDefaultRequestedVerts   = kDefaultRequestedGlyphs * 4,
     };
 
-    void*                   fVertices;
-    int32_t                 fMaxVertices;
-    GrTexture*              fCurrTexture;
-    int                     fCurrVertex;
-    SkRect                  fVertexBounds;
+    GrTextStrike*                      fStrike;
+    SkScalar                           fTextRatio;
+    bool                               fUseLCDText;
+    bool                               fEnableDFRendering;
+    SkAutoTUnref<GrGeometryProcessor>  fCachedGeometryProcessor;
+    // Used to check whether fCachedEffect is still valid.
+    uint32_t                           fEffectTextureUniqueID;
+    SkColor                            fEffectColor;
+    uint32_t                           fEffectFlags;
+    GrTexture*                         fGammaTexture;
+    void*                              fVertices;
+    int32_t                            fMaxVertices;
+    GrTexture*                         fCurrTexture;
+    int                                fCurrVertex;
+    SkRect                             fVertexBounds;
+
+    void init(const GrPaint&, const SkPaint&);
+    void appendGlyph(GrGlyph::PackedID, SkFixed left, SkFixed top, GrFontScaler*);
+    void setupCoverageEffect(const SkColor& filteredColor);
+    void flush();                 // automatically called by destructor
+    void finish();
 };
 
 #endif
diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp
index cfcabe9..1941fa7 100644
--- a/src/gpu/GrStencilAndCoverTextContext.cpp
+++ b/src/gpu/GrStencilAndCoverTextContext.cpp
@@ -28,6 +28,30 @@
 GrStencilAndCoverTextContext::~GrStencilAndCoverTextContext() {
 }
 
+bool GrStencilAndCoverTextContext::canDraw(const SkPaint& paint) {
+    if (paint.getRasterizer()) {
+        return false;
+    }
+    if (paint.getMaskFilter()) {
+        return false;
+    }
+    if (paint.getPathEffect()) {
+        return false;
+    }
+
+    // No hairlines unless we can map the 1 px width to the object space.
+    if (paint.getStyle() == SkPaint::kStroke_Style
+        && paint.getStrokeWidth() == 0
+        && fContext->getMatrix().hasPerspective()) {
+        return false;
+    }
+
+    // No color bitmap fonts.
+    SkScalerContext::Rec    rec;
+    SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec);
+    return rec.getFormat() != SkMask::kARGB32_Format;
+}
+
 void GrStencilAndCoverTextContext::drawText(const GrPaint& paint,
                                             const SkPaint& skPaint,
                                             const char text[],
@@ -189,30 +213,6 @@
     this->finish();
 }
 
-bool GrStencilAndCoverTextContext::canDraw(const SkPaint& paint) {
-    if (paint.getRasterizer()) {
-        return false;
-    }
-    if (paint.getMaskFilter()) {
-        return false;
-    }
-    if (paint.getPathEffect()) {
-        return false;
-    }
-
-    // No hairlines unless we can map the 1 px width to the object space.
-    if (paint.getStyle() == SkPaint::kStroke_Style
-        && paint.getStrokeWidth() == 0
-        && fContext->getMatrix().hasPerspective()) {
-        return false;
-    }
-
-    // No color bitmap fonts.
-    SkScalerContext::Rec    rec;
-    SkScalerContext::MakeRec(paint, &fDeviceProperties, NULL, &rec);
-    return rec.getFormat() != SkMask::kARGB32_Format;
-}
-
 static GrPathRange* get_gr_glyphs(GrContext* ctx,
                                   const SkTypeface* typeface,
                                   const SkDescriptor* desc,
diff --git a/src/gpu/GrStencilAndCoverTextContext.h b/src/gpu/GrStencilAndCoverTextContext.h
index b6e23bd..dc32025 100644
--- a/src/gpu/GrStencilAndCoverTextContext.h
+++ b/src/gpu/GrStencilAndCoverTextContext.h
@@ -27,6 +27,8 @@
     GrStencilAndCoverTextContext(GrContext*, const SkDeviceProperties&);
     virtual ~GrStencilAndCoverTextContext();
 
+    virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE;
+
     virtual void drawText(const GrPaint&, const SkPaint&, const char text[],
                           size_t byteLength,
                           SkScalar x, SkScalar y) SK_OVERRIDE;
@@ -35,8 +37,6 @@
                              const SkScalar pos[], int scalarsPerPosition,
                              const SkPoint& offset) SK_OVERRIDE;
 
-    virtual bool canDraw(const SkPaint& paint) SK_OVERRIDE;
-
 private:
     static const int kGlyphBufferSize = 1024;
 
@@ -61,6 +61,18 @@
         kMaxPerformance_RenderMode,
     };
 
+    GrDrawState::AutoRestoreEffects fStateRestore;
+    SkScalar                        fTextRatio;
+    float                           fTextInverseRatio;
+    SkGlyphCache*                   fGlyphCache;
+    GrPathRange*                    fGlyphs;
+    uint32_t                        fIndexBuffer[kGlyphBufferSize];
+    float                           fTransformBuffer[2 * kGlyphBufferSize];
+    GrDrawTarget::PathTransformType fTransformType;
+    int                             fPendingGlyphCount;
+    SkMatrix                        fContextInitialMatrix;
+    bool                            fNeedsDeviceSpaceGlyphs;
+
     void init(const GrPaint&, const SkPaint&, size_t textByteLength,
               RenderMode, const SkPoint& textTranslate);
     void initGlyphs(SkGlyphCache* cache);
@@ -69,17 +81,6 @@
     void flush();
     void finish();
 
-    GrDrawState::AutoRestoreEffects fStateRestore;
-    SkScalar fTextRatio;
-    float fTextInverseRatio;
-    SkGlyphCache* fGlyphCache;
-    GrPathRange* fGlyphs;
-    uint32_t fIndexBuffer[kGlyphBufferSize];
-    float fTransformBuffer[2 * kGlyphBufferSize];
-    GrDrawTarget::PathTransformType fTransformType;
-    int fPendingGlyphCount;
-    SkMatrix fContextInitialMatrix;
-    bool fNeedsDeviceSpaceGlyphs;
 };
 
 #endif
diff --git a/src/gpu/GrTextContext.h b/src/gpu/GrTextContext.h
index da41c1b..b82a648 100644
--- a/src/gpu/GrTextContext.h
+++ b/src/gpu/GrTextContext.h
@@ -24,6 +24,9 @@
 class GrTextContext {
 public:
     virtual ~GrTextContext() {}
+
+    virtual bool canDraw(const SkPaint& paint) = 0;
+
     virtual void drawText(const GrPaint&, const SkPaint&, const char text[], size_t byteLength,
                           SkScalar x, SkScalar y) = 0;
     virtual void drawPosText(const GrPaint&, const SkPaint&,
@@ -31,18 +34,7 @@
                              const SkScalar pos[], int scalarsPerPosition,
                              const SkPoint& offset) = 0;
 
-    virtual bool canDraw(const SkPaint& paint) = 0;
-
 protected:
-    GrTextContext(GrContext*, const SkDeviceProperties&);
-
-    static GrFontScaler* GetGrFontScaler(SkGlyphCache* cache);
-    static void MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
-                            const char text[], size_t byteLength, SkVector* stopVector);
-
-    void init(const GrPaint&, const SkPaint&);
-    void finish() { fDrawTarget = NULL; }
-
     GrContext*         fContext;
     SkDeviceProperties fDeviceProperties;
 
@@ -50,6 +42,15 @@
     SkIRect            fClipRect;
     GrPaint            fPaint;
     SkPaint            fSkPaint;
+
+    GrTextContext(GrContext*, const SkDeviceProperties&);
+
+    void init(const GrPaint&, const SkPaint&);
+    void finish() { fDrawTarget = NULL; }
+
+    static GrFontScaler* GetGrFontScaler(SkGlyphCache* cache);
+    static void MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
+                            const char text[], size_t byteLength, SkVector* stopVector);
 };
 
 #endif