| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 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 SkOpSegment_DEFINE | 7 #ifndef SkOpSegment_DEFINE |
| 8 #define SkOpSegment_DEFINE | 8 #define SkOpSegment_DEFINE |
| 9 | 9 |
| 10 #include "SkOpAngle.h" | 10 #include "SkOpAngle.h" |
| 11 #include "SkOpSpan.h" | 11 #include "SkOpSpan.h" |
| 12 #include "SkPathOpsBounds.h" | 12 #include "SkPathOpsBounds.h" |
| 13 #include "SkPathOpsCurve.h" | 13 #include "SkPathOpsCurve.h" |
| 14 #include "SkTArray.h" | 14 #include "SkTArray.h" |
| 15 #include "SkTDArray.h" | 15 #include "SkTDArray.h" |
| 16 | 16 |
| 17 class SkPathWriter; | 17 class SkPathWriter; |
| 18 | 18 |
| 19 class SkOpSegment { | 19 class SkOpSegment { |
| 20 public: | 20 public: |
| 21 SkOpSegment() { | 21 SkOpSegment() { |
| 22 #ifdef SK_DEBUG | 22 #if defined(SK_DEBUG) || !FORCE_RELEASE |
| 23 fID = ++SkPathOpsDebug::gSegmentID; | 23 fID = ++SkPathOpsDebug::gSegmentID; |
| 24 #endif | 24 #endif |
| 25 } | 25 } |
| 26 | 26 |
| 27 bool operator<(const SkOpSegment& rh) const { | 27 bool operator<(const SkOpSegment& rh) const { |
| 28 return fBounds.fTop < rh.fBounds.fTop; | 28 return fBounds.fTop < rh.fBounds.fTop; |
| 29 } | 29 } |
| 30 | 30 |
| 31 // FIXME: add some template or macro to avoid casting |
| 32 SkOpAngle& angle(int index) { |
| 33 const SkOpAngle& cAngle = (const_cast<const SkOpSegment*>(this))->angle(
index); |
| 34 return const_cast<SkOpAngle&>(cAngle); |
| 35 } |
| 36 |
| 31 const SkPathOpsBounds& bounds() const { | 37 const SkPathOpsBounds& bounds() const { |
| 32 return fBounds; | 38 return fBounds; |
| 33 } | 39 } |
| 34 | 40 |
| 35 // OPTIMIZE | 41 // OPTIMIZE |
| 36 // when the edges are initially walked, they don't automatically get the pri
or and next | 42 // when the edges are initially walked, they don't automatically get the pri
or and next |
| 37 // edges assigned to positions t=0 and t=1. Doing that would remove the need
for this check, | 43 // edges assigned to positions t=0 and t=1. Doing that would remove the need
for this check, |
| 38 // and would additionally remove the need for similar checks in condition ed
ges. It would | 44 // and would additionally remove the need for similar checks in condition ed
ges. It would |
| 39 // also allow intersection code to assume end of segment intersections (mayb
e?) | 45 // also allow intersection code to assume end of segment intersections (mayb
e?) |
| 40 bool complete() const { | 46 bool complete() const { |
| 41 int count = fTs.count(); | 47 int count = fTs.count(); |
| 42 return count > 1 && fTs[0].fT == 0 && fTs[--count].fT == 1; | 48 return count > 1 && fTs[0].fT == 0 && fTs[--count].fT == 1; |
| 43 } | 49 } |
| 44 | 50 |
| 51 void constructLine(SkPoint shortLine[2]); |
| 52 |
| 45 int count() const { | 53 int count() const { |
| 46 return fTs.count(); | 54 return fTs.count(); |
| 47 } | 55 } |
| 48 | 56 |
| 49 bool done() const { | 57 bool done() const { |
| 50 SkASSERT(fDoneSpans <= fTs.count()); | 58 SkASSERT(fDoneSpans <= fTs.count()); |
| 51 return fDoneSpans == fTs.count(); | 59 return fDoneSpans == fTs.count(); |
| 52 } | 60 } |
| 53 | 61 |
| 54 bool done(int min) const { | 62 bool done(int min) const { |
| 55 return fTs[min].fDone; | 63 return fTs[min].fDone; |
| 56 } | 64 } |
| 57 | 65 |
| 58 bool done(const SkOpAngle* angle) const { | 66 bool done(const SkOpAngle* angle) const { |
| 59 return done(SkMin32(angle->start(), angle->end())); | 67 return done(SkMin32(angle->start(), angle->end())); |
| 60 } | 68 } |
| 61 | 69 |
| 62 // used only by partial coincidence detection | |
| 63 SkDPoint dPtAtT(double mid) const { | 70 SkDPoint dPtAtT(double mid) const { |
| 64 return (*CurveDPointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid); | 71 return (*CurveDPointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid); |
| 65 } | 72 } |
| 66 | 73 |
| 67 SkVector dxdy(int index) const { | 74 SkVector dxdy(int index) const { |
| 68 return (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, fTs[index].f
T); | 75 return (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, fTs[index].f
T); |
| 69 } | 76 } |
| 70 | 77 |
| 71 SkScalar dy(int index) const { | 78 SkScalar dy(int index) const { |
| 72 return dxdy(index).fY; | 79 return dxdy(index).fY; |
| 73 } | 80 } |
| 74 | 81 |
| 82 bool hasSmall() const { |
| 83 return fSmall; |
| 84 } |
| 85 |
| 86 bool hasTiny() const { |
| 87 return fTiny; |
| 88 } |
| 89 |
| 75 bool intersected() const { | 90 bool intersected() const { |
| 76 return fTs.count() > 0; | 91 return fTs.count() > 0; |
| 77 } | 92 } |
| 78 | 93 |
| 79 bool isCanceled(int tIndex) const { | 94 bool isCanceled(int tIndex) const { |
| 80 return fTs[tIndex].fWindValue == 0 && fTs[tIndex].fOppValue == 0; | 95 return fTs[tIndex].fWindValue == 0 && fTs[tIndex].fOppValue == 0; |
| 81 } | 96 } |
| 82 | 97 |
| 83 bool isConnected(int startIndex, int endIndex) const { | 98 bool isConnected(int startIndex, int endIndex) const { |
| 84 return fTs[startIndex].fWindSum != SK_MinS32 || fTs[endIndex].fWindSum !
= SK_MinS32; | 99 return fTs[startIndex].fWindSum != SK_MinS32 || fTs[endIndex].fWindSum !
= SK_MinS32; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 124 | 139 |
| 125 int oppValue(int tIndex) const { | 140 int oppValue(int tIndex) const { |
| 126 return fTs[tIndex].fOppValue; | 141 return fTs[tIndex].fOppValue; |
| 127 } | 142 } |
| 128 | 143 |
| 129 int oppValue(const SkOpAngle* angle) const { | 144 int oppValue(const SkOpAngle* angle) const { |
| 130 int lesser = SkMin32(angle->start(), angle->end()); | 145 int lesser = SkMin32(angle->start(), angle->end()); |
| 131 return fTs[lesser].fOppValue; | 146 return fTs[lesser].fOppValue; |
| 132 } | 147 } |
| 133 | 148 |
| 134 const SkOpSegment* other(int index) const { | 149 #if DEBUG_VALIDATE |
| 135 return fTs[index].fOther; | 150 bool oppXor() const { |
| 151 return fOppXor; |
| 136 } | 152 } |
| 153 #endif |
| 137 | 154 |
| 138 // was used only by right angle winding finding | |
| 139 SkPoint ptAtT(double mid) const { | 155 SkPoint ptAtT(double mid) const { |
| 140 return (*CurvePointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid); | 156 return (*CurvePointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid); |
| 141 } | 157 } |
| 142 | 158 |
| 143 const SkPoint* pts() const { | 159 const SkPoint* pts() const { |
| 144 return fPts; | 160 return fPts; |
| 145 } | 161 } |
| 146 | 162 |
| 147 void reset() { | 163 void reset() { |
| 148 init(NULL, (SkPath::Verb) -1, false, false); | 164 init(NULL, (SkPath::Verb) -1, false, false); |
| 149 fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax); | 165 fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax); |
| 150 fTs.reset(); | 166 fTs.reset(); |
| 151 } | 167 } |
| 152 | 168 |
| 153 void setOppXor(bool isOppXor) { | 169 void setOppXor(bool isOppXor) { |
| 154 fOppXor = isOppXor; | 170 fOppXor = isOppXor; |
| 155 } | 171 } |
| 156 | 172 |
| 157 void setUpWinding(int index, int endIndex, int* maxWinding, int* sumWinding)
{ | 173 void setUpWinding(int index, int endIndex, int* maxWinding, int* sumWinding)
{ |
| 158 int deltaSum = spanSign(index, endIndex); | 174 int deltaSum = spanSign(index, endIndex); |
| 159 *maxWinding = *sumWinding; | 175 *maxWinding = *sumWinding; |
| 160 *sumWinding -= deltaSum; | 176 *sumWinding -= deltaSum; |
| 161 } | 177 } |
| 162 | 178 |
| 163 // OPTIMIZATION: mark as debugging only if used solely by tests | |
| 164 const SkOpSpan& span(int tIndex) const { | 179 const SkOpSpan& span(int tIndex) const { |
| 165 return fTs[tIndex]; | 180 return fTs[tIndex]; |
| 166 } | 181 } |
| 167 | 182 |
| 183 const SkOpAngle* spanToAngle(int tStart, int tEnd) const { |
| 184 SkASSERT(tStart != tEnd); |
| 185 const SkOpSpan& span = fTs[tStart]; |
| 186 int index = tStart < tEnd ? span.fToAngleIndex : span.fFromAngleIndex; |
| 187 return index >= 0 ? &angle(index) : NULL; |
| 188 } |
| 189 |
| 190 // FIXME: create some sort of macro or template that avoids casting |
| 191 SkOpAngle* spanToAngle(int tStart, int tEnd) { |
| 192 const SkOpAngle* cAngle = (const_cast<const SkOpSegment*>(this))->spanTo
Angle(tStart, tEnd); |
| 193 return const_cast<SkOpAngle*>(cAngle); |
| 194 } |
| 195 |
| 168 // OPTIMIZATION: mark as debugging only if used solely by tests | 196 // OPTIMIZATION: mark as debugging only if used solely by tests |
| 169 const SkTDArray<SkOpSpan>& spans() const { | 197 const SkTDArray<SkOpSpan>& spans() const { |
| 170 return fTs; | 198 return fTs; |
| 171 } | 199 } |
| 172 | 200 |
| 173 int spanSign(const SkOpAngle* angle) const { | 201 int spanSign(const SkOpAngle* angle) const { |
| 174 SkASSERT(angle->segment() == this); | 202 SkASSERT(angle->segment() == this); |
| 175 return spanSign(angle->start(), angle->end()); | 203 return spanSign(angle->start(), angle->end()); |
| 176 } | 204 } |
| 177 | 205 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 int windValue(int tIndex) const { | 238 int windValue(int tIndex) const { |
| 211 return fTs[tIndex].fWindValue; | 239 return fTs[tIndex].fWindValue; |
| 212 } | 240 } |
| 213 | 241 |
| 214 #if defined(SK_DEBUG) || DEBUG_WINDING | 242 #if defined(SK_DEBUG) || DEBUG_WINDING |
| 215 SkScalar xAtT(int index) const { | 243 SkScalar xAtT(int index) const { |
| 216 return xAtT(&fTs[index]); | 244 return xAtT(&fTs[index]); |
| 217 } | 245 } |
| 218 #endif | 246 #endif |
| 219 | 247 |
| 248 #if DEBUG_VALIDATE |
| 249 bool _xor() const { // FIXME: used only by SkOpAngle::debugValidateLoop() |
| 250 return fXor; |
| 251 } |
| 252 #endif |
| 253 |
| 220 const SkPoint& xyAtT(const SkOpSpan* span) const { | 254 const SkPoint& xyAtT(const SkOpSpan* span) const { |
| 221 return span->fPt; | 255 return span->fPt; |
| 222 } | 256 } |
| 223 | 257 |
| 224 const SkPoint& xyAtT(int index) const { | 258 const SkPoint& xyAtT(int index) const { |
| 225 return xyAtT(&fTs[index]); | 259 return xyAtT(&fTs[index]); |
| 226 } | 260 } |
| 227 | 261 |
| 228 #if defined(SK_DEBUG) || DEBUG_WINDING | 262 #if defined(SK_DEBUG) || DEBUG_WINDING |
| 229 SkScalar yAtT(int index) const { | 263 SkScalar yAtT(int index) const { |
| 230 return yAtT(&fTs[index]); | 264 return yAtT(&fTs[index]); |
| 231 } | 265 } |
| 232 #endif | 266 #endif |
| 233 | 267 |
| 234 bool activeAngle(int index, int* done, SkTArray<SkOpAngle, true>* angles); | 268 const SkOpAngle* activeAngle(int index, int* start, int* end, bool* done, |
| 269 bool* sortable) const; |
| 235 SkPoint activeLeftTop(bool onlySortable, int* firstT) const; | 270 SkPoint activeLeftTop(bool onlySortable, int* firstT) const; |
| 236 bool activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, SkPathO
p op); | 271 bool activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, SkPathO
p op); |
| 237 bool activeWinding(int index, int endIndex); | 272 bool activeWinding(int index, int endIndex); |
| 238 void addCubic(const SkPoint pts[4], bool operand, bool evenOdd); | 273 void addCubic(const SkPoint pts[4], bool operand, bool evenOdd); |
| 239 void addCurveTo(int start, int end, SkPathWriter* path, bool active) const; | 274 void addCurveTo(int start, int end, SkPathWriter* path, bool active) const; |
| 275 void addEndSpan(int endIndex); |
| 240 void addLine(const SkPoint pts[2], bool operand, bool evenOdd); | 276 void addLine(const SkPoint pts[2], bool operand, bool evenOdd); |
| 241 void addOtherT(int index, double otherT, int otherIndex); | 277 void addOtherT(int index, double otherT, int otherIndex); |
| 242 void addQuad(const SkPoint pts[3], bool operand, bool evenOdd); | 278 void addQuad(const SkPoint pts[3], bool operand, bool evenOdd); |
| 243 int addSelfT(SkOpSegment* other, const SkPoint& pt, double newT); | 279 void addSimpleAngle(int endIndex); |
| 280 int addSelfT(const SkPoint& pt, double newT); |
| 281 void addStartSpan(int endIndex); |
| 244 int addT(SkOpSegment* other, const SkPoint& pt, double newT); | 282 int addT(SkOpSegment* other, const SkPoint& pt, double newT); |
| 245 void addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* o
ther); | 283 void addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* o
ther); |
| 246 void addTCoincident(const SkPoint& startPt, const SkPoint& endPt, double end
T, | 284 void addTCoincident(const SkPoint& startPt, const SkPoint& endPt, double end
T, |
| 247 SkOpSegment* other); | 285 SkOpSegment* other); |
| 248 void addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind,
const SkPoint& pt); | 286 const SkOpSpan* addTPair(double t, SkOpSegment* other, double otherT, bool b
orrowWind, |
| 287 const SkPoint& pt); |
| 288 bool alignSpan(int index, double thisT, const SkPoint& thisPt); |
| 289 void alignSpanState(int start, int end); |
| 290 const SkOpAngle& angle(int index) const; |
| 249 bool betweenTs(int lesser, double testT, int greater) const; | 291 bool betweenTs(int lesser, double testT, int greater) const; |
| 292 bool calcAngles(); |
| 293 void checkDuplicates(); |
| 250 void checkEnds(); | 294 void checkEnds(); |
| 295 void checkMultiples(); |
| 296 void checkSmall(); |
| 251 bool checkSmall(int index) const; | 297 bool checkSmall(int index) const; |
| 252 void checkTiny(); | 298 void checkTiny(); |
| 253 int computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeT
ype, | 299 int computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeT
ype); |
| 254 SkTArray<SkOpAngle, true>* angles, SkTArray<SkOpAngle*, true
>* sorted); | |
| 255 int crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hitT, bool*
hitSomething, | 300 int crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hitT, bool*
hitSomething, |
| 256 double mid, bool opp, bool current) const; | 301 double mid, bool opp, bool current) const; |
| 257 bool findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* other, int
oStart, int oEnd, | 302 bool findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* other, int
oStart, int oEnd, |
| 258 int step, SkPoint* startPt, SkPoint* endPt, double*
endT) const; | 303 int step, SkPoint* startPt, SkPoint* endPt, double*
endT) const; |
| 259 SkOpSegment* findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart, int* ne
xtEnd, | 304 SkOpSegment* findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart, int* ne
xtEnd, |
| 260 bool* unsortable, SkPathOp op, const int xorMiMask, | 305 bool* unsortable, SkPathOp op, int xorMiMask, int xo
rSuMask); |
| 261 const int xorSuMask); | |
| 262 SkOpSegment* findNextWinding(SkTDArray<SkOpSpan*>* chase, int* nextStart, in
t* nextEnd, | 306 SkOpSegment* findNextWinding(SkTDArray<SkOpSpan*>* chase, int* nextStart, in
t* nextEnd, |
| 263 bool* unsortable); | 307 bool* unsortable); |
| 264 SkOpSegment* findNextXor(int* nextStart, int* nextEnd, bool* unsortable); | 308 SkOpSegment* findNextXor(int* nextStart, int* nextEnd, bool* unsortable); |
| 309 int findExactT(double t, const SkOpSegment* ) const; |
| 265 int findT(double t, const SkOpSegment* ) const; | 310 int findT(double t, const SkOpSegment* ) const; |
| 266 SkOpSegment* findTop(int* tIndex, int* endIndex, bool* unsortable, bool only
Sortable); | 311 SkOpSegment* findTop(int* tIndex, int* endIndex, bool* unsortable); |
| 267 void fixOtherTIndex(); | 312 void fixOtherTIndex(); |
| 268 void initWinding(int start, int end); | 313 void initWinding(int start, int end, SkOpAngle::IncludeType angleIncludeType
); |
| 269 void initWinding(int start, int end, double tHit, int winding, SkScalar hitD
x, int oppWind, | 314 void initWinding(int start, int end, double tHit, int winding, SkScalar hitD
x, int oppWind, |
| 270 SkScalar hitOppDx); | 315 SkScalar hitOppDx); |
| 271 bool isMissing(double startT, const SkPoint& pt) const; | 316 bool isMissing(double startT, const SkPoint& pt) const; |
| 317 bool isSmall(const SkOpAngle* angle) const; |
| 272 bool isTiny(const SkOpAngle* angle) const; | 318 bool isTiny(const SkOpAngle* angle) const; |
| 273 bool joinCoincidence(SkOpSegment* other, double otherT, int step, bool cance
l); | 319 bool joinCoincidence(SkOpSegment* other, double otherT, int step, bool cance
l); |
| 274 SkOpSpan* markAndChaseDoneBinary(int index, int endIndex); | 320 SkOpSpan* markAndChaseDoneBinary(int index, int endIndex); |
| 275 SkOpSpan* markAndChaseDoneUnary(int index, int endIndex); | 321 SkOpSpan* markAndChaseDoneUnary(int index, int endIndex); |
| 276 SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWi
nding); | 322 SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWi
nding); |
| 277 SkOpSpan* markAngle(int maxWinding, int sumWinding, int oppMaxWinding, int o
ppSumWinding, | 323 SkOpSpan* markAngle(int maxWinding, int sumWinding, int oppMaxWinding, int o
ppSumWinding, |
| 278 const SkOpAngle* angle); | 324 const SkOpAngle* angle); |
| 279 void markDone(int index, int winding); | 325 void markDone(int index, int winding); |
| 280 void markDoneBinary(int index); | 326 void markDoneBinary(int index); |
| 281 void markDoneUnary(int index); | 327 void markDoneUnary(int index); |
| 282 bool nextCandidate(int* start, int* end) const; | 328 bool nextCandidate(int* start, int* end) const; |
| 283 int nextSpan(int from, int step) const; | 329 int nextSpan(int from, int step) const; |
| 284 void setUpWindings(int index, int endIndex, int* sumMiWinding, int* sumSuWin
ding, | 330 void setUpWindings(int index, int endIndex, int* sumMiWinding, int* sumSuWin
ding, |
| 285 int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWin
ding); | 331 int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWin
ding); |
| 286 enum SortAngleKind { | 332 void sortAngles(); |
| 287 kMustBeOrdered_SortAngleKind, // required for winding calc | |
| 288 kMayBeUnordered_SortAngleKind // ok for find top | |
| 289 }; | |
| 290 static bool SortAngles(const SkTArray<SkOpAngle, true>& angles, // FIXME: r
eplace with | |
| 291 SkTArray<SkOpAngle*, true>* angleList, // Sort An
gles 2 | |
| 292 SortAngleKind ); | |
| 293 static bool SortAngles2(const SkTArray<SkOpAngle, true>& angles, | |
| 294 SkTArray<SkOpAngle*, true>* angleList); | |
| 295 bool subDivide(int start, int end, SkPoint edge[4]) const; | 333 bool subDivide(int start, int end, SkPoint edge[4]) const; |
| 296 bool subDivide(int start, int end, SkDCubic* result) const; | 334 bool subDivide(int start, int end, SkDCubic* result) const; |
| 297 void undoneSpan(int* start, int* end); | 335 void undoneSpan(int* start, int* end); |
| 298 int updateOppWindingReverse(const SkOpAngle* angle) const; | 336 int updateOppWindingReverse(const SkOpAngle* angle) const; |
| 299 int updateWindingReverse(const SkOpAngle* angle) const; | 337 int updateWindingReverse(const SkOpAngle* angle) const; |
| 300 static bool UseInnerWinding(int outerWinding, int innerWinding); | 338 static bool UseInnerWinding(int outerWinding, int innerWinding); |
| 339 static bool UseInnerWindingReverse(int outerWinding, int innerWinding); |
| 301 int windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar* dx) const; | 340 int windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar* dx) const; |
| 302 int windSum(const SkOpAngle* angle) const; | 341 int windSum(const SkOpAngle* angle) const; |
| 303 | 342 // available for testing only |
| 304 #ifdef SK_DEBUG | 343 #if DEBUG_VALIDATE |
| 344 bool debugContains(const SkOpAngle* ) const; |
| 345 #endif |
| 346 #if defined(SK_DEBUG) || !FORCE_RELEASE |
| 305 int debugID() const { | 347 int debugID() const { |
| 306 return fID; | 348 return fID; |
| 307 } | 349 } |
| 350 #else |
| 351 int debugID() const { |
| 352 return -1; |
| 353 } |
| 308 #endif | 354 #endif |
| 309 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY | 355 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY |
| 310 void debugShowActiveSpans() const; | 356 void debugShowActiveSpans() const; |
| 311 #endif | 357 #endif |
| 312 #if DEBUG_SORT || DEBUG_SWAP_TOP | |
| 313 void debugShowSort(const char* fun, const SkTArray<SkOpAngle*, true>& angles
, int first, | |
| 314 const int contourWinding, const int oppContourWinding, bool sortable
) const; | |
| 315 void debugShowSort(const char* fun, const SkTArray<SkOpAngle*, true>& angles
, int first, | |
| 316 bool sortable); | |
| 317 #endif | |
| 318 #if DEBUG_CONCIDENT | 358 #if DEBUG_CONCIDENT |
| 319 void debugShowTs(const char* prefix) const; | 359 void debugShowTs(const char* prefix) const; |
| 320 #endif | 360 #endif |
| 321 #if DEBUG_SHOW_WINDING | 361 #if DEBUG_SHOW_WINDING |
| 322 int debugShowWindingValues(int slotCount, int ofInterest) const; | 362 int debugShowWindingValues(int slotCount, int ofInterest) const; |
| 323 #endif | 363 #endif |
| 364 void debugValidate() const; |
| 365 // available to testing only |
| 366 void dumpAngles() const; |
| 367 void dumpContour(int firstID, int lastID) const; |
| 368 void dumpPts() const; |
| 369 void dumpSpans() const; |
| 324 | 370 |
| 325 private: | 371 private: |
| 326 struct MissingSpan { | 372 struct MissingSpan { |
| 327 double fT; | 373 double fT; |
| 328 double fEndT; | 374 double fEndT; |
| 329 SkOpSegment* fSegment; | 375 SkOpSegment* fSegment; |
| 330 SkOpSegment* fOther; | 376 SkOpSegment* fOther; |
| 331 double fOtherT; | 377 double fOtherT; |
| 332 SkPoint fPt; | 378 SkPoint fPt; |
| 333 }; | 379 }; |
| 334 | 380 |
| 335 bool activeAngleOther(int index, int* done, SkTArray<SkOpAngle, true>* angle
s); | 381 const SkOpAngle* activeAngleInner(int index, int* start, int* end, bool* don
e, |
| 336 bool activeAngleInner(int index, int* done, SkTArray<SkOpAngle, true>* angle
s); | 382 bool* sortable) const; |
| 383 const SkOpAngle* activeAngleOther(int index, int* start, int* end, bool* don
e, |
| 384 bool* sortable) const; |
| 337 bool activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, SkPathO
p op, | 385 bool activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, SkPathO
p op, |
| 338 int* sumMiWinding, int* sumSuWinding, int* maxWinding, int* su
mWinding, | 386 int* sumMiWinding, int* sumSuWinding); |
| 339 int* oppMaxWinding, int* oppSumWinding); | 387 bool activeWinding(int index, int endIndex, int* sumWinding); |
| 340 bool activeWinding(int index, int endIndex, int* maxWinding, int* sumWinding
); | |
| 341 void addAngle(SkTArray<SkOpAngle, true>* angles, int start, int end) const; | |
| 342 void addCancelOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSeg
ment* other); | 388 void addCancelOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSeg
ment* other); |
| 343 void addCoinOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSegme
nt* other); | 389 void addCoinOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSegme
nt* other); |
| 390 int addSingletonAngleDown(int start, SkOpSegment** otherPtr); |
| 391 int addSingletonAngleUp(int start, SkOpSegment** otherPtr); |
| 392 SkOpAngle* addSingletonAngles(int start, int step); |
| 344 void addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind,
const SkPoint& pt, | 393 void addTPair(double t, SkOpSegment* other, double otherT, bool borrowWind,
const SkPoint& pt, |
| 345 const SkPoint& oPt); | 394 const SkPoint& oPt); |
| 346 void addTwoAngles(int start, int end, SkTArray<SkOpAngle, true>* angles) con
st; | |
| 347 bool betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) cons
t; | 395 bool betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) cons
t; |
| 348 bool buildAngles(int index, SkTArray<SkOpAngle, true>* angles, bool includeO
pp) const; | |
| 349 void buildAnglesInner(int index, SkTArray<SkOpAngle, true>* angles) const; | |
| 350 void bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* index, | 396 void bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* index, |
| 351 SkTArray<SkPoint, true>* outsideTs); | 397 SkTArray<SkPoint, true>* outsideTs); |
| 352 void bumpCoincidentOther(const SkOpSpan& oTest, int* index, | 398 void bumpCoincidentOther(const SkOpSpan& oTest, int* index, |
| 353 SkTArray<SkPoint, true>* outsideTs); | 399 SkTArray<SkPoint, true>* outsideTs); |
| 354 bool bumpSpan(SkOpSpan* span, int windDelta, int oppDelta); | 400 bool bumpSpan(SkOpSpan* span, int windDelta, int oppDelta); |
| 401 bool calcLoopSpanCount(const SkOpSpan& thisSpan, int* smallCounts); |
| 402 void checkLinks(const SkOpSpan* , |
| 403 SkTArray<MissingSpan, true>* missingSpans) const; |
| 404 static void CheckOneLink(const SkOpSpan* test, const SkOpSpan* oSpan, |
| 405 const SkOpSpan* oFirst, const SkOpSpan* oLast, |
| 406 const SkOpSpan** missingPtr, |
| 407 SkTArray<MissingSpan, true>* missingSpans); |
| 408 int checkSetAngle(int tIndex) const; |
| 409 void checkSmallCoincidence(const SkOpSpan& span, SkTArray<MissingSpan, true>
* ); |
| 355 bool clockwise(int tStart, int tEnd) const; | 410 bool clockwise(int tStart, int tEnd) const; |
| 356 static void ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle, | 411 static void ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle, |
| 357 SkOpAngle::IncludeType ); | 412 SkOpAngle::IncludeType ); |
| 358 static void ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* next
Angle, | 413 static void ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* next
Angle, |
| 359 SkOpAngle::IncludeType ); | 414 SkOpAngle::IncludeType ); |
| 360 bool decrementSpan(SkOpSpan* span); | 415 bool decrementSpan(SkOpSpan* span); |
| 361 int findStartingEdge(const SkTArray<SkOpAngle*, true>& sorted, int start, in
t end); | 416 int findEndSpan(int endIndex) const; |
| 417 int findStartSpan(int startIndex) const; |
| 418 int firstActive(int tIndex) const; |
| 419 const SkOpSpan& firstSpan(const SkOpSpan& thisSpan) const; |
| 362 void init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd
); | 420 void init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd
); |
| 421 bool inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPtr) const; |
| 363 bool isSimple(int end) const; | 422 bool isSimple(int end) const; |
| 364 bool isTiny(int index) const; | 423 bool isTiny(int index) const; |
| 424 const SkOpSpan& lastSpan(const SkOpSpan& thisSpan) const; |
| 365 void matchWindingValue(int tIndex, double t, bool borrowWind); | 425 void matchWindingValue(int tIndex, double t, bool borrowWind); |
| 366 SkOpSpan* markAndChaseDone(int index, int endIndex, int winding); | 426 SkOpSpan* markAndChaseDone(int index, int endIndex, int winding); |
| 367 SkOpSpan* markAndChaseDoneBinary(const SkOpAngle* angle, int winding, int op
pWinding); | 427 SkOpSpan* markAndChaseDoneBinary(const SkOpAngle* angle, int winding, int op
pWinding); |
| 368 SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, const int winding); | 428 SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding); |
| 429 SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding); |
| 369 SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding, int oppW
inding); | 430 SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding, int oppW
inding); |
| 370 SkOpSpan* markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle); | 431 SkOpSpan* markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle); |
| 371 void markDoneBinary(int index, int winding, int oppWinding); | 432 void markDoneBinary(int index, int winding, int oppWinding); |
| 372 SkOpSpan* markAndChaseDoneUnary(const SkOpAngle* angle, int winding); | 433 SkOpSpan* markAndChaseDoneUnary(const SkOpAngle* angle, int winding); |
| 373 void markOneDone(const char* funName, int tIndex, int winding); | 434 void markOneDone(const char* funName, int tIndex, int winding); |
| 374 void markOneDoneBinary(const char* funName, int tIndex); | 435 void markOneDoneBinary(const char* funName, int tIndex); |
| 375 void markOneDoneBinary(const char* funName, int tIndex, int winding, int opp
Winding); | 436 void markOneDoneBinary(const char* funName, int tIndex, int winding, int opp
Winding); |
| 376 void markOneDoneUnary(const char* funName, int tIndex); | 437 void markOneDoneUnary(const char* funName, int tIndex); |
| 377 SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding); | 438 SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding); |
| 378 SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding, int o
ppWinding); | 439 SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding, int o
ppWinding); |
| 379 void markWinding(int index, int winding); | 440 void markWinding(int index, int winding); |
| 380 void markWinding(int index, int winding, int oppWinding); | 441 void markWinding(int index, int winding, int oppWinding); |
| 381 void markUnsortable(int start, int end); | 442 void markUnsortable(int start, int end); |
| 382 bool monotonicInY(int tStart, int tEnd) const; | 443 bool monotonicInY(int tStart, int tEnd) const; |
| 444 |
| 445 bool multipleEnds() const { |
| 446 return fTs[count() - 2].fT == 1; |
| 447 } |
| 448 |
| 449 bool multipleStarts() const { |
| 450 return fTs[1].fT == 0; |
| 451 } |
| 452 |
| 383 bool multipleSpans(int end) const; | 453 bool multipleSpans(int end) const; |
| 384 SkOpSegment* nextChase(int* index, const int step, int* min, SkOpSpan** last
); | 454 SkOpSegment* nextChase(int* index, const int step, int* min, SkOpSpan** last
); |
| 385 int nextExactSpan(int from, int step) const; | 455 int nextExactSpan(int from, int step) const; |
| 386 bool serpentine(int tStart, int tEnd) const; | 456 bool serpentine(int tStart, int tEnd) const; |
| 457 void setFromAngleIndex(int endIndex, int angleIndex); |
| 458 void setToAngleIndex(int endIndex, int angleIndex); |
| 387 void setUpWindings(int index, int endIndex, int* sumMiWinding, | 459 void setUpWindings(int index, int endIndex, int* sumMiWinding, |
| 388 int* maxWinding, int* sumWinding); | 460 int* maxWinding, int* sumWinding); |
| 389 void subDivideBounds(int start, int end, SkPathOpsBounds* bounds) const; | 461 void subDivideBounds(int start, int end, SkPathOpsBounds* bounds) const; |
| 390 static void TrackOutsidePair(SkTArray<SkPoint, true>* outsideTs, const SkPoi
nt& endPt, | 462 static void TrackOutsidePair(SkTArray<SkPoint, true>* outsideTs, const SkPoi
nt& endPt, |
| 391 const SkPoint& startPt); | 463 const SkPoint& startPt); |
| 392 static void TrackOutside(SkTArray<SkPoint, true>* outsideTs, const SkPoint&
startPt); | 464 static void TrackOutside(SkTArray<SkPoint, true>* outsideTs, const SkPoint&
startPt); |
| 393 int updateOppWinding(int index, int endIndex) const; | 465 int updateOppWinding(int index, int endIndex) const; |
| 394 int updateOppWinding(const SkOpAngle* angle) const; | 466 int updateOppWinding(const SkOpAngle* angle) const; |
| 395 int updateWinding(int index, int endIndex) const; | 467 int updateWinding(int index, int endIndex) const; |
| 396 int updateWinding(const SkOpAngle* angle) const; | 468 int updateWinding(const SkOpAngle* angle) const; |
| 397 int updateWindingReverse(int index, int endIndex) const; | 469 int updateWindingReverse(int index, int endIndex) const; |
| 398 static bool UseInnerWindingReverse(int outerWinding, int innerWinding); | |
| 399 SkOpSpan* verifyOneWinding(const char* funName, int tIndex); | 470 SkOpSpan* verifyOneWinding(const char* funName, int tIndex); |
| 400 SkOpSpan* verifyOneWindingU(const char* funName, int tIndex); | 471 SkOpSpan* verifyOneWindingU(const char* funName, int tIndex); |
| 401 | 472 |
| 402 SkScalar xAtT(const SkOpSpan* span) const { | 473 SkScalar xAtT(const SkOpSpan* span) const { |
| 403 return xyAtT(span).fX; | 474 return xyAtT(span).fX; |
| 404 } | 475 } |
| 405 | 476 |
| 406 SkScalar yAtT(const SkOpSpan* span) const { | 477 SkScalar yAtT(const SkOpSpan* span) const { |
| 407 return xyAtT(span).fY; | 478 return xyAtT(span).fY; |
| 408 } | 479 } |
| 409 | 480 |
| 410 void zeroSpan(SkOpSpan* span); | 481 void zeroSpan(SkOpSpan* span); |
| 411 | 482 |
| 412 #if DEBUG_SWAP_TOP | 483 #if DEBUG_SWAP_TOP |
| 413 bool controlsContainedByEnds(int tStart, int tEnd) const; | 484 bool controlsContainedByEnds(int tStart, int tEnd) const; |
| 414 #endif | 485 #endif |
| 486 void debugAddAngle(int start, int end); |
| 415 #if DEBUG_CONCIDENT | 487 #if DEBUG_CONCIDENT |
| 416 void debugAddTPair(double t, const SkOpSegment& other, double otherT) const
; | 488 void debugAddTPair(double t, const SkOpSegment& other, double otherT) const; |
| 489 #endif |
| 490 #if DEBUG_ANGLE |
| 491 void debugCheckPointsEqualish(int tStart, int tEnd) const; |
| 417 #endif | 492 #endif |
| 418 #if DEBUG_MARK_DONE || DEBUG_UNSORTABLE | 493 #if DEBUG_MARK_DONE || DEBUG_UNSORTABLE |
| 419 void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding)
; | 494 void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding)
; |
| 420 void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding,
int oppWinding); | 495 void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding,
int oppWinding); |
| 421 #endif | 496 #endif |
| 422 #if DEBUG_WINDING | 497 #if DEBUG_WINDING |
| 423 static char as_digit(int value) { | 498 static char as_digit(int value) { |
| 424 return value < 0 ? '?' : value <= 9 ? '0' + value : '+'; | 499 return value < 0 ? '?' : value <= 9 ? '0' + value : '+'; |
| 425 } | 500 } |
| 426 #endif | 501 #endif |
| 427 void debugValidate() const; | 502 // available to testing only |
| 428 #ifdef SK_DEBUG | 503 void debugConstruct(); |
| 429 void dumpPts() const; | 504 void debugConstructCubic(SkPoint shortQuad[4]); |
| 505 void debugConstructLine(SkPoint shortQuad[2]); |
| 506 void debugConstructQuad(SkPoint shortQuad[3]); |
| 507 void debugReset(); |
| 430 void dumpDPts() const; | 508 void dumpDPts() const; |
| 431 void dumpSpans() const; | 509 void dumpSpan(int index) const; |
| 432 #endif | |
| 433 | 510 |
| 434 const SkPoint* fPts; | 511 const SkPoint* fPts; |
| 435 SkPathOpsBounds fBounds; | 512 SkPathOpsBounds fBounds; |
| 436 // FIXME: can't convert to SkTArray because it uses insert | 513 // FIXME: can't convert to SkTArray because it uses insert |
| 437 SkTDArray<SkOpSpan> fTs; // two or more (always includes t=0 t=1) | 514 SkTDArray<SkOpSpan> fTs; // 2+ (always includes t=0 t=1) -- at least (numbe
r of spans) + 1 |
| 515 // FIXME: replace both with bucket storage that allows direct immovable pointers
to angles |
| 516 SkTArray<SkOpAngle, true> fSingletonAngles; // 0 or 2 -- allocated for sing
letons |
| 517 SkTArray<SkOpAngle, true> fAngles; // 0 or 2+ -- (number of non-zero spans)
* 2 |
| 438 // OPTIMIZATION: could pack donespans, verb, operand, xor into 1 int-sized v
alue | 518 // OPTIMIZATION: could pack donespans, verb, operand, xor into 1 int-sized v
alue |
| 439 int fDoneSpans; // quick check that segment is finished | 519 int fDoneSpans; // quick check that segment is finished |
| 440 // OPTIMIZATION: force the following to be byte-sized | 520 // OPTIMIZATION: force the following to be byte-sized |
| 441 SkPath::Verb fVerb; | 521 SkPath::Verb fVerb; |
| 522 bool fLoop; // set if cubic intersects itself |
| 442 bool fOperand; | 523 bool fOperand; |
| 443 bool fXor; // set if original contour had even-odd fill | 524 bool fXor; // set if original contour had even-odd fill |
| 444 bool fOppXor; // set if opposite operand had even-odd fill | 525 bool fOppXor; // set if opposite operand had even-odd fill |
| 445 #ifdef SK_DEBUG | 526 bool fSmall; // set if some span is small |
| 527 bool fTiny; // set if some span is tiny |
| 528 #if defined(SK_DEBUG) || !FORCE_RELEASE |
| 446 int fID; | 529 int fID; |
| 447 #endif | 530 #endif |
| 531 |
| 532 friend class PathOpsSegmentTester; |
| 448 }; | 533 }; |
| 449 | 534 |
| 450 #endif | 535 #endif |
| OLD | NEW |