/src/skia/src/pathops/SkOpCoincidence.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2013 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 | | #ifndef SkOpCoincidence_DEFINED |
8 | | #define SkOpCoincidence_DEFINED |
9 | | |
10 | | #include "include/private/SkTDArray.h" |
11 | | #include "src/core/SkArenaAlloc.h" |
12 | | #include "src/pathops/SkOpSpan.h" |
13 | | #include "src/pathops/SkPathOpsTypes.h" |
14 | | |
15 | | class SkOpPtT; |
16 | | class SkOpSpanBase; |
17 | | |
18 | | class SkCoincidentSpans { |
19 | | public: |
20 | | const SkOpPtT* coinPtTEnd() const; |
21 | | const SkOpPtT* coinPtTStart() const; |
22 | | |
23 | | // These return non-const pointers so that, as copies, they can be added |
24 | | // to a new span pair |
25 | 3.67M | SkOpPtT* coinPtTEndWritable() const { return const_cast<SkOpPtT*>(fCoinPtTEnd); } |
26 | 6.07M | SkOpPtT* coinPtTStartWritable() const { return const_cast<SkOpPtT*>(fCoinPtTStart); } |
27 | | |
28 | | bool collapsed(const SkOpPtT* ) const; |
29 | | bool contains(const SkOpPtT* s, const SkOpPtT* e) const; |
30 | | void correctEnds(); |
31 | | void correctOneEnd(const SkOpPtT* (SkCoincidentSpans::* getEnd)() const, |
32 | | void (SkCoincidentSpans::* setEnd)(const SkOpPtT* ptT) ); |
33 | | |
34 | | #if DEBUG_COIN |
35 | | void debugCorrectEnds(SkPathOpsDebug::GlitchLog* log) const; |
36 | | void debugCorrectOneEnd(SkPathOpsDebug::GlitchLog* log, |
37 | | const SkOpPtT* (SkCoincidentSpans::* getEnd)() const, |
38 | | void (SkCoincidentSpans::* setEnd)(const SkOpPtT* ptT) const) const; |
39 | | bool debugExpand(SkPathOpsDebug::GlitchLog* log) const; |
40 | | #endif |
41 | | |
42 | 0 | const char* debugID() const { |
43 | 0 | #if DEBUG_COIN |
44 | 0 | return fGlobalState->debugCoinDictEntry().fFunctionName; |
45 | 0 | #else |
46 | 0 | return nullptr; |
47 | 0 | #endif |
48 | 0 | } |
49 | | |
50 | | void debugShow() const; |
51 | | #ifdef SK_DEBUG |
52 | | void debugStartCheck(const SkOpSpanBase* outer, const SkOpSpanBase* over, |
53 | | const SkOpGlobalState* debugState) const; |
54 | | #endif |
55 | | void dump() const; |
56 | | bool expand(); |
57 | | bool extend(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
58 | | const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd); |
59 | 52.3M | bool flipped() const { return fOppPtTStart->fT > fOppPtTEnd->fT; } |
60 | | SkDEBUGCODE(SkOpGlobalState* globalState() { return fGlobalState; }) |
61 | | |
62 | 3.60M | void init(SkDEBUGCODE(SkOpGlobalState* globalState)) { |
63 | 3.60M | sk_bzero(this, sizeof(*this)); |
64 | 0 | SkDEBUGCODE(fGlobalState = globalState); |
65 | 3.60M | } SkCoincidentSpans::init() Line | Count | Source | 62 | 3.60M | void init(SkDEBUGCODE(SkOpGlobalState* globalState)) { | 63 | 3.60M | sk_bzero(this, sizeof(*this)); | 64 | 3.60M | SkDEBUGCODE(fGlobalState = globalState); | 65 | 3.60M | } |
Unexecuted instantiation: SkCoincidentSpans::init(SkOpGlobalState*) |
66 | | |
67 | 11.6G | SkCoincidentSpans* next() { return fNext; } |
68 | 1.44G | const SkCoincidentSpans* next() const { return fNext; } |
69 | 8.29M | SkCoincidentSpans** nextPtr() { return &fNext; } |
70 | | const SkOpPtT* oppPtTStart() const; |
71 | | const SkOpPtT* oppPtTEnd() const; |
72 | | // These return non-const pointers so that, as copies, they can be added |
73 | | // to a new span pair |
74 | 4.87M | SkOpPtT* oppPtTStartWritable() const { return const_cast<SkOpPtT*>(fOppPtTStart); } |
75 | 4.87M | SkOpPtT* oppPtTEndWritable() const { return const_cast<SkOpPtT*>(fOppPtTEnd); } |
76 | | bool ordered(bool* result) const; |
77 | | |
78 | | void set(SkCoincidentSpans* next, const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
79 | | const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd); |
80 | | |
81 | 4.32M | void setCoinPtTEnd(const SkOpPtT* ptT) { |
82 | 4.32M | SkOPASSERT(ptT == ptT->span()->ptT()); |
83 | 4.32M | SkOPASSERT(!fCoinPtTStart || ptT->fT != fCoinPtTStart->fT); |
84 | 4.32M | SkASSERT(!fCoinPtTStart || fCoinPtTStart->segment() == ptT->segment()); |
85 | 4.32M | fCoinPtTEnd = ptT; |
86 | 4.32M | ptT->setCoincident(); |
87 | 4.32M | } |
88 | | |
89 | 4.19M | void setCoinPtTStart(const SkOpPtT* ptT) { |
90 | 4.19M | SkOPASSERT(ptT == ptT->span()->ptT()); |
91 | 4.19M | SkOPASSERT(!fCoinPtTEnd || ptT->fT != fCoinPtTEnd->fT); |
92 | 4.19M | SkASSERT(!fCoinPtTEnd || fCoinPtTEnd->segment() == ptT->segment()); |
93 | 4.19M | fCoinPtTStart = ptT; |
94 | 4.19M | ptT->setCoincident(); |
95 | 4.19M | } |
96 | | |
97 | 4.14M | void setEnds(const SkOpPtT* coinPtTEnd, const SkOpPtT* oppPtTEnd) { |
98 | 4.14M | this->setCoinPtTEnd(coinPtTEnd); |
99 | 4.14M | this->setOppPtTEnd(oppPtTEnd); |
100 | 4.14M | } |
101 | | |
102 | 4.36M | void setOppPtTEnd(const SkOpPtT* ptT) { |
103 | 4.36M | SkOPASSERT(ptT == ptT->span()->ptT()); |
104 | 4.36M | SkOPASSERT(!fOppPtTStart || ptT->fT != fOppPtTStart->fT); |
105 | 4.36M | SkASSERT(!fOppPtTStart || fOppPtTStart->segment() == ptT->segment()); |
106 | 4.36M | fOppPtTEnd = ptT; |
107 | 4.36M | ptT->setCoincident(); |
108 | 4.36M | } |
109 | | |
110 | 4.11M | void setOppPtTStart(const SkOpPtT* ptT) { |
111 | 4.11M | SkOPASSERT(ptT == ptT->span()->ptT()); |
112 | 4.11M | SkOPASSERT(!fOppPtTEnd || ptT->fT != fOppPtTEnd->fT); |
113 | 4.11M | SkASSERT(!fOppPtTEnd || fOppPtTEnd->segment() == ptT->segment()); |
114 | 4.11M | fOppPtTStart = ptT; |
115 | 4.11M | ptT->setCoincident(); |
116 | 4.11M | } |
117 | | |
118 | 3.91M | void setStarts(const SkOpPtT* coinPtTStart, const SkOpPtT* oppPtTStart) { |
119 | 3.91M | this->setCoinPtTStart(coinPtTStart); |
120 | 3.91M | this->setOppPtTStart(oppPtTStart); |
121 | 3.91M | } |
122 | | |
123 | 382k | void setNext(SkCoincidentSpans* next) { fNext = next; } |
124 | | |
125 | | private: |
126 | | SkCoincidentSpans* fNext; |
127 | | const SkOpPtT* fCoinPtTStart; |
128 | | const SkOpPtT* fCoinPtTEnd; |
129 | | const SkOpPtT* fOppPtTStart; |
130 | | const SkOpPtT* fOppPtTEnd; |
131 | | SkDEBUGCODE(SkOpGlobalState* fGlobalState); |
132 | | }; |
133 | | |
134 | | class SkOpCoincidence { |
135 | | public: |
136 | | SkOpCoincidence(SkOpGlobalState* globalState) |
137 | | : fHead(nullptr) |
138 | | , fTop(nullptr) |
139 | | , fGlobalState(globalState) |
140 | | , fContinue(false) |
141 | | , fSpanDeleted(false) |
142 | | , fPtAllocated(false) |
143 | | , fCoinExtended(false) |
144 | 729k | , fSpanMerged(false) { |
145 | 729k | globalState->setCoincidence(this); |
146 | 729k | } |
147 | | |
148 | | void add(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpPtT* oppPtTStart, |
149 | | SkOpPtT* oppPtTEnd); |
150 | | bool addEndMovedSpans(DEBUG_COIN_DECLARE_ONLY_PARAMS()); |
151 | | bool addExpanded(DEBUG_COIN_DECLARE_ONLY_PARAMS()); |
152 | | bool addMissing(bool* added DEBUG_COIN_DECLARE_PARAMS()); |
153 | | bool apply(DEBUG_COIN_DECLARE_ONLY_PARAMS()); |
154 | | bool contains(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
155 | | const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd) const; |
156 | | void correctEnds(DEBUG_COIN_DECLARE_ONLY_PARAMS()); |
157 | | |
158 | | #if DEBUG_COIN |
159 | | void debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* log) const; |
160 | | void debugAddExpanded(SkPathOpsDebug::GlitchLog* ) const; |
161 | | void debugAddMissing(SkPathOpsDebug::GlitchLog* , bool* added) const; |
162 | | void debugAddOrOverlap(SkPathOpsDebug::GlitchLog* log, |
163 | | const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, |
164 | | double coinTs, double coinTe, double oppTs, double oppTe, |
165 | | bool* added) const; |
166 | | #endif |
167 | | |
168 | 0 | const SkOpAngle* debugAngle(int id) const { |
169 | 0 | return SkDEBUGRELEASE(fGlobalState->debugAngle(id), nullptr); |
170 | 0 | } |
171 | | |
172 | | void debugCheckBetween() const; |
173 | | |
174 | | #if DEBUG_COIN |
175 | | void debugCheckValid(SkPathOpsDebug::GlitchLog* log) const; |
176 | | #endif |
177 | | |
178 | 0 | SkOpContour* debugContour(int id) const { |
179 | 0 | return SkDEBUGRELEASE(fGlobalState->debugContour(id), nullptr); |
180 | 0 | } |
181 | | |
182 | | #if DEBUG_COIN |
183 | | void debugCorrectEnds(SkPathOpsDebug::GlitchLog* log) const; |
184 | | bool debugExpand(SkPathOpsDebug::GlitchLog* ) const; |
185 | | void debugMark(SkPathOpsDebug::GlitchLog* ) const; |
186 | | void debugMarkCollapsed(SkPathOpsDebug::GlitchLog* , |
187 | | const SkCoincidentSpans* coin, const SkOpPtT* test) const; |
188 | | void debugMarkCollapsed(SkPathOpsDebug::GlitchLog* , const SkOpPtT* test) const; |
189 | | #endif |
190 | | |
191 | 0 | const SkOpPtT* debugPtT(int id) const { |
192 | 0 | return SkDEBUGRELEASE(fGlobalState->debugPtT(id), nullptr); |
193 | 0 | } |
194 | | |
195 | 0 | const SkOpSegment* debugSegment(int id) const { |
196 | 0 | return SkDEBUGRELEASE(fGlobalState->debugSegment(id), nullptr); |
197 | 0 | } |
198 | | |
199 | | #if DEBUG_COIN |
200 | | void debugRelease(SkPathOpsDebug::GlitchLog* , const SkCoincidentSpans* , |
201 | | const SkCoincidentSpans* ) const; |
202 | | void debugRelease(SkPathOpsDebug::GlitchLog* , const SkOpSegment* ) const; |
203 | | #endif |
204 | | void debugShowCoincidence() const; |
205 | | |
206 | 0 | const SkOpSpanBase* debugSpan(int id) const { |
207 | 0 | return SkDEBUGRELEASE(fGlobalState->debugSpan(id), nullptr); |
208 | 0 | } |
209 | | |
210 | | void debugValidate() const; |
211 | | void dump() const; |
212 | | bool expand(DEBUG_COIN_DECLARE_ONLY_PARAMS()); |
213 | | bool extend(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, const SkOpPtT* oppPtTStart, |
214 | | const SkOpPtT* oppPtTEnd); |
215 | | bool findOverlaps(SkOpCoincidence* DEBUG_COIN_DECLARE_PARAMS()) const; |
216 | | void fixUp(SkOpPtT* deleted, const SkOpPtT* kept); |
217 | | |
218 | 3.60M | SkOpGlobalState* globalState() { |
219 | 3.60M | return fGlobalState; |
220 | 3.60M | } |
221 | | |
222 | 0 | const SkOpGlobalState* globalState() const { |
223 | 0 | return fGlobalState; |
224 | 0 | } |
225 | | |
226 | 31.6M | bool isEmpty() const { |
227 | 31.6M | return !fHead && !fTop; |
228 | 31.6M | } |
229 | | |
230 | | bool mark(DEBUG_COIN_DECLARE_ONLY_PARAMS()); |
231 | | void markCollapsed(SkOpPtT* ); |
232 | | |
233 | 10.7M | static bool Ordered(const SkOpPtT* coinPtTStart, const SkOpPtT* oppPtTStart) { |
234 | 10.7M | return Ordered(coinPtTStart->segment(), oppPtTStart->segment()); |
235 | 10.7M | } |
236 | | |
237 | | static bool Ordered(const SkOpSegment* coin, const SkOpSegment* opp); |
238 | | void release(const SkOpSegment* ); |
239 | | void releaseDeleted(); |
240 | | |
241 | | private: |
242 | | void add(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, const SkOpPtT* oppPtTStart, |
243 | 603k | const SkOpPtT* oppPtTEnd) { |
244 | 603k | this->add(const_cast<SkOpPtT*>(coinPtTStart), const_cast<SkOpPtT*>(coinPtTEnd), |
245 | 603k | const_cast<SkOpPtT*>(oppPtTStart), const_cast<SkOpPtT*>(oppPtTEnd)); |
246 | 603k | } |
247 | | |
248 | | bool addEndMovedSpans(const SkOpSpan* base, const SkOpSpanBase* testSpan); |
249 | | bool addEndMovedSpans(const SkOpPtT* ptT); |
250 | | |
251 | | bool addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over2s, |
252 | | double tStart, double tEnd, SkOpSegment* coinSeg, SkOpSegment* oppSeg, |
253 | | bool* added |
254 | | SkDEBUGPARAMS(const SkOpPtT* over1e) SkDEBUGPARAMS(const SkOpPtT* over2e)); |
255 | | bool addOrOverlap(SkOpSegment* coinSeg, SkOpSegment* oppSeg, |
256 | | double coinTs, double coinTe, double oppTs, double oppTe, bool* added); |
257 | | bool addOverlap(const SkOpSegment* seg1, const SkOpSegment* seg1o, |
258 | | const SkOpSegment* seg2, const SkOpSegment* seg2o, |
259 | | const SkOpPtT* overS, const SkOpPtT* overE); |
260 | | bool checkOverlap(SkCoincidentSpans* check, |
261 | | const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, |
262 | | double coinTs, double coinTe, double oppTs, double oppTe, |
263 | | SkTDArray<SkCoincidentSpans*>* overlaps) const; |
264 | | bool contains(const SkOpSegment* seg, const SkOpSegment* opp, double oppT) const; |
265 | | bool contains(const SkCoincidentSpans* coin, const SkOpSegment* seg, |
266 | | const SkOpSegment* opp, double oppT) const; |
267 | | #if DEBUG_COIN |
268 | | void debugAddIfMissing(SkPathOpsDebug::GlitchLog* , |
269 | | const SkCoincidentSpans* outer, const SkOpPtT* over1s, |
270 | | const SkOpPtT* over1e) const; |
271 | | void debugAddIfMissing(SkPathOpsDebug::GlitchLog* , |
272 | | const SkOpPtT* over1s, const SkOpPtT* over2s, |
273 | | double tStart, double tEnd, |
274 | | const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, bool* added, |
275 | | const SkOpPtT* over1e, const SkOpPtT* over2e) const; |
276 | | void debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* , |
277 | | const SkOpSpan* base, const SkOpSpanBase* testSpan) const; |
278 | | void debugAddEndMovedSpans(SkPathOpsDebug::GlitchLog* , |
279 | | const SkOpPtT* ptT) const; |
280 | | #endif |
281 | | void fixUp(SkCoincidentSpans* coin, SkOpPtT* deleted, const SkOpPtT* kept); |
282 | | void markCollapsed(SkCoincidentSpans* head, SkOpPtT* test); |
283 | | bool overlap(const SkOpPtT* coinStart1, const SkOpPtT* coinEnd1, |
284 | | const SkOpPtT* coinStart2, const SkOpPtT* coinEnd2, |
285 | | double* overS, double* overE) const; |
286 | | bool release(SkCoincidentSpans* coin, SkCoincidentSpans* ); |
287 | | void releaseDeleted(SkCoincidentSpans* ); |
288 | | void restoreHead(); |
289 | | // return coinPtT->segment()->t mapped from overS->fT <= t <= overE->fT |
290 | | static double TRange(const SkOpPtT* overS, double t, const SkOpSegment* coinPtT |
291 | | SkDEBUGPARAMS(const SkOpPtT* overE)); |
292 | | |
293 | | SkCoincidentSpans* fHead; |
294 | | SkCoincidentSpans* fTop; |
295 | | SkOpGlobalState* fGlobalState; |
296 | | bool fContinue; |
297 | | bool fSpanDeleted; |
298 | | bool fPtAllocated; |
299 | | bool fCoinExtended; |
300 | | bool fSpanMerged; |
301 | | }; |
302 | | |
303 | | #endif |