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

#ifndef SkRasterClipStack_DEFINED
#define SkRasterClipStack_DEFINED

#include "SkClipOp.h"
#include "SkDeque.h"
#include "SkRasterClip.h"

template <typename T> class SkTStack {
public:
    SkTStack(void* storage, size_t size) : fDeque(sizeof(T), storage, size), fTop(nullptr) {}
    ~SkTStack() {
        while (!fDeque.empty()) {
            ((T*)fDeque.back())->~T();
            fDeque.pop_back();
        }
    }

    bool empty() const { return fDeque.empty(); }

    int count() const { return fDeque.count(); }

    const T& top() const {
        SkASSERT(fTop);
        return *fTop;
    }

    T& top() {
        SkASSERT(fTop);
        return *fTop;
    }

    T* push_raw() { return (T*)fDeque.push_back(); }
    T& push() {
        fTop = this->push_raw();
        new (fTop) T();
        return *fTop;
    }
    T& push(const T& src) {
        fTop = this->push_raw();
        new (fTop) T(src);
        return *fTop;
    }

    void pop() {
        fTop->~T();
        fDeque.pop_back();
        fTop = fDeque.empty() ? nullptr : (T*)fDeque.back();
    }

private:
    SkDeque fDeque;
    T*      fTop;
};

class SkRasterClipStack : SkNoncopyable {
    int fCounter = 0;
public:
    SkRasterClipStack(int width, int height)
        : fStack(fStorage, sizeof(fStorage))
        , fRootBounds(SkIRect::MakeWH(width, height))
    {
        Rec& rec = fStack.push();
        rec.fRC.setRect(fRootBounds);
        rec.fDeferredCount = 0;
        SkASSERT(fStack.count() == 1);
    }

    void setNewSize(int w, int h) {
        SkASSERT(fStack.count() == 1);
        fRootBounds.setXYWH(0, 0, w, h);
    }

    const SkRasterClip& rc() const { return fStack.top().fRC; }

    void save() {
        fCounter += 1;
        SkASSERT(fStack.top().fDeferredCount >= 0);
        fStack.top().fDeferredCount += 1;
    }

    void restore() {
        fCounter -= 1; SkASSERT(fCounter >= 0);
        if (--fStack.top().fDeferredCount < 0) {
            SkASSERT(fStack.top().fDeferredCount == -1);
            SkASSERT(fStack.count() > 1);
            fStack.pop();
        }
    }

    void clipRect(const SkMatrix& ctm, const SkRect& rect, SkClipOp op, bool aa) {
        this->writable_rc().op(rect, ctm, fRootBounds, (SkRegion::Op)op, aa);
        this->trimIfExpanding(op);
        this->validate();
    }

    void clipRRect(const SkMatrix& ctm, const SkRRect& rrect, SkClipOp op, bool aa) {
        this->writable_rc().op(rrect, ctm, fRootBounds, (SkRegion::Op)op, aa);
        this->trimIfExpanding(op);
        this->validate();
    }

    void clipPath(const SkMatrix& ctm, const SkPath& path, SkClipOp op, bool aa) {
        this->writable_rc().op(path, ctm, fRootBounds, (SkRegion::Op)op, aa);
        this->trimIfExpanding(op);
        this->validate();
    }

    void clipRegion(const SkRegion& rgn, SkClipOp op) {
        this->writable_rc().op(rgn, (SkRegion::Op)op);
        this->trimIfExpanding(op);
        this->validate();
    }

    void setDeviceClipRestriction(SkIRect* mutableClipRestriction) {
        this->writable_rc().setDeviceClipRestriction(mutableClipRestriction);
    }

    void validate() const {
#ifdef SK_DEBUG
        const SkRasterClip& clip = this->rc();
        if (fRootBounds.isEmpty()) {
            SkASSERT(clip.isEmpty());
        } else if (!clip.isEmpty()) {
            SkASSERT(fRootBounds.contains(clip.getBounds()));
        }
#endif
    }

private:
    struct Rec {
        SkRasterClip    fRC;
        int             fDeferredCount; // 0 for a "normal" entry
    };

    enum {
        ELEM_COUNT = 16,
        PTR_COUNT = ELEM_COUNT * sizeof(Rec) / sizeof(void*)
    };
    void*           fStorage[PTR_COUNT];
    SkTStack<Rec>   fStack;
    SkIRect         fRootBounds;

    SkRasterClip& writable_rc() {
        SkASSERT(fStack.top().fDeferredCount >= 0);
        if (fStack.top().fDeferredCount > 0) {
            fStack.top().fDeferredCount -= 1;
            fStack.push(fStack.top());
            fStack.top().fDeferredCount = 0;
        }
        return fStack.top().fRC;
    }

    void trimIfExpanding(SkClipOp op) {
        if ((int)op > (int)SkClipOp::kIntersect) {
            Rec& rec = fStack.top();
            SkASSERT(rec.fDeferredCount == 0);
            rec.fRC.op(fRootBounds, SkRegion::kIntersect_Op);
        }
    }
};

#endif
