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

#include "GrAtlasTextBlob.h"
#include "GrTextUtils.h"
#include "SkDistanceFieldGen.h"
#include "SkGlyphCache.h"
#include "ops/GrAtlasTextOp.h"

using Regenerator = GrAtlasTextBlob::VertexRegenerator;

enum RegenMask {
    kNoRegen    = 0x0,
    kRegenPos   = 0x1,
    kRegenCol   = 0x2,
    kRegenTex   = 0x4,
    kRegenGlyph = 0x8 | kRegenTex,  // we have to regenerate the texture coords when we regen glyphs

    // combinations
    kRegenPosCol = kRegenPos | kRegenCol,
    kRegenPosTex = kRegenPos | kRegenTex,
    kRegenPosTexGlyph = kRegenPos | kRegenGlyph,
    kRegenPosColTex = kRegenPos | kRegenCol | kRegenTex,
    kRegenPosColTexGlyph = kRegenPos | kRegenCol | kRegenGlyph,
    kRegenColTex = kRegenCol | kRegenTex,
    kRegenColTexGlyph = kRegenCol | kRegenGlyph,
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// A large template to handle regenerating the vertices of a textblob with as few branches as
// possible
template <bool regenPos, bool regenCol, bool regenTexCoords>
inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStride,
                           bool useDistanceFields, SkScalar transX, SkScalar transY,
                           GrColor color) {
    uint16_t u0, v0, u1, v1;
#ifdef DISPLAY_PAGE_INDEX
    // Enable this to visualize the page from which each glyph is being drawn.
    // Green Red Magenta Cyan -> 0 1 2 3; Black -> error
    SkColor hackColor;
#endif
    if (regenTexCoords) {
        SkASSERT(glyph);
        int width = glyph->fBounds.width();
        int height = glyph->fBounds.height();

        if (useDistanceFields) {
            u0 = glyph->fAtlasLocation.fX + SK_DistanceFieldInset;
            v0 = glyph->fAtlasLocation.fY + SK_DistanceFieldInset;
            u1 = u0 + width - 2 * SK_DistanceFieldInset;
            v1 = v0 + height - 2 * SK_DistanceFieldInset;
        } else {
            u0 = glyph->fAtlasLocation.fX;
            v0 = glyph->fAtlasLocation.fY;
            u1 = u0 + width;
            v1 = v0 + height;
        }
        // We pack the 2bit page index in the low bit of the u and v texture coords
        uint32_t pageIndex = glyph->pageIndex();
        SkASSERT(pageIndex < 4);
        uint16_t uBit = (pageIndex >> 1) & 0x1;
        uint16_t vBit = pageIndex & 0x1;
        u0 <<= 1;
        u0 |= uBit;
        v0 <<= 1;
        v0 |= vBit;
        u1 <<= 1;
        u1 |= uBit;
        v1 <<= 1;
        v1 |= vBit;
#ifdef DISPLAY_PAGE_INDEX
        switch (pageIndex) {
            case 0:
                hackColor = SK_ColorGREEN;
                break;
            case 1:
                hackColor = SK_ColorRED;
                break;
            case 2:
                hackColor = SK_ColorMAGENTA;
                break;
            case 3:
                hackColor = SK_ColorCYAN;
                break;
            default:
                hackColor = SK_ColorBLACK;
                break;
        }
#endif
    }

    // This is a bit wonky, but sometimes we have LCD text, in which case we won't have color
    // vertices, hence vertexStride - sizeof(SkIPoint16)
    intptr_t texCoordOffset = vertexStride - sizeof(SkIPoint16);
    intptr_t colorOffset = texCoordOffset - sizeof(GrColor);

    // V0
    if (regenPos) {
        SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
        point->fX += transX;
        point->fY += transY;
    }

    if (regenCol) {
        SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
        *vcolor = color;
    }

    if (regenTexCoords) {
        uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset);
        textureCoords[0] = u0;
        textureCoords[1] = v0;
#ifdef DISPLAY_PAGE_INDEX
        SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
        *vcolor = hackColor;
#endif
    }
    vertex += vertexStride;

    // V1
    if (regenPos) {
        SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
        point->fX += transX;
        point->fY += transY;
    }

    if (regenCol) {
        SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
        *vcolor = color;
    }

    if (regenTexCoords) {
        uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset);
        textureCoords[0] = u0;
        textureCoords[1] = v1;
#ifdef DISPLAY_PAGE_INDEX
        SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
        *vcolor = hackColor;
