xref: /aosp_15_r20/external/skia/src/core/SkRasterClip.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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