/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "src/core/SkStrike.h"

#include "include/core/SkDrawable.h"
#include "include/core/SkGraphics.h"
#include "include/core/SkPath.h"
#include "include/core/SkTraceMemoryDump.h"
#include "include/core/SkTypeface.h"
#include "include/private/base/SkAssert.h"
#include "src/core/SkDistanceFieldGen.h"
#include "src/core/SkEnumerate.h"
#include "src/core/SkGlyph.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkScalerContext.h"
#include "src/core/SkStrikeCache.h"
#include "src/core/SkWriteBuffer.h"
#include "src/text/StrikeForGPU.h"

#include <optional>

#if defined(SK_GANESH)
    #include "src/text/gpu/StrikeCache.h"
#endif

using namespace skglyph;

static SkFontMetrics use_or_generate_metrics(
        const SkFontMetrics* metrics, SkScalerContext* context) {
    SkFontMetrics answer;
    if (metrics) {
        answer = *metrics;
    } else {
        context->getFontMetrics(&answer);
    }
    return answer;
}

SkStrike::SkStrike(SkStrikeCache* strikeCache,
                   const SkStrikeSpec& strikeSpec,
                   std::unique_ptr<SkScalerContext> scaler,
                   const SkFontMetrics* metrics,
                   std::unique_ptr<SkStrikePinner> pinner)
        : fFontMetrics{use_or_generate_metrics(metrics, scaler.get())}
        , fRoundingSpec{scaler->isSubpixel(),
                        scaler->computeAxisAlignmentForHText()}
        , fStrikeSpec{strikeSpec}
        , fStrikeCache{strikeCache}
        , fScalerContext{std::move(scaler)}
        , fPinner{std::move(pinner)} {
    SkASSERT(fScalerContext != nullptr);
}

class SK_SCOPED_CAPABILITY SkStrike::Monitor {
public:
    Monitor(SkStrike* strike) SK_ACQUIRE(strike->fStrikeLock)
            : fStrike{strike} {
        fStrike->lock();
    }

    ~Monitor() SK_RELEASE_CAPABILITY() {
        fStrike->unlock();
    }

private:
    SkStrike* const fStrike;
};

void SkStrike::lock() {
    fStrikeLock.acquire();
    fMemoryIncrease = 0;
}

void SkStrike::unlock() {
    const size_t memoryIncrease = fMemoryIncrease;
    fStrikeLock.release();
    this->updateMemoryUsage(memoryIncrease);
}

void
SkStrike::FlattenGlyphsByType(SkWriteBuffer& buffer,
                              SkSpan<SkGlyph> images,
                              SkSpan<SkGlyph> paths,
                              SkSpan<SkGlyph> drawables) {
    SkASSERT_RELEASE(SkTFitsIn<int>(images.size()) &&
                     SkTFitsIn<int>(paths.size()) &&
                     SkTFitsIn<int>(drawables.size()));

    buffer.writeInt(images.size());
    for (SkGlyph& glyph : images) {
        SkASSERT(SkMask::IsValidFormat(glyph.maskFormat()));
        glyph.flattenMetrics(buffer);
        glyph.flattenImage(buffer);
    }

    buffer.writeInt(paths.size());
    for (SkGlyph& glyph : paths) {
        SkASSERT(SkMask::IsValidFormat(glyph.maskFormat()));
        glyph.flattenMetrics(buffer);
        glyph.flattenPath(buffer);
    }

    buffer.writeInt(drawables.size());
    for (SkGlyph& glyph : drawables) {
        SkASSERT(SkMask::IsValidFormat(glyph.maskFormat()));
        glyph.flattenMetrics(buffer);
        glyph.flattenDrawable(buffer);
    }
}

bool SkStrike::mergeFromBuffer(SkReadBuffer& buffer) {
    // Read glyphs with images for the current strike.
    const int imagesCount = buffer.readInt();
    if (imagesCount == 0 && !buffer.isValid()) {
        return false;
    }

    {
        Monitor m{this};
        for (int curImage = 0; curImage < imagesCount; ++curImage) {
            if (!this->mergeGlyphAndImageFromBuffer(buffer)) {
                return false;
            }
        }
    }

    // Read glyphs with paths for the current strike.
    const int pathsCount = buffer.readInt();
    if (pathsCount == 0 && !buffer.isValid()) {
        return false;
    }
    {
        Monitor m{this};
        for (int curPath = 0; curPath < pathsCount; ++curPath) {
            if (!this->mergeGlyphAndPathFromBuffer(buffer)) {
                return false;
            }
        }
    }

    // Read glyphs with drawables for the current strike.
    const int drawablesCount = buffer.readInt();
    if (drawablesCount == 0 && !buffer.isValid()) {
        return false;
    }
    {
        Monitor m{this};
        for (int curDrawable = 0; curDrawable < drawablesCount; ++curDrawable) {
            if (!this->mergeGlyphAndDrawableFromBuffer(buffer)) {
                return false;
            }
        }
    }

    return true;
}

