Flutter Engine
The Flutter Engine
SkRasterClip.cpp
Go to the documentation of this file.
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
9
13#include "include/core/SkPath.h"
17
18class SkBlitter;
19
21 : fIsBW(that.fIsBW)
22 , fIsEmpty(that.fIsEmpty)
23 , fIsRect(that.fIsRect)
24 , fShader(that.fShader)
25{
27
28 if (fIsBW) {
29 fBW = that.fBW;
30 } else {
31 fAA = that.fAA;
32 }
33
34 SkDEBUGCODE(this->validate();)
35}
36
39
40 fIsBW = that.fIsBW;
41 if (fIsBW) {
42 fBW = that.fBW;
43 } else {
44 fAA = that.fAA;
45 }
46
47 fIsEmpty = that.isEmpty();
48 fIsRect = that.isRect();
49 fShader = that.fShader;
50 SkDEBUGCODE(this->validate();)
51 return *this;
52}
53
54SkRasterClip::SkRasterClip(const SkRegion& rgn) : fBW(rgn) {
55 fIsBW = true;
56 fIsEmpty = this->computeIsEmpty(); // bounds might be empty, so compute
57 fIsRect = !fIsEmpty;
58 SkDEBUGCODE(this->validate();)
59}
60
62 fIsBW = true;
63 fIsEmpty = this->computeIsEmpty(); // bounds might be empty, so compute
64 fIsRect = !fIsEmpty;
65 SkDEBUGCODE(this->validate();)
66}
67
69 fIsBW = true;
70 fIsEmpty = true;
71 fIsRect = false;
72 SkDEBUGCODE(this->validate();)
73}
74
76 if (doAA) {
77 fIsBW = false;
78 fAA.setPath(path, bounds, true);
79 } else {
80 fIsBW = true;
82 }
83 fIsEmpty = this->computeIsEmpty(); // bounds might be empty, so compute
84 fIsRect = this->computeIsRect();
85 SkDEBUGCODE(this->validate();)
86}
87
89 SkDEBUGCODE(this->validate();)
90}
91
94
95 fIsBW = true;
96 fBW.setEmpty();
97 fAA.setEmpty();
98 fIsEmpty = true;
99 fIsRect = false;
100 return false;
101}
102
105
106 fIsBW = true;
107 fAA.setEmpty();
108 fIsRect = fBW.setRect(rect);
109 fIsEmpty = !fIsRect;
110 return fIsRect;
111}
112
113/////////////////////////////////////////////////////////////////////////////////////
114
117
118 if (fIsBW) {
119 fBW.op(rect, (SkRegion::Op) op);
120 } else {
121 fAA.op(rect, op);
122 }
123 return this->updateCacheAndReturnNonEmpty();
124}
125
126bool SkRasterClip::op(const SkRegion& rgn, SkClipOp op) {
128
129 if (fIsBW) {
130 (void)fBW.op(rgn, (SkRegion::Op) op);
131 } else {
132 SkAAClip tmp;
133 tmp.setRegion(rgn);
134 (void)fAA.op(tmp, op);
135 }
136 return this->updateCacheAndReturnNonEmpty();
137}
138
139/**
140 * Our antialiasing currently has a granularity of 1/4 of a pixel along each
141 * axis. Thus we can treat an axis coordinate as an integer if it differs
142 * from its nearest int by < half of that value (1/8 in this case).
143 */
145 static const SkScalar domain = SK_Scalar1 / 4;
146 static const SkScalar halfDomain = domain / 2;
147
148 x += halfDomain;
149 return x - SkScalarFloorToScalar(x) < domain;
150}
151
152bool SkRasterClip::op(const SkRect& localRect, const SkMatrix& matrix, SkClipOp op, bool doAA) {
154
155 const bool isScaleTrans = matrix.isScaleTranslate();
156 if (!isScaleTrans) {
157 return this->op(SkPath::Rect(localRect), matrix, op, doAA);
158 }
159
160 SkRect devRect = matrix.mapRect(localRect);
161 if (fIsBW && doAA) {
162 // check that the rect really needs aa, or is it close enought to
163 // integer boundaries that we can just treat it as a BW rect?
164 if (nearly_integral(devRect.fLeft) && nearly_integral(devRect.fTop) &&
165 nearly_integral(devRect.fRight) && nearly_integral(devRect.fBottom)) {
166 doAA = false;
167 }
168 }
169
170 if (fIsBW && !doAA) {
171 (void)fBW.op(devRect.round(), (SkRegion::Op) op);
172 } else {
173 if (fIsBW) {
174 this->convertToAA();
175 }
176 (void)fAA.op(devRect, op, doAA);
177 }
178 return this->updateCacheAndReturnNonEmpty();
179}
180
181bool SkRasterClip::op(const SkRRect& rrect, const SkMatrix& matrix, SkClipOp op, bool doAA) {
182 return this->op(SkPath::RRect(rrect), matrix, op, doAA);
183}
184
185bool SkRasterClip::op(const SkPath& path, const SkMatrix& matrix, SkClipOp op, bool doAA) {
187
188 SkPath devPath;
189 path.transform(matrix, &devPath);
190
191 // Since op is either intersect or difference, the clip is always shrinking; that means we can
192 // always use our current bounds as the limiting factor for region/aaclip operations.
193 if (this->isRect() && op == SkClipOp::kIntersect) {
194 // However, in the relatively common case of intersecting a new path with a rectangular
195 // clip, it's faster to convert the path into a region/aa-mask in place than evaluate the
196 // actual intersection. See skbug.com/12398
197 if (doAA && fIsBW) {
198 this->convertToAA();
199 }
200 if (fIsBW) {
201 fBW.setPath(devPath, SkRegion(this->getBounds()));
202 } else {
203 fAA.setPath(devPath, this->getBounds(), doAA);
204 }
205 return this->updateCacheAndReturnNonEmpty();
206 } else {
207 return this->op(SkRasterClip(devPath, this->getBounds(), doAA), op);
208 }
209}
210
213
214 if (!fShader) {
215 fShader = sh;
216 } else {
217 fShader = SkShaders::Blend(SkBlendMode::kSrcIn, sh, fShader);
218 }
219 return !this->isEmpty();
220}
221
224 clip.validate();
225
226 if (this->isBW() && clip.isBW()) {
227 (void)fBW.op(clip.fBW, (SkRegion::Op) op);
228 } else {
229 SkAAClip tmp;
230 const SkAAClip* other;
231
232 if (this->isBW()) {
233 this->convertToAA();
234 }
235 if (clip.isBW()) {
236 tmp.setRegion(clip.bwRgn());
237 other = &tmp;
238 } else {
239 other = &clip.aaRgn();
240 }
241 (void)fAA.op(*other, op);
242 }
243 return this->updateCacheAndReturnNonEmpty();
244}
245
246void SkRasterClip::translate(int dx, int dy, SkRasterClip* dst) const {
247 if (nullptr == dst) {
248 return;
249 }
250
252
253 if (this->isEmpty()) {
254 dst->setEmpty();
255 return;
256 }
257 if (0 == (dx | dy)) {
258 *dst = *this;
259 return;
260 }
261
262 dst->fIsBW = fIsBW;
263 if (fIsBW) {
264 fBW.translate(dx, dy, &dst->fBW);
265 dst->fAA.setEmpty();
266 } else {
267 fAA.translate(dx, dy, &dst->fAA);
268 dst->fBW.setEmpty();
269 }
270 dst->updateCacheAndReturnNonEmpty();
271}
272
273void SkRasterClip::convertToAA() {
275
276 SkASSERT(fIsBW);
277 fAA.setRegion(fBW);
278 fIsBW = false;
279
280 // since we are being explicitly asked to convert-to-aa, we pass false so we don't "optimize"
281 // ourselves back to BW.
282 (void)this->updateCacheAndReturnNonEmpty(false);
283}
284
285#ifdef SK_DEBUG
286void SkRasterClip::validate() const {
287 // can't ever assert that fBW is empty, since we may have called forceGetBW
288 if (fIsBW) {
289 SkASSERT(fAA.isEmpty());
290 }
291
293 fAA.validate();
294
295 SkASSERT(this->computeIsEmpty() == fIsEmpty);
296 SkASSERT(this->computeIsRect() == fIsRect);
297}
298#endif
299
300///////////////////////////////////////////////////////////////////////////////
301
303 SkDEBUGCODE(fClipRgn = nullptr;)
304 SkDEBUGCODE(fBlitter = nullptr;)
305}
306
308 SkBlitter* blitter) {
309 this->init(clip, blitter);
310}
311
313 SkBlitter* blitter) {
314 SkASSERT(blitter);
315 SkASSERT(aaclip);
316 fBWRgn.setRect(aaclip->getBounds());
317 fAABlitter.init(blitter, aaclip);
318 // now our return values
319 fClipRgn = &fBWRgn;
320 fBlitter = &fAABlitter;
321}
322
324 SkASSERT(blitter);
325 if (clip.isBW()) {
326 fClipRgn = &clip.bwRgn();
327 fBlitter = blitter;
328 } else {
329 const SkAAClip& aaclip = clip.aaRgn();
330 fBWRgn.setRect(aaclip.getBounds());
331 fAABlitter.init(blitter, &aaclip);
332 // now our return values
333 fClipRgn = &fBWRgn;
334 fBlitter = &fAABlitter;
335 }
336}
#define SkASSERT(cond)
Definition: SkAssert.h:116
@ kSrcIn
r = s * da
SkClipOp
Definition: SkClipOp.h:13
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
static bool nearly_integral(SkScalar x)
#define AUTO_RASTERCLIP_VALIDATE(rc)
Definition: SkRasterClip.h:149
#define SkScalarFloorToScalar(x)
Definition: SkScalar.h:30
#define SK_Scalar1
Definition: SkScalar.h:18
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
void init(const SkRasterClip &, SkBlitter *)
void init(SkBlitter *blitter, const SkAAClip *aaclip)
Definition: SkAAClip.h:97
void validate() const
Definition: SkAAClip.h:65
bool setEmpty()
Definition: SkAAClip.cpp:1264
bool translate(int dx, int dy, SkAAClip *dst) const
Definition: SkAAClip.cpp:1524
const SkIRect & getBounds() const
Definition: SkAAClip.h:34
bool setPath(const SkPath &, const SkIRect &bounds, bool doAA=true)
Definition: SkAAClip.cpp:1401
bool op(const SkIRect &, SkClipOp)
Definition: SkAAClip.cpp:1459
bool isEmpty() const
Definition: SkAAClip.h:33
bool setRegion(const SkRegion &)
Definition: SkAAClip.cpp:1313
Definition: SkPath.h:59
static SkPath RRect(const SkRRect &, SkPathDirection dir=SkPathDirection::kCW)
Definition: SkPath.cpp:3602
static SkPath Rect(const SkRect &, SkPathDirection=SkPathDirection::kCW, unsigned startIndex=0)
Definition: SkPath.cpp:3586
const SkIRect & getBounds() const
Definition: SkRasterClip.h:60
void validate() const
Definition: SkRasterClip.h:92
SkRasterClip & operator=(const SkRasterClip &)
void translate(int dx, int dy, SkRasterClip *dst) const
bool isRect() const
Definition: SkRasterClip.h:52
bool isBW() const
Definition: SkRasterClip.h:42
bool setRect(const SkIRect &)
bool isEmpty() const
Definition: SkRasterClip.h:47
bool op(const SkIRect &, SkClipOp)
void translate(int dx, int dy)
Definition: SkRegion.h:349
bool setEmpty()
Definition: SkRegion.cpp:185
bool op(const SkIRect &rect, Op op)
Definition: SkRegion.h:384
bool setRect(const SkIRect &rect)
Definition: SkRegion.cpp:192
bool setPath(const SkPath &path, const SkRegion &clip)
float SkScalar
Definition: extension.cpp:12
double x
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
Optional< SkRect > bounds
Definition: SkRecords.h:189
SkRRect rrect
Definition: SkRecords.h:232
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
Definition: SkRecords.h:208
SK_API sk_sp< SkShader > Blend(SkBlendMode mode, sk_sp< SkShader > dst, sk_sp< SkShader > src)
void Validate(const Table &table)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
dst
Definition: cp.py:12
sh
Definition: run_sh.py:10
Definition: SkRect.h:32
SkScalar fBottom
larger y-axis bounds
Definition: extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition: extension.cpp:14
SkScalar fRight
larger x-axis bounds
Definition: extension.cpp:16
void round(SkIRect *dst) const
Definition: SkRect.h:1228
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15