#endif
    }
    vertex += vertexStride;

    // V2
    if (regenPos) {
        SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
        point->fX += transX;
        point->fY += transY;
    }

    if (regenCol) {
        SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
        *vcolor = color;
    }

    if (regenTexCoords) {
        uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset);
        textureCoords[0] = u1;
        textureCoords[1] = v0;
#ifdef DISPLAY_PAGE_INDEX
        SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
        *vcolor = hackColor;
#endif
    }
    vertex += vertexStride;

    // V3
    if (regenPos) {
        SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
        point->fX += transX;
        point->fY += transY;
    }

    if (regenCol) {
        SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
        *vcolor = color;
    }

    if (regenTexCoords) {
        uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset);
        textureCoords[0] = u1;
        textureCoords[1] = v1;
#ifdef DISPLAY_PAGE_INDEX
        SkColor* vcolor = reinterpret_cast<SkColor*>(vertex + colorOffset);
        *vcolor = hackColor;
#endif
    }
}

Regenerator::VertexRegenerator(GrAtlasTextBlob* blob, int runIdx, int subRunIdx,
                               const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
                               GrDeferredUploadTarget* uploadTarget, GrAtlasGlyphCache* glyphCache,
                               SkAutoGlyphCache* lazyCache)
        : fViewMatrix(viewMatrix)
        , fBlob(blob)
        , fUploadTarget(uploadTarget)
        , fGlyphCache(glyphCache)
        , fLazyCache(lazyCache)
        , fRun(&blob->fRuns[runIdx])
        , fSubRun(&blob->fRuns[runIdx].fSubRunInfo[subRunIdx])
        , fColor(color) {
    // Compute translation if any
    fSubRun->computeTranslation(fViewMatrix, x, y, &fTransX, &fTransY);

    // Because the GrAtlasGlyphCache may evict the strike a blob depends on using for
    // generating its texture coords, we have to track whether or not the strike has
    // been abandoned.  If it hasn't been abandoned, then we can use the GrGlyph*s as is
    // otherwise we have to get the new strike, and use that to get the correct glyphs.
    // Because we do not have the packed ids, and thus can't look up our glyphs in the
    // new strike, we instead keep our ref to the old strike and use the packed ids from
    // it.  These ids will still be valid as long as we hold the ref.  When we are done
    // updating our cache of the GrGlyph*s, we drop our ref on the old strike
    if (fSubRun->strike()->isAbandoned()) {
        fRegenFlags |= kRegenGlyph;
        fRegenFlags |= kRegenTex;
    }
    if (kARGB_GrMaskFormat != fSubRun->maskFormat() && fSubRun->color() != color) {
        fRegenFlags |= kRegenCol;
    }
    if (0.f != fTransX || 0.f != fTransY) {
        fRegenFlags |= kRegenPos;
    }
}