SkGlyph* SkStrike::mergeGlyphAndImage(SkPackedGlyphID toID, const SkGlyph& fromGlyph) {
    Monitor m{this};
    // TODO(herb): remove finding the glyph when setting the metrics and image are separated
    SkGlyphDigest* digest = fDigestForPackedGlyphID.find(toID);
    if (digest != nullptr) {
        SkGlyph* glyph = fGlyphForIndex[digest->index()];
        if (fromGlyph.setImageHasBeenCalled()) {
            if (glyph->setImageHasBeenCalled()) {
                // Should never set an image on a glyph which already has an image.
                SkDEBUGFAIL("Re-adding image to existing glyph. This should not happen.");
            }
            // TODO: assert that any metrics on fromGlyph are the same.
            fMemoryIncrease += glyph->setMetricsAndImage(&fAlloc, fromGlyph);
        }
        return glyph;
    } else {
        SkGlyph* glyph = fAlloc.make<SkGlyph>(toID);
        fMemoryIncrease += glyph->setMetricsAndImage(&fAlloc, fromGlyph) + sizeof(SkGlyph);
        (void)this->addGlyphAndDigest(glyph);
        return glyph;
    }
}

const SkPath* SkStrike::mergePath(SkGlyph* glyph, const SkPath* path, bool hairline) {
    Monitor m{this};
    if (glyph->setPathHasBeenCalled()) {
        SkDEBUGFAIL("Re-adding path to existing glyph. This should not happen.");
    }
    if (glyph->setPath(&fAlloc, path, hairline)) {
        fMemoryIncrease += glyph->path()->approximateBytesUsed();
    }

    return glyph->path();
}

const SkDrawable* SkStrike::mergeDrawable(SkGlyph* glyph, sk_sp<SkDrawable> drawable) {
    Monitor m{this};
    if (glyph->setDrawableHasBeenCalled()) {
        SkDEBUGFAIL("Re-adding drawable to existing glyph. This should not happen.");
    }
    if (glyph->setDrawable(&fAlloc, std::move(drawable))) {
        fMemoryIncrease += glyph->drawable()->approximateBytesUsed();
        SkASSERT(fMemoryIncrease > 0);
    }

    return glyph->drawable();
}

void SkStrike::findIntercepts(const SkScalar bounds[2], SkScalar scale, SkScalar xPos,
                              SkGlyph* glyph, SkScalar* array, int* count) {
    SkAutoMutexExclusive lock{fStrikeLock};
    glyph->ensureIntercepts(bounds, scale, xPos, array, count, &fAlloc);
}

SkSpan<const SkGlyph*> SkStrike::metrics(
        SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) {
    Monitor m{this};
    return this->internalPrepare(glyphIDs, kMetricsOnly, results);
}

SkSpan<const SkGlyph*> SkStrike::preparePaths(
        SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) {
    Monitor m{this};
    return this->internalPrepare(glyphIDs, kMetricsAndPath, results);
}

SkSpan<const SkGlyph*> SkStrike::prepareImages(
        SkSpan<const SkPackedGlyphID> glyphIDs, const SkGlyph* results[]) {
    const SkGlyph** cursor = results;
    Monitor m{this};
    for (auto glyphID : glyphIDs) {
        SkGlyph* glyph = this->glyph(glyphID);
        this->prepareForImage(glyph);
        *cursor++ = glyph;
    }

    return {results, glyphIDs.size()};
}

SkSpan<const SkGlyph*> SkStrike::prepareDrawables(
        SkSpan<const SkGlyphID> glyphIDs, const SkGlyph* results[]) {
    const SkGlyph** cursor = results;
    {
        Monitor m{this};
        for (auto glyphID : glyphIDs) {
            SkGlyph* glyph = this->glyph(SkPackedGlyphID{glyphID});
            this->prepareForDrawable(glyph);
            *cursor++ = glyph;
        }
    }

    return {results, glyphIDs.size()};
}

