Flutter Engine
The Flutter Engine
SkAddIntersections.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
9
25
26#include <cmath>
27#include <utility>
28
29#if DEBUG_ADD_INTERSECTING_TS
30
31static void debugShowLineIntersection(int pts, const SkIntersectionHelper& wt,
32 const SkIntersectionHelper& wn, const SkIntersections& i) {
33 SkASSERT(i.used() == pts);
34 if (!pts) {
35 SkDebugf("%s no intersect " LINE_DEBUG_STR " " LINE_DEBUG_STR "\n",
36 __FUNCTION__, LINE_DEBUG_DATA(wt.pts()), LINE_DEBUG_DATA(wn.pts()));
37 return;
38 }
39 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " LINE_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
40 i[0][0], LINE_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
41 if (pts == 2) {
42 SkDebugf(" " T_DEBUG_STR(wtTs, 1) " " PT_DEBUG_STR, i[0][1], PT_DEBUG_DATA(i, 1));
43 }
44 SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i[1][0], LINE_DEBUG_DATA(wn.pts()));
45 if (pts == 2) {
46 SkDebugf(" " T_DEBUG_STR(wnTs, 1), i[1][1]);
47 }
48 SkDebugf("\n");
49}
50
51static void debugShowQuadLineIntersection(int pts, const SkIntersectionHelper& wt,
52 const SkIntersectionHelper& wn,
53 const SkIntersections& i) {
54 SkASSERT(i.used() == pts);
55 if (!pts) {
56 SkDebugf("%s no intersect " QUAD_DEBUG_STR " " LINE_DEBUG_STR "\n",
57 __FUNCTION__, QUAD_DEBUG_DATA(wt.pts()), LINE_DEBUG_DATA(wn.pts()));
58 return;
59 }
60 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " QUAD_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
61 i[0][0], QUAD_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
62 for (int n = 1; n < pts; ++n) {
63 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
64 }
65 SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i[1][0], LINE_DEBUG_DATA(wn.pts()));
66 for (int n = 1; n < pts; ++n) {
67 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
68 }
69 SkDebugf("\n");
70}
71
72static void debugShowQuadIntersection(int pts, const SkIntersectionHelper& wt,
73 const SkIntersectionHelper& wn, const SkIntersections& i) {
74 SkASSERT(i.used() == pts);
75 if (!pts) {
76 SkDebugf("%s no intersect " QUAD_DEBUG_STR " " QUAD_DEBUG_STR "\n",
77 __FUNCTION__, QUAD_DEBUG_DATA(wt.pts()), QUAD_DEBUG_DATA(wn.pts()));
78 return;
79 }
80 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " QUAD_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
81 i[0][0], QUAD_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
82 for (int n = 1; n < pts; ++n) {
83 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
84 }
85 SkDebugf(" wnTs[0]=%g " QUAD_DEBUG_STR, i[1][0], QUAD_DEBUG_DATA(wn.pts()));
86 for (int n = 1; n < pts; ++n) {
87 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
88 }
89 SkDebugf("\n");
90}
91
92static void debugShowConicLineIntersection(int pts, const SkIntersectionHelper& wt,
93 const SkIntersectionHelper& wn, const SkIntersections& i) {
94 SkASSERT(i.used() == pts);
95 if (!pts) {
96 SkDebugf("%s no intersect " CONIC_DEBUG_STR " " LINE_DEBUG_STR "\n",
97 __FUNCTION__, CONIC_DEBUG_DATA(wt.pts(), wt.weight()), LINE_DEBUG_DATA(wn.pts()));
98 return;
99 }
100 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CONIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
101 i[0][0], CONIC_DEBUG_DATA(wt.pts(), wt.weight()), PT_DEBUG_DATA(i, 0));
102 for (int n = 1; n < pts; ++n) {
103 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
104 }
105 SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i[1][0], LINE_DEBUG_DATA(wn.pts()));
106 for (int n = 1; n < pts; ++n) {
107 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
108 }
109 SkDebugf("\n");
110}
111
112static void debugShowConicQuadIntersection(int pts, const SkIntersectionHelper& wt,
113 const SkIntersectionHelper& wn, const SkIntersections& i) {
114 SkASSERT(i.used() == pts);
115 if (!pts) {
116 SkDebugf("%s no intersect " CONIC_DEBUG_STR " " QUAD_DEBUG_STR "\n",
117 __FUNCTION__, CONIC_DEBUG_DATA(wt.pts(), wt.weight()), QUAD_DEBUG_DATA(wn.pts()));
118 return;
119 }
120 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CONIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
121 i[0][0], CONIC_DEBUG_DATA(wt.pts(), wt.weight()), PT_DEBUG_DATA(i, 0));
122 for (int n = 1; n < pts; ++n) {
123 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
124 }
125 SkDebugf(" wnTs[0]=%g " QUAD_DEBUG_STR, i[1][0], QUAD_DEBUG_DATA(wn.pts()));
126 for (int n = 1; n < pts; ++n) {
127 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
128 }
129 SkDebugf("\n");
130}
131
132static void debugShowConicIntersection(int pts, const SkIntersectionHelper& wt,
133 const SkIntersectionHelper& wn, const SkIntersections& i) {
134 SkASSERT(i.used() == pts);
135 if (!pts) {
136 SkDebugf("%s no intersect " CONIC_DEBUG_STR " " CONIC_DEBUG_STR "\n",
137 __FUNCTION__, CONIC_DEBUG_DATA(wt.pts(), wt.weight()),
138 CONIC_DEBUG_DATA(wn.pts(), wn.weight()));
139 return;
140 }
141 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CONIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
142 i[0][0], CONIC_DEBUG_DATA(wt.pts(), wt.weight()), PT_DEBUG_DATA(i, 0));
143 for (int n = 1; n < pts; ++n) {
144 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
145 }
146 SkDebugf(" wnTs[0]=%g " CONIC_DEBUG_STR, i[1][0], CONIC_DEBUG_DATA(wn.pts(), wn.weight()));
147 for (int n = 1; n < pts; ++n) {
148 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
149 }
150 SkDebugf("\n");
151}
152
153static void debugShowCubicLineIntersection(int pts, const SkIntersectionHelper& wt,
154 const SkIntersectionHelper& wn, const SkIntersections& i) {
155 SkASSERT(i.used() == pts);
156 if (!pts) {
157 SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " LINE_DEBUG_STR "\n",
158 __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), LINE_DEBUG_DATA(wn.pts()));
159 return;
160 }
161 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
162 i[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
163 for (int n = 1; n < pts; ++n) {
164 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
165 }
166 SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i[1][0], LINE_DEBUG_DATA(wn.pts()));
167 for (int n = 1; n < pts; ++n) {
168 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
169 }
170 SkDebugf("\n");
171}
172
173static void debugShowCubicQuadIntersection(int pts, const SkIntersectionHelper& wt,
174 const SkIntersectionHelper& wn, const SkIntersections& i) {
175 SkASSERT(i.used() == pts);
176 if (!pts) {
177 SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " QUAD_DEBUG_STR "\n",
178 __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), QUAD_DEBUG_DATA(wn.pts()));
179 return;
180 }
181 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
182 i[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
183 for (int n = 1; n < pts; ++n) {
184 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
185 }
186 SkDebugf(" wnTs[0]=%g " QUAD_DEBUG_STR, i[1][0], QUAD_DEBUG_DATA(wn.pts()));
187 for (int n = 1; n < pts; ++n) {
188 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
189 }
190 SkDebugf("\n");
191}
192
193static void debugShowCubicConicIntersection(int pts, const SkIntersectionHelper& wt,
194 const SkIntersectionHelper& wn, const SkIntersections& i) {
195 SkASSERT(i.used() == pts);
196 if (!pts) {
197 SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " CONIC_DEBUG_STR "\n",
198 __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), CONIC_DEBUG_DATA(wn.pts(), wn.weight()));
199 return;
200 }
201 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
202 i[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
203 for (int n = 1; n < pts; ++n) {
204 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
205 }
206 SkDebugf(" wnTs[0]=%g " CONIC_DEBUG_STR, i[1][0], CONIC_DEBUG_DATA(wn.pts(), wn.weight()));
207 for (int n = 1; n < pts; ++n) {
208 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
209 }
210 SkDebugf("\n");
211}
212
213static void debugShowCubicIntersection(int pts, const SkIntersectionHelper& wt,
214 const SkIntersectionHelper& wn, const SkIntersections& i) {
215 SkASSERT(i.used() == pts);
216 if (!pts) {
217 SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " CUBIC_DEBUG_STR "\n",
218 __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), CUBIC_DEBUG_DATA(wn.pts()));
219 return;
220 }
221 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
222 i[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
223 for (int n = 1; n < pts; ++n) {
224 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
225 }
226 SkDebugf(" wnTs[0]=%g " CUBIC_DEBUG_STR, i[1][0], CUBIC_DEBUG_DATA(wn.pts()));
227 for (int n = 1; n < pts; ++n) {
228 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
229 }
230 SkDebugf("\n");
231}
232
233#else
235 const SkIntersectionHelper& , const SkIntersections& ) {
236}
237
239 const SkIntersectionHelper& , const SkIntersections& ) {
240}
241
243 const SkIntersectionHelper& , const SkIntersections& ) {
244}
245
247 const SkIntersectionHelper& , const SkIntersections& ) {
248}
249
251 const SkIntersectionHelper& , const SkIntersections& ) {
252}
253
255 const SkIntersectionHelper& , const SkIntersections& ) {
256}
257
259 const SkIntersectionHelper& , const SkIntersections& ) {
260}
261
263 const SkIntersectionHelper& , const SkIntersections& ) {
264}
265
267 const SkIntersectionHelper& , const SkIntersections& ) {
268}
269
271 const SkIntersectionHelper& , const SkIntersections& ) {
272}
273#endif
274
276 if (test != next) {
277 if (AlmostLessUlps(test->bounds().fBottom, next->bounds().fTop)) {
278 return false;
279 }
280 // OPTIMIZATION: outset contour bounds a smidgen instead?
281 if (!SkPathOpsBounds::Intersects(test->bounds(), next->bounds())) {
282 return true;
283 }
284 }
286 wt.init(test);
287 do {
289 wn.init(next);
290 test->debugValidate();
291 next->debugValidate();
292 if (test == next && !wn.startAfter(wt)) {
293 continue;
294 }
295 do {
296 if (!SkPathOpsBounds::Intersects(wt.bounds(), wn.bounds())) {
297 continue;
298 }
299 int pts = 0;
300 SkIntersections ts { SkDEBUGCODE(test->globalState()) };
301 bool swap = false;
302 SkDQuad quad1, quad2;
303 SkDConic conic1, conic2;
304 SkDCubic cubic1, cubic2;
305 switch (wt.segmentType()) {
307 swap = true;
308 switch (wn.segmentType()) {
312 pts = ts.lineHorizontal(wn.pts(), wt.left(),
313 wt.right(), wt.y(), wt.xFlipped());
314 debugShowLineIntersection(pts, wn, wt, ts);
315 break;
317 pts = ts.quadHorizontal(wn.pts(), wt.left(),
318 wt.right(), wt.y(), wt.xFlipped());
319 debugShowQuadLineIntersection(pts, wn, wt, ts);
320 break;
322 pts = ts.conicHorizontal(wn.pts(), wn.weight(), wt.left(),
323 wt.right(), wt.y(), wt.xFlipped());
324 debugShowConicLineIntersection(pts, wn, wt, ts);
325 break;
327 pts = ts.cubicHorizontal(wn.pts(), wt.left(),
328 wt.right(), wt.y(), wt.xFlipped());
329 debugShowCubicLineIntersection(pts, wn, wt, ts);
330 break;
331 default:
332 SkASSERT(0);
333 }
334 break;
336 swap = true;
337 switch (wn.segmentType()) {
341 pts = ts.lineVertical(wn.pts(), wt.top(),
342 wt.bottom(), wt.x(), wt.yFlipped());
343 debugShowLineIntersection(pts, wn, wt, ts);
344 break;
345 }
347 pts = ts.quadVertical(wn.pts(), wt.top(),
348 wt.bottom(), wt.x(), wt.yFlipped());
349 debugShowQuadLineIntersection(pts, wn, wt, ts);
350 break;
351 }
353 pts = ts.conicVertical(wn.pts(), wn.weight(), wt.top(),
354 wt.bottom(), wt.x(), wt.yFlipped());
355 debugShowConicLineIntersection(pts, wn, wt, ts);
356 break;
357 }
359 pts = ts.cubicVertical(wn.pts(), wt.top(),
360 wt.bottom(), wt.x(), wt.yFlipped());
361 debugShowCubicLineIntersection(pts, wn, wt, ts);
362 break;
363 }
364 default:
365 SkASSERT(0);
366 }
367 break;
369 switch (wn.segmentType()) {
371 pts = ts.lineHorizontal(wt.pts(), wn.left(),
372 wn.right(), wn.y(), wn.xFlipped());
373 debugShowLineIntersection(pts, wt, wn, ts);
374 break;
376 pts = ts.lineVertical(wt.pts(), wn.top(),
377 wn.bottom(), wn.x(), wn.yFlipped());
378 debugShowLineIntersection(pts, wt, wn, ts);
379 break;
381 pts = ts.lineLine(wt.pts(), wn.pts());
382 debugShowLineIntersection(pts, wt, wn, ts);
383 break;
385 swap = true;
386 pts = ts.quadLine(wn.pts(), wt.pts());
387 debugShowQuadLineIntersection(pts, wn, wt, ts);
388 break;
390 swap = true;
391 pts = ts.conicLine(wn.pts(), wn.weight(), wt.pts());
392 debugShowConicLineIntersection(pts, wn, wt, ts);
393 break;
395 swap = true;
396 pts = ts.cubicLine(wn.pts(), wt.pts());
397 debugShowCubicLineIntersection(pts, wn, wt, ts);
398 break;
399 default:
400 SkASSERT(0);
401 }
402 break;
404 switch (wn.segmentType()) {
406 pts = ts.quadHorizontal(wt.pts(), wn.left(),
407 wn.right(), wn.y(), wn.xFlipped());
408 debugShowQuadLineIntersection(pts, wt, wn, ts);
409 break;
411 pts = ts.quadVertical(wt.pts(), wn.top(),
412 wn.bottom(), wn.x(), wn.yFlipped());
413 debugShowQuadLineIntersection(pts, wt, wn, ts);
414 break;
416 pts = ts.quadLine(wt.pts(), wn.pts());
417 debugShowQuadLineIntersection(pts, wt, wn, ts);
418 break;
420 pts = ts.intersect(quad1.set(wt.pts()), quad2.set(wn.pts()));
421 debugShowQuadIntersection(pts, wt, wn, ts);
422 break;
423 }
425 swap = true;
426 pts = ts.intersect(conic2.set(wn.pts(), wn.weight()),
427 quad1.set(wt.pts()));
428 debugShowConicQuadIntersection(pts, wn, wt, ts);
429 break;
430 }
432 swap = true;
433 pts = ts.intersect(cubic2.set(wn.pts()), quad1.set(wt.pts()));
434 debugShowCubicQuadIntersection(pts, wn, wt, ts);
435 break;
436 }
437 default:
438 SkASSERT(0);
439 }
440 break;
442 switch (wn.segmentType()) {
444 pts = ts.conicHorizontal(wt.pts(), wt.weight(), wn.left(),
445 wn.right(), wn.y(), wn.xFlipped());
446 debugShowConicLineIntersection(pts, wt, wn, ts);
447 break;
449 pts = ts.conicVertical(wt.pts(), wt.weight(), wn.top(),
450 wn.bottom(), wn.x(), wn.yFlipped());
451 debugShowConicLineIntersection(pts, wt, wn, ts);
452 break;
454 pts = ts.conicLine(wt.pts(), wt.weight(), wn.pts());
455 debugShowConicLineIntersection(pts, wt, wn, ts);
456 break;
458 pts = ts.intersect(conic1.set(wt.pts(), wt.weight()),
459 quad2.set(wn.pts()));
460 debugShowConicQuadIntersection(pts, wt, wn, ts);
461 break;
462 }
464 pts = ts.intersect(conic1.set(wt.pts(), wt.weight()),
465 conic2.set(wn.pts(), wn.weight()));
466 debugShowConicIntersection(pts, wt, wn, ts);
467 break;
468 }
470 swap = true;
471 pts = ts.intersect(cubic2.set(wn.pts()
472 SkDEBUGPARAMS(ts.globalState())),
473 conic1.set(wt.pts(), wt.weight()
474 SkDEBUGPARAMS(ts.globalState())));
475 debugShowCubicConicIntersection(pts, wn, wt, ts);
476 break;
477 }
478 }
479 break;
481 switch (wn.segmentType()) {
483 pts = ts.cubicHorizontal(wt.pts(), wn.left(),
484 wn.right(), wn.y(), wn.xFlipped());
485 debugShowCubicLineIntersection(pts, wt, wn, ts);
486 break;
488 pts = ts.cubicVertical(wt.pts(), wn.top(),
489 wn.bottom(), wn.x(), wn.yFlipped());
490 debugShowCubicLineIntersection(pts, wt, wn, ts);
491 break;
493 pts = ts.cubicLine(wt.pts(), wn.pts());
494 debugShowCubicLineIntersection(pts, wt, wn, ts);
495 break;
497 pts = ts.intersect(cubic1.set(wt.pts()), quad2.set(wn.pts()));
498 debugShowCubicQuadIntersection(pts, wt, wn, ts);
499 break;
500 }
502 pts = ts.intersect(cubic1.set(wt.pts()
503 SkDEBUGPARAMS(ts.globalState())),
504 conic2.set(wn.pts(), wn.weight()
505 SkDEBUGPARAMS(ts.globalState())));
506 debugShowCubicConicIntersection(pts, wt, wn, ts);
507 break;
508 }
510 pts = ts.intersect(cubic1.set(wt.pts()), cubic2.set(wn.pts()));
511 debugShowCubicIntersection(pts, wt, wn, ts);
512 break;
513 }
514 default:
515 SkASSERT(0);
516 }
517 break;
518 default:
519 SkASSERT(0);
520 }
521#if DEBUG_T_SECT_LOOP_COUNT
522 test->globalState()->debugAddLoopCount(&ts, wt, wn);
523#endif
524 int coinIndex = -1;
525 SkOpPtT* coinPtT[2];
526 for (int pt = 0; pt < pts; ++pt) {
527 SkASSERT(ts[0][pt] >= 0 && ts[0][pt] <= 1);
528 SkASSERT(ts[1][pt] >= 0 && ts[1][pt] <= 1);
529 wt.segment()->debugValidate();
530 // if t value is used to compute pt in addT, error may creep in and
531 // rect intersections may result in non-rects. if pt value from intersection
532 // is passed in, current tests break. As a workaround, pass in pt
533 // value from intersection only if pt.x and pt.y is integral
534 SkPoint iPt = ts.pt(pt).asSkPoint();
535 bool iPtIsIntegral = iPt.fX == floor(iPt.fX) && iPt.fY == floor(iPt.fY);
536 SkOpPtT* testTAt = iPtIsIntegral ? wt.segment()->addT(ts[swap][pt], iPt)
537 : wt.segment()->addT(ts[swap][pt]);
538 wn.segment()->debugValidate();
539 SkOpPtT* nextTAt = iPtIsIntegral ? wn.segment()->addT(ts[!swap][pt], iPt)
540 : wn.segment()->addT(ts[!swap][pt]);
541 if (!testTAt->contains(nextTAt)) {
542 SkOpPtT* oppPrev = testTAt->oppPrev(nextTAt); // Returns nullptr if pair
543 if (oppPrev) { // already share a pt-t loop.
544 testTAt->span()->mergeMatches(nextTAt->span());
545 testTAt->addOpp(nextTAt, oppPrev);
546 }
547 if (testTAt->fPt != nextTAt->fPt) {
548 testTAt->span()->unaligned();
549 nextTAt->span()->unaligned();
550 }
551 wt.segment()->debugValidate();
552 wn.segment()->debugValidate();
553 }
554 if (!ts.isCoincident(pt)) {
555 continue;
556 }
557 if (coinIndex < 0) {
558 coinPtT[0] = testTAt;
559 coinPtT[1] = nextTAt;
560 coinIndex = pt;
561 continue;
562 }
563 if (coinPtT[0]->span() == testTAt->span()) {
564 coinIndex = -1;
565 continue;
566 }
567 if (coinPtT[1]->span() == nextTAt->span()) {
568 coinIndex = -1; // coincidence span collapsed
569 continue;
570 }
571 if (swap) {
572 using std::swap;
573 swap(coinPtT[0], coinPtT[1]);
574 swap(testTAt, nextTAt);
575 }
576 SkASSERT(coincidence->globalState()->debugSkipAssert()
577 || coinPtT[0]->span()->t() < testTAt->span()->t());
578 if (coinPtT[0]->span()->deleted()) {
579 coinIndex = -1;
580 continue;
581 }
582 if (testTAt->span()->deleted()) {
583 coinIndex = -1;
584 continue;
585 }
586 coincidence->add(coinPtT[0], testTAt, coinPtT[1], nextTAt);
587 wt.segment()->debugValidate();
588 wn.segment()->debugValidate();
589 coinIndex = -1;
590 }
591 SkOPOBJASSERT(coincidence, coinIndex < 0); // expect coincidence to be paired
592 } while (wn.advance());
593 } while (wt.advance());
594 return true;
595}
static float next(float f)
static void debugShowConicQuadIntersection(int, const SkIntersectionHelper &, const SkIntersectionHelper &, const SkIntersections &)
static void debugShowQuadIntersection(int, const SkIntersectionHelper &, const SkIntersectionHelper &, const SkIntersections &)
static void debugShowQuadLineIntersection(int, const SkIntersectionHelper &, const SkIntersectionHelper &, const SkIntersections &)
static void debugShowCubicIntersection(int, const SkIntersectionHelper &, const SkIntersectionHelper &, const SkIntersections &)
bool AddIntersectTs(SkOpContour *test, SkOpContour *next, SkOpCoincidence *coincidence)
static void debugShowCubicConicIntersection(int, const SkIntersectionHelper &, const SkIntersectionHelper &, const SkIntersections &)
static void debugShowLineIntersection(int, const SkIntersectionHelper &, const SkIntersectionHelper &, const SkIntersections &)
static void debugShowConicLineIntersection(int, const SkIntersectionHelper &, const SkIntersectionHelper &, const SkIntersections &)
static void debugShowConicIntersection(int, const SkIntersectionHelper &, const SkIntersectionHelper &, const SkIntersections &)
static void debugShowCubicLineIntersection(int, const SkIntersectionHelper &, const SkIntersectionHelper &, const SkIntersections &)
static void debugShowCubicQuadIntersection(int, const SkIntersectionHelper &, const SkIntersectionHelper &, const SkIntersections &)
#define SkASSERT(cond)
Definition: SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
#define CONIC_DEBUG_DATA(c, w)
#define CUBIC_DEBUG_STR
#define CONIC_DEBUG_STR
#define SkDEBUGPARAMS(...)
#define TX_DEBUG_STR(t)
#define LINE_DEBUG_STR
#define PT_DEBUG_DATA(i, n)
#define QUAD_DEBUG_STR
#define LINE_DEBUG_DATA(l)
#define T_DEBUG_STR(t, n)
#define PT_DEBUG_STR
#define CUBIC_DEBUG_DATA(c)
#define QUAD_DEBUG_DATA(q)
bool AlmostLessUlps(float a, float b)
#define SkOPOBJASSERT(obj, cond)
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition: SkRefCnt.h:341
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
const SkPathOpsBounds & bounds() const
bool startAfter(const SkIntersectionHelper &after)
SkOpSegment * segment() const
void init(SkOpContour *contour)
SegmentType segmentType() const
const SkPoint * pts() const
void add(SkOpPtT *coinPtTStart, SkOpPtT *coinPtTEnd, SkOpPtT *oppPtTStart, SkOpPtT *oppPtTEnd)
SkOpGlobalState * globalState()
const SkOpSpanBase * span() const
Definition: SkOpSpan.h:154
SkPoint fPt
Definition: SkOpSpan.h:167
SkOpPtT * oppPrev(const SkOpPtT *opp) const
Definition: SkOpSpan.h:104
void addOpp(SkOpPtT *opp, SkOpPtT *oppPrev)
Definition: SkOpSpan.h:34
bool contains(const SkOpPtT *) const
Definition: SkOpSpan.cpp:36
void debugValidate() const
SkOpPtT * addT(double t)
bool mergeMatches(SkOpSpanBase *opp)
Definition: SkOpSpan.cpp:313
void unaligned()
Definition: SkOpSpan.h:379
bool deleted() const
Definition: SkOpSpan.h:261
double t() const
Definition: SkOpSpan.h:375
SIN Vec< N, float > floor(const Vec< N, float > &x)
Definition: SkVx.h:703
const SkDConic & set(const SkPoint pts[kPointCount], SkScalar weight SkDEBUGPARAMS(SkOpGlobalState *state=nullptr))
const SkDCubic & set(const SkPoint pts[kPointCount] SkDEBUGPARAMS(SkOpGlobalState *state=nullptr))
const SkDQuad & set(const SkPoint pts[kPointCount] SkDEBUGPARAMS(SkOpGlobalState *state=nullptr))
Definition: SkPathOpsQuad.h:65
static bool Intersects(const SkPathOpsBounds &a, const SkPathOpsBounds &b)
float fX
x-axis value
Definition: SkPoint_impl.h:164
float fY
y-axis value
Definition: SkPoint_impl.h:165