template <bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs>
Regenerator::Result Regenerator::doRegen() {
    static_assert(!regenGlyphs || regenTexCoords, "must regenTexCoords along regenGlyphs");
    GrAtlasTextStrike* strike = nullptr;
    if (regenTexCoords) {
        fSubRun->resetBulkUseToken();

        const SkDescriptor* desc = (fRun->fOverrideDescriptor && !fSubRun->drawAsDistanceFields())
                                           ? fRun->fOverrideDescriptor->getDesc()
                                           : fRun->fDescriptor.getDesc();

        if (!*fLazyCache || (*fLazyCache)->getDescriptor() != *desc) {
            SkScalerContextEffects effects;
            effects.fPathEffect = fRun->fPathEffect.get();
            effects.fMaskFilter = fRun->fMaskFilter.get();
            fLazyCache->reset(SkGlyphCache::DetachCache(fRun->fTypeface.get(), effects, desc));
        }

        if (regenGlyphs) {
            strike = fGlyphCache->getStrike(fLazyCache->get());
        } else {
            strike = fSubRun->strike();
        }
    }

    bool hasW = fSubRun->hasWCoord();
    Result result;
    auto vertexStride = GetVertexStride(fSubRun->maskFormat(), hasW);
    char* currVertex = fBlob->fVertices + fSubRun->vertexStartIndex() +
                       fCurrGlyph * kVerticesPerGlyph * vertexStride;
    result.fFirstVertex = currVertex;

    for (int glyphIdx = fCurrGlyph; glyphIdx < (int)fSubRun->glyphCount(); glyphIdx++) {
        GrGlyph* glyph = nullptr;
        if (regenTexCoords) {
            size_t glyphOffset = glyphIdx + fSubRun->glyphStartIndex();

            if (regenGlyphs) {
                // Get the id from the old glyph, and use the new strike to lookup
                // the glyph.
                GrGlyph::PackedID id = fBlob->fGlyphs[glyphOffset]->fPackedID;
                fBlob->fGlyphs[glyphOffset] =
                        strike->getGlyph(id, fSubRun->maskFormat(), fLazyCache->get());
                SkASSERT(id == fBlob->fGlyphs[glyphOffset]->fPackedID);
            }
            glyph = fBlob->fGlyphs[glyphOffset];
            SkASSERT(glyph && glyph->fMaskFormat == fSubRun->maskFormat());

            if (!fGlyphCache->hasGlyph(glyph) &&
                !strike->addGlyphToAtlas(fUploadTarget, fGlyphCache, glyph, fLazyCache->get(),
                                         fSubRun->maskFormat())) {
                fBrokenRun = glyphIdx > 0;
                result.fFinished = false;
                return result;
            }
            auto tokenTracker = fUploadTarget->tokenTracker();
            fGlyphCache->addGlyphToBulkAndSetUseToken(fSubRun->bulkUseToken(), glyph,
                                                      tokenTracker->nextDrawToken());
        }

        regen_vertices<regenPos, regenCol, regenTexCoords>(currVertex, glyph, vertexStride,
                                                           fSubRun->drawAsDistanceFields(), fTransX,
                                                           fTransY, fColor);
        currVertex += vertexStride * GrAtlasTextOp::kVerticesPerGlyph;
        ++result.fGlyphsRegenerated;
        ++fCurrGlyph;
    }

    // We may have changed the color so update it here
    fSubRun->setColor(fColor);
    if (regenTexCoords) {
        if (regenGlyphs) {
            fSubRun->setStrike(strike);
        }
        fSubRun->setAtlasGeneration(fBrokenRun
                                            ? GrDrawOpAtlas::kInvalidAtlasGeneration
                                            : fGlyphCache->atlasGeneration(fSubRun->maskFormat()));
    }
    return result;
}

Regenerator::Result Regenerator::regenerate() {
    uint64_t currentAtlasGen = fGlyphCache->atlasGeneration(fSubRun->maskFormat());
    // If regenerate() is called multiple times then the atlas gen may have changed. So we check
    // this each time.
    if (fSubRun->atlasGeneration() != currentAtlasGen) {
        fRegenFlags |= kRegenTex;
    }

    switch (static_cast<RegenMask>(fRegenFlags)) {
        case kRegenPos:
            return this->doRegen<true, false, false, false>();
        case kRegenCol:
            return this->doRegen<false, true, false, false>();
        case kRegenTex:
            return this->doRegen<false, false, true, false>();
        case kRegenGlyph:
            return this->doRegen<false, false, true, true>();

        // combinations
        case kRegenPosCol:
            return this->doRegen<true, true, false, false>();
        case kRegenPosTex:
            return this->doRegen<true, false, true, false>();
        case kRegenPosTexGlyph:
            return this->doRegen<true, false, true, true>();
        case kRegenPosColTex:
            return this->doRegen<true, true, true, false>();
        case kRegenPosColTexGlyph:
            return this->doRegen<true, true, true, true>();
        case kRegenColTex:
            return this->doRegen<false, true, true, false>();
        case kRegenColTexGlyph:
            return this->doRegen<false, true, true, true>();
        case kNoRegen: {
            Result result;
            bool hasW = fSubRun->hasWCoord();
            auto vertexStride = GetVertexStride(fSubRun->maskFormat(), hasW);
            result.fGlyphsRegenerated = fSubRun->glyphCount() - fCurrGlyph;
            result.fFirstVertex = fBlob->fVertices + fSubRun->vertexStartIndex() +
                                  fCurrGlyph * kVerticesPerGlyph * vertexStride;
            fCurrGlyph = fSubRun->glyphCount();

            // set use tokens for all of the glyphs in our subrun.  This is only valid if we
            // have a valid atlas generation
            fGlyphCache->setUseTokenBulk(*fSubRun->bulkUseToken(),
                                         fUploadTarget->tokenTracker()->nextDrawToken(),
                                         fSubRun->maskFormat());
            return result;
        }
    }
    SK_ABORT("Should not get here");
    return Result();
}
