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* fContours[2]; | 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 #if DEBUG_DUMP | 28 #ifdef SK_DEBUG |
29 fID = ++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 |
39 void addCoincident(int index, SkOpContour* other, int otherIndex, | 39 void addCoincident(int index, SkOpContour* other, int otherIndex, |
(...skipping 16 matching lines...) Expand all Loading... |
56 | 56 |
57 int addLine(const SkPoint pts[2]) { | 57 int addLine(const SkPoint pts[2]) { |
58 fSegments.push_back().addLine(pts, fOperand, fXor); | 58 fSegments.push_back().addLine(pts, fOperand, fXor); |
59 return fSegments.count(); | 59 return fSegments.count(); |
60 } | 60 } |
61 | 61 |
62 void addOtherT(int segIndex, int tIndex, double otherT, int otherIndex) { | 62 void addOtherT(int segIndex, int tIndex, double otherT, int otherIndex) { |
63 fSegments[segIndex].addOtherT(tIndex, otherT, otherIndex); | 63 fSegments[segIndex].addOtherT(tIndex, otherT, otherIndex); |
64 } | 64 } |
65 | 65 |
| 66 void addPartialCoincident(int index, SkOpContour* other, int otherIndex, |
| 67 const SkIntersections& ts, int ptIndex, bool swap); |
| 68 |
66 int addQuad(const SkPoint pts[3]) { | 69 int addQuad(const SkPoint pts[3]) { |
67 fSegments.push_back().addQuad(pts, fOperand, fXor); | 70 fSegments.push_back().addQuad(pts, fOperand, fXor); |
68 fContainsCurves = true; | 71 fContainsCurves = true; |
69 return fSegments.count(); | 72 return fSegments.count(); |
70 } | 73 } |
71 | 74 |
72 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 bool isNear) { |
73 setContainsIntercepts(); | 77 setContainsIntercepts(); |
74 return fSegments[segIndex].addT(&other->fSegments[otherIndex], pt, newT)
; | 78 return fSegments[segIndex].addT(&other->fSegments[otherIndex], pt, newT,
isNear); |
75 } | 79 } |
76 | 80 |
77 int addSelfT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint
& pt, double newT) { | 81 int addSelfT(int segIndex, SkOpContour* other, int otherIndex, const SkPoint
& pt, double newT) { |
78 setContainsIntercepts(); | 82 setContainsIntercepts(); |
79 return fSegments[segIndex].addSelfT(&other->fSegments[otherIndex], pt, n
ewT); | 83 return fSegments[segIndex].addSelfT(&other->fSegments[otherIndex], pt, n
ewT); |
80 } | 84 } |
81 | 85 |
82 int addUnsortableT(int segIndex, SkOpContour* other, int otherIndex, bool st
art, | |
83 const SkPoint& pt, double newT) { | |
84 return fSegments[segIndex].addUnsortableT(&other->fSegments[otherIndex],
start, pt, newT); | |
85 } | |
86 | |
87 const SkPathOpsBounds& bounds() const { | 86 const SkPathOpsBounds& bounds() const { |
88 return fBounds; | 87 return fBounds; |
89 } | 88 } |
90 | 89 |
91 void calcCoincidentWinding(); | 90 void calcCoincidentWinding(); |
| 91 void calcPartialCoincidentWinding(); |
92 | 92 |
93 void checkEnds() { | 93 void checkEnds() { |
94 if (!fContainsCurves) { | 94 if (!fContainsCurves) { |
95 return; | 95 return; |
96 } | 96 } |
97 int segmentCount = fSegments.count(); | 97 int segmentCount = fSegments.count(); |
98 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { | 98 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { |
99 SkOpSegment* segment = &fSegments[sIndex]; | 99 SkOpSegment* segment = &fSegments[sIndex]; |
100 if (segment->verb() == SkPath::kLine_Verb) { | 100 if (segment->verb() == SkPath::kLine_Verb) { |
101 continue; | 101 continue; |
102 } | 102 } |
103 fSegments[sIndex].checkEnds(); | 103 segment->checkEnds(); |
104 } | 104 } |
105 } | 105 } |
106 | 106 |
| 107 // if same point has different T values, choose a common T |
| 108 void checkTiny() { |
| 109 int segmentCount = fSegments.count(); |
| 110 if (segmentCount <= 2) { |
| 111 return; |
| 112 } |
| 113 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { |
| 114 fSegments[sIndex].checkTiny(); |
| 115 } |
| 116 } |
| 117 |
107 void complete() { | 118 void complete() { |
108 setBounds(); | 119 setBounds(); |
109 fContainsIntercepts = false; | 120 fContainsIntercepts = false; |
110 } | 121 } |
111 | 122 |
112 bool containsCubics() const { | 123 bool containsCubics() const { |
113 return fContainsCubics; | 124 return fContainsCubics; |
114 } | 125 } |
115 | 126 |
116 bool crosses(const SkOpContour* crosser) const { | 127 bool crosses(const SkOpContour* crosser) const { |
117 for (int index = 0; index < fCrosses.count(); ++index) { | 128 for (int index = 0; index < fCrosses.count(); ++index) { |
118 if (fCrosses[index] == crosser) { | 129 if (fCrosses[index] == crosser) { |
119 return true; | 130 return true; |
120 } | 131 } |
121 } | 132 } |
122 return false; | 133 return false; |
123 } | 134 } |
124 | 135 |
125 bool done() const { | 136 bool done() const { |
126 return fDone; | 137 return fDone; |
127 } | 138 } |
128 | 139 |
129 const SkPoint& end() const { | 140 const SkPoint& end() const { |
130 const SkOpSegment& segment = fSegments.back(); | 141 const SkOpSegment& segment = fSegments.back(); |
131 return segment.pts()[SkPathOpsVerbToPoints(segment.verb())]; | 142 return segment.pts()[SkPathOpsVerbToPoints(segment.verb())]; |
132 } | 143 } |
133 | 144 |
134 void findTooCloseToCall() { | |
135 int segmentCount = fSegments.count(); | |
136 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { | |
137 fSegments[sIndex].findTooCloseToCall(); | |
138 } | |
139 } | |
140 | |
141 void fixOtherTIndex() { | 145 void fixOtherTIndex() { |
142 int segmentCount = fSegments.count(); | 146 int segmentCount = fSegments.count(); |
143 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { | 147 for (int sIndex = 0; sIndex < segmentCount; ++sIndex) { |
144 fSegments[sIndex].fixOtherTIndex(); | 148 fSegments[sIndex].fixOtherTIndex(); |
145 } | 149 } |
146 } | 150 } |
147 | 151 |
148 SkOpSegment* nonVerticalSegment(int* start, int* end); | 152 SkOpSegment* nonVerticalSegment(int* start, int* end); |
149 | 153 |
150 bool operand() const { | 154 bool operand() const { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 } | 229 } |
226 } | 230 } |
227 #endif | 231 #endif |
228 | 232 |
229 #if DEBUG_SHOW_WINDING | 233 #if DEBUG_SHOW_WINDING |
230 int debugShowWindingValues(int totalSegments, int ofInterest); | 234 int debugShowWindingValues(int totalSegments, int ofInterest); |
231 static void debugShowWindingValues(const SkTArray<SkOpContour*, true>& conto
urList); | 235 static void debugShowWindingValues(const SkTArray<SkOpContour*, true>& conto
urList); |
232 #endif | 236 #endif |
233 | 237 |
234 private: | 238 private: |
| 239 void calcCommonCoincidentWinding(const SkCoincidence& coincidence); |
235 void setBounds(); | 240 void setBounds(); |
236 | 241 |
237 SkTArray<SkOpSegment> fSegments; | 242 SkTArray<SkOpSegment> fSegments; |
238 SkTArray<SkOpSegment*, true> fSortedSegments; | 243 SkTArray<SkOpSegment*, true> fSortedSegments; |
239 int fFirstSorted; | 244 int fFirstSorted; |
240 SkTArray<SkCoincidence, true> fCoincidences; | 245 SkTArray<SkCoincidence, true> fCoincidences; |
| 246 SkTArray<SkCoincidence, true> fPartialCoincidences; |
241 SkTArray<const SkOpContour*, true> fCrosses; | 247 SkTArray<const SkOpContour*, true> fCrosses; |
242 SkPathOpsBounds fBounds; | 248 SkPathOpsBounds fBounds; |
243 bool fContainsIntercepts; // FIXME: is this used by anybody? | 249 bool fContainsIntercepts; // FIXME: is this used by anybody? |
244 bool fContainsCubics; | 250 bool fContainsCubics; |
245 bool fContainsCurves; | 251 bool fContainsCurves; |
246 bool fDone; | 252 bool fDone; |
247 bool fOperand; // true for the second argument to a binary operator | 253 bool fOperand; // true for the second argument to a binary operator |
248 bool fXor; | 254 bool fXor; |
249 bool fOppXor; | 255 bool fOppXor; |
250 #if DEBUG_DUMP | 256 #ifdef SK_DEBUG |
251 int fID; | 257 int fID; |
252 #endif | 258 #endif |
253 }; | 259 }; |
254 | 260 |
255 #endif | 261 #endif |
OLD | NEW |