| 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 "SkTDArray.h" | 11 #include "SkTDArray.h" |
| 12 #include "SkTSort.h" | 12 #include "SkTSort.h" |
| 13 | 13 |
| 14 class SkChunkAlloc; | |
| 15 enum class SkOpRayDir; | 14 enum class SkOpRayDir; |
| 16 struct SkOpRayHit; | 15 struct SkOpRayHit; |
| 17 class SkPathWriter; | 16 class SkPathWriter; |
| 18 | 17 |
| 19 class SkOpContour { | 18 class SkOpContour { |
| 20 public: | 19 public: |
| 21 SkOpContour() { | 20 SkOpContour() { |
| 22 reset(); | 21 reset(); |
| 23 } | 22 } |
| 24 | 23 |
| 25 ~SkOpContour() { | 24 ~SkOpContour() { |
| 26 if (fNext) { | 25 if (fNext) { |
| 27 fNext->~SkOpContour(); | 26 fNext->~SkOpContour(); |
| 28 } | 27 } |
| 29 } | 28 } |
| 30 | 29 |
| 31 bool operator<(const SkOpContour& rh) const { | 30 bool operator<(const SkOpContour& rh) const { |
| 32 return fBounds.fTop == rh.fBounds.fTop | 31 return fBounds.fTop == rh.fBounds.fTop |
| 33 ? fBounds.fLeft < rh.fBounds.fLeft | 32 ? fBounds.fLeft < rh.fBounds.fLeft |
| 34 : fBounds.fTop < rh.fBounds.fTop; | 33 : fBounds.fTop < rh.fBounds.fTop; |
| 35 } | 34 } |
| 36 | 35 |
| 37 void addAlignIntersections(SkOpContourHead* contourList, SkChunkAlloc* alloc
ator) { | 36 void addConic(SkPoint pts[3], SkScalar weight) { |
| 38 SkASSERT(fCount > 0); | 37 appendSegment().addConic(pts, weight, this); |
| 39 SkOpSegment* segment = &fHead; | |
| 40 do { | |
| 41 segment->addAlignIntersections(contourList, allocator); | |
| 42 } while ((segment = segment->next())); | |
| 43 } | 38 } |
| 44 | 39 |
| 45 void addConic(SkPoint pts[3], SkScalar weight, SkChunkAlloc* allocator) { | 40 void addCubic(SkPoint pts[4]) { |
| 46 appendSegment(allocator).addConic(pts, weight, this); | 41 appendSegment().addCubic(pts, this); |
| 47 } | 42 } |
| 48 | 43 |
| 49 void addCubic(SkPoint pts[4], SkChunkAlloc* allocator) { | 44 SkOpSegment* addCurve(SkPath::Verb verb, const SkPoint pts[4]); |
| 50 appendSegment(allocator).addCubic(pts, this); | 45 |
| 46 SkOpSegment* addLine(SkPoint pts[2]) { |
| 47 return appendSegment().addLine(pts, this); |
| 51 } | 48 } |
| 52 | 49 |
| 53 SkOpSegment* addCurve(SkPath::Verb verb, const SkPoint pts[4], SkChunkAlloc*
allocator); | 50 void addQuad(SkPoint pts[3]) { |
| 54 | 51 appendSegment().addQuad(pts, this); |
| 55 void addLine(SkPoint pts[2], SkChunkAlloc* allocator) { | |
| 56 appendSegment(allocator).addLine(pts, this); | |
| 57 } | 52 } |
| 58 | 53 |
| 59 void addQuad(SkPoint pts[3], SkChunkAlloc* allocator) { | 54 SkOpSegment& appendSegment() { |
| 60 appendSegment(allocator).addQuad(pts, this); | |
| 61 } | |
| 62 | |
| 63 void align() { | |
| 64 SkASSERT(fCount > 0); | |
| 65 SkOpSegment* segment = &fHead; | |
| 66 do { | |
| 67 segment->align(); | |
| 68 } while ((segment = segment->next())); | |
| 69 } | |
| 70 | |
| 71 SkOpSegment& appendSegment(SkChunkAlloc* allocator) { | |
| 72 SkOpSegment* result = fCount++ | 55 SkOpSegment* result = fCount++ |
| 73 ? SkOpTAllocator<SkOpSegment>::Allocate(allocator) : &fHead; | 56 ? SkOpTAllocator<SkOpSegment>::Allocate(this->globalState()->allocat
or()) : &fHead; |
| 74 result->setPrev(fTail); | 57 result->setPrev(fTail); |
| 75 if (fTail) { | 58 if (fTail) { |
| 76 fTail->setNext(result); | 59 fTail->setNext(result); |
| 77 } | 60 } |
| 78 fTail = result; | 61 fTail = result; |
| 79 return *result; | 62 return *result; |
| 80 } | 63 } |
| 81 | 64 |
| 82 SkOpContour* appendContour(SkChunkAlloc* allocator) { | 65 SkOpContour* appendContour() { |
| 83 SkOpContour* contour = SkOpTAllocator<SkOpContour>::New(allocator); | 66 SkOpContour* contour = SkOpTAllocator<SkOpContour>::New(this->globalStat
e()->allocator()); |
| 84 contour->setNext(nullptr); | 67 contour->setNext(nullptr); |
| 85 SkOpContour* prev = this; | 68 SkOpContour* prev = this; |
| 86 SkOpContour* next; | 69 SkOpContour* next; |
| 87 while ((next = prev->next())) { | 70 while ((next = prev->next())) { |
| 88 prev = next; | 71 prev = next; |
| 89 } | 72 } |
| 90 prev->setNext(contour); | 73 prev->setNext(contour); |
| 91 return contour; | 74 return contour; |
| 92 } | 75 } |
| 93 | 76 |
| 94 const SkPathOpsBounds& bounds() const { | 77 const SkPathOpsBounds& bounds() const { |
| 95 return fBounds; | 78 return fBounds; |
| 96 } | 79 } |
| 97 | 80 |
| 98 void calcAngles(SkChunkAlloc* allocator) { | 81 void calcAngles() { |
| 99 SkASSERT(fCount > 0); | 82 SkASSERT(fCount > 0); |
| 100 SkOpSegment* segment = &fHead; | 83 SkOpSegment* segment = &fHead; |
| 101 do { | 84 do { |
| 102 segment->calcAngles(allocator); | 85 segment->calcAngles(); |
| 103 } while ((segment = segment->next())); | 86 } while ((segment = segment->next())); |
| 104 } | 87 } |
| 105 | 88 |
| 106 void complete() { | 89 void complete() { |
| 107 setBounds(); | 90 setBounds(); |
| 108 } | 91 } |
| 109 | 92 |
| 110 int count() const { | 93 int count() const { |
| 111 return fCount; | 94 return fCount; |
| 112 } | 95 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 125 do { | 108 do { |
| 126 segment->debugShowActiveSpans(); | 109 segment->debugShowActiveSpans(); |
| 127 } while ((segment = segment->next())); | 110 } while ((segment = segment->next())); |
| 128 } | 111 } |
| 129 #endif | 112 #endif |
| 130 | 113 |
| 131 const SkOpAngle* debugAngle(int id) const { | 114 const SkOpAngle* debugAngle(int id) const { |
| 132 return SkDEBUGRELEASE(this->globalState()->debugAngle(id), nullptr); | 115 return SkDEBUGRELEASE(this->globalState()->debugAngle(id), nullptr); |
| 133 } | 116 } |
| 134 | 117 |
| 118 const SkOpCoincidence* debugCoincidence() const { |
| 119 return this->globalState()->coincidence(); |
| 120 } |
| 121 |
| 122 #if DEBUG_COINCIDENCE_VERBOSE |
| 135 void debugCheckHealth(const char* id, SkPathOpsDebug::GlitchLog* ) const; | 123 void debugCheckHealth(const char* id, SkPathOpsDebug::GlitchLog* ) const; |
| 124 #endif |
| 136 | 125 |
| 137 SkOpContour* debugContour(int id) { | 126 SkOpContour* debugContour(int id) { |
| 138 return SkDEBUGRELEASE(this->globalState()->debugContour(id), nullptr); | 127 return SkDEBUGRELEASE(this->globalState()->debugContour(id), nullptr); |
| 139 } | 128 } |
| 140 | 129 |
| 141 void debugMissingCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log, | 130 #if DEBUG_COINCIDENCE_VERBOSE |
| 142 const SkOpCoincidence* coincidence) const; | 131 void debugMissingCoincidence(const char* id, SkPathOpsDebug::GlitchLog* log)
const; |
| 132 #endif |
| 143 | 133 |
| 144 const SkOpPtT* debugPtT(int id) const { | 134 const SkOpPtT* debugPtT(int id) const { |
| 145 return SkDEBUGRELEASE(this->globalState()->debugPtT(id), nullptr); | 135 return SkDEBUGRELEASE(this->globalState()->debugPtT(id), nullptr); |
| 146 } | 136 } |
| 147 | 137 |
| 148 const SkOpSegment* debugSegment(int id) const { | 138 const SkOpSegment* debugSegment(int id) const { |
| 149 return SkDEBUGRELEASE(this->globalState()->debugSegment(id), nullptr); | 139 return SkDEBUGRELEASE(this->globalState()->debugSegment(id), nullptr); |
| 150 } | 140 } |
| 151 | 141 |
| 152 const SkOpSpanBase* debugSpan(int id) const { | 142 const SkOpSpanBase* debugSpan(int id) const { |
| 153 return SkDEBUGRELEASE(this->globalState()->debugSpan(id), nullptr); | 143 return SkDEBUGRELEASE(this->globalState()->debugSpan(id), nullptr); |
| 154 } | 144 } |
| 155 | 145 |
| 156 SkOpGlobalState* globalState() const { | 146 SkOpGlobalState* globalState() const { |
| 157 return fState; | 147 return fState; |
| 158 } | 148 } |
| 159 | 149 |
| 160 void debugValidate() const { | 150 void debugValidate() const { |
| 161 #if DEBUG_VALIDATE | 151 #if DEBUG_VALIDATE |
| 162 const SkOpSegment* segment = &fHead; | 152 const SkOpSegment* segment = &fHead; |
| 163 const SkOpSegment* prior = nullptr; | 153 const SkOpSegment* prior = nullptr; |
| 164 do { | 154 do { |
| 165 segment->debugValidate(); | 155 segment->debugValidate(); |
| 166 SkASSERT(segment->prev() == prior); | 156 SkASSERT(segment->prev() == prior); |
| 167 prior = segment; | 157 prior = segment; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 190 void dumpPtsX(const char* prefix) const; | 180 void dumpPtsX(const char* prefix) const; |
| 191 void dumpSegment(int ) const; | 181 void dumpSegment(int ) const; |
| 192 void dumpSegments(const char* prefix = "seg", SkPathOp op = (SkPathOp) -1) c
onst; | 182 void dumpSegments(const char* prefix = "seg", SkPathOp op = (SkPathOp) -1) c
onst; |
| 193 void dumpSpan(int ) const; | 183 void dumpSpan(int ) const; |
| 194 void dumpSpans() const; | 184 void dumpSpans() const; |
| 195 | 185 |
| 196 const SkPoint& end() const { | 186 const SkPoint& end() const { |
| 197 return fTail->pts()[SkPathOpsVerbToPoints(fTail->verb())]; | 187 return fTail->pts()[SkPathOpsVerbToPoints(fTail->verb())]; |
| 198 } | 188 } |
| 199 | 189 |
| 200 bool findCollapsed() { | |
| 201 SkASSERT(fCount > 0); | |
| 202 SkOpSegment* segment = &fHead; | |
| 203 do { | |
| 204 segment->findCollapsed(); | |
| 205 } while ((segment = segment->next())); | |
| 206 return true; | |
| 207 } | |
| 208 | |
| 209 SkOpSpan* findSortableTop(SkOpContour* ); | 190 SkOpSpan* findSortableTop(SkOpContour* ); |
| 210 | 191 |
| 211 SkOpSegment* first() { | 192 SkOpSegment* first() { |
| 212 SkASSERT(fCount > 0); | 193 SkASSERT(fCount > 0); |
| 213 return &fHead; | 194 return &fHead; |
| 214 } | 195 } |
| 215 | 196 |
| 216 const SkOpSegment* first() const { | 197 const SkOpSegment* first() const { |
| 217 SkASSERT(fCount > 0); | 198 SkASSERT(fCount > 0); |
| 218 return &fHead; | 199 return &fHead; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 230 } | 211 } |
| 231 | 212 |
| 232 int isCcw() const { | 213 int isCcw() const { |
| 233 return fCcw; | 214 return fCcw; |
| 234 } | 215 } |
| 235 | 216 |
| 236 bool isXor() const { | 217 bool isXor() const { |
| 237 return fXor; | 218 return fXor; |
| 238 } | 219 } |
| 239 | 220 |
| 240 void markDone() { | 221 void markAllDone() { |
| 241 SkOpSegment* segment = &fHead; | 222 SkOpSegment* segment = &fHead; |
| 242 do { | 223 do { |
| 243 segment->markAllDone(); | 224 segment->markAllDone(); |
| 244 } while ((segment = segment->next())); | 225 } while ((segment = segment->next())); |
| 245 } | 226 } |
| 246 | 227 |
| 247 bool missingCoincidence(SkOpCoincidence* coincidences, SkChunkAlloc* allocat
or) { | 228 // Please keep this aligned with debugMissingCoincidence() |
| 229 bool missingCoincidence() { |
| 248 SkASSERT(fCount > 0); | 230 SkASSERT(fCount > 0); |
| 249 SkOpSegment* segment = &fHead; | 231 SkOpSegment* segment = &fHead; |
| 250 bool result = false; | 232 bool result = false; |
| 251 do { | 233 do { |
| 252 if (fState->angleCoincidence()) { | 234 if (fState->angleCoincidence()) { |
| 253 #if DEBUG_ANGLE | 235 #if DEBUG_ANGLE |
| 254 segment->debugCheckAngleCoin(); | 236 segment->debugCheckAngleCoin(); |
| 255 #endif | 237 #endif |
| 256 } else if (segment->missingCoincidence(coincidences, allocator)) { | 238 } else if (segment->missingCoincidence()) { |
| 257 result = true; | 239 result = true; |
| 258 // FIXME: trying again loops forever in issue3651_6 | 240 // FIXME: trying again loops forever in issue3651_6 |
| 259 // The continue below is speculative -- once there's an actual case that req
uires it, | 241 // The continue below is speculative -- once there's an actual case that req
uires it, |
| 260 // add the plumbing necessary to look for another missing coincidence in the
same segment | 242 // add the plumbing necessary to look for another missing coincidence in the
same segment |
| 261 // continue; // try again in case another missing coincidence is
further along | 243 // continue; // try again in case another missing coincidence is
further along |
| 262 } | 244 } |
| 263 segment = segment->next(); | 245 segment = segment->next(); |
| 264 } while (segment); | 246 } while (segment); |
| 265 return result; | 247 return result; |
| 266 } | 248 } |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 bool fXor; // set if original path had even-odd fill | 411 bool fXor; // set if original path had even-odd fill |
| 430 bool fOppXor; // set if opposite path had even-odd fill | 412 bool fOppXor; // set if opposite path had even-odd fill |
| 431 SkDEBUGCODE(int fID); | 413 SkDEBUGCODE(int fID); |
| 432 SkDEBUGCODE(mutable int fDebugIndent); | 414 SkDEBUGCODE(mutable int fDebugIndent); |
| 433 }; | 415 }; |
| 434 | 416 |
| 435 class SkOpContourHead : public SkOpContour { | 417 class SkOpContourHead : public SkOpContour { |
| 436 }; | 418 }; |
| 437 | 419 |
| 438 #endif | 420 #endif |
| OLD | NEW |