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