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