Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / GrBitmapTextContext.cpp
index 82784bf..a45aeae 100755 (executable)
 #include "GrFontScaler.h"
 #include "GrIndexBuffer.h"
 #include "GrStrokeInfo.h"
+#include "GrTexturePriv.h"
 #include "GrTextStrike.h"
 #include "GrTextStrike_impl.h"
-#include "SkColorPriv.h"
-#include "SkPath.h"
-#include "SkRTConf.h"
-#include "SkStrokeRec.h"
 #include "effects/GrCustomCoordsTextureEffect.h"
+#include "effects/GrSimpleTextureEffect.h"
 
 #include "SkAutoKern.h"
+#include "SkColorPriv.h"
 #include "SkDraw.h"
 #include "SkDrawProcs.h"
 #include "SkGlyphCache.h"
 #include "SkGpuDevice.h"
 #include "SkGr.h"
+#include "SkPath.h"
+#include "SkRTConf.h"
+#include "SkStrokeRec.h"
 #include "SkTextMapStateProc.h"
 
 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
@@ -32,22 +34,32 @@ SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
 
 namespace {
 // position + texture coord
-extern const GrVertexAttrib gTextVertexAttribs[] = {
+extern const GrVertexAttrib gLCDVertexAttribs[] = {
     {kVec2f_GrVertexAttribType, 0,               kPosition_GrVertexAttribBinding},
     {kVec2f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding}
 };
 
-static const size_t kTextVASize = 2 * sizeof(SkPoint); 
+static const size_t kLCDTextVASize = 2 * sizeof(SkPoint);
+
+// position + local coord
+extern const GrVertexAttrib gColorVertexAttribs[] = {
+    {kVec2f_GrVertexAttribType, 0,               kPosition_GrVertexAttribBinding},
+    {kVec2f_GrVertexAttribType, sizeof(SkPoint), kLocalCoord_GrVertexAttribBinding}
+};
+
+static const size_t kColorTextVASize = 2 * sizeof(SkPoint);
 
 // position + color + texture coord
-extern const GrVertexAttrib gTextVertexWithColorAttribs[] = {
+extern const GrVertexAttrib gGrayVertexAttribs[] = {
     {kVec2f_GrVertexAttribType,  0,                                 kPosition_GrVertexAttribBinding},
     {kVec4ub_GrVertexAttribType, sizeof(SkPoint),                   kColor_GrVertexAttribBinding},
     {kVec2f_GrVertexAttribType,  sizeof(SkPoint) + sizeof(GrColor), kGeometryProcessor_GrVertexAttribBinding}
 };
 
-static const size_t kTextVAColorSize = 2 * sizeof(SkPoint) + sizeof(GrColor); 
+static const size_t kGrayTextVASize = 2 * sizeof(SkPoint) + sizeof(GrColor);
 
+static const int kVerticesPerGlyph = 4;
+static const int kIndicesPerGlyph = 6;
 };
 
 GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
@@ -56,109 +68,29 @@ GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
     fStrike = NULL;
 
     fCurrTexture = NULL;
-    fCurrVertex = 0;
     fEffectTextureUniqueID = SK_InvalidUniqueID;
 
     fVertices = NULL;
-    fMaxVertices = 0;
+    fCurrVertex = 0;
+    fAllocVertexCount = 0;
+    fTotalVertexCount = 0;
 
     fVertexBounds.setLargestInverted();
 }
 
+GrBitmapTextContext* GrBitmapTextContext::Create(GrContext* context,
+                                                 const SkDeviceProperties& props) {
+    return SkNEW_ARGS(GrBitmapTextContext, (context, props));
+}
+
 GrBitmapTextContext::~GrBitmapTextContext() {
-    this->flushGlyphs();
+    this->finish();
 }
 
 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);
 
@@ -168,16 +100,11 @@ inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPai
     fCurrVertex = 0;
 
     fVertices = NULL;
-    fMaxVertices = 0;
+    fAllocVertexCount = 0;
+    fTotalVertexCount = 0;
 }
 
-inline void GrBitmapTextContext::finish() {
-    this->flushGlyphs();
-
-    GrTextContext::finish();
-}
-
-void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
+void GrBitmapTextContext::onDrawText(const GrPaint& paint, const SkPaint& skPaint,
                                    const char text[], size_t byteLength,
                                    SkScalar x, SkScalar y) {
     SkASSERT(byteLength == 0 || text != NULL);
@@ -204,13 +131,13 @@ void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
     }
 
     // need to measure first
+    int numGlyphs;
     if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
-        SkVector    stop;
-
-        MeasureText(cache, glyphCacheProc, text, byteLength, &stop);
+        SkVector    stopVector;
+        numGlyphs = MeasureText(cache, glyphCacheProc, text, byteLength, &stopVector);
 
