Add vertex color support to distance field text.

BUG=skia:
R=bsalomon@google.com

Author: jvanverth@google.com

Review URL: https://codereview.chromium.org/421563002
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
index 8827382..0ef596a 100755
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/src/gpu/GrDistanceFieldTextContext.cpp
@@ -25,7 +25,11 @@
 #include "SkStrokeRec.h"
 #include "effects/GrDistanceFieldTextureEffect.h"
 
-static const int kGlyphCoordsAttributeIndex = 1;
+SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
+                "Dump the contents of the font cache before every purge.");
+
+static const int kGlyphCoordsNoColorAttributeIndex = 1;
+static const int kGlyphCoordsWithColorAttributeIndex = 2;
 
 static const int kSmallDFFontSize = 32;
 static const int kSmallDFFontLimit = 32;
@@ -33,8 +37,21 @@
 static const int kMediumDFFontLimit = 64;
 static const int kLargeDFFontSize = 128;
 
-SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
-                "Dump the contents of the font cache before every purge.");
+namespace {
+// position + texture coord
+extern const GrVertexAttrib gTextVertexAttribs[] = {
+    {kVec2f_GrVertexAttribType, 0,                kPosition_GrVertexAttribBinding},
+    {kVec2f_GrVertexAttribType, sizeof(SkPoint) , kEffect_GrVertexAttribBinding}
+};
+
+// position + color + texture coord
+extern const GrVertexAttrib gTextVertexWithColorAttribs[] = {
+    {kVec2f_GrVertexAttribType,  0,                                 kPosition_GrVertexAttribBinding},
+    {kVec4ub_GrVertexAttribType, sizeof(SkPoint),                   kColor_GrVertexAttribBinding},
+    {kVec2f_GrVertexAttribType,  sizeof(SkPoint) + sizeof(GrColor), kEffect_GrVertexAttribBinding}
+};
+    
+};
 
 GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
                                                        const SkDeviceProperties& properties,
@@ -112,6 +129,8 @@
         GrTextureParams gammaParams(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
 
         // Effects could be stored with one of the cache objects (atlas?)
+        int coordsIdx = drawState->hasColorVertexAttribute() ? kGlyphCoordsWithColorAttributeIndex :
+                                                               kGlyphCoordsNoColorAttributeIndex;
         SkColor filteredColor;
         SkColorFilter* colorFilter = fSkPaint.getColorFilter();
         if (NULL != colorFilter) {
@@ -132,13 +151,14 @@
                                                             fContext->getMatrix().rectStaysRect() &&
                                                             fContext->getMatrix().isSimilarity(),
                                                             useBGR),
-                                         kGlyphCoordsAttributeIndex)->unref();
+                                         coordsIdx)->unref();
 
             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
@@ -158,18 +178,20 @@
                                                               fGammaTexture, gammaParams,
                                                               lum/255.f,
                                                               fContext->getMatrix().isSimilarity()),
-                                         kGlyphCoordsAttributeIndex)->unref();
+                                         coordsIdx)->unref();
 #else
             drawState->addCoverageEffect(GrDistanceFieldTextureEffect::Create(
                                                               currTexture, params,
                                                               fContext->getMatrix().isSimilarity()),
-                                         kGlyphCoordsAttributeIndex)->unref();
+                                         coordsIdx)->unref();
 #endif
             // set back to normal in case we took LCD path previously.
             drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
-            drawState->setColor(fPaint.getColor());
+            //drawState->setColor(fPaint.getColor());
+            // We're using per-vertex color.
+            SkASSERT(drawState->hasColorVertexAttribute());
+            drawState->setColor(0xFFFFFFFF);
         }
-
         int nGlyphs = fCurrVertex / 4;
         fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
         fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
@@ -181,16 +203,6 @@
     fVertices = NULL;
 }
 
