/*
 * 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 "GrStencilAndCoverTextContext.h"
#include "GrAtlasTextContext.h"
#include "GrContext.h"
#include "GrPath.h"
#include "GrPathRange.h"
#include "GrRenderTargetContext.h"
#include "GrResourceProvider.h"
#include "GrTextUtils.h"
#include "SkAutoKern.h"
#include "SkDraw.h"
#include "SkDrawFilter.h"
#include "SkDrawProcs.h"
#include "SkGlyphCache.h"
#include "SkGr.h"
#include "SkPath.h"
#include "SkTextBlobRunIterator.h"
#include "SkTextFormatParams.h"
#include "SkTextMapStateProc.h"

#include "ops/GrDrawPathOp.h"

template<typename Key, typename Val> static void delete_hash_map_entry(const Key&, Val* val) {
    SkASSERT(*val);
    delete *val;
}

template<typename T> static void delete_hash_table_entry(T* val) {
    SkASSERT(*val);
    delete *val;
}

GrStencilAndCoverTextContext::GrStencilAndCoverTextContext(GrAtlasTextContext* fallbackTextContext)
    : fFallbackTextContext(fallbackTextContext)
    , fCacheSize(0) {
}

GrStencilAndCoverTextContext*
GrStencilAndCoverTextContext::Create(GrAtlasTextContext* fallbackTextContext) {
    return new GrStencilAndCoverTextContext(fallbackTextContext);;
}

GrStencilAndCoverTextContext::~GrStencilAndCoverTextContext() {
    fBlobIdCache.foreach(delete_hash_map_entry<uint32_t, TextBlob*>);
    fBlobKeyCache.foreach(delete_hash_table_entry<TextBlob*>);
}

bool GrStencilAndCoverTextContext::internalCanDraw(const SkPaint& skPaint) {
    if (skPaint.getRasterizer()) {
        return false;
    }
    if (skPaint.getMaskFilter()) {
        return false;
    }
    if (SkPathEffect* pe = skPaint.getPathEffect()) {
        if (pe->asADash(nullptr) != SkPathEffect::kDash_DashType) {
            return false;
        }
    }
    // No hairlines. They would require new paths with customized strokes for every new draw matrix.
    return SkPaint::kStroke_Style != skPaint.getStyle() || 0 != skPaint.getStrokeWidth();
}

void GrStencilAndCoverTextContext::drawText(GrContext* context, GrRenderTargetContext* rtc,
                                            const GrClip& clip, const SkPaint& skPaint,
                                            const SkMatrix& viewMatrix, const SkSurfaceProps& props,
                                            const char text[], size_t byteLength, SkScalar x,
                                            SkScalar y, const SkIRect& clipBounds) {
    if (context->abandoned()) {
        return;
    } else if (this->canDraw(skPaint, viewMatrix)) {
        if (skPaint.getTextSize() > 0) {
            TextRun run(skPaint);
            run.setText(text, byteLength, x, y);
            run.draw(context, rtc, clip, viewMatrix, props, 0, 0, clipBounds, fFallbackTextContext,
                     skPaint);
        }
        return;
    } else if (fFallbackTextContext->canDraw(skPaint, viewMatrix, props,
                                             *context->caps()->shaderCaps())) {
        fFallbackTextContext->drawText(context, rtc, clip, skPaint, viewMatrix, props, text,
                                       byteLength, x, y, clipBounds);
        return;
    }

    // fall back to drawing as a path
    GrTextUtils::DrawTextAsPath(context, rtc, clip, skPaint, viewMatrix, text, byteLength, x, y,
                                clipBounds);
}

void GrStencilAndCoverTextContext::drawPosText(GrContext* context, GrRenderTargetContext* rtc,
                                               const GrClip& clip, const SkPaint& skPaint,
                                               const SkMatrix& viewMatrix,
                                               const SkSurfaceProps& props, const char text[],
                                               size_t byteLength, const SkScalar pos[],
                                               int scalarsPerPosition, const SkPoint& offset,
                                               const SkIRect& clipBounds) {
    if (context->abandoned()) {
        return;
    } else if (this->canDraw(skPaint, viewMatrix)) {
        if (skPaint.getTextSize() > 0) {
            TextRun run(skPaint);
            run.setPosText(text, byteLength, pos, scalarsPerPosition, offset);
            run.draw(context, rtc, clip, viewMatrix, props, 0, 0, clipBounds, fFallbackTextContext,
                     skPaint);
        }
        return;
    } else if (fFallbackTextContext->canDraw(skPaint, viewMatrix, props,
                                             *context->caps()->shaderCaps())) {
        fFallbackTextContext->drawPosText(context, rtc, clip, skPaint, viewMatrix, props, text,
                                          byteLength, pos, scalarsPerPosition, offset, clipBounds);
        return;
    }

    // fall back to drawing as a path
    GrTextUtils::DrawPosTextAsPath(context, rtc, props, clip, skPaint, viewMatrix, text,
                                   byteLength, pos, scalarsPerPosition, offset, clipBounds);
}

void GrStencilAndCoverTextContext::uncachedDrawTextBlob(GrContext* context,
                                                        GrRenderTargetContext* rtc,
                                                        const GrClip& clip,
                                                        const SkPaint& skPaint,
                                                        const SkMatrix& viewMatrix,
                                                        const SkSurfaceProps& props,
                                                        const SkTextBlob* blob,
                                                        SkScalar x, SkScalar y,
                                                        SkDrawFilter* drawFilter,
                                                        const SkIRect& clipBounds) {
    GrTextUtils::Paint paint(&skPaint, rtc->getColorSpace(), rtc->getColorXformFromSRGB());
    GrTextUtils::RunPaint runPaint(&paint, drawFilter, props);
    SkTextBlobRunIterator it(blob);
    for (;!it.done(); it.next()) {
        if (!runPaint.modifyForRun(it)) {
            continue;
        }
        size_t textLen = it.glyphCount() * sizeof(uint16_t);
        const SkPoint& offset = it.offset();

        switch (it.positioning()) {
            case SkTextBlob::kDefault_Positioning:
                this->drawText(context, rtc, clip, runPaint, viewMatrix, props,
                               (const char*)it.glyphs(), textLen, x + offset.x(), y + offset.y(),
                               clipBounds);
                break;
            case SkTextBlob::kHorizontal_Positioning:
                this->drawPosText(context, rtc, clip, runPaint, viewMatrix, props,
                                  (const char*)it.glyphs(), textLen, it.pos(), 1,
                                  SkPoint::Make(x, y + offset.y()), clipBounds);
                break;
            case SkTextBlob::kFull_Positioning:
                this->drawPosText(context, rtc, clip, runPaint, viewMatrix, props,
                                  (const char*)it.glyphs(), textLen, it.pos(), 2,
                                  SkPoint::Make(x, y), clipBounds);
                break;
        }
    }
}

void GrStencilAndCoverTextContext::drawTextBlob(GrContext* context, GrRenderTargetContext* rtc,
                                                const GrClip& clip, const SkPaint& skPaint,
                                                const SkMatrix& viewMatrix,
                                                const SkSurfaceProps& props,
                                                const SkTextBlob* skBlob, SkScalar x, SkScalar y,
                                                SkDrawFilter* drawFilter,
                                                const SkIRect& clipBounds) {
    if (context->abandoned()) {
        return;
    }

    if (!this->internalCanDraw(skPaint)) {
        fFallbackTextContext->drawTextBlob(context, rtc, clip, skPaint, viewMatrix, props, skBlob,
                                           x, y, drawFilter, clipBounds);
        return;
    }

    if (drawFilter || skPaint.getPathEffect()) {
        // This draw can't be cached.
        this->uncachedDrawTextBlob(context, rtc, clip, skPaint, viewMatrix, props, skBlob, x, y,
                                   drawFilter, clipBounds);
        return;
    }

    const TextBlob& blob = this->findOrCreateTextBlob(skBlob, skPaint);

    TextBlob::Iter iter(blob);
    for (TextRun *run = iter.get(), *nextRun; run; run = nextRun) {
        nextRun = iter.next();
        run->draw(context, rtc, clip, viewMatrix, props, x, y, clipBounds, fFallbackTextContext,
                  skPaint);
        run->releaseGlyphCache();
    }
}

static inline int style_key_cnt(const GrStyle& style) {
    int cnt = GrStyle::KeySize(style, GrStyle::Apply::kPathEffectAndStrokeRec);
    // We should be able to make a key because we filtered out arbitrary path effects.
    SkASSERT(cnt > 0);
    return cnt;
}

static inline void write_style_key(uint32_t* dst, const GrStyle& style) {
    // Pass 1 for the scale since the GPU will apply the style not GrStyle::applyToPath().
    GrStyle::WriteKey(dst, style, GrStyle::Apply::kPathEffectAndStrokeRec, SK_Scalar1);
}

const GrStencilAndCoverTextContext::TextBlob&
GrStencilAndCoverTextContext::findOrCreateTextBlob(const SkTextBlob* skBlob,
                                                   const SkPaint& skPaint) {
    // The font-related parameters are baked into the text blob and will override this skPaint, so
    // the only remaining properties that can affect a TextBlob are the ones related to stroke.
    if (SkPaint::kFill_Style == skPaint.getStyle()) { // Fast path.
        if (TextBlob** found = fBlobIdCache.find(skBlob->uniqueID())) {
            fLRUList.remove(*found);
            fLRUList.addToTail(*found);
            return **found;
        }
        TextBlob* blob = new TextBlob(skBlob->uniqueID(), skBlob, skPaint);
        this->purgeToFit(*blob);
        fBlobIdCache.set(skBlob->uniqueID(), blob);
        fLRUList.addToTail(blob);
        fCacheSize += blob->cpuMemorySize();
        return *blob;
    } else {
        GrStyle style(skPaint);
        SkSTArray<4, uint32_t, true> key;
        key.reset(1 + style_key_cnt(style));
        key[0] = skBlob->uniqueID();
        write_style_key(&key[1], style);
        if (TextBlob** found = fBlobKeyCache.find(key)) {
            fLRUList.remove(*found);
            fLRUList.addToTail(*found);
            return **found;
        }
        TextBlob* blob = new TextBlob(key, skBlob, skPaint);
        this->purgeToFit(*blob);
        fBlobKeyCache.set(blob);
        fLRUList.addToTail(blob);
        fCacheSize += blob->cpuMemorySize();
        return *blob;
    }
}

void GrStencilAndCoverTextContext::purgeToFit(const TextBlob& blob) {
    static const size_t maxCacheSize = 4 * 1024 * 1024; // Allow up to 4 MB for caching text blobs.

    size_t maxSizeForNewBlob = maxCacheSize - blob.cpuMemorySize();
    while (fCacheSize && fCacheSize > maxSizeForNewBlob) {
        TextBlob* lru = fLRUList.head();
        if (1 == lru->key().count()) {
            // 1-length keys are unterstood to be the blob id.
            fBlobIdCache.remove(lru->key()[0]);
        } else {
            fBlobKeyCache.remove(lru->key());
        }
        fLRUList.remove(lru);
        fCacheSize -= lru->cpuMemorySize();
        delete lru;
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void GrStencilAndCoverTextContext::TextBlob::init(const SkTextBlob* skBlob,
                                                  const SkPaint& skPaint) {
    fCpuMemorySize = sizeof(TextBlob);
    SkPaint runPaint(skPaint);
    for (SkTextBlobRunIterator iter(skBlob); !iter.done(); iter.next()) {
        iter.applyFontToPaint(&runPaint); // No need to re-seed the paint.
        if (runPaint.getTextSize() <= 0) {
            continue;
        }
        TextRun* run = this->addToTail(runPaint);

        const char* text = reinterpret_cast<const char*>(iter.glyphs());
        size_t byteLength = sizeof(uint16_t) * iter.glyphCount();
        const SkPoint& runOffset = iter.offset();

        switch (iter.positioning()) {
            case SkTextBlob::kDefault_Positioning:
                run->setText(text, byteLength, runOffset.fX, runOffset.fY);
                break;
            case SkTextBlob::kHorizontal_Positioning:
                run->setPosText(text, byteLength, iter.pos(), 1, SkPoint::Make(0, runOffset.fY));
                break;
            case SkTextBlob::kFull_Positioning:
                run->setPosText(text, byteLength, iter.pos(), 2, SkPoint::Make(0, 0));
                break;
        }

        fCpuMemorySize += run->computeSizeInCache();
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////

class GrStencilAndCoverTextContext::FallbackBlobBuilder {
public:
    FallbackBlobBuilder() : fBuffIdx(0), fCount(0) {}

    bool isInitialized() const { return fBuilder != nullptr; }

    void init(const SkPaint& font, SkScalar textRatio);

    void appendGlyph(uint16_t glyphId, const SkPoint& pos);

    sk_sp<SkTextBlob> makeIfNeeded(int* count);

private:
    enum { kWriteBufferSize = 1024 };

    void flush();

    std::unique_ptr<SkTextBlobBuilder> fBuilder;
    SkPaint                            fFont;
    int                                fBuffIdx;
    int                                fCount;
    uint16_t                           fGlyphIds[kWriteBufferSize];
    SkPoint                            fPositions[kWriteBufferSize];
};

////////////////////////////////////////////////////////////////////////////////////////////////////

GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke)
    : fStyle(fontAndStroke)
    , fFont(fontAndStroke)
    , fTotalGlyphCount(0)
    , fFallbackGlyphCount(0)
    , fDetachedGlyphCache(nullptr)
    , fLastDrawnGlyphsID(SK_InvalidUniqueID) {
    SkASSERT(fFont.getTextSize() > 0);
    SkASSERT(!fStyle.hasNonDashPathEffect()); // Arbitrary path effects not supported.
    SkASSERT(!fStyle.isSimpleHairline()); // Hairlines are not supported.

    // Setting to "fill" ensures that no strokes get baked into font outlines. (We use the GPU path
    // rendering API for stroking).
    fFont.setStyle(SkPaint::kFill_Style);

    if (fFont.isFakeBoldText() && fStyle.isSimpleFill()) {
        const SkStrokeRec& stroke = fStyle.strokeRec();
        // Instead of letting fake bold get baked into the glyph outlines, do it with GPU stroke.
        SkScalar fakeBoldScale = SkScalarInterpFunc(fFont.getTextSize(),
                                                    kStdFakeBoldInterpKeys,
                                                    kStdFakeBoldInterpValues,
                                                    kStdFakeBoldInterpLength);
        SkScalar extra = fFont.getTextSize() * fakeBoldScale;

        SkStrokeRec strokeRec(SkStrokeRec::kFill_InitStyle);
        strokeRec.setStrokeStyle(stroke.needToApply() ? stroke.getWidth() + extra : extra,
                                 true /*strokeAndFill*/);
        fStyle = GrStyle(strokeRec, fStyle.refPathEffect());
        fFont.setFakeBoldText(false);
    }

    if (!fFont.getPathEffect() && !fStyle.isDashed()) {
        const SkStrokeRec& stroke = fStyle.strokeRec();
        // We can draw the glyphs from canonically sized paths.
        fTextRatio = fFont.getTextSize() / SkPaint::kCanonicalTextSizeForPaths;
        fTextInverseRatio = SkPaint::kCanonicalTextSizeForPaths / fFont.getTextSize();

        // Compensate for the glyphs being scaled by fTextRatio.
        if (!fStyle.isSimpleFill()) {
            SkStrokeRec strokeRec(SkStrokeRec::kFill_InitStyle);
            strokeRec.setStrokeStyle(stroke.getWidth() / fTextRatio,
                                     SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle());
            fStyle = GrStyle(strokeRec, fStyle.refPathEffect());
        }

        fFont.setLinearText(true);
        fFont.setLCDRenderText(false);
        fFont.setAutohinted(false);
        fFont.setHinting(SkPaint::kNo_Hinting);
        fFont.setSubpixelText(true);
        fFont.setTextSize(SkIntToScalar(SkPaint::kCanonicalTextSizeForPaths));

        fUsingRawGlyphPaths = SK_Scalar1 == fFont.getTextScaleX() &&
                              0 == fFont.getTextSkewX() &&
                              !fFont.isFakeBoldText() &&
                              !fFont.isVerticalText();
    } else {
        fTextRatio = fTextInverseRatio = 1.0f;
        fUsingRawGlyphPaths = false;
    }

    // Generate the key that will be used to cache the GPU glyph path objects.
    if (fUsingRawGlyphPaths && fStyle.isSimpleFill()) {
        static const GrUniqueKey::Domain kRawFillPathGlyphDomain = GrUniqueKey::GenerateDomain();

        const SkTypeface* typeface = fFont.getTypeface();
        GrUniqueKey::Builder builder(&fGlyphPathsKey, kRawFillPathGlyphDomain, 1);
        reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqueID() : 0;
    } else {
        static const GrUniqueKey::Domain kPathGlyphDomain = GrUniqueKey::GenerateDomain();

        int styleDataCount = GrStyle::KeySize(fStyle, GrStyle::Apply::kPathEffectAndStrokeRec);
        // Key should be valid since we opted out of drawing arbitrary path effects.
        SkASSERT(styleDataCount >= 0);
        if (fUsingRawGlyphPaths) {
            const SkTypeface* typeface = fFont.getTypeface();
            GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain, 2 + styleDataCount);
            reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqueID() : 0;
            reinterpret_cast<uint32_t&>(builder[1]) = styleDataCount;
            if (styleDataCount) {
                write_style_key(&builder[2], fStyle);
            }
        } else {
            SkGlyphCache* glyphCache = this->getGlyphCache();
            const SkTypeface* typeface = glyphCache->getScalerContext()->getTypeface();
            const SkDescriptor* desc = &glyphCache->getDescriptor();
            int descDataCount = (desc->getLength() + 3) / 4;
            GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain,
                                         2 + styleDataCount + descDataCount);
            reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqueID() : 0;
            reinterpret_cast<uint32_t&>(builder[1]) = styleDataCount | (descDataCount << 16);
            if (styleDataCount) {
                write_style_key(&builder[2], fStyle);
            }
            memcpy(&builder[2 + styleDataCount], desc, desc->getLength());
        }
    }
}

