Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / GrBitmapTextContext.cpp
index 4f43c75..82784bf 100755 (executable)
@@ -10,6 +10,7 @@
 #include "GrDrawTarget.h"
 #include "GrFontScaler.h"
 #include "GrIndexBuffer.h"
+#include "GrStrokeInfo.h"
 #include "GrTextStrike.h"
 #include "GrTextStrike_impl.h"
 #include "SkColorPriv.h"
 
 #include "SkAutoKern.h"
 #include "SkDraw.h"
+#include "SkDrawProcs.h"
 #include "SkGlyphCache.h"
 #include "SkGpuDevice.h"
 #include "SkGr.h"
-
-static const int kGlyphCoordsAttributeIndex = 1;
+#include "SkTextMapStateProc.h"
 
 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), kGeometryProcessor_GrVertexAttribBinding}
+};
+
+static const size_t kTextVASize = 2 * sizeof(SkPoint); 
+
+// 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), kGeometryProcessor_GrVertexAttribBinding}
+};
+
+static const size_t kTextVAColorSize = 2 * sizeof(SkPoint) + sizeof(GrColor); 
+
+};
+
 GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
                                          const SkDeviceProperties& properties)
                                        : GrTextContext(context, properties) {
@@ -36,6 +57,7 @@ GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
 
     fCurrTexture = NULL;
     fCurrVertex = 0;
+    fEffectTextureUniqueID = SK_InvalidUniqueID;
 
     fVertices = NULL;
     fMaxVertices = 0;
@@ -69,40 +91,59 @@ void GrBitmapTextContext::flushGlyphs() {
 
     if (fCurrVertex > 0) {
         // setup our sampler state for our text texture/atlas
-        SkASSERT(GrIsALIGN4(fCurrVertex));
+        SkASSERT(SkIsAlign4(fCurrVertex));
         SkASSERT(fCurrTexture);
         GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode);
 
+        uint32_t textureUniqueID = fCurrTexture->getUniqueID();
+        
+        if (textureUniqueID != fEffectTextureUniqueID) {
+            fCachedGeometryProcessor.reset(GrCustomCoordsTextureEffect::Create(fCurrTexture,
+                                                                               params));
+            fEffectTextureUniqueID = textureUniqueID;
+        }
+
         // This effect could be stored with one of the cache objects (atlas?)
-        drawState->addCoverageEffect(
-                                GrCustomCoordsTextureEffect::Create(fCurrTexture, params),
-                                kGlyphCoordsAttributeIndex)->unref();
-
-        if (NULL != fStrike && kARGB_GrMaskFormat == fStrike->getMaskFormat()) {
-            drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
-            drawState->setColor(0xffffffff);
-        } else if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) {
-            if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
-                kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() ||
-                fPaint.numColorStages()) {
-                GrPrintf("LCD Text will not draw correctly.\n");
+        drawState->setGeometryProcessor(fCachedGeometryProcessor.get());
+        SkASSERT(fStrike);
+        switch (fStrike->getMaskFormat()) {
+            // Color bitmap text
+            case kARGB_GrMaskFormat:
+                SkASSERT(!drawState->hasColorVertexAttribute());
+                drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
+                drawState->setColor(0xffffffff);
+                break;
+            // LCD text
+            case kA888_GrMaskFormat:
+            case kA565_GrMaskFormat: {
+                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
+                //            mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
+                int a = SkColorGetA(fSkPaint.getColor());
+                // paintAlpha
+                drawState->setColor(SkColorSetARGB(a, a, a, a));
+                // paintColor
+                drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor()));
+                drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
+                break;
             }
-            // 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
-            //            mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstColor
-            int a = SkColorGetA(fSkPaint.getColor());
-            // paintAlpha
-            drawState->setColor(SkColorSetARGB(a, a, a, a));
-            // paintColor
-            drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPaint.getColor()));
-            drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff);
-        } else {
-            // set back to normal in case we took LCD path previously.
-            drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
-            drawState->setColor(fPaint.getColor());
+            // Grayscale/BW text
+            case kA8_GrMaskFormat:
+                // set back to normal in case we took LCD path previously.
+                drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff());
+                // We're using per-vertex color.
+                SkASSERT(drawState->hasColorVertexAttribute());
+                break;
+            default:
+                SkFAIL("Unexepected mask format.");
         }
