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