1 /* 2 * Copyright 2017 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SkRasterClipStack_DEFINED 9 #define SkRasterClipStack_DEFINED 10 11 #include "SkClipOp.h" 12 #include "SkDeque.h" 13 #include "SkRasterClip.h" 14 15 template <typename T> class SkTStack { 16 public: SkTStack(void * storage,size_t size)17 SkTStack(void* storage, size_t size) : fDeque(sizeof(T), storage, size), fTop(nullptr) {} ~SkTStack()18 ~SkTStack() { 19 while (!fDeque.empty()) { 20 ((T*)fDeque.back())->~T(); 21 fDeque.pop_back(); 22 } 23 } 24 empty()25 bool empty() const { return fDeque.empty(); } 26 count()27 int count() const { return fDeque.count(); } 28 top()29 const T& top() const { 30 SkASSERT(fTop); 31 return *fTop; 32 } 33 top()34 T& top() { 35 SkASSERT(fTop); 36 return *fTop; 37 } 38 push_raw()39 T* push_raw() { return (T*)fDeque.push_back(); } push()40 T& push() { 41 fTop = this->push_raw(); 42 new (fTop) T(); 43 return *fTop; 44 } push(const T & src)45 T& push(const T& src) { 46 fTop = this->push_raw(); 47 new (fTop) T(src); 48 return *fTop; 49 } 50 pop()51 void pop() { 52 fTop->~T(); 53 fDeque.pop_back(); 54 fTop = fDeque.empty() ? nullptr : (T*)fDeque.back(); 55 } 56 57 private: 58 SkDeque fDeque; 59 T* fTop; 60 }; 61 62 class SkRasterClipStack : SkNoncopyable { 63 int fCounter = 0; 64 public: SkRasterClipStack(int width,int height)65 SkRasterClipStack(int width, int height) 66 : fStack(fStorage, sizeof(fStorage)) 67 , fRootBounds(SkIRect::MakeWH(width, height)) 68 { 69 Rec& rec = fStack.push(); 70 rec.fRC.setRect(fRootBounds); 71 rec.fDeferredCount = 0; 72 SkASSERT(fStack.count() == 1); 73 } 74 setNewSize(int w,int h)75 void setNewSize(int w, int h) { 76 fRootBounds.setXYWH(0, 0, w, h); 77 78 SkASSERT(fStack.count() == 1); 79 Rec& rec = fStack.top(); 80 SkASSERT(rec.fDeferredCount == 0); 81 rec.fRC.setRect(fRootBounds); 82 } 83 rc()84 const SkRasterClip& rc() const { return fStack.top().fRC; } 85 save()86 void save() { 87 fCounter += 1; 88 SkASSERT(fStack.top().fDeferredCount >= 0); 89 fStack.top().fDeferredCount += 1; 90 } 91 restore()92 void restore() { 93 fCounter -= 1; SkASSERT(fCounter >= 0); 94 if (--fStack.top().fDeferredCount < 0) { 95 SkASSERT(fStack.top().fDeferredCount == -1); 96 SkASSERT(fStack.count() > 1); 97 fStack.pop(); 98 } 99 } 100 clipRect(const SkMatrix & ctm,const SkRect & rect,SkClipOp op,bool aa)101 void clipRect(const SkMatrix& ctm, const SkRect& rect, SkClipOp op, bool aa) { 102 this->writable_rc().op(rect, ctm, fRootBounds, (SkRegion::Op)op, aa); 103 this->trimIfExpanding(op); 104 this->validate(); 105 } 106 clipRRect(const SkMatrix & ctm,const SkRRect & rrect,SkClipOp op,bool aa)107 void clipRRect(const SkMatrix& ctm, const SkRRect& rrect, SkClipOp op, bool aa) { 108 this->writable_rc().op(rrect, ctm, fRootBounds, (SkRegion::Op)op, aa); 109 this->trimIfExpanding(op); 110 this->validate(); 111 } 112 clipPath(const SkMatrix & ctm,const SkPath & path,SkClipOp op,bool aa)113 void clipPath(const SkMatrix& ctm, const SkPath& path, SkClipOp op, bool aa) { 114 this->writable_rc().op(path, ctm, fRootBounds, (SkRegion::Op)op, aa); 115 this->trimIfExpanding(op); 116 this->validate(); 117 } 118 clipRegion(const SkRegion & rgn,SkClipOp op)119 void clipRegion(const SkRegion& rgn, SkClipOp op) { 120 this->writable_rc().op(rgn, (SkRegion::Op)op); 121 this->trimIfExpanding(op); 122 this->validate(); 123 } 124 setDeviceClipRestriction(SkIRect * mutableClipRestriction)125 void setDeviceClipRestriction(SkIRect* mutableClipRestriction) { 126 this->writable_rc().setDeviceClipRestriction(mutableClipRestriction); 127 } 128 validate()129 void validate() const { 130 #ifdef SK_DEBUG 131 const SkRasterClip& clip = this->rc(); 132 if (fRootBounds.isEmpty()) { 133 SkASSERT(clip.isEmpty()); 134 } else if (!clip.isEmpty()) { 135 SkASSERT(fRootBounds.contains(clip.getBounds())); 136 } 137 #endif 138 } 139 140 private: 141 struct Rec { 142 SkRasterClip fRC; 143 int fDeferredCount; // 0 for a "normal" entry 144 }; 145 146 enum { 147 ELEM_COUNT = 16, 148 PTR_COUNT = ELEM_COUNT * sizeof(Rec) / sizeof(void*) 149 }; 150 void* fStorage[PTR_COUNT]; 151 SkTStack<Rec> fStack; 152 SkIRect fRootBounds; 153 writable_rc()154 SkRasterClip& writable_rc() { 155 SkASSERT(fStack.top().fDeferredCount >= 0); 156 if (fStack.top().fDeferredCount > 0) { 157 fStack.top().fDeferredCount -= 1; 158 fStack.push(fStack.top()); 159 fStack.top().fDeferredCount = 0; 160 } 161 return fStack.top().fRC; 162 } 163 trimIfExpanding(SkClipOp op)164 void trimIfExpanding(SkClipOp op) { 165 if ((int)op > (int)SkClipOp::kIntersect) { 166 Rec& rec = fStack.top(); 167 SkASSERT(rec.fDeferredCount == 0); 168 rec.fRC.op(fRootBounds, SkRegion::kIntersect_Op); 169 } 170 } 171 }; 172 173 #endif 174