/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrTextBlob_DEFINED
#define GrTextBlob_DEFINED

#include "include/core/SkPathEffect.h"
#include "include/core/SkPoint3.h"
#include "include/core/SkSurfaceProps.h"
#include "src/core/SkDescriptor.h"
#include "src/core/SkMaskFilterBase.h"
#include "src/core/SkOpts.h"
#include "src/core/SkRectPriv.h"
#include "src/core/SkStrikeCache.h"
#include "src/core/SkStrikeSpec.h"
#include "src/core/SkTInternalLList.h"
#include "src/gpu/GrColor.h"
#include "src/gpu/GrDrawOpAtlas.h"
#include "src/gpu/text/GrStrikeCache.h"
#include "src/gpu/text/GrTextContext.h"
#include "src/gpu/text/GrTextTarget.h"

class GrAtlasManager;
struct GrDistanceFieldAdjustTable;
struct GrGlyph;

class SkTextBlob;
class SkTextBlobRunIterator;

// With this flag enabled, the GrTextContext will, as a sanity check, regenerate every blob
// that comes in to verify the integrity of its cache
#define CACHE_SANITY_CHECK 0

/*
 * A GrTextBlob contains a fully processed SkTextBlob, suitable for nearly immediate drawing
 * on the GPU.  These are initially created with valid positions and colors, but invalid
 * texture coordinates.  The GrTextBlob itself has a few Blob-wide properties, and also
 * consists of a number of runs.  Runs inside a blob are flushed individually so they can be
 * reordered.
 *
 * The only thing(aside from a memcopy) required to flush a GrTextBlob is to ensure that
 * the GrAtlas will not evict anything the Blob needs.
 *
 * Note: This struct should really be named GrCachedAtasTextBlob, but that is too verbose.
 *
 * *WARNING* If you add new fields to this struct, then you may need to to update AssertEqual
 */
