Line data Source code
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 SkRRect;
15 :
16 : class SkConservativeClip {
17 : SkIRect fBounds;
18 : const SkIRect* fClipRestrictionRect;
19 :
20 0 : inline void applyClipRestriction(SkRegion::Op op, SkIRect* bounds) {
21 0 : if (op >= SkRegion::kUnion_Op && fClipRestrictionRect
22 0 : && !fClipRestrictionRect->isEmpty()) {
23 0 : if (!bounds->intersect(*fClipRestrictionRect)) {
24 0 : bounds->setEmpty();
25 : }
26 : }
27 0 : }
28 :
29 : public:
30 63 : SkConservativeClip() : fBounds(SkIRect::MakeEmpty()), fClipRestrictionRect(nullptr) {}
31 :
32 406 : bool isEmpty() const { return fBounds.isEmpty(); }
33 : bool isRect() const { return true; }
34 1654 : const SkIRect& getBounds() const { return fBounds; }
35 :
36 0 : void setEmpty() { fBounds.setEmpty(); }
37 85 : void setRect(const SkIRect& r) { fBounds = r; }
38 63 : void setDeviceClipRestriction(const SkIRect* rect) {
39 63 : fClipRestrictionRect = rect;
40 63 : }
41 :
42 : void op(const SkRect&, const SkMatrix&, const SkIRect& limit, SkRegion::Op, bool isAA);
43 : void op(const SkRRect&, const SkMatrix&, const SkIRect& limit, SkRegion::Op, bool isAA);
44 : void op(const SkPath&, const SkMatrix&, const SkIRect& limit, SkRegion::Op, bool isAA);
45 : void op(const SkRegion&, SkRegion::Op);
46 : void op(const SkIRect&, SkRegion::Op);
47 : };
48 :
49 : /**
50 : * Wraps a SkRegion and SkAAClip, so we have a single object that can represent either our
51 : * BW or antialiased clips.
52 : *
53 : * This class is optimized for the raster backend of canvas, but can be expense to keep up2date,
54 : * so it supports a runtime option (force-conservative-rects) to turn it into a super-fast
55 : * rect-only tracker. The gpu backend uses this since it does not need the result (it uses
56 : * SkClipStack instead).
57 : */
58 0 : class SkRasterClip {
59 : public:
60 : SkRasterClip();
61 : SkRasterClip(const SkIRect&);
62 : SkRasterClip(const SkRegion&);
63 : SkRasterClip(const SkRasterClip&);
64 : ~SkRasterClip();
65 :
66 : // Only compares the current state. Does not compare isForceConservativeRects(), so that field
67 : // could be different but this could still return true.
68 : bool operator==(const SkRasterClip&) const;
69 : bool operator!=(const SkRasterClip& other) const {
70 : return !(*this == other);
71 : }
72 :
73 895 : bool isBW() const { return fIsBW; }
74 0 : bool isAA() const { return !fIsBW; }
75 322 : const SkRegion& bwRgn() const { SkASSERT(fIsBW); return fBW; }
76 185 : const SkAAClip& aaRgn() const { SkASSERT(!fIsBW); return fAA; }
77 :
78 2326 : bool isEmpty() const {
79 2326 : SkASSERT(this->computeIsEmpty() == fIsEmpty);
80 2326 : return fIsEmpty;
81 : }
82 :
83 648 : bool isRect() const {
84 648 : SkASSERT(this->computeIsRect() == fIsRect);
85 648 : return fIsRect;
86 : }
87 :
88 : bool isComplex() const;
89 : const SkIRect& getBounds() const;
90 :
91 : bool setEmpty();
92 : bool setRect(const SkIRect&);
93 :
94 : bool op(const SkIRect&, SkRegion::Op);
95 : bool op(const SkRegion&, SkRegion::Op);
96 : bool op(const SkRect&, const SkMatrix& matrix, const SkIRect&, SkRegion::Op, bool doAA);
97 : bool op(const SkRRect&, const SkMatrix& matrix, const SkIRect&, SkRegion::Op, bool doAA);
98 : bool op(const SkPath&, const SkMatrix& matrix, const SkIRect&, SkRegion::Op, bool doAA);
99 :
100 : void translate(int dx, int dy, SkRasterClip* dst) const;
101 : void translate(int dx, int dy) {
102 : this->translate(dx, dy, this);
103 : }
104 :
105 : bool quickContains(const SkIRect& rect) const;
106 43 : bool quickContains(int left, int top, int right, int bottom) const {
107 43 : return quickContains(SkIRect::MakeLTRB(left, top, right, bottom));
108 : }
109 :
110 : /**
111 : * Return true if this region is empty, or if the specified rectangle does
112 : * not intersect the region. Returning false is not a guarantee that they
113 : * intersect, but returning true is a guarantee that they do not.
114 : */
115 370 : bool quickReject(const SkIRect& rect) const {
116 370 : return !SkIRect::Intersects(this->getBounds(), rect);
117 : }
118 :
119 : // hack for SkCanvas::getTotalClip
120 : const SkRegion& forceGetBW();
121 :
122 : #ifdef SK_DEBUG
123 : void validate() const;
124 : #else
125 : void validate() const {}
126 : #endif
127 :
128 85 : void setDeviceClipRestriction(const SkIRect* rect) {
129 85 : fClipRestrictionRect = rect;
130 85 : }
131 :
132 : private:
133 : SkRegion fBW;
134 : SkAAClip fAA;
135 : bool fIsBW;
136 : // these 2 are caches based on querying the right obj based on fIsBW
137 : bool fIsEmpty;
138 : bool fIsRect;
139 : const SkIRect* fClipRestrictionRect = nullptr;
140 :
141 7645 : bool computeIsEmpty() const {
142 7645 : return fIsBW ? fBW.isEmpty() : fAA.isEmpty();
143 : }
144 :
145 5967 : bool computeIsRect() const {
146 5967 : return fIsBW ? fBW.isRect() : fAA.isRect();
147 : }
148 :
149 645 : bool updateCacheAndReturnNonEmpty(bool detectAARect = true) {
150 645 : fIsEmpty = this->computeIsEmpty();
151 :
152 : // detect that our computed AA is really just a (hard-edged) rect
153 645 : if (detectAARect && !fIsEmpty && !fIsBW && fAA.isRect()) {
154 7 : fBW.setRect(fAA.getBounds());
155 7 : fAA.setEmpty(); // don't need this guy anymore
156 7 : fIsBW = true;
157 : }
158 :
159 645 : fIsRect = this->computeIsRect();
160 645 : return !fIsEmpty;
161 : }
162 :
163 : void convertToAA();
164 :
165 : bool setPath(const SkPath& path, const SkRegion& clip, bool doAA);
166 : bool setPath(const SkPath& path, const SkIRect& clip, bool doAA);
167 : bool op(const SkRasterClip&, SkRegion::Op);
168 : bool setConservativeRect(const SkRect& r, const SkIRect& clipR, bool isInverse);
169 :
170 458 : inline void applyClipRestriction(SkRegion::Op op, SkIRect* bounds) {
171 916 : if (op >= SkRegion::kUnion_Op && fClipRestrictionRect
172 458 : && !fClipRestrictionRect->isEmpty()) {
173 0 : if (!bounds->intersect(*fClipRestrictionRect)) {
174 0 : bounds->setEmpty();
175 : }
176 : }
177 458 : }
178 :
179 113 : inline void applyClipRestriction(SkRegion::Op op, SkRect* bounds) {
180 226 : if (op >= SkRegion::kUnion_Op && fClipRestrictionRect
181 113 : && !fClipRestrictionRect->isEmpty()) {
182 0 : if (!bounds->intersect(SkRect::Make(*fClipRestrictionRect))) {
183 0 : bounds->setEmpty();
184 : }
185 : }
186 113 : }
187 : };
188 :
189 : class SkAutoRasterClipValidate : SkNoncopyable {
190 : public:
191 1367 : SkAutoRasterClipValidate(const SkRasterClip& rc) : fRC(rc) {
192 1367 : fRC.validate();
193 1367 : }
194 2734 : ~SkAutoRasterClipValidate() {
195 1367 : fRC.validate();
196 1367 : }
197 : private:
198 : const SkRasterClip& fRC;
199 : };
200 : #define SkAutoRasterClipValidate(...) SK_REQUIRE_LOCAL_VAR(SkAutoRasterClipValidate)
201 :
202 : #ifdef SK_DEBUG
203 : #define AUTO_RASTERCLIP_VALIDATE(rc) SkAutoRasterClipValidate arcv(rc)
204 : #else
205 : #define AUTO_RASTERCLIP_VALIDATE(rc)
206 : #endif
207 :
208 : ///////////////////////////////////////////////////////////////////////////////
209 :
210 : /**
211 : * Encapsulates the logic of deciding if we need to change/wrap the blitter
212 : * for aaclipping. If so, getRgn and getBlitter return modified values. If
213 : * not, they return the raw blitter and (bw) clip region.
214 : *
215 : * We need to keep the constructor/destructor cost as small as possible, so we
216 : * can freely put this guy on the stack, and not pay too much for the case when
217 : * we're really BW anyways.
218 : */
219 186 : class SkAAClipBlitterWrapper {
220 : public:
221 : SkAAClipBlitterWrapper();
222 : SkAAClipBlitterWrapper(const SkRasterClip&, SkBlitter*);
223 : SkAAClipBlitterWrapper(const SkAAClip*, SkBlitter*);
224 :
225 : void init(const SkRasterClip&, SkBlitter*);
226 :
227 : const SkIRect& getBounds() const {
228 : SkASSERT(fClipRgn);
229 : return fClipRgn->getBounds();
230 : }
231 150 : const SkRegion& getRgn() const {
232 150 : SkASSERT(fClipRgn);
233 150 : return *fClipRgn;
234 : }
235 171 : SkBlitter* getBlitter() {
236 171 : SkASSERT(fBlitter);
237 171 : return fBlitter;
238 : }
239 :
240 : private:
241 : SkRegion fBWRgn;
242 : SkAAClipBlitter fAABlitter;
243 : // what we return
244 : const SkRegion* fClipRgn;
245 : SkBlitter* fBlitter;
246 : };
247 :
248 : #endif
|