1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2010 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkPath.h"
9cb93a386Sopenharmony_ci#include "src/core/SkRasterClip.h"
10cb93a386Sopenharmony_ci#include "src/core/SkRegionPriv.h"
11cb93a386Sopenharmony_ci
12cb93a386Sopenharmony_ciSkRasterClip::SkRasterClip(const SkRasterClip& that)
13cb93a386Sopenharmony_ci        : fIsBW(that.fIsBW)
14cb93a386Sopenharmony_ci        , fIsEmpty(that.fIsEmpty)
15cb93a386Sopenharmony_ci        , fIsRect(that.fIsRect)
16cb93a386Sopenharmony_ci        , fShader(that.fShader)
17cb93a386Sopenharmony_ci{
18cb93a386Sopenharmony_ci    AUTO_RASTERCLIP_VALIDATE(that);
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_ci    if (fIsBW) {
21cb93a386Sopenharmony_ci        fBW = that.fBW;
22cb93a386Sopenharmony_ci    } else {
23cb93a386Sopenharmony_ci        fAA = that.fAA;
24cb93a386Sopenharmony_ci    }
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
27cb93a386Sopenharmony_ci}
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ciSkRasterClip& SkRasterClip::operator=(const SkRasterClip& that) {
30cb93a386Sopenharmony_ci    AUTO_RASTERCLIP_VALIDATE(that);
31cb93a386Sopenharmony_ci
32cb93a386Sopenharmony_ci    fIsBW = that.fIsBW;
33cb93a386Sopenharmony_ci    if (fIsBW) {
34cb93a386Sopenharmony_ci        fBW = that.fBW;
35cb93a386Sopenharmony_ci    } else {
36cb93a386Sopenharmony_ci        fAA = that.fAA;
37cb93a386Sopenharmony_ci    }
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_ci    fIsEmpty = that.isEmpty();
40cb93a386Sopenharmony_ci    fIsRect = that.isRect();
41cb93a386Sopenharmony_ci    fShader = that.fShader;
42cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
43cb93a386Sopenharmony_ci    return *this;
44cb93a386Sopenharmony_ci}
45cb93a386Sopenharmony_ci
46cb93a386Sopenharmony_ciSkRasterClip::SkRasterClip(const SkRegion& rgn) : fBW(rgn) {
47cb93a386Sopenharmony_ci    fIsBW = true;
48cb93a386Sopenharmony_ci    fIsEmpty = this->computeIsEmpty();  // bounds might be empty, so compute
49cb93a386Sopenharmony_ci    fIsRect = !fIsEmpty;
50cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
51cb93a386Sopenharmony_ci}
52cb93a386Sopenharmony_ci
53cb93a386Sopenharmony_ciSkRasterClip::SkRasterClip(const SkIRect& bounds) : fBW(bounds) {
54cb93a386Sopenharmony_ci    fIsBW = true;
55cb93a386Sopenharmony_ci    fIsEmpty = this->computeIsEmpty();  // bounds might be empty, so compute
56cb93a386Sopenharmony_ci    fIsRect = !fIsEmpty;
57cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
58cb93a386Sopenharmony_ci}
59cb93a386Sopenharmony_ci
60cb93a386Sopenharmony_ciSkRasterClip::SkRasterClip() {
61cb93a386Sopenharmony_ci    fIsBW = true;
62cb93a386Sopenharmony_ci    fIsEmpty = true;
63cb93a386Sopenharmony_ci    fIsRect = false;
64cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
65cb93a386Sopenharmony_ci}
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_ciSkRasterClip::SkRasterClip(const SkPath& path, const SkIRect& bounds, bool doAA) {
68cb93a386Sopenharmony_ci    if (doAA) {
69cb93a386Sopenharmony_ci        fIsBW = false;
70cb93a386Sopenharmony_ci        fAA.setPath(path, bounds, true);
71cb93a386Sopenharmony_ci    } else {
72cb93a386Sopenharmony_ci        fIsBW = true;
73cb93a386Sopenharmony_ci        fBW.setPath(path, SkRegion(bounds));
74cb93a386Sopenharmony_ci    }
75cb93a386Sopenharmony_ci    fIsEmpty = this->computeIsEmpty();  // bounds might be empty, so compute
76cb93a386Sopenharmony_ci    fIsRect = this->computeIsRect();
77cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
78cb93a386Sopenharmony_ci}
79cb93a386Sopenharmony_ci
80cb93a386Sopenharmony_ciSkRasterClip::~SkRasterClip() {
81cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
82cb93a386Sopenharmony_ci}
83cb93a386Sopenharmony_ci
84cb93a386Sopenharmony_cibool SkRasterClip::setEmpty() {
85cb93a386Sopenharmony_ci    AUTO_RASTERCLIP_VALIDATE(*this);
86cb93a386Sopenharmony_ci
87cb93a386Sopenharmony_ci    fIsBW = true;
88cb93a386Sopenharmony_ci    fBW.setEmpty();
89cb93a386Sopenharmony_ci    fAA.setEmpty();
90cb93a386Sopenharmony_ci    fIsEmpty = true;
91cb93a386Sopenharmony_ci    fIsRect = false;
92cb93a386Sopenharmony_ci    return false;
93cb93a386Sopenharmony_ci}
94cb93a386Sopenharmony_ci
95cb93a386Sopenharmony_cibool SkRasterClip::setRect(const SkIRect& rect) {
96cb93a386Sopenharmony_ci    AUTO_RASTERCLIP_VALIDATE(*this);
97cb93a386Sopenharmony_ci
98cb93a386Sopenharmony_ci    fIsBW = true;
99cb93a386Sopenharmony_ci    fAA.setEmpty();
100cb93a386Sopenharmony_ci    fIsRect = fBW.setRect(rect);
101cb93a386Sopenharmony_ci    fIsEmpty = !fIsRect;
102cb93a386Sopenharmony_ci    return fIsRect;
103cb93a386Sopenharmony_ci}
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////////////
106cb93a386Sopenharmony_ci
107cb93a386Sopenharmony_cibool SkRasterClip::op(const SkIRect& rect, SkClipOp op) {
108cb93a386Sopenharmony_ci    AUTO_RASTERCLIP_VALIDATE(*this);
109cb93a386Sopenharmony_ci
110cb93a386Sopenharmony_ci    if (fIsBW) {
111cb93a386Sopenharmony_ci        fBW.op(rect, (SkRegion::Op) op);
112cb93a386Sopenharmony_ci    } else {
113cb93a386Sopenharmony_ci        fAA.op(rect, op);
114cb93a386Sopenharmony_ci    }
115cb93a386Sopenharmony_ci    return this->updateCacheAndReturnNonEmpty();
116cb93a386Sopenharmony_ci}
117cb93a386Sopenharmony_ci
118cb93a386Sopenharmony_cibool SkRasterClip::op(const SkRegion& rgn, SkClipOp op) {
119cb93a386Sopenharmony_ci    AUTO_RASTERCLIP_VALIDATE(*this);
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_ci    if (fIsBW) {
122cb93a386Sopenharmony_ci        (void)fBW.op(rgn, (SkRegion::Op) op);
123cb93a386Sopenharmony_ci    } else {
124cb93a386Sopenharmony_ci        SkAAClip tmp;
125cb93a386Sopenharmony_ci        tmp.setRegion(rgn);
126cb93a386Sopenharmony_ci        (void)fAA.op(tmp, op);
127cb93a386Sopenharmony_ci    }
128cb93a386Sopenharmony_ci    return this->updateCacheAndReturnNonEmpty();
129cb93a386Sopenharmony_ci}
130cb93a386Sopenharmony_ci
131cb93a386Sopenharmony_ci/**
132cb93a386Sopenharmony_ci *  Our antialiasing currently has a granularity of 1/4 of a pixel along each
133cb93a386Sopenharmony_ci *  axis. Thus we can treat an axis coordinate as an integer if it differs
134cb93a386Sopenharmony_ci *  from its nearest int by < half of that value (1/8 in this case).
135cb93a386Sopenharmony_ci */
136cb93a386Sopenharmony_cistatic bool nearly_integral(SkScalar x) {
137cb93a386Sopenharmony_ci    static const SkScalar domain = SK_Scalar1 / 4;
138cb93a386Sopenharmony_ci    static const SkScalar halfDomain = domain / 2;
139cb93a386Sopenharmony_ci
140cb93a386Sopenharmony_ci    x += halfDomain;
141cb93a386Sopenharmony_ci    return x - SkScalarFloorToScalar(x) < domain;
142cb93a386Sopenharmony_ci}
143cb93a386Sopenharmony_ci
144cb93a386Sopenharmony_cibool SkRasterClip::op(const SkRect& localRect, const SkMatrix& matrix, SkClipOp op, bool doAA) {
145cb93a386Sopenharmony_ci    AUTO_RASTERCLIP_VALIDATE(*this);
146cb93a386Sopenharmony_ci
147cb93a386Sopenharmony_ci    const bool isScaleTrans = matrix.isScaleTranslate();
148cb93a386Sopenharmony_ci    if (!isScaleTrans) {
149cb93a386Sopenharmony_ci        return this->op(SkPath::Rect(localRect), matrix, op, doAA);
150cb93a386Sopenharmony_ci    }
151cb93a386Sopenharmony_ci
152cb93a386Sopenharmony_ci    SkRect devRect = matrix.mapRect(localRect);
153cb93a386Sopenharmony_ci    if (fIsBW && doAA) {
154cb93a386Sopenharmony_ci        // check that the rect really needs aa, or is it close enought to
155cb93a386Sopenharmony_ci        // integer boundaries that we can just treat it as a BW rect?
156cb93a386Sopenharmony_ci        if (nearly_integral(devRect.fLeft) && nearly_integral(devRect.fTop) &&
157cb93a386Sopenharmony_ci            nearly_integral(devRect.fRight) && nearly_integral(devRect.fBottom)) {
158cb93a386Sopenharmony_ci            doAA = false;
159cb93a386Sopenharmony_ci        }
160cb93a386Sopenharmony_ci    }
161cb93a386Sopenharmony_ci
162cb93a386Sopenharmony_ci    if (fIsBW && !doAA) {
163cb93a386Sopenharmony_ci        (void)fBW.op(devRect.round(), (SkRegion::Op) op);
164cb93a386Sopenharmony_ci    } else {
165cb93a386Sopenharmony_ci        if (fIsBW) {
166cb93a386Sopenharmony_ci            this->convertToAA();
167cb93a386Sopenharmony_ci        }
168cb93a386Sopenharmony_ci        (void)fAA.op(devRect, op, doAA);
169cb93a386Sopenharmony_ci    }
170cb93a386Sopenharmony_ci    return this->updateCacheAndReturnNonEmpty();
171cb93a386Sopenharmony_ci}
172cb93a386Sopenharmony_ci
173cb93a386Sopenharmony_cibool SkRasterClip::op(const SkRRect& rrect, const SkMatrix& matrix, SkClipOp op, bool doAA) {
174cb93a386Sopenharmony_ci    return this->op(SkPath::RRect(rrect), matrix, op, doAA);
175cb93a386Sopenharmony_ci}
176cb93a386Sopenharmony_ci
177cb93a386Sopenharmony_cibool SkRasterClip::op(const SkPath& path, const SkMatrix& matrix, SkClipOp op, bool doAA) {
178cb93a386Sopenharmony_ci    AUTO_RASTERCLIP_VALIDATE(*this);
179cb93a386Sopenharmony_ci
180cb93a386Sopenharmony_ci    SkPath devPath;
181cb93a386Sopenharmony_ci    path.transform(matrix, &devPath);
182cb93a386Sopenharmony_ci
183cb93a386Sopenharmony_ci    // Since op is either intersect or difference, the clip is always shrinking; that means we can
184cb93a386Sopenharmony_ci    // always use our current bounds as the limiting factor for region/aaclip operations.
185cb93a386Sopenharmony_ci    if (this->isRect() && op == SkClipOp::kIntersect) {
186cb93a386Sopenharmony_ci        // However, in the relatively common case of intersecting a new path with a rectangular
187cb93a386Sopenharmony_ci        // clip, it's faster to convert the path into a region/aa-mask in place than evaluate the
188cb93a386Sopenharmony_ci        // actual intersection. See skbug.com/12398
189cb93a386Sopenharmony_ci        if (doAA && fIsBW) {
190cb93a386Sopenharmony_ci            this->convertToAA();
191cb93a386Sopenharmony_ci        }
192cb93a386Sopenharmony_ci        if (fIsBW) {
193cb93a386Sopenharmony_ci            fBW.setPath(devPath, SkRegion(this->getBounds()));
194cb93a386Sopenharmony_ci        } else {
195cb93a386Sopenharmony_ci            fAA.setPath(devPath, this->getBounds(), doAA);
196cb93a386Sopenharmony_ci        }
197cb93a386Sopenharmony_ci        return this->updateCacheAndReturnNonEmpty();
198cb93a386Sopenharmony_ci    } else {
199cb93a386Sopenharmony_ci        return this->op(SkRasterClip(devPath, this->getBounds(), doAA), op);
200cb93a386Sopenharmony_ci    }
201cb93a386Sopenharmony_ci}
202cb93a386Sopenharmony_ci
203cb93a386Sopenharmony_cibool SkRasterClip::op(sk_sp<SkShader> sh) {
204cb93a386Sopenharmony_ci    AUTO_RASTERCLIP_VALIDATE(*this);
205cb93a386Sopenharmony_ci
206cb93a386Sopenharmony_ci    if (!fShader) {
207cb93a386Sopenharmony_ci        fShader = sh;
208cb93a386Sopenharmony_ci    } else {
209cb93a386Sopenharmony_ci        fShader = SkShaders::Blend(SkBlendMode::kSrcIn, sh, fShader);
210cb93a386Sopenharmony_ci    }
211cb93a386Sopenharmony_ci    return !this->isEmpty();
212cb93a386Sopenharmony_ci}
213cb93a386Sopenharmony_ci
214cb93a386Sopenharmony_cibool SkRasterClip::op(const SkRasterClip& clip, SkClipOp op) {
215cb93a386Sopenharmony_ci    AUTO_RASTERCLIP_VALIDATE(*this);
216cb93a386Sopenharmony_ci    clip.validate();
217cb93a386Sopenharmony_ci
218cb93a386Sopenharmony_ci    if (this->isBW() && clip.isBW()) {
219cb93a386Sopenharmony_ci        (void)fBW.op(clip.fBW, (SkRegion::Op) op);
220cb93a386Sopenharmony_ci    } else {
221cb93a386Sopenharmony_ci        SkAAClip tmp;
222cb93a386Sopenharmony_ci        const SkAAClip* other;
223cb93a386Sopenharmony_ci
224cb93a386Sopenharmony_ci        if (this->isBW()) {
225cb93a386Sopenharmony_ci            this->convertToAA();
226cb93a386Sopenharmony_ci        }
227cb93a386Sopenharmony_ci        if (clip.isBW()) {
228cb93a386Sopenharmony_ci            tmp.setRegion(clip.bwRgn());
229cb93a386Sopenharmony_ci            other = &tmp;
230cb93a386Sopenharmony_ci        } else {
231cb93a386Sopenharmony_ci            other = &clip.aaRgn();
232cb93a386Sopenharmony_ci        }
233cb93a386Sopenharmony_ci        (void)fAA.op(*other, op);
234cb93a386Sopenharmony_ci    }
235cb93a386Sopenharmony_ci    return this->updateCacheAndReturnNonEmpty();
236cb93a386Sopenharmony_ci}
237cb93a386Sopenharmony_ci
238cb93a386Sopenharmony_civoid SkRasterClip::translate(int dx, int dy, SkRasterClip* dst) const {
239cb93a386Sopenharmony_ci    if (nullptr == dst) {
240cb93a386Sopenharmony_ci        return;
241cb93a386Sopenharmony_ci    }
242cb93a386Sopenharmony_ci
243cb93a386Sopenharmony_ci    AUTO_RASTERCLIP_VALIDATE(*this);
244cb93a386Sopenharmony_ci
245cb93a386Sopenharmony_ci    if (this->isEmpty()) {
246cb93a386Sopenharmony_ci        dst->setEmpty();
247cb93a386Sopenharmony_ci        return;
248cb93a386Sopenharmony_ci    }
249cb93a386Sopenharmony_ci    if (0 == (dx | dy)) {
250cb93a386Sopenharmony_ci        *dst = *this;
251cb93a386Sopenharmony_ci        return;
252cb93a386Sopenharmony_ci    }
253cb93a386Sopenharmony_ci
254cb93a386Sopenharmony_ci    dst->fIsBW = fIsBW;
255cb93a386Sopenharmony_ci    if (fIsBW) {
256cb93a386Sopenharmony_ci        fBW.translate(dx, dy, &dst->fBW);
257cb93a386Sopenharmony_ci        dst->fAA.setEmpty();
258cb93a386Sopenharmony_ci    } else {
259cb93a386Sopenharmony_ci        fAA.translate(dx, dy, &dst->fAA);
260cb93a386Sopenharmony_ci        dst->fBW.setEmpty();
261cb93a386Sopenharmony_ci    }
262cb93a386Sopenharmony_ci    dst->updateCacheAndReturnNonEmpty();
263cb93a386Sopenharmony_ci}
264cb93a386Sopenharmony_ci
265cb93a386Sopenharmony_civoid SkRasterClip::convertToAA() {
266cb93a386Sopenharmony_ci    AUTO_RASTERCLIP_VALIDATE(*this);
267cb93a386Sopenharmony_ci
268cb93a386Sopenharmony_ci    SkASSERT(fIsBW);
269cb93a386Sopenharmony_ci    fAA.setRegion(fBW);
270cb93a386Sopenharmony_ci    fIsBW = false;
271cb93a386Sopenharmony_ci
272cb93a386Sopenharmony_ci    // since we are being explicitly asked to convert-to-aa, we pass false so we don't "optimize"
273cb93a386Sopenharmony_ci    // ourselves back to BW.
274cb93a386Sopenharmony_ci    (void)this->updateCacheAndReturnNonEmpty(false);
275cb93a386Sopenharmony_ci}
276cb93a386Sopenharmony_ci
277cb93a386Sopenharmony_ci#ifdef SK_DEBUG
278cb93a386Sopenharmony_civoid SkRasterClip::validate() const {
279cb93a386Sopenharmony_ci    // can't ever assert that fBW is empty, since we may have called forceGetBW
280cb93a386Sopenharmony_ci    if (fIsBW) {
281cb93a386Sopenharmony_ci        SkASSERT(fAA.isEmpty());
282cb93a386Sopenharmony_ci    }
283cb93a386Sopenharmony_ci
284cb93a386Sopenharmony_ci    SkRegionPriv::Validate(fBW);
285cb93a386Sopenharmony_ci    fAA.validate();
286cb93a386Sopenharmony_ci
287cb93a386Sopenharmony_ci    SkASSERT(this->computeIsEmpty() == fIsEmpty);
288cb93a386Sopenharmony_ci    SkASSERT(this->computeIsRect() == fIsRect);
289cb93a386Sopenharmony_ci}
290cb93a386Sopenharmony_ci#endif
291cb93a386Sopenharmony_ci
292cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
293cb93a386Sopenharmony_ci
294cb93a386Sopenharmony_ciSkAAClipBlitterWrapper::SkAAClipBlitterWrapper() {
295cb93a386Sopenharmony_ci    SkDEBUGCODE(fClipRgn = nullptr;)
296cb93a386Sopenharmony_ci    SkDEBUGCODE(fBlitter = nullptr;)
297cb93a386Sopenharmony_ci}
298cb93a386Sopenharmony_ci
299cb93a386Sopenharmony_ciSkAAClipBlitterWrapper::SkAAClipBlitterWrapper(const SkRasterClip& clip,
300cb93a386Sopenharmony_ci                                               SkBlitter* blitter) {
301cb93a386Sopenharmony_ci    this->init(clip, blitter);
302cb93a386Sopenharmony_ci}
303cb93a386Sopenharmony_ci
304cb93a386Sopenharmony_ciSkAAClipBlitterWrapper::SkAAClipBlitterWrapper(const SkAAClip* aaclip,
305cb93a386Sopenharmony_ci                                               SkBlitter* blitter) {
306cb93a386Sopenharmony_ci    SkASSERT(blitter);
307cb93a386Sopenharmony_ci    SkASSERT(aaclip);
308cb93a386Sopenharmony_ci    fBWRgn.setRect(aaclip->getBounds());
309cb93a386Sopenharmony_ci    fAABlitter.init(blitter, aaclip);
310cb93a386Sopenharmony_ci    // now our return values
311cb93a386Sopenharmony_ci    fClipRgn = &fBWRgn;
312cb93a386Sopenharmony_ci    fBlitter = &fAABlitter;
313cb93a386Sopenharmony_ci}
314cb93a386Sopenharmony_ci
315cb93a386Sopenharmony_civoid SkAAClipBlitterWrapper::init(const SkRasterClip& clip, SkBlitter* blitter) {
316cb93a386Sopenharmony_ci    SkASSERT(blitter);
317cb93a386Sopenharmony_ci    if (clip.isBW()) {
318cb93a386Sopenharmony_ci        fClipRgn = &clip.bwRgn();
319cb93a386Sopenharmony_ci        fBlitter = blitter;
320cb93a386Sopenharmony_ci    } else {
321cb93a386Sopenharmony_ci        const SkAAClip& aaclip = clip.aaRgn();
322cb93a386Sopenharmony_ci        fBWRgn.setRect(aaclip.getBounds());
323cb93a386Sopenharmony_ci        fAABlitter.init(blitter, &aaclip);
324cb93a386Sopenharmony_ci        // now our return values
325cb93a386Sopenharmony_ci        fClipRgn = &fBWRgn;
326cb93a386Sopenharmony_ci        fBlitter = &fAABlitter;
327cb93a386Sopenharmony_ci    }
328cb93a386Sopenharmony_ci}
329