Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(372)

Side by Side Diff: src/pathops/SkOpSegment.h

Issue 1037573004: cumulative pathops patch (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix pathopsinverse gm Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pathops/SkOpEdgeBuilder.cpp ('k') | src/pathops/SkOpSegment.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "SkOpTAllocator.h"
12 #include "SkPathOpsBounds.h" 13 #include "SkPathOpsBounds.h"
13 #include "SkPathOpsCurve.h" 14 #include "SkPathOpsCurve.h"
14 #include "SkTArray.h" 15
15 #include "SkTDArray.h" 16 class SkOpCoincidence;
16 17 class SkOpContour;
17 #if defined(SK_DEBUG) || !FORCE_RELEASE
18 #include "SkThread.h"
19 #endif
20
21 struct SkCoincidence;
22 class SkPathWriter; 18 class SkPathWriter;
23 19
24 class SkOpSegment { 20 class SkOpSegment {
25 public: 21 public:
26 SkOpSegment() { 22 enum AllowAlias {
27 #if defined(SK_DEBUG) || !FORCE_RELEASE 23 kAllowAlias,
28 fID = sk_atomic_inc(&SkPathOpsDebug::gSegmentID); 24 kNoAlias
29 #endif 25 };
30 }
31 26
32 bool operator<(const SkOpSegment& rh) const { 27 bool operator<(const SkOpSegment& rh) const {
33 return fBounds.fTop < rh.fBounds.fTop; 28 return fBounds.fTop < rh.fBounds.fTop;
34 } 29 }
35 30
36 struct AlignedSpan { 31 SkOpAngle* activeAngle(SkOpSpanBase* start, SkOpSpanBase** startPtr, SkOpSpa nBase** endPtr,
37 double fOldT; 32 bool* done, bool* sortable);
38 double fT; 33 SkOpAngle* activeAngleInner(SkOpSpanBase* start, SkOpSpanBase** startPtr,
39 SkPoint fOldPt; 34 SkOpSpanBase** endPtr, bool* done, bool* sortable);
40 SkPoint fPt; 35 SkOpAngle* activeAngleOther(SkOpSpanBase* start, SkOpSpanBase** startPtr,
41 const SkOpSegment* fSegment; 36 SkOpSpanBase** endPtr, bool* done, bool* sortable);
42 const SkOpSegment* fOther1; 37 bool activeOp(SkOpSpanBase* start, SkOpSpanBase* end, int xorMiMask, int xor SuMask,
43 const SkOpSegment* fOther2; 38 SkPathOp op);
44 }; 39 bool activeOp(int xorMiMask, int xorSuMask, SkOpSpanBase* start, SkOpSpanBas e* end, SkPathOp op,
40 int* sumMiWinding, int* sumSuWinding);
41
42 SkPoint activeLeftTop(SkOpSpanBase** firstT);
43
44 bool activeWinding(SkOpSpanBase* start, SkOpSpanBase* end);
45 bool activeWinding(SkOpSpanBase* start, SkOpSpanBase* end, int* sumWinding);
46
47 void addCubic(SkPoint pts[4], SkOpContour* parent) {
48 init(pts, parent, SkPath::kCubic_Verb);
49 fBounds.setCubicBounds(pts);
50 }
51
52 void addCurveTo(const SkOpSpanBase* start, const SkOpSpanBase* end, SkPathWr iter* path,
53 bool active) const;
54
55 SkOpAngle* addEndSpan(SkChunkAlloc* allocator) {
56 SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate(allocator);
57 angle->set(&fTail, fTail.prev());
58 fTail.setFromAngle(angle);
59 return angle;
60 }
61
62 void addLine(SkPoint pts[2], SkOpContour* parent) {
63 init(pts, parent, SkPath::kLine_Verb);
64 fBounds.set(pts, 2);
65 }
66
67 SkOpPtT* addMissing(double t, SkOpSegment* opp, SkChunkAlloc* );
68 SkOpAngle* addSingletonAngleDown(SkOpSegment** otherPtr, SkOpAngle** , SkChu nkAlloc* );
69 SkOpAngle* addSingletonAngles(int step, SkChunkAlloc* );
70 SkOpAngle* addSingletonAngleUp(SkOpSegment** otherPtr, SkOpAngle** , SkChunk Alloc* );
71
72 SkOpAngle* addStartSpan(SkChunkAlloc* allocator) {
73 SkOpAngle* angle = SkOpTAllocator<SkOpAngle>::Allocate(allocator);
74 angle->set(&fHead, fHead.next());
75 fHead.setToAngle(angle);
76 return angle;
77 }
78
79 void addQuad(SkPoint pts[3], SkOpContour* parent) {
80 init(pts, parent, SkPath::kQuad_Verb);
81 fBounds.setQuadBounds(pts);
82 }
83
84 SkOpPtT* addT(double t, AllowAlias , SkChunkAlloc* );
85
86 void align();
87 static bool BetweenTs(const SkOpSpanBase* lesser, double testT, const SkOpSp anBase* greater);
45 88
46 const SkPathOpsBounds& bounds() const { 89 const SkPathOpsBounds& bounds() const {
47 return fBounds; 90 return fBounds;
48 } 91 }
49 92
50 // OPTIMIZE 93 void bumpCount() {
51 // when the edges are initially walked, they don't automatically get the pri or and next 94 ++fCount;
52 // edges assigned to positions t=0 and t=1. Doing that would remove the need for this check, 95 }
53 // and would additionally remove the need for similar checks in condition ed ges. It would 96
54 // also allow intersection code to assume end of segment intersections (mayb e?) 97 void calcAngles(SkChunkAlloc*);
55 bool complete() const { 98 void checkAngleCoin(SkOpCoincidence* coincidences, SkChunkAlloc* allocator);
56 int count = fTs.count(); 99 void checkNearCoincidence(SkOpAngle* );
57 return count > 1 && fTs[0].fT == 0 && fTs[--count].fT == 1; 100 bool clockwise(const SkOpSpanBase* start, const SkOpSpanBase* end, bool* swa p) const;
101 static void ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle,
102 SkOpAngle::IncludeType );
103 static void ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* next Angle,
104 SkOpAngle::IncludeType );
105 int computeSum(SkOpSpanBase* start, SkOpSpanBase* end, SkOpAngle::IncludeTyp e includeType);
106
107 SkOpContour* contour() const {
108 return fContour;
58 } 109 }
59 110
60 int count() const { 111 int count() const {
61 return fTs.count(); 112 return fCount;
62 } 113 }
114
115 SkOpSpan* crossedSpanY(const SkPoint& basePt, double mid, bool opp, bool cur rent,
116 SkScalar* bestY, double* hitT, bool* hitSomething, b ool* vertical);
117
118 void debugAddAngle(double startT, double endT, SkChunkAlloc*);
119 const SkOpAngle* debugAngle(int id) const;
120 SkOpContour* debugContour(int id);
121
122 int debugID() const {
123 return PATH_OPS_DEBUG_RELEASE(fID, -1);
124 }
125
126 #if DEBUG_SWAP_TOP
127 int debugInflections(const SkOpSpanBase* start, const SkOpSpanBase* end) con st;
128 #endif
129
130 SkOpAngle* debugLastAngle();
131 const SkOpPtT* debugPtT(int id) const;
132 void debugReset();
133 const SkOpSegment* debugSegment(int id) const;
134
135 #if DEBUG_ACTIVE_SPANS
136 void debugShowActiveSpans() const;
137 #endif
138 #if DEBUG_MARK_DONE
139 void debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding) ;
140 void debugShowNewWinding(const char* fun, const SkOpSpan* span, int winding, int oppWinding);
141 #endif
142
143 const SkOpSpanBase* debugSpan(int id) const;
144 void debugValidate() const;
145 void detach(const SkOpSpan* );
146 double distSq(double t, SkOpAngle* opp);
63 147
64 bool done() const { 148 bool done() const {
65 SkASSERT(fDoneSpans <= fTs.count()); 149 SkASSERT(fDoneCount <= fCount);
66 return fDoneSpans == fTs.count(); 150 return fDoneCount == fCount;
67 }
68
69 bool done(int min) const {
70 return fTs[min].fDone;
71 } 151 }
72 152
73 bool done(const SkOpAngle* angle) const { 153 bool done(const SkOpAngle* angle) const {
74 return done(SkMin32(angle->start(), angle->end())); 154 return angle->start()->starter(angle->end())->done();
75 } 155 }
76 156
77 SkDPoint dPtAtT(double mid) const { 157 SkDPoint dPtAtT(double mid) const {
78 return (*CurveDPointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid); 158 return (*CurveDPointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid);
79 } 159 }
80 160
81 SkVector dxdy(int index) const { 161 SkDVector dSlopeAtT(double mid) const {
82 return (*CurveSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, fTs[index].f T); 162 return (*CurveDSlopeAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid);
83 } 163 }
84 164
85 SkScalar dy(int index) const { 165 void dump() const;
86 return dxdy(index).fY; 166 void dumpAll() const;
87 } 167 void dumpAngles() const;
88 168 void dumpCoin() const;
89 bool hasMultiples() const { 169 void dumpPts() const;
90 return fMultiples; 170
91 } 171 SkOpSegment* findNextOp(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** next Start,
92 172 SkOpSpanBase** nextEnd, bool* unsortable, SkPathOp op,
93 bool hasSmall() const { 173 int xorMiMask, int xorSuMask);
94 return fSmall; 174 SkOpSegment* findNextWinding(SkTDArray<SkOpSpanBase*>* chase, SkOpSpanBase** nextStart,
95 } 175 SkOpSpanBase** nextEnd, bool* unsortable);
96 176 SkOpSegment* findNextXor(SkOpSpanBase** nextStart, SkOpSpanBase** nextEnd, b ool* unsortable);
97 bool hasTiny() const { 177 SkOpSegment* findTop(bool firstPass, SkOpSpanBase** startPtr, SkOpSpanBase** endPtr,
98 return fTiny; 178 bool* unsortable, SkChunkAlloc* );
99 } 179 SkOpGlobalState* globalState() const;
100 180
101 bool intersected() const { 181 const SkOpSpan* head() const {
102 return fTs.count() > 0; 182 return &fHead;
103 } 183 }
104 184
105 bool isCanceled(int tIndex) const { 185 SkOpSpan* head() {
106 return fTs[tIndex].fWindValue == 0 && fTs[tIndex].fOppValue == 0; 186 return &fHead;
107 } 187 }
108 188
109 bool isConnected(int startIndex, int endIndex) const { 189 void init(SkPoint pts[], SkOpContour* parent, SkPath::Verb verb);
110 return fTs[startIndex].fWindSum != SK_MinS32 || fTs[endIndex].fWindSum ! = SK_MinS32; 190 void initWinding(SkOpSpanBase* start, SkOpSpanBase* end,
111 } 191 SkOpAngle::IncludeType angleIncludeType);
192 bool initWinding(SkOpSpanBase* start, SkOpSpanBase* end, double tHit, int wi nding,
193 SkScalar hitDx, int oppWind, SkScalar hitOppDx);
194
195 SkOpSpan* insert(SkOpSpan* prev, SkChunkAlloc* allocator) {
196 SkOpSpan* result = SkOpTAllocator<SkOpSpan>::Allocate(allocator);
197 SkOpSpanBase* next = prev->next();
198 result->setPrev(prev);
199 prev->setNext(result);
200 SkDEBUGCODE(result->ptT()->fT = 0);
201 result->setNext(next);
202 if (next) {
203 next->setPrev(result);
204 }
205 return result;
206 }
207
208 bool isClose(double t, const SkOpSegment* opp) const;
112 209
113 bool isHorizontal() const { 210 bool isHorizontal() const {
114 return fBounds.fTop == fBounds.fBottom; 211 return fBounds.fTop == fBounds.fBottom;
115 } 212 }
116 213
214 SkOpSegment* isSimple(SkOpSpanBase** end, int* step) {
215 return nextChase(end, step, NULL, NULL);
216 }
217
117 bool isVertical() const { 218 bool isVertical() const {
118 return fBounds.fLeft == fBounds.fRight; 219 return fBounds.fLeft == fBounds.fRight;
119 } 220 }
120 221
121 bool isVertical(int start, int end) const { 222 bool isVertical(SkOpSpanBase* start, SkOpSpanBase* end) const {
122 return (*CurveIsVertical[SkPathOpsVerbToPoints(fVerb)])(fPts, start, end ); 223 return (*CurveIsVertical[SkPathOpsVerbToPoints(fVerb)])(fPts, start->t() , end->t());
123 } 224 }
124 225
125 bool operand() const { 226 bool isXor() const;
126 return fOperand; 227
127 } 228 const SkPoint& lastPt() const {
128 229 return fPts[SkPathOpsVerbToPoints(fVerb)];
129 int oppSign(const SkOpAngle* angle) const { 230 }
130 SkASSERT(angle->segment() == this); 231
131 return oppSign(angle->start(), angle->end()); 232 SkOpSpanBase* markAndChaseDone(SkOpSpanBase* start, SkOpSpanBase* end);
132 } 233 bool markAndChaseWinding(SkOpSpanBase* start, SkOpSpanBase* end, int winding ,
133 234 SkOpSpanBase** lastPtr);
134 int oppSign(int startIndex, int endIndex) const { 235 bool markAndChaseWinding(SkOpSpanBase* start, SkOpSpanBase* end, int winding ,
135 int result = startIndex < endIndex ? -fTs[startIndex].fOppValue : fTs[en dIndex].fOppValue; 236 int oppWinding, SkOpSpanBase** lastPtr);
136 #if DEBUG_WIND_BUMP 237 SkOpSpanBase* markAngle(int maxWinding, int sumWinding, const SkOpAngle* ang le);
137 SkDebugf("%s oppSign=%d\n", __FUNCTION__, result); 238 SkOpSpanBase* markAngle(int maxWinding, int sumWinding, int oppMaxWinding, i nt oppSumWinding,
138 #endif 239 const SkOpAngle* angle);
240 void markDone(SkOpSpan* );
241 bool markWinding(SkOpSpan* , int winding);
242 bool markWinding(SkOpSpan* , int winding, int oppWinding);
243 bool match(const SkOpPtT* span, const SkOpSegment* parent, double t, const S kPoint& pt) const;
244 void missingCoincidence(SkOpCoincidence* coincidences, SkChunkAlloc* allocat or);
245 bool monotonicInY(const SkOpSpanBase* start, const SkOpSpanBase* end) const;
246 bool moveNearby();
247
248 SkOpSegment* next() const {
249 return fNext;
250 }
251
252 static bool NextCandidate(SkOpSpanBase* span, SkOpSpanBase** start, SkOpSpan Base** end);
253 SkOpSegment* nextChase(SkOpSpanBase** , int* step, SkOpSpan** , SkOpSpanBase ** last) const;
254 bool operand() const;
255
256 static int OppSign(const SkOpSpanBase* start, const SkOpSpanBase* end) {
257 int result = start->t() < end->t() ? -start->upCast()->oppValue()
258 : end->upCast()->oppValue();
139 return result; 259 return result;
140 } 260 }
141 261
142 int oppSum(int tIndex) const { 262 bool oppXor() const;
143 return fTs[tIndex].fOppSum; 263
144 } 264 const SkOpSegment* prev() const {
145 265 return fPrev;
146 int oppSum(const SkOpAngle* angle) const { 266 }
147 int lesser = SkMin32(angle->start(), angle->end());
148 return fTs[lesser].fOppSum;
149 }
150
151 int oppValue(int tIndex) const {
152 return fTs[tIndex].fOppValue;
153 }
154
155 int oppValue(const SkOpAngle* angle) const {
156 int lesser = SkMin32(angle->start(), angle->end());
157 return fTs[lesser].fOppValue;
158 }
159
160 #if DEBUG_VALIDATE
161 bool oppXor() const {
162 return fOppXor;
163 }
164 #endif
165 267
166 SkPoint ptAtT(double mid) const { 268 SkPoint ptAtT(double mid) const {
167 return (*CurvePointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid); 269 return (*CurvePointAtT[SkPathOpsVerbToPoints(fVerb)])(fPts, mid);
168 } 270 }
169 271
170 const SkPoint* pts() const { 272 const SkPoint* pts() const {
171 return fPts; 273 return fPts;
172 } 274 }
173 275
174 void reset() { 276 bool ptsDisjoint(const SkOpPtT& span, const SkOpPtT& test) const {
175 init(NULL, (SkPath::Verb) -1, false, false); 277 return ptsDisjoint(span.fT, span.fPt, test.fT, test.fPt);
176 fBounds.set(SK_ScalarMax, SK_ScalarMax, SK_ScalarMax, SK_ScalarMax);
177 fTs.reset();
178 } 278 }
179 279
180 bool reversePoints(const SkPoint& p1, const SkPoint& p2) const; 280 bool ptsDisjoint(const SkOpPtT& span, double t, const SkPoint& pt) const {
181 281 return ptsDisjoint(span.fT, span.fPt, t, pt);
182 void setOppXor(bool isOppXor) {
183 fOppXor = isOppXor;
184 } 282 }
185 283
186 void setUpWinding(int index, int endIndex, int* maxWinding, int* sumWinding) { 284 bool ptsDisjoint(double t1, const SkPoint& pt1, double t2, const SkPoint& pt 2) const;
187 int deltaSum = spanSign(index, endIndex); 285
286 void resetVisited() {
287 fVisited = false;
288 }
289
290 void setContour(SkOpContour* contour) {
291 fContour = contour;
292 }
293
294 void setNext(SkOpSegment* next) {
295 fNext = next;
296 }
297
298 void setPrev(SkOpSegment* prev) {
299 fPrev = prev;
300 }
301
302 bool setVisited() {
303 if (fVisited) {
304 return false;
305 }
306 return (fVisited = true);
307 }
308
309 void setUpWinding(SkOpSpanBase* start, SkOpSpanBase* end, int* maxWinding, i nt* sumWinding) {
310 int deltaSum = SpanSign(start, end);
188 *maxWinding = *sumWinding; 311 *maxWinding = *sumWinding;
189 *sumWinding -= deltaSum; 312 *sumWinding -= deltaSum;
190 } 313 }
191 314
192 const SkOpSpan& span(int tIndex) const { 315 void setUpWindings(SkOpSpanBase* start, SkOpSpanBase* end, int* sumMiWinding ,
193 return fTs[tIndex]; 316 int* maxWinding, int* sumWinding);
194 } 317 void setUpWindings(SkOpSpanBase* start, SkOpSpanBase* end, int* sumMiWinding , int* sumSuWinding,
318 int* maxWinding, int* sumWinding, int* oppMaxWinding, int * oppSumWinding);
319 void sortAngles();
195 320
196 const SkOpAngle* spanToAngle(int tStart, int tEnd) const { 321 static int SpanSign(const SkOpSpanBase* start, const SkOpSpanBase* end) {
197 SkASSERT(tStart != tEnd); 322 int result = start->t() < end->t() ? -start->upCast()->windValue()
198 const SkOpSpan& span = fTs[tStart]; 323 : end->upCast()->windValue();
199 return tStart < tEnd ? span.fToAngle : span.fFromAngle;
200 }
201
202 // FIXME: create some sort of macro or template that avoids casting
203 SkOpAngle* spanToAngle(int tStart, int tEnd) {
204 const SkOpAngle* cAngle = (const_cast<const SkOpSegment*>(this))->spanTo Angle(tStart, tEnd);
205 return const_cast<SkOpAngle*>(cAngle);
206 }
207
208 int spanSign(const SkOpAngle* angle) const {
209 SkASSERT(angle->segment() == this);
210 return spanSign(angle->start(), angle->end());
211 }
212
213 int spanSign(int startIndex, int endIndex) const {
214 int result = startIndex < endIndex ? -fTs[startIndex].fWindValue : fTs[e ndIndex].fWindValue;
215 #if DEBUG_WIND_BUMP
216 SkDebugf("%s spanSign=%d\n", __FUNCTION__, result);
217 #endif
218 return result; 324 return result;
219 } 325 }
220 326
221 double t(int tIndex) const { 327 SkOpAngle* spanToAngle(SkOpSpanBase* start, SkOpSpanBase* end) {
222 return fTs[tIndex].fT; 328 SkASSERT(start != end);
329 return start->t() < end->t() ? start->upCast()->toAngle() : start->fromA ngle();
223 } 330 }
224 331
225 double tAtMid(int start, int end, double mid) const { 332 bool subDivide(const SkOpSpanBase* start, const SkOpSpanBase* end, SkPoint e dge[4]) const;
226 return fTs[start].fT * (1 - mid) + fTs[end].fT * mid; 333 bool subDivide(const SkOpSpanBase* start, const SkOpSpanBase* end, SkDCubic* result) const;
334 void subDivideBounds(const SkOpSpanBase* start, const SkOpSpanBase* end,
335 SkPathOpsBounds* bounds) const;
336
337 const SkOpSpanBase* tail() const {
338 return &fTail;
227 } 339 }
228 340
229 void updatePts(const SkPoint pts[]) { 341 SkOpSpanBase* tail() {
230 fPts = pts; 342 return &fTail;
231 } 343 }
232 344
345 static double TAtMid(const SkOpSpanBase* start, const SkOpSpanBase* end, dou ble mid) {
346 return start->t() * (1 - mid) + end->t() * mid;
347 }
348
349 void undoneSpan(SkOpSpanBase** start, SkOpSpanBase** end);
350 int updateOppWinding(const SkOpSpanBase* start, const SkOpSpanBase* end) con st;
351 int updateOppWinding(const SkOpAngle* angle) const;
352 int updateOppWindingReverse(const SkOpAngle* angle) const;
353 int updateWinding(const SkOpSpanBase* start, const SkOpSpanBase* end) const;
354 int updateWinding(const SkOpAngle* angle) const;
355 int updateWindingReverse(const SkOpAngle* angle) const;
356
357 static bool UseInnerWinding(int outerWinding, int innerWinding);
358
233 SkPath::Verb verb() const { 359 SkPath::Verb verb() const {
234 return fVerb; 360 return fVerb;
235 } 361 }
236 362
237 int windSum(int tIndex) const { 363 int windingAtT(double tHit, const SkOpSpan* span, bool crossOpp, SkScalar* d x) const;
238 return fTs[tIndex].fWindSum; 364 int windSum(const SkOpAngle* angle) const;
365
366 SkPoint* writablePt(bool end) {
367 return &fPts[end ? SkPathOpsVerbToPoints(fVerb) : 0];
239 } 368 }
240 369
241 int windValue(int tIndex) const {
242 return fTs[tIndex].fWindValue;
243 }
244
245 #if defined(SK_DEBUG) || DEBUG_WINDING
246 SkScalar xAtT(int index) const {
247 return xAtT(&fTs[index]);
248 }
249 #endif
250
251 #if DEBUG_VALIDATE
252 bool _xor() const { // FIXME: used only by SkOpAngle::debugValidateLoop()
253 return fXor;
254 }
255 #endif
256
257 const SkPoint& xyAtT(const SkOpSpan* span) const {
258 return span->fPt;
259 }
260
261 const SkPoint& xyAtT(int index) const {
262 return xyAtT(&fTs[index]);
263 }
264
265 #if defined(SK_DEBUG) || DEBUG_WINDING
266 SkScalar yAtT(int index) const {
267 return yAtT(&fTs[index]);
268 }
269 #endif
270
271 const SkOpAngle* activeAngle(int index, int* start, int* end, bool* done,
272 bool* sortable) const;
273 SkPoint activeLeftTop(int* firstT) const;
274 bool activeOp(int index, int endIndex, int xorMiMask, int xorSuMask, SkPathO p op);
275 bool activeWinding(int index, int endIndex);
276 void addCubic(const SkPoint pts[4], bool operand, bool evenOdd);
277 void addCurveTo(int start, int end, SkPathWriter* path, bool active) const;
278 void addEndSpan(int endIndex);
279 void addLine(const SkPoint pts[2], bool operand, bool evenOdd);
280 void addOtherT(int index, double otherT, int otherIndex);
281 void addQuad(const SkPoint pts[3], bool operand, bool evenOdd);
282 void addSimpleAngle(int endIndex);
283 int addSelfT(const SkPoint& pt, double newT);
284 void addStartSpan(int endIndex);
285 int addT(SkOpSegment* other, const SkPoint& pt, double newT);
286 void addTCancel(const SkPoint& startPt, const SkPoint& endPt, SkOpSegment* o ther);
287 bool addTCoincident(const SkPoint& startPt, const SkPoint& endPt, double end T,
288 SkOpSegment* other);
289 const SkOpSpan* addTPair(double t, SkOpSegment* other, double otherT, bool b orrowWind,
290 const SkPoint& pt);
291 const SkOpSpan* addTPair(double t, SkOpSegment* other, double otherT, bool b orrowWind,
292 const SkPoint& pt, const SkPoint& oPt);
293 void alignMultiples(SkTDArray<AlignedSpan>* aligned);
294 bool alignSpan(int index, double thisT, const SkPoint& thisPt);
295 void alignSpanState(int start, int end);
296 bool betweenTs(int lesser, double testT, int greater) const;
297 void blindCancel(const SkCoincidence& coincidence, SkOpSegment* other);
298 void blindCoincident(const SkCoincidence& coincidence, SkOpSegment* other);
299 bool calcAngles();
300 double calcMissingTEnd(const SkOpSegment* ref, double loEnd, double min, dou ble max,
301 double hiEnd, const SkOpSegment* other, int thisEnd);
302 double calcMissingTStart(const SkOpSegment* ref, double loEnd, double min, d ouble max,
303 double hiEnd, const SkOpSegment* other, int thisEnd );
304 void checkDuplicates();
305 bool checkEnds();
306 void checkMultiples();
307 void checkSmall();
308 bool checkSmall(int index) const;
309 void checkTiny();
310 int computeSum(int startIndex, int endIndex, SkOpAngle::IncludeType includeT ype);
311 bool containsPt(const SkPoint& , int index, int endIndex) const;
312 int crossedSpanY(const SkPoint& basePt, SkScalar* bestY, double* hitT, bool* hitSomething,
313 double mid, bool opp, bool current) const;
314 bool findCoincidentMatch(const SkOpSpan* span, const SkOpSegment* other, int oStart, int oEnd,
315 int step, SkPoint* startPt, SkPoint* endPt, double* endT) const;
316 SkOpSegment* findNextOp(SkTDArray<SkOpSpan*>* chase, int* nextStart, int* ne xtEnd,
317 bool* unsortable, SkPathOp op, int xorMiMask, int xo rSuMask);
318 SkOpSegment* findNextWinding(SkTDArray<SkOpSpan*>* chase, int* nextStart, in t* nextEnd,
319 bool* unsortable);
320 SkOpSegment* findNextXor(int* nextStart, int* nextEnd, bool* unsortable);
321 int findExactT(double t, const SkOpSegment* ) const;
322 int findOtherT(double t, const SkOpSegment* ) const;
323 int findT(double t, const SkPoint& , const SkOpSegment* ) const;
324 SkOpSegment* findTop(int* tIndex, int* endIndex, bool* unsortable, bool firs tPass);
325 void fixOtherTIndex();
326 bool inconsistentAngle(int maxWinding, int sumWinding, int oppMaxWinding, in t oppSumWinding,
327 const SkOpAngle* angle) const;
328 void initWinding(int start, int end, SkOpAngle::IncludeType angleIncludeType );
329 bool initWinding(int start, int end, double tHit, int winding, SkScalar hitD x, int oppWind,
330 SkScalar hitOppDx);
331 bool isMissing(double startT, const SkPoint& pt) const;
332 bool isTiny(const SkOpAngle* angle) const;
333 bool joinCoincidence(SkOpSegment* other, double otherT, const SkPoint& other Pt, int step,
334 bool cancel);
335 SkOpSpan* markAndChaseDoneBinary(int index, int endIndex);
336 SkOpSpan* markAndChaseDoneUnary(int index, int endIndex);
337 bool markAndChaseWinding(const SkOpAngle* angle, int winding, int oppWinding ,
338 SkOpSpan** lastPtr);
339 SkOpSpan* markAngle(int maxWinding, int sumWinding, int oppMaxWinding, int o ppSumWinding,
340 const SkOpAngle* angle);
341 void markDone(int index, int winding);
342 void markDoneBinary(int index);
343 void markDoneFinal(int index);
344 void markDoneUnary(int index);
345 bool nextCandidate(int* start, int* end) const;
346 int nextSpan(int from, int step) const;
347 void pinT(const SkPoint& pt, double* t);
348 void setUpWindings(int index, int endIndex, int* sumMiWinding, int* sumSuWin ding,
349 int* maxWinding, int* sumWinding, int* oppMaxWinding, int* oppSumWin ding);
350 void sortAngles();
351 bool subDivide(int start, int end, SkPoint edge[4]) const;
352 bool subDivide(int start, int end, SkDCubic* result) const;
353 void undoneSpan(int* start, int* end);
354 int updateOppWindingReverse(const SkOpAngle* angle) const;
355 int updateWindingReverse(const SkOpAngle* angle) const;
356 static bool UseInnerWinding(int outerWinding, int innerWinding);
357 static bool UseInnerWindingReverse(int outerWinding, int innerWinding);
358 int windingAtT(double tHit, int tIndex, bool crossOpp, SkScalar* dx) const;
359 int windSum(const SkOpAngle* angle) const;
360 // available for testing only
361 #if defined(SK_DEBUG) || !FORCE_RELEASE
362 int debugID() const {
363 return fID;
364 }
365 #else
366 int debugID() const {
367 return -1;
368 }
369 #endif
370 #if DEBUG_ACTIVE_SPANS || DEBUG_ACTIVE_SPANS_FIRST_ONLY
371 void debugShowActiveSpans() const;
372 #endif
373 #if DEBUG_CONCIDENT
374 void debugShowTs(const char* prefix) const;
375 #endif
376 #if DEBUG_SHOW_WINDING
377 int debugShowWindingValues(int slotCount, int ofInterest) const;
378 #endif
379 const SkTDArray<SkOpSpan>& debugSpans() const;
380 void debugValidate() const;
381 // available to testing only
382 const SkOpAngle* debugLastAngle() const;
383 void dumpAngles() const;
384 void dumpContour(int firstID, int lastID) const;
385 void dumpPts() const;
386 void dumpSpans() const;
387
388 private: 370 private:
389 struct MissingSpan { 371 SkOpSpan fHead; // the head span always has its t set to zero
390 double fT; 372 SkOpSpanBase fTail; // the tail span always has its t set to one
391 double fEndT; 373 SkOpContour* fContour;
392 SkOpSegment* fSegment; 374 SkOpSegment* fNext; // forward-only linked list used by contour to walk the segments
393 SkOpSegment* fOther; 375 const SkOpSegment* fPrev;
394 double fOtherT; 376 SkPoint* fPts; // pointer into array of points owned by edge builder that m ay be tweaked
395 SkPoint fPt; 377 SkPathOpsBounds fBounds; // tight bounds
396 }; 378 int fCount; // number of spans (one for a non-intersecting segment)
397 379 int fDoneCount; // number of processed spans (zero initially)
398 const SkOpAngle* activeAngleInner(int index, int* start, int* end, bool* don e,
399 bool* sortable) const;
400 const SkOpAngle* activeAngleOther(int index, int* start, int* end, bool* don e,
401 bool* sortable) const;
402 bool activeOp(int xorMiMask, int xorSuMask, int index, int endIndex, SkPathO p op,
403 int* sumMiWinding, int* sumSuWinding);
404 bool activeWinding(int index, int endIndex, int* sumWinding);
405 void addCancelOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSeg ment* other);
406 void addCoinOutsides(const SkPoint& startPt, const SkPoint& endPt, SkOpSegme nt* other);
407 SkOpAngle* addSingletonAngleDown(SkOpSegment** otherPtr, SkOpAngle** );
408 SkOpAngle* addSingletonAngleUp(SkOpSegment** otherPtr, SkOpAngle** );
409 SkOpAngle* addSingletonAngles(int step);
410 void alignRange(int lower, int upper, const SkOpSegment* other, int oLower, int oUpper);
411 void alignSpan(const SkPoint& newPt, double newT, const SkOpSegment* other, double otherT,
412 const SkOpSegment* other2, SkOpSpan* oSpan, SkTDArray<Aligned Span>* );
413 bool betweenPoints(double midT, const SkPoint& pt1, const SkPoint& pt2) cons t;
414 void bumpCoincidentBlind(bool binary, int index, int last);
415 bool bumpCoincidentThis(const SkOpSpan& oTest, bool binary, int* index,
416 SkTArray<SkPoint, true>* outsideTs);
417 void bumpCoincidentOBlind(int index, int last);
418 bool bumpCoincidentOther(const SkOpSpan& oTest, int* index,
419 SkTArray<SkPoint, true>* outsideTs, const SkPoint& endPt);
420 bool bumpSpan(SkOpSpan* span, int windDelta, int oppDelta);
421 bool calcLoopSpanCount(const SkOpSpan& thisSpan, int* smallCounts);
422 bool checkForSmall(const SkOpSpan* span, const SkPoint& pt, double newT,
423 int* less, int* more) const;
424 void checkLinks(const SkOpSpan* ,
425 SkTArray<MissingSpan, true>* missingSpans) const;
426 static void CheckOneLink(const SkOpSpan* test, const SkOpSpan* oSpan,
427 const SkOpSpan* oFirst, const SkOpSpan* oLast,
428 const SkOpSpan** missingPtr,
429 SkTArray<MissingSpan, true>* missingSpans);
430 int checkSetAngle(int tIndex) const;
431 void checkSmallCoincidence(const SkOpSpan& span, SkTArray<MissingSpan, true> * );
432 bool coincidentSmall(const SkPoint& pt, double t, const SkOpSegment* other) const;
433 bool clockwise(int tStart, int tEnd, bool* swap) const;
434 static void ComputeOneSum(const SkOpAngle* baseAngle, SkOpAngle* nextAngle,
435 SkOpAngle::IncludeType );
436 static void ComputeOneSumReverse(const SkOpAngle* baseAngle, SkOpAngle* next Angle,
437 SkOpAngle::IncludeType );
438 bool containsT(double t, const SkOpSegment* other, double otherT) const;
439 bool decrementSpan(SkOpSpan* span);
440 int findEndSpan(int endIndex) const;
441 int findStartSpan(int startIndex) const;
442 int firstActive(int tIndex) const;
443 const SkOpSpan& firstSpan(const SkOpSpan& thisSpan) const;
444 void init(const SkPoint pts[], SkPath::Verb verb, bool operand, bool evenOdd );
445 bool inCoincidentSpan(double t, const SkOpSegment* other) const;
446 bool inconsistentWinding(const SkOpAngle* , int maxWinding, int oppMaxWindin g) const;
447 bool inconsistentWinding(int min, int maxWinding, int oppMaxWinding) const;
448 bool inconsistentWinding(const char* funName, int tIndex, int winding, int o ppWinding) const;
449 bool inLoop(const SkOpAngle* baseAngle, int spanCount, int* indexPtr) const;
450 #if OLD_CHASE
451 bool isSimple(int end) const;
452 #else
453 SkOpSegment* isSimple(int* end, int* step);
454 #endif
455 bool isTiny(int index) const;
456 const SkOpSpan& lastSpan(const SkOpSpan& thisSpan) const;
457 void matchWindingValue(int tIndex, double t, bool borrowWind);
458 SkOpSpan* markAndChaseDone(int index, int endIndex, int winding);
459 SkOpSpan* markAndChaseDoneBinary(const SkOpAngle* angle, int winding, int op pWinding);
460 bool markAndChaseWinding(const SkOpAngle* angle, int winding, SkOpSpan** las tPtr);
461 bool markAndChaseWinding(int index, int endIndex, int winding, SkOpSpan** la stPtr);
462 bool markAndChaseWinding(int index, int endIndex, int winding, int oppWindin g,
463 SkOpSpan** lastPtr);
464 SkOpSpan* markAngle(int maxWinding, int sumWinding, const SkOpAngle* angle);
465 void markDoneBinary(int index, int winding, int oppWinding);
466 SkOpSpan* markAndChaseDoneUnary(const SkOpAngle* angle, int winding);
467 void markOneDone(const char* funName, int tIndex, int winding);
468 void markOneDoneBinary(const char* funName, int tIndex);
469 void markOneDoneBinary(const char* funName, int tIndex, int winding, int opp Winding);
470 void markOneDoneFinal(const char* funName, int tIndex);
471 void markOneDoneUnary(const char* funName, int tIndex);
472 bool markOneWinding(const char* funName, int tIndex, int winding, SkOpSpan** lastPtr);
473 bool markOneWinding(const char* funName, int tIndex, int winding, int oppWin ding,
474 SkOpSpan** lastPtr);
475 bool markWinding(int index, int winding);
476 bool markWinding(int index, int winding, int oppWinding);
477 bool monotonicInY(int tStart, int tEnd) const;
478
479 bool multipleEnds() const { return fTs[count() - 2].fT == 1; }
480 bool multipleStarts() const { return fTs[1].fT == 0; }
481
482 SkOpSegment* nextChase(int* index, int* step, int* min, SkOpSpan** last) con st;
483 int nextExactSpan(int from, int step) const;
484 void resetSpanFlags();
485 bool serpentine(int tStart, int tEnd) const;
486 void setCoincidentRange(const SkPoint& startPt, const SkPoint& endPt, SkOpS egment* other);
487 void setFromAngle(int endIndex, SkOpAngle* );
488 void setSpanFlags(const SkPoint& pt, double newT, SkOpSpan* span);
489 void setToAngle(int endIndex, SkOpAngle* );
490 void setUpWindings(int index, int endIndex, int* sumMiWinding,
491 int* maxWinding, int* sumWinding);
492 void subDivideBounds(int start, int end, SkPathOpsBounds* bounds) const;
493 static void TrackOutsidePair(SkTArray<SkPoint, true>* outsideTs, const SkPoi nt& endPt,
494 const SkPoint& startPt);
495 static void TrackOutside(SkTArray<SkPoint, true>* outsideTs, const SkPoint& startPt);
496 int updateOppWinding(int index, int endIndex) const;
497 int updateOppWinding(const SkOpAngle* angle) const;
498 int updateWinding(int index, int endIndex) const;
499 int updateWinding(const SkOpAngle* angle) const;
500 int updateWindingReverse(int index, int endIndex) const;
501 SkOpSpan* verifyOneWinding(const char* funName, int tIndex);
502 SkOpSpan* verifyOneWindingU(const char* funName, int tIndex);
503
504 SkScalar xAtT(const SkOpSpan* span) const {
505 return xyAtT(span).fX;
506 }
507
508 SkScalar yAtT(const SkOpSpan* span) const {
509 return xyAtT(span).fY;
510 }
511
512 void zeroSpan(SkOpSpan* span);
513
514 #if DEBUG_SWAP_TOP
515 bool controlsContainedByEnds(int tStart, int tEnd) const;
516 #endif
517 void debugAddAngle(int start, int end);
518 #if DEBUG_CONCIDENT
519 void debugAddTPair(double t, const SkOpSegment& other, double otherT) const;
520 #endif
521 #if DEBUG_ANGLE
522 void debugCheckPointsEqualish(int tStart, int tEnd) const;
523 #endif
524 #if DEBUG_SWAP_TOP
525 int debugInflections(int index, int endIndex) const;
526 #endif
527 #if DEBUG_MARK_DONE || DEBUG_UNSORTABLE
528 void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding) ;
529 void debugShowNewWinding(const char* fun, const SkOpSpan& span, int winding, int oppWinding);
530 #endif
531 #if DEBUG_WINDING
532 static char as_digit(int value) {
533 return value < 0 ? '?' : value <= 9 ? '0' + value : '+';
534 }
535 #endif
536 // available to testing only
537 void debugConstruct();
538 void debugConstructCubic(SkPoint shortQuad[4]);
539 void debugConstructLine(SkPoint shortQuad[2]);
540 void debugConstructQuad(SkPoint shortQuad[3]);
541 void debugReset();
542 void dumpDPts() const;
543 void dumpHexPts() const;
544 void dumpSpan(int index) const;
545
546 const SkPoint* fPts;
547 SkPathOpsBounds fBounds;
548 // FIXME: can't convert to SkTArray because it uses insert
549 SkTDArray<SkOpSpan> fTs; // 2+ (always includes t=0 t=1) -- at least (numbe r of spans) + 1
550 SkOpAngleSet fAngles; // empty or 2+ -- (number of non-zero spans) * 2
551 // OPTIMIZATION: could pack donespans, verb, operand, xor into 1 int-sized v alue
552 int fDoneSpans; // quick check that segment is finished
553 // OPTIMIZATION: force the following to be byte-sized
554 SkPath::Verb fVerb; 380 SkPath::Verb fVerb;
555 bool fLoop; // set if cubic intersects itself 381 bool fVisited; // used by missing coincidence check
556 bool fMultiples; // set if curve intersects multiple other curves at one in terior point 382 PATH_OPS_DEBUG_CODE(int fID);
557 bool fOperand;
558 bool fXor; // set if original contour had even-odd fill
559 bool fOppXor; // set if opposite operand had even-odd fill
560 bool fSmall; // set if some span is small
561 bool fTiny; // set if some span is tiny
562 #if defined(SK_DEBUG) || !FORCE_RELEASE
563 int fID;
564 #endif
565
566 friend class PathOpsSegmentTester;
567 }; 383 };
568 384
569 #endif 385 #endif
OLDNEW
« no previous file with comments | « src/pathops/SkOpEdgeBuilder.cpp ('k') | src/pathops/SkOpSegment.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698