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