SkRasterClip.cpp revision 420f74fa720272b1164eae55d7b6c10e07d41601
1/* 2 * Copyright 2010 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#include "SkRasterClip.h" 9 10 11SkRasterClip::SkRasterClip() { 12 fIsBW = true; 13 fIsEmpty = true; 14 fIsRect = false; 15 SkDEBUGCODE(this->validate();) 16} 17 18SkRasterClip::SkRasterClip(const SkRasterClip& src) { 19 AUTO_RASTERCLIP_VALIDATE(src); 20 21 fIsBW = src.fIsBW; 22 if (fIsBW) { 23 fBW = src.fBW; 24 } else { 25 fAA = src.fAA; 26 } 27 28 fIsEmpty = src.isEmpty(); 29 fIsRect = src.isRect(); 30 SkDEBUGCODE(this->validate();) 31} 32 33SkRasterClip::SkRasterClip(const SkIRect& bounds) : fBW(bounds) { 34 fIsBW = true; 35 fIsEmpty = this->computeIsEmpty(); // bounds might be empty, so compute 36 fIsRect = !fIsEmpty; 37 SkDEBUGCODE(this->validate();) 38} 39 40SkRasterClip::~SkRasterClip() { 41 SkDEBUGCODE(this->validate();) 42} 43 44bool SkRasterClip::isComplex() const { 45 return fIsBW ? fBW.isComplex() : !fAA.isEmpty(); 46} 47 48const SkIRect& SkRasterClip::getBounds() const { 49 return fIsBW ? fBW.getBounds() : fAA.getBounds(); 50} 51 52bool SkRasterClip::setEmpty() { 53 AUTO_RASTERCLIP_VALIDATE(*this); 54 55 fIsBW = true; 56 fBW.setEmpty(); 57 fAA.setEmpty(); 58 fIsEmpty = true; 59 fIsRect = false; 60 return false; 61} 62 63bool SkRasterClip::setRect(const SkIRect& rect) { 64 AUTO_RASTERCLIP_VALIDATE(*this); 65 66 fIsBW = true; 67 fAA.setEmpty(); 68 fIsRect = fBW.setRect(rect); 69 fIsEmpty = !fIsRect; 70 return fIsRect; 71} 72 73bool SkRasterClip::setPath(const SkPath& path, const SkRegion& clip, bool doAA) { 74 AUTO_RASTERCLIP_VALIDATE(*this); 75 76 if (this->isBW() && !doAA) { 77 (void)fBW.setPath(path, clip); 78 } else { 79 // TODO: since we are going to over-write fAA completely (aren't we?) 80 // we should just clear our BW data (if any) and set fIsAA=true 81 if (this->isBW()) { 82 this->convertToAA(); 83 } 84 (void)fAA.setPath(path, &clip, doAA); 85 } 86 return this->updateCacheAndReturnNonEmpty(); 87} 88 89bool SkRasterClip::setPath(const SkPath& path, const SkIRect& clip, bool doAA) { 90 SkRegion tmp; 91 tmp.setRect(clip); 92 return this->setPath(path, tmp, doAA); 93} 94 95bool SkRasterClip::setPath(const SkPath& path, const SkRasterClip& clip, 96 bool doAA) { 97 if (clip.isBW()) { 98 return this->setPath(path, clip.bwRgn(), doAA); 99 } else { 100 SkRegion tmp; 101 tmp.setRect(clip.getBounds()); 102 if (!this->setPath(path, clip, doAA)) { 103 return false; 104 } 105 return this->op(clip, SkRegion::kIntersect_Op); 106 } 107} 108 109bool SkRasterClip::op(const SkIRect& rect, SkRegion::Op op) { 110 AUTO_RASTERCLIP_VALIDATE(*this); 111 112 fIsBW ? fBW.op(rect, op) : fAA.op(rect, op); 113 return this->updateCacheAndReturnNonEmpty(); 114} 115 116bool SkRasterClip::op(const SkRegion& rgn, SkRegion::Op op) { 117 AUTO_RASTERCLIP_VALIDATE(*this); 118 119 if (fIsBW) { 120 (void)fBW.op(rgn, op); 121 } else { 122 SkAAClip tmp; 123 tmp.setRegion(rgn); 124 (void)fAA.op(tmp, op); 125 } 126 return this->updateCacheAndReturnNonEmpty(); 127} 128 129bool SkRasterClip::op(const SkRasterClip& clip, SkRegion::Op op) { 130 AUTO_RASTERCLIP_VALIDATE(*this); 131 clip.validate(); 132 133 if (this->isBW() && clip.isBW()) { 134 (void)fBW.op(clip.fBW, op); 135 } else { 136 SkAAClip tmp; 137 const SkAAClip* other; 138 139 if (this->isBW()) { 140 this->convertToAA(); 141 } 142 if (clip.isBW()) { 143 tmp.setRegion(clip.bwRgn()); 144 other = &tmp; 145 } else { 146 other = &clip.aaRgn(); 147 } 148 (void)fAA.op(*other, op); 149 } 150 return this->updateCacheAndReturnNonEmpty(); 151} 152 153// return true if x is nearly integral (within 1/16) since that is the highest 154// precision our aa code can have. 155static bool is_integral(SkScalar x) { 156 int ix = SkScalarRoundToInt(x); 157 SkScalar sx = SkIntToScalar(ix); 158 return SkScalarAbs(sx - x) < (SK_Scalar1 / 16); 159} 160 161bool SkRasterClip::op(const SkRect& r, SkRegion::Op op, bool doAA) { 162 AUTO_RASTERCLIP_VALIDATE(*this); 163 164 if (fIsBW && doAA) { 165 // check that the rect really needs aa 166 if (is_integral(r.fLeft) && is_integral(r.fTop) && 167 is_integral(r.fRight) && is_integral(r.fBottom)) { 168 doAA = false; 169 } 170 } 171 172 if (fIsBW && !doAA) { 173 SkIRect ir; 174 r.round(&ir); 175 (void)fBW.op(ir, op); 176 } else { 177 if (fIsBW) { 178 this->convertToAA(); 179 } 180 (void)fAA.op(r, op, doAA); 181 } 182 return this->updateCacheAndReturnNonEmpty(); 183} 184 185void SkRasterClip::translate(int dx, int dy, SkRasterClip* dst) const { 186 if (NULL == dst) { 187 return; 188 } 189 190 AUTO_RASTERCLIP_VALIDATE(*this); 191 192 if (this->isEmpty()) { 193 dst->setEmpty(); 194 return; 195 } 196 if (0 == (dx | dy)) { 197 *dst = *this; 198 return; 199 } 200 201 dst->fIsBW = fIsBW; 202 if (fIsBW) { 203 fBW.translate(dx, dy, &dst->fBW); 204 dst->fAA.setEmpty(); 205 } else { 206 fAA.translate(dx, dy, &dst->fAA); 207 dst->fBW.setEmpty(); 208 } 209 dst->updateCacheAndReturnNonEmpty(); 210} 211 212bool SkRasterClip::quickContains(const SkIRect& ir) const { 213 return fIsBW ? fBW.quickContains(ir) : fAA.quickContains(ir); 214} 215 216/////////////////////////////////////////////////////////////////////////////// 217 218const SkRegion& SkRasterClip::forceGetBW() { 219 AUTO_RASTERCLIP_VALIDATE(*this); 220 221 if (!fIsBW) { 222 fBW.setRect(fAA.getBounds()); 223 } 224 return fBW; 225} 226 227void SkRasterClip::convertToAA() { 228 AUTO_RASTERCLIP_VALIDATE(*this); 229 230 SkASSERT(fIsBW); 231 fAA.setRegion(fBW); 232 fIsBW = false; 233 (void)this->updateCacheAndReturnNonEmpty(); 234} 235 236#ifdef SK_DEBUG 237void SkRasterClip::validate() const { 238 // can't ever assert that fBW is empty, since we may have called forceGetBW 239 if (fIsBW) { 240 SkASSERT(fAA.isEmpty()); 241 } 242 243 fBW.validate(); 244 fAA.validate(); 245 246 SkASSERT(this->computeIsEmpty() == fIsEmpty); 247 SkASSERT(this->computeIsRect() == fIsRect); 248} 249#endif 250 251/////////////////////////////////////////////////////////////////////////////// 252 253SkAAClipBlitterWrapper::SkAAClipBlitterWrapper() { 254 SkDEBUGCODE(fClipRgn = NULL;) 255 SkDEBUGCODE(fBlitter = NULL;) 256} 257 258SkAAClipBlitterWrapper::SkAAClipBlitterWrapper(const SkRasterClip& clip, 259 SkBlitter* blitter) { 260 this->init(clip, blitter); 261} 262 263SkAAClipBlitterWrapper::SkAAClipBlitterWrapper(const SkAAClip* aaclip, 264 SkBlitter* blitter) { 265 SkASSERT(blitter); 266 SkASSERT(aaclip); 267 fBWRgn.setRect(aaclip->getBounds()); 268 fAABlitter.init(blitter, aaclip); 269 // now our return values 270 fClipRgn = &fBWRgn; 271 fBlitter = &fAABlitter; 272} 273 274void SkAAClipBlitterWrapper::init(const SkRasterClip& clip, SkBlitter* blitter) { 275 SkASSERT(blitter); 276 if (clip.isBW()) { 277 fClipRgn = &clip.bwRgn(); 278 fBlitter = blitter; 279 } else { 280 const SkAAClip& aaclip = clip.aaRgn(); 281 fBWRgn.setRect(aaclip.getBounds()); 282 fAABlitter.init(blitter, &aaclip); 283 // now our return values 284 fClipRgn = &fBWRgn; 285 fBlitter = &fAABlitter; 286 } 287} 288 289