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