void SkStrike::glyphIDsToPaths(SkSpan<sktext::IDOrPath> idsOrPaths) {
    Monitor m{this};
    for (sktext::IDOrPath& idOrPath : idsOrPaths) {
        SkGlyph* glyph = this->glyph(SkPackedGlyphID{idOrPath.fGlyphID});
        this->prepareForPath(glyph);
        new (&idOrPath.fPath) SkPath{*glyph->path()};
    }
}

void SkStrike::glyphIDsToDrawables(SkSpan<sktext::IDOrDrawable> idsOrDrawables) {
    Monitor m{this};
    for (sktext::IDOrDrawable& idOrDrawable : idsOrDrawables) {
        SkGlyph* glyph = this->glyph(SkPackedGlyphID{idOrDrawable.fGlyphID});
        this->prepareForDrawable(glyph);
        SkASSERT(glyph->drawable() != nullptr);
        idOrDrawable.fDrawable = glyph->drawable();
    }
}

void SkStrike::dump() const {
    SkAutoMutexExclusive lock{fStrikeLock};
    const SkTypeface* face = fScalerContext->getTypeface();
    const SkScalerContextRec& rec = fScalerContext->getRec();
    SkMatrix matrix;
    rec.getSingleMatrix(&matrix);
    matrix.preScale(SkScalarInvert(rec.fTextSize), SkScalarInvert(rec.fTextSize));
    SkString name;
    face->getFamilyName(&name);

    SkString msg;
    SkFontStyle style = face->fontStyle();
    msg.printf("cache typeface:%x %25s:(%d,%d,%d)\n %s glyphs:%3d",
               face->uniqueID(), name.c_str(), style.weight(), style.width(), style.slant(),
               rec.dump().c_str(), fDigestForPackedGlyphID.count());
    SkDebugf("%s\n", msg.c_str());
}

void SkStrike::dumpMemoryStatistics(SkTraceMemoryDump* dump) const {
    SkAutoMutexExclusive lock{fStrikeLock};
    const SkTypeface* face = fScalerContext->getTypeface();
    const SkScalerContextRec& rec = fScalerContext->getRec();

    SkString fontName;
    face->getFamilyName(&fontName);
    // Replace all special characters with '_'.
    for (size_t index = 0; index < fontName.size(); ++index) {
        if (!std::isalnum(fontName[index])) {
            fontName[index] = '_';
        }
    }

    SkString dumpName = SkStringPrintf("%s/%s_%d/%p",
                                       SkStrikeCache::kGlyphCacheDumpName,
                                       fontName.c_str(),
                                       rec.fTypefaceID,
                                       this);

    dump->dumpNumericValue(dumpName.c_str(), "size", "bytes", fMemoryUsed);
    dump->dumpNumericValue(dumpName.c_str(),
                           "glyph_count", "objects",
                           fDigestForPackedGlyphID.count());
    dump->setMemoryBacking(dumpName.c_str(), "malloc", nullptr);
}

SkGlyph* SkStrike::glyph(SkGlyphDigest digest) {
    return fGlyphForIndex[digest.index()];
}

SkGlyph* SkStrike::glyph(SkPackedGlyphID packedGlyphID) {
    SkGlyphDigest digest = this->digestFor(kDirectMask, packedGlyphID);
    return this->glyph(digest);
}

SkGlyphDigest SkStrike::digestFor(ActionType actionType, SkPackedGlyphID packedGlyphID) {
    SkGlyphDigest* digestPtr = fDigestForPackedGlyphID.find(packedGlyphID);
    if (digestPtr != nullptr && digestPtr->actionFor(actionType) != GlyphAction::kUnset) {
        return *digestPtr;
    }

    SkGlyph* glyph;
    if (digestPtr != nullptr) {
        glyph = fGlyphForIndex[digestPtr->index()];
    } else {
        glyph = fAlloc.make<SkGlyph>(fScalerContext->makeGlyph(packedGlyphID, &fAlloc));
        fMemoryIncrease += sizeof(SkGlyph);
        digestPtr = this->addGlyphAndDigest(glyph);
    }

    digestPtr->setActionFor(actionType, glyph, this);

    return *digestPtr;
}