GrStencilAndCoverTextContext::TextRun::~TextRun() {
    this->releaseGlyphCache();
}

void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t byteLength,
                                                    SkScalar x, SkScalar y) {
    SkASSERT(byteLength == 0 || text != nullptr);

    SkGlyphCache* glyphCache = this->getGlyphCache();
    SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(fFont.getTextEncoding(),
                                                                        fFont.isDevKernText(),
                                                                        true);

    fTotalGlyphCount = fFont.countText(text, byteLength);
    fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTransformType,
                                            fTotalGlyphCount));

    const char* stop = text + byteLength;

    // Measure first if needed.
    if (fFont.getTextAlign() != SkPaint::kLeft_Align) {
        SkScalar   stopX = 0;
        SkScalar   stopY = 0;

        const char* textPtr = text;
        while (textPtr < stop) {
            // We don't need x, y here, since all subpixel variants will have the
            // same advance.
            const SkGlyph& glyph = glyphCacheProc(glyphCache, &textPtr);

            stopX += SkFloatToScalar(glyph.fAdvanceX);
            stopY += SkFloatToScalar(glyph.fAdvanceY);
        }
        SkASSERT(textPtr == stop);

        SkScalar alignX = stopX * fTextRatio;
        SkScalar alignY = stopY * fTextRatio;

        if (fFont.getTextAlign() == SkPaint::kCenter_Align) {
            alignX = SkScalarHalf(alignX);
            alignY = SkScalarHalf(alignY);
        }

        x -= alignX;
        y -= alignY;
    }

    SkAutoKern autokern;

    FallbackBlobBuilder fallback;
    while (text < stop) {
        const SkGlyph& glyph = glyphCacheProc(glyphCache, &text);
        x += autokern.adjust(glyph) * fTextRatio;
        if (glyph.fWidth) {
            this->appendGlyph(glyph, SkPoint::Make(x, y), &fallback);
        }

        x += SkFloatToScalar(glyph.fAdvanceX) * fTextRatio;
        y += SkFloatToScalar(glyph.fAdvanceY) * fTextRatio;
    }

    fFallbackTextBlob = fallback.makeIfNeeded(&fFallbackGlyphCount);
}

