/*
 * 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 "GrBatchFlushState.h"
#include "GrTextUtils.h"

#include "SkDistanceFieldGen.h"
#include "SkGlyphCache.h"

#include "batches/GrAtlasTextBatch.h"

////////////////////////////////////////////////////////////////////////////////////////////////////
// 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(intptr_t vertex, const GrGlyph* glyph, size_t vertexStride,
                           bool useDistanceFields, SkScalar transX, SkScalar transY,
                           int32_t log2Width, int32_t log2Height,
                           GrColor color) {
    int u0, v0, u1, v1;
    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;
        }

        // normalize
        u0 *= 65535;
        u0 >>= log2Width;
        u1 *= 65535;
        u1 >>= log2Width;
        v0 *= 65535;
        v0 >>= log2Height;
        v1 *= 65535;
        v1 >>= log2Height;
        SkASSERT(u0 >= 0 && u0 <= 65535);
        SkASSERT(u1 >= 0 && u1 <= 65535);
        SkASSERT(v0 >= 0 && v0 <= 65535);
        SkASSERT(v1 >= 0 && v1 <= 65535);
    }

    // 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 colorOffset = sizeof(SkPoint);
    intptr_t texCoordOffset = vertexStride - sizeof(SkIPoint16);

    // 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] = (uint16_t) u0;
        textureCoords[1] = (uint16_t) v0;
    }
    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] = (uint16_t)u0;
        textureCoords[1] = (uint16_t)v1;
    }
    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] = (uint16_t)u1;
        textureCoords[1] = (uint16_t)v1;
    }
    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] = (uint16_t)u1;
        textureCoords[1] = (uint16_t)v0;
    }
}

template <bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs>
void GrAtlasTextBlob::regenInBatch(GrDrawBatch::Target* target,
                                   GrBatchFontCache* fontCache,
                                   GrBlobRegenHelper *helper,
                                   Run* run,
                                   Run::SubRunInfo* info, SkGlyphCache** cache,
                                   SkTypeface** typeface, GrFontScaler** scaler,
                                   const SkDescriptor** desc,
                                   int glyphCount, size_t vertexStride,
                                   GrColor color, SkScalar transX,
                                   SkScalar transY) const {
    static_assert(!regenGlyphs || regenTexCoords, "must regenTexCoords along regenGlyphs");
    GrBatchTextStrike* strike = nullptr;
    if (regenTexCoords) {
        info->resetBulkUseToken();

        // We can reuse if we have a valid strike and our descriptors / typeface are the
        // same.  The override descriptor is only for the non distance field text within
        // a run
        const SkDescriptor* newDesc = (run->fOverrideDescriptor && !info->drawAsDistanceFields()) ?
                                      run->fOverrideDescriptor->getDesc() :
                                      run->fDescriptor.getDesc();
        if (!*cache || !SkTypeface::Equal(*typeface, run->fTypeface) ||
            !((*desc)->equals(*newDesc))) {
            if (*cache) {
                SkGlyphCache::AttachCache(*cache);
            }
            *desc = newDesc;
            *cache = SkGlyphCache::DetachCache(run->fTypeface, run->fEffects, *desc);
            *scaler = GrTextUtils::GetGrFontScaler(*cache);
            *typeface = run->fTypeface;
        }

        if (regenGlyphs) {
            strike = fontCache->getStrike(*scaler);
        } else {
            strike = info->strike();
        }
    }

    bool brokenRun = false;
    for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) {
        GrGlyph* glyph = nullptr;
        int log2Width = 0, log2Height = 0;
        if (regenTexCoords) {
            size_t glyphOffset = glyphIdx + info->glyphStartIndex();

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

            if (!fontCache->hasGlyph(glyph) &&
                !strike->addGlyphToAtlas(target, glyph, *scaler, info->maskFormat())) {
                helper->flush();
                brokenRun = glyphIdx > 0;

                SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(target,
                                                                    glyph,
                                                                    *scaler,
                                                                    info->maskFormat());
                SkASSERT(success);
            }
            fontCache->addGlyphToBulkAndSetUseToken(info->bulkUseToken(), glyph,
                                                    target->nextDrawToken());
            log2Width = fontCache->log2Width(info->maskFormat());
            log2Height = fontCache->log2Height(info->maskFormat());
        }

        intptr_t vertex = reinterpret_cast<intptr_t>(fVertices);
        vertex += info->vertexStartIndex();
        vertex += vertexStride * glyphIdx * GrAtlasTextBatch::kVerticesPerGlyph;
        regen_vertices<regenPos, regenCol, regenTexCoords>(vertex, glyph, vertexStride,
                                                           info->drawAsDistanceFields(), transX,
                                                           transY, log2Width, log2Height, color);
        helper->incGlyphCount();
    }

    // We may have changed the color so update it here
    info->setColor(color);
    if (regenTexCoords) {
        if (regenGlyphs) {
            info->setStrike(strike);
        }
        info->setAtlasGeneration(brokenRun ? GrBatchAtlas::kInvalidAtlasGeneration :
                                 fontCache->atlasGeneration(info->maskFormat()));
    }
}

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,
};

#define REGEN_ARGS target, fontCache, helper, &run, &info, cache, typeface, scaler, desc, \
                   *glyphCount, vertexStride, color, transX, transY

void GrAtlasTextBlob::regenInBatch(GrDrawBatch::Target* target,
                                   GrBatchFontCache* fontCache,
                                   GrBlobRegenHelper *helper,
                                   int runIndex, int subRunIndex, SkGlyphCache** cache,
                                   SkTypeface** typeface, GrFontScaler** scaler,
                                   const SkDescriptor** desc, size_t vertexStride,
                                   const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
                                   GrColor color,
                                   void** vertices, size_t* byteCount, int* glyphCount) {
    Run& run = fRuns[runIndex];
    Run::SubRunInfo& info = run.fSubRunInfo[subRunIndex];

    uint64_t currentAtlasGen = fontCache->atlasGeneration(info.maskFormat());

    // Compute translation if any
    SkScalar transX, transY;
    info.computeTranslation(viewMatrix, x, y, &transX, &transY);

    // Because the GrBatchFontCache 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
    bool regenerateGlyphs = info.strike()->isAbandoned();
    bool regenerateTextureCoords = info.atlasGeneration() != currentAtlasGen ||
                                   regenerateGlyphs;
    bool regenerateColors = kARGB_GrMaskFormat != info.maskFormat() &&
                            info.color() != color;
    bool regeneratePositions = transX != 0.f || transY != 0.f;
    *glyphCount = info.glyphCount();

    uint32_t regenMaskBits = kNoRegen;
    regenMaskBits |= regeneratePositions ? kRegenPos : 0;
    regenMaskBits |= regenerateColors ? kRegenCol : 0;
    regenMaskBits |= regenerateTextureCoords ? kRegenTex : 0;
    regenMaskBits |= regenerateGlyphs ? kRegenGlyph : 0;
    RegenMask regenMask = (RegenMask)regenMaskBits;

    switch (regenMask) {
        case kRegenPos: this->regenInBatch<true, false, false, false>(REGEN_ARGS); break;
        case kRegenCol: this->regenInBatch<false, true, false, false>(REGEN_ARGS); break;
        case kRegenTex: this->regenInBatch<false, false, true, false>(REGEN_ARGS); break;
        case kRegenGlyph: this->regenInBatch<false, false, true, true>(REGEN_ARGS); break;

            // combinations
        case kRegenPosCol: this->regenInBatch<true, true, false, false>(REGEN_ARGS); break;
        case kRegenPosTex: this->regenInBatch<true, false, true, false>(REGEN_ARGS); break;
        case kRegenPosTexGlyph: this->regenInBatch<true, false, true, true>(REGEN_ARGS); break;
        case kRegenPosColTex: this->regenInBatch<true, true, true, false>(REGEN_ARGS); break;
        case kRegenPosColTexGlyph: this->regenInBatch<true, true, true, true>(REGEN_ARGS); break;
        case kRegenColTex: this->regenInBatch<false, true, true, false>(REGEN_ARGS); break;
        case kRegenColTexGlyph: this->regenInBatch<false, true, true, true>(REGEN_ARGS); break;
        case kNoRegen:
            helper->incGlyphCount(*glyphCount);

            // set use tokens for all of the glyphs in our subrun.  This is only valid if we
            // have a valid atlas generation
            fontCache->setUseTokenBulk(*info.bulkUseToken(), target->nextDrawToken(),
                                        info.maskFormat());
            break;
    }

    *byteCount = info.byteCount();
    *vertices = fVertices + info.vertexStartIndex();
}
