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