void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t byteLength,
                                                       const SkScalar pos[], int scalarsPerPosition,
                                                       const SkPoint& offset) {
    SkASSERT(byteLength == 0 || text != nullptr);
    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);

    SkGlyphCache* glyphCache = this->getGlyphCache();
    SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(fFont.getTextEncoding(),
                                                                        fFont.isDevKernText(),
                                                                        true);

    fTotalGlyphCount = fFont.countText(text, byteLength);
    fInstanceData.reset(InstanceData::Alloc(GrPathRendering::kTranslate_PathTransformType,
                                            fTotalGlyphCount));

    const char* stop = text + byteLength;

    SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition);
    SkTextAlignProc alignProc(fFont.getTextAlign());
    FallbackBlobBuilder fallback;
    while (text < stop) {
        const SkGlyph& glyph = glyphCacheProc(glyphCache, &text);
        if (glyph.fWidth) {
            SkPoint tmsLoc;
            tmsProc(pos, &tmsLoc);
            SkPoint loc;
            alignProc(tmsLoc, glyph, &loc);

            this->appendGlyph(glyph, loc, &fallback);
        }
        pos += scalarsPerPosition;
    }

    fFallbackTextBlob = fallback.makeIfNeeded(&fFallbackGlyphCount);
}

sk_sp<GrPathRange> GrStencilAndCoverTextContext::TextRun::createGlyphs(
                                                    GrResourceProvider* resourceProvider) const {
    sk_sp<GrPathRange> glyphs;

    glyphs.reset(static_cast<GrPathRange*>(
            resourceProvider->findAndRefResourceByUniqueKey(fGlyphPathsKey)));
    if (!glyphs) {
        if (fUsingRawGlyphPaths) {
            SkScalerContextEffects noeffects;
            glyphs = resourceProvider->createGlyphs(fFont.getTypeface(), noeffects,
                                                    nullptr, fStyle);
        } else {
            SkGlyphCache* cache = this->getGlyphCache();
            glyphs = resourceProvider->createGlyphs(cache->getScalerContext()->getTypeface(),
                                                    cache->getScalerContext()->getEffects(),
                                                    &cache->getDescriptor(),
                                                    fStyle);
        }
        resourceProvider->assignUniqueKeyToResource(fGlyphPathsKey, glyphs.get());
    }
    return glyphs;
}

