Add fallback code for TextContexts that don't support all features

BUG=skia:2018

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

Author: jvanverth@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@13236 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/gpu/GrBitmapTextContext.h b/include/gpu/GrBitmapTextContext.h
index c66f8a8..6550e3c 100755
--- a/include/gpu/GrBitmapTextContext.h
+++ b/include/gpu/GrBitmapTextContext.h
@@ -17,16 +17,17 @@
  */
 class GrBitmapTextContext : public GrTextContext {
 public:
+    GrBitmapTextContext(GrContext*, const GrPaint&, const SkPaint&, const SkDeviceProperties&);
+    virtual ~GrBitmapTextContext();
+
     virtual void drawText(const char text[], size_t byteLength, SkScalar x, SkScalar y) SK_OVERRIDE;
     virtual void drawPosText(const char text[], size_t byteLength,
                              const SkScalar pos[], SkScalar constY,
                              int scalarsPerPosition) SK_OVERRIDE;
 
+    static bool CanDraw(const SkPaint& paint, const SkMatrix& ctm);
+    
 private:
-    GrBitmapTextContext(GrContext*, const GrPaint&, const SkPaint&, const SkDeviceProperties&);
-    virtual ~GrBitmapTextContext();
-    friend class GrTTextContextManager<GrBitmapTextContext>;
-
     GrTextStrike*          fStrike;
 
     void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top, GrFontScaler*);
diff --git a/include/gpu/GrDistanceFieldTextContext.h b/include/gpu/GrDistanceFieldTextContext.h
index 172342a..8b94038 100755
--- a/include/gpu/GrDistanceFieldTextContext.h
+++ b/include/gpu/GrDistanceFieldTextContext.h
@@ -21,6 +21,8 @@
     virtual void drawPosText(const char text[], size_t byteLength,
                              const SkScalar pos[], SkScalar constY,
                              int scalarsPerPosition) SK_OVERRIDE;
+    
+    static bool CanDraw(const SkPaint& paint, const SkMatrix& ctm);
 
 private:
     GrDistanceFieldTextContext(GrContext*, const GrPaint&, const SkPaint&,
diff --git a/include/gpu/GrTextContext.h b/include/gpu/GrTextContext.h
index 273e094..c572d0d 100644
--- a/include/gpu/GrTextContext.h
+++ b/include/gpu/GrTextContext.h
@@ -29,7 +29,7 @@
     virtual void drawPosText(const char text[], size_t byteLength,
                              const SkScalar pos[], SkScalar constY,
                              int scalarsPerPosition) = 0;
-
+    
 protected:
     GrTextContext(GrContext*, const GrPaint&, const SkPaint&, const SkDeviceProperties&);
 
@@ -55,6 +55,7 @@
     virtual ~GrTextContextManager() {}
     virtual GrTextContext* create(GrContext* grContext, const GrPaint& grPaint,
                                   const SkPaint& skPaint, const SkDeviceProperties& props) = 0;
+    virtual bool canDraw(const SkPaint& paint, const SkMatrix& ctm) = 0;
 };
 
 template <class TextContextClass>
@@ -110,6 +111,10 @@
         return obj;
     }
 
+    virtual bool canDraw(const SkPaint& paint, const SkMatrix& ctm) SK_OVERRIDE {
+        return TextContextClass::CanDraw(paint, ctm);
+    }
+
 private:
     void recycle(GrTextContext* textContext) {
         SkASSERT((void*)textContext == fAllocation);
diff --git a/src/gpu/GrBitmapTextContext.cpp b/src/gpu/GrBitmapTextContext.cpp
index ff81b2d..488aa13 100755
--- a/src/gpu/GrBitmapTextContext.cpp
+++ b/src/gpu/GrBitmapTextContext.cpp
@@ -19,6 +19,7 @@
 #include "effects/GrCustomCoordsTextureEffect.h"
 
 #include "SkAutoKern.h"
+#include "SkDraw.h"
 #include "SkGlyphCache.h"
 #include "SkGpuDevice.h"
 #include "SkGr.h"
@@ -28,6 +29,10 @@
 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
                 "Dump the contents of the font cache before every purge.");
 
