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