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

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

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

Powered by Google App Engine
This is Rietveld 408576698