use common impl for drawTextOnPath

BUG=skia:

Review URL: https://codereview.chromium.org/925343003
diff --git a/include/core/SkBitmapDevice.h b/include/core/SkBitmapDevice.h
index a801420..8ca6a52 100644
--- a/include/core/SkBitmapDevice.h
+++ b/include/core/SkBitmapDevice.h
@@ -93,9 +93,6 @@
     virtual void drawPosText(const SkDraw&, const void* text, size_t len,
                              const SkScalar pos[], int scalarsPerPos,
                              const SkPoint& offset, const SkPaint& paint) SK_OVERRIDE;
-    virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
-                                const SkPath& path, const SkMatrix* matrix,
-                                const SkPaint& paint) SK_OVERRIDE;
     virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
                               const SkPoint verts[], const SkPoint texs[],
                               const SkColor colors[], SkXfermode* xmode,
diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h
index 9f3ac58..777b7f8 100644
--- a/include/core/SkDevice.h
+++ b/include/core/SkDevice.h
@@ -218,9 +218,6 @@
     virtual void drawPosText(const SkDraw&, const void* text, size_t len,
                              const SkScalar pos[], int scalarsPerPos,
                              const SkPoint& offset, const SkPaint& paint) = 0;
-    virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len,
-                                const SkPath& path, const SkMatrix* matrix,
-                                const SkPaint& paint) = 0;
     virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
                               const SkPoint verts[], const SkPoint texs[],
                               const SkColor colors[], SkXfermode* xmode,
@@ -238,6 +235,8 @@
     virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y,
                             const SkPaint&) = 0;
 
+    virtual void drawTextOnPath(const SkDraw&, const void* text, size_t len, const SkPath&,
+                                const SkMatrix*, const SkPaint&);
     bool readPixels(const SkImageInfo&, void* dst, size_t rowBytes, int x, int y);
 
     ///////////////////////////////////////////////////////////////////////////
diff --git a/include/core/SkDraw.h b/include/core/SkDraw.h
index 2bb9c89..7b5514d 100644
--- a/include/core/SkDraw.h
+++ b/include/core/SkDraw.h
@@ -68,8 +68,6 @@
     void    drawPosText(const char text[], size_t byteLength,
                         const SkScalar pos[], int scalarsPerPosition,
                         const SkPoint& offset, const SkPaint& paint) const;