-
         int nGlyphs = fCurrVertex / 4;
         fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
         fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
@@ -131,7 +172,7 @@ inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPai
 }
 
 inline void GrBitmapTextContext::finish() {
-    flushGlyphs();
+    this->flushGlyphs();
 
     GrTextContext::finish();
 }
@@ -227,98 +268,6 @@ void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint,
     this->finish();
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// Copied from SkDraw
-
-// last parameter is interpreted as SkFixed [x, y]
-// return the fixed position, which may be rounded or not by the caller
-//   e.g. subpixel doesn't round
-typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*);
-
-static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
-    dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY));
-}
-
-static void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
-    dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1),
-             SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1));
-}
-
-static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
-    dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX,
-             SkScalarToFixed(loc.fY) - glyph.fAdvanceY);
-}
-
-static AlignProc pick_align_proc(SkPaint::Align align) {
-    static const AlignProc gProcs[] = {
-        leftAlignProc, centerAlignProc, rightAlignProc
-    };
-
-    SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
-
-    return gProcs[align];
-}
-
-class BitmapTextMapState {
-public:
-    mutable SkPoint fLoc;
-
-    BitmapTextMapState(const SkMatrix& matrix, SkScalar y)
-        : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {}
-
-    typedef void (*Proc)(const BitmapTextMapState&, const SkScalar pos[]);
-
-    Proc pickProc(int scalarsPerPosition);
-
-private:
-    const SkMatrix&     fMatrix;
-    SkMatrix::MapXYProc fProc;
-    SkScalar            fY; // ignored by MapXYProc
-    // these are only used by Only... procs
-    SkScalar            fScaleX, fTransX, fTransformedY;
-
-    static void MapXProc(const BitmapTextMapState& state, const SkScalar pos[]) {
-        state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc);
-    }
-
-    static void MapXYProc(const BitmapTextMapState& state, const SkScalar pos[]) {
-        state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc);
-    }
-
-    static void MapOnlyScaleXProc(const BitmapTextMapState& state,
-                                  const SkScalar pos[]) {
-        state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX,
-                       state.fTransformedY);
-    }
-
-    static void MapOnlyTransXProc(const BitmapTextMapState& state,
-                                  const SkScalar pos[]) {
-        state.fLoc.set(*pos + state.fTransX, state.fTransformedY);
-    }
-};
-
-BitmapTextMapState::Proc BitmapTextMapState::pickProc(int scalarsPerPosition) {
-    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
-
-    if (1 == scalarsPerPosition) {
-        unsigned mtype = fMatrix.getType();
-        if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
-            return MapXProc;
-        } else {
-            fScaleX = fMatrix.getScaleX();
-            fTransX = fMatrix.getTranslateX();
-            fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) +
-                            fMatrix.getTranslateY();
-            return (mtype & SkMatrix::kScale_Mask) ?
-                        MapOnlyScaleXProc : MapOnlyTransXProc;
-        }
-    } else {
-        return MapXYProc;
-    }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
 void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
                                       const char text[], size_t byteLength,
                                       const SkScalar pos[], SkScalar constY,
@@ -345,9 +294,8 @@ void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai
     autoMatrix.setIdentity(fContext, &fPaint);
 
     const char*        stop = text + byteLength;
