Initial change to move text blob to GrTextContext

BUG=skia:

Review URL: https://codereview.chromium.org/1019633002
diff --git a/include/core/SkTextBlob.h b/include/core/SkTextBlob.h
index 1f04d38..6970e6d 100644
--- a/include/core/SkTextBlob.h
+++ b/include/core/SkTextBlob.h
@@ -91,6 +91,7 @@
 
     static unsigned ScalarsPerGlyph(GlyphPositioning pos);
 
+    friend class GrTextContext;
     friend class SkBaseDevice;
     friend class SkTextBlobBuilder;
     friend class TextBlobTester;
diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp
index 28e10e3..d4c0171 100644
--- a/src/gpu/GrTextContext.cpp
+++ b/src/gpu/GrTextContext.cpp
@@ -11,9 +11,11 @@
 #include "GrFontScaler.h"
 
 #include "SkAutoKern.h"
+#include "SkDrawFilter.h"
 #include "SkDrawProcs.h"
 #include "SkGlyphCache.h"
 #include "SkGpuDevice.h"
+#include "SkTextBlob.h"
 #include "SkTextMapStateProc.h"
 #include "SkTextToPathIter.h"
 
@@ -91,6 +93,25 @@
                             clipBounds);
 }
 
+void GrTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip, const SkPaint& skPaint,
+                                 const SkMatrix& viewMatrix, const SkTextBlob* blob,
+                                 SkScalar x, SkScalar y,
+                                 SkDrawFilter* drawFilter, const SkIRect& clipBounds) {
+    if (!fContext->getTextTarget()) {
+        return;
+    }
+
+    GrTextContext* textContext = this;
+    do {
+        if (textContext->canDraw(skPaint, viewMatrix)) {
+            textContext->onDrawTextBlob(rt, clip, skPaint, viewMatrix, blob, x, y, drawFilter,
+                                        clipBounds);
+            return;
+        }
+        textContext = textContext->fFallbackTextContext;
+    } while (textContext);
+}
+
 void GrTextContext::drawTextAsPath(const SkPaint& skPaint, const SkMatrix& viewMatrix,
                                    const char text[], size_t byteLength, SkScalar x, SkScalar y,
                                    const SkIRect& clipBounds) {
@@ -159,6 +180,55 @@
     }
 }
 
