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 : #include "SkRasterClip.h"
9 :
10 :
11 0 : SkRasterClip::SkRasterClip() {
12 0 : fIsBW = true;
13 0 : }
14 :
15 0 : SkRasterClip::SkRasterClip(const SkRasterClip& src) {
16 0 : AUTO_RASTERCLIP_VALIDATE(src);
17 :
18 0 : fIsBW = src.fIsBW;
19 0 : if (fIsBW) {
20 0 : fBW = src.fBW;
21 : } else {
22 0 : fAA = src.fAA;
23 : }
24 0 : }
25 :
26 0 : SkRasterClip::SkRasterClip(const SkIRect& bounds) : fBW(bounds) {
27 0 : fIsBW = true;
28 0 : }
29 :
30 0 : SkRasterClip::~SkRasterClip() {
31 0 : AUTO_RASTERCLIP_VALIDATE(*this);
32 0 : }
33 :
34 0 : bool SkRasterClip::isEmpty() const {
35 0 : return fIsBW ? fBW.isEmpty() : fAA.isEmpty();
36 : }
37 :
38 0 : bool SkRasterClip::isRect() const {
39 0 : return fIsBW ? fBW.isRect() : false;
40 : }
41 :
42 0 : bool SkRasterClip::isComplex() const {
43 0 : return fIsBW ? fBW.isComplex() : !fAA.isEmpty();
44 : }
45 :
46 0 : const SkIRect& SkRasterClip::getBounds() const {
47 0 : return fIsBW ? fBW.getBounds() : fAA.getBounds();
48 : }
49 :
50 0 : bool SkRasterClip::setEmpty() {
51 0 : AUTO_RASTERCLIP_VALIDATE(*this);
52 :
53 0 : fIsBW = true;
54 0 : fBW.setEmpty();
55 0 : fAA.setEmpty();
56 0 : return false;
57 : }
58 :
59 0 : bool SkRasterClip::setRect(const SkIRect& rect) {
60 0 : AUTO_RASTERCLIP_VALIDATE(*this);
61 :
62 0 : fIsBW = true;
63 0 : fAA.setEmpty();
64 0 : return fBW.setRect(rect);
65 : }
66 :
67 0 : bool SkRasterClip::setPath(const SkPath& path, const SkRegion& clip, bool doAA) {
68 0 : AUTO_RASTERCLIP_VALIDATE(*this);
69 :
70 0 : if (this->isBW() && !doAA) {
71 0 : return fBW.setPath(path, clip);
72 : } else {
73 0 : if (this->isBW()) {
74 0 : this->convertToAA();
75 : }
76 0 : return fAA.setPath(path, &clip, doAA);
77 : }
78 : }
79 :
80 0 : bool SkRasterClip::setPath(const SkPath& path, const SkIRect& clip, bool doAA) {
81 0 : SkRegion tmp;
82 0 : tmp.setRect(clip);
83 0 : return this->setPath(path, tmp, doAA);
84 : }
85 :
86 0 : bool SkRasterClip::setPath(const SkPath& path, const SkRasterClip& clip,
87 : bool doAA) {
88 0 : if (clip.isBW()) {
89 0 : return this->setPath(path, clip.bwRgn(), doAA);
90 : } else {
91 0 : SkRegion tmp;
92 0 : tmp.setRect(clip.getBounds());
93 0 : if (!this->setPath(path, clip, doAA)) {
94 0 : return false;
95 : }
96 0 : return this->op(clip, SkRegion::kIntersect_Op);
97 : }
98 : }
99 :
100 0 : bool SkRasterClip::op(const SkIRect& rect, SkRegion::Op op) {
101 0 : AUTO_RASTERCLIP_VALIDATE(*this);
102 :
103 0 : return fIsBW ? fBW.op(rect, op) : fAA.op(rect, op);
104 : }
105 :
106 0 : bool SkRasterClip::op(const SkRegion& rgn, SkRegion::Op op) {
107 0 : AUTO_RASTERCLIP_VALIDATE(*this);
108 :
109 0 : if (fIsBW) {
110 0 : return fBW.op(rgn, op);
111 : } else {
112 0 : SkAAClip tmp;
113 0 : tmp.setRegion(rgn);
114 0 : return fAA.op(tmp, op);
115 : }
116 : }
117 :
118 0 : bool SkRasterClip::op(const SkRasterClip& clip, SkRegion::Op op) {
119 0 : AUTO_RASTERCLIP_VALIDATE(*this);
120 0 : clip.validate();
121 :
122 0 : if (this->isBW() && clip.isBW()) {
123 0 : return fBW.op(clip.fBW, op);
124 : } else {
125 0 : SkAAClip tmp;
126 : const SkAAClip* other;
127 :
128 0 : if (this->isBW()) {
129 0 : this->convertToAA();
130 : }
131 0 : if (clip.isBW()) {
132 0 : tmp.setRegion(clip.bwRgn());
133 0 : other = &tmp;
134 : } else {
135 0 : other = &clip.aaRgn();
136 : }
137 0 : return fAA.op(*other, op);
138 : }
139 : }
140 :
141 : // return true if x is nearly integral (within 1/16) since that is the highest
142 : // precision our aa code can have.
143 0 : static bool is_integral(SkScalar x) {
144 0 : int ix = SkScalarRoundToInt(x);
145 0 : SkScalar sx = SkIntToScalar(ix);
146 0 : return SkScalarAbs(sx - x) < (SK_Scalar1 / 16);
147 : }
148 :
149 0 : bool SkRasterClip::op(const SkRect& r, SkRegion::Op op, bool doAA) {
150 0 : AUTO_RASTERCLIP_VALIDATE(*this);
151 :
152 0 : if (doAA) {
153 : // check that the rect really needs aa
154 0 : if (is_integral(r.fLeft) && is_integral(r.fTop) &&
155 0 : is_integral(r.fRight) && is_integral(r.fBottom)) {
156 0 : doAA = false;
157 : }
158 : }
159 :
160 0 : if (fIsBW && !doAA) {
161 : SkIRect ir;
162 0 : r.round(&ir);
163 0 : return fBW.op(ir, op);
164 : } else {
165 0 : if (fIsBW) {
166 0 : this->convertToAA();
167 : }
168 0 : return fAA.op(r, op, doAA);
169 : }
170 : }
171 :
172 0 : void SkRasterClip::translate(int dx, int dy, SkRasterClip* dst) const {
173 0 : if (NULL == dst) {
174 0 : return;
175 : }
176 :
177 0 : AUTO_RASTERCLIP_VALIDATE(*this);
178 :
179 0 : if (this->isEmpty()) {
180 0 : dst->setEmpty();
181 : return;
182 : }
183 0 : if (0 == (dx | dy)) {
184 0 : *dst = *this;
185 : return;
186 : }
187 :
188 0 : dst->fIsBW = fIsBW;
189 0 : if (fIsBW) {
190 0 : fBW.translate(dx, dy, &dst->fBW);
191 0 : dst->fAA.setEmpty();
192 : } else {
193 0 : fAA.translate(dx, dy, &dst->fAA);
194 0 : dst->fBW.setEmpty();
195 : }
196 : }
197 :
198 0 : bool SkRasterClip::quickContains(const SkIRect& ir) const {
199 0 : return fIsBW ? fBW.quickContains(ir) : fAA.quickContains(ir);
200 : }
201 :
202 : ///////////////////////////////////////////////////////////////////////////////
203 :
204 0 : const SkRegion& SkRasterClip::forceGetBW() {
205 0 : AUTO_RASTERCLIP_VALIDATE(*this);
206 :
207 0 : if (!fIsBW) {
208 0 : fBW.setRect(fAA.getBounds());
209 : }
210 0 : return fBW;
211 : }
212 :
213 0 : void SkRasterClip::convertToAA() {
214 0 : AUTO_RASTERCLIP_VALIDATE(*this);
215 :
216 0 : SkASSERT(fIsBW);
217 0 : fAA.setRegion(fBW);
218 0 : fIsBW = false;
219 0 : }
220 :
221 : #ifdef SK_DEBUG
222 0 : void SkRasterClip::validate() const {
223 : // can't ever assert that fBW is empty, since we may have called forceGetBW
224 0 : if (fIsBW) {
225 0 : SkASSERT(fAA.isEmpty());
226 : }
227 :
228 0 : fBW.validate();
229 0 : fAA.validate();
230 0 : }
231 : #endif
232 :
233 : ///////////////////////////////////////////////////////////////////////////////
234 :
235 0 : SkAAClipBlitterWrapper::SkAAClipBlitterWrapper() {
236 0 : SkDEBUGCODE(fClipRgn = NULL;)
237 0 : SkDEBUGCODE(fBlitter = NULL;)
238 0 : }
239 :
240 0 : SkAAClipBlitterWrapper::SkAAClipBlitterWrapper(const SkRasterClip& clip,
241 0 : SkBlitter* blitter) {
242 0 : this->init(clip, blitter);
243 0 : }
244 :
245 0 : SkAAClipBlitterWrapper::SkAAClipBlitterWrapper(const SkAAClip* aaclip,
246 0 : SkBlitter* blitter) {
247 0 : SkASSERT(blitter);
248 0 : SkASSERT(aaclip);
249 0 : fBWRgn.setRect(aaclip->getBounds());
250 0 : fAABlitter.init(blitter, aaclip);
251 : // now our return values
252 0 : fClipRgn = &fBWRgn;
253 0 : fBlitter = &fAABlitter;
254 0 : }
255 :
256 0 : void SkAAClipBlitterWrapper::init(const SkRasterClip& clip, SkBlitter* blitter) {
257 0 : SkASSERT(blitter);
258 0 : if (clip.isBW()) {
259 0 : fClipRgn = &clip.bwRgn();
260 0 : fBlitter = blitter;
261 : } else {
262 0 : const SkAAClip& aaclip = clip.aaRgn();
263 0 : fBWRgn.setRect(aaclip.getBounds());
264 0 : fAABlitter.init(blitter, &aaclip);
265 : // now our return values
266 0 : fClipRgn = &fBWRgn;
267 0 : fBlitter = &fAABlitter;
268 : }
269 0 : }
270 :
|