/src/skia/src/core/SkClipStackDevice.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2017 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 "src/core/SkClipStackDevice.h" |
9 | | #include "src/core/SkDraw.h" |
10 | | #include "src/core/SkRasterClip.h" |
11 | | |
12 | 160k | SkIRect SkClipStackDevice::onDevClipBounds() const { |
13 | 160k | SkIRect r = fClipStack.bounds(this->imageInfo().bounds()).roundOut(); |
14 | 160k | if (!r.isEmpty()) { |
15 | 160k | SkASSERT(this->imageInfo().bounds().contains(r)); |
16 | 160k | } |
17 | 160k | return r; |
18 | 160k | } |
19 | | |
20 | | /////////////////////////////////////////////////////////////////////////////////////////////////// |
21 | | |
22 | 106k | void SkClipStackDevice::onSave() { |
23 | 106k | fClipStack.save(); |
24 | 106k | } |
25 | | |
26 | 106k | void SkClipStackDevice::onRestore() { |
27 | 106k | fClipStack.restore(); |
28 | 106k | } |
29 | | |
30 | 41.2k | void SkClipStackDevice::onClipRect(const SkRect& rect, SkClipOp op, bool aa) { |
31 | 41.2k | fClipStack.clipRect(rect, this->localToDevice(), op, aa); |
32 | 41.2k | } |
33 | | |
34 | 10.4k | void SkClipStackDevice::onClipRRect(const SkRRect& rrect, SkClipOp op, bool aa) { |
35 | 10.4k | fClipStack.clipRRect(rrect, this->localToDevice(), op, aa); |
36 | 10.4k | } |
37 | | |
38 | 5.35k | void SkClipStackDevice::onClipPath(const SkPath& path, SkClipOp op, bool aa) { |
39 | 5.35k | fClipStack.clipPath(path, this->localToDevice(), op, aa); |
40 | 5.35k | } |
41 | | |
42 | 0 | void SkClipStackDevice::onClipShader(sk_sp<SkShader> shader) { |
43 | 0 | fClipStack.clipShader(std::move(shader)); |
44 | 0 | } |
45 | | |
46 | 2.28k | void SkClipStackDevice::onClipRegion(const SkRegion& rgn, SkClipOp op) { |
47 | 2.28k | SkIPoint origin = this->getOrigin(); |
48 | 2.28k | SkRegion tmp; |
49 | 2.28k | SkPath path; |
50 | 2.28k | rgn.getBoundaryPath(&path); |
51 | 2.28k | path.transform(SkMatrix::Translate(-origin)); |
52 | 2.28k | fClipStack.clipPath(path, SkMatrix::I(), op, false); |
53 | 2.28k | } |
54 | | |
55 | 0 | void SkClipStackDevice::onReplaceClip(const SkIRect& rect) { |
56 | 0 | SkRect deviceRect = SkMatrixPriv::MapRect(this->globalToDevice(), SkRect::Make(rect)); |
57 | 0 | fClipStack.replaceClip(deviceRect, /*doAA=*/false); |
58 | 0 | } |
59 | | |
60 | 0 | bool SkClipStackDevice::onClipIsAA() const { |
61 | 0 | SkClipStack::B2TIter iter(fClipStack); |
62 | 0 | const SkClipStack::Element* element; |
63 | |
|
64 | 0 | while ((element = iter.next()) != nullptr) { |
65 | 0 | if (element->isAA()) { |
66 | 0 | return true; |
67 | 0 | } |
68 | 0 | } |
69 | 0 | return false; |
70 | 0 | } |
71 | | |
72 | 0 | bool SkClipStackDevice::onClipIsWideOpen() const { |
73 | 0 | return fClipStack.quickContains(SkRect::MakeIWH(this->width(), this->height())); |
74 | 0 | } |
75 | | |
76 | 0 | void SkClipStackDevice::onAsRgnClip(SkRegion* rgn) const { |
77 | 0 | SkClipStack::BoundsType boundType; |
78 | 0 | bool isIntersectionOfRects; |
79 | 0 | SkRect bounds; |
80 | 0 | fClipStack.getBounds(&bounds, &boundType, &isIntersectionOfRects); |
81 | 0 | if (isIntersectionOfRects && SkClipStack::kNormal_BoundsType == boundType) { |
82 | 0 | rgn->setRect(bounds.round()); |
83 | 0 | } else { |
84 | 0 | SkRegion boundsRgn({0, 0, this->width(), this->height()}); |
85 | 0 | SkPath tmpPath; |
86 | |
|
87 | 0 | *rgn = boundsRgn; |
88 | 0 | SkClipStack::B2TIter iter(fClipStack); |
89 | 0 | while (auto elem = iter.next()) { |
90 | 0 | tmpPath.rewind(); |
91 | 0 | elem->asDeviceSpacePath(&tmpPath); |
92 | 0 | SkRegion tmpRgn; |
93 | 0 | tmpRgn.setPath(tmpPath, boundsRgn); |
94 | 0 | if (elem->isReplaceOp()) { |
95 | | // All replace elements are rectangles |
96 | | // TODO: SkClipStack can be simplified to be I,D,R ops now, which means element |
97 | | // iteration can be from top of the stack to the most recent replace element. |
98 | | // When that's done, this loop will be simplifiable. |
99 | 0 | rgn->setRect(elem->getDeviceSpaceRect().round()); |
100 | 0 | } else { |
101 | 0 | rgn->op(tmpRgn, static_cast<SkRegion::Op>(elem->getOp())); |
102 | 0 | } |
103 | 0 | } |
104 | 0 | } |
105 | 0 | } |
106 | | |
107 | 263k | SkBaseDevice::ClipType SkClipStackDevice::onGetClipType() const { |
108 | 263k | if (fClipStack.isWideOpen()) { |
109 | 125k | return ClipType::kRect; |
110 | 125k | } |
111 | 138k | if (fClipStack.isEmpty(SkIRect::MakeWH(this->width(), this->height()))) { |
112 | 102k | return ClipType::kEmpty; |
113 | 35.8k | } else { |
114 | 35.8k | SkClipStack::BoundsType boundType; |
115 | 35.8k | bool isIntersectionOfRects; |
116 | 35.8k | SkRect bounds; |
117 | 35.8k | fClipStack.getBounds(&bounds, &boundType, &isIntersectionOfRects); |
118 | 35.8k | if (isIntersectionOfRects && SkClipStack::kNormal_BoundsType == boundType) { |
119 | 2.04k | return ClipType::kRect; |
120 | 33.8k | } else { |
121 | 33.8k | return ClipType::kComplex; |
122 | 33.8k | } |
123 | 35.8k | } |
124 | 138k | } |