| Index: src/gpu/GrStencilAndCoverTextContext.cpp | 
| diff --git a/src/gpu/GrStencilAndCoverTextContext.cpp b/src/gpu/GrStencilAndCoverTextContext.cpp | 
| index 77960dbe7a8f6ec8beeee92e3840ec040369d92d..d28f1a803a0abe7df26843e7848fd21821d8b4f5 100644 | 
| --- a/src/gpu/GrStencilAndCoverTextContext.cpp | 
| +++ b/src/gpu/GrStencilAndCoverTextContext.cpp | 
| @@ -233,7 +233,7 @@ void GrStencilAndCoverTextContext::TextBlob::init(const SkTextBlob* skBlob, | 
|  | 
| class GrStencilAndCoverTextContext::FallbackBlobBuilder { | 
| public: | 
| -    FallbackBlobBuilder() : fBuffIdx(0) {} | 
| +    FallbackBlobBuilder() : fBuffIdx(0), fCount(0) {} | 
|  | 
| bool isInitialized() const { return SkToBool(fBuilder); } | 
|  | 
| @@ -241,7 +241,7 @@ public: | 
|  | 
| void appendGlyph(uint16_t glyphId, const SkPoint& pos); | 
|  | 
| -    const SkTextBlob* buildIfInitialized(); | 
| +    const SkTextBlob* buildIfNeeded(int* count); | 
|  | 
| private: | 
| enum { kWriteBufferSize = 1024 }; | 
| @@ -251,6 +251,7 @@ private: | 
| SkAutoTDelete<SkTextBlobBuilder>   fBuilder; | 
| SkPaint                            fFont; | 
| int                                fBuffIdx; | 
| +    int                                fCount; | 
| uint16_t                           fGlyphIds[kWriteBufferSize]; | 
| SkPoint                            fPositions[kWriteBufferSize]; | 
| }; | 
| @@ -261,6 +262,7 @@ GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke) | 
| : fStroke(fontAndStroke), | 
| fFont(fontAndStroke), | 
| fTotalGlyphCount(0), | 
| +      fFallbackGlyphCount(0), | 
| fDetachedGlyphCache(nullptr), | 
| fLastDrawnGlyphsID(SK_InvalidUniqueID) { | 
| SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported. | 
| @@ -339,9 +341,6 @@ GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke) | 
| memcpy(&builder[2 + strokeDataCount], desc, desc->getLength()); | 
| } | 
| } | 
| - | 
| -    // When drawing from canonically sized paths, the actual local coords are fTextRatio * coords. | 
| -    fLocalMatrixTemplate.setScale(fTextRatio, fTextRatio); | 
| } | 
|  | 
| GrStencilAndCoverTextContext::TextRun::~TextRun() { | 
| @@ -355,8 +354,9 @@ void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t by | 
| SkGlyphCache* glyphCache = this->getGlyphCache(); | 
| SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc(); | 
|  | 
| -    fDraw.reset(GrPathRangeDraw::Create(GrPathRendering::kTranslate_PathTransformType, | 
| -                                        fTotalGlyphCount = fFont.countText(text, byteLength))); | 
| +    fTotalGlyphCount = fFont.countText(text, byteLength); | 
| +    fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTransformType, | 
| +                                            fTotalGlyphCount)); | 
|  | 
| const char* stop = text + byteLength; | 
|  | 
| @@ -407,7 +407,7 @@ void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t by | 
| fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio); | 
| } | 
|  | 
| -    fFallbackTextBlob.reset(fallback.buildIfInitialized()); | 
| +    fFallbackTextBlob.reset(fallback.buildIfNeeded(&fFallbackGlyphCount)); | 
| } | 
|  | 
| void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t byteLength, | 
| @@ -419,8 +419,9 @@ void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t | 
| SkGlyphCache* glyphCache = this->getGlyphCache(); | 
| SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc(); | 
|  | 
| -    fDraw.reset(GrPathRangeDraw::Create(GrPathRendering::kTranslate_PathTransformType, | 
| -                                        fTotalGlyphCount = fFont.countText(text, byteLength))); | 
| +    fTotalGlyphCount = fFont.countText(text, byteLength); | 
| +    fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTransformType, | 
| +                                            fTotalGlyphCount)); | 
|  | 
| const char* stop = text + byteLength; | 
|  | 
| @@ -440,7 +441,7 @@ void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t | 
| pos += scalarsPerPosition; | 
| } | 
|  | 
| -    fFallbackTextBlob.reset(fallback.buildIfInitialized()); | 
| +    fFallbackTextBlob.reset(fallback.buildIfNeeded(&fFallbackGlyphCount)); | 
| } | 
|  | 
| GrPathRange* GrStencilAndCoverTextContext::TextRun::createGlyphs(GrContext* ctx) const { | 
| @@ -470,8 +471,8 @@ inline void GrStencilAndCoverTextContext::TextRun::appendGlyph(const SkGlyph& gl | 
| } | 
| fallback->appendGlyph(glyph.getGlyphID(), pos); | 
| } else { | 
| -        float translate[] = { fTextInverseRatio * pos.x(), fTextInverseRatio * pos.y() }; | 
| -        fDraw->append(glyph.getGlyphID(), translate); | 
| +        fInstanceData->append(glyph.getGlyphID(), fTextInverseRatio * pos.x(), | 
| +                              fTextInverseRatio * pos.y()); | 
| } | 
| } | 
|  | 
| @@ -484,10 +485,10 @@ void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx, | 
| const SkIRect& clipBounds, | 
| GrTextContext* fallbackTextContext, | 
| const SkPaint& originalSkPaint) const { | 
| -    SkASSERT(fDraw); | 
| +    SkASSERT(fInstanceData); | 
| SkASSERT(dc->accessRenderTarget()->isStencilBufferMultisampled() || !fFont.isAntiAlias()); | 
|  | 
| -    if (fDraw->count()) { | 
| +    if (fInstanceData->count()) { | 
| pipelineBuilder->setState(GrPipelineBuilder::kHWAntialias_Flag, fFont.isAntiAlias()); | 
|  | 
| GR_STATIC_CONST_SAME_STENCIL(kStencilPass, | 
| @@ -503,18 +504,10 @@ void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx, | 
| SkAutoTUnref<GrPathRange> glyphs(this->createGlyphs(ctx)); | 
| if (fLastDrawnGlyphsID != glyphs->getUniqueID()) { | 
| // Either this is the first draw or the glyphs object was purged since last draw. | 
| -            glyphs->loadPathsIfNeeded(fDraw->indices(), fDraw->count()); | 
| +            glyphs->loadPathsIfNeeded(fInstanceData->indices(), fInstanceData->count()); | 
| fLastDrawnGlyphsID = glyphs->getUniqueID(); | 
| } | 
|  | 
| -        SkMatrix drawMatrix(viewMatrix); | 
| -        drawMatrix.preTranslate(x, y); | 
| -        drawMatrix.preScale(fTextRatio, fTextRatio); | 
| - | 
| -        SkMatrix& localMatrix = fLocalMatrixTemplate; | 
| -        localMatrix.setTranslateX(x); | 
| -        localMatrix.setTranslateY(y); | 
| - | 
| // Don't compute a bounding box. For dst copy texture, we'll opt instead for it to just copy | 
| // the entire dst. Realistically this is a moot point, because any context that supports | 
| // NV_path_rendering will also support NV_blend_equation_advanced. | 
| @@ -524,8 +517,9 @@ void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx, | 
| pipelineBuilder->getRenderTarget()->height()); | 
|  | 
| SkAutoTUnref<GrDrawPathBatchBase> batch( | 
| -            GrDrawPathRangeBatch::Create(drawMatrix, localMatrix, color, | 
| -                                         GrPathRendering::kWinding_FillType, glyphs, fDraw, | 
| +            GrDrawPathRangeBatch::Create(viewMatrix, fTextRatio, fTextInverseRatio * x, | 
| +                                         fTextInverseRatio * y, color, | 
| +                                         GrPathRendering::kWinding_FillType, glyphs, fInstanceData, | 
| bounds)); | 
|  | 
| dc->drawPathBatch(*pipelineBuilder, batch); | 
| @@ -559,11 +553,11 @@ void GrStencilAndCoverTextContext::TextRun::releaseGlyphCache() const { | 
| } | 
|  | 
| size_t GrStencilAndCoverTextContext::TextRun::computeSizeInCache() const { | 
| -    size_t size = sizeof(TextRun) + | 
| -               fGlyphPathsKey.size() + | 
| -               fTotalGlyphCount * (sizeof(uint16_t) + 2 * sizeof(float)); | 
| -    if (fDraw) { | 
| -        size += sizeof(GrPathRangeDraw); | 
| +    size_t size = sizeof(TextRun) + fGlyphPathsKey.size(); | 
| +    // The instance data always reserves enough space for every glyph. | 
| +    size += (fTotalGlyphCount + fFallbackGlyphCount) * (sizeof(uint16_t) + 2 * sizeof(float)); | 
| +    if (fInstanceData) { | 
| +        size += sizeof(InstanceData); | 
| } | 
| if (fFallbackTextBlob) { | 
| size += sizeof(SkTextBlob); | 
| @@ -596,6 +590,7 @@ void GrStencilAndCoverTextContext::FallbackBlobBuilder::appendGlyph(uint16_t gly | 
| fGlyphIds[fBuffIdx] = glyphId; | 
| fPositions[fBuffIdx] = pos; | 
| fBuffIdx++; | 
| +    fCount++; | 
| } | 
|  | 
| void GrStencilAndCoverTextContext::FallbackBlobBuilder::flush() { | 
| @@ -611,10 +606,11 @@ void GrStencilAndCoverTextContext::FallbackBlobBuilder::flush() { | 
| fBuffIdx = 0; | 
| } | 
|  | 
| -const SkTextBlob* GrStencilAndCoverTextContext::FallbackBlobBuilder::buildIfInitialized() { | 
| -    if (!this->isInitialized()) { | 
| -        return nullptr; | 
| +const SkTextBlob* GrStencilAndCoverTextContext::FallbackBlobBuilder::buildIfNeeded(int *count) { | 
| +    *count = fCount; | 
| +    if (fCount) { | 
| +        this->flush(); | 
| +        return fBuilder->build(); | 
| } | 
| -    this->flush(); | 
| -    return fBuilder->build(); | 
| +    return nullptr; | 
| } | 
|  |