/*
 * 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"
#include <new>

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) {
        fRootBounds.setXYWH(0, 0, w, h);

        SkASSERT(fStack.count() == 1);
        Rec& rec = fStack.top();
        SkASSERT(rec.fDeferredCount == 0);
        rec.fRC.setRect(fRootBounds);
    }

    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
