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

#include "include/core/SkPaint.h"
#include "src/core/SkRemoteGlyphCache.h"
#include "src/core/SkStrike.h"
#include "src/core/SkStrikeCache.h"
#include "src/core/SkTraceEvent.h"
#include "src/core/SkTypeface_remote.h"

SkScalerContextProxy::SkScalerContextProxy(sk_sp<SkTypeface> tf,
                                           const SkScalerContextEffects& effects,
                                           const SkDescriptor* desc,
                                           sk_sp<SkStrikeClient::DiscardableHandleManager> manager)
        : SkScalerContext{std::move(tf), effects, desc}
        , fDiscardableManager{std::move(manager)} {}

void SkScalerContextProxy::initCache(SkStrike* cache, SkStrikeCache* strikeCache) {
    SkASSERT(fCache == nullptr);
    SkASSERT(cache != nullptr);

    fCache = cache;
    fStrikeCache = strikeCache;
}

unsigned SkScalerContextProxy::generateGlyphCount()  {
    SK_ABORT("Should never be called.");
}

bool SkScalerContextProxy::generateAdvance(SkGlyph* glyph) {
    return false;
}

void SkScalerContextProxy::generateMetrics(SkGlyph* glyph) {
    TRACE_EVENT1("skia", "generateMetrics", "rec", TRACE_STR_COPY(this->getRec().dump().c_str()));
    if (this->getProxyTypeface()->isLogging()) {
        SkDebugf("GlyphCacheMiss generateMetrics: %s\n", this->getRec().dump().c_str());
    }

    glyph->fMaskFormat = fRec.fMaskFormat;

    // Since the scaler context is being called, we don't have the needed data. Try to find a
    // fallback before failing.
    if (fCache && fCache->glyphOrNull(glyph->getPackedID()) != nullptr) {
        // First check the original cache, in case there is a sub-pixel pos mismatch.
        if (const SkGlyph* from =
                    fCache->getCachedGlyphAnySubPix(glyph->getGlyphID(), glyph->getPackedID())) {
            fCache->mergeGlyphAndImage(glyph->getPackedID(), *from);
            fDiscardableManager->notifyCacheMiss(
                    SkStrikeClient::CacheMissType::kGlyphMetricsFallback);
            return;
        }

        // Now check other caches for a desc mismatch.
        if (fStrikeCache->desperationSearchForImage(fCache->getDescriptor(), glyph, fCache)) {
            fDiscardableManager->notifyCacheMiss(
                    SkStrikeClient::CacheMissType::kGlyphMetricsFallback);
            return;
        }
    }

    glyph->zeroMetrics();
    fDiscardableManager->notifyCacheMiss(SkStrikeClient::CacheMissType::kGlyphMetrics);
}

void SkScalerContextProxy::generateImage(const SkGlyph& glyph) {
    TRACE_EVENT1("skia", "generateImage", "rec", TRACE_STR_COPY(this->getRec().dump().c_str()));
    if (this->getProxyTypeface()->isLogging()) {
        SkDebugf("GlyphCacheMiss generateImage: %s\n", this->getRec().dump().c_str());
    }

    // There is no desperation search here, because if there was an image to be found it was
    // copied over with the metrics search.
    fDiscardableManager->notifyCacheMiss(SkStrikeClient::CacheMissType::kGlyphImage);
}

bool SkScalerContextProxy::generatePath(SkGlyphID glyphID, SkPath* path) {
    TRACE_EVENT1("skia", "generatePath", "rec", TRACE_STR_COPY(this->getRec().dump().c_str()));
    if (this->getProxyTypeface()->isLogging()) {
        SkDebugf("GlyphCacheMiss generatePath: %s\n", this->getRec().dump().c_str());
    }

    // Since the scaler context is being called, we don't have the needed data. Try to find a
    // fallback before failing.
    auto desc = SkScalerContext::DescriptorGivenRecAndEffects(this->getRec(), this->getEffects());
    bool foundPath = fStrikeCache && fStrikeCache->desperationSearchForPath(*desc, glyphID, path);
    fDiscardableManager->notifyCacheMiss(foundPath
                                                 ? SkStrikeClient::CacheMissType::kGlyphPathFallback
                                                 : SkStrikeClient::CacheMissType::kGlyphPath);
    return foundPath;
}

void SkScalerContextProxy::generateFontMetrics(SkFontMetrics* metrics) {
    TRACE_EVENT1(
            "skia", "generateFontMetrics", "rec", TRACE_STR_COPY(this->getRec().dump().c_str()));
    if (this->getProxyTypeface()->isLogging()) {
        SkDebugf("GlyphCacheMiss generateFontMetrics: %s\n", this->getRec().dump().c_str());
        SkDEBUGCODE(SkStrikeCache::Dump());
    }

    // Font metrics aren't really used for render, so just zero out the data and return.
    fDiscardableManager->notifyCacheMiss(SkStrikeClient::CacheMissType::kFontMetrics);
    sk_bzero(metrics, sizeof(*metrics));
}

SkTypefaceProxy* SkScalerContextProxy::getProxyTypeface() const {
    return (SkTypefaceProxy*)this->getTypeface();
}
