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 SkOpContour_DEFINED | 7 #ifndef SkOpContour_DEFINED |
8 #define SkOpContour_DEFINED | 8 #define SkOpContour_DEFINED |
9 | 9 |
10 #include "SkOpSegment.h" | 10 #include "SkOpSegment.h" |
11 #include "SkTArray.h" | 11 #include "SkTDArray.h" |
| 12 #include "SkTSort.h" |
12 | 13 |
13 #if defined(SK_DEBUG) || !FORCE_RELEASE | 14 class SkChunkAlloc; |
14 #include "SkThread.h" | |
15 #endif | |
16 | |
17 class SkIntersections; | |
18 class SkOpContour; | |
19 class SkPathWriter; | 15 class SkPathWriter; |
20 | 16 |
21 struct SkCoincidence { | |
22 SkOpContour* fOther; | |
23 int fSegments[2]; | |
24 double fTs[2][2]; | |
25 SkPoint fPts[2][2]; | |
26 int fNearly[2]; | |
27 }; | |
28 | |
29 class SkOpContour { | 17 class SkOpContour { |
30 public: | 18 public: |
31 SkOpContour() { | 19 SkOpContour() { |
32 reset(); | 20 reset(); |
33 #if defined(SK_DEBUG) || !FORCE_RELEASE | |
34 fID = sk_atomic_inc(&SkPathOpsDebug::gContourID); | |
35 #endif | |
36 } | 21 } |
37 | 22 |
38 bool operator<(const SkOpContour& rh) const { | 23 bool operator<(const SkOpContour& rh) const { |
39 return fBounds.fTop == rh.fBounds.fTop | 24 return fBounds.fTop == rh.fBounds.fTop |
40 ? fBounds.fLeft < rh.fBounds.fLeft | 25 ? fBounds.fLeft < rh.fBounds.fLeft |
41 : fBounds.fTop < rh.fBounds.fTop; | 26 : fBounds.fTop < rh.fBounds.fTop; |
42 } | 27 } |
43 | 28 |
44 bool addCoincident(int index, SkOpContour* other, int otherIndex, | 29 void addCubic(SkPoint pts[4], SkChunkAlloc* allocator) { |
45 const SkIntersections& ts, bool swap); | 30 appendSegment(allocator).addCubic(pts, this); |
46 void addCoincidentPoints(); | 31 } |
47 | 32 |
48 void addCross(const SkOpContour* crosser) { | 33 void addCurve(SkPath::Verb verb, const SkPoint pts[4], SkChunkAlloc* allocat
or); |
49 #ifdef DEBUG_CROSS | 34 |
50 for (int index = 0; index < fCrosses.count(); ++index) { | 35 void addLine(SkPoint pts[2], SkChunkAlloc* allocator) { |
51 SkASSERT(fCrosses[index] != crosser); | 36 appendSegment(allocator).addLine(pts, this); |
52 } | 37 } |
53 #endif | 38 |
54 fCrosses.push_back(crosser); | 39 void addQuad(SkPoint pts[3], SkChunkAlloc* allocator) { |
55 } | 40 appendSegment(allocator).addQuad(pts, this); |
56 | 41 } |
57 void addCubic(const SkPoint pts[4]) { | 42 |
58 fSegments.push_back().addCubic(pts, fOperand, fXor); | 43 void align() { |
59 fContainsCurves = fContainsCubics = true; | 44 SkASSERT(fCount > 0); |
60 } | 45 SkOpSegment* segment = &fHead; |
61 | 46 do { |
62 int addLine(const SkPoint pts[2]) { | 47 segment->align(); |
63 fSegments.push_back().addLine(pts, fOperand, fXor); | 48 } while ((segment = segment->next())); |
64 return fSegments.count(); | 49 } |
65 } | 50 |
66 | 51 SkOpSegment& appendSegment(SkChunkAlloc* allocator) { |
67 void addOtherT(int segIndex, int tIndex, double otherT, int otherIndex) { | 52 SkOpSegment* result = fCount++ |
68 fSegments[segIndex].addOtherT(tIndex, otherT, otherIndex); | 53 ? SkOpTAllocator<SkOpSegment>::Allocate(allocator) : &fHead; |
69 } | 54 result->setPrev(fTail); |
70 | 55 if (fTail) { |
71 bool addPartialCoincident(int index, SkOpContour* other, int otherIndex, | 56 fTail->setNext(result); |
72 const SkIntersections& ts, int ptIndex, bool swap); | 57 } |
73 | 58 fTail = result; |
74 int addQuad(const SkPoint pts[3]) { | 59 return *result; |
75 fSegments.push_back().addQuad(pts, fOperand, fXor); | 60 } |
76 fContainsCurves = true; | 61 |
77 return fSegments.count(); | 62 SkOpContour* appendContour(SkChunkAlloc* allocator) { |
78 } | 63 SkOpContour* contour = SkOpTAllocator<SkOpContour>::New(allocator); |
79 | 64 |
80 int addT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt
, double newT) { | 65 SkOpContour* prev = this; |
81 setContainsIntercepts(); | 66 SkOpContour* next; |
82 return fSegments[segIndex].addT(&other->fSegments[otherIndex], pt, newT)
; | 67 while ((next = prev->next())) { |
83 } | 68 prev = next; |
84 | 69 } |
85 int addSelfT(int segIndex, const SkPoint& pt, double newT) { | 70 prev->setNext(contour); |
86 setContainsIntercepts(); | 71 return contour; |
87 return fSegments[segIndex].addSelfT(pt, newT); | 72 } |
88 } | 73 |
89 | |
90 void align(const SkOpSegment::AlignedSpan& aligned, bool swap, SkCoincidence
* coincidence); | |
91 void alignCoincidence(const SkOpSegment::AlignedSpan& aligned, | |
92 SkTArray<SkCoincidence, true>* coincidences); | |
93 | |
94 void alignCoincidence(const SkOpSegment::AlignedSpan& aligned) { | |
95 alignCoincidence(aligned, &fCoincidences); | |
96 alignCoincidence(aligned, &fPartialCoincidences); | |
97 } | |
98 | |
99 void alignMultiples(SkTDArray<SkOpSegment::AlignedSpan>* aligned) { | |
100 int segmentCount = fSegments.count(); | |
101 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { | |
102 SkOpSegment& segment = fSegments[sIndex]; | |
103 if (segment.hasMultiples()) { | |
104 segment.alignMultiples(aligned); | |
105 } | |
106 } | |
107 } | |
108 | |
109 void alignTPt(int segmentIndex, const SkOpContour* other, int otherIndex, | |
110 bool swap, int tIndex, SkIntersections* ts, SkPoint* point) co
nst; | |
111 | |
112 const SkPathOpsBounds& bounds() const { | 74 const SkPathOpsBounds& bounds() const { |
113 return fBounds; | 75 return fBounds; |
114 } | 76 } |
115 | 77 |
116 bool calcAngles(); | 78 void calcAngles(SkChunkAlloc* allocator) { |
117 bool calcCoincidentWinding(); | 79 SkASSERT(fCount > 0); |
118 void calcPartialCoincidentWinding(); | 80 SkOpSegment* segment = &fHead; |
119 | 81 do { |
120 void checkDuplicates() { | 82 segment->calcAngles(allocator); |
121 int segmentCount = fSegments.count(); | 83 } while ((segment = segment->next())); |
122 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { | 84 } |
123 SkOpSegment& segment = fSegments[sIndex]; | 85 |
124 if (segment.count() > 2) { | 86 void complete() { |
125 segment.checkDuplicates(); | 87 setBounds(); |
| 88 } |
| 89 |
| 90 int count() const { |
| 91 return fCount; |
| 92 } |
| 93 |
| 94 int debugID() const { |
| 95 return PATH_OPS_DEBUG_RELEASE(fID, -1); |
| 96 } |
| 97 |
| 98 int debugIndent() const { |
| 99 return PATH_OPS_DEBUG_RELEASE(fIndent, 0); |
| 100 } |
| 101 |
| 102 #if DEBUG_ACTIVE_SPANS |
| 103 void debugShowActiveSpans() { |
| 104 SkOpSegment* segment = &fHead; |
| 105 do { |
| 106 segment->debugShowActiveSpans(); |
| 107 } while ((segment = segment->next())); |
| 108 } |
| 109 #endif |
| 110 |
| 111 const SkOpAngle* debugAngle(int id) const { |
| 112 return PATH_OPS_DEBUG_RELEASE(globalState()->debugAngle(id), NULL); |
| 113 } |
| 114 |
| 115 SkOpContour* debugContour(int id) { |
| 116 return PATH_OPS_DEBUG_RELEASE(globalState()->debugContour(id), NULL); |
| 117 } |
| 118 |
| 119 const SkOpPtT* debugPtT(int id) const { |
| 120 return PATH_OPS_DEBUG_RELEASE(globalState()->debugPtT(id), NULL); |
| 121 } |
| 122 |
| 123 const SkOpSegment* debugSegment(int id) const { |
| 124 return PATH_OPS_DEBUG_RELEASE(globalState()->debugSegment(id), NULL); |
| 125 } |
| 126 |
| 127 const SkOpSpanBase* debugSpan(int id) const { |
| 128 return PATH_OPS_DEBUG_RELEASE(globalState()->debugSpan(id), NULL); |
| 129 } |
| 130 |
| 131 SkOpGlobalState* globalState() const { |
| 132 return fState; |
| 133 } |
| 134 |
| 135 void debugValidate() const { |
| 136 #if DEBUG_VALIDATE |
| 137 const SkOpSegment* segment = &fHead; |
| 138 const SkOpSegment* prior = NULL; |
| 139 do { |
| 140 segment->debugValidate(); |
| 141 SkASSERT(segment->prev() == prior); |
| 142 prior = segment; |
| 143 } while ((segment = segment->next())); |
| 144 SkASSERT(prior == fTail); |
| 145 #endif |
| 146 } |
| 147 |
| 148 bool done() const { |
| 149 return fDone; |
| 150 } |
| 151 |
| 152 void dump(); |
| 153 void dumpAll(); |
| 154 void dumpAngles() const; |
| 155 void dumpPt(int ) const; |
| 156 void dumpPts() const; |
| 157 void dumpPtsX() const; |
| 158 void dumpSegment(int ) const; |
| 159 void dumpSegments(SkPathOp op) const; |
| 160 void dumpSpan(int ) const; |
| 161 void dumpSpans() const; |
| 162 |
| 163 const SkPoint& end() const { |
| 164 return fTail->pts()[SkPathOpsVerbToPoints(fTail->verb())]; |
| 165 } |
| 166 |
| 167 SkOpSegment* first() { |
| 168 SkASSERT(fCount > 0); |
| 169 return &fHead; |
| 170 } |
| 171 |
| 172 const SkOpSegment* first() const { |
| 173 SkASSERT(fCount > 0); |
| 174 return &fHead; |
| 175 } |
| 176 |
| 177 void indentDump() { |
| 178 PATH_OPS_DEBUG_CODE(fIndent += 2); |
| 179 } |
| 180 |
| 181 void init(SkOpGlobalState* globalState, bool operand, bool isXor) { |
| 182 fState = globalState; |
| 183 fOperand = operand; |
| 184 fXor = isXor; |
| 185 } |
| 186 |
| 187 bool isXor() const { |
| 188 return fXor; |
| 189 } |
| 190 |
| 191 void missingCoincidence(SkOpCoincidence* coincidences, SkChunkAlloc* allocat
or) { |
| 192 SkASSERT(fCount > 0); |
| 193 SkOpSegment* segment = &fHead; |
| 194 do { |
| 195 if (fState->angleCoincidence()) { |
| 196 segment->checkAngleCoin(coincidences, allocator); |
| 197 } else { |
| 198 segment->missingCoincidence(coincidences, allocator); |
126 } | 199 } |
127 } | 200 } while ((segment = segment->next())); |
128 } | 201 } |
129 | 202 |
130 bool checkEnds() { | 203 bool moveNearby() { |
131 if (!fContainsCurves) { | 204 SkASSERT(fCount > 0); |
132 return true; | 205 SkOpSegment* segment = &fHead; |
133 } | 206 do { |
134 int segmentCount = fSegments.count(); | 207 if (!segment->moveNearby()) { |
135 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { | |
136 SkOpSegment* segment = &fSegments[sIndex]; | |
137 if (segment->verb() == SkPath::kLine_Verb) { | |
138 continue; | |
139 } | |
140 if (segment->done()) { | |
141 continue; // likely coincident, nothing to do | |
142 } | |
143 if (!segment->checkEnds()) { | |
144 return false; | 208 return false; |
145 } | 209 } |
146 } | 210 } while ((segment = segment->next())); |
147 return true; | 211 return true; |
148 } | 212 } |
149 | 213 |
150 void checkMultiples() { | 214 SkOpContour* next() { |
151 int segmentCount = fSegments.count(); | 215 return fNext; |
152 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { | 216 } |
153 SkOpSegment& segment = fSegments[sIndex]; | 217 |
154 if (segment.count() > 2) { | 218 const SkOpContour* next() const { |
155 segment.checkMultiples(); | 219 return fNext; |
156 fMultiples |= segment.hasMultiples(); | 220 } |
157 } | 221 |
158 } | 222 SkOpSegment* nonVerticalSegment(SkOpSpanBase** start, SkOpSpanBase** end); |
159 } | |
160 | |
161 void checkSmall() { | |
162 int segmentCount = fSegments.count(); | |
163 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { | |
164 SkOpSegment& segment = fSegments[sIndex]; | |
165 // OPTIMIZATION : skip segments that are done? | |
166 if (segment.hasSmall()) { | |
167 segment.checkSmall(); | |
168 } | |
169 } | |
170 } | |
171 | |
172 // if same point has different T values, choose a common T | |
173 void checkTiny() { | |
174 int segmentCount = fSegments.count(); | |
175 if (segmentCount <= 2) { | |
176 return; | |
177 } | |
178 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { | |
179 SkOpSegment& segment = fSegments[sIndex]; | |
180 if (segment.hasTiny()) { | |
181 segment.checkTiny(); | |
182 } | |
183 } | |
184 } | |
185 | |
186 void complete() { | |
187 setBounds(); | |
188 fContainsIntercepts = false; | |
189 } | |
190 | |
191 bool containsCubics() const { | |
192 return fContainsCubics; | |
193 } | |
194 | |
195 bool crosses(const SkOpContour* crosser) const { | |
196 for (int index = 0; index < fCrosses.count(); ++index) { | |
197 if (fCrosses[index] == crosser) { | |
198 return true; | |
199 } | |
200 } | |
201 return false; | |
202 } | |
203 | |
204 bool done() const { | |
205 return fDone; | |
206 } | |
207 | |
208 const SkPoint& end() const { | |
209 const SkOpSegment& segment = fSegments.back(); | |
210 return segment.pts()[SkPathOpsVerbToPoints(segment.verb())]; | |
211 } | |
212 | |
213 void fixOtherTIndex() { | |
214 int segmentCount = fSegments.count(); | |
215 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { | |
216 fSegments[sIndex].fixOtherTIndex(); | |
217 } | |
218 } | |
219 | |
220 bool hasMultiples() const { | |
221 return fMultiples; | |
222 } | |
223 | |
224 void joinCoincidence() { | |
225 joinCoincidence(fCoincidences, false); | |
226 joinCoincidence(fPartialCoincidences, true); | |
227 } | |
228 | |
229 SkOpSegment* nonVerticalSegment(int* start, int* end); | |
230 | 223 |
231 bool operand() const { | 224 bool operand() const { |
232 return fOperand; | 225 return fOperand; |
233 } | 226 } |
234 | 227 |
| 228 bool oppXor() const { |
| 229 return fOppXor; |
| 230 } |
| 231 |
| 232 void outdentDump() { |
| 233 PATH_OPS_DEBUG_CODE(fIndent -= 2); |
| 234 } |
| 235 |
| 236 void remove(SkOpContour* contour) { |
| 237 if (contour == this) { |
| 238 SkASSERT(fCount == 0); |
| 239 return; |
| 240 } |
| 241 SkASSERT(contour->fNext == NULL); |
| 242 SkOpContour* prev = this; |
| 243 SkOpContour* next; |
| 244 while ((next = prev->next()) != contour) { |
| 245 SkASSERT(next); |
| 246 prev = next; |
| 247 } |
| 248 SkASSERT(prev); |
| 249 prev->setNext(NULL); |
| 250 } |
| 251 |
235 void reset() { | 252 void reset() { |
236 fSegments.reset(); | 253 fTail = NULL; |
237 fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax); | 254 fNext = NULL; |
238 fContainsCurves = fContainsCubics = fContainsIntercepts = fDone = fMulti
ples = false; | 255 fCount = 0; |
239 } | 256 fDone = false; |
240 | 257 SkDEBUGCODE(fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMin, SK_Sca
larMin)); |
241 void resolveNearCoincidence(); | 258 SkDEBUGCODE(fFirstSorted = -1); |
242 | 259 PATH_OPS_DEBUG_CODE(fIndent = 0); |
243 SkTArray<SkOpSegment>& segments() { | 260 } |
244 return fSegments; | 261 |
245 } | 262 void setBounds() { |
246 | 263 SkASSERT(fCount > 0); |
247 void setContainsIntercepts() { | 264 const SkOpSegment* segment = &fHead; |
248 fContainsIntercepts = true; | 265 fBounds = segment->bounds(); |
| 266 while ((segment = segment->next())) { |
| 267 fBounds.add(segment->bounds()); |
| 268 } |
| 269 } |
| 270 |
| 271 void setGlobalState(SkOpGlobalState* state) { |
| 272 fState = state; |
| 273 } |
| 274 |
| 275 void setNext(SkOpContour* contour) { |
| 276 SkASSERT(!fNext == !!contour); |
| 277 fNext = contour; |
249 } | 278 } |
250 | 279 |
251 void setOperand(bool isOp) { | 280 void setOperand(bool isOp) { |
252 fOperand = isOp; | 281 fOperand = isOp; |
253 } | 282 } |
254 | 283 |
255 void setOppXor(bool isOppXor) { | 284 void setOppXor(bool isOppXor) { |
256 fOppXor = isOppXor; | 285 fOppXor = isOppXor; |
257 int segmentCount = fSegments.count(); | |
258 for (int test = 0; test < segmentCount; ++test) { | |
259 fSegments[test].setOppXor(isOppXor); | |
260 } | |
261 } | 286 } |
262 | 287 |
263 void setXor(bool isXor) { | 288 void setXor(bool isXor) { |
264 fXor = isXor; | 289 fXor = isXor; |
265 } | 290 } |
266 | 291 |
267 void sortAngles(); | 292 SkPath::Verb simplifyCubic(SkPoint pts[4]); |
268 void sortSegments(); | 293 |
| 294 void sortAngles() { |
| 295 SkASSERT(fCount > 0); |
| 296 SkOpSegment* segment = &fHead; |
| 297 do { |
| 298 segment->sortAngles(); |
| 299 } while ((segment = segment->next())); |
| 300 } |
| 301 |
| 302 void sortSegments() { |
| 303 SkOpSegment* segment = &fHead; |
| 304 do { |
| 305 *fSortedSegments.append() = segment; |
| 306 } while ((segment = segment->next())); |
| 307 SkTQSort<SkOpSegment>(fSortedSegments.begin(), fSortedSegments.end() - 1
); |
| 308 fFirstSorted = 0; |
| 309 } |
269 | 310 |
270 const SkPoint& start() const { | 311 const SkPoint& start() const { |
271 return fSegments.front().pts()[0]; | 312 return fHead.pts()[0]; |
| 313 } |
| 314 |
| 315 void toPartialBackward(SkPathWriter* path) const { |
| 316 const SkOpSegment* segment = fTail; |
| 317 do { |
| 318 segment->addCurveTo(segment->tail(), segment->head(), path, true); |
| 319 } while ((segment = segment->prev())); |
| 320 } |
| 321 |
| 322 void toPartialForward(SkPathWriter* path) const { |
| 323 const SkOpSegment* segment = &fHead; |
| 324 do { |
| 325 segment->addCurveTo(segment->head(), segment->tail(), path, true); |
| 326 } while ((segment = segment->next())); |
272 } | 327 } |
273 | 328 |
274 void toPath(SkPathWriter* path) const; | 329 void toPath(SkPathWriter* path) const; |
275 | |
276 void toPartialBackward(SkPathWriter* path) const { | |
277 int segmentCount = fSegments.count(); | |
278 for (int test = segmentCount - 1; test >= 0; --test) { | |
279 fSegments[test].addCurveTo(1, 0, path, true); | |
280 } | |
281 } | |
282 | |
283 void toPartialForward(SkPathWriter* path) const { | |
284 int segmentCount = fSegments.count(); | |
285 for (int test = 0; test < segmentCount; ++test) { | |
286 fSegments[test].addCurveTo(0, 1, path, true); | |
287 } | |
288 } | |
289 | |
290 void topSortableSegment(const SkPoint& topLeft, SkPoint* bestXY, SkOpSegment
** topStart); | 330 void topSortableSegment(const SkPoint& topLeft, SkPoint* bestXY, SkOpSegment
** topStart); |
291 SkOpSegment* undoneSegment(int* start, int* end); | 331 SkOpSegment* undoneSegment(SkOpSpanBase** startPtr, SkOpSpanBase** endPtr); |
292 | |
293 int updateSegment(int index, const SkPoint* pts) { | |
294 SkOpSegment& segment = fSegments[index]; | |
295 segment.updatePts(pts); | |
296 return SkPathOpsVerbToPoints(segment.verb()) + 1; | |
297 } | |
298 | |
299 #if DEBUG_TEST | |
300 SkTArray<SkOpSegment>& debugSegments() { | |
301 return fSegments; | |
302 } | |
303 #endif | |
304 | |
305 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY | |
306 void debugShowActiveSpans() { | |
307 for (int index = 0; index < fSegments.count(); ++index) { | |
308 fSegments[index].debugShowActiveSpans(); | |
309 } | |
310 } | |
311 #endif | |
312 | |
313 #if DEBUG_SHOW_WINDING | |
314 int debugShowWindingValues(int totalSegments, int ofInterest); | |
315 static void debugShowWindingValues(const SkTArray<SkOpContour*, true>& conto
urList); | |
316 #endif | |
317 | |
318 // available to test routines only | |
319 void dump() const; | |
320 void dumpAngles() const; | |
321 void dumpCoincidence(const SkCoincidence& ) const; | |
322 void dumpCoincidences() const; | |
323 void dumpPt(int ) const; | |
324 void dumpPts() const; | |
325 void dumpSpan(int ) const; | |
326 void dumpSpans() const; | |
327 | 332 |
328 private: | 333 private: |
329 void alignPt(int index, SkPoint* point, int zeroPt) const; | 334 SkOpGlobalState* fState; |
330 int alignT(bool swap, int tIndex, SkIntersections* ts) const; | 335 SkOpSegment fHead; |
331 bool calcCommonCoincidentWinding(const SkCoincidence& ); | 336 SkOpSegment* fTail; |
332 void checkCoincidentPair(const SkCoincidence& oneCoin, int oneIdx, | 337 SkOpContour* fNext; |
333 const SkCoincidence& twoCoin, int twoIdx, bool part
ial); | 338 SkTDArray<SkOpSegment*> fSortedSegments; // set by find top segment |
334 void joinCoincidence(const SkTArray<SkCoincidence, true>& , bool partial); | 339 SkPathOpsBounds fBounds; |
335 void setBounds(); | 340 int fCount; |
336 | |
337 SkTArray<SkOpSegment> fSegments; | |
338 SkTArray<SkOpSegment*, true> fSortedSegments; | |
339 int fFirstSorted; | 341 int fFirstSorted; |
340 SkTArray<SkCoincidence, true> fCoincidences; | 342 bool fDone; // set by find top segment |
341 SkTArray<SkCoincidence, true> fPartialCoincidences; | |
342 SkTArray<const SkOpContour*, true> fCrosses; | |
343 SkPathOpsBounds fBounds; | |
344 bool fContainsIntercepts; // FIXME: is this used by anybody? | |
345 bool fContainsCubics; | |
346 bool fContainsCurves; | |
347 bool fDone; | |
348 bool fMultiples; // set if some segment has multiple identical intersection
s with other curves | |
349 bool fOperand; // true for the second argument to a binary operator | 343 bool fOperand; // true for the second argument to a binary operator |
350 bool fXor; | 344 bool fXor; // set if original path had even-odd fill |
351 bool fOppXor; | 345 bool fOppXor; // set if opposite path had even-odd fill |
352 #if defined(SK_DEBUG) || !FORCE_RELEASE | 346 PATH_OPS_DEBUG_CODE(int fID); |
353 int debugID() const { return fID; } | 347 PATH_OPS_DEBUG_CODE(int fIndent); |
354 int fID; | |
355 #else | |
356 int debugID() const { return -1; } | |
357 #endif | |
358 }; | 348 }; |
359 | 349 |
360 #endif | 350 #endif |
OLD | NEW |