-    AlignProc          alignProc = pick_align_proc(fSkPaint.getTextAlign());
-    BitmapTextMapState       tms(ctm, constY);
-    BitmapTextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
+    SkTextAlignProc    alignProc(fSkPaint.getTextAlign());
+    SkTextMapStateProc tmsProc(ctm, constY, scalarsPerPosition);
     SkFixed halfSampleX = 0, halfSampleY = 0;
 
     if (cache->isSubpixel()) {
@@ -370,9 +318,10 @@ void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai
 
         if (SkPaint::kLeft_Align == fSkPaint.getTextAlign()) {
             while (text < stop) {
-                tmsProc(tms, pos);
-                SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + halfSampleX;
-                SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + halfSampleY;
+                SkPoint tmsLoc;
+                tmsProc(pos, &tmsLoc);
+                SkFixed fx = SkScalarToFixed(tmsLoc.fX) + halfSampleX;
+                SkFixed fy = SkScalarToFixed(tmsLoc.fY) + halfSampleY;
 
                 const SkGlyph& glyph = glyphCacheProc(cache, &text,
                                                       fx & fxMask, fy & fyMask);
@@ -395,10 +344,10 @@ void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai
                 if (metricGlyph.fWidth) {
                     SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
                     SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
-
-                    tmsProc(tms, pos);
+                    SkPoint tmsLoc;
+                    tmsProc(pos, &tmsLoc);
                     SkIPoint fixedLoc;
-                    alignProc(tms.fLoc, metricGlyph, &fixedLoc);
+                    alignProc(tmsLoc, metricGlyph, &fixedLoc);
 
                     SkFixed fx = fixedLoc.fX + halfSampleX;
                     SkFixed fy = fixedLoc.fY + halfSampleY;
@@ -429,10 +378,11 @@ void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai
                 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
 
                 if (glyph.fWidth) {
-                    tmsProc(tms, pos);
+                    SkPoint tmsLoc;
+                    tmsProc(pos, &tmsLoc);
 
-                    SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + SK_FixedHalf; //halfSampleX;
-                    SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + SK_FixedHalf; //halfSampleY;
+                    SkFixed fx = SkScalarToFixed(tmsLoc.fX) + SK_FixedHalf; //halfSampleX;
+                    SkFixed fy = SkScalarToFixed(tmsLoc.fY) + SK_FixedHalf; //halfSampleY;
                     this->drawPackedGlyph(GrGlyph::Pack(glyph.getGlyphID(),
                                                         glyph.getSubXFixed(),
                                                         glyph.getSubYFixed()),
@@ -448,10 +398,11 @@ void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai
                 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
 
                 if (glyph.fWidth) {
-                    tmsProc(tms, pos);
+                    SkPoint tmsLoc;
+                    tmsProc(pos, &tmsLoc);
 
                     SkIPoint fixedLoc;
-                    alignProc(tms.fLoc, glyph, &fixedLoc);
+                    alignProc(tmsLoc, glyph, &fixedLoc);
 
                     SkFixed fx = fixedLoc.fX + SK_FixedHalf; //halfSampleX;
                     SkFixed fy = fixedLoc.fY + SK_FixedHalf; //halfSampleY;
@@ -470,29 +421,15 @@ void GrBitmapTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPai
     this->finish();
 }
 
-namespace {
-
-// position + texture coord
-extern const GrVertexAttrib gTextVertexAttribs[] = {
-    {kVec2f_GrVertexAttribType, 0,               kPosition_GrVertexAttribBinding},
-    {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding}
-};
-
-};
-
 void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
-                                          GrFixed vx, GrFixed vy,
+                                          SkFixed vx, SkFixed vy,
                                           GrFontScaler* scaler) {
     if (NULL == fDrawTarget) {
         return;
     }
 
     if (NULL == fStrike) {
-#if SK_DISTANCEFIELD_FONTS
         fStrike = fContext->getFontCache()->getStrike(scaler, false);
-#else
-        fStrike = fContext->getFontCache()->getStrike(scaler);
-#endif
     }
 
     GrGlyph* glyph = fStrike->getGlyph(packed, scaler);
@@ -504,8 +441,8 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
     vy += SkIntToFixed(glyph->fBounds.fTop);
 
     // keep them as ints until we've done the clip-test
-    GrFixed width = glyph->fBounds.width();
-    GrFixed height = glyph->fBounds.height();
+    SkFixed width = glyph->fBounds.width();
+    SkFixed height = glyph->fBounds.height();
 
     // check if we clipped out
     if (true || NULL == glyph->fPlot) {
@@ -518,31 +455,32 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
     }
 
     if (NULL == glyph->fPlot) {
-        if (fStrike->getGlyphAtlas(glyph, scaler)) {
-            goto HAS_ATLAS;
-        }
+        if (!fStrike->glyphTooLargeForAtlas(glyph)) {
+            if (fStrike->addGlyphToAtlas(glyph, scaler)) {
+                goto HAS_ATLAS;
+            }
 
-        // try to clear out an unused plot before we flush
-        fContext->getFontCache()->freePlotExceptFor(fStrike);
-        if (fStrike->getGlyphAtlas(glyph, scaler)) {
-            goto HAS_ATLAS;
-        }
+            // try to clear out an unused plot before we flush
+            if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+                fStrike->addGlyphToAtlas(glyph, scaler)) {
+                goto HAS_ATLAS;
+            }
 
-        if (c_DumpFontCache) {
+            if (c_DumpFontCache) {
 #ifdef SK_DEVELOPER
-            fContext->getFontCache()->dump();
+                fContext->getFontCache()->dump();
 #endif
-        }
+            }
 
-        // before we purge the cache, we must flush any accumulated draws
-        this->flushGlyphs();
-        fContext->flush();
+            // flush any accumulated draws to allow us to free up a plot
+            this->flushGlyphs();
+            fContext->flush();
 
-        // try to purge
-        fContext->getFontCache()->purgeExceptFor(fStrike);
-        // need to use new flush count here
-        if (fStrike->getGlyphAtlas(glyph, scaler)) {
-            goto HAS_ATLAS;
+            // we should have an unused plot now
+            if (fContext->getFontCache()->freeUnusedPlot(fStrike) &&
+                fStrike->addGlyphToAtlas(glyph, scaler)) {
+                goto HAS_ATLAS;
+            }
         }
 
         if (NULL == glyph->fPath) {
@@ -561,8 +499,8 @@ void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed,
                                SkFixedToScalar(vy - SkIntToFixed(glyph->fBounds.fTop)));
         GrPaint tmpPaint(fPaint);
         am.setPreConcat(fContext, translate, &tmpPaint);
-        SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
-        fContext->drawPath(tmpPaint, *glyph->fPath, stroke);
+        GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
+        fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo);
         return;
     }
 
@@ -584,18 +522,30 @@ HAS_ATLAS:
         fCurrTexture->ref();
     }
 
+    bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat();
+
     if (NULL == fVertices) {
        // If we need to reserve vertices allow the draw target to suggest
         // a number of verts to reserve and whether to perform a flush.
         fMaxVertices = kMinRequestedVerts;
-        fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
-            SK_ARRAY_COUNT(gTextVertexAttribs));
+        if (useColorVerts) {
+            fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
+                SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize);
+        } else {
+            fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
+                SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
+        }
         bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL);
         if (flush) {
             this->flushGlyphs();
             fContext->flush();
-            fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
-                SK_ARRAY_COUNT(gTextVertexAttribs));
+            if (useColorVerts) {
+                fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
+                    SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize);
+            } else {
+                fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
+                    SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
+            }
         }
         fMaxVertices = kDefaultRequestedVerts;
         // ignore return, no point in flushing again.
