Coverage Report

Created: 2021-08-22 09:07

/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