| 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 |