class GrTextBlob : public SkNVRefCnt<GrTextBlob>, public SkGlyphRunPainterInterface {
    struct Run;
public:
    SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrTextBlob);

    class VertexRegenerator;

    void generateFromGlyphRunList(const GrShaderCaps& shaderCaps,
                                  const GrTextContext::Options& options,
                                  const SkPaint& paint,
                                  SkScalerContextFlags scalerContextFlags,
                                  const SkMatrix& viewMatrix,
                                  const SkSurfaceProps& props,
                                  const SkGlyphRunList& glyphRunList,
                                  SkGlyphRunListPainter* glyphPainter);

    static sk_sp<GrTextBlob> Make(
            int glyphCount,
            int runCount,
            GrColor color,
            GrStrikeCache* strikeCache);

    /**
     * We currently force regeneration of a blob if old or new matrix differ in having perspective.
     * If we ever change that then the key must contain the perspectiveness when there are distance
     * fields as perspective distance field use 3 component vertex positions and non-perspective
     * uses 2.
     */
    struct Key {
        Key() {
            sk_bzero(this, sizeof(Key));
        }
        uint32_t fUniqueID;
        // Color may affect the gamma of the mask we generate, but in a fairly limited way.
        // Each color is assigned to on of a fixed number of buckets based on its
        // luminance. For each luminance bucket there is a "canonical color" that
        // represents the bucket.  This functionality is currently only supported for A8
        SkColor fCanonicalColor;
        SkPaint::Style fStyle;
        SkPixelGeometry fPixelGeometry;
        bool fHasBlur;
        uint32_t fScalerContextFlags;

        bool operator==(const Key& other) const {
            return 0 == memcmp(this, &other, sizeof(Key));
        }
    };

    void setupKey(const GrTextBlob::Key& key,
                  const SkMaskFilterBase::BlurRec& blurRec,
                  const SkPaint& paint) {
        fKey = key;
        if (key.fHasBlur) {
            fBlurRec = blurRec;
        }
        if (key.fStyle != SkPaint::kFill_Style) {
            fStrokeInfo.fFrameWidth = paint.getStrokeWidth();
            fStrokeInfo.fMiterLimit = paint.getStrokeMiter();
            fStrokeInfo.fJoin = paint.getStrokeJoin();
        }
    }

    static const Key& GetKey(const GrTextBlob& blob) {
        return blob.fKey;
    }

    static uint32_t Hash(const Key& key) {
        return SkOpts::hash(&key, sizeof(Key));
    }

    void operator delete(void* p) {
        ::operator delete(p);
    }

    void* operator new(size_t) {
        SK_ABORT("All blobs are created by placement new.");
    }

    void* operator new(size_t, void* p) { return p; }

    bool hasDistanceField() const { return SkToBool(fTextType & kHasDistanceField_TextType); }
    bool hasBitmap() const { return SkToBool(fTextType & kHasBitmap_TextType); }
    void setHasDistanceField() { fTextType |= kHasDistanceField_TextType; }
    void setHasBitmap() { fTextType |= kHasBitmap_TextType; }

    int runCountLimit() const { return fRunCountLimit; }

    Run* pushBackRun() {
        SkASSERT(fRunCount < fRunCountLimit);

        // If there is more run, then connect up the subruns.
        if (fRunCount > 0) {
            SubRun& newRun = fRuns[fRunCount].fSubRunInfo.back();
            SubRun& lastRun = fRuns[fRunCount - 1].fSubRunInfo.back();
            newRun.setAsSuccessor(lastRun);
        }

        fRunCount++;
        return this->currentRun();
    }

    void setMinAndMaxScale(SkScalar scaledMin, SkScalar scaledMax) {
        // we init fMaxMinScale and fMinMaxScale in the constructor
        fMaxMinScale = SkMaxScalar(scaledMin, fMaxMinScale);
        fMinMaxScale = SkMinScalar(scaledMax, fMinMaxScale);
    }

    static size_t GetVertexStride(GrMaskFormat maskFormat, bool hasWCoord) {
        switch (maskFormat) {
            case kA8_GrMaskFormat:
                return hasWCoord ? kGrayTextDFPerspectiveVASize : kGrayTextVASize;
            case kARGB_GrMaskFormat:
                return hasWCoord ? kColorTextPerspectiveVASize : kColorTextVASize;
            default:
                SkASSERT(!hasWCoord);
                return kLCDTextVASize;
        }
    }

    bool mustRegenerate(const SkPaint&, bool, const SkMaskFilterBase::BlurRec& blurRec,
                        const SkMatrix& viewMatrix, SkScalar x, SkScalar y);

    void flush(GrTextTarget*, const SkSurfaceProps& props,
               const GrDistanceFieldAdjustTable* distanceAdjustTable,
               const SkPaint& paint, const SkPMColor4f& filteredColor, const GrClip& clip,
               const SkMatrix& viewMatrix, SkScalar x, SkScalar y);

    void computeSubRunBounds(SkRect* outBounds, int runIndex, int subRunIndex,
                             const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
                             bool needsGlyphTransform) {
        // We don't yet position distance field text on the cpu, so we have to map the vertex bounds
        // into device space.
        // We handle vertex bounds differently for distance field text and bitmap text because
        // the vertex bounds of bitmap text are in device space.  If we are flushing multiple runs
        // from one blob then we are going to pay the price here of mapping the rect for each run.
        const Run& run = fRuns[runIndex];
        const SubRun& subRun = run.fSubRunInfo[subRunIndex];
        *outBounds = subRun.vertexBounds();
        if (needsGlyphTransform) {
            // Distance field text is positioned with the (X,Y) as part of the glyph position,
            // and currently the view matrix is applied on the GPU
            outBounds->offset(x - fInitialX, y - fInitialY);
            viewMatrix.mapRect(outBounds);
        } else {
            // Bitmap text is fully positioned on the CPU, and offset by an (X,Y) translate in
            // device space.
            SkMatrix boundsMatrix = fInitialViewMatrixInverse;

            boundsMatrix.postTranslate(-fInitialX, -fInitialY);

            boundsMatrix.postTranslate(x, y);

            boundsMatrix.postConcat(viewMatrix);
            boundsMatrix.mapRect(outBounds);

            // Due to floating point numerical inaccuracies, we have to round out here
            outBounds->roundOut(outBounds);
        }
    }

    // position + local coord
    static const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16);
    static const size_t kColorTextPerspectiveVASize = sizeof(SkPoint3) + sizeof(SkIPoint16);
    static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof(SkIPoint16);
    static const size_t kGrayTextDFPerspectiveVASize =
            sizeof(SkPoint3) + sizeof(GrColor) + sizeof(SkIPoint16);
    static const size_t kLCDTextVASize = kGrayTextVASize;
    static const size_t kMaxVASize = kGrayTextDFPerspectiveVASize;
    static const int kVerticesPerGlyph = 4;

    static void AssertEqual(const GrTextBlob&, const GrTextBlob&);

    // The color here is the GrPaint color, and it is used to determine whether we
    // have to regenerate LCD text blobs.
    // We use this color vs the SkPaint color because it has the colorfilter applied.
    void initReusableBlob(SkColor luminanceColor, const SkMatrix& viewMatrix,
                          SkScalar x, SkScalar y) {
        fLuminanceColor = luminanceColor;
        this->setupViewMatrix(viewMatrix, x, y);
    }

    void initThrowawayBlob(const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
        this->setupViewMatrix(viewMatrix, x, y);
    }

    const Key& key() const { return fKey; }

    size_t size() const { return fSize; }

    ~GrTextBlob() override {
        for (int i = 0; i < fRunCountLimit; i++) {
            fRuns[i].~Run();
        }
    }

    ////////////////////////////////////////////////////////////////////////////////////////////////
    // Internal test methods
    std::unique_ptr<GrDrawOp> test_makeOp(int glyphCount, uint16_t run, uint16_t subRun,
                                          const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
                                          const SkPaint& paint, const SkPMColor4f& filteredColor,
                                          const SkSurfaceProps&, const GrDistanceFieldAdjustTable*,
                                          GrTextTarget*);