-    void    drawTextOnPath(const char text[], size_t byteLength,
-                        const SkPath&, const SkMatrix*, const SkPaint&) const;
     void    drawVertices(SkCanvas::VertexMode mode, int count,
                          const SkPoint vertices[], const SkPoint textures[],
                          const SkColor colors[], SkXfermode* xmode,
diff --git a/include/pdf/SkPDFDevice.h b/include/pdf/SkPDFDevice.h
index 66689f2..af65005 100644
--- a/include/pdf/SkPDFDevice.h
+++ b/include/pdf/SkPDFDevice.h
@@ -98,9 +98,6 @@
     void drawPosText(const SkDraw&, const void* text, size_t len,
                      const SkScalar pos[], int scalarsPerPos,
                      const SkPoint& offset, const SkPaint&) SK_OVERRIDE;
-    void drawTextOnPath(const SkDraw&, const void* text, size_t len,
-                        const SkPath& path, const SkMatrix* matrix,
-                        const SkPaint& paint) SK_OVERRIDE;
     void drawVertices(const SkDraw&, SkCanvas::VertexMode,
                       int vertexCount, const SkPoint verts[],
                       const SkPoint texs[], const SkColor colors[],
diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp
index 1f17e6f..e545bae 100644
--- a/src/core/SkBitmapDevice.cpp
+++ b/src/core/SkBitmapDevice.cpp
@@ -329,13 +329,6 @@
     draw.drawPosText((const char*)text, len, xpos, scalarsPerPos, offset, paint);
 }
 
-void SkBitmapDevice::drawTextOnPath(const SkDraw& draw, const void* text,
-                                    size_t len, const SkPath& path,
-                                    const SkMatrix* matrix,
-                                    const SkPaint& paint) {
-    draw.drawTextOnPath((const char*)text, len, path, matrix, paint);
-}
-
 void SkBitmapDevice::drawVertices(const SkDraw& draw, SkCanvas::VertexMode vmode,
                                   int vertexCount,
                                   const SkPoint verts[], const SkPoint textures[],
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index bc6c892..2f51070 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -10,8 +10,11 @@
 #include "SkDraw.h"
 #include "SkMetaData.h"
 #include "SkPatchUtils.h"
+#include "SkPathMeasure.h"
+#include "SkRasterClip.h"
 #include "SkShader.h"
 #include "SkTextBlob.h"
+#include "SkTextToPathIter.h"
 
 SkBaseDevice::SkBaseDevice()
     : fLeakyProperties(SkNEW_ARGS(SkDeviceProperties, (SkDeviceProperties::kLegacyLCD_InitType)))
@@ -212,6 +215,129 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+static void morphpoints(SkPoint dst[], const SkPoint src[], int count,
+                        SkPathMeasure& meas, const SkMatrix& matrix) {
+    SkMatrix::MapXYProc proc = matrix.getMapXYProc();
+    
+    for (int i = 0; i < count; i++) {
+        SkPoint pos;
+        SkVector tangent;
+        
+        proc(matrix, src[i].fX, src[i].fY, &pos);
+        SkScalar sx = pos.fX;
+        SkScalar sy = pos.fY;
+        
+        if (!meas.getPosTan(sx, &pos, &tangent)) {
+            // set to 0 if the measure failed, so that we just set dst == pos
+            tangent.set(0, 0);
+        }
+        
+        /*  This is the old way (that explains our approach but is way too slow
+         SkMatrix    matrix;
+         SkPoint     pt;
+         
+         pt.set(sx, sy);
+         matrix.setSinCos(tangent.fY, tangent.fX);
+         matrix.preTranslate(-sx, 0);
+         matrix.postTranslate(pos.fX, pos.fY);
+         matrix.mapPoints(&dst[i], &pt, 1);
+         */
+        dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy),
+                   pos.fY + SkScalarMul(tangent.fX, sy));
+    }
+}
+
+/*  TODO
+ 
+ Need differentially more subdivisions when the follow-path is curvy. Not sure how to
+ determine that, but we need it. I guess a cheap answer is let the caller tell us,
+ but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out.
+ */
+static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas,
+                      const SkMatrix& matrix) {
+    SkPath::Iter    iter(src, false);
+    SkPoint         srcP[4], dstP[3];
+    SkPath::Verb    verb;
+    
+    while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) {
+        switch (verb) {
+            case SkPath::kMove_Verb:
+                morphpoints(dstP, srcP, 1, meas, matrix);
+                dst->moveTo(dstP[0]);
+                break;
+            case SkPath::kLine_Verb:
+                // turn lines into quads to look bendy
+                srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX);
+                srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY);
+                morphpoints(dstP, srcP, 2, meas, matrix);
+                dst->quadTo(dstP[0], dstP[1]);
+                break;
+            case SkPath::kQuad_Verb:
+                morphpoints(dstP, &srcP[1], 2, meas, matrix);
+                dst->quadTo(dstP[0], dstP[1]);
+                break;
+            case SkPath::kCubic_Verb:
+                morphpoints(dstP, &srcP[1], 3, meas, matrix);
+                dst->cubicTo(dstP[0], dstP[1], dstP[2]);
+                break;
+            case SkPath::kClose_Verb:
+                dst->close();
+                break;
+            default:
+                SkDEBUGFAIL("unknown verb");
+                break;
+        }
+    }
+}
+
+void SkBaseDevice::drawTextOnPath(const SkDraw& draw, const void* text, size_t byteLength,
+                                  const SkPath& follow, const SkMatrix* matrix,
+                                  const SkPaint& paint) {
+    SkASSERT(byteLength == 0 || text != NULL);
+    
+    // nothing to draw
+    if (text == NULL || byteLength == 0 || draw.fRC->isEmpty()) {
+        return;
+    }
+    
+    SkTextToPathIter    iter((const char*)text, byteLength, paint, true);
+    SkPathMeasure       meas(follow, false);
+    SkScalar            hOffset = 0;
+    
+    // need to measure first
+    if (paint.getTextAlign() != SkPaint::kLeft_Align) {
+        SkScalar pathLen = meas.getLength();
+        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
+            pathLen = SkScalarHalf(pathLen);
+        }
+        hOffset += pathLen;
+    }
+    
+    const SkPath*   iterPath;
+    SkScalar        xpos;
+    SkMatrix        scaledMatrix;
+    SkScalar        scale = iter.getPathScale();
+    
+    scaledMatrix.setScale(scale, scale);
+    
+    while (iter.next(&iterPath, &xpos)) {
+        if (iterPath) {
+            SkPath      tmp;
+            SkMatrix    m(scaledMatrix);
+            
+            tmp.setIsVolatile(true);
+            m.postTranslate(xpos + hOffset, 0);
+            if (matrix) {
+                m.postConcat(*matrix);
+            }
+            morphpath(&tmp, *iterPath, meas, m);
+            this->drawPath(draw, tmp, iter.getPaint(), NULL, true);
+        }
+    }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
 uint32_t SkBaseDevice::filterTextFlags(const SkPaint& paint) const {
     uint32_t flags = paint.getFlags();
 
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index 03b3311..f40c1bb 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -1866,135 +1866,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-#include "SkPathMeasure.h"
-
-static void morphpoints(SkPoint dst[], const SkPoint src[], int count,
-                        SkPathMeasure& meas, const SkMatrix& matrix) {
-    SkMatrix::MapXYProc proc = matrix.getMapXYProc();
-
-    for (int i = 0; i < count; i++) {
-        SkPoint pos;
-        SkVector tangent;
-
-        proc(matrix, src[i].fX, src[i].fY, &pos);
-        SkScalar sx = pos.fX;
-        SkScalar sy = pos.fY;
-
-        if (!meas.getPosTan(sx, &pos, &tangent)) {
-            // set to 0 if the measure failed, so that we just set dst == pos
-            tangent.set(0, 0);
-        }
-
-        /*  This is the old way (that explains our approach but is way too slow
-            SkMatrix    matrix;
-            SkPoint     pt;
-
-            pt.set(sx, sy);
-            matrix.setSinCos(tangent.fY, tangent.fX);
-            matrix.preTranslate(-sx, 0);
-            matrix.postTranslate(pos.fX, pos.fY);
-            matrix.mapPoints(&dst[i], &pt, 1);
-        */
-        dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy),
-                   pos.fY + SkScalarMul(tangent.fX, sy));
-    }
-}
-
-/*  TODO
-
-    Need differentially more subdivisions when the follow-path is curvy. Not sure how to
-    determine that, but we need it. I guess a cheap answer is let the caller tell us,
-    but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out.
-*/
-static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas,
-                      const SkMatrix& matrix) {
-    SkPath::Iter    iter(src, false);
-    SkPoint         srcP[4], dstP[3];
-    SkPath::Verb    verb;
-
-    while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) {
-        switch (verb) {
-            case SkPath::kMove_Verb:
-                morphpoints(dstP, srcP, 1, meas, matrix);
-                dst->moveTo(dstP[0]);
-                break;
-            case SkPath::kLine_Verb:
-                // turn lines into quads to look bendy
-                srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX);
-                srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY);
-                morphpoints(dstP, srcP, 2, meas, matrix);
-                dst->quadTo(dstP[0], dstP[1]);
-                break;
-            case SkPath::kQuad_Verb:
-                morphpoints(dstP, &srcP[1], 2, meas, matrix);
-                dst->quadTo(dstP[0], dstP[1]);
-                break;
-            case SkPath::kCubic_Verb:
-                morphpoints(dstP, &srcP[1], 3, meas, matrix);
-                dst->cubicTo(dstP[0], dstP[1], dstP[2]);
-                break;
-            case SkPath::kClose_Verb:
-                dst->close();
-                break;
-            default:
-                SkDEBUGFAIL("unknown verb");
-                break;
-        }
-    }
-}
-
-void SkDraw::drawTextOnPath(const char text[], size_t byteLength,
-                            const SkPath& follow, const SkMatrix* matrix,
-                            const SkPaint& paint) const {
-    SkASSERT(byteLength == 0 || text != NULL);
-
-    // nothing to draw
-    if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
-        return;
-    }
-
-    SkTextToPathIter    iter(text, byteLength, paint, true);
-    SkPathMeasure       meas(follow, false);
-    SkScalar            hOffset = 0;
-
-    // need to measure first
-    if (paint.getTextAlign() != SkPaint::kLeft_Align) {
-        SkScalar pathLen = meas.getLength();
-        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
-            pathLen = SkScalarHalf(pathLen);
-        }
-        hOffset += pathLen;
-    }
-
-    const SkPath*   iterPath;
-    SkScalar        xpos;
-    SkMatrix        scaledMatrix;
-    SkScalar        scale = iter.getPathScale();
-
-    scaledMatrix.setScale(scale, scale);
-
-    while (iter.next(&iterPath, &xpos)) {
-        if (iterPath) {
-            SkPath      tmp;
-            SkMatrix    m(scaledMatrix);
-
-            tmp.setIsVolatile(true);
-            m.postTranslate(xpos + hOffset, 0);
-            if (matrix) {
-                m.postConcat(*matrix);
-            }
-            morphpath(&tmp, *iterPath, meas, m);
-            if (fDevice) {
-                fDevice->drawPath(*this, tmp, iter.getPaint(), NULL, true);
-            } else {
-                this->drawPath(tmp, iter.getPaint(), NULL, true);
-            }
-        }
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
 typedef void (*HairProc)(const SkPoint&, const SkPoint&, const SkRasterClip&,
                          SkBlitter*);
 
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index b6cc69d..20dae68 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1767,15 +1767,6 @@
     }
 }
 