inline void GrStencilAndCoverTextContext::TextRun::appendGlyph(const SkGlyph& glyph,
                                                               const SkPoint& pos,
                                                               FallbackBlobBuilder* fallback) {
    // Stick the glyphs we can't draw into the fallback text blob.
    if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
        if (!fallback->isInitialized()) {
            fallback->init(fFont, fTextRatio);
        }
        fallback->appendGlyph(glyph.getGlyphID(), pos);
    } else {
        fInstanceData->append(glyph.getGlyphID(), fTextInverseRatio * pos.x(),
                              fTextInverseRatio * pos.y());
    }
}

void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx,
                                                 GrRenderTargetContext* renderTargetContext,
                                                 const GrClip& clip, const SkMatrix& viewMatrix,
                                                 const SkSurfaceProps& props, SkScalar x,
                                                 SkScalar y, const SkIRect& clipBounds,
                                                 GrAtlasTextContext* fallbackTextContext,
                                                 const SkPaint& originalSkPaint) const {
    SkASSERT(fInstanceData);

    if (fInstanceData->count()) {
        static constexpr GrUserStencilSettings kCoverPass(
            GrUserStencilSettings::StaticInit<
                0x0000,
                GrUserStencilTest::kNotEqual, // Stencil pass accounts for clip.
                0xffff,
                GrUserStencilOp::kZero,
                GrUserStencilOp::kKeep,
                0xffff>()
        );

        sk_sp<GrPathRange> glyphs(this->createGlyphs(ctx->resourceProvider()));
        if (fLastDrawnGlyphsID != glyphs->uniqueID()) {
            // Either this is the first draw or the glyphs object was purged since last draw.
            glyphs->loadPathsIfNeeded(fInstanceData->indices(), fInstanceData->count());
            fLastDrawnGlyphsID = glyphs->uniqueID();
        }

        GrPaint grPaint;
        if (!SkPaintToGrPaint(ctx, renderTargetContext, originalSkPaint, viewMatrix, &grPaint)) {
            return;
        }

        // 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.
        // For clipping we'll just skip any optimizations based on the bounds. This does, however,
        // hurt GrOp combining.
        const SkRect bounds = SkRect::MakeIWH(renderTargetContext->width(),
                                              renderTargetContext->height());

        // The run's "font" overrides the anti-aliasing of the passed in SkPaint!
        GrAAType aaType = GrChooseAAType(this->aa(), renderTargetContext->fsaaType(),
                                         GrAllowMixedSamples::kYes, *renderTargetContext->caps());

        std::unique_ptr<GrDrawOp> op = GrDrawPathRangeOp::Make(
                viewMatrix, fTextRatio, fTextInverseRatio * x, fTextInverseRatio * y,
                std::move(grPaint), GrPathRendering::kWinding_FillType, aaType, glyphs.get(),
                fInstanceData.get(), bounds);

        renderTargetContext->addDrawOp(clip, std::move(op));
    }

    if (fFallbackTextBlob) {
        SkPaint fallbackSkPaint(originalSkPaint);
        fStyle.strokeRec().applyToPaint(&fallbackSkPaint);
        if (!fStyle.isSimpleFill()) {
            fallbackSkPaint.setStrokeWidth(fStyle.strokeRec().getWidth() * fTextRatio);
        }

        fallbackTextContext->drawTextBlob(ctx, renderTargetContext, clip, fallbackSkPaint,
                                          viewMatrix, props, fFallbackTextBlob.get(), x, y, nullptr,
                                          clipBounds);
    }
}

