OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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, §1->fHeap); | 1826 span1->addBounded(span2, §1->fHeap); |
1796 span2->addBounded(span1, §2->fHeap); | 1827 span2->addBounded(span1, §2->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, §1->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, §2->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 } |
OLD | NEW |