blob: b47e7df5993caaa2532863cb373eed8af7166de2 [file] [log] [blame]
caryclark@google.com07393ca2013-04-08 11:47:37 +00001/*
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#include "SkAddIntersections.h"
caryclark54359292015-03-26 07:52:43 -07008#include "SkOpCoincidence.h"
caryclark@google.com07393ca2013-04-08 11:47:37 +00009#include "SkPathOpsBounds.h"
10
11#if DEBUG_ADD_INTERSECTING_TS
12
13static void debugShowLineIntersection(int pts, const SkIntersectionHelper& wt,
14 const SkIntersectionHelper& wn, const SkIntersections& i) {
15 SkASSERT(i.used() == pts);
16 if (!pts) {
17 SkDebugf("%s no intersect " LINE_DEBUG_STR " " LINE_DEBUG_STR "\n",
18 __FUNCTION__, LINE_DEBUG_DATA(wt.pts()), LINE_DEBUG_DATA(wn.pts()));
19 return;
20 }
21 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " LINE_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
22 i[0][0], LINE_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
23 if (pts == 2) {
24 SkDebugf(" " T_DEBUG_STR(wtTs, 1) " " PT_DEBUG_STR, i[0][1], PT_DEBUG_DATA(i, 1));
25 }
26 SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i[1][0], LINE_DEBUG_DATA(wn.pts()));
27 if (pts == 2) {
28 SkDebugf(" " T_DEBUG_STR(wnTs, 1), i[1][1]);
29 }
30 SkDebugf("\n");
31}
32
33static void debugShowQuadLineIntersection(int pts, const SkIntersectionHelper& wt,
34 const SkIntersectionHelper& wn,
35 const SkIntersections& i) {
36 SkASSERT(i.used() == pts);
37 if (!pts) {
38 SkDebugf("%s no intersect " QUAD_DEBUG_STR " " LINE_DEBUG_STR "\n",
39 __FUNCTION__, QUAD_DEBUG_DATA(wt.pts()), LINE_DEBUG_DATA(wn.pts()));
40 return;
41 }
42 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " QUAD_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
43 i[0][0], QUAD_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
44 for (int n = 1; n < pts; ++n) {
45 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
46 }
47 SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i[1][0], LINE_DEBUG_DATA(wn.pts()));
48 for (int n = 1; n < pts; ++n) {
49 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
50 }
51 SkDebugf("\n");
52}
53
54static void debugShowQuadIntersection(int pts, const SkIntersectionHelper& wt,
55 const SkIntersectionHelper& wn, const SkIntersections& i) {
56 SkASSERT(i.used() == pts);
57 if (!pts) {
58 SkDebugf("%s no intersect " QUAD_DEBUG_STR " " QUAD_DEBUG_STR "\n",
59 __FUNCTION__, QUAD_DEBUG_DATA(wt.pts()), QUAD_DEBUG_DATA(wn.pts()));
60 return;
61 }
62 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " QUAD_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
63 i[0][0], QUAD_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
64 for (int n = 1; n < pts; ++n) {
65 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
66 }
67 SkDebugf(" wnTs[0]=%g " QUAD_DEBUG_STR, i[1][0], QUAD_DEBUG_DATA(wn.pts()));
68 for (int n = 1; n < pts; ++n) {
69 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
70 }
71 SkDebugf("\n");
72}
73
caryclark1049f122015-04-20 08:31:59 -070074static void debugShowConicLineIntersection(int pts, const SkIntersectionHelper& wt,
75 const SkIntersectionHelper& wn, const SkIntersections& i) {
76 SkASSERT(i.used() == pts);
77 if (!pts) {
78 SkDebugf("%s no intersect " CONIC_DEBUG_STR " " LINE_DEBUG_STR "\n",
79 __FUNCTION__, CONIC_DEBUG_DATA(wt.pts(), wt.weight()), LINE_DEBUG_DATA(wn.pts()));
80 return;
81 }
82 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CONIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
83 i[0][0], CONIC_DEBUG_DATA(wt.pts(), wt.weight()), PT_DEBUG_DATA(i, 0));
84 for (int n = 1; n < pts; ++n) {
85 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
86 }
87 SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i[1][0], LINE_DEBUG_DATA(wn.pts()));
88 for (int n = 1; n < pts; ++n) {
89 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
90 }
91 SkDebugf("\n");
92}
93
94static void debugShowConicQuadIntersection(int pts, const SkIntersectionHelper& wt,
95 const SkIntersectionHelper& wn, const SkIntersections& i) {
96 SkASSERT(i.used() == pts);
97 if (!pts) {
98 SkDebugf("%s no intersect " CONIC_DEBUG_STR " " QUAD_DEBUG_STR "\n",
99 __FUNCTION__, CONIC_DEBUG_DATA(wt.pts(), wt.weight()), QUAD_DEBUG_DATA(wn.pts()));
100 return;
101 }
102 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CONIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
103 i[0][0], CONIC_DEBUG_DATA(wt.pts(), wt.weight()), PT_DEBUG_DATA(i, 0));
104 for (int n = 1; n < pts; ++n) {
105 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
106 }
107 SkDebugf(" wnTs[0]=%g " QUAD_DEBUG_STR, i[1][0], QUAD_DEBUG_DATA(wn.pts()));
108 for (int n = 1; n < pts; ++n) {
109 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
110 }
111 SkDebugf("\n");
112}
113
114static void debugShowConicIntersection(int pts, const SkIntersectionHelper& wt,
115 const SkIntersectionHelper& wn, const SkIntersections& i) {
116 SkASSERT(i.used() == pts);
117 if (!pts) {
118 SkDebugf("%s no intersect " CONIC_DEBUG_STR " " CONIC_DEBUG_STR "\n",
119 __FUNCTION__, CONIC_DEBUG_DATA(wt.pts(), wt.weight()),
120 CONIC_DEBUG_DATA(wn.pts(), wn.weight()));
121 return;
122 }
123 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CONIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
124 i[0][0], CONIC_DEBUG_DATA(wt.pts(), wt.weight()), PT_DEBUG_DATA(i, 0));
125 for (int n = 1; n < pts; ++n) {
126 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
127 }
128 SkDebugf(" wnTs[0]=%g " CONIC_DEBUG_STR, i[1][0], CONIC_DEBUG_DATA(wn.pts(), wn.weight()));
129 for (int n = 1; n < pts; ++n) {
130 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
131 }
132 SkDebugf("\n");
133}
134
caryclark@google.com07393ca2013-04-08 11:47:37 +0000135static void debugShowCubicLineIntersection(int pts, const SkIntersectionHelper& wt,
136 const SkIntersectionHelper& wn, const SkIntersections& i) {
137 SkASSERT(i.used() == pts);
138 if (!pts) {
139 SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " LINE_DEBUG_STR "\n",
140 __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), LINE_DEBUG_DATA(wn.pts()));
141 return;
142 }
143 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
144 i[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
145 for (int n = 1; n < pts; ++n) {
146 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
147 }
148 SkDebugf(" wnTs[0]=%g " LINE_DEBUG_STR, i[1][0], LINE_DEBUG_DATA(wn.pts()));
149 for (int n = 1; n < pts; ++n) {
150 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
151 }
152 SkDebugf("\n");
153}
154
155static void debugShowCubicQuadIntersection(int pts, const SkIntersectionHelper& wt,
156 const SkIntersectionHelper& wn, const SkIntersections& i) {
157 SkASSERT(i.used() == pts);
158 if (!pts) {
159 SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " QUAD_DEBUG_STR "\n",
160 __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), QUAD_DEBUG_DATA(wn.pts()));
161 return;
162 }
163 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
164 i[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
165 for (int n = 1; n < pts; ++n) {
166 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
167 }
168 SkDebugf(" wnTs[0]=%g " QUAD_DEBUG_STR, i[1][0], QUAD_DEBUG_DATA(wn.pts()));
169 for (int n = 1; n < pts; ++n) {
170 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
171 }
172 SkDebugf("\n");
173}
174
caryclark1049f122015-04-20 08:31:59 -0700175static void debugShowCubicConicIntersection(int pts, const SkIntersectionHelper& wt,
176 const SkIntersectionHelper& wn, const SkIntersections& i) {
177 SkASSERT(i.used() == pts);
178 if (!pts) {
179 SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " CONIC_DEBUG_STR "\n",
180 __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), CONIC_DEBUG_DATA(wn.pts(), wn.weight()));
181 return;
182 }
183 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
184 i[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
185 for (int n = 1; n < pts; ++n) {
186 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
187 }
188 SkDebugf(" wnTs[0]=%g " CONIC_DEBUG_STR, i[1][0], CONIC_DEBUG_DATA(wn.pts(), wn.weight()));
189 for (int n = 1; n < pts; ++n) {
190 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
191 }
192 SkDebugf("\n");
193}
194
caryclark@google.com07393ca2013-04-08 11:47:37 +0000195static void debugShowCubicIntersection(int pts, const SkIntersectionHelper& wt,
196 const SkIntersectionHelper& wn, const SkIntersections& i) {
197 SkASSERT(i.used() == pts);
198 if (!pts) {
199 SkDebugf("%s no intersect " CUBIC_DEBUG_STR " " CUBIC_DEBUG_STR "\n",
200 __FUNCTION__, CUBIC_DEBUG_DATA(wt.pts()), CUBIC_DEBUG_DATA(wn.pts()));
201 return;
202 }
203 SkDebugf("%s " T_DEBUG_STR(wtTs, 0) " " CUBIC_DEBUG_STR " " PT_DEBUG_STR, __FUNCTION__,
204 i[0][0], CUBIC_DEBUG_DATA(wt.pts()), PT_DEBUG_DATA(i, 0));
205 for (int n = 1; n < pts; ++n) {
206 SkDebugf(" " TX_DEBUG_STR(wtTs) " " PT_DEBUG_STR, n, i[0][n], PT_DEBUG_DATA(i, n));
207 }
208 SkDebugf(" wnTs[0]=%g " CUBIC_DEBUG_STR, i[1][0], CUBIC_DEBUG_DATA(wn.pts()));
209 for (int n = 1; n < pts; ++n) {
210 SkDebugf(" " TX_DEBUG_STR(wnTs), n, i[1][n]);
211 }
212 SkDebugf("\n");
213}
214
caryclark@google.com07393ca2013-04-08 11:47:37 +0000215#else
216static void debugShowLineIntersection(int , const SkIntersectionHelper& ,
217 const SkIntersectionHelper& , const SkIntersections& ) {
218}
219
220static void debugShowQuadLineIntersection(int , const SkIntersectionHelper& ,
221 const SkIntersectionHelper& , const SkIntersections& ) {
222}
223
224static void debugShowQuadIntersection(int , const SkIntersectionHelper& ,
225 const SkIntersectionHelper& , const SkIntersections& ) {
226}
227
caryclark1049f122015-04-20 08:31:59 -0700228static void debugShowConicLineIntersection(int , const SkIntersectionHelper& ,
229 const SkIntersectionHelper& , const SkIntersections& ) {
230}
231
232static void debugShowConicQuadIntersection(int , const SkIntersectionHelper& ,
233 const SkIntersectionHelper& , const SkIntersections& ) {
234}
235
236static void debugShowConicIntersection(int , const SkIntersectionHelper& ,
237 const SkIntersectionHelper& , const SkIntersections& ) {
238}
239
caryclark@google.com07393ca2013-04-08 11:47:37 +0000240static void debugShowCubicLineIntersection(int , const SkIntersectionHelper& ,
241 const SkIntersectionHelper& , const SkIntersections& ) {
242}
243
244static void debugShowCubicQuadIntersection(int , const SkIntersectionHelper& ,
245 const SkIntersectionHelper& , const SkIntersections& ) {
246}
247
caryclark1049f122015-04-20 08:31:59 -0700248static void debugShowCubicConicIntersection(int , const SkIntersectionHelper& ,
249 const SkIntersectionHelper& , const SkIntersections& ) {
250}
251
caryclark@google.com07393ca2013-04-08 11:47:37 +0000252static void debugShowCubicIntersection(int , const SkIntersectionHelper& ,
253 const SkIntersectionHelper& , const SkIntersections& ) {
254}
caryclark@google.com07393ca2013-04-08 11:47:37 +0000255#endif
256
caryclark55888e42016-07-18 10:01:36 -0700257bool AddIntersectTs(SkOpContour* test, SkOpContour* next, SkOpCoincidence* coincidence) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000258 if (test != next) {
caryclark@google.com570863f2013-09-16 15:55:01 +0000259 if (AlmostLessUlps(test->bounds().fBottom, next->bounds().fTop)) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000260 return false;
261 }
caryclark@google.com570863f2013-09-16 15:55:01 +0000262 // OPTIMIZATION: outset contour bounds a smidgen instead?
caryclark@google.com07393ca2013-04-08 11:47:37 +0000263 if (!SkPathOpsBounds::Intersects(test->bounds(), next->bounds())) {
264 return true;
265 }
266 }
267 SkIntersectionHelper wt;
268 wt.init(test);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000269 do {
270 SkIntersectionHelper wn;
271 wn.init(next);
caryclark54359292015-03-26 07:52:43 -0700272 test->debugValidate();
273 next->debugValidate();
caryclark@google.com07393ca2013-04-08 11:47:37 +0000274 if (test == next && !wn.startAfter(wt)) {
275 continue;
276 }
277 do {
278 if (!SkPathOpsBounds::Intersects(wt.bounds(), wn.bounds())) {
279 continue;
280 }
281 int pts = 0;
caryclarkdae6b972016-06-08 04:28:19 -0700282 SkIntersections ts { SkDEBUGCODE(test->globalState()) };
caryclark@google.com07393ca2013-04-08 11:47:37 +0000283 bool swap = false;
caryclark1049f122015-04-20 08:31:59 -0700284 SkDQuad quad1, quad2;
285 SkDConic conic1, conic2;
286 SkDCubic cubic1, cubic2;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000287 switch (wt.segmentType()) {
288 case SkIntersectionHelper::kHorizontalLine_Segment:
289 swap = true;
290 switch (wn.segmentType()) {
291 case SkIntersectionHelper::kHorizontalLine_Segment:
292 case SkIntersectionHelper::kVerticalLine_Segment:
caryclark1049f122015-04-20 08:31:59 -0700293 case SkIntersectionHelper::kLine_Segment:
caryclark@google.com07393ca2013-04-08 11:47:37 +0000294 pts = ts.lineHorizontal(wn.pts(), wt.left(),
295 wt.right(), wt.y(), wt.xFlipped());
caryclark@google.coma5e55922013-05-07 18:51:31 +0000296 debugShowLineIntersection(pts, wn, wt, ts);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000297 break;
caryclark1049f122015-04-20 08:31:59 -0700298 case SkIntersectionHelper::kQuad_Segment:
caryclark@google.com07393ca2013-04-08 11:47:37 +0000299 pts = ts.quadHorizontal(wn.pts(), wt.left(),
300 wt.right(), wt.y(), wt.xFlipped());
301 debugShowQuadLineIntersection(pts, wn, wt, ts);
302 break;
caryclark1049f122015-04-20 08:31:59 -0700303 case SkIntersectionHelper::kConic_Segment:
304 pts = ts.conicHorizontal(wn.pts(), wn.weight(), wt.left(),
305 wt.right(), wt.y(), wt.xFlipped());
306 debugShowConicLineIntersection(pts, wn, wt, ts);
307 break;
308 case SkIntersectionHelper::kCubic_Segment:
caryclark@google.com07393ca2013-04-08 11:47:37 +0000309 pts = ts.cubicHorizontal(wn.pts(), wt.left(),
310 wt.right(), wt.y(), wt.xFlipped());
311 debugShowCubicLineIntersection(pts, wn, wt, ts);
312 break;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000313 default:
314 SkASSERT(0);
315 }
316 break;
317 case SkIntersectionHelper::kVerticalLine_Segment:
318 swap = true;
319 switch (wn.segmentType()) {
320 case SkIntersectionHelper::kHorizontalLine_Segment:
321 case SkIntersectionHelper::kVerticalLine_Segment:
322 case SkIntersectionHelper::kLine_Segment: {
323 pts = ts.lineVertical(wn.pts(), wt.top(),
324 wt.bottom(), wt.x(), wt.yFlipped());
caryclark@google.coma5e55922013-05-07 18:51:31 +0000325 debugShowLineIntersection(pts, wn, wt, ts);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000326 break;
327 }
328 case SkIntersectionHelper::kQuad_Segment: {
329 pts = ts.quadVertical(wn.pts(), wt.top(),
330 wt.bottom(), wt.x(), wt.yFlipped());
331 debugShowQuadLineIntersection(pts, wn, wt, ts);
332 break;
333 }
caryclark1049f122015-04-20 08:31:59 -0700334 case SkIntersectionHelper::kConic_Segment: {
335 pts = ts.conicVertical(wn.pts(), wn.weight(), wt.top(),
336 wt.bottom(), wt.x(), wt.yFlipped());
337 debugShowConicLineIntersection(pts, wn, wt, ts);
338 break;
339 }
caryclark@google.com07393ca2013-04-08 11:47:37 +0000340 case SkIntersectionHelper::kCubic_Segment: {
341 pts = ts.cubicVertical(wn.pts(), wt.top(),
342 wt.bottom(), wt.x(), wt.yFlipped());
343 debugShowCubicLineIntersection(pts, wn, wt, ts);
344 break;
345 }
346 default:
347 SkASSERT(0);
348 }
349 break;
350 case SkIntersectionHelper::kLine_Segment:
351 switch (wn.segmentType()) {
352 case SkIntersectionHelper::kHorizontalLine_Segment:
353 pts = ts.lineHorizontal(wt.pts(), wn.left(),
354 wn.right(), wn.y(), wn.xFlipped());
355 debugShowLineIntersection(pts, wt, wn, ts);
356 break;
357 case SkIntersectionHelper::kVerticalLine_Segment:
358 pts = ts.lineVertical(wt.pts(), wn.top(),
359 wn.bottom(), wn.x(), wn.yFlipped());
360 debugShowLineIntersection(pts, wt, wn, ts);
361 break;
caryclark1049f122015-04-20 08:31:59 -0700362 case SkIntersectionHelper::kLine_Segment:
caryclark@google.com07393ca2013-04-08 11:47:37 +0000363 pts = ts.lineLine(wt.pts(), wn.pts());
364 debugShowLineIntersection(pts, wt, wn, ts);
365 break;
caryclark1049f122015-04-20 08:31:59 -0700366 case SkIntersectionHelper::kQuad_Segment:
caryclark@google.com07393ca2013-04-08 11:47:37 +0000367 swap = true;
368 pts = ts.quadLine(wn.pts(), wt.pts());
369 debugShowQuadLineIntersection(pts, wn, wt, ts);
370 break;
caryclark1049f122015-04-20 08:31:59 -0700371 case SkIntersectionHelper::kConic_Segment:
372 swap = true;
373 pts = ts.conicLine(wn.pts(), wn.weight(), wt.pts());
374 debugShowConicLineIntersection(pts, wn, wt, ts);
375 break;
376 case SkIntersectionHelper::kCubic_Segment:
caryclark@google.com07393ca2013-04-08 11:47:37 +0000377 swap = true;
378 pts = ts.cubicLine(wn.pts(), wt.pts());
caryclark1049f122015-04-20 08:31:59 -0700379 debugShowCubicLineIntersection(pts, wn, wt, ts);
caryclark@google.com07393ca2013-04-08 11:47:37 +0000380 break;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000381 default:
382 SkASSERT(0);
383 }
384 break;
385 case SkIntersectionHelper::kQuad_Segment:
386 switch (wn.segmentType()) {
387 case SkIntersectionHelper::kHorizontalLine_Segment:
388 pts = ts.quadHorizontal(wt.pts(), wn.left(),
389 wn.right(), wn.y(), wn.xFlipped());
390 debugShowQuadLineIntersection(pts, wt, wn, ts);
391 break;
392 case SkIntersectionHelper::kVerticalLine_Segment:
393 pts = ts.quadVertical(wt.pts(), wn.top(),
394 wn.bottom(), wn.x(), wn.yFlipped());
395 debugShowQuadLineIntersection(pts, wt, wn, ts);
396 break;
caryclark1049f122015-04-20 08:31:59 -0700397 case SkIntersectionHelper::kLine_Segment:
caryclark@google.com07393ca2013-04-08 11:47:37 +0000398 pts = ts.quadLine(wt.pts(), wn.pts());
399 debugShowQuadLineIntersection(pts, wt, wn, ts);
400 break;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000401 case SkIntersectionHelper::kQuad_Segment: {
caryclark1049f122015-04-20 08:31:59 -0700402 pts = ts.intersect(quad1.set(wt.pts()), quad2.set(wn.pts()));
caryclark@google.com07393ca2013-04-08 11:47:37 +0000403 debugShowQuadIntersection(pts, wt, wn, ts);
404 break;
405 }
caryclark1049f122015-04-20 08:31:59 -0700406 case SkIntersectionHelper::kConic_Segment: {
407 swap = true;
408 pts = ts.intersect(conic2.set(wn.pts(), wn.weight()),
409 quad1.set(wt.pts()));
410 debugShowConicQuadIntersection(pts, wn, wt, ts);
411 break;
412 }
caryclark@google.com07393ca2013-04-08 11:47:37 +0000413 case SkIntersectionHelper::kCubic_Segment: {
414 swap = true;
caryclark1049f122015-04-20 08:31:59 -0700415 pts = ts.intersect(cubic2.set(wn.pts()), quad1.set(wt.pts()));
caryclark@google.com07393ca2013-04-08 11:47:37 +0000416 debugShowCubicQuadIntersection(pts, wn, wt, ts);
417 break;
418 }
419 default:
420 SkASSERT(0);
421 }
422 break;
caryclark1049f122015-04-20 08:31:59 -0700423 case SkIntersectionHelper::kConic_Segment:
424 switch (wn.segmentType()) {
425 case SkIntersectionHelper::kHorizontalLine_Segment:
426 pts = ts.conicHorizontal(wt.pts(), wt.weight(), wn.left(),
427 wn.right(), wn.y(), wn.xFlipped());
428 debugShowConicLineIntersection(pts, wt, wn, ts);
429 break;
430 case SkIntersectionHelper::kVerticalLine_Segment:
431 pts = ts.conicVertical(wt.pts(), wt.weight(), wn.top(),
432 wn.bottom(), wn.x(), wn.yFlipped());
433 debugShowConicLineIntersection(pts, wt, wn, ts);
434 break;
435 case SkIntersectionHelper::kLine_Segment:
436 pts = ts.conicLine(wt.pts(), wt.weight(), wn.pts());
437 debugShowConicLineIntersection(pts, wt, wn, ts);
438 break;
439 case SkIntersectionHelper::kQuad_Segment: {
440 pts = ts.intersect(conic1.set(wt.pts(), wt.weight()),
441 quad2.set(wn.pts()));
442 debugShowConicQuadIntersection(pts, wt, wn, ts);
443 break;
444 }
445 case SkIntersectionHelper::kConic_Segment: {
446 pts = ts.intersect(conic1.set(wt.pts(), wt.weight()),
447 conic2.set(wn.pts(), wn.weight()));
448 debugShowConicIntersection(pts, wt, wn, ts);
449 break;
450 }
451 case SkIntersectionHelper::kCubic_Segment: {
452 swap = true;
caryclarka35ab3e2016-10-20 08:32:18 -0700453 pts = ts.intersect(cubic2.set(wn.pts()
454 SkDEBUGPARAMS(ts.globalState())),
455 conic1.set(wt.pts(), wt.weight()
456 SkDEBUGPARAMS(ts.globalState())));
caryclark1049f122015-04-20 08:31:59 -0700457 debugShowCubicConicIntersection(pts, wn, wt, ts);
458 break;
459 }
460 }
461 break;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000462 case SkIntersectionHelper::kCubic_Segment:
463 switch (wn.segmentType()) {
464 case SkIntersectionHelper::kHorizontalLine_Segment:
465 pts = ts.cubicHorizontal(wt.pts(), wn.left(),
466 wn.right(), wn.y(), wn.xFlipped());
467 debugShowCubicLineIntersection(pts, wt, wn, ts);
468 break;
469 case SkIntersectionHelper::kVerticalLine_Segment:
470 pts = ts.cubicVertical(wt.pts(), wn.top(),
471 wn.bottom(), wn.x(), wn.yFlipped());
472 debugShowCubicLineIntersection(pts, wt, wn, ts);
473 break;
caryclark1049f122015-04-20 08:31:59 -0700474 case SkIntersectionHelper::kLine_Segment:
caryclark@google.com07393ca2013-04-08 11:47:37 +0000475 pts = ts.cubicLine(wt.pts(), wn.pts());
476 debugShowCubicLineIntersection(pts, wt, wn, ts);
477 break;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000478 case SkIntersectionHelper::kQuad_Segment: {
caryclark1049f122015-04-20 08:31:59 -0700479 pts = ts.intersect(cubic1.set(wt.pts()), quad2.set(wn.pts()));
caryclark@google.com07393ca2013-04-08 11:47:37 +0000480 debugShowCubicQuadIntersection(pts, wt, wn, ts);
481 break;
482 }
caryclark1049f122015-04-20 08:31:59 -0700483 case SkIntersectionHelper::kConic_Segment: {
caryclarka35ab3e2016-10-20 08:32:18 -0700484 pts = ts.intersect(cubic1.set(wt.pts()
485 SkDEBUGPARAMS(ts.globalState())),
486 conic2.set(wn.pts(), wn.weight()
487 SkDEBUGPARAMS(ts.globalState())));
caryclark1049f122015-04-20 08:31:59 -0700488 debugShowCubicConicIntersection(pts, wt, wn, ts);
489 break;
490 }
caryclark@google.com07393ca2013-04-08 11:47:37 +0000491 case SkIntersectionHelper::kCubic_Segment: {
caryclark1049f122015-04-20 08:31:59 -0700492 pts = ts.intersect(cubic1.set(wt.pts()), cubic2.set(wn.pts()));
caryclark@google.com07393ca2013-04-08 11:47:37 +0000493 debugShowCubicIntersection(pts, wt, wn, ts);
494 break;
495 }
496 default:
497 SkASSERT(0);
498 }
499 break;
500 default:
501 SkASSERT(0);
502 }
caryclark26ad22a2015-10-16 09:03:38 -0700503#if DEBUG_T_SECT_LOOP_COUNT
504 test->globalState()->debugAddLoopCount(&ts, wt, wn);
505#endif
caryclark54359292015-03-26 07:52:43 -0700506 int coinIndex = -1;
507 SkOpPtT* coinPtT[2];
caryclark@google.com07393ca2013-04-08 11:47:37 +0000508 for (int pt = 0; pt < pts; ++pt) {
509 SkASSERT(ts[0][pt] >= 0 && ts[0][pt] <= 1);
510 SkASSERT(ts[1][pt] >= 0 && ts[1][pt] <= 1);
caryclark54359292015-03-26 07:52:43 -0700511 wt.segment()->debugValidate();
caryclark29b25632016-08-25 11:27:17 -0700512 SkOpPtT* testTAt = wt.segment()->addT(ts[swap][pt]);
caryclark54359292015-03-26 07:52:43 -0700513 wn.segment()->debugValidate();
caryclark29b25632016-08-25 11:27:17 -0700514 SkOpPtT* nextTAt = wn.segment()->addT(ts[!swap][pt]);
caryclark30b9fdd2016-08-31 14:36:29 -0700515 if (!testTAt->contains(nextTAt)) {
516 SkOpPtT* oppPrev = testTAt->oppPrev(nextTAt); // Returns nullptr if pair
caryclark81a478c2016-09-09 09:37:57 -0700517 if (oppPrev) { // already share a pt-t loop.
caryclark30b9fdd2016-08-31 14:36:29 -0700518 testTAt->span()->mergeMatches(nextTAt->span());
519 testTAt->addOpp(nextTAt, oppPrev);
520 }
521 if (testTAt->fPt != nextTAt->fPt) {
522 testTAt->span()->unaligned();
523 nextTAt->span()->unaligned();
524 }
525 wt.segment()->debugValidate();
526 wn.segment()->debugValidate();
caryclark55888e42016-07-18 10:01:36 -0700527 }
caryclark54359292015-03-26 07:52:43 -0700528 if (!ts.isCoincident(pt)) {
529 continue;
530 }
531 if (coinIndex < 0) {
532 coinPtT[0] = testTAt;
533 coinPtT[1] = nextTAt;
534 coinIndex = pt;
535 continue;
536 }
537 if (coinPtT[0]->span() == testTAt->span()) {
538 coinIndex = -1;
539 continue;
540 }
541 if (coinPtT[1]->span() == nextTAt->span()) {
542 coinIndex = -1; // coincidence span collapsed
543 continue;
544 }
545 if (swap) {
546 SkTSwap(coinPtT[0], coinPtT[1]);
547 SkTSwap(testTAt, nextTAt);
548 }
caryclark27c015d2016-09-23 05:47:20 -0700549 SkASSERT(coincidence->globalState()->debugSkipAssert()
550 || coinPtT[0]->span()->t() < testTAt->span()->t());
caryclark81a478c2016-09-09 09:37:57 -0700551 if (coinPtT[0]->span()->deleted()) {
552 coinIndex = -1;
553 continue;
554 }
555 if (testTAt->span()->deleted()) {
556 coinIndex = -1;
557 continue;
558 }
caryclark55888e42016-07-18 10:01:36 -0700559 coincidence->add(coinPtT[0], testTAt, coinPtT[1], nextTAt);
caryclark54359292015-03-26 07:52:43 -0700560 wt.segment()->debugValidate();
561 wn.segment()->debugValidate();
562 coinIndex = -1;
caryclark@google.com07393ca2013-04-08 11:47:37 +0000563 }
Cary Clark4c76c412017-01-20 08:14:33 -0500564 SkOPOBJASSERT(coincidence, coinIndex < 0); // expect coincidence to be paired
caryclark@google.com07393ca2013-04-08 11:47:37 +0000565 } while (wn.advance());
566 } while (wt.advance());
567 return true;
568}