SkClipStack.cpp revision 5c3d1471e4908706cd053a5e2ea9ded3a6c2eaeb
1#include "SkClipStack.h" 2#include "SkPath.h" 3#include <new> 4 5struct SkClipStack::Rec { 6 enum State { 7 kEmpty_State, 8 kRect_State, 9 kPath_State 10 }; 11 12 SkPath fPath; 13 SkRect fRect; 14 int fSaveCount; 15 SkRegion::Op fOp; 16 State fState; 17 18 Rec(int saveCount, const SkRect& rect, SkRegion::Op op) : fRect(rect) { 19 fSaveCount = saveCount; 20 fOp = op; 21 fState = kRect_State; 22 } 23 24 Rec(int saveCount, const SkPath& path, SkRegion::Op op) : fPath(path) { 25 fSaveCount = saveCount; 26 fOp = op; 27 fState = kPath_State; 28 } 29 30 /** 31 * Returns true if this Rec can be intersected in place with a new clip 32 */ 33 bool canBeIntersected(int saveCount, SkRegion::Op op) const { 34 if (kEmpty_State == fState) { 35 return true; 36 } 37 return fSaveCount == saveCount && 38 SkRegion::kIntersect_Op == fOp && 39 SkRegion::kIntersect_Op == op; 40 } 41}; 42 43SkClipStack::SkClipStack() : fDeque(sizeof(Rec)) { 44 fSaveCount = 0; 45} 46 47void SkClipStack::reset() { 48 // don't have a reset() on SkDeque, so fake it here 49 fDeque.~SkDeque(); 50 new (&fDeque) SkDeque(sizeof(Rec)); 51 52 fSaveCount = 0; 53} 54 55void SkClipStack::save() { 56 fSaveCount += 1; 57} 58 59void SkClipStack::restore() { 60 fSaveCount -= 1; 61 while (!fDeque.empty()) { 62 Rec* rec = (Rec*)fDeque.back(); 63 if (rec->fSaveCount <= fSaveCount) { 64 break; 65 } 66 rec->~Rec(); 67 fDeque.pop_back(); 68 } 69} 70 71void SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op) { 72 Rec* rec = (Rec*)fDeque.back(); 73 if (rec && rec->canBeIntersected(fSaveCount, op)) { 74 switch (rec->fState) { 75 case Rec::kEmpty_State: 76 return; 77 case Rec::kRect_State: 78 if (!rec->fRect.intersect(rect)) { 79 rec->fState = Rec::kEmpty_State; 80 } 81 return; 82 case Rec::kPath_State: 83 if (!SkRect::Intersects(rec->fPath.getBounds(), rect)) { 84 rec->fState = Rec::kEmpty_State; 85 return; 86 } 87 break; 88 } 89 } 90 new (fDeque.push_back()) Rec(fSaveCount, rect, op); 91} 92 93void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op) { 94 Rec* rec = (Rec*)fDeque.back(); 95 if (rec && rec->canBeIntersected(fSaveCount, op)) { 96 const SkRect& pathBounds = path.getBounds(); 97 switch (rec->fState) { 98 case Rec::kEmpty_State: 99 return; 100 case Rec::kRect_State: 101 if (!SkRect::Intersects(rec->fRect, pathBounds)) { 102 rec->fState = Rec::kEmpty_State; 103 return; 104 } 105 break; 106 case Rec::kPath_State: 107 if (!SkRect::Intersects(rec->fPath.getBounds(), pathBounds)) { 108 rec->fState = Rec::kEmpty_State; 109 return; 110 } 111 break; 112 } 113 } 114 new (fDeque.push_back()) Rec(fSaveCount, path, op); 115} 116 117/////////////////////////////////////////////////////////////////////////////// 118 119SkClipStack::B2FIter::B2FIter(const SkClipStack& stack) : fIter(stack.fDeque) { 120} 121 122const SkClipStack::B2FIter::Clip* SkClipStack::B2FIter::next() { 123 const SkClipStack::Rec* rec = (const SkClipStack::Rec*)fIter.next(); 124 if (NULL == rec) { 125 return NULL; 126 } 127 128 switch (rec->fState) { 129 case SkClipStack::Rec::kEmpty_State: 130 fClip.fRect = NULL; 131 fClip.fPath = NULL; 132 break; 133 case SkClipStack::Rec::kRect_State: 134 fClip.fRect = &rec->fRect; 135 fClip.fPath = NULL; 136 break; 137 case SkClipStack::Rec::kPath_State: 138 fClip.fRect = NULL; 139 fClip.fPath = &rec->fPath; 140 break; 141 } 142 fClip.fOp = rec->fOp; 143 return &fClip; 144} 145