SkGlyphCache* GrStencilAndCoverTextContext::TextRun::getGlyphCache() const {
    if (!fDetachedGlyphCache) {
        fDetachedGlyphCache = fFont.detachCache(nullptr, SkPaint::kNone_ScalerContextFlags,
                                                nullptr);
    }
    return fDetachedGlyphCache;
}


void GrStencilAndCoverTextContext::TextRun::releaseGlyphCache() const {
    if (fDetachedGlyphCache) {
        SkGlyphCache::AttachCache(fDetachedGlyphCache);
        fDetachedGlyphCache = nullptr;
    }
}

size_t GrStencilAndCoverTextContext::TextRun::computeSizeInCache() const {
    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);
    }
    return size;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

void GrStencilAndCoverTextContext::FallbackBlobBuilder::init(const SkPaint& font,
                                                             SkScalar textRatio) {
    SkASSERT(!this->isInitialized());
    fBuilder.reset(new SkTextBlobBuilder);
    fFont = font;
    fFont.setTextAlign(SkPaint::kLeft_Align); // The glyph positions will already account for align.
    fFont.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    // No need for subpixel positioning with bitmap glyphs. TODO: revisit if non-bitmap color glyphs
    // show up and https://code.google.com/p/skia/issues/detail?id=4408 gets resolved.
    fFont.setSubpixelText(false);
    fFont.setTextSize(fFont.getTextSize() * textRatio);
    fBuffIdx = 0;
}