-        SkScalar    stopX = stop.fX;
-        SkScalar    stopY = stop.fY;
+        SkScalar    stopX = stopVector.fX;
+        SkScalar    stopY = stopVector.fY;
 
         if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
             stopX = SkScalarHalf(stopX);
@@ -218,7 +145,10 @@ void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
         }
         x -= stopX;
         y -= stopY;
+    } else {
+        numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
     }
+    fTotalVertexCount = kVerticesPerGlyph*numGlyphs;
 
     const char* stop = text + byteLength;
 
@@ -253,12 +183,12 @@ void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
         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;
@@ -268,10 +198,10 @@ void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
     this->finish();
 }
 
-void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
+void GrBitmapTextContext::onDrawPosText(const GrPaint& paint, const SkPaint& skPaint,
                                       const char text[], size_t byteLength,
-                                      const SkScalar pos[], SkScalar constY,
-                                      int scalarsPerPosition) {
+                                      const SkScalar pos[], int scalarsPerPosition,
+                                      const SkPoint& offset) {
     SkASSERT(byteLength == 0 || text != NULL);
     SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
 
@@ -293,9 +223,12 @@ void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai
     GrContext::AutoMatrix  autoMatrix;
     autoMatrix.setIdentity(fContext, &fPaint);
 
+    int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
+    fTotalVertexCount = kVerticesPerGlyph*numGlyphs;
+
     const char*        stop = text + byteLength;
     SkTextAlignProc    alignProc(fSkPaint.getTextAlign());
-    SkTextMapStateProc tmsProc(ctm, constY, scalarsPerPosition);
+    SkTextMapStateProc tmsProc(ctm, offset, scalarsPerPosition);
     SkFixed halfSampleX = 0, halfSampleY = 0;
 
     if (cache->isSubpixel()) {
@@ -327,12 +260,12 @@ void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai
                                                       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;
             }
@@ -360,12 +293,12 @@ void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai
                     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;
             }
@@ -383,12 +316,12 @@ void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai
 
                     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;
             }
@@ -406,12 +339,12 @@ void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai
 
                     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;
             }
@@ -421,9 +354,34 @@ void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai
     this->finish();
 }
 
-void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
-                                          SkFixed vx, SkFixed vy,
-                                          GrFontScaler* scaler) {
+static void* alloc_vertices(GrDrawTarget* drawTarget, int numVertices, GrMaskFormat maskFormat) {
+    if (numVertices <= 0) {
+        return NULL;
+    }
+
+    // set up attributes
+    if (kA8_GrMaskFormat == maskFormat) {
+        drawTarget->drawState()->setVertexAttribs<gGrayVertexAttribs>(
+                                    SK_ARRAY_COUNT(gGrayVertexAttribs), kGrayTextVASize);
+    } else if (kARGB_GrMaskFormat == maskFormat) {
+        drawTarget->drawState()->setVertexAttribs<gColorVertexAttribs>(
+                                    SK_ARRAY_COUNT(gColorVertexAttribs), kColorTextVASize);
+    } else {
+        drawTarget->drawState()->setVertexAttribs<gLCDVertexAttribs>(
+                                    SK_ARRAY_COUNT(gLCDVertexAttribs), kLCDTextVASize);
+    }
+    void* vertices = NULL;
+    bool success = drawTarget->reserveVertexAndIndexSpace(numVertices,
+                                                          0,
+                                                          &vertices,
+                                                          NULL);
+    GrAlwaysAssert(success);
+    return vertices;
+}
+
+void GrBitmapTextContext::appendGlyph(GrGlyph::PackedID packed,
+                                      SkFixed vx, SkFixed vy,
+                                      GrFontScaler* scaler) {
     if (NULL == fDrawTarget) {
         return;
     }
@@ -461,7 +419,7 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
             }
 
             // try to clear out an unused plot before we flush
-            if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+            if (fContext->getFontCache()->freeUnusedPlot(fStrike, glyph) &&
                 fStrike->addGlyphToAtlas(glyph, scaler)) {
                 goto HAS_ATLAS;
             }
@@ -473,11 +431,11 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
             }
 
             // 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
-            if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+            if (fContext->getFontCache()->freeUnusedPlot(fStrike, glyph) &&
                 fStrike->addGlyphToAtlas(glyph, scaler)) {
                 goto HAS_ATLAS;
             }
@@ -493,6 +451,9 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
             glyph->fPath = path;
         }
 
+        // flush any accumulated draws before drawing this glyph as a path.
+        this->flush();
+
         GrContext::AutoMatrix am;
         SkMatrix translate;
         translate.setTranslate(SkFixedToScalar(vx - SkIntToFixed(glyph->fBounds.fLeft)),
@@ -501,6 +462,9 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
         am.setPreConcat(fContext, translate, &tmpPaint);
         GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
         fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo);
+
+        // remove this glyph from the vertices we need to allocate
+        fTotalVertexCount -= kVerticesPerGlyph;
         return;
     }
 
