1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 #include "SkClipStack.h" 9 #include "SkPath.h" 10 #include <new> 11 12 struct SkClipStack::Rec { 13 enum State { 14 kEmpty_State, 15 kRect_State, 16 kPath_State 17 }; 18 19 SkPath fPath; 20 SkRect fRect; 21 int fSaveCount; 22 SkRegion::Op fOp; 23 State fState; 24 bool fDoAA; 25 26 Rec(int saveCount, const SkRect& rect, SkRegion::Op op, bool doAA) : fRect(rect) { 27 fSaveCount = saveCount; 28 fOp = op; 29 fState = kRect_State; 30 fDoAA = doAA; 31 } 32 33 Rec(int saveCount, const SkPath& path, SkRegion::Op op, bool doAA) : fPath(path) { 34 fRect.setEmpty(); 35 fSaveCount = saveCount; 36 fOp = op; 37 fState = kPath_State; 38 fDoAA = doAA; 39 } 40 41 bool operator==(const Rec& b) const { 42 if (fSaveCount != b.fSaveCount || fOp != b.fOp || fState != b.fState || 43 fDoAA != b.fDoAA) { 44 return false; 45 } 46 switch (fState) { 47 case kEmpty_State: 48 return true; 49 case kRect_State: 50 return fRect == b.fRect; 51 case kPath_State: 52 return fPath == b.fPath; 53 } 54 return false; // Silence the compiler. 55 } 56 57 bool operator!=(const Rec& b) const { 58 return !(*this == b); 59 } 60 61 62 /** 63 * Returns true if this Rec can be intersected in place with a new clip 64 */ 65 bool canBeIntersected(int saveCount, SkRegion::Op op) const { 66 if (kEmpty_State == fState && ( 67 SkRegion::kDifference_Op == op || 68 SkRegion::kIntersect_Op == op)) { 69 return true; 70 } 71 return fSaveCount == saveCount && 72 SkRegion::kIntersect_Op == fOp && 73 SkRegion::kIntersect_Op == op; 74 } 75 }; 76 77 SkClipStack::SkClipStack() : fDeque(sizeof(Rec)) { 78 fSaveCount = 0; 79 } 80 81 SkClipStack::SkClipStack(const SkClipStack& b) : fDeque(sizeof(Rec)) { 82 *this = b; 83 } 84 85 SkClipStack& SkClipStack::operator=(const SkClipStack& b) { 86 if (this == &b) { 87 return *this; 88 } 89 reset(); 90 91 fSaveCount = b.fSaveCount; 92 SkDeque::F2BIter recIter(b.fDeque); 93 for (const Rec* rec = (const Rec*)recIter.next(); 94 rec != NULL; 95 rec = (const Rec*)recIter.next()) { 96 new (fDeque.push_back()) Rec(*rec); 97 } 98 99 return *this; 100 } 101 102 bool SkClipStack::operator==(const SkClipStack& b) const { 103 if (fSaveCount != b.fSaveCount || fDeque.count() != b.fDeque.count()) { 104 return false; 105 } 106 SkDeque::F2BIter myIter(fDeque); 107 SkDeque::F2BIter bIter(b.fDeque); 108 const Rec* myRec = (const Rec*)myIter.next(); 109 const Rec* bRec = (const Rec*)bIter.next(); 110 111 while (myRec != NULL && bRec != NULL) { 112 if (*myRec != *bRec) { 113 return false; 114 } 115 myRec = (const Rec*)myIter.next(); 116 bRec = (const Rec*)bIter.next(); 117 } 118 return myRec == NULL && bRec == NULL; 119 } 120 121 void SkClipStack::reset() { 122 // don't have a reset() on SkDeque, so fake it here 123 fDeque.~SkDeque(); 124 new (&fDeque) SkDeque(sizeof(Rec)); 125 126 fSaveCount = 0; 127 } 128 129 void SkClipStack::save() { 130 fSaveCount += 1; 131 } 132 133 void SkClipStack::restore() { 134 fSaveCount -= 1; 135 while (!fDeque.empty()) { 136 Rec* rec = (Rec*)fDeque.back(); 137 if (rec->fSaveCount <= fSaveCount) { 138 break; 139 } 140 rec->~Rec(); 141 fDeque.pop_back(); 142 } 143 } 144 145 void SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op, bool doAA) { 146 Rec* rec = (Rec*)fDeque.back(); 147 if (rec && rec->canBeIntersected(fSaveCount, op)) { 148 switch (rec->fState) { 149 case Rec::kEmpty_State: 150 return; 151 case Rec::kRect_State: 152 if (!rec->fRect.intersect(rect)) { 153 rec->fState = Rec::kEmpty_State; 154 } 155 return; 156 case Rec::kPath_State: 157 if (!SkRect::Intersects(rec->fPath.getBounds(), rect)) { 158 rec->fState = Rec::kEmpty_State; 159 return; 160 } 161 break; 162 } 163 } 164 new (fDeque.push_back()) Rec(fSaveCount, rect, op, doAA); 165 } 166 167 void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) { 168 Rec* rec = (Rec*)fDeque.back(); 169 if (rec && rec->canBeIntersected(fSaveCount, op)) { 170 const SkRect& pathBounds = path.getBounds(); 171 switch (rec->fState) { 172 case Rec::kEmpty_State: 173 return; 174 case Rec::kRect_State: 175 if (!SkRect::Intersects(rec->fRect, pathBounds)) { 176 rec->fState = Rec::kEmpty_State; 177 return; 178 } 179 break; 180 case Rec::kPath_State: 181 if (!SkRect::Intersects(rec->fPath.getBounds(), pathBounds)) { 182 rec->fState = Rec::kEmpty_State; 183 return; 184 } 185 break; 186 } 187 } 188 new (fDeque.push_back()) Rec(fSaveCount, path, op, doAA); 189 } 190 191 /////////////////////////////////////////////////////////////////////////////// 192 193 SkClipStack::B2FIter::B2FIter() { 194 } 195 196 bool operator==(const SkClipStack::B2FIter::Clip& a, 197 const SkClipStack::B2FIter::Clip& b) { 198 return a.fOp == b.fOp && a.fDoAA == b.fDoAA && 199 ((a.fRect == NULL && b.fRect == NULL) || 200 (a.fRect != NULL && b.fRect != NULL && *a.fRect == *b.fRect)) && 201 ((a.fPath == NULL && b.fPath == NULL) || 202 (a.fPath != NULL && b.fPath != NULL && *a.fPath == *b.fPath)); 203 } 204 205 bool operator!=(const SkClipStack::B2FIter::Clip& a, 206 const SkClipStack::B2FIter::Clip& b) { 207 return !(a == b); 208 } 209 210 SkClipStack::B2FIter::B2FIter(const SkClipStack& stack) { 211 this->reset(stack); 212 } 213 214 const SkClipStack::B2FIter::Clip* SkClipStack::B2FIter::next() { 215 const SkClipStack::Rec* rec = (const SkClipStack::Rec*)fIter.next(); 216 if (NULL == rec) { 217 return NULL; 218 } 219 220 switch (rec->fState) { 221 case SkClipStack::Rec::kEmpty_State: 222 fClip.fRect = NULL; 223 fClip.fPath = NULL; 224 break; 225 case SkClipStack::Rec::kRect_State: 226 fClip.fRect = &rec->fRect; 227 fClip.fPath = NULL; 228 break; 229 case SkClipStack::Rec::kPath_State: 230 fClip.fRect = NULL; 231 fClip.fPath = &rec->fPath; 232 break; 233 } 234 fClip.fOp = rec->fOp; 235 fClip.fDoAA = rec->fDoAA; 236 return &fClip; 237 } 238 239 void SkClipStack::B2FIter::reset(const SkClipStack& stack) { 240 fIter.reset(stack.fDeque); 241 } 242