void GrStencilAndCoverTextContext::FallbackBlobBuilder::appendGlyph(uint16_t glyphId,
                                                                    const SkPoint& pos) {
    SkASSERT(this->isInitialized());
    if (fBuffIdx >= kWriteBufferSize) {
        this->flush();
    }
    fGlyphIds[fBuffIdx] = glyphId;
    fPositions[fBuffIdx] = pos;
    fBuffIdx++;
    fCount++;
}

void GrStencilAndCoverTextContext::FallbackBlobBuilder::flush() {
    SkASSERT(this->isInitialized());
    SkASSERT(fBuffIdx <= kWriteBufferSize);
    if (!fBuffIdx) {
        return;
    }
    // This will automatically merge with previous runs since we use the same font.
    const SkTextBlobBuilder::RunBuffer& buff = fBuilder->allocRunPos(fFont, fBuffIdx);
    memcpy(buff.glyphs, fGlyphIds, fBuffIdx * sizeof(uint16_t));
    memcpy(buff.pos, fPositions[0].asScalars(), fBuffIdx * 2 * sizeof(SkScalar));
    fBuffIdx = 0;
}

sk_sp<SkTextBlob> GrStencilAndCoverTextContext::FallbackBlobBuilder::makeIfNeeded(int *count) {
    *count = fCount;
    if (fCount) {
        this->flush();
        return fBuilder->make();
    }
    return nullptr;
}
