OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 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 SkOpContour_DEFINED | 7 #ifndef SkOpContour_DEFINED |
8 #define SkOpContour_DEFINED | 8 #define SkOpContour_DEFINED |
9 | 9 |
10 #include "SkOpSegment.h" | 10 #include "SkOpSegment.h" |
11 #include "SkTArray.h" | 11 #include "SkTArray.h" |
12 | 12 |
13 #if defined(SK_DEBUG) || !FORCE_RELEASE | 13 #if defined(SK_DEBUG) || !FORCE_RELEASE |
14 #include "SkThread.h" | 14 #include "SkThread.h" |
15 #endif | 15 #endif |
16 | 16 |
17 class SkIntersections; | 17 class SkIntersections; |
18 class SkOpContour; | 18 class SkOpContour; |
19 class SkPathWriter; | 19 class SkPathWriter; |
20 | 20 |
21 struct SkCoincidence { | 21 struct SkCoincidence { |
22 SkOpContour* fOther; | 22 SkOpContour* fOther; |
23 int fSegments[2]; | 23 int fSegments[2]; |
24 double fTs[2][2]; | 24 double fTs[2][2]; |
25 SkPoint fPts[2]; | 25 SkPoint fPts[2][2]; |
| 26 int fNearly[2]; |
26 }; | 27 }; |
27 | 28 |
28 class SkOpContour { | 29 class SkOpContour { |
29 public: | 30 public: |
30 SkOpContour() { | 31 SkOpContour() { |
31 reset(); | 32 reset(); |
32 #if defined(SK_DEBUG) || !FORCE_RELEASE | 33 #if defined(SK_DEBUG) || !FORCE_RELEASE |
33 fID = sk_atomic_inc(&SkPathOpsDebug::gContourID); | 34 fID = sk_atomic_inc(&SkPathOpsDebug::gContourID); |
34 #endif | 35 #endif |
35 } | 36 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 int addT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt
, double newT) { | 80 int addT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt
, double newT) { |
80 setContainsIntercepts(); | 81 setContainsIntercepts(); |
81 return fSegments[segIndex].addT(&other->fSegments[otherIndex], pt, newT)
; | 82 return fSegments[segIndex].addT(&other->fSegments[otherIndex], pt, newT)
; |
82 } | 83 } |
83 | 84 |
84 int addSelfT(int segIndex, const SkPoint& pt, double newT) { | 85 int addSelfT(int segIndex, const SkPoint& pt, double newT) { |
85 setContainsIntercepts(); | 86 setContainsIntercepts(); |
86 return fSegments[segIndex].addSelfT(pt, newT); | 87 return fSegments[segIndex].addSelfT(pt, newT); |
87 } | 88 } |
88 | 89 |
| 90 void align(const SkOpSegment::AlignedSpan& aligned, bool swap, SkCoincidence
* coincidence); |
| 91 void alignCoincidence(const SkOpSegment::AlignedSpan& aligned, |
| 92 SkTArray<SkCoincidence, true>* coincidences); |
| 93 |
| 94 void alignCoincidence(const SkOpSegment::AlignedSpan& aligned) { |
| 95 alignCoincidence(aligned, &fCoincidences); |
| 96 alignCoincidence(aligned, &fPartialCoincidences); |
| 97 } |
| 98 |
| 99 void alignMultiples(SkTDArray<SkOpSegment::AlignedSpan>* aligned) { |
| 100 int segmentCount = fSegments.count(); |
| 101 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { |
| 102 SkOpSegment& segment = fSegments[sIndex]; |
| 103 if (segment.hasMultiples()) { |
| 104 segment.alignMultiples(aligned); |
| 105 } |
| 106 } |
| 107 } |
| 108 |
| 109 void alignTPt(int segmentIndex, const SkOpContour* other, int otherIndex, |
| 110 bool swap, int tIndex, SkIntersections* ts, SkPoint* point) co
nst; |
| 111 |
89 const SkPathOpsBounds& bounds() const { | 112 const SkPathOpsBounds& bounds() const { |
90 return fBounds; | 113 return fBounds; |
91 } | 114 } |
92 | 115 |
93 bool calcAngles(); | 116 bool calcAngles(); |
94 void calcCoincidentWinding(); | 117 void calcCoincidentWinding(); |
95 void calcPartialCoincidentWinding(); | 118 void calcPartialCoincidentWinding(); |
96 | 119 |
97 void checkDuplicates() { | 120 void checkDuplicates() { |
98 int segmentCount = fSegments.count(); | 121 int segmentCount = fSegments.count(); |
(...skipping 21 matching lines...) Expand all Loading... |
120 segment->checkEnds(); | 143 segment->checkEnds(); |
121 } | 144 } |
122 } | 145 } |
123 | 146 |
124 void checkMultiples() { | 147 void checkMultiples() { |
125 int segmentCount = fSegments.count(); | 148 int segmentCount = fSegments.count(); |
126 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { | 149 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { |
127 SkOpSegment& segment = fSegments[sIndex]; | 150 SkOpSegment& segment = fSegments[sIndex]; |
128 if (segment.count() > 2) { | 151 if (segment.count() > 2) { |
129 segment.checkMultiples(); | 152 segment.checkMultiples(); |
| 153 fMultiples |= segment.hasMultiples(); |
130 } | 154 } |
131 } | 155 } |
132 } | 156 } |
133 | 157 |
134 void checkSmall() { | 158 void checkSmall() { |
135 int segmentCount = fSegments.count(); | 159 int segmentCount = fSegments.count(); |
136 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { | 160 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { |
137 SkOpSegment& segment = fSegments[sIndex]; | 161 SkOpSegment& segment = fSegments[sIndex]; |
| 162 // OPTIMIZATION : skip segments that are done? |
138 if (segment.hasSmall()) { | 163 if (segment.hasSmall()) { |
139 segment.checkSmall(); | 164 segment.checkSmall(); |
140 } | 165 } |
141 } | 166 } |
142 } | 167 } |
143 | 168 |
144 // if same point has different T values, choose a common T | 169 // if same point has different T values, choose a common T |
145 void checkTiny() { | 170 void checkTiny() { |
146 int segmentCount = fSegments.count(); | 171 int segmentCount = fSegments.count(); |
147 if (segmentCount <= 2) { | 172 if (segmentCount <= 2) { |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
182 return segment.pts()[SkPathOpsVerbToPoints(segment.verb())]; | 207 return segment.pts()[SkPathOpsVerbToPoints(segment.verb())]; |
183 } | 208 } |
184 | 209 |
185 void fixOtherTIndex() { | 210 void fixOtherTIndex() { |
186 int segmentCount = fSegments.count(); | 211 int segmentCount = fSegments.count(); |
187 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { | 212 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { |
188 fSegments[sIndex].fixOtherTIndex(); | 213 fSegments[sIndex].fixOtherTIndex(); |
189 } | 214 } |
190 } | 215 } |
191 | 216 |
| 217 bool hasMultiples() const { |
| 218 return fMultiples; |
| 219 } |
| 220 |
192 void joinCoincidence() { | 221 void joinCoincidence() { |
193 joinCoincidence(fCoincidences, false); | 222 joinCoincidence(fCoincidences, false); |
194 joinCoincidence(fPartialCoincidences, true); | 223 joinCoincidence(fPartialCoincidences, true); |
195 } | 224 } |
196 | 225 |
197 SkOpSegment* nonVerticalSegment(int* start, int* end); | 226 SkOpSegment* nonVerticalSegment(int* start, int* end); |
198 | 227 |
199 bool operand() const { | 228 bool operand() const { |
200 return fOperand; | 229 return fOperand; |
201 } | 230 } |
202 | 231 |
203 void reset() { | 232 void reset() { |
204 fSegments.reset(); | 233 fSegments.reset(); |
205 fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax); | 234 fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax); |
206 fContainsCurves = fContainsCubics = fContainsIntercepts = fDone = false; | 235 fContainsCurves = fContainsCubics = fContainsIntercepts = fDone = fMulti
ples = false; |
207 } | 236 } |
208 | 237 |
| 238 void resolveNearCoincidence(); |
| 239 |
209 SkTArray<SkOpSegment>& segments() { | 240 SkTArray<SkOpSegment>& segments() { |
210 return fSegments; | 241 return fSegments; |
211 } | 242 } |
212 | 243 |
213 void setContainsIntercepts() { | 244 void setContainsIntercepts() { |
214 fContainsIntercepts = true; | 245 fContainsIntercepts = true; |
215 } | 246 } |
216 | 247 |
217 void setOperand(bool isOp) { | 248 void setOperand(bool isOp) { |
218 fOperand = isOp; | 249 fOperand = isOp; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 #endif | 308 #endif |
278 | 309 |
279 #if DEBUG_SHOW_WINDING | 310 #if DEBUG_SHOW_WINDING |
280 int debugShowWindingValues(int totalSegments, int ofInterest); | 311 int debugShowWindingValues(int totalSegments, int ofInterest); |
281 static void debugShowWindingValues(const SkTArray<SkOpContour*, true>& conto
urList); | 312 static void debugShowWindingValues(const SkTArray<SkOpContour*, true>& conto
urList); |
282 #endif | 313 #endif |
283 | 314 |
284 // available to test routines only | 315 // available to test routines only |
285 void dump() const; | 316 void dump() const; |
286 void dumpAngles() const; | 317 void dumpAngles() const; |
| 318 void dumpCoincidence(const SkCoincidence& ) const; |
| 319 void dumpCoincidences() const; |
| 320 void dumpPt(int ) const; |
287 void dumpPts() const; | 321 void dumpPts() const; |
| 322 void dumpSpan(int ) const; |
288 void dumpSpans() const; | 323 void dumpSpans() const; |
289 | 324 |
290 private: | 325 private: |
| 326 void alignPt(int index, SkPoint* point, int zeroPt) const; |
| 327 int alignT(bool swap, int tIndex, SkIntersections* ts) const; |
291 void calcCommonCoincidentWinding(const SkCoincidence& ); | 328 void calcCommonCoincidentWinding(const SkCoincidence& ); |
| 329 void checkCoincidentPair(const SkCoincidence& oneCoin, int oneIdx, |
| 330 const SkCoincidence& twoCoin, int twoIdx, bool part
ial); |
292 void joinCoincidence(const SkTArray<SkCoincidence, true>& , bool partial); | 331 void joinCoincidence(const SkTArray<SkCoincidence, true>& , bool partial); |
293 void setBounds(); | 332 void setBounds(); |
294 | 333 |
295 SkTArray<SkOpSegment> fSegments; | 334 SkTArray<SkOpSegment> fSegments; |
296 SkTArray<SkOpSegment*, true> fSortedSegments; | 335 SkTArray<SkOpSegment*, true> fSortedSegments; |
297 int fFirstSorted; | 336 int fFirstSorted; |
298 SkTArray<SkCoincidence, true> fCoincidences; | 337 SkTArray<SkCoincidence, true> fCoincidences; |
299 SkTArray<SkCoincidence, true> fPartialCoincidences; | 338 SkTArray<SkCoincidence, true> fPartialCoincidences; |
300 SkTArray<const SkOpContour*, true> fCrosses; | 339 SkTArray<const SkOpContour*, true> fCrosses; |
301 SkPathOpsBounds fBounds; | 340 SkPathOpsBounds fBounds; |
302 bool fContainsIntercepts; // FIXME: is this used by anybody? | 341 bool fContainsIntercepts; // FIXME: is this used by anybody? |
303 bool fContainsCubics; | 342 bool fContainsCubics; |
304 bool fContainsCurves; | 343 bool fContainsCurves; |
305 bool fDone; | 344 bool fDone; |
| 345 bool fMultiples; // set if some segment has multiple identical intersection
s with other curves |
306 bool fOperand; // true for the second argument to a binary operator | 346 bool fOperand; // true for the second argument to a binary operator |
307 bool fXor; | 347 bool fXor; |
308 bool fOppXor; | 348 bool fOppXor; |
309 #if defined(SK_DEBUG) || !FORCE_RELEASE | 349 #if defined(SK_DEBUG) || !FORCE_RELEASE |
310 int debugID() const { return fID; } | 350 int debugID() const { return fID; } |
311 int fID; | 351 int fID; |
312 #else | 352 #else |
313 int debugID() const { return -1; } | 353 int debugID() const { return -1; } |
314 #endif | 354 #endif |
315 }; | 355 }; |
316 | 356 |
317 #endif | 357 #endif |
OLD | NEW |