SkGlyphDigest* SkStrike::addGlyphAndDigest(SkGlyph* glyph) {
    size_t index = fGlyphForIndex.size();
    SkGlyphDigest digest = SkGlyphDigest{index, *glyph};
    SkGlyphDigest* newDigest = fDigestForPackedGlyphID.set(digest);
    fGlyphForIndex.push_back(glyph);
    return newDigest;
}

bool SkStrike::prepareForImage(SkGlyph* glyph) {
    if (glyph->setImage(&fAlloc, fScalerContext.get())) {
        fMemoryIncrease += glyph->imageSize();
    }
    return glyph->image() != nullptr;
}

bool SkStrike::prepareForPath(SkGlyph* glyph) {
    if (glyph->setPath(&fAlloc, fScalerContext.get())) {
        fMemoryIncrease += glyph->path()->approximateBytesUsed();
    }
    return glyph->path() !=nullptr;
}

bool SkStrike::prepareForDrawable(SkGlyph* glyph) {
    if (glyph->setDrawable(&fAlloc, fScalerContext.get())) {
        size_t increase = glyph->drawable()->approximateBytesUsed();
        SkASSERT(increase > 0);
        fMemoryIncrease += increase;
    }
    return glyph->drawable() != nullptr;
}

SkGlyph* SkStrike::mergeGlyphFromBuffer(SkReadBuffer& buffer) {
    SkASSERT(buffer.isValid());
    std::optional<SkGlyph> prototypeGlyph = SkGlyph::MakeFromBuffer(buffer);
    if (!buffer.validate(prototypeGlyph.has_value())) {
        return nullptr;
    }

    // Check if this glyph has already been seen.
    SkGlyphDigest* digestPtr = fDigestForPackedGlyphID.find(prototypeGlyph->getPackedID());
    if (digestPtr != nullptr) {
        return fGlyphForIndex[digestPtr->index()];
    }

    // This is the first time. Allocate a new glyph.
    SkGlyph* glyph = fAlloc.make<SkGlyph>(prototypeGlyph.value());
    fMemoryIncrease += sizeof(SkGlyph);
    this->addGlyphAndDigest(glyph);
    return glyph;
}

bool SkStrike::mergeGlyphAndImageFromBuffer(SkReadBuffer& buffer) {
    SkASSERT(buffer.isValid());
    SkGlyph* glyph = this->mergeGlyphFromBuffer(buffer);
    if (!buffer.validate(glyph != nullptr)) {
        return false;
    }
    fMemoryIncrease += glyph->addImageFromBuffer(buffer, &fAlloc);
    return buffer.isValid();
}

bool SkStrike::mergeGlyphAndPathFromBuffer(SkReadBuffer& buffer) {
    SkASSERT(buffer.isValid());
    SkGlyph* glyph = this->mergeGlyphFromBuffer(buffer);
    if (!buffer.validate(glyph != nullptr)) {
        return false;
    }
    fMemoryIncrease += glyph->addPathFromBuffer(buffer, &fAlloc);
    return buffer.isValid();
}

bool SkStrike::mergeGlyphAndDrawableFromBuffer(SkReadBuffer& buffer) {
    SkASSERT(buffer.isValid());
    SkGlyph* glyph = this->mergeGlyphFromBuffer(buffer);
    if (!buffer.validate(glyph != nullptr)) {
        return false;
    }
    fMemoryIncrease += glyph->addDrawableFromBuffer(buffer, &fAlloc);
    return buffer.isValid();
}

SkSpan<const SkGlyph*> SkStrike::internalPrepare(
        SkSpan<const SkGlyphID> glyphIDs, PathDetail pathDetail, const SkGlyph** results) {
    const SkGlyph** cursor = results;
    for (auto glyphID : glyphIDs) {
        SkGlyph* glyph = this->glyph(SkPackedGlyphID{glyphID});
        if (pathDetail == kMetricsAndPath) {
            this->prepareForPath(glyph);
        }
        *cursor++ = glyph;
    }

    return {results, glyphIDs.size()};
}

void SkStrike::updateMemoryUsage(size_t increase) {
    if (increase > 0) {
        // fRemoved and the cache's total memory are managed under the cache's lock. This allows
        // them to be accessed under LRU operation.
        SkAutoMutexExclusive lock{fStrikeCache->fLock};
        fMemoryUsed += increase;
        if (!fRemoved) {
            fStrikeCache->fTotalMemoryUsed += increase;
        }
    }
}
