Fix the rendering error of SkDraw::drawVertices in gpu path for solid color.

If both textures and vertex-colors are NULL, drawVertices should stroke hairlines with the paint's color.
This behavior is a useful debugging mode to visualize the mesh.

BUG=skia:2266
R=bsalomon@google.com, reed@google.com

Author: yunchao.he@intel.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@14985 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index 1739fef..5692fe1 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -26,6 +26,7 @@
 #include "SkStroke.h"
 #include "SkTLazy.h"
 #include "SkUtils.h"
+#include "SkVertState.h"
 
 #include "SkAutoKern.h"
 #include "SkBitmapProcShader.h"
@@ -2210,133 +2211,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-struct VertState {
-    int f0, f1, f2;
-
-    VertState(int vCount, const uint16_t indices[], int indexCount)
-            : fIndices(indices) {
-        fCurrIndex = 0;
-        if (indices) {
-            fCount = indexCount;
-        } else {
-            fCount = vCount;
-        }
-    }
-
-    typedef bool (*Proc)(VertState*);
-    Proc chooseProc(SkCanvas::VertexMode mode);
-
-private:
-    int             fCount;
-    int             fCurrIndex;
-    const uint16_t* fIndices;
-
-    static bool Triangles(VertState*);
-    static bool TrianglesX(VertState*);
-    static bool TriangleStrip(VertState*);
-    static bool TriangleStripX(VertState*);
-    static bool TriangleFan(VertState*);
-    static bool TriangleFanX(VertState*);
-};
-
-bool VertState::Triangles(VertState* state) {
-    int index = state->fCurrIndex;
-    if (index + 3 > state->fCount) {
-        return false;
-    }
-    state->f0 = index + 0;
-    state->f1 = index + 1;
-    state->f2 = index + 2;
-    state->fCurrIndex = index + 3;
-    return true;
-}
-
-bool VertState::TrianglesX(VertState* state) {
-    const uint16_t* indices = state->fIndices;
-    int index = state->fCurrIndex;
-    if (index + 3 > state->fCount) {
-        return false;
-    }
-    state->f0 = indices[index + 0];
-    state->f1 = indices[index + 1];
-    state->f2 = indices[index + 2];
-    state->fCurrIndex = index + 3;
-    return true;
-}
-
-bool VertState::TriangleStrip(VertState* state) {
-    int index = state->fCurrIndex;
-    if (index + 3 > state->fCount) {
-        return false;
-    }
-    state->f2 = index + 2;
-    if (index & 1) {
-        state->f0 = index + 1;
-        state->f1 = index + 0;
-    } else {
-        state->f0 = index + 0;
-        state->f1 = index + 1;
-    }
-    state->fCurrIndex = index + 1;
-    return true;
-}
-
-bool VertState::TriangleStripX(VertState* state) {
-    const uint16_t* indices = state->fIndices;
-    int index = state->fCurrIndex;
-    if (index + 3 > state->fCount) {
-        return false;
-    }
-    state->f2 = indices[index + 2];
-    if (index & 1) {
-        state->f0 = indices[index + 1];
-        state->f1 = indices[index + 0];
-    } else {
-        state->f0 = indices[index + 0];
-        state->f1 = indices[index + 1];
-    }
-    state->fCurrIndex = index + 1;
-    return true;
-}
-
-bool VertState::TriangleFan(VertState* state) {
-    int index = state->fCurrIndex;
-    if (index + 3 > state->fCount) {
-        return false;
-    }
-    state->f0 = 0;
-    state->f1 = index + 1;
-    state->f2 = index + 2;
-    state->fCurrIndex = index + 1;
-    return true;
-}
-
-bool VertState::TriangleFanX(VertState* state) {
-    const uint16_t* indices = state->fIndices;
-    int index = state->fCurrIndex;
-    if (index + 3 > state->fCount) {
-        return false;
-    }
-    state->f0 = indices[0];
-    state->f1 = indices[index + 1];
-    state->f2 = indices[index + 2];
-    state->fCurrIndex = index + 1;
-    return true;
-}
-
-VertState::Proc VertState::chooseProc(SkCanvas::VertexMode mode) {
-    switch (mode) {
-        case SkCanvas::kTriangles_VertexMode:
-            return fIndices ? TrianglesX : Triangles;
-        case SkCanvas::kTriangleStrip_VertexMode:
-            return fIndices ? TriangleStripX : TriangleStrip;
-        case SkCanvas::kTriangleFan_VertexMode:
-            return fIndices ? TriangleFanX : TriangleFan;
-        default:
-            return NULL;
-    }
-}
-
 typedef void (*HairProc)(const SkPoint&, const SkPoint&, const SkRasterClip&,
                          SkBlitter*);
 
