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 class SkIntersections; | 13 class SkIntersections; |
14 class SkOpContour; | 14 class SkOpContour; |
15 class SkPathWriter; | 15 class SkPathWriter; |
16 | 16 |
17 struct SkCoincidence { | 17 struct SkCoincidence { |
18 SkOpContour* fOther; | 18 SkOpContour* fOther; |
19 int fSegments[2]; | 19 int fSegments[2]; |
20 double fTs[2][2]; | 20 double fTs[2][2]; |
21 SkPoint fPts[2]; | 21 SkPoint fPts[2]; |
22 }; | 22 }; |
23 | 23 |
24 class SkOpContour { | 24 class SkOpContour { |
25 public: | 25 public: |
26 SkOpContour() { | 26 SkOpContour() { |
27 reset(); | 27 reset(); |
28 #ifdef SK_DEBUG | 28 #if defined(SK_DEBUG) || !FORCE_RELEASE |
29 fID = ++SkPathOpsDebug::gContourID; | 29 fID = ++SkPathOpsDebug::gContourID; |
30 #endif | 30 #endif |
31 } | 31 } |
32 | 32 |
33 bool operator<(const SkOpContour& rh) const { | 33 bool operator<(const SkOpContour& rh) const { |
34 return fBounds.fTop == rh.fBounds.fTop | 34 return fBounds.fTop == rh.fBounds.fTop |
35 ? fBounds.fLeft < rh.fBounds.fLeft | 35 ? fBounds.fLeft < rh.fBounds.fLeft |
36 : fBounds.fTop < rh.fBounds.fTop; | 36 : fBounds.fTop < rh.fBounds.fTop; |
37 } | 37 } |
38 | 38 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 fSegments.push_back().addQuad(pts, fOperand, fXor); | 70 fSegments.push_back().addQuad(pts, fOperand, fXor); |
71 fContainsCurves = true; | 71 fContainsCurves = true; |
72 return fSegments.count(); | 72 return fSegments.count(); |
73 } | 73 } |
74 | 74 |
75 int addT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt
, double newT) { | 75 int addT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint& pt
, double newT) { |
76 setContainsIntercepts(); | 76 setContainsIntercepts(); |
77 return fSegments[segIndex].addT(&other->fSegments[otherIndex], pt, newT)
; | 77 return fSegments[segIndex].addT(&other->fSegments[otherIndex], pt, newT)
; |
78 } | 78 } |
79 | 79 |
80 int addSelfT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint
& pt, double newT) { | 80 int addSelfT(int segIndex, const SkPoint& pt, double newT) { |
81 setContainsIntercepts(); | 81 setContainsIntercepts(); |
82 return fSegments[segIndex].addSelfT(&other->fSegments[otherIndex], pt, n
ewT); | 82 return fSegments[segIndex].addSelfT(pt, newT); |
83 } | 83 } |
84 | 84 |
85 const SkPathOpsBounds& bounds() const { | 85 const SkPathOpsBounds& bounds() const { |
86 return fBounds; | 86 return fBounds; |
87 } | 87 } |
88 | 88 |
| 89 bool calcAngles(); |
89 void calcCoincidentWinding(); | 90 void calcCoincidentWinding(); |
90 void calcPartialCoincidentWinding(); | 91 void calcPartialCoincidentWinding(); |
91 | 92 |
| 93 void checkDuplicates() { |
| 94 int segmentCount = fSegments.count(); |
| 95 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { |
| 96 SkOpSegment& segment = fSegments[sIndex]; |
| 97 if (segment.count() > 2) { |
| 98 segment.checkDuplicates(); |
| 99 } |
| 100 } |
| 101 } |
| 102 |
92 void checkEnds() { | 103 void checkEnds() { |
93 if (!fContainsCurves) { | 104 if (!fContainsCurves) { |
94 return; | 105 return; |
95 } | 106 } |
96 int segmentCount = fSegments.count(); | 107 int segmentCount = fSegments.count(); |
97 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { | 108 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { |
98 SkOpSegment* segment = &fSegments[sIndex]; | 109 SkOpSegment* segment = &fSegments[sIndex]; |
99 if (segment->verb() == SkPath::kLine_Verb) { | 110 if (segment->verb() == SkPath::kLine_Verb) { |
100 continue; | 111 continue; |
101 } | 112 } |
102 if (segment->done()) { | 113 if (segment->done()) { |
103 continue; // likely coincident, nothing to do | 114 continue; // likely coincident, nothing to do |
104 } | 115 } |
105 segment->checkEnds(); | 116 segment->checkEnds(); |
106 } | 117 } |
107 } | 118 } |
108 | 119 |
| 120 void checkMultiples() { |
| 121 int segmentCount = fSegments.count(); |
| 122 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { |
| 123 SkOpSegment& segment = fSegments[sIndex]; |
| 124 if (segment.count() > 2) { |
| 125 segment.checkMultiples(); |
| 126 } |
| 127 } |
| 128 } |
| 129 |
| 130 void checkSmall() { |
| 131 int segmentCount = fSegments.count(); |
| 132 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { |
| 133 SkOpSegment& segment = fSegments[sIndex]; |
| 134 if (segment.hasSmall()) { |
| 135 segment.checkSmall(); |
| 136 } |
| 137 } |
| 138 } |
| 139 |
109 // if same point has different T values, choose a common T | 140 // if same point has different T values, choose a common T |
110 void checkTiny() { | 141 void checkTiny() { |
111 int segmentCount = fSegments.count(); | 142 int segmentCount = fSegments.count(); |
112 if (segmentCount <= 2) { | 143 if (segmentCount <= 2) { |
113 return; | 144 return; |
114 } | 145 } |
115 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { | 146 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { |
116 fSegments[sIndex].checkTiny(); | 147 SkOpSegment& segment = fSegments[sIndex]; |
| 148 if (segment.hasTiny()) { |
| 149 segment.checkTiny(); |
| 150 } |
117 } | 151 } |
118 } | 152 } |
119 | 153 |
120 void complete() { | 154 void complete() { |
121 setBounds(); | 155 setBounds(); |
122 fContainsIntercepts = false; | 156 fContainsIntercepts = false; |
123 } | 157 } |
124 | 158 |
125 bool containsCubics() const { | 159 bool containsCubics() const { |
126 return fContainsCubics; | 160 return fContainsCubics; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 int segmentCount = fSegments.count(); | 219 int segmentCount = fSegments.count(); |
186 for (int test = 0; test < segmentCount; ++test) { | 220 for (int test = 0; test < segmentCount; ++test) { |
187 fSegments[test].setOppXor(isOppXor); | 221 fSegments[test].setOppXor(isOppXor); |
188 } | 222 } |
189 } | 223 } |
190 | 224 |
191 void setXor(bool isXor) { | 225 void setXor(bool isXor) { |
192 fXor = isXor; | 226 fXor = isXor; |
193 } | 227 } |
194 | 228 |
| 229 void sortAngles(); |
195 void sortSegments(); | 230 void sortSegments(); |
196 | 231 |
197 const SkPoint& start() const { | 232 const SkPoint& start() const { |
198 return fSegments.front().pts()[0]; | 233 return fSegments.front().pts()[0]; |
199 } | 234 } |
200 | 235 |
201 void toPath(SkPathWriter* path) const; | 236 void toPath(SkPathWriter* path) const; |
202 | 237 |
203 void toPartialBackward(SkPathWriter* path) const { | 238 void toPartialBackward(SkPathWriter* path) const { |
204 int segmentCount = fSegments.count(); | 239 int segmentCount = fSegments.count(); |
(...skipping 30 matching lines...) Expand all Loading... |
235 fSegments[index].debugShowActiveSpans(); | 270 fSegments[index].debugShowActiveSpans(); |
236 } | 271 } |
237 } | 272 } |
238 #endif | 273 #endif |
239 | 274 |
240 #if DEBUG_SHOW_WINDING | 275 #if DEBUG_SHOW_WINDING |
241 int debugShowWindingValues(int totalSegments, int ofInterest); | 276 int debugShowWindingValues(int totalSegments, int ofInterest); |
242 static void debugShowWindingValues(const SkTArray<SkOpContour*, true>& conto
urList); | 277 static void debugShowWindingValues(const SkTArray<SkOpContour*, true>& conto
urList); |
243 #endif | 278 #endif |
244 | 279 |
| 280 // available to test routines only |
| 281 void dump() const; |
| 282 void dumpAngles() const; |
| 283 void dumpPts() const; |
| 284 void dumpSpans() const; |
| 285 |
245 private: | 286 private: |
246 void calcCommonCoincidentWinding(const SkCoincidence& ); | 287 void calcCommonCoincidentWinding(const SkCoincidence& ); |
247 void joinCoincidence(const SkTArray<SkCoincidence, true>& , bool partial); | 288 void joinCoincidence(const SkTArray<SkCoincidence, true>& , bool partial); |
248 void setBounds(); | 289 void setBounds(); |
249 | 290 |
250 SkTArray<SkOpSegment> fSegments; | 291 SkTArray<SkOpSegment> fSegments; |
251 SkTArray<SkOpSegment*, true> fSortedSegments; | 292 SkTArray<SkOpSegment*, true> fSortedSegments; |
252 int fFirstSorted; | 293 int fFirstSorted; |
253 SkTArray<SkCoincidence, true> fCoincidences; | 294 SkTArray<SkCoincidence, true> fCoincidences; |
254 SkTArray<SkCoincidence, true> fPartialCoincidences; | 295 SkTArray<SkCoincidence, true> fPartialCoincidences; |
255 SkTArray<const SkOpContour*, true> fCrosses; | 296 SkTArray<const SkOpContour*, true> fCrosses; |
256 SkPathOpsBounds fBounds; | 297 SkPathOpsBounds fBounds; |
257 bool fContainsIntercepts; // FIXME: is this used by anybody? | 298 bool fContainsIntercepts; // FIXME: is this used by anybody? |
258 bool fContainsCubics; | 299 bool fContainsCubics; |
259 bool fContainsCurves; | 300 bool fContainsCurves; |
260 bool fDone; | 301 bool fDone; |
261 bool fOperand; // true for the second argument to a binary operator | 302 bool fOperand; // true for the second argument to a binary operator |
262 bool fXor; | 303 bool fXor; |
263 bool fOppXor; | 304 bool fOppXor; |
264 #ifdef SK_DEBUG | 305 #if defined(SK_DEBUG) || !FORCE_RELEASE |
| 306 int debugID() const { return fID; } |
265 int fID; | 307 int fID; |
| 308 #else |
| 309 int debugID() const { return -1; } |
266 #endif | 310 #endif |
267 }; | 311 }; |
268 | 312 |
269 #endif | 313 #endif |
OLD | NEW |