123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- /*
- * 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 "include/core/SkClipOp.h"
- #include "include/core/SkDeque.h"
- #include "src/core/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
|