@@ -610,14 +560,13 @@ HAS_ATLAS:
         }
         bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices,
                                                                0,
-                                                               GrTCast<void**>(&fVertices),
+                                                               &fVertices,
                                                                NULL);
         GrAlwaysAssert(success);
-        SkASSERT(2*sizeof(GrPoint) == fDrawTarget->getDrawState().getVertexSize());
     }
 
-    GrFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
-    GrFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY);
+    SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
+    SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY);
 
     SkRect r;
     r.fLeft = SkFixedToFloat(vx);
@@ -627,12 +576,33 @@ HAS_ATLAS:
 
     fVertexBounds.growToInclude(r);
 
-    fVertices[2*fCurrVertex].setRectFan(r.fLeft, r.fTop, r.fRight, r.fBottom,
-                                        2 * sizeof(SkPoint));
-    fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)),
-                                          SkFixedToFloat(texture->normalizeFixedY(ty)),
-                                          SkFixedToFloat(texture->normalizeFixedX(tx + width)),
-                                          SkFixedToFloat(texture->normalizeFixedY(ty + height)),
-                                          2 * sizeof(SkPoint));
+    size_t vertSize = useColorVerts ? (2 * sizeof(SkPoint) + sizeof(GrColor)) :
+                                      (2 * sizeof(SkPoint));
+
+    SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexStride());
+
+    SkPoint* positions = reinterpret_cast<SkPoint*>(
+        reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex);
+    positions->setRectFan(r.fLeft, r.fTop, r.fRight, r.fBottom, 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) + vertSize  - sizeof(SkPoint));
+    textureCoords->setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)),
+                              SkFixedToFloat(texture->normalizeFixedY(ty)),
+                              SkFixedToFloat(texture->normalizeFixedX(tx + width)),
+                              SkFixedToFloat(texture->normalizeFixedY(ty + height)),
+                              vertSize);
+    if (useColorVerts) {
+        if (0xFF == GrColorUnpackA(fPaint.getColor())) {
+            fDrawTarget->drawState()->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
+        }
+        // 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;
 }