@@ -513,56 +477,21 @@ HAS_ATLAS:
     width = SkIntToFixed(width);
     height = SkIntToFixed(height);
 
+    // the current texture/maskformat must match what the glyph needs
     GrTexture* texture = glyph->fPlot->texture();
     SkASSERT(texture);
 
-    if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
-        this->flushGlyphs();
+    if (fCurrTexture != texture || fCurrVertex + kVerticesPerGlyph > fAllocVertexCount) {
+        this->flush();
         fCurrTexture = texture;
         fCurrTexture->ref();
+        fCurrMaskFormat = glyph->fMaskFormat;
     }
 
-    bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat();
-
     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);
+        int maxQuadVertices = kVerticesPerGlyph * fContext->getQuadIndexBuffer()->maxQuads();
+        fAllocVertexCount = SkMin32(fTotalVertexCount, maxQuadVertices);
+        fVertices = alloc_vertices(fDrawTarget, fAllocVertexCount, fCurrMaskFormat);
     }
 
     SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
@@ -574,10 +503,18 @@ HAS_ATLAS:
     r.fRight = SkFixedToFloat(vx + width);
     r.fBottom = SkFixedToFloat(vy + height);
 
-    fVertexBounds.growToInclude(r);
-
-    size_t vertSize = useColorVerts ? (2 * sizeof(SkPoint) + sizeof(GrColor)) :
-                                      (2 * sizeof(SkPoint));
+    fVertexBounds.joinNonEmptyArg(r);
+
+    size_t vertSize;
+    switch (fCurrMaskFormat) {
+        case kA8_GrMaskFormat:
+            vertSize = kGrayTextVASize;
+            break;
+        case kARGB_GrMaskFormat:
+            vertSize = kColorTextVASize;
+        default:
+            vertSize = kLCDTextVASize;
+    }
 
     SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexStride());
 
@@ -588,12 +525,12 @@ HAS_ATLAS:
     // 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->normalizeFixedX(tx)),
-                              SkFixedToFloat(texture->normalizeFixedY(ty)),
-                              SkFixedToFloat(texture->normalizeFixedX(tx + width)),
-                              SkFixedToFloat(texture->normalizeFixedY(ty + height)),
+    textureCoords->setRectFan(SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx)),
+                              SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty)),
+                              SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx + width)),
+                              SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty + height)),
                               vertSize);
-    if (useColorVerts) {
+    if (kA8_GrMaskFormat == fCurrMaskFormat) {
         if (0xFF == GrColorUnpackA(fPaint.getColor())) {
             fDrawTarget->drawState()->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
         }
@@ -606,3 +543,106 @@ HAS_ATLAS:
     }
     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);
+
+        // This effect could be stored with one of the cache objects (atlas?)
+        if (kARGB_GrMaskFormat == fCurrMaskFormat) {
+            GrFragmentProcessor* fragProcessor = GrSimpleTextureEffect::Create(fCurrTexture,
+                                                                               SkMatrix::I(),
+                                                                               params);
+            drawState->addColorProcessor(fragProcessor)->unref();
+        } else {
+            uint32_t textureUniqueID = fCurrTexture->getUniqueID();
+            if (textureUniqueID != fEffectTextureUniqueID) {
+                fCachedGeometryProcessor.reset(GrCustomCoordsTextureEffect::Create(fCurrTexture,
+                                                                                   params));
+                fEffectTextureUniqueID = textureUniqueID;
+            }
+
+            drawState->setGeometryProcessor(fCachedGeometryProcessor.get());
+        }
+
+        SkASSERT(fStrike);
+        switch (fCurrMaskFormat) {
+                // Color bitmap text
+            case kARGB_GrMaskFormat:
+                SkASSERT(!drawState->hasColorVertexAttribute());
+                drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
+                drawState->setAlpha(fSkPaint.getAlpha());
+                break;
+                // LCD text
+            case kA888_GrMaskFormat:
+            case kA565_GrMaskFormat: {
+                if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
+                    kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
+                    fPaint.numColorStages()) {
+                    SkDebugf("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("Unexpected mask format.");
+        }
+        int nGlyphs = fCurrVertex / kVerticesPerGlyph;
+        fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
+        fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
+                                          nGlyphs,
+                                          kVerticesPerGlyph, kIndicesPerGlyph, &fVertexBounds);
+
+        fDrawTarget->resetVertexSource();
+        fVertices = NULL;
+        fAllocVertexCount = 0;
+        // reset to be those that are left
+        fTotalVertexCount -= fCurrVertex;
+        fCurrVertex = 0;
+        fVertexBounds.setLargestInverted();
+        SkSafeSetNull(fCurrTexture);
+    }
+}
+
+inline void GrBitmapTextContext::finish() {
+    this->flush();
+    fTotalVertexCount = 0;
+
+    GrTextContext::finish();
+}
+