OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 #ifndef SkOpCoincidence_DEFINED | 7 #ifndef SkOpCoincidence_DEFINED |
8 #define SkOpCoincidence_DEFINED | 8 #define SkOpCoincidence_DEFINED |
9 | 9 |
| 10 #include "SkTDArray.h" |
10 #include "SkOpTAllocator.h" | 11 #include "SkOpTAllocator.h" |
11 #include "SkOpSpan.h" | 12 #include "SkOpSpan.h" |
12 #include "SkPathOpsTypes.h" | 13 #include "SkPathOpsTypes.h" |
13 | 14 |
14 class SkOpPtT; | 15 class SkOpPtT; |
15 | 16 class SkOpSpanBase; |
16 struct SkCoincidentSpans { | 17 |
17 SkCoincidentSpans* fNext; | 18 class SkCoincidentSpans { |
18 SkOpPtT* fCoinPtTStart; | 19 public: |
19 SkOpPtT* fCoinPtTEnd; | 20 const SkOpPtT* coinPtTEnd() const { return fCoinPtTEnd; } |
20 SkOpPtT* fOppPtTStart; | 21 const SkOpPtT* coinPtTStart() const { return fCoinPtTStart; } |
21 SkOpPtT* fOppPtTEnd; | 22 |
22 bool fFlipped; | 23 // These return non-const pointers so that, as copies, they can be added |
23 SkDEBUGCODE(int fID); | 24 // to a new span pair |
| 25 SkOpPtT* coinPtTEndWritable() const { return const_cast<SkOpPtT*>(fCoinPtTEn
d); } |
| 26 SkOpPtT* coinPtTStartWritable() const { return const_cast<SkOpPtT*>(fCoinPtT
Start); } |
| 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_COINCIDENCE_VERBOSE |
| 35 bool debugExpand(const char* id, SkPathOpsDebug::GlitchLog* log) const; |
| 36 #endif |
24 | 37 |
25 int debugID() const { | 38 int debugID() const { |
26 return SkDEBUGRELEASE(fID, -1); | 39 return SkDEBUGRELEASE(fID, -1); |
27 } | 40 } |
28 | 41 |
| 42 void debugShow() const; |
| 43 #ifdef SK_DEBUG |
| 44 void debugStartCheck(const SkOpSpanBase* outer, const SkOpSpanBase* over, |
| 45 const SkOpGlobalState* debugState) const; |
| 46 #endif |
29 void dump() const; | 47 void dump() const; |
| 48 bool expand(); |
| 49 bool extend(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
| 50 const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd); |
| 51 bool flipped() const { return fOppPtTStart->fT > fOppPtTEnd->fT; } |
| 52 void init() { sk_bzero(this, sizeof(*this)); } |
| 53 const SkOpPtT* oppPtTStart() const { return fOppPtTStart; } |
| 54 const SkOpPtT* oppPtTEnd() const { return fOppPtTEnd; } |
| 55 // These return non-const pointers so that, as copies, they can be added |
| 56 // to a new span pair |
| 57 SkOpPtT* oppPtTStartWritable() const { return const_cast<SkOpPtT*>(fOppPtTSt
art); } |
| 58 SkOpPtT* oppPtTEndWritable() const { return const_cast<SkOpPtT*>(fOppPtTEnd)
; } |
| 59 SkCoincidentSpans* next() { return fNext; } |
| 60 const SkCoincidentSpans* next() const { return fNext; } |
| 61 SkCoincidentSpans** nextPtr() { return &fNext; } |
| 62 int spanCount() const; |
| 63 |
| 64 void set(SkCoincidentSpans* next, const SkOpPtT* coinPtTStart, const SkOpPtT
* coinPtTEnd, |
| 65 const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd |
| 66 SkDEBUGPARAMS(int id)); |
| 67 |
| 68 void setCoinPtTEnd(const SkOpPtT* ptT) { |
| 69 SkASSERT(ptT == ptT->span()->ptT()) |
| 70 SkASSERT(!fCoinPtTStart || ptT->fT != fCoinPtTStart->fT); |
| 71 SkASSERT(!fCoinPtTStart || fCoinPtTStart->segment() == ptT->segment()); |
| 72 fCoinPtTEnd = ptT; |
| 73 ptT->setCoincident(); |
| 74 } |
| 75 |
| 76 void setCoinPtTStart(const SkOpPtT* ptT) { |
| 77 SkASSERT(ptT == ptT->span()->ptT()) |
| 78 SkASSERT(!fCoinPtTEnd || ptT->fT != fCoinPtTEnd->fT); |
| 79 SkASSERT(!fCoinPtTEnd || fCoinPtTEnd->segment() == ptT->segment()); |
| 80 fCoinPtTStart = ptT; |
| 81 ptT->setCoincident(); |
| 82 } |
| 83 |
| 84 void setEnds(const SkOpPtT* coinPtTEnd, const SkOpPtT* oppPtTEnd) { |
| 85 this->setCoinPtTEnd(coinPtTEnd); |
| 86 this->setOppPtTEnd(oppPtTEnd); |
| 87 } |
| 88 |
| 89 void setOppPtTEnd(const SkOpPtT* ptT) { |
| 90 SkASSERT(ptT == ptT->span()->ptT()) |
| 91 SkASSERT(!fOppPtTStart || ptT->fT != fOppPtTStart->fT); |
| 92 SkASSERT(!fOppPtTStart || fOppPtTStart->segment() == ptT->segment()); |
| 93 fOppPtTEnd = ptT; |
| 94 ptT->setCoincident(); |
| 95 } |
| 96 |
| 97 void setOppPtTStart(const SkOpPtT* ptT) { |
| 98 SkASSERT(ptT == ptT->span()->ptT()) |
| 99 SkASSERT(!fOppPtTEnd || ptT->fT != fOppPtTEnd->fT); |
| 100 SkASSERT(!fOppPtTEnd || fOppPtTEnd->segment() == ptT->segment()); |
| 101 fOppPtTStart = ptT; |
| 102 ptT->setCoincident(); |
| 103 } |
| 104 |
| 105 void setStarts(const SkOpPtT* coinPtTStart, const SkOpPtT* oppPtTStart) { |
| 106 this->setCoinPtTStart(coinPtTStart); |
| 107 this->setOppPtTStart(oppPtTStart); |
| 108 } |
| 109 |
| 110 void setNext(SkCoincidentSpans* next) { fNext = next; } |
| 111 |
| 112 bool startEquals(const SkOpSpanBase* outer, const SkOpSpanBase* over) const
{ |
| 113 return fCoinPtTStart->span() == over && fOppPtTStart->span() == outer; |
| 114 } |
| 115 private: |
| 116 SkCoincidentSpans* fNext; |
| 117 const SkOpPtT* fCoinPtTStart; |
| 118 const SkOpPtT* fCoinPtTEnd; |
| 119 const SkOpPtT* fOppPtTStart; |
| 120 const SkOpPtT* fOppPtTEnd; |
| 121 SkDEBUGCODE(int fID); |
30 }; | 122 }; |
31 | 123 |
32 class SkOpCoincidence { | 124 class SkOpCoincidence { |
33 public: | 125 public: |
34 SkOpCoincidence() | 126 SkOpCoincidence(SkOpGlobalState* globalState) |
35 : fHead(nullptr) | 127 : fHead(nullptr) |
36 , fTop(nullptr) | 128 , fTop(nullptr) |
37 SkDEBUGPARAMS(fDebugState(nullptr)) | 129 , fGlobalState(globalState) |
38 { | 130 , fContinue(false) |
| 131 , fSpanDeleted(false) |
| 132 , fPtAllocated(false) |
| 133 , fCoinExtended(false) |
| 134 , fSpanMerged(false) { |
| 135 globalState->setCoincidence(this); |
39 } | 136 } |
40 | 137 |
41 void add(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpPtT* oppPtTStart, | 138 void add(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpPtT* oppPtTStart, |
42 SkOpPtT* oppPtTEnd, SkChunkAlloc* allocator); | 139 SkOpPtT* oppPtTEnd); |
43 bool addExpanded(SkChunkAlloc* allocator PATH_OPS_DEBUG_VALIDATE_PARAMS(SkO
pGlobalState* )); | 140 bool addEndMovedSpans(); |
44 bool addMissing(SkChunkAlloc* allocator); | 141 bool addExpanded(); |
| 142 bool addMissing(); |
| 143 bool addUncommon(); |
45 bool apply(); | 144 bool apply(); |
46 bool contains(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, | 145 bool contains(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
47 const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, bool fli
pped) const; | 146 const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd) const; |
48 | 147 void correctEnds(); |
| 148 |
| 149 #if DEBUG_COINCIDENCE_VERBOSE |
49 void debugAddExpanded(const char* id, SkPathOpsDebug::GlitchLog* ) const; | 150 void debugAddExpanded(const char* id, SkPathOpsDebug::GlitchLog* ) const; |
50 void debugAddMissing(const char* id, SkPathOpsDebug::GlitchLog* ) const; | 151 void debugAddMissing(const char* id, SkPathOpsDebug::GlitchLog* ) const; |
| 152 void debugAddOrOverlap(const SkOpSegment* coinSeg, const SkOpSegment* oppSeg
, |
| 153 double coinTs, double coinTe, double oppTs, double op
pTe, |
| 154 const char* id, SkPathOpsDebug::GlitchLog* log) const
; |
| 155 #endif |
51 | 156 |
52 const SkOpAngle* debugAngle(int id) const { | 157 const SkOpAngle* debugAngle(int id) const { |
53 return SkDEBUGRELEASE(fDebugState->debugAngle(id), nullptr); | 158 return SkDEBUGRELEASE(fGlobalState->debugAngle(id), nullptr); |
54 } | 159 } |
| 160 |
| 161 #if DEBUG_COINCIDENCE_VERBOSE |
| 162 void debugCheckOverlap(const char* id, SkPathOpsDebug::GlitchLog* log) const
; |
| 163 void debugCheckValid(const char* id, SkPathOpsDebug::GlitchLog* log) const; |
| 164 #endif |
55 | 165 |
56 SkOpContour* debugContour(int id) { | 166 SkOpContour* debugContour(int id) { |
57 return SkDEBUGRELEASE(fDebugState->debugContour(id), nullptr); | 167 return SkDEBUGRELEASE(fGlobalState->debugContour(id), nullptr); |
58 } | 168 } |
59 | 169 |
| 170 #if DEBUG_COINCIDENCE_VERBOSE |
60 bool debugExpand(const char* id, SkPathOpsDebug::GlitchLog* ) const; | 171 bool debugExpand(const char* id, SkPathOpsDebug::GlitchLog* ) const; |
61 void debugMark(const char* id, SkPathOpsDebug::GlitchLog* ) const; | 172 void debugMark(const char* id, SkPathOpsDebug::GlitchLog* ) const; |
| 173 void debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchLog* , |
| 174 const SkCoincidentSpans* coin, const SkOpPtT* test)
const; |
| 175 void debugMarkCollapsed(const char* id, SkPathOpsDebug::GlitchLog* , const S
kOpPtT* test) const; |
| 176 #endif |
62 | 177 |
63 const SkOpPtT* debugPtT(int id) const { | 178 const SkOpPtT* debugPtT(int id) const { |
64 return SkDEBUGRELEASE(fDebugState->debugPtT(id), nullptr); | 179 return SkDEBUGRELEASE(fGlobalState->debugPtT(id), nullptr); |
65 } | 180 } |
66 | 181 |
67 const SkOpSegment* debugSegment(int id) const { | 182 const SkOpSegment* debugSegment(int id) const { |
68 return SkDEBUGRELEASE(fDebugState->debugSegment(id), nullptr); | 183 return SkDEBUGRELEASE(fGlobalState->debugSegment(id), nullptr); |
69 } | 184 } |
70 | 185 |
71 void debugSetGlobalState(SkOpGlobalState* debugState) { | 186 #if DEBUG_COINCIDENCE_VERBOSE |
72 SkDEBUGCODE(fDebugState = debugState); | 187 void debugRemoveCollapsed(const char* id, SkPathOpsDebug::GlitchLog* ) const
; |
73 } | 188 void debugReorder(const char* id, SkPathOpsDebug::GlitchLog* ) const; |
74 | 189 void debugRelease(const char* id, SkPathOpsDebug::GlitchLog* , const SkOpSeg
ment* ) const; |
75 void debugFixAligned(const char* id, SkPathOpsDebug::GlitchLog* ) const; | 190 #endif |
76 void debugShowCoincidence() const; | 191 void debugShowCoincidence() const; |
77 | 192 |
78 const SkOpSpanBase* debugSpan(int id) const { | 193 const SkOpSpanBase* debugSpan(int id) const { |
79 return SkDEBUGRELEASE(fDebugState->debugSpan(id), nullptr); | 194 return SkDEBUGRELEASE(fGlobalState->debugSpan(id), nullptr); |
80 } | 195 } |
81 | 196 |
82 void release(SkCoincidentSpans* ); | 197 void debugValidate() const; |
83 void dump() const; | 198 void dump() const; |
| 199 bool edge(const SkOpPtT* , bool* start) const; |
84 bool expand(); | 200 bool expand(); |
85 bool extend(SkOpPtT* coinPtTStart, SkOpPtT* coinPtTEnd, SkOpPtT* oppPtTStart
, | 201 bool extend(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, const Sk
OpPtT* oppPtTStart, |
86 SkOpPtT* oppPtTEnd); | 202 const SkOpPtT* oppPtTEnd); |
87 bool findOverlaps(SkOpCoincidence* , SkChunkAlloc* allocator) const; | 203 bool findOverlaps(SkOpCoincidence* ) const; |
88 bool fixAligned(); | 204 void fixUp(SkOpPtT* deleted, const SkOpPtT* kept); |
89 void fixUp(SkOpPtT* deleted, SkOpPtT* kept); | 205 |
| 206 SkOpGlobalState* globalState() { |
| 207 return fGlobalState; |
| 208 } |
90 | 209 |
91 bool isEmpty() const { | 210 bool isEmpty() const { |
92 return !fHead; | 211 return !fHead && !fTop; |
93 } | 212 } |
94 | 213 |
95 bool mark(); | 214 bool mark(); |
| 215 void markCollapsed(SkOpPtT* ); |
| 216 |
| 217 static bool Ordered(const SkOpPtT* coinPtTStart, const SkOpPtT* oppPtTStart)
{ |
| 218 return Ordered(coinPtTStart->segment(), oppPtTStart->segment()); |
| 219 } |
| 220 |
| 221 static bool Ordered(const SkOpSegment* coin, const SkOpSegment* opp); |
| 222 void release(const SkOpSegment* ); |
| 223 bool removeCollapsed(); |
| 224 bool reorder(); |
96 | 225 |
97 private: | 226 private: |
98 bool addIfMissing(const SkCoincidentSpans* outer, SkOpPtT* over1s, SkOpPtT*
over1e, | 227 void add(const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, const SkOpP
tT* oppPtTStart, |
99 SkChunkAlloc* ); | 228 const SkOpPtT* oppPtTEnd) { |
| 229 this->add(const_cast<SkOpPtT*>(coinPtTStart), const_cast<SkOpPtT*>(coinP
tTEnd), |
| 230 const_cast<SkOpPtT*>(oppPtTStart), const_cast<SkOpPtT*>(oppPtTEnd)); |
| 231 } |
| 232 |
| 233 void addEndMovedSpans(const SkOpSpan* base, const SkOpSpanBase* testSpan); |
| 234 bool addEndMovedSpans(const SkOpPtT* ptT); |
| 235 |
| 236 bool addIfMissing(const SkCoincidentSpans* outer, SkOpPtT* over1s, SkOpPtT*
over1e); |
| 237 |
| 238 bool addIfMissing(const SkCoincidentSpans* outer, const SkOpPtT* over1s, |
| 239 const SkOpPtT* over1e) { |
| 240 return addIfMissing(outer, const_cast<SkOpPtT*>(over1s), const_cast<SkOp
PtT*>(over1e)); |
| 241 } |
| 242 |
100 bool addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e, | 243 bool addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e, |
101 const SkOpPtT* over2s, const SkOpPtT* over2e, | 244 const SkOpPtT* over2s, const SkOpPtT* over2e, |
102 double tStart, double tEnd, | 245 double tStart, double tEnd, |
103 SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, | 246 SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
104 SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, | 247 SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd); |
105 SkChunkAlloc* ); | 248 |
106 bool addOverlap(SkOpSegment* seg1, SkOpSegment* seg1o, SkOpSegment* seg2, Sk
OpSegment* seg2o, | 249 bool addIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e, |
107 SkOpPtT* overS, SkOpPtT* overE, SkChunkAlloc* ); | 250 const SkOpPtT* over2s, const SkOpPtT* over2e, |
108 bool debugAddIfMissing(const SkCoincidentSpans* outer, const SkOpPtT* over1s
, | 251 double tStart, double tEnd, |
109 const SkOpPtT* over1e) const; | 252 const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, |
110 bool debugAddIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e, | 253 const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd) { |
| 254 return addIfMissing(over1s, over1e, over2s, over2e, tStart, tEnd, |
| 255 const_cast<SkOpPtT*>(coinPtTStart), coinPtTEnd, |
| 256 const_cast<SkOpPtT*>(oppPtTStart), oppPtTEnd); |
| 257 } |
| 258 |
| 259 bool addOrOverlap(SkOpSegment* coinSeg, SkOpSegment* oppSeg, |
| 260 double coinTs, double coinTe, double oppTs, double oppTe); |
| 261 bool addOverlap(const SkOpSegment* seg1, const SkOpSegment* seg1o, |
| 262 const SkOpSegment* seg2, const SkOpSegment* seg2o, |
| 263 const SkOpPtT* overS, const SkOpPtT* overE); |
| 264 bool alreadyAdded(const SkCoincidentSpans* check, const SkCoincidentSpans* o
uter, |
| 265 const SkOpPtT* over1s, const SkOpPtT* over1e) const; |
| 266 bool checkOverlap(SkCoincidentSpans* check, |
| 267 const SkOpSegment* coinSeg, const SkOpSegment* oppSeg, |
| 268 double coinTs, double coinTe, double oppTs, double oppTe, |
| 269 SkTDArray<SkCoincidentSpans*>* overlaps) const; |
| 270 bool contains(const SkOpSegment* seg, const SkOpSegment* opp, double oppT) c
onst; |
| 271 bool contains(const SkCoincidentSpans* coin, const SkOpSegment* seg, |
| 272 const SkOpSegment* opp, double oppT) const; |
| 273 #if DEBUG_COINCIDENCE_VERBOSE |
| 274 void debugAddIfMissing(const SkCoincidentSpans* outer, const SkOpPtT* over1s
, |
| 275 const SkOpPtT* over1e, const char* id, SkPathOpsDebug
::GlitchLog*) const; |
| 276 void debugAddIfMissing(const SkOpPtT* over1s, const SkOpPtT* over1e, |
111 const SkOpPtT* over2s, const SkOpPtT* over2e, | 277 const SkOpPtT* over2s, const SkOpPtT* over2e, |
112 double tStart, double tEnd, | 278 double tStart, double tEnd, |
113 SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEnd, | 279 const SkOpPtT* coinPtTStart, const SkOpPtT* coinPtTEn
d, |
114 SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd) const
; | 280 const SkOpPtT* oppPtTStart, const SkOpPtT* oppPtTEnd, |
| 281 const char* id, SkPathOpsDebug::GlitchLog*) const; |
| 282 #endif |
| 283 void fixUp(SkCoincidentSpans* coin, SkOpPtT* deleted, const SkOpPtT* kept); |
| 284 void markCollapsed(SkCoincidentSpans* head, SkOpPtT* test); |
115 bool overlap(const SkOpPtT* coinStart1, const SkOpPtT* coinEnd1, | 285 bool overlap(const SkOpPtT* coinStart1, const SkOpPtT* coinEnd1, |
116 const SkOpPtT* coinStart2, const SkOpPtT* coinEnd2, | 286 const SkOpPtT* coinStart2, const SkOpPtT* coinEnd2, |
117 double* overS, double* overE) const; | 287 double* overS, double* overE) const; |
118 | 288 bool release(SkCoincidentSpans* coin, SkCoincidentSpans* ); |
| 289 void restoreHead(); |
119 bool testForCoincidence(const SkCoincidentSpans* outer, const SkOpPtT* testS
, | 290 bool testForCoincidence(const SkCoincidentSpans* outer, const SkOpPtT* testS
, |
120 const SkOpPtT* testE) const; | 291 const SkOpPtT* testE) const; |
| 292 static void TRange(const SkOpPtT* overS, const SkOpPtT* overE, double tStart
, |
| 293 double tEnd, const SkOpPtT* coinPtTStart, const SkOpPtT*
coinPtTEnd, |
| 294 double* coinTs, double* coinTe); |
| 295 |
121 SkCoincidentSpans* fHead; | 296 SkCoincidentSpans* fHead; |
122 SkCoincidentSpans* fTop; | 297 SkCoincidentSpans* fTop; |
123 SkDEBUGCODE_(SkOpGlobalState* fDebugState); | 298 SkOpGlobalState* fGlobalState; |
| 299 bool fContinue; |
| 300 bool fSpanDeleted; |
| 301 bool fPtAllocated; |
| 302 bool fCoinExtended; |
| 303 bool fSpanMerged; |
124 }; | 304 }; |
125 | 305 |
126 #endif | 306 #endif |
OLD | NEW |