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

#include "src/core/SkMaskCache.h"

#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"
#include "include/core/SkSize.h"
#include "include/private/SkAssert.h"
#include "src/core/SkCachedData.h"
#include "src/core/SkMask.h"
#include "src/core/SkResourceCache.h"
#include "src/core/SkTLazy.h"

#include <cstddef>
#include <cstdint>

class SkDiscardableMemory;
enum SkBlurStyle : int;

#define CHECK_LOCAL(localCache, localName, globalName, ...) \
    ((localCache) ? localCache->localName(__VA_ARGS__) : SkResourceCache::globalName(__VA_ARGS__))

struct MaskValue {
    SkMask          fMask;
    SkCachedData*   fData;
};

namespace {
static unsigned gRRectBlurKeyNamespaceLabel;

struct RRectBlurKey : public SkResourceCache::Key {
public:
    RRectBlurKey(SkScalar sigma, const SkRRect& rrect, SkBlurStyle style)
        : fSigma(sigma)
        , fStyle(style)
        , fRRect(rrect)
    {
        this->init(&gRRectBlurKeyNamespaceLabel, 0,
                   sizeof(fSigma) + sizeof(fStyle) + sizeof(fRRect));
    }

    SkScalar   fSigma;
    int32_t    fStyle;
    SkRRect    fRRect;
};

struct RRectBlurRec : public SkResourceCache::Rec {
    RRectBlurRec(RRectBlurKey key, const SkMask& mask, SkCachedData* data)
        : fKey(key), fValue({{nullptr, mask.fBounds, mask.fRowBytes, mask.fFormat}, data})
    {
        fValue.fData->attachToCacheAndRef();
    }
    ~RRectBlurRec() override {
        fValue.fData->detachFromCacheAndUnref();
    }

    RRectBlurKey   fKey;
    MaskValue      fValue;

    const Key& getKey() const override { return fKey; }
    size_t bytesUsed() const override { return sizeof(*this) + fValue.fData->size(); }
    const char* getCategory() const override { return "rrect-blur"; }
    SkDiscardableMemory* diagnostic_only_getDiscardable() const override {
        return fValue.fData->diagnostic_only_getDiscardable();
    }

    static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextData) {
        const RRectBlurRec& rec = static_cast<const RRectBlurRec&>(baseRec);
        SkTLazy<MaskValue>* result = (SkTLazy<MaskValue>*)contextData;

        SkCachedData* tmpData = rec.fValue.fData;
        tmpData->ref();
        if (nullptr == tmpData->data()) {
            tmpData->unref();
            return false;
        }
        result->init(rec.fValue);
        return true;
    }
};
} // namespace

sk_sp<SkCachedData> SkMaskCache::Find(SkScalar sigma,
                                      SkBlurStyle style,
                                      const SkRRect& rrect,
                                      SkTLazy<SkMask>* mask,
                                      SkResourceCache* localCache) {
    SkTLazy<MaskValue> result;
    RRectBlurKey key(sigma, rrect, style);
    if (!CHECK_LOCAL(localCache, find, Find, key, RRectBlurRec::Visitor, &result)) {
        return nullptr;
    }

    mask->init(static_cast<const uint8_t*>(result->fData->data()),
               result->fMask.fBounds, result->fMask.fRowBytes, result->fMask.fFormat);
    return sk_sp<SkCachedData>(result->fData);
}

void SkMaskCache::Add(SkScalar sigma,
                      SkBlurStyle style,
                      const SkRRect& rrect,
                      const SkMask& mask,
                      sk_sp<SkCachedData> data,
                      SkResourceCache* localCache) {
    RRectBlurKey key(sigma, rrect, style);
    return CHECK_LOCAL(localCache, add, Add, new RRectBlurRec(key, mask, data.get()));
}

//////////////////////////////////////////////////////////////////////////////////////////

namespace {
static unsigned gRectsBlurKeyNamespaceLabel;

struct RectsBlurKey : public SkResourceCache::Key {
public:
    RectsBlurKey(SkScalar sigma, SkBlurStyle style, SkSpan<const SkRect> rects)
            : fSigma(sigma), fStyle(style) {
        SkASSERT(rects.size() == 1 || rects.size() == 2);
        SkIRect ir;
        rects[0].roundOut(&ir);
        fSizes[0] = SkSize{rects[0].width(), rects[0].height()};
        if (rects.size() == 2) {
            fSizes[1] = SkSize{rects[1].width(), rects[1].height()};
            fSizes[2] = SkSize{rects[0].x() - rects[1].x(), rects[0].y() - rects[1].y()};
        } else {
            fSizes[1] = SkSize{0, 0};
            fSizes[2] = SkSize{0, 0};
        }
        fSizes[3] = SkSize{rects[0].x() - ir.x(), rects[0].y() - ir.y()};

        this->init(&gRectsBlurKeyNamespaceLabel, 0,
                   sizeof(fSigma) + sizeof(fStyle) + sizeof(fSizes));
    }

    SkScalar    fSigma;
    int32_t     fStyle;
    SkSize      fSizes[4];
};

struct RectsBlurRec : public SkResourceCache::Rec {
    RectsBlurRec(RectsBlurKey key, const SkMask& mask, SkCachedData* data)
        : fKey(key), fValue({{nullptr, mask.fBounds, mask.fRowBytes, mask.fFormat}, data})
    {
        fValue.fData->attachToCacheAndRef();
    }
    ~RectsBlurRec() override {
        fValue.fData->detachFromCacheAndUnref();
    }

    RectsBlurKey   fKey;
    MaskValue      fValue;

    const Key& getKey() const override { return fKey; }
    size_t bytesUsed() const override { return sizeof(*this) + fValue.fData->size(); }
    const char* getCategory() const override { return "rects-blur"; }
    SkDiscardableMemory* diagnostic_only_getDiscardable() const override {
        return fValue.fData->diagnostic_only_getDiscardable();
    }

    static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextData) {
        const RectsBlurRec& rec = static_cast<const RectsBlurRec&>(baseRec);
        SkTLazy<MaskValue>* result = static_cast<SkTLazy<MaskValue>*>(contextData);

        SkCachedData* tmpData = rec.fValue.fData;
        tmpData->ref();
        if (nullptr == tmpData->data()) {
            tmpData->unref();
            return false;
        }
        result->init(rec.fValue);
        return true;
    }
};
} // namespace

sk_sp<SkCachedData> SkMaskCache::Find(SkScalar sigma,
                                      SkBlurStyle style,
                                      SkSpan<const SkRect> rects,
                                      SkTLazy<SkMask>* mask,
                                      SkResourceCache* localCache) {
    SkTLazy<MaskValue> result;
    RectsBlurKey key(sigma, style, rects);
    if (!CHECK_LOCAL(localCache, find, Find, key, RectsBlurRec::Visitor, &result)) {
        return nullptr;
    }

    mask->init(static_cast<const uint8_t*>(result->fData->data()),
               result->fMask.fBounds, result->fMask.fRowBytes, result->fMask.fFormat);
    return sk_sp<SkCachedData>(result->fData);
}

void SkMaskCache::Add(SkScalar sigma,
                      SkBlurStyle style,
                      SkSpan<const SkRect> rects,
                      const SkMask& mask,
                      sk_sp<SkCachedData> data,
                      SkResourceCache* localCache) {
    RectsBlurKey key(sigma, style, rects);
    return CHECK_LOCAL(localCache, add, Add, new RectsBlurRec(key, mask, data.get()));
}