@@ -2613,7 +2487,7 @@
             SkScan::FillTriangle(tmp, *fRC, blitter.get());
         }
     } else {
-        // no colors[] and no texture
+        // no colors[] and no texture, stroke hairlines with paint's color.
         HairProc hairProc = ChooseHairProc(paint.isAntiAlias());
         const SkRasterClip& clip = *fRC;
         while (vertProc(&state)) {
diff --git a/src/core/SkVertState.cpp b/src/core/SkVertState.cpp
new file mode 100644
index 0000000..f23b108
--- /dev/null
+++ b/src/core/SkVertState.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkVertState.h"
+
+bool VertState::Triangles(VertState* state) {
+    int index = state->fCurrIndex;
+    if (index + 3 > state->fCount) {
+        return false;
+    }
+    state->f0 = index + 0;
+    state->f1 = index + 1;
+    state->f2 = index + 2;
+    state->fCurrIndex = index + 3;
+    return true;
+}
+
+bool VertState::TrianglesX(VertState* state) {
+    const uint16_t* indices = state->fIndices;
+    int index = state->fCurrIndex;
+    if (index + 3 > state->fCount) {
+        return false;
+    }
+    state->f0 = indices[index + 0];
+    state->f1 = indices[index + 1];
+    state->f2 = indices[index + 2];
+    state->fCurrIndex = index + 3;
+    return true;
+}
+
+bool VertState::TriangleStrip(VertState* state) {
+    int index = state->fCurrIndex;
+    if (index + 3 > state->fCount) {
+        return false;
+    }
+    state->f2 = index + 2;
+    if (index & 1) {
+        state->f0 = index + 1;
+        state->f1 = index + 0;
+    } else {
+        state->f0 = index + 0;
+        state->f1 = index + 1;
+    }
+    state->fCurrIndex = index + 1;
+    return true;
+}
+
+bool VertState::TriangleStripX(VertState* state) {
+    const uint16_t* indices = state->fIndices;
+    int index = state->fCurrIndex;
+    if (index + 3 > state->fCount) {
+        return false;
+    }
+    state->f2 = indices[index + 2];
+    if (index & 1) {
+        state->f0 = indices[index + 1];
+        state->f1 = indices[index + 0];
+    } else {
+        state->f0 = indices[index + 0];
+        state->f1 = indices[index + 1];
+    }
+    state->fCurrIndex = index + 1;
+    return true;
+}
+
+bool VertState::TriangleFan(VertState* state) {
+    int index = state->fCurrIndex;
+    if (index + 3 > state->fCount) {
+        return false;
+    }
+    state->f0 = 0;
+    state->f1 = index + 1;
+    state->f2 = index + 2;
+    state->fCurrIndex = index + 1;
+    return true;
+}
+
+bool VertState::TriangleFanX(VertState* state) {
+    const uint16_t* indices = state->fIndices;
+    int index = state->fCurrIndex;
+    if (index + 3 > state->fCount) {
+        return false;
+    }
+    state->f0 = indices[0];
+    state->f1 = indices[index + 1];
+    state->f2 = indices[index + 2];
+    state->fCurrIndex = index + 1;
+    return true;
+}
+
+VertState::Proc VertState::chooseProc(SkCanvas::VertexMode mode) {
+    switch (mode) {
+        case SkCanvas::kTriangles_VertexMode:
+            return fIndices ? TrianglesX : Triangles;
+        case SkCanvas::kTriangleStrip_VertexMode:
+            return fIndices ? TriangleStripX : TriangleStrip;
+        case SkCanvas::kTriangleFan_VertexMode:
+            return fIndices ? TriangleFanX : TriangleFan;
+        default:
+            return NULL;
+    }
+}
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 431238b..45da4cf 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -34,6 +34,7 @@
 #include "SkSurface.h"
 #include "SkTLazy.h"
 #include "SkUtils.h"
+#include "SkVertState.h"
 #include "SkErrorInternals.h"
 
 #define CACHE_COMPATIBLE_DEVICE_TEXTURES 1
@@ -1628,6 +1629,31 @@
                               const SkPaint& paint) {
     CHECK_SHOULD_DRAW(draw, false);
 
+    // If both textures and vertex-colors are NULL, strokes hairlines with the paint's color.
+    if ((NULL == texs || NULL == paint.getShader()) && NULL == colors) {
+        texs = NULL;
+        SkPaint copy(paint);
+        copy.setStyle(SkPaint::kStroke_Style);
+        copy.setStrokeWidth(0);
+
+        VertState       state(vertexCount, indices, indexCount);
+        VertState::Proc vertProc = state.chooseProc(vmode);
+
+        SkPoint* pts = new SkPoint[vertexCount * 6];
+        int i = 0;
+        while (vertProc(&state)) {
+            pts[i] = vertices[state.f0];
+            pts[i + 1] = vertices[state.f1];
+            pts[i + 2] = vertices[state.f1];
+            pts[i + 3] = vertices[state.f2];
+            pts[i + 4] = vertices[state.f2];
+            pts[i + 5] = vertices[state.f0];
+            i += 6;
+        }
+        draw.drawPoints(SkCanvas::kLines_PointMode, i, pts, copy, true);
+        return;
+    }
+
     GrPaint grPaint;
     // we ignore the shader if texs is null.
     if (NULL == texs) {