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