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 "include/core/SkClipOp.h" 12 #include "src/core/SkRasterClip.h" 13 #include "src/core/SkScan.h" 14 #include "src/core/SkTBlockList.h" 15 16 class SkRasterClipStack : SkNoncopyable { 17 public: SkRasterClipStack(int width,int height)18 SkRasterClipStack(int width, int height) 19 : fRootBounds(SkIRect::MakeWH(width, height)) 20 , fDisableAA(SkScan::DowngradeClipAA(fRootBounds)) { 21 fStack.emplace_back(SkRasterClip(fRootBounds)); 22 SkASSERT(fStack.count() == 1); 23 } 24 setNewSize(int w,int h)25 void setNewSize(int w, int h) { 26 fRootBounds.setXYWH(0, 0, w, h); 27 28 SkASSERT(fStack.count() == 1); 29 Rec& rec = fStack.back(); 30 SkASSERT(rec.fDeferredCount == 0); 31 rec.fRC.setRect(fRootBounds); 32 } 33 rc()34 const SkRasterClip& rc() const { return fStack.back().fRC; } 35 save()36 void save() { 37 SkDEBUGCODE(fCounter += 1); 38 SkASSERT(fStack.back().fDeferredCount >= 0); 39 fStack.back().fDeferredCount += 1; 40 } 41 restore()42 void restore() { 43 SkDEBUGCODE(fCounter -= 1); 44 SkASSERT(fCounter >= 0); 45 46 if (--fStack.back().fDeferredCount < 0) { 47 SkASSERT(fStack.back().fDeferredCount == -1); 48 SkASSERT(fStack.count() > 1); 49 fStack.pop_back(); 50 } 51 } 52 clipRect(const SkMatrix & ctm,const SkRect & rect,SkClipOp op,bool aa)53 void clipRect(const SkMatrix& ctm, const SkRect& rect, SkClipOp op, bool aa) { 54 this->writable_rc().op(rect, ctm, op, this->finalAA(aa)); 55 this->validate(); 56 } 57 clipRRect(const SkMatrix & ctm,const SkRRect & rrect,SkClipOp op,bool aa)58 void clipRRect(const SkMatrix& ctm, const SkRRect& rrect, SkClipOp op, bool aa) { 59 this->writable_rc().op(rrect, ctm, op, this->finalAA(aa)); 60 this->validate(); 61 } 62 clipPath(const SkMatrix & ctm,const SkPath & path,SkClipOp op,bool aa)63 void clipPath(const SkMatrix& ctm, const SkPath& path, SkClipOp op, bool aa) { 64 this->writable_rc().op(path, ctm, op, this->finalAA(aa)); 65 this->validate(); 66 } 67 clipShader(sk_sp<SkShader> sh)68 void clipShader(sk_sp<SkShader> sh) { 69 this->writable_rc().op(std::move(sh)); 70 this->validate(); 71 } 72 clipRegion(const SkRegion & rgn,SkClipOp op)73 void clipRegion(const SkRegion& rgn, SkClipOp op) { 74 this->writable_rc().op(rgn, op); 75 this->validate(); 76 } 77 replaceClip(const SkIRect & rect)78 void replaceClip(const SkIRect& rect) { 79 SkIRect devRect = rect; 80 if (!devRect.intersect(fRootBounds)) { 81 this->writable_rc().setEmpty(); 82 } else { 83 this->writable_rc().setRect(devRect); 84 } 85 } 86 validate()87 void validate() const { 88 #ifdef SK_DEBUG 89 const SkRasterClip& clip = this->rc(); 90 if (fRootBounds.isEmpty()) { 91 SkASSERT(clip.isEmpty()); 92 } else if (!clip.isEmpty()) { 93 SkASSERT(fRootBounds.contains(clip.getBounds())); 94 } 95 #endif 96 } 97 98 private: 99 struct Rec { 100 SkRasterClip fRC; 101 int fDeferredCount; // 0 for a "normal" entry 102 RecRec103 Rec(const SkRasterClip& rc) : fRC(rc), fDeferredCount(0) {} 104 }; 105 106 SkTBlockList<Rec, 16> fStack; 107 SkIRect fRootBounds; 108 bool fDisableAA; 109 SkDEBUGCODE(int fCounter = 0); 110 writable_rc()111 SkRasterClip& writable_rc() { 112 SkASSERT(fStack.back().fDeferredCount >= 0); 113 if (fStack.back().fDeferredCount > 0) { 114 fStack.back().fDeferredCount -= 1; 115 fStack.emplace_back(fStack.back().fRC); 116 } 117 return fStack.back().fRC; 118 } 119 finalAA(bool aa)120 bool finalAA(bool aa) const { return aa && !fDisableAA; } 121 }; 122 123 #endif 124