Line data Source code
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 : #ifndef SkRasterClipStack_DEFINED
9 : #define SkRasterClipStack_DEFINED
10 :
11 : #include "SkClipOp.h"
12 : #include "SkDeque.h"
13 : #include "SkRasterClip.h"
14 :
15 : template <typename T> class SkTStack {
16 : public:
17 85 : SkTStack(void* storage, size_t size) : fDeque(sizeof(T), storage, size), fTop(nullptr) {}
18 118 : ~SkTStack() {
19 177 : while (!fDeque.empty()) {
20 59 : ((T*)fDeque.back())->~T();
21 59 : fDeque.pop_back();
22 : }
23 59 : }
24 :
25 : bool empty() const { return fDeque.empty(); }
26 :
27 680 : int count() const { return fDeque.count(); }
28 :
29 1047 : const T& top() const {
30 1047 : SkASSERT(fTop);
31 1047 : return *fTop;
32 : }
33 :
34 6271 : T& top() {
35 6271 : SkASSERT(fTop);
36 6271 : return *fTop;
37 : }
38 :
39 680 : T* push_raw() { return (T*)fDeque.push_back(); }
40 85 : T& push() {
41 85 : fTop = this->push_raw();
42 85 : new (fTop) T();
43 85 : return *fTop;
44 : }
45 595 : T& push(const T& src) {
46 595 : fTop = this->push_raw();
47 595 : new (fTop) T(src);
48 595 : return *fTop;
49 : }
50 :
51 595 : void pop() {
52 595 : fTop->~T();
53 595 : fDeque.pop_back();
54 595 : fTop = fDeque.empty() ? nullptr : (T*)fDeque.back();
55 595 : }
56 :
57 : private:
58 : SkDeque fDeque;
59 : T* fTop;
60 : };
61 :
62 59 : class SkRasterClipStack : SkNoncopyable {
63 : int fCounter = 0;
64 : public:
65 85 : SkRasterClipStack(int width, int height)
66 85 : : fStack(fStorage, sizeof(fStorage))
67 85 : , fRootBounds(SkIRect::MakeWH(width, height))
68 : {
69 85 : Rec& rec = fStack.push();
70 85 : rec.fRC.setRect(fRootBounds);
71 85 : rec.fDeferredCount = 0;
72 85 : SkASSERT(fStack.count() == 1);
73 85 : }
74 :
75 : void setNewSize(int w, int h) {
76 : fRootBounds.setXYWH(0, 0, w, h);
77 :
78 : SkASSERT(fStack.count() == 1);
79 : Rec& rec = fStack.top();
80 : SkASSERT(rec.fDeferredCount == 0);
81 : rec.fRC.setRect(fRootBounds);
82 : }
83 :
84 1047 : const SkRasterClip& rc() const { return fStack.top().fRC; }
85 :
86 617 : void save() {
87 617 : fCounter += 1;
88 617 : SkASSERT(fStack.top().fDeferredCount >= 0);
89 617 : fStack.top().fDeferredCount += 1;
90 617 : }
91 :
92 617 : void restore() {
93 617 : fCounter -= 1; SkASSERT(fCounter >= 0);
94 617 : if (--fStack.top().fDeferredCount < 0) {
95 595 : SkASSERT(fStack.top().fDeferredCount == -1);
96 595 : SkASSERT(fStack.count() > 1);
97 595 : fStack.pop();
98 : }
99 617 : }
100 :
101 532 : void clipRect(const SkMatrix& ctm, const SkRect& rect, SkClipOp op, bool aa) {
102 532 : this->writable_rc().op(rect, ctm, fRootBounds, (SkRegion::Op)op, aa);
103 532 : this->trimIfExpanding(op);
104 532 : this->validate();
105 532 : }
106 :
107 0 : void clipRRect(const SkMatrix& ctm, const SkRRect& rrect, SkClipOp op, bool aa) {
108 0 : this->writable_rc().op(rrect, ctm, fRootBounds, (SkRegion::Op)op, aa);
109 0 : this->trimIfExpanding(op);
110 0 : this->validate();
111 0 : }
112 :
113 39 : void clipPath(const SkMatrix& ctm, const SkPath& path, SkClipOp op, bool aa) {
114 39 : this->writable_rc().op(path, ctm, fRootBounds, (SkRegion::Op)op, aa);
115 39 : this->trimIfExpanding(op);
116 39 : this->validate();
117 39 : }
118 :
119 24 : void clipRegion(const SkRegion& rgn, SkClipOp op) {
120 24 : this->writable_rc().op(rgn, (SkRegion::Op)op);
121 24 : this->trimIfExpanding(op);
122 24 : this->validate();
123 24 : }
124 :
125 85 : void setDeviceClipRestriction(SkIRect* mutableClipRestriction) {
126 85 : this->writable_rc().setDeviceClipRestriction(mutableClipRestriction);
127 85 : }
128 :
129 595 : void validate() const {
130 : #ifdef SK_DEBUG
131 595 : const SkRasterClip& clip = this->rc();
132 595 : if (fRootBounds.isEmpty()) {
133 0 : SkASSERT(clip.isEmpty());
134 595 : } else if (!clip.isEmpty()) {
135 580 : SkASSERT(fRootBounds.contains(clip.getBounds()));
136 : }
137 : #endif
138 595 : }
139 :
140 : private:
141 1334 : struct Rec {
142 : SkRasterClip fRC;
143 : int fDeferredCount; // 0 for a "normal" entry
144 : };
145 :
146 : enum {
147 : ELEM_COUNT = 16,
148 : PTR_COUNT = ELEM_COUNT * sizeof(Rec) / sizeof(void*)
149 : };
150 : void* fStorage[PTR_COUNT];
151 : SkTStack<Rec> fStack;
152 : SkIRect fRootBounds;
153 :
154 680 : SkRasterClip& writable_rc() {
155 680 : SkASSERT(fStack.top().fDeferredCount >= 0);
156 680 : if (fStack.top().fDeferredCount > 0) {
157 595 : fStack.top().fDeferredCount -= 1;
158 595 : fStack.push(fStack.top());
159 595 : fStack.top().fDeferredCount = 0;
160 : }
161 680 : return fStack.top().fRC;
162 : }
163 :
164 595 : void trimIfExpanding(SkClipOp op) {
165 595 : if ((int)op > (int)SkClipOp::kIntersect) {
166 0 : Rec& rec = fStack.top();
167 0 : SkASSERT(rec.fDeferredCount == 0);
168 0 : rec.fRC.op(fRootBounds, SkRegion::kIntersect_Op);
169 : }
170 595 : }
171 : };
172 :
173 : #endif
|