private:
    GrTextBlob(GrStrikeCache* strikeCache) : fStrikeCache{strikeCache} { }

    // This function will only be called when we are generating a blob from scratch. We record the
    // initial view matrix and initial offsets(x,y), because we record vertex bounds relative to
    // these numbers.  When blobs are reused with new matrices, we need to return to model space so
    // we can update the vertex bounds appropriately.
    void setupViewMatrix(const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
        fInitialViewMatrix = viewMatrix;
        if (!viewMatrix.invert(&fInitialViewMatrixInverse)) {
            fInitialViewMatrixInverse = SkMatrix::I();
        }
        fInitialX = x;
        fInitialY = y;

        // make sure all initial subruns have the correct VM and X/Y applied
        for (int i = 0; i < fRunCountLimit; i++) {
            fRuns[i].fSubRunInfo[0].init(fInitialViewMatrix, x, y);
        }
    }

    class SubRun {
    public:
        SubRun(Run* run, const SkStrikeSpec& strikeSpec, GrColor color)
            : fColor{color}
            , fRun{run}
            , fStrikeSpec{strikeSpec} {}

        // When used with emplace_back, this constructs a SubRun from the last SubRun in an array.
        //SubRun(SkSTArray<1, SubRun>* subRunList)
        //    : fColor{subRunList->fromBack(1).fColor} { }

        void appendGlyph(GrGlyph* glyph, SkRect dstRect);

        // TODO when this object is more internal, drop the privacy
        void resetBulkUseToken() { fBulkUseToken.reset(); }
        GrDrawOpAtlas::BulkUseTokenUpdater* bulkUseToken() { return &fBulkUseToken; }
        void setStrike(sk_sp<GrTextStrike> strike) { fStrike = std::move(strike); }
        GrTextStrike* strike() const { return fStrike.get(); }
        sk_sp<GrTextStrike> refStrike() const { return fStrike; }

        void setAtlasGeneration(uint64_t atlasGeneration) { fAtlasGeneration = atlasGeneration;}
        uint64_t atlasGeneration() const { return fAtlasGeneration; }

        size_t byteCount() const { return fVertexEndIndex - fVertexStartIndex; }
        size_t vertexStartIndex() const { return fVertexStartIndex; }
        size_t vertexEndIndex() const { return fVertexEndIndex; }

        uint32_t glyphCount() const { return fGlyphEndIndex - fGlyphStartIndex; }
        uint32_t glyphStartIndex() const { return fGlyphStartIndex; }
        uint32_t glyphEndIndex() const { return fGlyphEndIndex; }
        void setColor(GrColor color) { fColor = color; }
        GrColor color() const { return fColor; }
        void setMaskFormat(GrMaskFormat format) { fMaskFormat = format; }
        GrMaskFormat maskFormat() const { return fMaskFormat; }

        void setAsSuccessor(const SubRun& prev) {
            fGlyphStartIndex = prev.glyphEndIndex();
            fGlyphEndIndex = fGlyphStartIndex;

            fVertexStartIndex = prev.vertexEndIndex();
            fVertexEndIndex = fVertexStartIndex;

            // copy over viewmatrix settings
            this->init(prev.fCurrentViewMatrix, prev.fX, prev.fY);
        }

        const SkRect& vertexBounds() const { return fVertexBounds; }
        void joinGlyphBounds(const SkRect& glyphBounds) {
            fVertexBounds.joinNonEmptyArg(glyphBounds);
        }

        void init(const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
            fCurrentViewMatrix = viewMatrix;
            fX = x;
            fY = y;
        }

        // This function assumes the translation will be applied before it is called again
        void computeTranslation(const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
                                SkScalar* transX, SkScalar* transY);

        // df properties
        void setDrawAsDistanceFields() { fFlags.drawAsSdf = true; }
        bool drawAsDistanceFields() const { return fFlags.drawAsSdf; }
        void setUseLCDText(bool useLCDText) { fFlags.useLCDText = useLCDText; }
        bool hasUseLCDText() const { return fFlags.useLCDText; }
        void setAntiAliased(bool antiAliased) { fFlags.antiAliased = antiAliased; }
        bool isAntiAliased() const { return fFlags.antiAliased; }
        void setHasWCoord(bool hasW) { fFlags.hasWCoord = hasW; }
        bool hasWCoord() const { return fFlags.hasWCoord; }
        void setNeedsTransform(bool needsTransform) { fFlags.needsTransform = needsTransform; }
        bool needsTransform() const { return fFlags.needsTransform; }
        void setFallback() { fFlags.argbFallback = true; }
        bool isFallback() { return fFlags.argbFallback; }

        const SkStrikeSpec& strikeSpec() const { return fStrikeSpec; }

    private:
        GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken;
        sk_sp<GrTextStrike> fStrike;
        SkMatrix fCurrentViewMatrix;
        SkRect fVertexBounds = SkRectPriv::MakeLargestInverted();
        uint64_t fAtlasGeneration{GrDrawOpAtlas::kInvalidAtlasGeneration};
        size_t fVertexStartIndex{0};
        size_t fVertexEndIndex{0};
        uint32_t fGlyphStartIndex{0};
        uint32_t fGlyphEndIndex{0};
        SkScalar fX;
        SkScalar fY;
        GrColor fColor{GrColor_ILLEGAL};
        GrMaskFormat fMaskFormat{kA8_GrMaskFormat};
        struct {
            bool drawAsSdf:1;
            bool useLCDText:1;
            bool antiAliased:1;
            bool hasWCoord:1;
            bool needsTransform:1;
            bool argbFallback:1;
        } fFlags{false, false, false, false, false, false};
        Run* const fRun;
        const SkStrikeSpec& fStrikeSpec;
    };  // SubRunInfo

    /*
     * Each Run inside of the blob can have its texture coordinates regenerated if required.
     * To determine if regeneration is necessary, fAtlasGeneration is used.  If there have been
     * any evictions inside of the atlas, then we will simply regenerate Runs.  We could track
     * this at a more fine grained level, but its not clear if this is worth it, as evictions
     * should be fairly rare.
     *
     * One additional point, each run can contain glyphs with any of the three mask formats.
     * We call these SubRuns.  Because a subrun must be a contiguous range, we have to create
     * a new subrun each time the mask format changes in a run.  In theory, a run can have as
     * many SubRuns as it has glyphs, ie if a run alternates between color emoji and A8.  In
     * practice, the vast majority of runs have only a single subrun.
     *
     * Finally, for runs where the entire thing is too large for the GrTextContext to
     * handle, we have a bit to mark the run as flushable via rendering as paths or as scaled
     * glyphs. It would be a bit expensive to figure out ahead of time whether or not a run
     * can flush in this manner, so we always allocate vertices for the run, regardless of
     * whether or not it is too large.  The benefit of this strategy is that we can always reuse
     * a blob allocation regardless of viewmatrix changes.  We could store positions for these
     * glyphs, however, it's not clear if this is a win because we'd still have to either go to the
     * glyph cache to get the path at flush time, or hold onto the path in the cache, which
     * would greatly increase the memory of these cached items.
     */
    struct Run {
        explicit Run(GrTextBlob* blob, GrColor color)
        : fBlob{blob}, fColor{color} {
            // To ensure we always have one subrun, we push back a fresh run here
            fSubRunInfo.emplace_back(this, fStrikeSpec, color);
        }

        // sets the last subrun of runIndex to use w values
        void setSubRunHasW(bool hasWCoord) {
            SubRun& subRun = this->fSubRunInfo.back();
            subRun.setHasWCoord(hasWCoord);
        }

        // inits the override descriptor on the current run.  All following subruns must use this
        // descriptor
        SubRun* initARGBFallback() {
            fFallbackStrikeSpec.reset(new SkStrikeSpec{});
            // Push back a new subrun to fill and set the override descriptor
            SubRun* subRun = this->pushBackSubRun(*fFallbackStrikeSpec, fColor);
            subRun->setMaskFormat(kARGB_GrMaskFormat);
            subRun->setFallback();
            return subRun;
        }

        // Appends a glyph to the blob as a path only.
        void appendPathGlyph(
                const SkPath& path, SkPoint position, SkScalar scale, bool preTransformed);

        // Append a glyph to the sub run taking care to switch the glyph if needed.
        void switchSubRunIfNeededAndAppendGlyph(GrGlyph* glyph,
                                                const sk_sp<GrTextStrike>& strike,
                                                const SkRect& destRect,
                                                bool needsTransform);

        // Used when the glyph in the cache has the CTM already applied, therefore no transform
        // is needed during rendering.
        void appendDeviceSpaceGlyph(const sk_sp<GrTextStrike>& strike,
                                    const SkGlyph& skGlyph,
                                    SkPoint origin);

        // The glyph is oriented upright in the cache and needs to be transformed onto the screen.
        void appendSourceSpaceGlyph(const sk_sp<GrTextStrike>& strike,
                                    const SkGlyph& skGlyph,
                                    SkPoint origin,
                                    SkScalar textScale);

        void setupFont(const SkStrikeSpec& strikeSpec);

        void setRunFontAntiAlias(bool aa) {
            fAntiAlias = aa;
        }

        // sets the last subrun of runIndex to use distance field text
        void setSubRunHasDistanceFields(bool hasLCD, bool isAntiAlias, bool hasWCoord) {
            SubRun& subRun = fSubRunInfo.back();
            subRun.setUseLCDText(hasLCD);
            subRun.setAntiAliased(isAntiAlias);
            subRun.setDrawAsDistanceFields();
            subRun.setHasWCoord(hasWCoord);
        }

        SubRun* pushBackSubRun(const SkStrikeSpec& desc, GrColor color) {
            // Forward glyph / vertex information to seed the new sub run
            SubRun& newSubRun = fSubRunInfo.emplace_back(this, desc, color);

            const SubRun& prevSubRun = fSubRunInfo.fromBack(1);

            // Forward glyph / vertex information to seed the new sub run
            newSubRun.setAsSuccessor(prevSubRun);
            return &newSubRun;
        }

        // Any glyphs that can't be rendered with the base or override descriptor
        // are rendered as paths
        struct PathGlyph {
            PathGlyph(const SkPath& path, SkScalar x, SkScalar y, SkScalar scale, bool preXformed)
                : fPath(path)
                , fX(x)
                , fY(y)
                , fScale(scale)
                , fPreTransformed(preXformed) {}
            SkPath fPath;
            SkScalar fX;
            SkScalar fY;
            SkScalar fScale;
            bool fPreTransformed;
        };

        SkSTArray<1, SubRun> fSubRunInfo;
        SkStrikeSpec fStrikeSpec;

        // Distance field text cannot draw coloremoji, and so has to fall back.  However,
        // though the distance field text and the coloremoji may share the same run, they
        // will have different descriptors.  If fFallbackStrikeSpec is non-nullptr, then it
        // will be used in place of the run's descriptor to regen texture coords
        std::unique_ptr<SkStrikeSpec> fFallbackStrikeSpec;

        SkTArray<PathGlyph> fPathGlyphs;

        bool fAntiAlias{false};   // needed mainly for rendering paths
        bool fInitialized{false};

        GrTextBlob* const fBlob;
        GrColor fColor;
    };  // Run

    std::unique_ptr<GrAtlasTextOp> makeOp(
            const SubRun& info, int glyphCount, uint16_t run, uint16_t subRun,
            const SkMatrix& viewMatrix, SkScalar x, SkScalar y, const SkIRect& clipRect,
            const SkPaint& paint, const SkPMColor4f& filteredColor, const SkSurfaceProps&,
            const GrDistanceFieldAdjustTable*, GrTextTarget*);

    // currentRun, startRun, and the process* calls are all used by the SkGlyphRunPainter, and
    // live in SkGlyphRunPainter.cpp file.
    Run* currentRun();

    void startRun(const SkGlyphRun& glyphRun, bool useSDFT) override;

    void processDeviceMasks(SkSpan<const SkGlyphPos> masks,
                            const SkStrikeSpec& strikeSpec) override;

    void processSourcePaths(SkSpan<const SkGlyphPos> paths,
                            const SkStrikeSpec& strikeSpec) override;

    void processDevicePaths(SkSpan<const SkGlyphPos> paths) override;

    void processSourceSDFT(SkSpan<const SkGlyphPos> masks,
                           const SkStrikeSpec& strikeSpec,
                           const SkFont& runFont,
                           SkScalar minScale,
                           SkScalar maxScale,
                           bool hasWCoord) override;

    void processSourceFallback(SkSpan<const SkGlyphPos> masks,
                               const SkStrikeSpec& strikeSpec,
                               bool hasW) override;

    void processDeviceFallback(SkSpan<const SkGlyphPos> masks,
                               const SkStrikeSpec& strikeSpec) override;

    struct StrokeInfo {
        SkScalar fFrameWidth;
        SkScalar fMiterLimit;
        SkPaint::Join fJoin;
    };

    enum TextType {
        kHasDistanceField_TextType = 0x1,
        kHasBitmap_TextType = 0x2,
    };

    // all glyph / vertex offsets are into these pools.
    char* fVertices;
    GrGlyph** fGlyphs;
    Run* fRuns;

    // Lifetime: The GrStrikeCache is owned by and has the same lifetime as the GrRecordingContext.
    // The GrRecordingContext also owns the GrTextBlob cache which owns this GrTextBlob.
    GrStrikeCache* const fStrikeCache;
    SkMaskFilterBase::BlurRec fBlurRec;
    StrokeInfo fStrokeInfo;
    Key fKey;
    SkMatrix fInitialViewMatrix;
    SkMatrix fInitialViewMatrixInverse;
    size_t fSize;
    SkColor fLuminanceColor;
    SkScalar fInitialX;
    SkScalar fInitialY;

    // We can reuse distance field text, but only if the new viewmatrix would not result in
    // a mip change.  Because there can be multiple runs in a blob, we track the overall
    // maximum minimum scale, and minimum maximum scale, we can support before we need to regen
    SkScalar fMaxMinScale{-SK_ScalarMax};
    SkScalar fMinMaxScale{SK_ScalarMax};
    int fRunCount{0};
    int fRunCountLimit;
    uint8_t fTextType{0};
};