-namespace {
-
-// position + texture coord
-extern const GrVertexAttrib gTextVertexAttribs[] = {
-    {kVec2f_GrVertexAttribType, 0,               kPosition_GrVertexAttribBinding},
-    {kVec2f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding}
-};
-
-};
-
 void GrDistanceFieldTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
                                                  SkFixed vx, SkFixed vy,
                                                  GrFontScaler* scaler) {
@@ -294,21 +306,32 @@
     SkFixed tw = SkIntToFixed(glyph->fBounds.width() - 2*SK_DistanceFieldInset);
     SkFixed th = SkIntToFixed(glyph->fBounds.height() - 2*SK_DistanceFieldInset);
 
-    static const size_t kVertexSize = 2 * sizeof(SkPoint);
+    size_t vertSize = fUseLCDText ? (2 * sizeof(SkPoint))
+                                  : (2 * sizeof(SkPoint) + sizeof(GrColor));
+    
+    SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexSize());
+    
     SkPoint* positions = reinterpret_cast<SkPoint*>(
-                                reinterpret_cast<intptr_t>(fVertices) + kVertexSize * fCurrVertex);
-    positions->setRectFan(sx,
-                          sy,
-                          sx + width,
-                          sy + height,
-                          kVertexSize);
+        reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex);
+    positions->setRectFan(sx, sy, sx + width, sy + height, vertSize);
+    
+    // The texture coords are last in both the with and without color vertex layouts.
     SkPoint* textureCoords = reinterpret_cast<SkPoint*>(
-                            reinterpret_cast<intptr_t>(positions) + kVertexSize  - sizeof(SkPoint));
+            reinterpret_cast<intptr_t>(positions) + vertSize  - sizeof(SkPoint));
     textureCoords->setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)),
-                                          SkFixedToFloat(texture->normalizeFixedY(ty)),
-                                          SkFixedToFloat(texture->normalizeFixedX(tx + tw)),
-                                          SkFixedToFloat(texture->normalizeFixedY(ty + th)),
-                                          kVertexSize);
+                              SkFixedToFloat(texture->normalizeFixedY(ty)),
+                              SkFixedToFloat(texture->normalizeFixedX(tx + tw)),
+                              SkFixedToFloat(texture->normalizeFixedY(ty + th)),
+                              vertSize);
+    if (!fUseLCDText) {
+        // color comes after position.
+        GrColor* colors = reinterpret_cast<GrColor*>(positions + 1);
+        for (int i = 0; i < 4; ++i) {
+            *colors = fPaint.getColor();
+            colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(colors) + vertSize);
+        }
+    }
+    
     fCurrVertex += 4;
 }
 
@@ -342,7 +365,7 @@
 }
 
 inline void GrDistanceFieldTextContext::finish() {
-    flushGlyphs();
+    this->flushGlyphs();
 
     GrTextContext::finish();
 }
@@ -419,8 +442,13 @@
 
     // allocate vertices
     SkASSERT(NULL == fVertices);
-    fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
-                                                                SK_ARRAY_COUNT(gTextVertexAttribs));
+    if (!fUseLCDText) {
+        fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
+                                                       SK_ARRAY_COUNT(gTextVertexWithColorAttribs));
+    } else {
+        fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
+                                                       SK_ARRAY_COUNT(gTextVertexAttribs));
+    }
     int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
     bool success = fDrawTarget->reserveVertexAndIndexSpace(4*numGlyphs,
                                                            0,
@@ -510,8 +538,13 @@
 
     // allocate vertices
     SkASSERT(NULL == fVertices);
-    fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
-                                                                SK_ARRAY_COUNT(gTextVertexAttribs));
+    if (!fUseLCDText) {
+        fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
+                                                       SK_ARRAY_COUNT(gTextVertexWithColorAttribs));
+    } else {
+        fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
+                                                       SK_ARRAY_COUNT(gTextVertexAttribs));
+    }
     int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
     bool success = fDrawTarget->reserveVertexAndIndexSpace(4*numGlyphs,
                                                            0,