+void GrTextContext::onDrawTextBlob(GrRenderTarget* rt, const GrClip& clip,
+                                   const SkPaint& skPaint, const SkMatrix& viewMatrix,
+                                   const SkTextBlob* blob, SkScalar x, SkScalar y,
+                                   SkDrawFilter* drawFilter, const SkIRect& clipBounds) {
+    SkPaint runPaint = skPaint;
+
+    SkTextBlob::RunIterator it(blob);
+    for (;!it.done(); it.next()) {
+        size_t textLen = it.glyphCount() * sizeof(uint16_t);
+        const SkPoint& offset = it.offset();
+        // applyFontToPaint() always overwrites the exact same attributes,
+        // so it is safe to not re-seed the paint for this reason.
+        it.applyFontToPaint(&runPaint);
+
+        if (drawFilter && !drawFilter->filter(&runPaint, SkDrawFilter::kText_Type)) {
+            // A false return from filter() means we should abort the current draw.
+            runPaint = skPaint;
+            continue;
+        }
+
+        runPaint.setFlags(fGpuDevice->filterTextFlags(runPaint));
+
+        GrPaint grPaint;
+        SkPaint2GrPaintShader(fContext, fRenderTarget, runPaint, viewMatrix, true, &grPaint);
+
+        switch (it.positioning()) {
+        case SkTextBlob::kDefault_Positioning:
+            this->drawText(rt, clip, grPaint, runPaint, viewMatrix, (const char *)it.glyphs(),
+                           textLen, x + offset.x(), y + offset.y(), clipBounds);
+            break;
+        case SkTextBlob::kHorizontal_Positioning:
+            this->drawPosText(rt, clip, grPaint, runPaint, viewMatrix, (const char*)it.glyphs(),
+                              textLen, it.pos(), 1, SkPoint::Make(x, y + offset.y()), clipBounds);
+            break;
+        case SkTextBlob::kFull_Positioning:
+            this->drawPosText(rt, clip, grPaint, runPaint, viewMatrix, (const char*)it.glyphs(),
+                              textLen, it.pos(), 2, SkPoint::Make(x, y), clipBounds);
+            break;
+        default:
+            SkFAIL("unhandled positioning mode");
+        }
+
+        if (drawFilter) {
+            // A draw filter may change the paint arbitrarily, so we must re-seed in this case.
+            runPaint = skPaint;
+        }
+    }
+}
+
 //*** change to output positions?
 int GrTextContext::MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
                                 const char text[], size_t byteLength, SkVector* stopVector) {
diff --git a/src/gpu/GrTextContext.h b/src/gpu/GrTextContext.h
index 56a113d..6dfd860 100644
--- a/src/gpu/GrTextContext.h
+++ b/src/gpu/GrTextContext.h
@@ -19,7 +19,9 @@
 class GrContext;
 class GrDrawTarget;
 class GrFontScaler;
+class SkDrawFilter;
 class SkGpuDevice;
+class SkTextBlob;
 
 /*
  * This class wraps the state for a single text render
@@ -36,6 +38,9 @@
                      const char text[], size_t byteLength,
                      const SkScalar pos[], int scalarsPerPosition,
                      const SkPoint& offset, const SkIRect& clipBounds);
+    void drawTextBlob(GrRenderTarget*, const GrClip&, const SkPaint&,
+                      const SkMatrix& viewMatrix, const SkTextBlob*, SkScalar x, SkScalar y,
+                      SkDrawFilter*, const SkIRect& clipBounds);
 
 protected:
     GrTextContext*                 fFallbackTextContext;
@@ -67,6 +72,9 @@
                                const char text[], size_t byteLength,
                                const SkScalar pos[], int scalarsPerPosition,
                                const SkPoint& offset, const SkIRect& clipBounds) = 0;
+    virtual void onDrawTextBlob(GrRenderTarget*, const GrClip&, const SkPaint&,
+                                const SkMatrix& viewMatrix, const SkTextBlob*,
+                                SkScalar x, SkScalar y, SkDrawFilter*, const SkIRect& clipBounds);
 
     void drawTextAsPath(const SkPaint& origPaint, const SkMatrix& viewMatrix,
                         const char text[], size_t byteLength, SkScalar x, SkScalar y,
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 0335bcf..38a22e6 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1845,6 +1845,17 @@
                               draw.fClip->getBounds());
 }
 
+void SkGpuDevice::drawTextBlob(const SkDraw& draw, const SkTextBlob* blob, SkScalar x, SkScalar y,
+                               const SkPaint& paint, SkDrawFilter* drawFilter) {
+    GR_CREATE_TRACE_MARKER_CONTEXT("SkGpuDevice::drawTextBlob", fContext);
+    CHECK_SHOULD_DRAW(draw);
+
+    SkDEBUGCODE(this->validate();)
+
+    fTextContext->drawTextBlob(fRenderTarget, fClip, paint, *draw.fMatrix, blob, x, y, drawFilter,
+                               draw.fClip->getBounds());
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 bool SkGpuDevice::onShouldDisableLCD(const SkPaint& paint) const {
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index be7857a..c712ca9 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -99,6 +99,8 @@
     virtual void drawPosText(const SkDraw&, const void* text, size_t len,
                              const SkScalar pos[], int scalarsPerPos,
                              const SkPoint& offset, const SkPaint&) SK_OVERRIDE;
+    virtual void drawTextBlob(const SkDraw&, const SkTextBlob*, SkScalar x, SkScalar y,
+                              const SkPaint& paint, SkDrawFilter* drawFilter) SK_OVERRIDE;
     virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
                               const SkPoint verts[], const SkPoint texs[],
                               const SkColor colors[], SkXfermode* xmode,