Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1037)

Side by Side Diff: src/pathops/SkPathOpsTSect.h

Issue 1002693002: pathops version two (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix arm 64 inspired coincident handling Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pathops/SkPathOpsTQuadSect.cpp ('k') | src/pathops/SkPathOpsTightBounds.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2014 Google Inc. 2 * Copyright 2014 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 7
8 #include "SkChunkAlloc.h" 8 #include "SkChunkAlloc.h"
9 #include "SkPathOpsBounds.h"
9 #include "SkPathOpsRect.h" 10 #include "SkPathOpsRect.h"
10 #include "SkPathOpsQuad.h" 11 #include "SkPathOpsQuad.h"
11 #include "SkIntersections.h" 12 #include "SkIntersections.h"
12 #include "SkTArray.h" 13 #include "SkTSort.h"
13 14
14 /* TCurve is either SkDQuadratic or SkDCubic */ 15 /* TCurve is either SkDQuadratic or SkDCubic */
15 template<typename TCurve> 16 template<typename TCurve>
16 class SkTCoincident { 17 class SkTCoincident {
17 public: 18 public:
19 SkTCoincident()
20 : fCoincident(false) {
21 }
22
23 void clear() {
24 fPerpT = -1;
25 fCoincident = false;
26 }
27
18 bool isCoincident() const { 28 bool isCoincident() const {
19 return fCoincident; 29 return fCoincident;
20 } 30 }
21 31
22 void init() { 32 void init() {
23 fCoincident = false; 33 fCoincident = false;
24 SkDEBUGCODE(fPerpPt.fX = fPerpPt.fY = SK_ScalarNaN); 34 SkDEBUGCODE(fPerpPt.fX = fPerpPt.fY = SK_ScalarNaN);
25 SkDEBUGCODE(fPerpT = SK_ScalarNaN); 35 SkDEBUGCODE(fPerpT = SK_ScalarNaN);
26 } 36 }
27 37
(...skipping 19 matching lines...) Expand all
47 double fPerpT; // perpendicular intersection on opposite curve 57 double fPerpT; // perpendicular intersection on opposite curve
48 bool fCoincident; 58 bool fCoincident;
49 }; 59 };
50 60
51 template<typename TCurve> class SkTSect; 61 template<typename TCurve> class SkTSect;
52 62
53 /* Curve is either TCurve or SkDCubic */ 63 /* Curve is either TCurve or SkDCubic */
54 template<typename TCurve> 64 template<typename TCurve>
55 class SkTSpan { 65 class SkTSpan {
56 public: 66 public:
57 void init(const TCurve& ); 67 void addBounded(SkTSpan* );
58 void initBounds(const TCurve& ); 68 double closestBoundedT(const SkDPoint& pt) const;
69 bool contains(double t) const;
59 70
60 double closestBoundedT(const SkDPoint& pt) const; 71 const SkTSect<TCurve>* debugOpp() const;
61 72 const SkTSpan* debugSpan(int ) const;
62 bool contains(double t) const { 73 const SkTSpan* debugT(double t) const;
63 return !! const_cast<SkTSpan*>(this)->innerFind(t); 74 #ifdef SK_DEBUG
64 } 75 bool debugIsBefore(const SkTSpan* span) const;
65 76 #endif
66 bool contains(const SkTSpan* span) const; 77 void dump() const;
78 void dumpBounds(int id) const;
67 79
68 double endT() const { 80 double endT() const {
69 return fEndT; 81 return fEndT;
70 } 82 }
71 83
72 SkTSpan* find(double t) { 84 SkTSpan* findOppSpan(const SkTSpan* opp) const;
73 SkTSpan* result = innerFind(t); 85
86 SkTSpan* findOppT(double t) const {
87 SkTSpan* result = oppT(t);
74 SkASSERT(result); 88 SkASSERT(result);
75 return result; 89 return result;
76 } 90 }
77 91
78 bool intersects(const SkTSpan* span, bool* check); 92 bool hasOppT(double t) const {
93 return SkToBool(oppT(t));
94 }
95
96 int hullsIntersect(SkTSpan* span, bool* start, bool* oppStart);
97 void init(const TCurve& );
98 void initBounds(const TCurve& );
99
100 bool isBounded() const {
101 return fBounded.count() > 0;
102 }
103
104 bool linearsIntersect(SkTSpan* span);
105 double linearT(const SkDPoint& ) const;
106
107 void markCoincident() {
108 fCoinStart.markCoincident();
109 fCoinEnd.markCoincident();
110 }
79 111
80 const SkTSpan* next() const { 112 const SkTSpan* next() const {
81 return fNext; 113 return fNext;
82 } 114 }
83 115
116 bool onlyEndPointsInCommon(const SkTSpan* opp, bool* start, bool* oppStart, bool* ptsInCommon);
117
84 const TCurve& part() const { 118 const TCurve& part() const {
85 return fPart; 119 return fPart;
86 } 120 }
87 121
122 bool removeAllBounded();
123 bool removeBounded(const SkTSpan* opp);
124
88 void reset() { 125 void reset() {
89 fBounded.reset(); 126 fBounded.reset();
90 } 127 }
91 128
129 void resetBounds(const TCurve& curve) {
130 fIsLinear = fIsLine = false;
131 initBounds(curve);
132 }
133
92 bool split(SkTSpan* work) { 134 bool split(SkTSpan* work) {
93 return splitAt(work, (work->fStartT + work->fEndT) * 0.5); 135 return splitAt(work, (work->fStartT + work->fEndT) * 0.5);
94 } 136 }
95 137
96 bool splitAt(SkTSpan* work, double t); 138 bool splitAt(SkTSpan* work, double t);
97 139
98 double startT() const { 140 double startT() const {
99 return fStartT; 141 return fStartT;
100 } 142 }
101 143
102 bool tightBoundsIntersects(const SkTSpan* span) const; 144 private:
103 145
104 // implementation is for testing only 146 // implementation is for testing only
105 void dump() const { 147 int debugID() const {
106 dump(NULL); 148 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1);
107 } 149 }
108 150
109 private: 151 void dumpID() const;
110 SkTSpan* innerFind(double t);
111 bool linearIntersects(const TCurve& ) const;
112 152
113 // implementation is for testing only 153 int hullCheck(const SkTSpan* opp, bool* start, bool* oppStart);
114 #if DEBUG_T_SECT 154 int linearIntersects(const TCurve& ) const;
115 int debugID(const SkTSect<TCurve>* ) const { return fDebugID; } 155 SkTSpan* oppT(double t) const;
116 #else
117 int debugID(const SkTSect<TCurve>* ) const;
118 #endif
119 void dump(const SkTSect<TCurve>* ) const;
120 void dumpID(const SkTSect<TCurve>* ) const;
121 156
122 #if DEBUG_T_SECT
123 void validate() const; 157 void validate() const;
124 #endif 158 void validateBounded() const;
159 void validatePerpT(double oppT) const;
160 void validatePerpPt(double t, const SkDPoint& ) const;
125 161
126 TCurve fPart; 162 TCurve fPart;
127 SkTCoincident<TCurve> fCoinStart; 163 SkTCoincident<TCurve> fCoinStart;
128 SkTCoincident<TCurve> fCoinEnd; 164 SkTCoincident<TCurve> fCoinEnd;
129 SkSTArray<4, SkTSpan*, true> fBounded; 165 SkSTArray<4, SkTSpan*, true> fBounded;
130 SkTSpan* fPrev; 166 SkTSpan* fPrev;
131 SkTSpan* fNext; 167 SkTSpan* fNext;
132 SkDRect fBounds; 168 SkDRect fBounds;
133 double fStartT; 169 double fStartT;
134 double fEndT; 170 double fEndT;
135 double fBoundsMax; 171 double fBoundsMax;
136 bool fCollapsed; 172 bool fCollapsed;
137 bool fHasPerp; 173 bool fHasPerp;
138 bool fIsLinear; 174 bool fIsLinear;
139 #if DEBUG_T_SECT 175 bool fIsLine;
140 int fDebugID; 176 bool fDeleted;
141 bool fDebugDeleted; 177 PATH_OPS_DEBUG_CODE(SkTSect<TCurve>* fDebugSect);
142 #endif 178 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
143 friend class SkTSect<TCurve>; 179 friend class SkTSect<TCurve>;
144 }; 180 };
145 181
146 template<typename TCurve> 182 template<typename TCurve>
147 class SkTSect { 183 class SkTSect {
148 public: 184 public:
149 SkTSect(const TCurve& c PATH_OPS_DEBUG_PARAMS(int id)); 185 SkTSect(const TCurve& c PATH_OPS_DEBUG_T_SECT_PARAMS(int id));
150 static void BinarySearch(SkTSect* sect1, SkTSect* sect2, SkIntersections* in tersections); 186 static void BinarySearch(SkTSect* sect1, SkTSect* sect2, SkIntersections* in tersections);
151 187
152 // for testing only 188 // for testing only
189 bool debugHasBounded(const SkTSpan<TCurve>* ) const;
190
191 const SkTSect* debugOpp() const {
192 return PATH_OPS_DEBUG_RELEASE(fOppSect, NULL);
193 }
194
195 const SkTSpan<TCurve>* debugSpan(int id) const;
196 const SkTSpan<TCurve>* debugT(double t) const;
153 void dump() const; 197 void dump() const;
154 void dumpBoth(const SkTSect& opp) const; 198 void dumpBoth(SkTSect* ) const;
155 void dumpBoth(const SkTSect* opp) const; 199 void dumpBounds(int id) const;
200 void dumpCoin() const;
201 void dumpCoinCurves() const;
156 void dumpCurves() const; 202 void dumpCurves() const;
157 203
158 private: 204 private:
159 enum { 205 enum {
160 kZeroS1Set = 1, 206 kZeroS1Set = 1,
161 kOneS1Set = 2, 207 kOneS1Set = 2,
162 kZeroS2Set = 4, 208 kZeroS2Set = 4,
163 kOneS2Set = 8 209 kOneS2Set = 8
164 }; 210 };
165 211
212 SkTSpan<TCurve>* addFollowing(SkTSpan<TCurve>* prior);
213 void addForPerp(SkTSpan<TCurve>* span, double t);
166 SkTSpan<TCurve>* addOne(); 214 SkTSpan<TCurve>* addOne();
167 bool binarySearchCoin(const SkTSect& , double tStart, double tStep, double* t, double* oppT); 215
216 SkTSpan<TCurve>* addSplitAt(SkTSpan<TCurve>* span, double t) {
217 SkTSpan<TCurve>* result = this->addOne();
218 result->splitAt(span, t);
219 result->initBounds(fCurve);
220 span->initBounds(fCurve);
221 return result;
222 }
223
224 bool binarySearchCoin(SkTSect* , double tStart, double tStep, double* t, dou ble* oppT);
168 SkTSpan<TCurve>* boundsMax() const; 225 SkTSpan<TCurve>* boundsMax() const;
169 void coincidentCheck(SkTSect* sect2); 226 void coincidentCheck(SkTSect* sect2);
227 bool coincidentHasT(double t);
228 void computePerpendiculars(SkTSect* sect2, SkTSpan<TCurve>* first, SkTSpan<T Curve>* last);
229 int countConsecutiveSpans(SkTSpan<TCurve>* first, SkTSpan<TCurve>** last) co nst;
230
231 int debugID() const {
232 return PATH_OPS_DEBUG_T_SECT_RELEASE(fID, -1);
233 }
234
235 void deleteEmptySpans();
236 void dumpCommon(const SkTSpan<TCurve>* ) const;
237 void dumpCommonCurves(const SkTSpan<TCurve>* ) const;
170 static int EndsEqual(const SkTSect* sect1, const SkTSect* sect2, SkIntersect ions* ); 238 static int EndsEqual(const SkTSect* sect1, const SkTSect* sect2, SkIntersect ions* );
171 bool intersects(SkTSpan<TCurve>* span, const SkTSect* opp, 239 SkTSpan<TCurve>* extractCoincident(SkTSect* sect2, SkTSpan<TCurve>* first,
172 const SkTSpan<TCurve>* oppSpan) const; 240 SkTSpan<TCurve>* last);
173 void onCurveCheck(SkTSect* sect2, SkTSpan<TCurve>* first, SkTSpan<TCurve>* l ast); 241 SkTSpan<TCurve>* findCoincidentRun(SkTSpan<TCurve>* first, SkTSpan<TCurve>** lastPtr,
242 const SkTSect* sect2);
243 int intersects(SkTSpan<TCurve>* span, const SkTSect* opp,
244 SkTSpan<TCurve>* oppSpan, int* oppResult) const;
245 int linesIntersect(const SkTSpan<TCurve>* span, const SkTSect* opp,
246 const SkTSpan<TCurve>* oppSpan, SkIntersections* ) const;
247 void markSpanGone(SkTSpan<TCurve>* span);
248 bool matchedDirection(double t, const SkTSect* sect2, double t2) const;
249 void matchedDirCheck(double t, const SkTSect* sect2, double t2,
250 bool* calcMatched, bool* oppMatched) const;
251 void mergeCoincidence(SkTSect* sect2);
252 SkTSpan<TCurve>* prev(SkTSpan<TCurve>* ) const;
253 void removeByPerpendicular(SkTSect* opp);
174 void recoverCollapsed(); 254 void recoverCollapsed();
255 void removeCoincident(SkTSpan<TCurve>* span, bool isBetween);
256 void removeAllBut(const SkTSpan<TCurve>* keep, SkTSpan<TCurve>* span, SkTSec t* opp);
175 void removeSpan(SkTSpan<TCurve>* span); 257 void removeSpan(SkTSpan<TCurve>* span);
176 void removeOne(const SkTSpan<TCurve>* test, SkTSpan<TCurve>* span); 258 void removeSpanRange(SkTSpan<TCurve>* first, SkTSpan<TCurve>* last);
177 void removeSpans(SkTSpan<TCurve>* span, SkTSect* opp); 259 void removeSpans(SkTSpan<TCurve>* span, SkTSect* opp);
178 void setPerp(const TCurve& opp, SkTSpan<TCurve>* first, SkTSpan<TCurve>* las t); 260 SkTSpan<TCurve>* spanAtT(double t, SkTSpan<TCurve>** priorSpan);
179 const SkTSpan<TCurve>* tail() const; 261 SkTSpan<TCurve>* tail();
180 void trim(SkTSpan<TCurve>* span, SkTSect* opp); 262 void trim(SkTSpan<TCurve>* span, SkTSect* opp);
263 void unlinkSpan(SkTSpan<TCurve>* span);
264 bool updateBounded(SkTSpan<TCurve>* first, SkTSpan<TCurve>* last, SkTSpan<TC urve>* oppFirst);
265 void validate() const;
266 void validateBounded() const;
181 267
182 #if DEBUG_T_SECT
183 int debugID() const { return fDebugID; }
184 void validate() const;
185 #else
186 int debugID() const { return 0; }
187 #endif
188 const TCurve& fCurve; 268 const TCurve& fCurve;
189 SkChunkAlloc fHeap; 269 SkChunkAlloc fHeap;
190 SkTSpan<TCurve>* fHead; 270 SkTSpan<TCurve>* fHead;
271 SkTSpan<TCurve>* fCoincident;
191 SkTSpan<TCurve>* fDeleted; 272 SkTSpan<TCurve>* fDeleted;
192 int fActiveCount; 273 int fActiveCount;
274 PATH_OPS_DEBUG_CODE(SkTSect* fOppSect);
275 PATH_OPS_DEBUG_T_SECT_CODE(int fID);
276 PATH_OPS_DEBUG_T_SECT_CODE(int fDebugCount);
193 #if DEBUG_T_SECT 277 #if DEBUG_T_SECT
194 int fDebugID;
195 int fDebugCount;
196 int fDebugAllocatedCount; 278 int fDebugAllocatedCount;
197 #endif 279 #endif
198 friend class SkTSpan<TCurve>; // only used by debug id 280 friend class SkTSpan<TCurve>; // only used by debug id
199 }; 281 };
200 282
201 #define COINCIDENT_SPAN_COUNT 9 283 #define COINCIDENT_SPAN_COUNT 9
202 284
203 template<typename TCurve> 285 template<typename TCurve>
204 void SkTCoincident<TCurve>::setPerp(const TCurve& c1, double t, 286 void SkTCoincident<TCurve>::setPerp(const TCurve& c1, double t,
205 const SkDPoint& cPt, const TCurve& c2) { 287 const SkDPoint& cPt, const TCurve& c2) {
206 SkDVector dxdy = c1.dxdyAtT(t); 288 SkDVector dxdy = c1.dxdyAtT(t);
207 SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }}; 289 SkDLine perp = {{ cPt, {cPt.fX + dxdy.fY, cPt.fY - dxdy.fX} }};
208 SkIntersections i; 290 SkIntersections i;
209 int used = i.intersectRay(c2, perp); 291 int used = i.intersectRay(c2, perp);
210 // only keep closest 292 // only keep closest
211 if (used == 0) { 293 if (used == 0 || used == 3) {
212 fPerpT = -1; 294 this->clear();
213 return; 295 return;
214 } 296 }
215 fPerpT = i[0][0]; 297 fPerpT = i[0][0];
216 fPerpPt = i.pt(0); 298 fPerpPt = i.pt(0);
217 SkASSERT(used <= 2); 299 SkASSERT(used <= 2);
218 if (used == 2) { 300 if (used == 2) {
219 double distSq = (fPerpPt - cPt).lengthSquared(); 301 double distSq = (fPerpPt - cPt).lengthSquared();
220 double dist2Sq = (i.pt(1) - cPt).lengthSquared(); 302 double dist2Sq = (i.pt(1) - cPt).lengthSquared();
221 if (dist2Sq < distSq) { 303 if (dist2Sq < distSq) {
222 fPerpT = i[0][1]; 304 fPerpT = i[0][1];
223 fPerpPt = i.pt(1); 305 fPerpPt = i.pt(1);
224 } 306 }
225 } 307 }
308 #if DEBUG_T_SECT
309 SkDebugf("%s cPt=(%1.9g,%1.9g) %s fPerpPt=(%1.9g,%1.9g)\n", __FUNCTION__, cP t.fX, cPt.fY,
310 cPt.approximatelyEqual(fPerpPt) ? "==" : "!=", fPerpPt.fX, fPerpPt.f Y);
311 #endif
226 fCoincident = cPt.approximatelyEqual(fPerpPt); 312 fCoincident = cPt.approximatelyEqual(fPerpPt);
227 #if DEBUG_T_SECT 313 #if DEBUG_T_SECT
228 if (fCoincident) { 314 if (fCoincident) {
229 SkDebugf(""); // allow setting breakpoint 315 SkDebugf(""); // allow setting breakpoint
230 } 316 }
231 #endif 317 #endif
232 } 318 }
233 319
234 template<typename TCurve> 320 template<typename TCurve>
235 void SkTSpan<TCurve>::init(const TCurve& c) { 321 void SkTSpan<TCurve>::addBounded(SkTSpan* span) {
236 fPrev = fNext = NULL; 322 if (this->findOppSpan(span)) {
237 fIsLinear = false; 323 return;
238 fStartT = 0; 324 }
239 fEndT = 1; 325 fBounded.push_back() = span;
240 initBounds(c);
241 } 326 }
242 327
243 template<typename TCurve> 328 template<typename TCurve>
244 void SkTSpan<TCurve>::initBounds(const TCurve& c) { 329 SkTSpan<TCurve>* SkTSect<TCurve>::addFollowing(SkTSpan<TCurve>* prior) {
245 fPart = c.subDivide(fStartT, fEndT); 330 SkTSpan<TCurve>* result = this->addOne();
246 fBounds.setBounds(fPart); 331 result->fStartT = prior ? prior->fEndT : 0;
247 fCoinStart.init(); 332 SkTSpan<TCurve>* next = prior ? prior->fNext : fHead;
248 fCoinEnd.init(); 333 result->fEndT = next ? next->fStartT : 1;
249 fBoundsMax = SkTMax(fBounds.width(), fBounds.height()); 334 result->fPrev = prior;
250 fCollapsed = fPart.collapsed(); 335 result->fNext = next;
251 fHasPerp = false; 336 if (prior) {
252 #if DEBUG_T_SECT 337 prior->fNext = result;
253 fDebugDeleted = false; 338 } else {
254 if (fCollapsed) { 339 fHead = result;
255 SkDebugf(""); // for convenient breakpoints
256 } 340 }
257 #endif 341 if (next) {
342 next->fPrev = result;
343 }
344 result->resetBounds(fCurve);
345 return result;
258 } 346 }
259 347
260 template<typename TCurve> 348 template<typename TCurve>
349 void SkTSect<TCurve>::addForPerp(SkTSpan<TCurve>* span, double t) {
350 if (!span->hasOppT(t)) {
351 SkTSpan<TCurve>* priorSpan;
352 SkTSpan<TCurve>* opp = this->spanAtT(t, &priorSpan);
353 if (!opp) {
354 opp = this->addFollowing(priorSpan);
355 #if DEBUG_PERP
356 SkDebugf("%s priorSpan=%d t=%1.9g opp=%d\n", __FUNCTION__, priorSpan ->debugID(), t,
357 opp->debugID());
358 #endif
359 }
360 #if DEBUG_PERP
361 opp->dump(); SkDebugf("\n");
362 SkDebugf("%s fBounded.push_back span=%d opp=%d\n", __FUNCTION__, priorSp an->debugID(),
363 opp->debugID());
364 #endif
365 opp->fBounded.push_back(span);
366 span->fBounded.push_back(opp);
367 }
368 this->validate();
369 span->validatePerpT(t);
370 }
371
372 template<typename TCurve>
261 double SkTSpan<TCurve>::closestBoundedT(const SkDPoint& pt) const { 373 double SkTSpan<TCurve>::closestBoundedT(const SkDPoint& pt) const {
262 int count = fBounded.count(); 374 int count = fBounded.count();
263 double result = -1; 375 double result = -1;
264 double closest = FLT_MAX; 376 double closest = FLT_MAX;
265 for (int index = 0; index < count; ++index) { 377 for (int index = 0; index < count; ++index) {
266 const SkTSpan* test = fBounded[index]; 378 const SkTSpan* test = fBounded[index];
267 double startDist = test->fPart[0].distanceSquared(pt); 379 double startDist = test->fPart[0].distanceSquared(pt);
268 if (closest > startDist) { 380 if (closest > startDist) {
269 closest = startDist; 381 closest = startDist;
270 result = test->fStartT; 382 result = test->fStartT;
271 } 383 }
272 double endDist = test->fPart[TCurve::kPointLast].distanceSquared(pt); 384 double endDist = test->fPart[TCurve::kPointLast].distanceSquared(pt);
273 if (closest > endDist) { 385 if (closest > endDist) {
274 closest = endDist; 386 closest = endDist;
275 result = test->fEndT; 387 result = test->fEndT;
276 } 388 }
277 } 389 }
278 SkASSERT(between(0, result, 1)); 390 SkASSERT(between(0, result, 1));
279 return result; 391 return result;
280 } 392 }
281 393
394 #ifdef SK_DEBUG
282 template<typename TCurve> 395 template<typename TCurve>
283 bool SkTSpan<TCurve>::contains(const SkTSpan* span) const { 396 bool SkTSpan<TCurve>::debugIsBefore(const SkTSpan* span) const {
284 int count = fBounded.count(); 397 const SkTSpan* work = this;
285 for (int index = 0; index < count; ++index) { 398 do {
286 const SkTSpan* test = fBounded[index]; 399 if (span == work) {
287 if (span == test) {
288 return true; 400 return true;
289 } 401 }
290 } 402 } while ((work = work->fNext));
403 return false;
404 }
405 #endif
406
407 template<typename TCurve>
408 bool SkTSpan<TCurve>::contains(double t) const {
409 const SkTSpan* work = this;
410 do {
411 if (between(work->fStartT, t, work->fEndT)) {
412 return true;
413 }
414 } while ((work = work->fNext));
291 return false; 415 return false;
292 } 416 }
293 417
294 template<typename TCurve> 418 template<typename TCurve>
295 SkTSpan<TCurve>* SkTSpan<TCurve>::innerFind(double t) { 419 const SkTSect<TCurve>* SkTSpan<TCurve>::debugOpp() const {
296 SkTSpan* work = this; 420 return PATH_OPS_DEBUG_RELEASE(fDebugSect->debugOpp(), NULL);
297 do { 421 }
298 if (between(work->fStartT, t, work->fEndT)) { 422
299 return work; 423 template<typename TCurve>
424 SkTSpan<TCurve>* SkTSpan<TCurve>::findOppSpan(const SkTSpan* opp) const {
425 int count = fBounded.count();
426 for (int index = 0; index < count; ++index) {
427 SkTSpan* test = fBounded[index];
428 if (opp == test) {
429 return test;
300 } 430 }
301 } while ((work = work->fNext)); 431 }
302 return NULL; 432 return NULL;
303 } 433 }
304 434
435 // returns 0 if no hull intersection
436 // 1 if hulls intersect
437 // 2 if hulls only share a common endpoint
438 // -1 if linear and further checking is required
439 template<typename TCurve>
440 int SkTSpan<TCurve>::hullCheck(const SkTSpan* opp, bool* start, bool* oppStart) {
441 if (fIsLinear) {
442 return -1;
443 }
444 bool ptsInCommon;
445 if (onlyEndPointsInCommon(opp, start, oppStart, &ptsInCommon)) {
446 SkASSERT(ptsInCommon);
447 return 2;
448 }
449 bool linear;
450 if (fPart.hullIntersects(opp->fPart, &linear)) {
451 if (!linear) { // check set true if linear
452 return 1;
453 }
454 fIsLinear = true;
455 fIsLine = fPart.controlsInside();
456 return ptsInCommon ? 2 : -1;
457 } else { // hull is not linear; check set true if intersected at the end po ints
458 return ((int) ptsInCommon) << 1; // 0 or 2
459 }
460 return 0;
461 }
462
305 // OPTIMIZE ? If at_most_end_pts_in_common detects that one quad is near linear, 463 // OPTIMIZE ? If at_most_end_pts_in_common detects that one quad is near linear,
306 // use line intersection to guess a better split than 0.5 464 // use line intersection to guess a better split than 0.5
307 // OPTIMIZE Once at_most_end_pts_in_common detects linear, mark span so all futu re splits are linear 465 // OPTIMIZE Once at_most_end_pts_in_common detects linear, mark span so all futu re splits are linear
308 template<typename TCurve> 466 template<typename TCurve>
309 bool SkTSpan<TCurve>::intersects(const SkTSpan* span, bool* check) { 467 int SkTSpan<TCurve>::hullsIntersect(SkTSpan* opp, bool* start, bool* oppStart) {
310 if (!fBounds.intersects(span->fBounds)) { 468 if (!fBounds.intersects(opp->fBounds)) {
311 *check = false; // no need to check to see if the bounds have end point s in common 469 return 0;
312 return false;
313 } 470 }
314 if (!fIsLinear && fPart.hullIntersects(span->fPart, check)) { 471 int hullSect = this->hullCheck(opp, start, oppStart);
315 if (!*check) { 472 if (hullSect >= 0) {
316 return true; 473 return hullSect;
317 }
318 fIsLinear = true;
319 } 474 }
320 if (fIsLinear) { 475 hullSect = opp->hullCheck(this, oppStart, start);
321 *check = false; 476 if (hullSect >= 0) {
322 return linearIntersects(span->fPart); 477 return hullSect;
323 } 478 }
324 return *check; 479 return -1;
325 } 480 }
326 481
327 template<typename TCurve> 482 template<typename TCurve>
328 bool SkTSpan<TCurve>::linearIntersects(const TCurve& q2) const { 483 void SkTSpan<TCurve>::init(const TCurve& c) {
484 fPrev = fNext = NULL;
485 fStartT = 0;
486 fEndT = 1;
487 resetBounds(c);
488 }
489
490 template<typename TCurve>
491 void SkTSpan<TCurve>::initBounds(const TCurve& c) {
492 fPart = c.subDivide(fStartT, fEndT);
493 fBounds.setBounds(fPart);
494 fCoinStart.init();
495 fCoinEnd.init();
496 fBoundsMax = SkTMax(fBounds.width(), fBounds.height());
497 fCollapsed = fPart.collapsed();
498 fHasPerp = false;
499 fDeleted = false;
500 #if DEBUG_T_SECT
501 if (fCollapsed) {
502 SkDebugf(""); // for convenient breakpoints
503 }
504 #endif
505 }
506
507 template<typename TCurve>
508 bool SkTSpan<TCurve>::linearsIntersect(SkTSpan* span) {
509 int result = this->linearIntersects(span->fPart);
510 if (result <= 1) {
511 return SkToBool(result);
512 }
513 SkASSERT(span->fIsLinear);
514 result = span->linearIntersects(this->fPart);
515 // SkASSERT(result <= 1);
516 return SkToBool(result);
517 }
518
519 template<typename TCurve>
520 double SkTSpan<TCurve>::linearT(const SkDPoint& pt) const {
521 SkDVector len = fPart[TCurve::kPointLast] - fPart[0];
522 return fabs(len.fX) > fabs(len.fY)
523 ? (pt.fX - fPart[0].fX) / len.fX
524 : (pt.fY - fPart[0].fY) / len.fY;
525 }
526
527 template<typename TCurve>
528 int SkTSpan<TCurve>::linearIntersects(const TCurve& q2) const {
329 // looks like q1 is near-linear 529 // looks like q1 is near-linear
330 int start = 0, end = TCurve::kPointCount - 1; // the outside points are usu ally the extremes 530 int start = 0, end = TCurve::kPointLast; // the outside points are usually the extremes
331 if (!fPart.controlsInside()) { 531 if (!fPart.controlsInside()) {
332 double dist = 0; // if there's any question, compute distance to find b est outsiders 532 double dist = 0; // if there's any question, compute distance to find b est outsiders
333 for (int outer = 0; outer < TCurve::kPointCount - 1; ++outer) { 533 for (int outer = 0; outer < TCurve::kPointCount - 1; ++outer) {
334 for (int inner = outer + 1; inner < TCurve::kPointCount; ++inner) { 534 for (int inner = outer + 1; inner < TCurve::kPointCount; ++inner) {
335 double test = (fPart[outer] - fPart[inner]).lengthSquared(); 535 double test = (fPart[outer] - fPart[inner]).lengthSquared();
336 if (dist > test) { 536 if (dist > test) {
337 continue; 537 continue;
338 } 538 }
339 dist = test; 539 dist = test;
340 start = outer; 540 start = outer;
341 end = inner; 541 end = inner;
342 } 542 }
343 } 543 }
344 } 544 }
345 // see if q2 is on one side of the line formed by the extreme points 545 // see if q2 is on one side of the line formed by the extreme points
346 double origX = fPart[start].fX; 546 double origX = fPart[start].fX;
347 double origY = fPart[start].fY; 547 double origY = fPart[start].fY;
348 double adj = fPart[end].fX - origX; 548 double adj = fPart[end].fX - origX;
349 double opp = fPart[end].fY - origY; 549 double opp = fPart[end].fY - origY;
350 double sign; 550 double maxPart = SkTMax(fabs(adj), fabs(opp));
551 double sign = 0; // initialization to shut up warning in release build
351 for (int n = 0; n < TCurve::kPointCount; ++n) { 552 for (int n = 0; n < TCurve::kPointCount; ++n) {
553 double dx = q2[n].fY - origY;
554 double dy = q2[n].fX - origX;
555 double maxVal = SkTMax(maxPart, SkTMax(fabs(dx), fabs(dy)));
352 double test = (q2[n].fY - origY) * adj - (q2[n].fX - origX) * opp; 556 double test = (q2[n].fY - origY) * adj - (q2[n].fX - origX) * opp;
353 if (precisely_zero(test)) { 557 if (precisely_zero_when_compared_to(test, maxVal)) {
354 return true; 558 return 1;
559 }
560 if (approximately_zero_when_compared_to(test, maxVal)) {
561 return 3;
355 } 562 }
356 if (n == 0) { 563 if (n == 0) {
357 sign = test; 564 sign = test;
358 continue; 565 continue;
359 } 566 }
360 if (test * sign < 0) { 567 if (test * sign < 0) {
361 return true; 568 return 1;
362 } 569 }
363 } 570 }
571 return 0;
572 }
573
574 template<typename TCurve>
575 bool SkTSpan<TCurve>::onlyEndPointsInCommon(const SkTSpan* opp, bool* start, boo l* oppStart,
576 bool* ptsInCommon) {
577 if (opp->fPart[0] == fPart[0]) {
578 *start = *oppStart = true;
579 } else if (opp->fPart[0] == fPart[TCurve::kPointLast]) {
580 *start = false;
581 *oppStart = true;
582 } else if (opp->fPart[TCurve::kPointLast] == fPart[0]) {
583 *start = true;
584 *oppStart = false;
585 } else if (opp->fPart[TCurve::kPointLast] == fPart[TCurve::kPointLast]) {
586 *start = *oppStart = false;
587 } else {
588 *ptsInCommon = false;
589 return false;
590 }
591 *ptsInCommon = true;
592 const SkDPoint* o1Pts[TCurve::kPointCount - 1], * o2Pts[TCurve::kPointCount - 1];
593 int baseIndex = *start ? 0 : TCurve::kPointLast;
594 fPart.otherPts(baseIndex, o1Pts);
595 opp->fPart.otherPts(*oppStart ? 0 : TCurve::kPointLast, o2Pts);
596 const SkDPoint& base = fPart[baseIndex];
597 for (int o1 = 0; o1 < (int) SK_ARRAY_COUNT(o1Pts); ++o1) {
598 SkDVector v1 = *o1Pts[o1] - base;
599 for (int o2 = 0; o2 < (int) SK_ARRAY_COUNT(o2Pts); ++o2) {
600 SkDVector v2 = *o2Pts[o2] - base;
601 if (v2.dot(v1) >= 0) {
602 return false;
603 }
604 }
605 }
606 return true;
607 }
608
609 template<typename TCurve>
610 SkTSpan<TCurve>* SkTSpan<TCurve>::oppT(double t) const {
611 int count = fBounded.count();
612 for (int index = 0; index < count; ++index) {
613 SkTSpan* test = fBounded[index];
614 if (between(test->fStartT, t, test->fEndT)) {
615 return test;
616 }
617 }
618 return NULL;
619 }
620
621 template<typename TCurve>
622 bool SkTSpan<TCurve>::removeAllBounded() {
623 bool deleteSpan = false;
624 int count = fBounded.count();
625 for (int index = 0; index < count; ++index) {
626 SkTSpan* opp = fBounded[index];
627 deleteSpan |= opp->removeBounded(this);
628 }
629 return deleteSpan;
630 }
631
632 template<typename TCurve>
633 bool SkTSpan<TCurve>::removeBounded(const SkTSpan* opp) {
634 int count = fBounded.count();
635 if (fHasPerp) {
636 bool foundStart = false;
637 bool foundEnd = false;
638 for (int index = 0; index < count; ++index) {
639 const SkTSpan* test = fBounded[index];
640 if (opp == test) {
641 continue;
642 }
643 foundStart |= between(test->fStartT, fCoinStart.perpT(), test->fEndT );
644 foundEnd |= between(test->fStartT, fCoinEnd.perpT(), test->fEndT);
645 }
646 if (!foundStart || !foundEnd) {
647 fHasPerp = false;
648 fCoinStart.init();
649 fCoinEnd.init();
650 }
651 }
652 for (int index = 0; index < count; ++index) {
653 if (opp == fBounded[index]) {
654 fBounded.removeShuffle(index);
655 SkASSERT((count == 1) == (fBounded.count() == 0));
656 return count == 1;
657 }
658 }
659 SkASSERT(0);
364 return false; 660 return false;
365 } 661 }
366 662
367 template<typename TCurve> 663 template<typename TCurve>
368 bool SkTSpan<TCurve>::splitAt(SkTSpan* work, double t) { 664 bool SkTSpan<TCurve>::splitAt(SkTSpan* work, double t) {
369 fStartT = t; 665 fStartT = t;
370 fEndT = work->fEndT; 666 fEndT = work->fEndT;
371 if (fStartT == fEndT) { 667 if (fStartT == fEndT) {
372 fCollapsed = true; 668 fCollapsed = true;
373 return false; 669 return false;
374 } 670 }
375 work->fEndT = t; 671 work->fEndT = t;
376 if (work->fStartT == work->fEndT) { 672 if (work->fStartT == work->fEndT) {
377 work->fCollapsed = true; 673 work->fCollapsed = true;
378 return false; 674 return false;
379 } 675 }
380 fPrev = work; 676 fPrev = work;
381 fNext = work->fNext; 677 fNext = work->fNext;
382 fIsLinear = work->fIsLinear; 678 fIsLinear = work->fIsLinear;
679 fIsLine = work->fIsLine;
680
383 work->fNext = this; 681 work->fNext = this;
384 if (fNext) { 682 if (fNext) {
385 fNext->fPrev = this; 683 fNext->fPrev = this;
386 } 684 }
387 fBounded = work->fBounded; 685 fBounded = work->fBounded;
388 int count = fBounded.count(); 686 int count = fBounded.count();
389 for (int index = 0; index < count; ++index) { 687 for (int index = 0; index < count; ++index) {
390 fBounded[index]->fBounded.push_back() = this; 688 fBounded[index]->fBounded.push_back() = this;
391 } 689 }
392 return true; 690 return true;
393 } 691 }
394 692
395 template<typename TCurve> 693 template<typename TCurve>
396 bool SkTSpan<TCurve>::tightBoundsIntersects(const SkTSpan* span) const { 694 void SkTSpan<TCurve>::validate() const {
397 // skew all to an axis
398 SkDVector v2_0 = fPart[TCurve::kPointLast] - fPart[0];
399 bool skewToXAxis = fabs(v2_0.fX) > fabs(v2_0.fY);
400 double ratio = skewToXAxis ? v2_0.fY / v2_0.fX : v2_0.fX / v2_0.fY;
401 TCurve r1 = fPart;
402 if (skewToXAxis) {
403 r1[1].fY -= (fPart[1].fX - r1[0].fX) * ratio;
404 if (TCurve::IsCubic()) {
405 r1[2].fY -= (fPart[2].fX - r1[0].fX) * ratio;
406 r1[3].fY = r1[0].fY;
407 } else {
408 r1[2].fY = r1[0].fY;
409 }
410 } else {
411 r1[1].fX -= (fPart[1].fY - r1[0].fY) * ratio;
412 if (TCurve::IsCubic()) {
413 r1[2].fX -= (fPart[2].fY - r1[0].fY) * ratio;
414 r1[3].fX = r1[0].fX;
415 } else {
416 r1[2].fX = r1[0].fX;
417 }
418 }
419 // compute the tight skewed bounds
420 SkDRect bounds;
421 bounds.setBounds(r1);
422 // see if opposite ends are within range of tight skewed bounds
423 TCurve r2 = span->fPart;
424 for (int i = 0; i < TCurve::kPointCount; i += 2) {
425 if (skewToXAxis) {
426 r2[i].fY -= (r2[i].fX - r1[0].fX) * ratio;
427 if (between(bounds.fTop, r2[i].fY, bounds.fBottom)) {
428 return true;
429 }
430 } else {
431 r2[i].fX -= (r2[i].fY - r1[0].fY) * ratio;
432 if (between(bounds.fLeft, r2[i].fX, bounds.fRight)) {
433 return true;
434 }
435 }
436 }
437 // see if opposite ends are on either side of tight skewed bounds
438 if ((skewToXAxis ? (r2[0].fY - r1[0].fY) * (r2[TCurve::kPointLast].fY - r1[0 ].fY)
439 : (r2[0].fX - r1[0].fX) * (r2[TCurve::kPointLast].fX - r 1[0].fX)) < 0) {
440 return true;
441 }
442 // compute opposite tight skewed bounds
443 if (skewToXAxis) {
444 r2[1].fY -= (r2[1].fX - r1[0].fX) * ratio;
445 if (TCurve::IsCubic()) {
446 r2[2].fY -= (r2[2].fX - r1[0].fX) * ratio;
447 }
448 } else {
449 r2[1].fX -= (r2[1].fY - r1[0].fY) * ratio;
450 if (TCurve::IsCubic()) {
451 r2[2].fX -= (r2[2].fY - r1[0].fY) * ratio;
452 }
453 }
454 SkDRect sBounds;
455 sBounds.setBounds(r2);
456 // see if tight bounds overlap
457 if (skewToXAxis) {
458 return bounds.fTop <= sBounds.fBottom && sBounds.fTop <= bounds.fBottom;
459 } else {
460 return bounds.fLeft <= sBounds.fRight && sBounds.fLeft <= bounds.fRight;
461 }
462 }
463
464 #if DEBUG_T_SECT 695 #if DEBUG_T_SECT
465 template<typename TCurve>
466 void SkTSpan<TCurve>::validate() const {
467 SkASSERT(fNext == NULL || fNext != fPrev); 696 SkASSERT(fNext == NULL || fNext != fPrev);
468 SkASSERT(fNext == NULL || this == fNext->fPrev); 697 SkASSERT(fNext == NULL || this == fNext->fPrev);
469 SkASSERT(fBounds.width() || fBounds.height()); 698 SkASSERT(fPrev == NULL || this == fPrev->fNext);
699 SkASSERT(fBounds.width() || fBounds.height() || fCollapsed);
470 SkASSERT(fBoundsMax == SkTMax(fBounds.width(), fBounds.height())); 700 SkASSERT(fBoundsMax == SkTMax(fBounds.width(), fBounds.height()));
471 SkASSERT(0 <= fStartT); 701 SkASSERT(0 <= fStartT);
472 SkASSERT(fEndT <= 1); 702 SkASSERT(fEndT <= 1);
473 SkASSERT(fStartT < fEndT); 703 SkASSERT(fStartT <= fEndT);
474 SkASSERT(fBounded.count() > 0); 704 SkASSERT(fBounded.count() > 0);
705 this->validateBounded();
706 if (fHasPerp) {
707 if (fCoinStart.isCoincident()) {
708 validatePerpT(fCoinStart.perpT());
709 validatePerpPt(fCoinStart.perpT(), fCoinStart.perpPt());
710 }
711 if (fCoinEnd.isCoincident()) {
712 validatePerpT(fCoinEnd.perpT());
713 validatePerpPt(fCoinEnd.perpT(), fCoinEnd.perpPt());
714 }
715 }
716 #endif
717 }
718
719 template<typename TCurve>
720 void SkTSpan<TCurve>::validateBounded() const {
721 #if DEBUG_VALIDATE
475 for (int index = 0; index < fBounded.count(); ++index) { 722 for (int index = 0; index < fBounded.count(); ++index) {
476 const SkTSpan* overlap = fBounded[index]; 723 const SkTSpan* overlap = fBounded[index];
477 SkASSERT(((fDebugID ^ overlap->fDebugID) & 1) == 1); 724 SkASSERT(!overlap->fDeleted);
478 SkASSERT(overlap->contains(this)); 725 SkASSERT(((this->debugID() ^ overlap->debugID()) & 1) == 1);
726 SkASSERT(overlap->findOppSpan(this));
479 } 727 }
728 #endif
480 } 729 }
481 #endif
482 730
483 template<typename TCurve> 731 template<typename TCurve>
484 SkTSect<TCurve>::SkTSect(const TCurve& c PATH_OPS_DEBUG_PARAMS(int id)) 732 void SkTSpan<TCurve>::validatePerpT(double oppT) const {
733 #if DEBUG_VALIDATE
734 for (int index = 0; index < fBounded.count(); ++index) {
735 const SkTSpan* overlap = fBounded[index];
736 if (between(overlap->fStartT, oppT, overlap->fEndT)) {
737 return;
738 }
739 }
740 SkASSERT(0);
741 #endif
742 }
743
744 template<typename TCurve>
745 void SkTSpan<TCurve>::validatePerpPt(double t, const SkDPoint& pt) const {
746 #if DEBUG_T_SECT
747 PATH_OPS_DEBUG_CODE(SkASSERT(fDebugSect->fOppSect->fCurve.ptAtT(t) == pt));
748 #endif
749 }
750
751
752 template<typename TCurve>
753 SkTSect<TCurve>::SkTSect(const TCurve& c PATH_OPS_DEBUG_T_SECT_PARAMS(int id))
485 : fCurve(c) 754 : fCurve(c)
486 , fHeap(sizeof(SkTSpan<TCurve>) * 4) 755 , fHeap(sizeof(SkTSpan<TCurve>) * 4)
756 , fCoincident(NULL)
487 , fDeleted(NULL) 757 , fDeleted(NULL)
488 , fActiveCount(0) 758 , fActiveCount(0)
489 PATH_OPS_DEBUG_PARAMS(fDebugID(id)) 759 PATH_OPS_DEBUG_T_SECT_PARAMS(fID(id))
490 PATH_OPS_DEBUG_PARAMS(fDebugCount(0)) 760 PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugCount(0))
491 PATH_OPS_DEBUG_PARAMS(fDebugAllocatedCount(0)) 761 PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugAllocatedCount(0))
492 { 762 {
493 fHead = addOne(); 763 fHead = addOne();
494 fHead->init(c); 764 fHead->init(c);
495 } 765 }
496 766
497 template<typename TCurve> 767 template<typename TCurve>
498 SkTSpan<TCurve>* SkTSect<TCurve>::addOne() { 768 SkTSpan<TCurve>* SkTSect<TCurve>::addOne() {
499 SkTSpan<TCurve>* result; 769 SkTSpan<TCurve>* result;
500 if (fDeleted) { 770 if (fDeleted) {
501 result = fDeleted; 771 result = fDeleted;
502 result->reset(); 772 result->reset();
503 fDeleted = result->fNext; 773 fDeleted = result->fNext;
504 } else { 774 } else {
505 result = SkNEW_PLACEMENT(fHeap.allocThrow(sizeof(SkTSpan<TCurve>)), SkTS pan<TCurve>); 775 result = SkNEW_PLACEMENT(fHeap.allocThrow(sizeof(SkTSpan<TCurve>)), SkTS pan<TCurve>);
506 #if DEBUG_T_SECT 776 #if DEBUG_T_SECT
507 ++fDebugAllocatedCount; 777 ++fDebugAllocatedCount;
508 #endif 778 #endif
509 } 779 }
510 ++fActiveCount; 780 ++fActiveCount;
511 #if DEBUG_T_SECT 781 PATH_OPS_DEBUG_T_SECT_CODE(result->fID = fDebugCount++ * 2 + fID);
512 result->fDebugID = fDebugCount++ * 2 + fDebugID; 782 PATH_OPS_DEBUG_CODE(result->fDebugSect = this);
513 #endif
514 return result; 783 return result;
515 } 784 }
516 785
517 template<typename TCurve> 786 template<typename TCurve>
518 bool SkTSect<TCurve>::binarySearchCoin(const SkTSect& sect2, double tStart, doub le tStep, 787 bool SkTSect<TCurve>::binarySearchCoin(SkTSect* sect2, double tStart, double tSt ep,
519 double* resultT, double* oppT) { 788 double* resultT, double* oppT) {
520 SkTSpan<TCurve> work; 789 SkTSpan<TCurve> work;
521 double result = work.fStartT = work.fEndT = tStart; 790 double result = work.fStartT = work.fEndT = tStart;
791 PATH_OPS_DEBUG_CODE(work.fDebugSect = this);
522 SkDPoint last = fCurve.ptAtT(tStart); 792 SkDPoint last = fCurve.ptAtT(tStart);
523 SkDPoint oppPt; 793 SkDPoint oppPt;
524 bool flip = false; 794 bool flip = false;
525 SkDEBUGCODE(bool down = tStep < 0); 795 SkDEBUGCODE(bool down = tStep < 0);
526 const TCurve& opp = sect2.fCurve; 796 const TCurve& opp = sect2->fCurve;
527 do { 797 do {
528 tStep *= 0.5; 798 tStep *= 0.5;
529 work.fStartT += tStep; 799 work.fStartT += tStep;
530 if (flip) { 800 if (flip) {
531 tStep = -tStep; 801 tStep = -tStep;
532 flip = false; 802 flip = false;
533 } 803 }
534 work.initBounds(fCurve); 804 work.initBounds(fCurve);
535 if (work.fCollapsed) { 805 if (work.fCollapsed) {
536 return false; 806 return false;
537 } 807 }
538 if (last.approximatelyEqual(work.fPart[0])) { 808 if (last.approximatelyEqual(work.fPart[0])) {
539 break; 809 break;
540 } 810 }
541 last = work.fPart[0]; 811 last = work.fPart[0];
542 work.fCoinStart.setPerp(fCurve, work.fStartT, last, opp); 812 work.fCoinStart.setPerp(fCurve, work.fStartT, last, opp);
543 if (work.fCoinStart.isCoincident()) { 813 if (work.fCoinStart.isCoincident()) {
814 #if DEBUG_T_SECT
815 work.validatePerpPt(work.fCoinStart.perpT(), work.fCoinStart.perpPt( ));
816 #endif
544 double oppTTest = work.fCoinStart.perpT(); 817 double oppTTest = work.fCoinStart.perpT();
545 if (sect2.fHead->contains(oppTTest)) { 818 if (sect2->fHead->contains(oppTTest)) {
546 *oppT = oppTTest; 819 *oppT = oppTTest;
547 oppPt = work.fCoinStart.perpPt(); 820 oppPt = work.fCoinStart.perpPt();
548 SkASSERT(down ? result > work.fStartT : result < work.fStartT); 821 SkASSERT(down ? result > work.fStartT : result < work.fStartT);
549 result = work.fStartT; 822 result = work.fStartT;
550 continue; 823 continue;
551 } 824 }
552 } 825 }
553 tStep = -tStep; 826 tStep = -tStep;
554 flip = true; 827 flip = true;
555 } while (true); 828 } while (true);
(...skipping 11 matching lines...) Expand all
567 return true; 840 return true;
568 } 841 }
569 842
570 // OPTIMIZE ? keep a sorted list of sizes in the form of a doubly-linked list in quad span 843 // OPTIMIZE ? keep a sorted list of sizes in the form of a doubly-linked list in quad span
571 // so that each quad sect has a pointer to the largest, and can updat e it as spans 844 // so that each quad sect has a pointer to the largest, and can updat e it as spans
572 // are split 845 // are split
573 template<typename TCurve> 846 template<typename TCurve>
574 SkTSpan<TCurve>* SkTSect<TCurve>::boundsMax() const { 847 SkTSpan<TCurve>* SkTSect<TCurve>::boundsMax() const {
575 SkTSpan<TCurve>* test = fHead; 848 SkTSpan<TCurve>* test = fHead;
576 SkTSpan<TCurve>* largest = fHead; 849 SkTSpan<TCurve>* largest = fHead;
577 bool largestCoin = largest->fCoinStart.isCoincident() && largest->fCoinEnd.i sCoincident(); 850 bool lCollapsed = largest->fCollapsed;
578 while ((test = test->fNext)) { 851 while ((test = test->fNext)) {
579 bool testCoin = test->fCoinStart.isCoincident() || test->fCoinEnd.isCoin cident(); 852 bool tCollapsed = test->fCollapsed;
580 if ((largestCoin && !testCoin) || (largestCoin == testCoin 853 if ((lCollapsed && !tCollapsed) || (lCollapsed == tCollapsed &&
581 && (largest->fBoundsMax < test->fBoundsMax 854 largest->fBoundsMax < test->fBoundsMax)) {
582 || (largest->fCollapsed && !test->fCollapsed)))) {
583 largest = test; 855 largest = test;
584 largestCoin = testCoin; 856 }
585 } 857 }
586 } 858 return largest;
587 return largestCoin ? NULL : largest;
588 } 859 }
589 860
590 template<typename TCurve> 861 template<typename TCurve>
591 void SkTSect<TCurve>::coincidentCheck(SkTSect* sect2) { 862 void SkTSect<TCurve>::coincidentCheck(SkTSect* sect2) {
592 SkTSpan<TCurve>* first = fHead; 863 SkTSpan<TCurve>* first = fHead;
593 SkTSpan<TCurve>* next; 864 SkTSpan<TCurve>* last, * next;
594 do { 865 do {
595 int consecutive = 1; 866 int consecutive = this->countConsecutiveSpans(first, &last);
596 SkTSpan<TCurve>* last = first; 867 next = last->fNext;
597 do {
598 next = last->fNext;
599 if (!next) {
600 break;
601 }
602 if (next->fStartT > last->fEndT) {
603 break;
604 }
605 ++consecutive;
606 last = next;
607 } while (true);
608 if (consecutive < COINCIDENT_SPAN_COUNT) { 868 if (consecutive < COINCIDENT_SPAN_COUNT) {
609 continue; 869 continue;
610 } 870 }
611 setPerp(sect2->fCurve, first, last); 871 this->validate();
872 sect2->validate();
873 this->computePerpendiculars(sect2, first, last);
874 this->validate();
875 sect2->validate();
612 // check to see if a range of points are on the curve 876 // check to see if a range of points are on the curve
613 onCurveCheck(sect2, first, last); 877 SkTSpan<TCurve>* coinStart = first;
614 SkTSpan<TCurve>* removalCandidate = NULL; 878 do {
615 if (!first->fCoinStart.isCoincident()) { 879 coinStart = this->extractCoincident(sect2, coinStart, last);
616 SkTSpan<TCurve>* firstCoin = first->fNext; 880 } while (coinStart && !last->fDeleted);
617 removalCandidate = first;
618 first = firstCoin;
619 }
620 if (!first->fCoinStart.isCoincident()) {
621 continue;
622 }
623 if (removalCandidate) {
624 removeSpans(removalCandidate, sect2);
625 }
626 if (!last->fCoinStart.isCoincident()) {
627 continue;
628 }
629 if (!last->fCoinEnd.isCoincident()) {
630 if (--consecutive < COINCIDENT_SPAN_COUNT) {
631 continue;
632 }
633 last = last->fPrev;
634 SkASSERT(last->fCoinStart.isCoincident());
635 SkASSERT(last->fCoinEnd.isCoincident());
636 }
637 SkASSERT(between(0, first->fCoinStart.perpT(), 1) || first->fCoinStart.p erpT() == -1);
638 if (first->fCoinStart.perpT() < 0) {
639 first->fCoinStart.setPerp(fCurve, first->fStartT, first->fPart[0], s ect2->fCurve);
640 }
641 SkASSERT(between(0, last->fCoinEnd.perpT(), 1) || last->fCoinEnd.perpT() == -1);
642 if (last->fCoinEnd.perpT() < 0) {
643 last->fCoinEnd.setPerp(fCurve, last->fEndT, last->fPart[TCurve::kPoi ntLast],
644 sect2->fCurve);
645 }
646 SkTSpan<TCurve>* removeMe = first->fNext;
647 while (removeMe != last) {
648 SkTSpan<TCurve>* removeNext = removeMe->fNext;
649 removeSpans(removeMe, sect2);
650 removeMe = removeNext;
651 }
652 } while ((first = next)); 881 } while ((first = next));
653 } 882 }
654 883
655 template<typename TCurve> 884 template<typename TCurve>
656 bool SkTSect<TCurve>::intersects(SkTSpan<TCurve>* span, const SkTSect* opp, 885 bool SkTSect<TCurve>::coincidentHasT(double t) {
657 const SkTSpan<TCurve>* oppSpan) const { 886 SkTSpan<TCurve>* test = fCoincident;
658 bool check; // we ignore whether the end points are in common or not 887 while (test) {
659 if (!span->intersects(oppSpan, &check)) { 888 if (between(test->fStartT, t, test->fEndT)) {
660 return false; 889 return true;
661 } 890 }
662 if (fActiveCount < COINCIDENT_SPAN_COUNT || opp->fActiveCount < COINCIDENT_S PAN_COUNT) { 891 test = test->fNext;
663 return true; 892 }
664 } 893 return false;
665 return span->tightBoundsIntersects(oppSpan); 894 }
666 } 895
667 896 template<typename TCurve>
668 template<typename TCurve> 897 void SkTSect<TCurve>::computePerpendiculars(SkTSect* sect2, SkTSpan<TCurve>* fir st,
669 void SkTSect<TCurve>::onCurveCheck(SkTSect* sect2, SkTSpan<TCurve>* first, SkTSp an<TCurve>* last) { 898 SkTSpan<TCurve>* last) {
670 SkTSpan<TCurve>* work = first; 899 const TCurve& opp = sect2->fCurve;
671 first = NULL; 900 SkTSpan<TCurve>* work = first;
672 do { 901 SkTSpan<TCurve>* prior = NULL;
673 if (work->fCoinStart.isCoincident()) { 902 do {
674 if (!first) { 903 if (!work->fHasPerp && !work->fCollapsed) {
675 first = work; 904 if (prior) {
676 } 905 work->fCoinStart = prior->fCoinEnd;
677 } else if (first) { 906 } else {
678 break; 907 work->fCoinStart.setPerp(fCurve, work->fStartT, work->fPart[0], opp);
908 }
909 if (work->fCoinStart.isCoincident()) {
910 double perpT = work->fCoinStart.perpT();
911 if (sect2->coincidentHasT(perpT)) {
912 work->fCoinStart.clear();
913 } else {
914 sect2->addForPerp(work, perpT);
915 }
916 }
917 work->fCoinEnd.setPerp(fCurve, work->fEndT, work->fPart[TCurve::kPoi ntLast], opp);
918 if (work->fCoinEnd.isCoincident()) {
919 double perpT = work->fCoinEnd.perpT();
920 if (sect2->coincidentHasT(perpT)) {
921 work->fCoinEnd.clear();
922 } else {
923 sect2->addForPerp(work, perpT);
924 }
925 }
926 work->fHasPerp = true;
679 } 927 }
680 if (work == last) { 928 if (work == last) {
681 break; 929 break;
682 } 930 }
931 prior = work;
683 work = work->fNext; 932 work = work->fNext;
684 SkASSERT(work); 933 SkASSERT(work);
685 } while (true); 934 } while (true);
935 }
936
937 template<typename TCurve>
938 int SkTSect<TCurve>::countConsecutiveSpans(SkTSpan<TCurve>* first,
939 SkTSpan<TCurve>** lastPtr) const {
940 int consecutive = 1;
941 SkTSpan<TCurve>* last = first;
942 do {
943 SkTSpan<TCurve>* next = last->fNext;
944 if (!next) {
945 break;
946 }
947 if (next->fStartT > last->fEndT) {
948 break;
949 }
950 ++consecutive;
951 last = next;
952 } while (true);
953 *lastPtr = last;
954 return consecutive;
955 }
956
957 template<typename TCurve>
958 bool SkTSect<TCurve>::debugHasBounded(const SkTSpan<TCurve>* span) const {
959 const SkTSpan<TCurve>* test = fHead;
960 if (!test) {
961 return false;
962 }
963 do {
964 if (test->findOppSpan(span)) {
965 return true;
966 }
967 } while ((test = test->next()));
968 return false;
969 }
970
971 template<typename TCurve>
972 void SkTSect<TCurve>::deleteEmptySpans() {
973 SkTSpan<TCurve>* test;
974 SkTSpan<TCurve>* next = fHead;
975 while ((test = next)) {
976 next = test->fNext;
977 if (test->fBounded.count() == 0) {
978 this->removeSpan(test);
979 }
980 }
981 }
982
983 template<typename TCurve>
984 SkTSpan<TCurve>* SkTSect<TCurve>::extractCoincident(SkTSect* sect2, SkTSpan<TCur ve>* first,
985 SkTSpan<TCurve>* last) {
986 first = findCoincidentRun(first, &last, sect2);
686 if (!first) { 987 if (!first) {
687 return; 988 return NULL;
688 } 989 }
689 // march outwards to find limit of coincidence from here to previous and nex t spans 990 // march outwards to find limit of coincidence from here to previous and nex t spans
690 double startT = first->fStartT; 991 double startT = first->fStartT;
691 double oppT; 992 double oppStartT;
993 double oppEndT SK_INIT_TO_AVOID_WARNING;
692 SkTSpan<TCurve>* prev = first->fPrev; 994 SkTSpan<TCurve>* prev = first->fPrev;
693 if (prev) { 995 SkASSERT(first->fCoinStart.isCoincident());
694 double coinStart; 996 SkTSpan<TCurve>* oppFirst = first->findOppT(first->fCoinStart.perpT());
695 if (binarySearchCoin(*sect2, startT, prev->fStartT - startT, &coinStart, &oppT)) { 997 SkASSERT(last->fCoinEnd.isCoincident());
696 if (coinStart < startT) { 998 bool oppMatched = first->fCoinStart.perpT() < first->fCoinEnd.perpT();
697 SkASSERT(prev->fStartT < coinStart && coinStart < prev->fEndT); 999 double coinStart;
698 SkTSpan<TCurve>* oppStart = sect2->fHead->find(oppT); 1000 SkDEBUGCODE(double coinEnd);
699 if (oppStart->fStartT < oppT && oppT < oppStart->fEndT) { 1001 if (prev && prev->fEndT == startT
700 // split prev at coinStart if needed 1002 && this->binarySearchCoin(sect2, startT, prev->fStartT - startT, &co inStart,
701 SkTSpan<TCurve>* half2 = addOne(); 1003 &oppStartT)
702 half2->splitAt(prev, coinStart); 1004 && prev->fStartT < coinStart && coinStart < startT) {
703 half2->initBounds(fCurve); 1005 oppFirst = prev->findOppT(oppStartT); // find opp start before splittin g prev
704 prev->initBounds(fCurve); 1006 SkASSERT(oppFirst);
705 prev->fCoinEnd.markCoincident(); 1007 first = this->addSplitAt(prev, coinStart);
706 half2->fCoinStart.markCoincident(); 1008 first->markCoincident();
707 half2->fCoinEnd.markCoincident(); 1009 prev->fCoinEnd.markCoincident();
708 // find span containing opposite t, and split that too 1010 if (oppFirst->fStartT < oppStartT && oppStartT < oppFirst->fEndT) {
709 SkTSpan<TCurve>* oppHalf = sect2->addOne(); 1011 SkTSpan<TCurve>* oppHalf = sect2->addSplitAt(oppFirst, oppStartT);
710 oppHalf->splitAt(oppStart, oppT); 1012 if (oppMatched) {
711 oppHalf->initBounds(sect2->fCurve); 1013 oppFirst->fCoinEnd.markCoincident();
712 oppStart->initBounds(sect2->fCurve); 1014 oppHalf->markCoincident();
1015 oppFirst = oppHalf;
1016 } else {
1017 oppFirst->markCoincident();
1018 oppHalf->fCoinStart.markCoincident();
1019 }
1020 }
1021 } else {
1022 SkDEBUGCODE(coinStart = first->fStartT);
1023 SkDEBUGCODE(oppStartT = oppMatched ? oppFirst->fStartT : oppFirst->fEndT );
1024 }
1025 SkTSpan<TCurve>* oppLast;
1026 SkASSERT(last->fCoinEnd.isCoincident());
1027 oppLast = last->findOppT(last->fCoinEnd.perpT());
1028 SkDEBUGCODE(coinEnd = last->fEndT);
1029 SkDEBUGCODE(oppEndT = oppMatched ? oppLast->fEndT : oppLast->fStartT);
1030 if (!oppMatched) {
1031 SkTSwap(oppFirst, oppLast);
1032 SkTSwap(oppStartT, oppEndT);
1033 }
1034 SkASSERT(oppStartT < oppEndT);
1035 SkASSERT(coinStart == first->fStartT);
1036 SkASSERT(coinEnd == last->fEndT);
1037 SkASSERT(oppStartT == oppFirst->fStartT);
1038 SkASSERT(oppEndT == oppLast->fEndT);
1039 // reduce coincident runs to single entries
1040 this->validate();
1041 sect2->validate();
1042 bool deleteThisSpan = this->updateBounded(first, last, oppFirst);
1043 bool deleteSect2Span = sect2->updateBounded(oppFirst, oppLast, first);
1044 this->removeSpanRange(first, last);
1045 sect2->removeSpanRange(oppFirst, oppLast);
1046 first->fEndT = last->fEndT;
1047 first->resetBounds(this->fCurve);
1048 first->fCoinStart.setPerp(fCurve, first->fStartT, first->fPart[0], sect2->fC urve);
1049 first->fCoinEnd.setPerp(fCurve, first->fEndT, first->fPart[TCurve::kPointLas t], sect2->fCurve);
1050 oppStartT = first->fCoinStart.perpT();
1051 oppEndT = first->fCoinEnd.perpT();
1052 if (between(0, oppStartT, 1) && between(0, oppEndT, 1)) {
1053 if (!oppMatched) {
1054 SkTSwap(oppStartT, oppEndT);
1055 }
1056 oppFirst->fStartT = oppStartT;
1057 oppFirst->fEndT = oppEndT;
1058 oppFirst->resetBounds(sect2->fCurve);
1059 }
1060 this->validateBounded();
1061 sect2->validateBounded();
1062 last = first->fNext;
1063 this->removeCoincident(first, false);
1064 sect2->removeCoincident(oppFirst, true);
1065 if (deleteThisSpan) {
1066 this->deleteEmptySpans();
1067 }
1068 if (deleteSect2Span) {
1069 sect2->deleteEmptySpans();
1070 }
1071 this->validate();
1072 sect2->validate();
1073 return last && !last->fDeleted ? last : NULL;
1074 }
1075
1076 template<typename TCurve>
1077 SkTSpan<TCurve>* SkTSect<TCurve>::findCoincidentRun(SkTSpan<TCurve>* first,
1078 SkTSpan<TCurve>** lastPtr, const SkTSect* sect2) {
1079 SkTSpan<TCurve>* work = first;
1080 SkTSpan<TCurve>* lastCandidate = NULL;
1081 first = NULL;
1082 // find the first fully coincident span
1083 do {
1084 if (work->fCoinStart.isCoincident()) {
1085 work->validatePerpT(work->fCoinStart.perpT());
1086 work->validatePerpPt(work->fCoinStart.perpT(), work->fCoinStart.perp Pt());
1087 SkASSERT(work->hasOppT(work->fCoinStart.perpT()));
1088 if (!work->fCoinEnd.isCoincident()) {
1089 break;
1090 }
1091 lastCandidate = work;
1092 if (!first) {
1093 first = work;
1094 }
1095 } else {
1096 lastCandidate = NULL;
1097 SkASSERT(!first);
1098 }
1099 if (work == *lastPtr) {
1100 return first;
1101 }
1102 work = work->fNext;
1103 SkASSERT(work);
1104 } while (true);
1105 if (lastCandidate) {
1106 *lastPtr = lastCandidate;
1107 }
1108 return first;
1109 }
1110
1111 template<typename TCurve>
1112 int SkTSect<TCurve>::intersects(SkTSpan<TCurve>* span, const SkTSect* opp,
1113 SkTSpan<TCurve>* oppSpan, int* oppResult) const {
1114 bool spanStart, oppStart;
1115 int hullResult = span->hullsIntersect(oppSpan, &spanStart, &oppStart);
1116 if (hullResult >= 0) {
1117 if (hullResult == 2) { // hulls have one point in common
1118 if (span->fBounded.count() <= 1) {
1119 SkASSERT(span->fBounded.count() == 0 || span->fBounded[0] == opp Span);
1120 if (spanStart) {
1121 span->fEndT = span->fStartT;
713 } else { 1122 } else {
714 SkASSERT(oppStart->fStartT == oppT || oppT == oppStart->fEnd T); 1123 span->fStartT = span->fEndT;
715 first->fStartT = coinStart; 1124 }
716 prev->fEndT = coinStart; 1125 } else {
717 first->initBounds(fCurve); 1126 hullResult = 1;
718 prev->initBounds(fCurve); 1127 }
719 first->fCoinStart.markCoincident(); 1128 if (oppSpan->fBounded.count() <= 1) {
720 first->fCoinEnd.markCoincident(); 1129 SkASSERT(span->fBounded.count() == 0 || oppSpan->fBounded[0] == span);
721 } 1130 if (oppStart) {
722 } 1131 oppSpan->fEndT = oppSpan->fStartT;
723 }
724 }
725 if (!work->fCoinEnd.isCoincident()) {
726 if (work->fEndT == 1) {
727 SkDebugf("!");
728 }
729 // SkASSERT(work->fEndT < 1);
730 startT = work->fStartT;
731 double coinEnd;
732 if (binarySearchCoin(*sect2, startT, work->fEndT - startT, &coinEnd, &op pT)) {
733 if (coinEnd > startT) {
734 SkTSpan<TCurve>* oppStart = sect2->fHead->find(oppT);
735 if (oppStart->fStartT < oppT && oppT < oppStart->fEndT) {
736 SkASSERT(coinEnd < work->fEndT);
737 // split prev at coinEnd if needed
738 SkTSpan<TCurve>* half2 = addOne();
739 half2->splitAt(work, coinEnd);
740 half2->initBounds(fCurve);
741 work->initBounds(fCurve);
742 work->fCoinStart.markCoincident();
743 work->fCoinEnd.markCoincident();
744 half2->fCoinStart.markCoincident();
745 SkTSpan<TCurve>* oppHalf = sect2->addOne();
746 oppHalf->splitAt(oppStart, oppT);
747 oppHalf->initBounds(sect2->fCurve);
748 oppStart->initBounds(sect2->fCurve);
749 } else { 1132 } else {
750 SkASSERT(oppStart->fStartT == oppT || oppT == oppStart->fEnd T); 1133 oppSpan->fStartT = oppSpan->fEndT;
751 SkTSpan<TCurve>* next = work->fNext; 1134 }
752 bool hasNext = next && work->fEndT == next->fStartT; 1135 *oppResult = 2;
753 work->fEndT = coinEnd; 1136 } else {
754 work->initBounds(fCurve); 1137 *oppResult = 1;
755 work->fCoinStart.markCoincident(); 1138 }
756 work->fCoinEnd.markCoincident(); 1139 } else {
757 if (hasNext) { 1140 *oppResult = 1;
758 next->fStartT = coinEnd; 1141 }
759 next->initBounds(fCurve); 1142 return hullResult;
760 } 1143 }
761 } 1144 if (span->fIsLine && oppSpan->fIsLine) {
762 } 1145 SkIntersections i;
763 } 1146 int sects = this->linesIntersect(span, opp, oppSpan, &i);
764 } 1147 if (!sects) {
765 } 1148 return -1;
766 1149 }
767 template<typename TCurve> 1150 span->fStartT = span->fEndT = i[0][0];
1151 oppSpan->fStartT = oppSpan->fEndT = i[1][0];
1152 return *oppResult = 2;
1153 }
1154 if (span->fIsLinear || oppSpan->fIsLinear) {
1155 return *oppResult = (int) span->linearsIntersect(oppSpan);
1156 }
1157 return *oppResult = 1;
1158 }
1159
1160 // while the intersection points are sufficiently far apart:
1161 // construct the tangent lines from the intersections
1162 // find the point where the tangent line intersects the opposite curve
1163 template<typename TCurve>
1164 int SkTSect<TCurve>::linesIntersect(const SkTSpan<TCurve>* span, const SkTSect* opp,
1165 const SkTSpan<TCurve>* oppSpan, SkIntersections* i) const {
1166 SkIntersections thisRayI, oppRayI;
1167 SkDLine thisLine = {{ span->fPart[0], span->fPart[TCurve::kPointLast] }};
1168 SkDLine oppLine = {{ oppSpan->fPart[0], oppSpan->fPart[TCurve::kPointLast] } };
1169 int loopCount = 0;
1170 double bestDistSq = DBL_MAX;
1171 do {
1172 if (!thisRayI.intersectRay(opp->fCurve, thisLine)) {
1173 return 0;
1174 }
1175 if (!oppRayI.intersectRay(this->fCurve, oppLine)) {
1176 return 0;
1177 }
1178 // pick the closest pair of points
1179 double closest = DBL_MAX;
1180 int closeIndex SK_INIT_TO_AVOID_WARNING;
1181 int oppCloseIndex SK_INIT_TO_AVOID_WARNING;
1182 for (int index = 0; index < oppRayI.used(); ++index) {
1183 if (!roughly_between(span->fStartT, oppRayI[0][index], span->fEndT)) {
1184 continue;
1185 }
1186 for (int oIndex = 0; oIndex < thisRayI.used(); ++oIndex) {
1187 if (!roughly_between(oppSpan->fStartT, thisRayI[0][oIndex], oppS pan->fEndT)) {
1188 continue;
1189 }
1190 double distSq = thisRayI.pt(index).distanceSquared(oppRayI.pt(oI ndex));
1191 if (closest > distSq) {
1192 closest = distSq;
1193 closeIndex = index;
1194 oppCloseIndex = oIndex;
1195 }
1196 }
1197 }
1198 if (closest == DBL_MAX) {
1199 return 0;
1200 }
1201 const SkDPoint& oppIPt = thisRayI.pt(oppCloseIndex);
1202 const SkDPoint& iPt = oppRayI.pt(closeIndex);
1203 if (between(span->fStartT, oppRayI[0][closeIndex], span->fEndT)
1204 && between(oppSpan->fStartT, thisRayI[0][oppCloseIndex], oppSpan ->fEndT)
1205 && oppIPt.approximatelyEqual(iPt)) {
1206 i->merge(oppRayI, closeIndex, thisRayI, oppCloseIndex);
1207 return i->used();
1208 }
1209 double distSq = oppIPt.distanceSquared(iPt);
1210 if (bestDistSq < distSq || ++loopCount > 5) {
1211 break;
1212 }
1213 bestDistSq = distSq;
1214 thisLine[0] = fCurve.ptAtT(oppRayI[0][closeIndex]);
1215 thisLine[1] = thisLine[0] + fCurve.dxdyAtT(oppRayI[0][closeIndex]);
1216 oppLine[0] = opp->fCurve.ptAtT(thisRayI[0][oppCloseIndex]);
1217 oppLine[1] = oppLine[0] + opp->fCurve.dxdyAtT(thisRayI[0][oppCloseIndex] );
1218 } while (true);
1219 return false;
1220 }
1221
1222
1223 template<typename TCurve>
1224 void SkTSect<TCurve>::markSpanGone(SkTSpan<TCurve>* span) {
1225 --fActiveCount;
1226 span->fNext = fDeleted;
1227 fDeleted = span;
1228 SkASSERT(!span->fDeleted);
1229 span->fDeleted = true;
1230 }
1231
1232 template<typename TCurve>
1233 bool SkTSect<TCurve>::matchedDirection(double t, const SkTSect* sect2, double t2 ) const {
1234 SkDVector dxdy = this->fCurve.dxdyAtT(t);
1235 SkDVector dxdy2 = sect2->fCurve.dxdyAtT(t2);
1236 return dxdy.dot(dxdy2) >= 0;
1237 }
1238
1239 template<typename TCurve>
1240 void SkTSect<TCurve>::matchedDirCheck(double t, const SkTSect* sect2, double t2,
1241 bool* calcMatched, bool* oppMatched) const {
1242 if (*calcMatched) {
1243 SkASSERT(*oppMatched == this->matchedDirection(t, sect2, t2));
1244 } else {
1245 *oppMatched = this->matchedDirection(t, sect2, t2);
1246 *calcMatched = true;
1247 }
1248 }
1249
1250 template<typename TCurve>
1251 void SkTSect<TCurve>::mergeCoincidence(SkTSect* sect2) {
1252 double smallLimit = 0;
1253 do {
1254 // find the smallest unprocessed span
1255 SkTSpan<TCurve>* smaller = NULL;
1256 SkTSpan<TCurve>* test = fCoincident;
1257 do {
1258 if (test->fStartT < smallLimit) {
1259 continue;
1260 }
1261 if (smaller && smaller->fEndT < test->fStartT) {
1262 continue;
1263 }
1264 smaller = test;
1265 } while ((test = test->fNext));
1266 if (!smaller) {
1267 return;
1268 }
1269 smallLimit = smaller->fEndT;
1270 // find next larger span
1271 SkTSpan<TCurve>* prior = NULL;
1272 SkTSpan<TCurve>* larger = NULL;
1273 SkTSpan<TCurve>* largerPrior = NULL;
1274 test = fCoincident;
1275 do {
1276 if (test->fStartT < smaller->fEndT) {
1277 continue;
1278 }
1279 SkASSERT(test->fStartT != smaller->fEndT);
1280 if (larger && larger->fStartT < test->fStartT) {
1281 continue;
1282 }
1283 largerPrior = prior;
1284 larger = test;
1285 } while ((prior = test), (test = test->fNext));
1286 if (!larger) {
1287 continue;
1288 }
1289 // check middle t value to see if it is coincident as well
1290 double midT = (smaller->fEndT + larger->fStartT) / 2;
1291 SkDPoint midPt = fCurve.ptAtT(midT);
1292 SkTCoincident<TCurve> coin;
1293 coin.setPerp(fCurve, midT, midPt, sect2->fCurve);
1294 if (coin.isCoincident()) {
1295 smaller->fEndT = larger->fEndT;
1296 smaller->fCoinEnd = larger->fCoinEnd;
1297 if (largerPrior) {
1298 largerPrior->fNext = larger->fNext;
1299 } else {
1300 fCoincident = larger->fNext;
1301 }
1302 }
1303 } while (true);
1304 }
1305
1306 template<typename TCurve>
1307 SkTSpan<TCurve>* SkTSect<TCurve>::prev(SkTSpan<TCurve>* span) const {
1308 SkTSpan<TCurve>* result = NULL;
1309 SkTSpan<TCurve>* test = fHead;
1310 while (span != test) {
1311 result = test;
1312 test = test->fNext;
1313 SkASSERT(test);
1314 }
1315 return result;
1316 }
1317
1318 template<typename TCurve>
768 void SkTSect<TCurve>::recoverCollapsed() { 1319 void SkTSect<TCurve>::recoverCollapsed() {
769 SkTSpan<TCurve>* deleted = fDeleted; 1320 SkTSpan<TCurve>* deleted = fDeleted;
770 while (deleted) { 1321 while (deleted) {
771 SkTSpan<TCurve>* delNext = deleted->fNext; 1322 SkTSpan<TCurve>* delNext = deleted->fNext;
772 if (deleted->fCollapsed) { 1323 if (deleted->fCollapsed) {
773 SkTSpan<TCurve>** spanPtr = &fHead; 1324 SkTSpan<TCurve>** spanPtr = &fHead;
774 while (*spanPtr && (*spanPtr)->fEndT <= deleted->fStartT) { 1325 while (*spanPtr && (*spanPtr)->fEndT <= deleted->fStartT) {
775 spanPtr = &(*spanPtr)->fNext; 1326 spanPtr = &(*spanPtr)->fNext;
776 } 1327 }
777 deleted->fNext = *spanPtr; 1328 deleted->fNext = *spanPtr;
778 *spanPtr = deleted; 1329 *spanPtr = deleted;
779 } 1330 }
780 deleted = delNext; 1331 deleted = delNext;
781 } 1332 }
782 } 1333 }
783 1334
784 template<typename TCurve> 1335 template<typename TCurve>
1336 void SkTSect<TCurve>::removeAllBut(const SkTSpan<TCurve>* keep, SkTSpan<TCurve>* span,
1337 SkTSect* opp) {
1338 int count = span->fBounded.count();
1339 for (int index = 0; index < count; ++index) {
1340 SkTSpan<TCurve>* bounded = span->fBounded[0];
1341 if (bounded == keep) {
1342 continue;
1343 }
1344 if (bounded->fDeleted) { // may have been deleted when opp did 'remove all but'
1345 continue;
1346 }
1347 SkAssertResult(SkDEBUGCODE(!) span->removeBounded(bounded));
1348 if (bounded->removeBounded(span)) {
1349 opp->removeSpan(bounded);
1350 }
1351 }
1352 SkASSERT(!span->fDeleted);
1353 SkASSERT(span->findOppSpan(keep));
1354 SkASSERT(keep->findOppSpan(span));
1355 }
1356
1357 template<typename TCurve>
1358 void SkTSect<TCurve>::removeByPerpendicular(SkTSect<TCurve>* opp) {
1359 SkTSpan<TCurve>* test = fHead;
1360 SkTSpan<TCurve>* next;
1361 do {
1362 next = test->fNext;
1363 if (test->fCoinStart.perpT() < 0 || test->fCoinEnd.perpT() < 0) {
1364 continue;
1365 }
1366 SkDVector startV = test->fCoinStart.perpPt() - test->fPart[0];
1367 SkDVector endV = test->fCoinEnd.perpPt() - test->fPart[TCurve::kPointLas t];
1368 #if DEBUG_T_SECT
1369 SkDebugf("%s startV=(%1.9g,%1.9g) endV=(%1.9g,%1.9g) dot=%1.9g\n", __FUN CTION__,
1370 startV.fX, startV.fY, endV.fX, endV.fY, startV.dot(endV));
1371 #endif
1372 if (startV.dot(endV) <= 0) {
1373 continue;
1374 }
1375 this->removeSpans(test, opp);
1376 } while ((test = next));
1377 }
1378
1379 template<typename TCurve>
1380 void SkTSect<TCurve>::removeCoincident(SkTSpan<TCurve>* span, bool isBetween) {
1381 this->unlinkSpan(span);
1382 if (isBetween || between(0, span->fCoinStart.perpT(), 1)) {
1383 --fActiveCount;
1384 span->fNext = fCoincident;
1385 fCoincident = span;
1386 } else {
1387 this->markSpanGone(span);
1388 }
1389 }
1390
1391 template<typename TCurve>
785 void SkTSect<TCurve>::removeSpan(SkTSpan<TCurve>* span) { 1392 void SkTSect<TCurve>::removeSpan(SkTSpan<TCurve>* span) {
786 SkTSpan<TCurve>* prev = span->fPrev; 1393 this->unlinkSpan(span);
787 SkTSpan<TCurve>* next = span->fNext; 1394 this->markSpanGone(span);
788 if (prev) {
789 prev->fNext = next;
790 if (next) {
791 next->fPrev = prev;
792 }
793 } else {
794 fHead = next;
795 if (next) {
796 next->fPrev = NULL;
797 }
798 }
799 --fActiveCount;
800 span->fNext = fDeleted;
801 fDeleted = span;
802 #if DEBUG_T_SECT
803 SkASSERT(!span->fDebugDeleted);
804 span->fDebugDeleted = true;
805 #endif
806 } 1395 }
807 1396
808 template<typename TCurve> 1397 template<typename TCurve>
809 void SkTSect<TCurve>::removeOne(const SkTSpan<TCurve>* test, SkTSpan<TCurve>* sp an) { 1398 void SkTSect<TCurve>::removeSpanRange(SkTSpan<TCurve>* first, SkTSpan<TCurve>* l ast) {
810 int last = span->fBounded.count() - 1; 1399 if (first == last) {
811 for (int index = 0; index <= last; ++index) { 1400 return;
812 if (span->fBounded[index] == test) {
813 span->fBounded.removeShuffle(index);
814 if (!last) {
815 removeSpan(span);
816 }
817 return;
818 }
819 } 1401 }
1402 SkTSpan<TCurve>* span = first;
1403 SkASSERT(span);
1404 SkTSpan<TCurve>* final = last->fNext;
1405 SkTSpan<TCurve>* next = span->fNext;
1406 while ((span = next) && span != final) {
1407 next = span->fNext;
1408 this->markSpanGone(span);
1409 }
1410 if (final) {
1411 final->fPrev = first;
1412 }
1413 first->fNext = final;
820 } 1414 }
821 1415
822 template<typename TCurve> 1416 template<typename TCurve>
823 void SkTSect<TCurve>::removeSpans(SkTSpan<TCurve>* span, SkTSect<TCurve>* opp) { 1417 void SkTSect<TCurve>::removeSpans(SkTSpan<TCurve>* span, SkTSect<TCurve>* opp) {
824 int count = span->fBounded.count(); 1418 int count = span->fBounded.count();
825 for (int index = 0; index < count; ++index) { 1419 for (int index = 0; index < count; ++index) {
826 SkTSpan<TCurve>* bounded = span->fBounded[0]; 1420 SkTSpan<TCurve>* bounded = span->fBounded[0];
827 removeOne(bounded, span); // shuffles last into position 0 1421 if (span->removeBounded(bounded)) { // shuffles last into position 0
828 opp->removeOne(span, bounded); 1422 this->removeSpan(span);
1423 }
1424 if (bounded->removeBounded(span)) {
1425 opp->removeSpan(bounded);
1426 }
1427 SkASSERT(!span->fDeleted || !opp->debugHasBounded(span));
1428
829 } 1429 }
830 } 1430 }
831 1431
832 template<typename TCurve> 1432 template<typename TCurve>
833 void SkTSect<TCurve>::setPerp(const TCurve& opp, SkTSpan<TCurve>* first, SkTSpan <TCurve>* last) { 1433 SkTSpan<TCurve>* SkTSect<TCurve>::spanAtT(double t, SkTSpan<TCurve>** priorSpan) {
834 SkTSpan<TCurve>* work = first; 1434 SkTSpan<TCurve>* test = fHead;
835 if (!work->fHasPerp) { 1435 SkTSpan<TCurve>* prev = NULL;
836 work->fCoinStart.setPerp(fCurve, work->fStartT, work->fPart[0], opp); 1436 while (test && test->fEndT < t) {
1437 prev = test;
1438 test = test->fNext;
837 } 1439 }
838 do { 1440 *priorSpan = prev;
839 if (!work->fHasPerp) { 1441 return test && test->fStartT <= t ? test : NULL;
840 work->fCoinEnd.setPerp(fCurve, work->fEndT, work->fPart[TCurve::kPoi ntLast], opp);
841 work->fHasPerp = true;
842 }
843 if (work == last) {
844 break;
845 }
846 SkTSpan<TCurve>* last = work;
847 work = work->fNext;
848 SkASSERT(work);
849 if (!work->fHasPerp) {
850 work->fCoinStart = last->fCoinEnd;
851 }
852 } while (true);
853 } 1442 }
854 1443
855 template<typename TCurve> 1444 template<typename TCurve>
856 const SkTSpan<TCurve>* SkTSect<TCurve>::tail() const { 1445 SkTSpan<TCurve>* SkTSect<TCurve>::tail() {
857 const SkTSpan<TCurve>* result = fHead; 1446 SkTSpan<TCurve>* result = fHead;
858 const SkTSpan<TCurve>* next = fHead; 1447 SkTSpan<TCurve>* next = fHead;
859 while ((next = next->fNext)) { 1448 while ((next = next->fNext)) {
860 if (next->fEndT > result->fEndT) { 1449 if (next->fEndT > result->fEndT) {
861 result = next; 1450 result = next;
862 } 1451 }
863 } 1452 }
864 return result; 1453 return result;
865 } 1454 }
866 1455
867 /* Each span has a range of opposite spans it intersects. After the span is spli t in two, 1456 /* Each span has a range of opposite spans it intersects. After the span is spli t in two,
868 adjust the range to its new size */ 1457 adjust the range to its new size */
869 template<typename TCurve> 1458 template<typename TCurve>
870 void SkTSect<TCurve>::trim(SkTSpan<TCurve>* span, SkTSect* opp) { 1459 void SkTSect<TCurve>::trim(SkTSpan<TCurve>* span, SkTSect* opp) {
871 span->initBounds(fCurve); 1460 span->initBounds(fCurve);
872 int count = span->fBounded.count(); 1461 for (int index = 0; index < span->fBounded.count(); ) {
873 for (int index = 0; index < count; ) {
874 SkTSpan<TCurve>* test = span->fBounded[index]; 1462 SkTSpan<TCurve>* test = span->fBounded[index];
875 bool sects = intersects(span, opp, test); 1463 int oppSects, sects = this->intersects(span, opp, test, &oppSects);
876 if (sects) { 1464 if (sects >= 1) {
1465 if (sects == 2) {
1466 span->initBounds(fCurve);
1467 this->removeAllBut(test, span, opp);
1468 }
1469 if (oppSects == 2) {
1470 test->initBounds(opp->fCurve);
1471 opp->removeAllBut(span, test, this);
1472 }
877 ++index; 1473 ++index;
878 } else { 1474 } else {
879 removeOne(test, span); 1475 if (span->removeBounded(test)) {
880 opp->removeOne(span, test); 1476 this->removeSpan(span);
881 --count; 1477 }
1478 if (test->removeBounded(span)) {
1479 opp->removeSpan(test);
1480 }
882 } 1481 }
883 } 1482 }
884 } 1483 }
885 1484
886 #if DEBUG_T_SECT 1485 template<typename TCurve>
1486 void SkTSect<TCurve>::unlinkSpan(SkTSpan<TCurve>* span) {
1487 SkTSpan<TCurve>* prev = span->fPrev;
1488 SkTSpan<TCurve>* next = span->fNext;
1489 if (prev) {
1490 prev->fNext = next;
1491 if (next) {
1492 next->fPrev = prev;
1493 }
1494 } else {
1495 fHead = next;
1496 if (next) {
1497 next->fPrev = NULL;
1498 }
1499 }
1500 }
1501
1502 template<typename TCurve>
1503 bool SkTSect<TCurve>::updateBounded(SkTSpan<TCurve>* first, SkTSpan<TCurve>* las t,
1504 SkTSpan<TCurve>* oppFirst) {
1505 SkTSpan<TCurve>* test = first;
1506 const SkTSpan<TCurve>* final = last->next();
1507 bool deleteSpan = false;
1508 do {
1509 deleteSpan |= test->removeAllBounded();
1510 } while ((test = test->fNext) != final);
1511 first->fBounded.resize_back(1);
1512 first->fBounded[0] = oppFirst;
1513 // cannot call validate until remove span range is called
1514 return deleteSpan;
1515 }
1516
1517
887 template<typename TCurve> 1518 template<typename TCurve>
888 void SkTSect<TCurve>::validate() const { 1519 void SkTSect<TCurve>::validate() const {
1520 #if DEBUG_T_SECT
889 int count = 0; 1521 int count = 0;
890 if (fHead) { 1522 if (fHead) {
891 const SkTSpan<TCurve>* span = fHead; 1523 const SkTSpan<TCurve>* span = fHead;
892 SkASSERT(!span->fPrev); 1524 SkASSERT(!span->fPrev);
893 double last = 0; 1525 SkDEBUGCODE(double last = 0);
894 do { 1526 do {
895 span->validate(); 1527 span->validate();
896 SkASSERT(span->fStartT >= last); 1528 SkASSERT(span->fStartT >= last);
897 last = span->fEndT; 1529 SkDEBUGCODE(last = span->fEndT);
898 ++count; 1530 ++count;
899 } while ((span = span->fNext) != NULL); 1531 } while ((span = span->fNext) != NULL);
900 } 1532 }
901 SkASSERT(count == fActiveCount); 1533 SkASSERT(count == fActiveCount);
902 SkASSERT(fActiveCount <= fDebugAllocatedCount); 1534 SkASSERT(fActiveCount <= fDebugAllocatedCount);
903 int deletedCount = 0; 1535 int deletedCount = 0;
904 const SkTSpan<TCurve>* deleted = fDeleted; 1536 const SkTSpan<TCurve>* deleted = fDeleted;
905 while (deleted) { 1537 while (deleted) {
906 ++deletedCount; 1538 ++deletedCount;
907 deleted = deleted->fNext; 1539 deleted = deleted->fNext;
908 } 1540 }
1541 const SkTSpan<TCurve>* coincident = fCoincident;
1542 while (coincident) {
1543 ++deletedCount;
1544 coincident = coincident->fNext;
1545 }
909 SkASSERT(fActiveCount + deletedCount == fDebugAllocatedCount); 1546 SkASSERT(fActiveCount + deletedCount == fDebugAllocatedCount);
1547 #endif
910 } 1548 }
1549
1550 template<typename TCurve>
1551 void SkTSect<TCurve>::validateBounded() const {
1552 #if DEBUG_T_SECT
1553 if (!fHead) {
1554 return;
1555 }
1556 const SkTSpan<TCurve>* span = fHead;
1557 do {
1558 span->validateBounded();
1559 } while ((span = span->fNext) != NULL);
911 #endif 1560 #endif
1561 }
912 1562
913 template<typename TCurve> 1563 template<typename TCurve>
914 int SkTSect<TCurve>::EndsEqual(const SkTSect* sect1, const SkTSect* sect2, 1564 int SkTSect<TCurve>::EndsEqual(const SkTSect* sect1, const SkTSect* sect2,
915 SkIntersections* intersections) { 1565 SkIntersections* intersections) {
916 int zeroOneSet = 0; 1566 int zeroOneSet = 0;
1567 if (sect1->fCurve[0] == sect2->fCurve[0]) {
1568 zeroOneSet |= kZeroS1Set | kZeroS2Set;
1569 intersections->insert(0, 0, sect1->fCurve[0]);
1570 }
1571 if (sect1->fCurve[0] == sect2->fCurve[TCurve::kPointLast]) {
1572 zeroOneSet |= kZeroS1Set | kOneS2Set;
1573 intersections->insert(0, 1, sect1->fCurve[0]);
1574 }
1575 if (sect1->fCurve[TCurve::kPointLast] == sect2->fCurve[0]) {
1576 zeroOneSet |= kOneS1Set | kZeroS2Set;
1577 intersections->insert(1, 0, sect1->fCurve[TCurve::kPointLast]);
1578 }
1579 if (sect1->fCurve[TCurve::kPointLast] == sect2->fCurve[TCurve::kPointLast]) {
1580 zeroOneSet |= kOneS1Set | kOneS2Set;
1581 intersections->insert(1, 1, sect1->fCurve[TCurve::kPointLast]);
1582 }
917 // check for zero 1583 // check for zero
918 if (sect1->fCurve[0].approximatelyEqual(sect2->fCurve[0])) { 1584 if (!(zeroOneSet & (kZeroS1Set | kZeroS2Set))
1585 && sect1->fCurve[0].approximatelyEqual(sect2->fCurve[0])) {
919 zeroOneSet |= kZeroS1Set | kZeroS2Set; 1586 zeroOneSet |= kZeroS1Set | kZeroS2Set;
920 if (sect1->fCurve[0] != sect2->fCurve[0]) { 1587 intersections->insertNear(0, 0, sect1->fCurve[0], sect2->fCurve[0]);
921 intersections->insertNear(0, 0, sect1->fCurve[0], sect2->fCurve[0]); 1588 }
922 } else { 1589 if (!(zeroOneSet & (kZeroS1Set | kOneS2Set))
923 intersections->insert(0, 0, sect1->fCurve[0]); 1590 && sect1->fCurve[0].approximatelyEqual(sect2->fCurve[TCurve::kPointL ast])) {
924 }
925 }
926 if (sect1->fCurve[0].approximatelyEqual(sect2->fCurve[TCurve::kPointLast])) {
927 zeroOneSet |= kZeroS1Set | kOneS2Set; 1591 zeroOneSet |= kZeroS1Set | kOneS2Set;
928 if (sect1->fCurve[0] != sect2->fCurve[TCurve::kPointLast]) { 1592 intersections->insertNear(0, 1, sect1->fCurve[0], sect2->fCurve[TCurve:: kPointLast]);
929 intersections->insertNear(0, 1, sect1->fCurve[0], sect2->fCurve[TCur ve::kPointLast]); 1593 }
930 } else {
931 intersections->insert(0, 1, sect1->fCurve[0]);
932 }
933 }
934 // check for one 1594 // check for one
935 if (sect1->fCurve[TCurve::kPointLast].approximatelyEqual(sect2->fCurve[0])) { 1595 if (!(zeroOneSet & (kOneS1Set | kZeroS2Set))
1596 && sect1->fCurve[TCurve::kPointLast].approximatelyEqual(sect2->fCurv e[0])) {
936 zeroOneSet |= kOneS1Set | kZeroS2Set; 1597 zeroOneSet |= kOneS1Set | kZeroS2Set;
937 if (sect1->fCurve[TCurve::kPointLast] != sect2->fCurve[0]) { 1598 intersections->insertNear(1, 0, sect1->fCurve[TCurve::kPointLast], sect2 ->fCurve[0]);
938 intersections->insertNear(1, 0, sect1->fCurve[TCurve::kPointLast], s ect2->fCurve[0]); 1599 }
939 } else { 1600 if (!(zeroOneSet & (kOneS1Set | kOneS2Set))
940 intersections->insert(1, 0, sect1->fCurve[TCurve::kPointLast]); 1601 && sect1->fCurve[TCurve::kPointLast].approximatelyEqual(sect2->fCurv e[
941 } 1602 TCurve::kPointLast])) {
942 }
943 if (sect1->fCurve[TCurve::kPointLast].approximatelyEqual(sect2->fCurve[TCurv e::kPointLast])) {
944 zeroOneSet |= kOneS1Set | kOneS2Set; 1603 zeroOneSet |= kOneS1Set | kOneS2Set;
945 if (sect1->fCurve[TCurve::kPointLast] != sect2->fCurve[TCurve::kPointLas t]) { 1604 intersections->insertNear(1, 1, sect1->fCurve[TCurve::kPointLast],
946 intersections->insertNear(1, 1, sect1->fCurve[TCurve::kPointLast], 1605 sect2->fCurve[TCurve::kPointLast]);
947 sect2->fCurve[TCurve::kPointLast]);
948 } else {
949 intersections->insert(1, 1, sect1->fCurve[TCurve::kPointLast]);
950 }
951 } 1606 }
952 return zeroOneSet; 1607 return zeroOneSet;
953 } 1608 }
954 1609
955 template<typename TCurve> 1610 template<typename TCurve>
956 struct SkClosestRecord { 1611 struct SkClosestRecord {
1612 bool operator<(const SkClosestRecord& rh) const {
1613 return fClosest < rh.fClosest;
1614 }
1615
957 void addIntersection(SkIntersections* intersections) const { 1616 void addIntersection(SkIntersections* intersections) const {
958 double r1t = fC1Index ? fC1Span->endT() : fC1Span->startT(); 1617 double r1t = fC1Index ? fC1Span->endT() : fC1Span->startT();
959 double r2t = fC2Index ? fC2Span->endT() : fC2Span->startT(); 1618 double r2t = fC2Index ? fC2Span->endT() : fC2Span->startT();
960 intersections->insert(r1t, r2t, fC1Span->part()[fC1Index]); 1619 intersections->insert(r1t, r2t, fC1Span->part()[fC1Index]);
961 } 1620 }
962 1621
963 void findEnd(const SkTSpan<TCurve>* span1, const SkTSpan<TCurve>* span2, 1622 void findEnd(const SkTSpan<TCurve>* span1, const SkTSpan<TCurve>* span2,
964 int c1Index, int c2Index) { 1623 int c1Index, int c2Index) {
965 const TCurve& c1 = span1->part(); 1624 const TCurve& c1 = span1->part();
966 const TCurve& c2 = span2->part(); 1625 const TCurve& c2 = span2->part();
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1026 int fC2Index; 1685 int fC2Index;
1027 }; 1686 };
1028 1687
1029 template<typename TCurve> 1688 template<typename TCurve>
1030 struct SkClosestSect { 1689 struct SkClosestSect {
1031 SkClosestSect() 1690 SkClosestSect()
1032 : fUsed(0) { 1691 : fUsed(0) {
1033 fClosest.push_back().reset(); 1692 fClosest.push_back().reset();
1034 } 1693 }
1035 1694
1036 void find(const SkTSpan<TCurve>* span1, const SkTSpan<TCurve>* span2) { 1695 bool find(const SkTSpan<TCurve>* span1, const SkTSpan<TCurve>* span2) {
1037 SkClosestRecord<TCurve>* record = &fClosest[fUsed]; 1696 SkClosestRecord<TCurve>* record = &fClosest[fUsed];
1038 record->findEnd(span1, span2, 0, 0); 1697 record->findEnd(span1, span2, 0, 0);
1039 record->findEnd(span1, span2, 0, TCurve::kPointLast); 1698 record->findEnd(span1, span2, 0, TCurve::kPointLast);
1040 record->findEnd(span1, span2, TCurve::kPointLast, 0); 1699 record->findEnd(span1, span2, TCurve::kPointLast, 0);
1041 record->findEnd(span1, span2, TCurve::kPointLast, TCurve::kPointLast); 1700 record->findEnd(span1, span2, TCurve::kPointLast, TCurve::kPointLast);
1042 if (record->fClosest == FLT_MAX) { 1701 if (record->fClosest == FLT_MAX) {
1043 return; 1702 return false;
1044 } 1703 }
1045 for (int index = 0; index < fUsed; ++index) { 1704 for (int index = 0; index < fUsed; ++index) {
1046 SkClosestRecord<TCurve>* test = &fClosest[index]; 1705 SkClosestRecord<TCurve>* test = &fClosest[index];
1047 if (test->matesWith(*record)) { 1706 if (test->matesWith(*record)) {
1048 if (test->fClosest > record->fClosest) { 1707 if (test->fClosest > record->fClosest) {
1049 test->merge(*record); 1708 test->merge(*record);
1050 } 1709 }
1051 test->update(*record); 1710 test->update(*record);
1052 record->reset(); 1711 record->reset();
1053 return; 1712 return false;
1054 } 1713 }
1055 } 1714 }
1056 ++fUsed; 1715 ++fUsed;
1057 fClosest.push_back().reset(); 1716 fClosest.push_back().reset();
1717 return true;
1058 } 1718 }
1059 1719
1060 void finish(SkIntersections* intersections) const { 1720 void finish(SkIntersections* intersections) const {
1721 SkSTArray<TCurve::kMaxIntersections * 2, const SkClosestRecord<TCurve>*, true> closestPtrs;
1061 for (int index = 0; index < fUsed; ++index) { 1722 for (int index = 0; index < fUsed; ++index) {
1062 const SkClosestRecord<TCurve>& test = fClosest[index]; 1723 closestPtrs.push_back(&fClosest[index]);
1063 test.addIntersection(intersections); 1724 }
1725 SkTQSort<const SkClosestRecord<TCurve> >(closestPtrs.begin(), closestPtr s.end() - 1);
1726 for (int index = 0; index < fUsed; ++index) {
1727 const SkClosestRecord<TCurve>* test = closestPtrs[index];
1728 test->addIntersection(intersections);
1064 } 1729 }
1065 } 1730 }
1066 1731
1067 // this is oversized by one so that an extra record can merge into final one 1732 // this is oversized so that an extra records can merge into final one
1068 SkSTArray<TCurve::kMaxIntersections + 1, SkClosestRecord<TCurve>, true> fClo sest; 1733 SkSTArray<TCurve::kMaxIntersections * 2, SkClosestRecord<TCurve>, true> fClo sest;
1069 int fUsed; 1734 int fUsed;
1070 }; 1735 };
1071 1736
1072 // returns true if the rect is too small to consider 1737 // returns true if the rect is too small to consider
1073 template<typename TCurve> 1738 template<typename TCurve>
1074 void SkTSect<TCurve>::BinarySearch(SkTSect* sect1, SkTSect* sect2, SkIntersectio ns* intersections) { 1739 void SkTSect<TCurve>::BinarySearch(SkTSect* sect1, SkTSect* sect2, SkIntersectio ns* intersections) {
1740 PATH_OPS_DEBUG_CODE(sect1->fOppSect = sect2);
1741 PATH_OPS_DEBUG_CODE(sect2->fOppSect = sect1);
1075 intersections->reset(); 1742 intersections->reset();
1076 intersections->setMax(TCurve::kMaxIntersections); 1743 intersections->setMax(TCurve::kMaxIntersections * 2); // give extra for slo p
1077 SkTSpan<TCurve>* span1 = sect1->fHead; 1744 SkTSpan<TCurve>* span1 = sect1->fHead;
1078 SkTSpan<TCurve>* span2 = sect2->fHead; 1745 SkTSpan<TCurve>* span2 = sect2->fHead;
1079 bool check; 1746 int oppSect, sect = sect1->intersects(span1, sect2, span2, &oppSect);
1080 if (!span1->intersects(span2, &check)) { 1747 // SkASSERT(between(0, sect, 2));
1748 if (!sect) {
1081 return; 1749 return;
1082 } 1750 }
1083 if (check) { 1751 if (sect == 2 && oppSect == 2) {
1084 (void) EndsEqual(sect1, sect2, intersections); 1752 (void) EndsEqual(sect1, sect2, intersections);
1085 return; 1753 return;
1086 } 1754 }
1087 span1->fBounded.push_back() = span2; 1755 span1->fBounded.push_back() = span2;
1088 span2->fBounded.push_back() = span1; 1756 span2->fBounded.push_back() = span1;
1089 do { 1757 do {
1090 // find the largest bounds 1758 // find the largest bounds
1091 SkTSpan<TCurve>* largest1 = sect1->boundsMax(); 1759 SkTSpan<TCurve>* largest1 = sect1->boundsMax();
1092 if (!largest1) { 1760 if (!largest1) {
1093 break; 1761 break;
1094 } 1762 }
1095 SkTSpan<TCurve>* largest2 = sect2->boundsMax(); 1763 SkTSpan<TCurve>* largest2 = sect2->boundsMax();
1096 bool split1 = !largest2 || (largest1 && (largest1->fBoundsMax > largest2 ->fBoundsMax 1764 bool split1 = !largest2 || (largest1 && (largest1->fBoundsMax > largest2 ->fBoundsMax
1097 || (!largest1->fCollapsed && largest2->fCollapsed))); 1765 || (!largest1->fCollapsed && largest2->fCollapsed)));
1098 // split it 1766 // split it
1099 SkTSect* splitSect = split1 ? sect1 : sect2;
1100 SkTSpan<TCurve>* half1 = split1 ? largest1 : largest2; 1767 SkTSpan<TCurve>* half1 = split1 ? largest1 : largest2;
1101 SkASSERT(half1); 1768 SkASSERT(half1);
1102 if (half1->fCollapsed) { 1769 if (half1->fCollapsed) {
1103 break; 1770 break;
1104 } 1771 }
1772 SkTSect* splitSect = split1 ? sect1 : sect2;
1105 // trim parts that don't intersect the opposite 1773 // trim parts that don't intersect the opposite
1106 SkTSpan<TCurve>* half2 = splitSect->addOne(); 1774 SkTSpan<TCurve>* half2 = splitSect->addOne();
1107 SkTSect* unsplitSect = split1 ? sect2 : sect1; 1775 SkTSect* unsplitSect = split1 ? sect2 : sect1;
1108 if (!half2->split(half1)) { 1776 if (!half2->split(half1)) {
1109 break; 1777 break;
1110 } 1778 }
1111 splitSect->trim(half1, unsplitSect); 1779 splitSect->trim(half1, unsplitSect);
1112 splitSect->trim(half2, unsplitSect); 1780 splitSect->trim(half2, unsplitSect);
1781 sect1->validate();
1782 sect2->validate();
1113 // if there are 9 or more continuous spans on both sects, suspect coinci dence 1783 // if there are 9 or more continuous spans on both sects, suspect coinci dence
1114 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT 1784 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT
1115 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) { 1785 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) {
1116 sect1->coincidentCheck(sect2); 1786 sect1->coincidentCheck(sect2);
1787 sect1->validate();
1788 sect2->validate();
1117 } 1789 }
1118 #if DEBUG_T_SECT 1790 if (sect1->fActiveCount >= COINCIDENT_SPAN_COUNT
1119 sect1->validate(); 1791 && sect2->fActiveCount >= COINCIDENT_SPAN_COUNT) {
1120 sect2->validate(); 1792 sect1->computePerpendiculars(sect2, sect1->fHead, sect1->tail());
1121 #endif 1793 sect2->computePerpendiculars(sect1, sect2->fHead, sect2->tail());
1122 #if DEBUG_T_SECT_DUMP > 1 1794 sect1->removeByPerpendicular(sect2);
1123 sect1->dumpBoth(*sect2); 1795 sect1->validate();
1796 sect2->validate();
1797 }
1798 #if DEBUG_T_SECT_DUMP
1799 sect1->dumpBoth(sect2);
1124 #endif 1800 #endif
1125 if (!sect1->fHead || !sect2->fHead) { 1801 if (!sect1->fHead || !sect2->fHead) {
1126 return; 1802 break;
1127 } 1803 }
1128 } while (true); 1804 } while (true);
1129 if (sect1->fActiveCount >= 2 && sect2->fActiveCount >= 2) { 1805 SkTSpan<TCurve>* coincident = sect1->fCoincident;
1130 // check for coincidence 1806 if (coincident) {
1131 SkTSpan<TCurve>* first = sect1->fHead; 1807 // if there is more than one coincident span, check loosely to see if th ey should be joined
1808 if (coincident->fNext) {
1809 sect1->mergeCoincidence(sect2);
1810 coincident = sect1->fCoincident;
1811 }
1812 SkASSERT(sect2->fCoincident); // courtesy check : coincidence only look s at sect 1
1132 do { 1813 do {
1133 if (!first->fCoinStart.isCoincident()) { 1814 SkASSERT(coincident->fCoinStart.isCoincident());
1134 continue; 1815 SkASSERT(coincident->fCoinEnd.isCoincident());
1135 } 1816 int index = intersections->insertCoincident(coincident->fStartT,
1136 int spanCount = 1; 1817 coincident->fCoinStart.perpT(), coincident->fPart[0]);
1137 SkTSpan<TCurve>* last = first; 1818 if ((intersections->insertCoincident(coincident->fEndT,
1138 while (last->fCoinEnd.isCoincident()) { 1819 coincident->fCoinEnd.perpT(),
1139 SkTSpan<TCurve>* next = last->fNext; 1820 coincident->fPart[TCurve::kPointLast]) < 0) && index >= 0) {
1140 if (!next || !next->fCoinEnd.isCoincident()) {
1141 break;
1142 }
1143 last = next;
1144 ++spanCount;
1145 }
1146 if (spanCount < 2) {
1147 first = last;
1148 continue;
1149 }
1150 int index = intersections->insertCoincident(first->fStartT, first->f CoinStart.perpT(),
1151 first->fPart[0]);
1152 if (intersections->insertCoincident(last->fEndT, last->fCoinEnd.perp T(),
1153 last->fPart[TCurve::kPointLast]) < 0) {
1154 intersections->clearCoincidence(index); 1821 intersections->clearCoincidence(index);
1155 } 1822 }
1156 } while ((first = first->fNext)); 1823 } while ((coincident = coincident->fNext));
1824 }
1825 if (!sect1->fHead || !sect2->fHead) {
1826 return;
1157 } 1827 }
1158 int zeroOneSet = EndsEqual(sect1, sect2, intersections); 1828 int zeroOneSet = EndsEqual(sect1, sect2, intersections);
1159 sect1->recoverCollapsed(); 1829 sect1->recoverCollapsed();
1160 sect2->recoverCollapsed(); 1830 sect2->recoverCollapsed();
1161 SkTSpan<TCurve>* result1 = sect1->fHead; 1831 SkTSpan<TCurve>* result1 = sect1->fHead;
1162 // check heads and tails for zero and ones and insert them if we haven't alr eady done so 1832 // check heads and tails for zero and ones and insert them if we haven't alr eady done so
1163 const SkTSpan<TCurve>* head1 = result1; 1833 const SkTSpan<TCurve>* head1 = result1;
1164 if (!(zeroOneSet & kZeroS1Set) && approximately_less_than_zero(head1->fStart T)) { 1834 if (!(zeroOneSet & kZeroS1Set) && approximately_less_than_zero(head1->fStart T)) {
1165 const SkDPoint& start1 = sect1->fCurve[0]; 1835 const SkDPoint& start1 = sect1->fCurve[0];
1166 double t = head1->closestBoundedT(start1); 1836 if (head1->isBounded()) {
1167 if (sect2->fCurve.ptAtT(t).approximatelyEqual(start1)) { 1837 double t = head1->closestBoundedT(start1);
1168 intersections->insert(0, t, start1); 1838 if (sect2->fCurve.ptAtT(t).approximatelyEqual(start1)) {
1839 intersections->insert(0, t, start1);
1840 }
1169 } 1841 }
1170 } 1842 }
1171 const SkTSpan<TCurve>* head2 = sect2->fHead; 1843 const SkTSpan<TCurve>* head2 = sect2->fHead;
1172 if (!(zeroOneSet & kZeroS2Set) && approximately_less_than_zero(head2->fStart T)) { 1844 if (!(zeroOneSet & kZeroS2Set) && approximately_less_than_zero(head2->fStart T)) {
1173 const SkDPoint& start2 = sect2->fCurve[0]; 1845 const SkDPoint& start2 = sect2->fCurve[0];
1174 double t = head2->closestBoundedT(start2); 1846 if (head2->isBounded()) {
1175 if (sect1->fCurve.ptAtT(t).approximatelyEqual(start2)) { 1847 double t = head2->closestBoundedT(start2);
1176 intersections->insert(t, 0, start2); 1848 if (sect1->fCurve.ptAtT(t).approximatelyEqual(start2)) {
1849 intersections->insert(t, 0, start2);
1850 }
1177 } 1851 }
1178 } 1852 }
1179 const SkTSpan<TCurve>* tail1 = sect1->tail(); 1853 const SkTSpan<TCurve>* tail1 = sect1->tail();
1180 if (!(zeroOneSet & kOneS1Set) && approximately_greater_than_one(tail1->fEndT )) { 1854 if (!(zeroOneSet & kOneS1Set) && approximately_greater_than_one(tail1->fEndT )) {
1181 const SkDPoint& end1 = sect1->fCurve[TCurve::kPointLast]; 1855 const SkDPoint& end1 = sect1->fCurve[TCurve::kPointLast];
1182 double t = tail1->closestBoundedT(end1); 1856 if (tail1->isBounded()) {
1183 if (sect2->fCurve.ptAtT(t).approximatelyEqual(end1)) { 1857 double t = tail1->closestBoundedT(end1);
1184 intersections->insert(1, t, end1); 1858 if (sect2->fCurve.ptAtT(t).approximatelyEqual(end1)) {
1859 intersections->insert(1, t, end1);
1860 }
1185 } 1861 }
1186 } 1862 }
1187 const SkTSpan<TCurve>* tail2 = sect2->tail(); 1863 const SkTSpan<TCurve>* tail2 = sect2->tail();
1188 if (!(zeroOneSet & kOneS2Set) && approximately_greater_than_one(tail2->fEndT )) { 1864 if (!(zeroOneSet & kOneS2Set) && approximately_greater_than_one(tail2->fEndT )) {
1189 const SkDPoint& end2 = sect2->fCurve[TCurve::kPointLast]; 1865 const SkDPoint& end2 = sect2->fCurve[TCurve::kPointLast];
1190 double t = tail2->closestBoundedT(end2); 1866 if (tail2->isBounded()) {
1191 if (sect1->fCurve.ptAtT(t).approximatelyEqual(end2)) { 1867 double t = tail2->closestBoundedT(end2);
1192 intersections->insert(t, 1, end2); 1868 if (sect1->fCurve.ptAtT(t).approximatelyEqual(end2)) {
1869 intersections->insert(t, 1, end2);
1870 }
1193 } 1871 }
1194 } 1872 }
1195 SkClosestSect<TCurve> closest; 1873 SkClosestSect<TCurve> closest;
1196 do { 1874 do {
1197 while (result1 && result1->fCoinStart.isCoincident() && result1->fCoinEn d.isCoincident()) { 1875 while (result1 && result1->fCoinStart.isCoincident() && result1->fCoinEn d.isCoincident()) {
1198 result1 = result1->fNext; 1876 result1 = result1->fNext;
1199 } 1877 }
1200 if (!result1) { 1878 if (!result1) {
1201 break; 1879 break;
1202 } 1880 }
1203 SkTSpan<TCurve>* result2 = sect2->fHead; 1881 SkTSpan<TCurve>* result2 = sect2->fHead;
1882 bool found = false;
1204 while (result2) { 1883 while (result2) {
1205 closest.find(result1, result2); 1884 found |= closest.find(result1, result2);
1206 result2 = result2->fNext; 1885 result2 = result2->fNext;
1207 } 1886 }
1208
1209 } while ((result1 = result1->fNext)); 1887 } while ((result1 = result1->fNext));
1210 closest.finish(intersections); 1888 closest.finish(intersections);
1889 // if there is more than one intersection and it isn't already coincident, c heck
1890 int last = intersections->used() - 1;
1891 for (int index = 0; index < last; ) {
1892 if (intersections->isCoincident(index) && intersections->isCoincident(in dex + 1)) {
1893 ++index;
1894 continue;
1895 }
1896 double midT = ((*intersections)[0][index] + (*intersections)[0][index + 1]) / 2;
1897 SkDPoint midPt = sect1->fCurve.ptAtT(midT);
1898 // intersect perpendicular with opposite curve
1899 SkTCoincident<TCurve> perp;
1900 perp.setPerp(sect1->fCurve, midT, midPt, sect2->fCurve);
1901 if (!perp.isCoincident()) {
1902 ++index;
1903 continue;
1904 }
1905 if (intersections->isCoincident(index)) {
1906 intersections->removeOne(index);
1907 --last;
1908 } else if (intersections->isCoincident(index + 1)) {
1909 intersections->removeOne(index + 1);
1910 --last;
1911 } else {
1912 intersections->setCoincident(index++);
1913 }
1914 intersections->setCoincident(index);
1915 }
1916 SkASSERT(intersections->used() <= TCurve::kMaxIntersections);
1211 } 1917 }
OLDNEW
« no previous file with comments | « src/pathops/SkPathOpsTQuadSect.cpp ('k') | src/pathops/SkPathOpsTightBounds.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698