• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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