-void SkGpuDevice::drawTextOnPath(const SkDraw& draw, const void* text,
-                                 size_t len, const SkPath& path,
-                                 const SkMatrix* m, const SkPaint& paint) {
-    CHECK_SHOULD_DRAW(draw);
-
-    SkASSERT(draw.fDevice == this);
-    draw.drawTextOnPath((const char*)text, len, path, m, paint);
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 
 bool SkGpuDevice::onShouldDisableLCD(const SkPaint& paint) const {
diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h
index 6cbf628..4830c02 100644
--- a/src/gpu/SkGpuDevice.h
+++ b/src/gpu/SkGpuDevice.h
@@ -97,9 +97,6 @@
     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 drawTextOnPath(const SkDraw&, const void* text, size_t len,
-                                const SkPath& path, const SkMatrix* matrix,
-                                const SkPaint&) SK_OVERRIDE;
     virtual void drawVertices(const SkDraw&, SkCanvas::VertexMode, int vertexCount,
                               const SkPoint verts[], const SkPoint texs[],
                               const SkColor colors[], SkXfermode* xmode,
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index c3ee262..a15571a 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -1194,15 +1194,6 @@
     content.entry()->fContent.writeText("ET\n");
 }
 
-void SkPDFDevice::drawTextOnPath(const SkDraw& d, const void* text, size_t len,
-                                 const SkPath& path, const SkMatrix* matrix,
-                                 const SkPaint& paint) {
-    if (d.fClip->isEmpty()) {
-        return;
-    }
-    d.drawTextOnPath((const char*)text, len, path, matrix, paint);
-}
-
 void SkPDFDevice::drawVertices(const SkDraw& d, SkCanvas::VertexMode,
                                int vertexCount, const SkPoint verts[],
                                const SkPoint texs[], const SkColor colors[],
diff --git a/src/pdf/SkPDFDeviceFlattener.cpp b/src/pdf/SkPDFDeviceFlattener.cpp
index 4774864..ab6ce09 100644
--- a/src/pdf/SkPDFDeviceFlattener.cpp
+++ b/src/pdf/SkPDFDeviceFlattener.cpp
@@ -132,16 +132,6 @@
     INHERITED::drawPosText(d, text, len, pos, scalarsPerPos, offset, paint);
 }
 
-void SkPDFDeviceFlattener::drawTextOnPath(const SkDraw& d, const void* text, size_t len,
-                                          const SkPath& path, const SkMatrix* matrix,
-                                          const SkPaint& paint) {
-    if (mustPathText(d, paint) || (matrix && matrix->hasPerspective())) {
-        d.drawTextOnPath((const char*)text, len, path, matrix, paint);
-        return;
-    }
-    INHERITED::drawTextOnPath(d, text, len, path, matrix, paint);
-}
-
 bool SkPDFDeviceFlattener::mustFlatten(const SkDraw& d) const {
     // TODO(edisonn): testability, add flag to force return true.
     return d.fMatrix->hasPerspective();
diff --git a/src/pdf/SkPDFDeviceFlattener.h b/src/pdf/SkPDFDeviceFlattener.h
index b2c3d7e..acf1447 100644
--- a/src/pdf/SkPDFDeviceFlattener.h
+++ b/src/pdf/SkPDFDeviceFlattener.h
@@ -39,9 +39,6 @@
     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 drawTextOnPath(const SkDraw&, const void* text, size_t len,
-                                const SkPath& path, const SkMatrix* matrix,
-                                const SkPaint& paint) SK_OVERRIDE;
 private:
 
     bool mustFlatten(const SkDraw& d) const;