/**
 * Used to produce vertices for a subrun of a blob. The vertices are cached in the blob itself.
 * This is invoked each time a sub run is drawn. It regenerates the vertex data as required either
 * because of changes to the atlas or because of different draw parameters (e.g. color change). In
 * rare cases the draw may have to interrupted and flushed in the middle of the sub run in order to
 * free up atlas space. Thus, this generator is stateful and should be invoked in a loop until the
 * entire sub run has been completed.
 */
class GrTextBlob::VertexRegenerator {
public:
    /**
     * Consecutive VertexRegenerators often use the same SkGlyphCache. If the same instance of
     * SkAutoGlyphCache is reused then it can save the cost of multiple detach/attach operations of
     * SkGlyphCache.
     */
    VertexRegenerator(GrResourceProvider*, GrTextBlob*, int runIdx, int subRunIdx,
                      const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
                      GrDeferredUploadTarget*, GrStrikeCache*, GrAtlasManager*,
                      SkExclusiveStrikePtr*);

    struct Result {
        /**
         * Was regenerate() able to draw all the glyphs from the sub run? If not flush all glyph
         * draws and call regenerate() again.
         */
        bool fFinished = true;

        /**
         * How many glyphs were regenerated. Will be equal to the sub run's glyph count if
         * fType is kFinished.
         */
        int fGlyphsRegenerated = 0;

        /**
         * Pointer where the caller finds the first regenerated vertex.
         */
        const char* fFirstVertex;
    };

    bool regenerate(Result*);

private:
    bool doRegen(Result*, bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs);

    GrResourceProvider* fResourceProvider;
    const SkMatrix& fViewMatrix;
    GrTextBlob* fBlob;
    GrDeferredUploadTarget* fUploadTarget;
    GrStrikeCache* fGlyphCache;
    GrAtlasManager* fFullAtlasManager;
    SkExclusiveStrikePtr* fLazyStrike;
    SubRun* fSubRun;
    GrColor fColor;
    SkScalar fTransX;
    SkScalar fTransY;

    uint32_t fRegenFlags = 0;
    int fCurrGlyph = 0;
    bool fBrokenRun = false;
};

#endif  // GrTextBlob_DEFINED