+bool GrBitmapTextContext::CanDraw(const SkPaint& paint, const SkMatrix& ctm) {
+    return !SkDraw::ShouldDrawTextAsPaths(paint, ctm);
+}
+
 GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
                                          const GrPaint& grPaint,
                                          const SkPaint& skPaint,
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
index 505ee39..52b714c 100755
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/src/gpu/GrDistanceFieldTextContext.cpp
@@ -13,6 +13,7 @@
 #include "GrIndexBuffer.h"
 #include "GrTextStrike.h"
 #include "GrTextStrike_impl.h"
+#include "SkDraw.h"
 #include "SkGpuDevice.h"
 #include "SkPath.h"
 #include "SkRTConf.h"
@@ -26,6 +27,12 @@
 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
                 "Dump the contents of the font cache before every purge.");
 
+bool GrDistanceFieldTextContext::CanDraw(const SkPaint& paint, const SkMatrix& ctm) {
+    return !paint.getRasterizer() && !paint.getMaskFilter() &&
+           paint.getStyle() == SkPaint::kFill_Style &&
+           !SkDraw::ShouldDrawTextAsPaths(paint, ctm);
+}
+
 GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
                                                        const GrPaint& grPaint,
                                                        const SkPaint& skPaint,
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index df302c4..f951a15 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1771,9 +1771,7 @@
                           const SkPaint& paint) {
     CHECK_SHOULD_DRAW(draw, false);
 
-    if (SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix())) {
-        draw.drawText_asPaths((const char*)text, byteLength, x, y, paint);
-    } else {
+    if (fTextContextManager->canDraw(paint, fContext->getMatrix())) {
         GrPaint grPaint;
         if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
             return;
@@ -1785,6 +1783,20 @@
                                                                      grPaint, paint,
                                                                      this->getDeviceProperties()));
         ctx->drawText((const char *)text, byteLength, x, y);
+    } else if (GrBitmapTextContext::CanDraw(paint, fContext->getMatrix())) {
+        GrPaint grPaint;
+        if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
+            return;
+        }
+
+        SkDEBUGCODE(this->validate();)
+
+        GrBitmapTextContext textContext(this->context(), grPaint, paint,
+                                        this->getDeviceProperties());
+        textContext.drawText((const char *)text, byteLength, x, y);
+    } else {
+        // this guy will just call our drawPath()
+        draw.drawText_asPaths((const char*)text, byteLength, x, y, paint);
     }
 }
 
@@ -1794,11 +1806,7 @@
                              const SkPaint& paint) {
     CHECK_SHOULD_DRAW(draw, false);
 
-    if (SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix())) {
-        // this guy will just call our drawPath()
-        draw.drawPosText_asPaths((const char*)text, byteLength, pos, constY,
-                         scalarsPerPos, paint);
-    } else {
+    if (fTextContextManager->canDraw(paint, fContext->getMatrix())) {
         GrPaint grPaint;
         if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
             return;
@@ -1810,6 +1818,20 @@
                                                                      grPaint, paint,
                                                                      this->getDeviceProperties()));
         ctx->drawPosText((const char *)text, byteLength, pos, constY, scalarsPerPos);
+    } else if (GrBitmapTextContext::CanDraw(paint, fContext->getMatrix())) {
+        GrPaint grPaint;
+        if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) {
+            return;
+        }
+        
+        SkDEBUGCODE(this->validate();)
+        
+        GrBitmapTextContext textContext(this->context(), grPaint, paint,
+                                        this->getDeviceProperties());
+        textContext.drawPosText((const char *)text, byteLength, pos, constY, scalarsPerPos);
+    } else {
+        draw.drawPosText_asPaths((const char*)text, byteLength, pos, constY,
+                                 scalarsPerPos, paint);
     }
 }