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 #ifndef SkRasterClip_DEFINED 9 #define SkRasterClip_DEFINED 10 11 #include "SkRegion.h" 12 #include "SkAAClip.h" 13 14 class SkRRect; 15 16 class SkRasterClip { 17 public: 18 SkRasterClip(bool forceConservativeRects = false); 19 SkRasterClip(const SkIRect&, bool forceConservativeRects = false); 20 SkRasterClip(const SkRasterClip&); 21 ~SkRasterClip(); 22 23 bool isForceConservativeRects() const { return fForceConservativeRects; } 24 25 bool isBW() const { return fIsBW; } 26 bool isAA() const { return !fIsBW; } 27 const SkRegion& bwRgn() const { SkASSERT(fIsBW); return fBW; } 28 const SkAAClip& aaRgn() const { SkASSERT(!fIsBW); return fAA; } 29 30 bool isEmpty() const { 31 SkASSERT(this->computeIsEmpty() == fIsEmpty); 32 return fIsEmpty; 33 } 34 35 bool isRect() const { 36 SkASSERT(this->computeIsRect() == fIsRect); 37 return fIsRect; 38 } 39 40 bool isComplex() const; 41 const SkIRect& getBounds() const; 42 43 bool setEmpty(); 44 bool setRect(const SkIRect&); 45 46 bool op(const SkIRect&, SkRegion::Op); 47 bool op(const SkRegion&, SkRegion::Op); 48 bool op(const SkRect&, const SkIRect&, SkRegion::Op, bool doAA); 49 bool op(const SkRRect&, const SkIRect&, SkRegion::Op, bool doAA); 50 bool op(const SkPath&, const SkIRect&, SkRegion::Op, bool doAA); 51 52 void translate(int dx, int dy, SkRasterClip* dst) const; 53 void translate(int dx, int dy) { 54 this->translate(dx, dy, this); 55 } 56 57 bool quickContains(const SkIRect& rect) const; 58 bool quickContains(int left, int top, int right, int bottom) const { 59 return quickContains(SkIRect::MakeLTRB(left, top, right, bottom)); 60 } 61 62 /** 63 * Return true if this region is empty, or if the specified rectangle does 64 * not intersect the region. Returning false is not a guarantee that they 65 * intersect, but returning true is a guarantee that they do not. 66 */ 67 bool quickReject(const SkIRect& rect) const { 68 return !SkIRect::Intersects(this->getBounds(), rect); 69 } 70 71 // hack for SkCanvas::getTotalClip 72 const SkRegion& forceGetBW(); 73 74 #ifdef SK_DEBUG 75 void validate() const; 76 #else 77 void validate() const {} 78 #endif 79 80 private: 81 SkRegion fBW; 82 SkAAClip fAA; 83 bool fForceConservativeRects; 84 bool fIsBW; 85 // these 2 are caches based on querying the right obj based on fIsBW 86 bool fIsEmpty; 87 bool fIsRect; 88 89 bool computeIsEmpty() const { 90 return fIsBW ? fBW.isEmpty() : fAA.isEmpty(); 91 } 92 93 bool computeIsRect() const { 94 return fIsBW ? fBW.isRect() : fAA.isRect(); 95 } 96 97 bool updateCacheAndReturnNonEmpty(bool detectAARect = true) { 98 fIsEmpty = this->computeIsEmpty(); 99 100 // detect that our computed AA is really just a (hard-edged) rect 101 if (detectAARect && !fIsEmpty && !fIsBW && fAA.isRect()) { 102 fBW.setRect(fAA.getBounds()); 103 fAA.setEmpty(); // don't need this guy anymore 104 fIsBW = true; 105 } 106 107 fIsRect = this->computeIsRect(); 108 return !fIsEmpty; 109 } 110 111 void convertToAA(); 112 113 bool setPath(const SkPath& path, const SkRegion& clip, bool doAA); 114 bool setPath(const SkPath& path, const SkIRect& clip, bool doAA); 115 bool op(const SkRasterClip&, SkRegion::Op); 116 bool setConservativeRect(const SkRect& r, const SkIRect& clipR, bool isInverse); 117 }; 118 119 class SkAutoRasterClipValidate : SkNoncopyable { 120 public: 121 SkAutoRasterClipValidate(const SkRasterClip& rc) : fRC(rc) { 122 fRC.validate(); 123 } 124 ~SkAutoRasterClipValidate() { 125 fRC.validate(); 126 } 127 private: 128 const SkRasterClip& fRC; 129 }; 130 #define SkAutoRasterClipValidate(...) SK_REQUIRE_LOCAL_VAR(SkAutoRasterClipValidate) 131 132 #ifdef SK_DEBUG 133 #define AUTO_RASTERCLIP_VALIDATE(rc) SkAutoRasterClipValidate arcv(rc) 134 #else 135 #define AUTO_RASTERCLIP_VALIDATE(rc) 136 #endif 137 138 /////////////////////////////////////////////////////////////////////////////// 139 140 /** 141 * Encapsulates the logic of deciding if we need to change/wrap the blitter 142 * for aaclipping. If so, getRgn and getBlitter return modified values. If 143 * not, they return the raw blitter and (bw) clip region. 144 * 145 * We need to keep the constructor/destructor cost as small as possible, so we 146 * can freely put this guy on the stack, and not pay too much for the case when 147 * we're really BW anyways. 148 */ 149 class SkAAClipBlitterWrapper { 150 public: 151 SkAAClipBlitterWrapper(); 152 SkAAClipBlitterWrapper(const SkRasterClip&, SkBlitter*); 153 SkAAClipBlitterWrapper(const SkAAClip*, SkBlitter*); 154 155 void init(const SkRasterClip&, SkBlitter*); 156 157 const SkIRect& getBounds() const { 158 SkASSERT(fClipRgn); 159 return fClipRgn->getBounds(); 160 } 161 const SkRegion& getRgn() const { 162 SkASSERT(fClipRgn); 163 return *fClipRgn; 164 } 165 SkBlitter* getBlitter() { 166 SkASSERT(fBlitter); 167 return fBlitter; 168 } 169 170 private: 171 SkRegion fBWRgn; 172 SkAAClipBlitter fAABlitter; 173 // what we return 174 const SkRegion* fClipRgn; 175 SkBlitter* fBlitter; 176 }; 177 178 #endif 179