SkClipStack.cpp revision 8887ede82465687355c7a1c51e4553e99b2fb15a
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 bool operator==(const Rec& b) const { 31 if (fSaveCount != b.fSaveCount || fOp != b.fOp || fState != b.fState) { 32 return false; 33 } 34 switch (fState) { 35 case kEmpty_State: 36 return true; 37 case kRect_State: 38 return fRect == b.fRect; 39 case kPath_State: 40 return fPath == b.fPath; 41 } 42 return false; // Silence the compiler. 43 } 44 45 bool operator!=(const Rec& b) const { 46 return !(*this == b); 47 } 48 49 50 /** 51 * Returns true if this Rec can be intersected in place with a new clip 52 */ 53 bool canBeIntersected(int saveCount, SkRegion::Op op) const { 54 if (kEmpty_State == fState && ( 55 SkRegion::kDifference_Op == op || 56 SkRegion::kIntersect_Op == op)) { 57 return true; 58 } 59 return fSaveCount == saveCount && 60 SkRegion::kIntersect_Op == fOp && 61 SkRegion::kIntersect_Op == op; 62 } 63}; 64 65SkClipStack::SkClipStack() : fDeque(sizeof(Rec)) { 66 fSaveCount = 0; 67} 68 69SkClipStack::SkClipStack(const SkClipStack& b) : fDeque(sizeof(Rec)) { 70 *this = b; 71} 72 73SkClipStack& SkClipStack::operator=(const SkClipStack& b) { 74 if (this == &b) { 75 return *this; 76 } 77 reset(); 78 79 fSaveCount = b.fSaveCount; 80 SkDeque::F2BIter recIter(b.fDeque); 81 for (const Rec* rec = (const Rec*)recIter.next(); 82 rec != NULL; 83 rec = (const Rec*)recIter.next()) { 84 new (fDeque.push_back()) Rec(*rec); 85 } 86 87 return *this; 88} 89 90bool SkClipStack::operator==(const SkClipStack& b) const { 91 if (fSaveCount != b.fSaveCount || fDeque.count() != b.fDeque.count()) { 92 return false; 93 } 94 SkDeque::F2BIter myIter(fDeque); 95 SkDeque::F2BIter bIter(b.fDeque); 96 const Rec* myRec = (const Rec*)myIter.next(); 97 const Rec* bRec = (const Rec*)bIter.next(); 98 99 while (myRec != NULL && bRec != NULL) { 100 if (*myRec != *bRec) { 101 return false; 102 } 103 myRec = (const Rec*)myIter.next(); 104 bRec = (const Rec*)bIter.next(); 105 } 106 return myRec == NULL && bRec == NULL; 107} 108 109void SkClipStack::reset() { 110 // don't have a reset() on SkDeque, so fake it here 111 fDeque.~SkDeque(); 112 new (&fDeque) SkDeque(sizeof(Rec)); 113 114 fSaveCount = 0; 115} 116 117void SkClipStack::save() { 118 fSaveCount += 1; 119} 120 121void SkClipStack::restore() { 122 fSaveCount -= 1; 123 while (!fDeque.empty()) { 124 Rec* rec = (Rec*)fDeque.back(); 125 if (rec->fSaveCount <= fSaveCount) { 126 break; 127 } 128 rec->~Rec(); 129 fDeque.pop_back(); 130 } 131} 132 133void SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op) { 134 Rec* rec = (Rec*)fDeque.back(); 135 if (rec && rec->canBeIntersected(fSaveCount, op)) { 136 switch (rec->fState) { 137 case Rec::kEmpty_State: 138 return; 139 case Rec::kRect_State: 140 if (!rec->fRect.intersect(rect)) { 141 rec->fState = Rec::kEmpty_State; 142 } 143 return; 144 case Rec::kPath_State: 145 if (!SkRect::Intersects(rec->fPath.getBounds(), rect)) { 146 rec->fState = Rec::kEmpty_State; 147 return; 148 } 149 break; 150 } 151 } 152 new (fDeque.push_back()) Rec(fSaveCount, rect, op); 153} 154 155void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op) { 156 Rec* rec = (Rec*)fDeque.back(); 157 if (rec && rec->canBeIntersected(fSaveCount, op)) { 158 const SkRect& pathBounds = path.getBounds(); 159 switch (rec->fState) { 160 case Rec::kEmpty_State: 161 return; 162 case Rec::kRect_State: 163 if (!SkRect::Intersects(rec->fRect, pathBounds)) { 164 rec->fState = Rec::kEmpty_State; 165 return; 166 } 167 break; 168 case Rec::kPath_State: 169 if (!SkRect::Intersects(rec->fPath.getBounds(), pathBounds)) { 170 rec->fState = Rec::kEmpty_State; 171 return; 172 } 173 break; 174 } 175 } 176 new (fDeque.push_back()) Rec(fSaveCount, path, op); 177} 178 179/////////////////////////////////////////////////////////////////////////////// 180 181SkClipStack::B2FIter::B2FIter() { 182} 183 184bool operator==(const SkClipStack::B2FIter::Clip& a, 185 const SkClipStack::B2FIter::Clip& b) { 186 return a.fOp == b.fOp && 187 ((a.fRect == NULL && b.fRect == NULL) || *a.fRect == *b.fRect) && 188 ((a.fPath == NULL && b.fPath == NULL) || *a.fPath == *b.fPath); 189} 190 191bool operator!=(const SkClipStack::B2FIter::Clip& a, 192 const SkClipStack::B2FIter::Clip& b) { 193 return !(a == b); 194} 195 196SkClipStack::B2FIter::B2FIter(const SkClipStack& stack) { 197 this->reset(stack); 198} 199 200const SkClipStack::B2FIter::Clip* SkClipStack::B2FIter::next() { 201 const SkClipStack::Rec* rec = (const SkClipStack::Rec*)fIter.next(); 202 if (NULL == rec) { 203 return NULL; 204 } 205 206 switch (rec->fState) { 207 case SkClipStack::Rec::kEmpty_State: 208 fClip.fRect = NULL; 209 fClip.fPath = NULL; 210 break; 211 case SkClipStack::Rec::kRect_State: 212 fClip.fRect = &rec->fRect; 213 fClip.fPath = NULL; 214 break; 215 case SkClipStack::Rec::kPath_State: 216 fClip.fRect = NULL; 217 fClip.fPath = &rec->fPath; 218 break; 219 } 220 fClip.fOp = rec->fOp; 221 return &fClip; 222} 223 224void SkClipStack::B2FIter::reset(const SkClipStack& stack) { 225 fIter.reset(stack.fDeque); 226} 227