OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2012 Google Inc. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. |
| 6 */ |
| 7 #ifndef SkOpSegment_DEFINE |
| 8 #define SkOpSegment_DEFINE |
| 9 |
| 10 #include "SkOpAngle.h" |
| 11 #include "SkPathOpsBounds.h" |
| 12 #include "SkPathOpsCurve.h" |
| 13 #include "SkTDArray.h" |
| 14 |
| 15 class SkPathWriter; |
| 16 |
| 17 class SkOpSegment { |
| 18 public: |
| 19 SkOpSegment() { |
| 20 #if DEBUG_DUMP |
| 21 fID = ++gSegmentID; |
| 22 #endif |
| 23 } |
| 24 |
| 25 bool operator<(const SkOpSegment& rh) const { |
| 26 return fBounds.fTop < rh.fBounds.fTop; |
| 27 } |
| 28 |
| 29 const SkPathOpsBounds& bounds() const { |
| 30 return fBounds; |
| 31 } |
| 32 |
| 33 // OPTIMIZE |
| 34 // when the edges are initially walked, they don't automatically get the pri
or and next |
| 35 // edges assigned to positions t=0 and t=1. Doing that would remove the need
for this check, |
| 36 // and would additionally remove the need for similar checks in condition ed
ges. It would |
| 37 // also allow intersection code to assume end of segment intersections (mayb
e?) |
| 38 bool complete() const { |
| 39 int count = fTs.count(); |
| 40 return count > 1 && fTs[0].fT == 0 && fTs[--count].fT == 1; |
| 41 } |
| 42 |
| 43 bool done() const { |
| 44 SkASSERT(fDoneSpans <= fTs.count()); |
| 45 return fDoneSpans == fTs.count(); |
| 46 } |
| 47 |
| 48 bool done(int min) const { |
| 49 return fTs[min].fDone; |
| 50 } |
| 51 |
| 52 bool done(const SkOpAngle* angle) const { |
| 53 return done(SkMin32(angle->start(), angle->end())); |
| 54 } |
| 55 |
| 56 SkVector dxdy(int index) const { |
| 57 return (*CurveSlopeAtT[fVerb])(fPts, fTs[index].fT); |
| 58 } |
| 59 |
| 60 SkScalar dy(int index) const { |
| 61 return dxdy(index).fY; |
| 62 } |
| 63 |
| 64 bool intersected() const { |
| 65 return fTs.count() > 0; |
| 66 } |
| 67 |
| 68 bool isCanceled(int tIndex) const { |
| 69 return fTs[tIndex].fWindValue == 0 && fTs[tIndex].fOppValue == 0; |
| 70 } |
| 71 |
| 72 bool isConnected(int startIndex, int endIndex) const { |
| 73 return fTs[startIndex].fWindSum != SK_MinS32 || fTs[endIndex].fWindSum !
= SK_MinS32; |
| 74 } |
| 75 |
| 76 bool isHorizontal() const { |
| 77 return fBounds.fTop == fBounds.fBottom; |
| 78 } |
| 79 |
| 80 bool isVertical() const { |
| 81 return fBounds.fLeft == fBounds.fRight; |
| 82 } |
| 83 |
| 84 bool isVertical(int start, int end) const { |
| 85 return (*CurveIsVertical[fVerb])(fPts, start, end); |
| 86 } |
| 87 |
| 88 bool operand() const { |
| 89 return fOperand; |
| 90 } |
| 91 |
| 92 int oppSign(const SkOpAngle* angle) const { |
| 93 SkASSERT(angle->segment() == this); |
| 94 return oppSign(angle->start(), angle->end()); |
| 95 } |
| 96 |
| 97 int oppSign(int startIndex, int endIndex) const { |
| 98 int result = startIndex < endIndex ? -fTs[startIndex].fOppValue : fTs[en
dIndex].fOppValue; |
| 99 #if DEBUG_WIND_BUMP |
| 100 SkDebugf("%s oppSign=%d\n", __FUNCTION__, result); |
| 101 #endif |
| 102 return result; |
| 103 } |
| 104 |
| 105 int oppSum(int tIndex) const { |
| 106 return fTs[tIndex].fOppSum; |
| 107 } |
| 108 |
| 109 int oppSum(const SkOpAngle* angle) const { |
| 110 int lesser = SkMin32(angle->start(), angle->end()); |
| 111 return fTs[lesser].fOppSum; |
| 112 } |
| 113 |
| 114 int oppValue(int tIndex) const { |
| 115 return fTs[tIndex].fOppValue; |
| 116 } |
| 117 |
| 118 int oppValue(const SkOpAngle* angle) const { |
| 119 int lesser = SkMin32(angle->start(), angle->end()); |
| 120 return fTs[lesser].fOppValue; |
| 121 } |
| 122 |
| 123 const SkPoint* pts() const { |
| 124 return fPts; |
| 125 } |
| 126 |
| 127 void reset() { |
| 128 init(NULL, (SkPath::Verb) -1, false, false); |
| 129 fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax); |
| 130 fTs.reset(); |
| 131 } |
| 132 |
| 133 void setOppXor(bool isOppXor) { |
| 134 fOppXor = isOppXor; |
| 135 } |
| 136 |
| 137 void setSpanT(int index, double t) { |
| 138 SkOpSpan& span = fTs[index]; |
| 139 span.fT = t; |
| 140 span.fOther->fTs[span.fOtherIndex].fOtherT = t; |
| 141 } |
| 142 |
| 143 void setUpWinding(int index, int endIndex, int& maxWinding, int& sumWinding)
{ |
| 144 int deltaSum = spanSign(index, endIndex); |
| 145 maxWinding = sumWinding; |
| 146 sumWinding = sumWinding -= deltaSum; |
| 147 } |
| 148 |
| 149 // OPTIMIZATION: mark as debugging only if used solely by tests |
| 150 const SkOpSpan& span(int tIndex) const { |
| 151 return fTs[tIndex]; |
| 152 } |
| 153 |
| 154 int spanSign(const SkOpAngle* angle) const { |
| 155 SkASSERT(angle->segment() == this); |
| 156 return spanSign(angle->start(), angle->end()); |
| 157 } |
| 158 |
| 159 int spanSign(int startIndex, int endIndex) const { |
| 160 int result = startIndex < endIndex ? -fTs[startIndex].fWindValue : fTs[e
ndIndex].fWindValue; |
| 161 #if DEBUG_WIND_BUMP |
| 162 SkDebugf("%s spanSign=%d\n", __FUNCTION__, result); |
| 163 #endif |
| 164 return result; |
| 165 } |
| 166 |
| 167 // OPTIMIZATION: mark as debugging only if used solely by tests |
| 168 double t(int tIndex) const { |
| 169 return fTs[tIndex].fT; |
| 170 } |
| 171 |
| 172 double tAtMid(int start, int end, double mid) const { |
| 173 return fTs[start].fT * (1 - mid) + fTs[end].fT * mid; |
| 174 } |
| 175 |
| 176 bool unsortable(int index) const { |
| 177 return fTs[index].fUnsortableStart || fTs[index].fUnsortableEnd; |
| 178 } |
| 179 |
| 180 void updatePts(const SkPoint pts[]) { |
| 181 fPts = pts; |
| 182 } |
| 183 |
| 184 SkPath::Verb verb() const { |
| 185 return fVerb; |
| 186 } |
| 187 |
| 188 int windSum(int tIndex) const { |
| 189 return fTs[tIndex].fWindSum; |
| 190 } |
| 191 |
| 192 int windValue(int tIndex) const { |
| 193 return fTs[tIndex].fWindValue; |
| 194 } |
| 195 |
| 196 SkScalar xAtT(int index) const { |
| 197 return xAtT(&fTs[index]); |
| 198 } |
| 199 |
| 200 SkScalar xAtT(const SkOpSpan* span) const { |
| 201 return xyAtT(span).fX; |
| 202 } |
| 203 |
| 204 const SkPoint& xyAtT(const SkOpSpan* span) const { |
| 205 return span->fPt; |
| 206 } |
| 207 |
| 208 // used only by right angle winding finding |
| 209 SkPoint xyAtT(double mid) const { |
| 210 return (*CurvePointAtT[fVerb])(fPts, mid); |
| 211 } |
| 212 |
| 213 const SkPoint& xyAtT(int index) const { |
| 214 return xyAtT(&fTs[index]); |
| 215 } |
| 216 |
| 217 SkScalar yAtT(int index) const { |
| 218 return yAtT(&fTs[index]); |
| 219 } |
| 220 |
| 221 SkScalar yAtT(const SkOpSpan* span) const { |
| 222 return xyAtT(span).fY; |
| 223 } |
| 224 |
| 225 bool activeAngle(int index, int& done, SkTDArray<SkOpAngle>& angles); |
| 226 bool activeAngleOther(int index, int& done, SkTDArray<SkOpAngle>& angles); |
| 227 bool activeAngleInner(int index, int& done, SkTDArray<SkOpAngle>& angles); |
| 228 SkPoint activeLeftTop(bool onlySortable, int* firstT) const; |
| 229 bool activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, SkPathO
p op); |
| 230 bool activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, SkPathO
p op, |
| 231 int& sumMiWinding, int& sumSuWinding, int& maxWinding, int& su
mWinding, |
| 232 int& oppMaxWinding, int& oppSumWinding); |
| 233 bool activeWinding(int index, int endIndex); |
| 234 bool activeWinding(int index, int endIndex, int& maxWinding, int& sumWinding
); |
| 235 void addAngle(SkTDArray<SkOpAngle>& angles, int start, int end) const; |
| 236 void addCancelOutsides(double tStart, double oStart, SkOpSegment& other, dou
ble oEnd); |
| 237 void addCoinOutsides(const SkTDArray<double>& outsideTs, SkOpSegment& other,
double oEnd); |
| 238 void addCubic(const SkPoint pts[4], bool operand, bool evenOdd); |
| 239 void addCurveTo(int start, int end, SkPathWriter& path, bool active) const; |
| 240 void addLine(const SkPoint pts[2], bool operand, bool evenOdd); |
| 241 void addOtherT(int index, double otherT, int otherIndex); |
| 242 void addQuad(const SkPoint pts[3], bool operand, bool evenOdd); |
| 243 int addSelfT(SkOpSegment* other, const SkPoint& pt, double newT); |
| 244 int addT(SkOpSegment* other, const SkPoint& pt, double newT); |
| 245 void addTCancel(double startT, double endT, SkOpSegment& other, double oStar
tT, double oEndT); |
| 246 void addTCoincident(double startT, double endT, SkOpSegment& other, double o
StartT, |
| 247 double oEndT); |
| 248 void addTPair(double t, SkOpSegment& other, double otherT, bool borrowWind,
const SkPoint& pt); |
| 249 void addTwoAngles(int start, int end, SkTDArray<SkOpAngle>& angles) const; |
| 250 |
| 251 int addUnsortableT(SkOpSegment* other, bool start, const SkPoint& pt, double
newT); |
| 252 int advanceCoincidentOther(const SkOpSpan* test, double oEndT, int& oIndex); |
| 253 int advanceCoincidentThis(const SkOpSpan* oTest, bool opp, int index); |
| 254 bool betweenTs(int lesser, double testT, int greater); |
| 255 void buildAngles(int index, SkTDArray<SkOpAngle>& angles, bool includeOpp) c
onst; |
| 256 void buildAnglesInner(int index, SkTDArray<SkOpAngle>& angles) const; |
| 257 int bumpCoincidentThis(const SkOpSpan* oTest, bool opp, int index, |
| 258 SkTDArray<double>& outsideTs); |
| 259 int bumpCoincidentOther(const SkOpSpan* test, double oEndT, int& oIndex, |
| 260 SkTDArray<double>& oOutsideTs); |
| 261 bool bumpSpan(SkOpSpan* span, int windDelta, int oppDelta); |
| 262 bool clockwise(int tStart, int tEnd) const; |
| 263 int computeSum(int startIndex, int endIndex, bool binary); |
| 264 int crossedSpanY(const SkPoint& basePt, SkScalar& bestY, double& hitT, bool&
hitSomething, |
| 265 double mid, bool opp, bool current) const; |
| 266 void decrementSpan(SkOpSpan* span); |
| 267 bool equalPoints(int greaterTIndex, int lesserTIndex); |
| 268 SkOpSegment* findNextOp(SkTDArray<SkOpSpan*>& chase, int& nextStart, int& ne
xtEnd, |
| 269 bool& unsortable, SkPathOp op, const int xorMiMask, |
| 270 const int xorSuMask); |
| 271 int findStartingEdge(SkTDArray<SkOpAngle*>& sorted, int start, int end); |
| 272 SkOpSegment* findNextWinding(SkTDArray<SkOpSpan*>& chase, int& nextStart, in
t& nextEnd, |
| 273 bool& unsortable); |
| 274 SkOpSegment* findNextXor(int& nextStart, int& nextEnd, bool& unsortable); |
| 275 void findTooCloseToCall(); |
| 276 SkOpSegment* findTop(int& tIndex, int& endIndex, bool& unsortable, bool only
Sortable); |
| 277 void fixOtherTIndex(); |
| 278 void init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd
); |
| 279 void initWinding(int start, int end); |
| 280 void initWinding(int start, int end, int winding, int oppWinding); |
| 281 void initWinding(int start, int end, double tHit, int winding, SkScalar hitD
x, int oppWind, |
| 282 SkScalar hitOppDx); |
| 283 bool isLinear(int start, int end) const; |
| 284 bool isMissing(double startT) const; |
| 285 bool isSimple(int end) const; |
| 286 SkOpSpan* markAndChaseDone(const SkOpAngle* angle, int winding); |
| 287 SkOpSpan* markAndChaseDone(int index, int endIndex, int winding); |
| 288 SkOpSpan* markAndChaseDoneBinary(const SkOpAngle* angle, int winding, int op
pWinding); |
| 289 SkOpSpan* markAndChaseDoneBinary(int index, int endIndex); |
| 290 SkOpSpan* markAndChaseDoneUnary(int index, int endIndex); |
| 291 SkOpSpan* markAndChaseDoneUnary(const SkOpAngle* angle, int winding); |
| 292 SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, const int winding); |
| 293 SkOpSpan* markAndChaseWinding(int index, int endIndex, int winding, int oppW
inding); |
| 294 SkOpSpan* markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWi
nding); |
| 295 SkOpSpan* markAngle(int maxWinding, int sumWinding, bool activeAngle, const
SkOpAngle* angle); |
| 296 SkOpSpan* markAngle(int maxWinding, int sumWinding, int oppMaxWinding, int o
ppSumWinding, |
| 297 bool activeAngle, const SkOpAngle* angle); |
| 298 void markDone(int index, int winding); |
| 299 void markDoneBinary(int index, int winding, int oppWinding); |
| 300 void markDoneBinary(int index); |
| 301 void markDoneUnary(int index, int winding); |
| 302 void markDoneUnary(int index); |
| 303 void markOneDone(const char* funName, int tIndex, int winding); |
| 304 void markOneDoneBinary(const char* funName, int tIndex); |
| 305 void markOneDoneBinary(const char* funName, int tIndex, int winding, int opp
Winding); |
| 306 void markOneDoneUnary(const char* funName, int tIndex); |
| 307 void markOneDoneUnary(const char* funName, int tIndex, int winding); |
| 308 SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding); |
| 309 SkOpSpan* markOneWinding(const char* funName, int tIndex, int winding, int o
ppWinding); |
| 310 void markUnsortable(int start, int end); |
| 311 void markWinding(int index, int winding); |
| 312 void markWinding(int index, int winding, int oppWinding); |
| 313 void matchWindingValue(int tIndex, double t, bool borrowWind); |
| 314 |
| 315 bool monotonicInY(int tStart, int tEnd) const; |
| 316 bool moreHorizontal(int index, int endIndex, bool& unsortable) const; |
| 317 bool multipleSpans(int end) const; |
| 318 bool nextCandidate(int& start, int& end) const; |
| 319 SkOpSegment* nextChase(int& index, const int step, int& min, SkOpSpan*& last
); |
| 320 int nextExactSpan(int from, int step) const; |
| 321 int nextSpan(int from, int step) const; |
| 322 bool serpentine(int tStart, int tEnd) const; |
| 323 void setUpWindings(int index, int endIndex, int& sumMiWinding, int& sumSuWin
ding, |
| 324 int& maxWinding, int& sumWinding, int& oppMaxWinding, int& oppSumWin
ding); |
| 325 static bool SortAngles(SkTDArray<SkOpAngle>& angles, SkTDArray<SkOpAngle*>&
angleList); |
| 326 void subDivide(int start, int end, SkPoint edge[4]) const; |
| 327 void subDivideBounds(int start, int end, SkPathOpsBounds& bounds) const; |
| 328 bool tiny(const SkOpAngle* angle) const; |
| 329 static void TrackOutside(SkTDArray<double>& outsideTs, double end, double st
art); |
| 330 void undoneSpan(int& start, int& end); |
| 331 int updateOppWinding(int index, int endIndex) const; |
| 332 int updateOppWinding(const SkOpAngle* angle) const; |
| 333 int updateOppWindingReverse(const SkOpAngle* angle) const; |
| 334 int updateWinding(int index, int endIndex) const; |
| 335 int updateWinding(const SkOpAngle* angle) const; |
| 336 int updateWindingReverse(const SkOpAngle* angle) const; |
| 337 static bool UseInnerWinding(int outerWinding, int innerWinding); |
| 338 SkOpSpan* verifyOneWinding(const char* funName, int tIndex); |
| 339 SkOpSpan* verifyOneWindingU(const char* funName, int tIndex); |
| 340 int windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar& dx) const; |
| 341 int windSum(const SkOpAngle* angle) const; |
| 342 int windValue(const SkOpAngle* angle) const; |
| 343 int windValueAt(double t) const; |
| 344 void zeroCoincidentOpp(SkOpSpan* oTest, int index); |
| 345 void zeroCoincidentOther(SkOpSpan* test, const double tRatio, const double o
EndT, int oIndex); |
| 346 void zeroSpan(SkOpSpan* span); |
| 347 |
| 348 #if DEBUG_WINDING |
| 349 static char as_digit(int value) { |
| 350 return value < 0 ? '?' : value <= 9 ? '0' + value : '+'; |
| 351 } |
| 352 #endif |
| 353 |
| 354 #if DEBUG_DUMP |
| 355 int debugID() const { |
| 356 return fID; |
| 357 } |
| 358 #endif |
| 359 |
| 360 #if DEBUG_SWAP_TOP |
| 361 bool controlsContainedByEnds(int tStart, int tEnd) const; |
| 362 #endif |
| 363 #if DEBUG_CONCIDENT |
| 364 void debugAddTPair(double t, const SkOpSegment& other, double otherT) const
; |
| 365 #endif |
| 366 #if DEBUG_ACTIVE_SPANS |
| 367 void debugShowActiveSpans() const; |
| 368 #endif |
| 369 #if DEBUG_MARK_DONE || DEBUG_UNSORTABLE |
| 370 void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding)
; |
| 371 void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding,
int oppWinding); |
| 372 #endif |
| 373 #if DEBUG_SORT || DEBUG_SWAP_TOP |
| 374 void debugShowSort(const char* fun, const SkTDArray<SkOpAngle*>& angles, int
first, |
| 375 const int contourWinding, const int oppContourWinding) const; |
| 376 void debugShowSort(const char* fun, const SkTDArray<SkOpAngle*>& angles, int
first); |
| 377 #endif |
| 378 #if DEBUG_WINDING |
| 379 void debugShowSums() const; |
| 380 #endif |
| 381 #if DEBUG_CONCIDENT |
| 382 void debugShowTs() const; |
| 383 #endif |
| 384 #if DEBUG_SHOW_WINDING |
| 385 int debugShowWindingValues(int slotCount, int ofInterest) const; |
| 386 #endif |
| 387 #if DEBUG_DUMP |
| 388 void dump() const; |
| 389 #endif |
| 390 #if DEBUG_ACTIVE_SPANS |
| 391 void validateActiveSpans() const; |
| 392 #endif |
| 393 |
| 394 private: |
| 395 const SkPoint* fPts; |
| 396 SkPathOpsBounds fBounds; |
| 397 SkTDArray<SkOpSpan> fTs; // two or more (always includes t=0 t=1) |
| 398 // OPTIMIZATION: could pack donespans, verb, operand, xor into 1 int-sized v
alue |
| 399 int fDoneSpans; // quick check that segment is finished |
| 400 // OPTIMIZATION: force the following to be byte-sized |
| 401 SkPath::Verb fVerb; |
| 402 bool fOperand; |
| 403 bool fXor; // set if original contour had even-odd fill |
| 404 bool fOppXor; // set if opposite operand had even-odd fill |
| 405 #if DEBUG_DUMP |
| 406 int fID; |
| 407 #endif |
| 408 }; |
| 409 |
| 410 #endif |
OLD | NEW |