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

Side by Side Diff: src/pathops/SkOpContour.cpp

Issue 272153002: fix bugs found by computing flat clips in 800K skps (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix maybe-uninitialized error in unbuntu Created 6 years, 6 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/SkOpContour.h ('k') | src/pathops/SkOpSegment.h » ('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 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 #include "SkIntersections.h" 7 #include "SkIntersections.h"
8 #include "SkOpContour.h" 8 #include "SkOpContour.h"
9 #include "SkPathWriter.h" 9 #include "SkPathWriter.h"
10 #include "SkTSort.h" 10 #include "SkTSort.h"
(...skipping 10 matching lines...) Expand all
21 return false; 21 return false;
22 } 22 }
23 SkCoincidence& coincidence = fCoincidences.push_back(); 23 SkCoincidence& coincidence = fCoincidences.push_back();
24 coincidence.fOther = other; 24 coincidence.fOther = other;
25 coincidence.fSegments[0] = index; 25 coincidence.fSegments[0] = index;
26 coincidence.fSegments[1] = otherIndex; 26 coincidence.fSegments[1] = otherIndex;
27 coincidence.fTs[swap][0] = ts[0][0]; 27 coincidence.fTs[swap][0] = ts[0][0];
28 coincidence.fTs[swap][1] = ts[0][1]; 28 coincidence.fTs[swap][1] = ts[0][1];
29 coincidence.fTs[!swap][0] = ts[1][0]; 29 coincidence.fTs[!swap][0] = ts[1][0];
30 coincidence.fTs[!swap][1] = ts[1][1]; 30 coincidence.fTs[!swap][1] = ts[1][1];
31 coincidence.fPts[0] = pt0; 31 coincidence.fPts[swap][0] = pt0;
32 coincidence.fPts[1] = pt1; 32 coincidence.fPts[swap][1] = pt1;
33 bool nearStart = ts.nearlySame(0);
34 bool nearEnd = ts.nearlySame(1);
35 coincidence.fPts[!swap][0] = nearStart ? ts.pt2(0).asSkPoint() : pt0;
36 coincidence.fPts[!swap][1] = nearEnd ? ts.pt2(1).asSkPoint() : pt1;
37 coincidence.fNearly[0] = nearStart;
38 coincidence.fNearly[1] = nearEnd;
33 return true; 39 return true;
34 } 40 }
35 41
36 SkOpSegment* SkOpContour::nonVerticalSegment(int* start, int* end) { 42 SkOpSegment* SkOpContour::nonVerticalSegment(int* start, int* end) {
37 int segmentCount = fSortedSegments.count(); 43 int segmentCount = fSortedSegments.count();
38 SkASSERT(segmentCount > 0); 44 SkASSERT(segmentCount > 0);
39 for (int sortedIndex = fFirstSorted; sortedIndex < segmentCount; ++sortedInd ex) { 45 for (int sortedIndex = fFirstSorted; sortedIndex < segmentCount; ++sortedInd ex) {
40 SkOpSegment* testSegment = fSortedSegments[sortedIndex]; 46 SkOpSegment* testSegment = fSortedSegments[sortedIndex];
41 if (testSegment->done()) { 47 if (testSegment->done()) {
42 continue; 48 continue;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 } 92 }
87 } 93 }
88 SkASSERT(!approximately_negative(endT - startT)); 94 SkASSERT(!approximately_negative(endT - startT));
89 double oStartT = coincidence.fTs[1][0]; 95 double oStartT = coincidence.fTs[1][0];
90 double oEndT = coincidence.fTs[1][1]; 96 double oEndT = coincidence.fTs[1][1];
91 if ((oStartSwapped = oStartT > oEndT)) { 97 if ((oStartSwapped = oStartT > oEndT)) {
92 SkTSwap(oStartT, oEndT); 98 SkTSwap(oStartT, oEndT);
93 cancelers ^= true; 99 cancelers ^= true;
94 } 100 }
95 SkASSERT(!approximately_negative(oEndT - oStartT)); 101 SkASSERT(!approximately_negative(oEndT - oStartT));
102 const SkPoint& startPt = coincidence.fPts[0][startSwapped];
96 if (cancelers) { 103 if (cancelers) {
97 // make sure startT and endT have t entries 104 // make sure startT and endT have t entries
98 const SkPoint& startPt = coincidence.fPts[startSwapped];
99 if (startT > 0 || oEndT < 1 105 if (startT > 0 || oEndT < 1
100 || thisOne.isMissing(startT, startPt) || other.isMissing(oEn dT, startPt)) { 106 || thisOne.isMissing(startT, startPt) || other.isMissing(oEn dT, startPt)) {
101 thisOne.addTPair(startT, &other, oEndT, true, startPt); 107 thisOne.addTPair(startT, &other, oEndT, true, startPt,
108 coincidence.fPts[1][startSwapped]);
102 } 109 }
103 const SkPoint& oStartPt = coincidence.fPts[oStartSwapped]; 110 const SkPoint& oStartPt = coincidence.fPts[1][oStartSwapped];
104 if (oStartT > 0 || endT < 1 111 if (oStartT > 0 || endT < 1
105 || thisOne.isMissing(endT, oStartPt) || other.isMissing(oSta rtT, oStartPt)) { 112 || thisOne.isMissing(endT, oStartPt) || other.isMissing(oSta rtT, oStartPt)) {
106 other.addTPair(oStartT, &thisOne, endT, true, oStartPt); 113 other.addTPair(oStartT, &thisOne, endT, true, oStartPt,
114 coincidence.fPts[0][oStartSwapped]);
107 } 115 }
108 } else { 116 } else {
109 const SkPoint& startPt = coincidence.fPts[startSwapped];
110 if (startT > 0 || oStartT > 0 117 if (startT > 0 || oStartT > 0
111 || thisOne.isMissing(startT, startPt) || other.isMissing(oSt artT, startPt)) { 118 || thisOne.isMissing(startT, startPt) || other.isMissing(oSt artT, startPt)) {
112 thisOne.addTPair(startT, &other, oStartT, true, startPt); 119 thisOne.addTPair(startT, &other, oStartT, true, startPt,
120 coincidence.fPts[1][startSwapped]);
113 } 121 }
114 const SkPoint& oEndPt = coincidence.fPts[!oStartSwapped]; 122 const SkPoint& oEndPt = coincidence.fPts[1][!oStartSwapped];
115 if (endT < 1 || oEndT < 1 123 if (endT < 1 || oEndT < 1
116 || thisOne.isMissing(endT, oEndPt) || other.isMissing(oEndT, oEndPt)) { 124 || thisOne.isMissing(endT, oEndPt) || other.isMissing(oEndT, oEndPt)) {
117 other.addTPair(oEndT, &thisOne, endT, true, oEndPt); 125 other.addTPair(oEndT, &thisOne, endT, true, oEndPt,
126 coincidence.fPts[0][!oStartSwapped]);
118 } 127 }
119 } 128 }
120 #if DEBUG_CONCIDENT 129 #if DEBUG_CONCIDENT
121 thisOne.debugShowTs("+"); 130 thisOne.debugShowTs("+");
122 other.debugShowTs("o"); 131 other.debugShowTs("o");
123 #endif 132 #endif
124 } 133 }
134 // if there are multiple pairs of coincidence that share an edge, see if the opposite
135 // are also coincident
136 for (int index = 0; index < count - 1; ++index) {
137 const SkCoincidence& coincidence = fCoincidences[index];
138 int thisIndex = coincidence.fSegments[0];
139 SkOpContour* otherContour = coincidence.fOther;
140 int otherIndex = coincidence.fSegments[1];
141 for (int idx2 = 1; idx2 < count; ++idx2) {
142 const SkCoincidence& innerCoin = fCoincidences[idx2];
143 int innerThisIndex = innerCoin.fSegments[0];
144 if (thisIndex == innerThisIndex) {
145 checkCoincidentPair(coincidence, 1, innerCoin, 1, false);
146 }
147 if (this == otherContour && otherIndex == innerThisIndex) {
148 checkCoincidentPair(coincidence, 0, innerCoin, 1, false);
149 }
150 SkOpContour* innerOtherContour = innerCoin.fOther;
151 innerThisIndex = innerCoin.fSegments[1];
152 if (this == innerOtherContour && thisIndex == innerThisIndex) {
153 checkCoincidentPair(coincidence, 1, innerCoin, 0, false);
154 }
155 if (otherContour == innerOtherContour && otherIndex == innerThisInde x) {
156 checkCoincidentPair(coincidence, 0, innerCoin, 0, false);
157 }
158 }
159 }
125 } 160 }
126 161
127 bool SkOpContour::addPartialCoincident(int index, SkOpContour* other, int otherI ndex, 162 bool SkOpContour::addPartialCoincident(int index, SkOpContour* other, int otherI ndex,
128 const SkIntersections& ts, int ptIndex, bool swap) { 163 const SkIntersections& ts, int ptIndex, bool swap) {
129 SkPoint pt0 = ts.pt(ptIndex).asSkPoint(); 164 SkPoint pt0 = ts.pt(ptIndex).asSkPoint();
130 SkPoint pt1 = ts.pt(ptIndex + 1).asSkPoint(); 165 SkPoint pt1 = ts.pt(ptIndex + 1).asSkPoint();
131 if (SkDPoint::ApproximatelyEqual(pt0, pt1)) { 166 if (SkDPoint::ApproximatelyEqual(pt0, pt1)) {
132 // FIXME: one could imagine a case where it would be incorrect to ignore this 167 // FIXME: one could imagine a case where it would be incorrect to ignore this
133 // suppose two self-intersecting cubics overlap to form a partial coinci dence -- 168 // suppose two self-intersecting cubics overlap to form a partial coinci dence --
134 // although it isn't clear why the regular coincidence could wouldn't pi ck this up 169 // although it isn't clear why the regular coincidence could wouldn't pi ck this up
135 // this is exceptional enough to ignore for now 170 // this is exceptional enough to ignore for now
136 return false; 171 return false;
137 } 172 }
138 SkCoincidence& coincidence = fPartialCoincidences.push_back(); 173 SkCoincidence& coincidence = fPartialCoincidences.push_back();
139 coincidence.fOther = other; 174 coincidence.fOther = other;
140 coincidence.fSegments[0] = index; 175 coincidence.fSegments[0] = index;
141 coincidence.fSegments[1] = otherIndex; 176 coincidence.fSegments[1] = otherIndex;
142 coincidence.fTs[swap][0] = ts[0][ptIndex]; 177 coincidence.fTs[swap][0] = ts[0][ptIndex];
143 coincidence.fTs[swap][1] = ts[0][ptIndex + 1]; 178 coincidence.fTs[swap][1] = ts[0][ptIndex + 1];
144 coincidence.fTs[!swap][0] = ts[1][ptIndex]; 179 coincidence.fTs[!swap][0] = ts[1][ptIndex];
145 coincidence.fTs[!swap][1] = ts[1][ptIndex + 1]; 180 coincidence.fTs[!swap][1] = ts[1][ptIndex + 1];
146 coincidence.fPts[0] = pt0; 181 coincidence.fPts[0][0] = coincidence.fPts[1][0] = pt0;
147 coincidence.fPts[1] = pt1; 182 coincidence.fPts[0][1] = coincidence.fPts[1][1] = pt1;
183 coincidence.fNearly[0] = 0;
184 coincidence.fNearly[1] = 0;
148 return true; 185 return true;
149 } 186 }
150 187
188 void SkOpContour::align(const SkOpSegment::AlignedSpan& aligned, bool swap,
189 SkCoincidence* coincidence) {
190 for (int idx2 = 0; idx2 < 2; ++idx2) {
191 if (coincidence->fPts[0][idx2] == aligned.fOldPt
192 && coincidence->fTs[swap][idx2] == aligned.fOldT) {
193 SkASSERT(SkDPoint::RoughlyEqual(coincidence->fPts[0][idx2], aligned. fPt));
194 coincidence->fPts[0][idx2] = aligned.fPt;
195 SkASSERT(way_roughly_equal(coincidence->fTs[swap][idx2], aligned.fT) );
196 coincidence->fTs[swap][idx2] = aligned.fT;
197 }
198 }
199 }
200
201 void SkOpContour::alignCoincidence(const SkOpSegment::AlignedSpan& aligned,
202 SkTArray<SkCoincidence, true>* coincidences) {
203 int count = coincidences->count();
204 for (int index = 0; index < count; ++index) {
205 SkCoincidence& coincidence = (*coincidences)[index];
206 int thisIndex = coincidence.fSegments[0];
207 const SkOpSegment* thisOne = &fSegments[thisIndex];
208 const SkOpContour* otherContour = coincidence.fOther;
209 int otherIndex = coincidence.fSegments[1];
210 const SkOpSegment* other = &otherContour->fSegments[otherIndex];
211 if (thisOne == aligned.fOther1 && other == aligned.fOther2) {
212 align(aligned, false, &coincidence);
213 } else if (thisOne == aligned.fOther2 && other == aligned.fOther1) {
214 align(aligned, true, &coincidence);
215 }
216 }
217 }
218
219 void SkOpContour::alignTPt(int segmentIndex, const SkOpContour* other, int other Index,
220 bool swap, int tIndex, SkIntersections* ts, SkPoint* point) const {
221 int zeroPt;
222 if ((zeroPt = alignT(swap, tIndex, ts)) >= 0) {
223 alignPt(segmentIndex, point, zeroPt);
224 }
225 if ((zeroPt = other->alignT(!swap, tIndex, ts)) >= 0) {
226 other->alignPt(otherIndex, point, zeroPt);
227 }
228 }
229
230 void SkOpContour::alignPt(int index, SkPoint* point, int zeroPt) const {
231 const SkOpSegment& segment = fSegments[index];
232 if (0 == zeroPt) {
233 *point = segment.pts()[0];
234 } else {
235 *point = segment.pts()[SkPathOpsVerbToPoints(segment.verb())];
236 }
237 }
238
239 int SkOpContour::alignT(bool swap, int tIndex, SkIntersections* ts) const {
240 double tVal = (*ts)[swap][tIndex];
241 if (tVal != 0 && precisely_zero(tVal)) {
242 ts->set(swap, tIndex, 0);
243 return 0;
244 }
245 if (tVal != 1 && precisely_equal(tVal, 1)) {
246 ts->set(swap, tIndex, 1);
247 return 1;
248 }
249 return -1;
250 }
251
151 bool SkOpContour::calcAngles() { 252 bool SkOpContour::calcAngles() {
152 int segmentCount = fSegments.count(); 253 int segmentCount = fSegments.count();
153 for (int test = 0; test < segmentCount; ++test) { 254 for (int test = 0; test < segmentCount; ++test) {
154 if (!fSegments[test].calcAngles()) { 255 if (!fSegments[test].calcAngles()) {
155 return false; 256 return false;
156 } 257 }
157 } 258 }
158 return true; 259 return true;
159 } 260 }
160 261
(...skipping 12 matching lines...) Expand all
173 274
174 void SkOpContour::calcPartialCoincidentWinding() { 275 void SkOpContour::calcPartialCoincidentWinding() {
175 int count = fPartialCoincidences.count(); 276 int count = fPartialCoincidences.count();
176 #if DEBUG_CONCIDENT 277 #if DEBUG_CONCIDENT
177 if (count > 0) { 278 if (count > 0) {
178 SkDebugf("%s count=%d\n", __FUNCTION__, count); 279 SkDebugf("%s count=%d\n", __FUNCTION__, count);
179 } 280 }
180 #endif 281 #endif
181 for (int index = 0; index < count; ++index) { 282 for (int index = 0; index < count; ++index) {
182 SkCoincidence& coincidence = fPartialCoincidences[index]; 283 SkCoincidence& coincidence = fPartialCoincidences[index];
183 calcCommonCoincidentWinding(coincidence); 284 calcCommonCoincidentWinding(coincidence);
285 }
286 // if there are multiple pairs of partial coincidence that share an edge, se e if the opposite
287 // are also coincident
288 for (int index = 0; index < count - 1; ++index) {
289 const SkCoincidence& coincidence = fPartialCoincidences[index];
290 int thisIndex = coincidence.fSegments[0];
291 SkOpContour* otherContour = coincidence.fOther;
292 int otherIndex = coincidence.fSegments[1];
293 for (int idx2 = 1; idx2 < count; ++idx2) {
294 const SkCoincidence& innerCoin = fPartialCoincidences[idx2];
295 int innerThisIndex = innerCoin.fSegments[0];
296 if (thisIndex == innerThisIndex) {
297 checkCoincidentPair(coincidence, 1, innerCoin, 1, true);
298 }
299 if (this == otherContour && otherIndex == innerThisIndex) {
300 checkCoincidentPair(coincidence, 0, innerCoin, 1, true);
301 }
302 SkOpContour* innerOtherContour = innerCoin.fOther;
303 innerThisIndex = innerCoin.fSegments[1];
304 if (this == innerOtherContour && thisIndex == innerThisIndex) {
305 checkCoincidentPair(coincidence, 1, innerCoin, 0, true);
306 }
307 if (otherContour == innerOtherContour && otherIndex == innerThisInde x) {
308 checkCoincidentPair(coincidence, 0, innerCoin, 0, true);
309 }
310 }
184 } 311 }
185 } 312 }
186 313
314 void SkOpContour::checkCoincidentPair(const SkCoincidence& oneCoin, int oneIdx,
315 const SkCoincidence& twoCoin, int twoIdx, bool partial) {
316 SkASSERT((oneIdx ? this : oneCoin.fOther) == (twoIdx ? this : twoCoin.fOther ));
317 SkASSERT(oneCoin.fSegments[!oneIdx] == twoCoin.fSegments[!twoIdx]);
318 // look for common overlap
319 double min = SK_ScalarMax;
320 double max = SK_ScalarMin;
321 double min1 = oneCoin.fTs[!oneIdx][0];
322 double max1 = oneCoin.fTs[!oneIdx][1];
323 double min2 = twoCoin.fTs[!twoIdx][0];
324 double max2 = twoCoin.fTs[!twoIdx][1];
325 bool cancelers = (min1 < max1) != (min2 < max2);
326 if (min1 > max1) {
327 SkTSwap(min1, max1);
328 }
329 if (min2 > max2) {
330 SkTSwap(min2, max2);
331 }
332 if (between(min1, min2, max1)) {
333 min = min2;
334 }
335 if (between(min1, max2, max1)) {
336 max = max2;
337 }
338 if (between(min2, min1, max2)) {
339 min = SkTMin(min, min1);
340 }
341 if (between(min2, max1, max2)) {
342 max = SkTMax(max, max1);
343 }
344 if (min >= max) {
345 return; // no overlap
346 }
347 // look to see if opposite are different segments
348 int seg1Index = oneCoin.fSegments[oneIdx];
349 int seg2Index = twoCoin.fSegments[twoIdx];
350 if (seg1Index == seg2Index) {
351 return;
352 }
353 SkOpContour* contour1 = oneIdx ? oneCoin.fOther : this;
354 SkOpContour* contour2 = twoIdx ? twoCoin.fOther : this;
355 SkOpSegment* segment1 = &contour1->fSegments[seg1Index];
356 SkOpSegment* segment2 = &contour2->fSegments[seg2Index];
357 // find opposite t value ranges corresponding to reference min/max range
358 const SkOpContour* refContour = oneIdx ? this : oneCoin.fOther;
359 const int refSegIndex = oneCoin.fSegments[!oneIdx];
360 const SkOpSegment* refSegment = &refContour->fSegments[refSegIndex];
361 int seg1Start = segment1->findOtherT(min, refSegment);
362 int seg1End = segment1->findOtherT(max, refSegment);
363 int seg2Start = segment2->findOtherT(min, refSegment);
364 int seg2End = segment2->findOtherT(max, refSegment);
365 // if the opposite pairs already contain min/max, we're done
366 if (seg1Start >= 0 && seg1End >= 0 && seg2Start >= 0 && seg2End >= 0) {
367 return;
368 }
369 double loEnd = SkTMin(min1, min2);
370 double hiEnd = SkTMax(max1, max2);
371 // insert the missing coincident point(s)
372 double missingT1 = -1;
373 double otherT1 = -1;
374 if (seg1Start < 0) {
375 if (seg2Start < 0) {
376 return;
377 }
378 missingT1 = segment1->calcMissingTStart(refSegment, loEnd, min, max, hiE nd,
379 segment2, seg1End);
380 if (missingT1 < 0) {
381 return;
382 }
383 const SkOpSpan* missingSpan = &segment2->span(seg2Start);
384 otherT1 = missingSpan->fT;
385 } else if (seg2Start < 0) {
386 SkASSERT(seg1Start >= 0);
387 missingT1 = segment2->calcMissingTStart(refSegment, loEnd, min, max, hiE nd,
388 segment1, seg2End);
389 if (missingT1 < 0) {
390 return;
391 }
392 const SkOpSpan* missingSpan = &segment1->span(seg1Start);
393 otherT1 = missingSpan->fT;
394 }
395 SkPoint missingPt1;
396 SkOpSegment* addTo1 = NULL;
397 SkOpSegment* addOther1 = seg1Start < 0 ? segment2 : segment1;
398 int minTIndex = refSegment->findExactT(min, addOther1);
399 SkASSERT(minTIndex >= 0);
400 if (missingT1 >= 0) {
401 missingPt1 = refSegment->span(minTIndex).fPt;
402 addTo1 = seg1Start < 0 ? segment1 : segment2;
403 }
404 double missingT2 = -1;
405 double otherT2 = -1;
406 if (seg1End < 0) {
407 if (seg2End < 0) {
408 return;
409 }
410 missingT2 = segment1->calcMissingTEnd(refSegment, loEnd, min, max, hiEnd ,
411 segment2, seg1Start);
412 if (missingT2 < 0) {
413 return;
414 }
415 const SkOpSpan* missingSpan = &segment2->span(seg2End);
416 otherT2 = missingSpan->fT;
417 } else if (seg2End < 0) {
418 SkASSERT(seg1End >= 0);
419 missingT2 = segment2->calcMissingTEnd(refSegment, loEnd, min, max, hiEnd ,
420 segment1, seg2Start);
421 if (missingT2 < 0) {
422 return;
423 }
424 const SkOpSpan* missingSpan = &segment1->span(seg1End);
425 otherT2 = missingSpan->fT;
426 }
427 SkPoint missingPt2;
428 SkOpSegment* addTo2 = NULL;
429 SkOpSegment* addOther2 = seg1End < 0 ? segment2 : segment1;
430 int maxTIndex = refSegment->findExactT(max, addOther2);
431 SkASSERT(maxTIndex >= 0);
432 if (missingT2 >= 0) {
433 missingPt2 = refSegment->span(maxTIndex).fPt;
434 addTo2 = seg1End < 0 ? segment1 : segment2;
435 }
436 if (missingT1 >= 0) {
437 addTo1->pinT(missingPt1, &missingT1);
438 addTo1->addTPair(missingT1, addOther1, otherT1, false, missingPt1);
439 } else {
440 SkASSERT(minTIndex >= 0);
441 missingPt1 = refSegment->span(minTIndex).fPt;
442 }
443 if (missingT2 >= 0) {
444 addTo2->pinT(missingPt2, &missingT2);
445 addTo2->addTPair(missingT2, addOther2, otherT2, false, missingPt2);
446 } else {
447 SkASSERT(minTIndex >= 0);
448 missingPt2 = refSegment->span(maxTIndex).fPt;
449 }
450 if (!partial) {
451 return;
452 }
453 if (cancelers) {
454 if (missingT1 >= 0) {
455 addTo1->addTCancel(missingPt1, missingPt2, addOther1);
456 } else {
457 addTo2->addTCancel(missingPt1, missingPt2, addOther2);
458 }
459 } else if (missingT1 >= 0) {
460 addTo1->addTCoincident(missingPt1, missingPt2, addTo1 == addTo2 ? missin gT2 : otherT2,
461 addOther1);
462 } else {
463 addTo2->addTCoincident(missingPt2, missingPt1, addTo2 == addTo1 ? missin gT1 : otherT1,
464 addOther2);
465 }
466 }
467
187 void SkOpContour::joinCoincidence(const SkTArray<SkCoincidence, true>& coinciden ces, bool partial) { 468 void SkOpContour::joinCoincidence(const SkTArray<SkCoincidence, true>& coinciden ces, bool partial) {
188 int count = coincidences.count(); 469 int count = coincidences.count();
189 #if DEBUG_CONCIDENT 470 #if DEBUG_CONCIDENT
190 if (count > 0) { 471 if (count > 0) {
191 SkDebugf("%s count=%d\n", __FUNCTION__, count); 472 SkDebugf("%s count=%d\n", __FUNCTION__, count);
192 } 473 }
193 #endif 474 #endif
194 // look for a lineup where the partial implies another adjoining coincidence 475 // look for a lineup where the partial implies another adjoining coincidence
195 for (int index = 0; index < count; ++index) { 476 for (int index = 0; index < count; ++index) {
196 const SkCoincidence& coincidence = coincidences[index]; 477 const SkCoincidence& coincidence = coincidences[index];
197 int thisIndex = coincidence.fSegments[0]; 478 int thisIndex = coincidence.fSegments[0];
198 SkOpSegment& thisOne = fSegments[thisIndex]; 479 SkOpSegment& thisOne = fSegments[thisIndex];
480 if (thisOne.done()) {
481 continue;
482 }
199 SkOpContour* otherContour = coincidence.fOther; 483 SkOpContour* otherContour = coincidence.fOther;
200 int otherIndex = coincidence.fSegments[1]; 484 int otherIndex = coincidence.fSegments[1];
201 SkOpSegment& other = otherContour->fSegments[otherIndex]; 485 SkOpSegment& other = otherContour->fSegments[otherIndex];
486 if (other.done()) {
487 continue;
488 }
202 double startT = coincidence.fTs[0][0]; 489 double startT = coincidence.fTs[0][0];
203 double endT = coincidence.fTs[0][1]; 490 double endT = coincidence.fTs[0][1];
204 if (startT == endT) { // this can happen in very large compares 491 if (startT == endT) { // this can happen in very large compares
205 continue; 492 continue;
206 } 493 }
207 double oStartT = coincidence.fTs[1][0]; 494 double oStartT = coincidence.fTs[1][0];
208 double oEndT = coincidence.fTs[1][1]; 495 double oEndT = coincidence.fTs[1][1];
209 if (oStartT == oEndT) { 496 if (oStartT == oEndT) {
210 continue; 497 continue;
211 } 498 }
212 bool swapStart = startT > endT; 499 bool swapStart = startT > endT;
213 bool swapOther = oStartT > oEndT; 500 bool swapOther = oStartT > oEndT;
214 const SkPoint* startPt = &coincidence.fPts[0]; 501 const SkPoint* startPt = &coincidence.fPts[0][0];
215 const SkPoint* endPt = &coincidence.fPts[1]; 502 const SkPoint* endPt = &coincidence.fPts[0][1];
216 if (swapStart) { 503 if (swapStart) {
217 SkTSwap(startT, endT); 504 SkTSwap(startT, endT);
218 SkTSwap(oStartT, oEndT); 505 SkTSwap(oStartT, oEndT);
219 SkTSwap(startPt, endPt); 506 SkTSwap(startPt, endPt);
220 } 507 }
221 bool cancel = swapOther != swapStart; 508 bool cancel = swapOther != swapStart;
222 int step = swapStart ? -1 : 1; 509 int step = swapStart ? -1 : 1;
223 int oStep = swapOther ? -1 : 1; 510 int oStep = swapOther ? -1 : 1;
224 double oMatchStart = cancel ? oEndT : oStartT; 511 double oMatchStart = cancel ? oEndT : oStartT;
225 if (partial ? startT != 0 || oMatchStart != 0 : (startT == 0) != (oMatch Start == 0)) { 512 if (partial ? startT != 0 || oMatchStart != 0 : (startT == 0) != (oMatch Start == 0)) {
(...skipping 10 matching lines...) Expand all
236 if (partial ? endT != 1 || oMatchEnd != 1 : (endT == 1) != (oMatchEnd == 1)) { 523 if (partial ? endT != 1 || oMatchEnd != 1 : (endT == 1) != (oMatchEnd == 1)) {
237 bool added = false; 524 bool added = false;
238 if (cancel && endT != 1 && !added) { 525 if (cancel && endT != 1 && !added) {
239 (void) other.joinCoincidence(&thisOne, endT, *endPt, -step, canc el); 526 (void) other.joinCoincidence(&thisOne, endT, *endPt, -step, canc el);
240 } 527 }
241 } 528 }
242 } 529 }
243 } 530 }
244 531
245 void SkOpContour::calcCommonCoincidentWinding(const SkCoincidence& coincidence) { 532 void SkOpContour::calcCommonCoincidentWinding(const SkCoincidence& coincidence) {
533 if (coincidence.fNearly[0] && coincidence.fNearly[1]) {
534 return;
535 }
246 int thisIndex = coincidence.fSegments[0]; 536 int thisIndex = coincidence.fSegments[0];
247 SkOpSegment& thisOne = fSegments[thisIndex]; 537 SkOpSegment& thisOne = fSegments[thisIndex];
248 if (thisOne.done()) { 538 if (thisOne.done()) {
249 return; 539 return;
250 } 540 }
251 SkOpContour* otherContour = coincidence.fOther; 541 SkOpContour* otherContour = coincidence.fOther;
252 int otherIndex = coincidence.fSegments[1]; 542 int otherIndex = coincidence.fSegments[1];
253 SkOpSegment& other = otherContour->fSegments[otherIndex]; 543 SkOpSegment& other = otherContour->fSegments[otherIndex];
254 if (other.done()) { 544 if (other.done()) {
255 return; 545 return;
256 } 546 }
257 double startT = coincidence.fTs[0][0]; 547 double startT = coincidence.fTs[0][0];
258 double endT = coincidence.fTs[0][1]; 548 double endT = coincidence.fTs[0][1];
259 const SkPoint* startPt = &coincidence.fPts[0]; 549 const SkPoint* startPt = &coincidence.fPts[0][0];
260 const SkPoint* endPt = &coincidence.fPts[1]; 550 const SkPoint* endPt = &coincidence.fPts[0][1];
261 bool cancelers; 551 bool cancelers;
262 if ((cancelers = startT > endT)) { 552 if ((cancelers = startT > endT)) {
263 SkTSwap<double>(startT, endT); 553 SkTSwap<double>(startT, endT);
264 SkTSwap<const SkPoint*>(startPt, endPt); 554 SkTSwap<const SkPoint*>(startPt, endPt);
265 } 555 }
266 if (startT == endT) { // if span is very large, the smaller may have collaps ed to nothing 556 if (startT == endT) { // if span is very large, the smaller may have collaps ed to nothing
267 if (endT <= 1 - FLT_EPSILON) { 557 if (endT <= 1 - FLT_EPSILON) {
268 endT += FLT_EPSILON; 558 endT += FLT_EPSILON;
269 SkASSERT(endT <= 1); 559 SkASSERT(endT <= 1);
270 } else { 560 } else {
(...skipping 13 matching lines...) Expand all
284 thisOne.addTCancel(*startPt, *endPt, &other); 574 thisOne.addTCancel(*startPt, *endPt, &other);
285 } else { 575 } else {
286 thisOne.addTCoincident(*startPt, *endPt, endT, &other); 576 thisOne.addTCoincident(*startPt, *endPt, endT, &other);
287 } 577 }
288 #if DEBUG_CONCIDENT 578 #if DEBUG_CONCIDENT
289 thisOne.debugShowTs("p"); 579 thisOne.debugShowTs("p");
290 other.debugShowTs("o"); 580 other.debugShowTs("o");
291 #endif 581 #endif
292 } 582 }
293 583
584 void SkOpContour::resolveNearCoincidence() {
585 int count = fCoincidences.count();
586 for (int index = 0; index < count; ++index) {
587 SkCoincidence& coincidence = fCoincidences[index];
588 if (!coincidence.fNearly[0] || !coincidence.fNearly[1]) {
589 continue;
590 }
591 int thisIndex = coincidence.fSegments[0];
592 SkOpSegment& thisOne = fSegments[thisIndex];
593 SkOpContour* otherContour = coincidence.fOther;
594 int otherIndex = coincidence.fSegments[1];
595 SkOpSegment& other = otherContour->fSegments[otherIndex];
596 if ((thisOne.done() || other.done()) && thisOne.complete() && other.comp lete()) {
597 // OPTIMIZATION: remove from coincidence array
598 continue;
599 }
600 #if DEBUG_CONCIDENT
601 thisOne.debugShowTs("-");
602 other.debugShowTs("o");
603 #endif
604 double startT = coincidence.fTs[0][0];
605 double endT = coincidence.fTs[0][1];
606 bool cancelers;
607 if ((cancelers = startT > endT)) {
608 SkTSwap<double>(startT, endT);
609 }
610 if (startT == endT) { // if span is very large, the smaller may have col lapsed to nothing
611 if (endT <= 1 - FLT_EPSILON) {
612 endT += FLT_EPSILON;
613 SkASSERT(endT <= 1);
614 } else {
615 startT -= FLT_EPSILON;
616 SkASSERT(startT >= 0);
617 }
618 }
619 SkASSERT(!approximately_negative(endT - startT));
620 double oStartT = coincidence.fTs[1][0];
621 double oEndT = coincidence.fTs[1][1];
622 if (oStartT > oEndT) {
623 SkTSwap<double>(oStartT, oEndT);
624 cancelers ^= true;
625 }
626 SkASSERT(!approximately_negative(oEndT - oStartT));
627 if (cancelers) {
628 thisOne.blindCancel(coincidence, &other);
629 } else {
630 thisOne.blindCoincident(coincidence, &other);
631 }
632 }
633 }
634
294 void SkOpContour::sortAngles() { 635 void SkOpContour::sortAngles() {
295 int segmentCount = fSegments.count(); 636 int segmentCount = fSegments.count();
296 for (int test = 0; test < segmentCount; ++test) { 637 for (int test = 0; test < segmentCount; ++test) {
297 fSegments[test].sortAngles(); 638 fSegments[test].sortAngles();
298 } 639 }
299 } 640 }
300 641
301 void SkOpContour::sortSegments() { 642 void SkOpContour::sortSegments() {
302 int segmentCount = fSegments.count(); 643 int segmentCount = fSegments.count();
303 fSortedSegments.push_back_n(segmentCount); 644 fSortedSegments.push_back_n(segmentCount);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 SkDebugf("%s empty contour\n", __FUNCTION__); 741 SkDebugf("%s empty contour\n", __FUNCTION__);
401 SkASSERT(0); 742 SkASSERT(0);
402 // FIXME: delete empty contour? 743 // FIXME: delete empty contour?
403 return; 744 return;
404 } 745 }
405 fBounds = fSegments.front().bounds(); 746 fBounds = fSegments.front().bounds();
406 for (int index = 1; index < count; ++index) { 747 for (int index = 1; index < count; ++index) {
407 fBounds.add(fSegments[index].bounds()); 748 fBounds.add(fSegments[index].bounds());
408 } 749 }
409 } 750 }
OLDNEW
« no previous file with comments | « src/pathops/SkOpContour.h ('k') | src/pathops/SkOpSegment.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698