/*
 * 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.");
        return sk_malloc_throw(0);
    }

    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
