Line data Source code
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 : #include "SkAddIntersections.h"
8 : #include "SkOpCoincidence.h"
9 : #include "SkPathOpsBounds.h"
10 :
11 : #if DEBUG_ADD_INTERSECTING_TS
12 :
13 : static 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 :
33 : static 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 :
54 : static 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 :
74 : static 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 :
94 : static 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 :
114 : static 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 :
135 : static 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 :
155 : static 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 :
175 : static 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 :
195 : static 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 :
215 : #else
216 0 : static void debugShowLineIntersection(int , const SkIntersectionHelper& ,
217 : const SkIntersectionHelper& , const SkIntersections& ) {
218 0 : }
219 :
220 0 : static void debugShowQuadLineIntersection(int , const SkIntersectionHelper& ,
221 : const SkIntersectionHelper& , const SkIntersections& ) {
222 0 : }
223 :
224 0 : static void debugShowQuadIntersection(int , const SkIntersectionHelper& ,
225 : const SkIntersectionHelper& , const SkIntersections& ) {
226 0 : }
227 :
228 0 : static void debugShowConicLineIntersection(int , const SkIntersectionHelper& ,
229 : const SkIntersectionHelper& , const SkIntersections& ) {
230 0 : }
231 :
232 0 : static void debugShowConicQuadIntersection(int , const SkIntersectionHelper& ,
233 : const SkIntersectionHelper& , const SkIntersections& ) {
234 0 : }
235 :
236 0 : static void debugShowConicIntersection(int , const SkIntersectionHelper& ,
237 : const SkIntersectionHelper& , const SkIntersections& ) {
238 0 : }
239 :
240 0 : static void debugShowCubicLineIntersection(int , const SkIntersectionHelper& ,
241 : const SkIntersectionHelper& , const SkIntersections& ) {
242 0 : }
243 :
244 0 : static void debugShowCubicQuadIntersection(int , const SkIntersectionHelper& ,
245 : const SkIntersectionHelper& , const SkIntersections& ) {
246 0 : }
247 :
248 0 : static void debugShowCubicConicIntersection(int , const SkIntersectionHelper& ,
249 : const SkIntersectionHelper& , const SkIntersections& ) {
250 0 : }
251 :
252 0 : static void debugShowCubicIntersection(int , const SkIntersectionHelper& ,
253 : const SkIntersectionHelper& , const SkIntersections& ) {
254 0 : }
255 : #endif
256 :
257 0 : bool AddIntersectTs(SkOpContour* test, SkOpContour* next, SkOpCoincidence* coincidence) {
258 0 : if (test != next) {
259 0 : if (AlmostLessUlps(test->bounds().fBottom, next->bounds().fTop)) {
260 0 : return false;
261 : }
262 : // OPTIMIZATION: outset contour bounds a smidgen instead?
263 0 : if (!SkPathOpsBounds::Intersects(test->bounds(), next->bounds())) {
264 0 : return true;
265 : }
266 : }
267 : SkIntersectionHelper wt;
268 0 : wt.init(test);
269 0 : do {
270 : SkIntersectionHelper wn;
271 0 : wn.init(next);
272 0 : test->debugValidate();
273 0 : next->debugValidate();
274 0 : if (test == next && !wn.startAfter(wt)) {
275 0 : continue;
276 : }
277 0 : do {
278 0 : if (!SkPathOpsBounds::Intersects(wt.bounds(), wn.bounds())) {
279 0 : continue;
280 : }
281 0 : int pts = 0;
282 0 : SkIntersections ts { SkDEBUGCODE(test->globalState()) };
283 0 : bool swap = false;
284 : SkDQuad quad1, quad2;
285 : SkDConic conic1, conic2;
286 : SkDCubic cubic1, cubic2;
287 0 : switch (wt.segmentType()) {
288 : case SkIntersectionHelper::kHorizontalLine_Segment:
289 0 : swap = true;
290 0 : switch (wn.segmentType()) {
291 : case SkIntersectionHelper::kHorizontalLine_Segment:
292 : case SkIntersectionHelper::kVerticalLine_Segment:
293 : case SkIntersectionHelper::kLine_Segment:
294 0 : pts = ts.lineHorizontal(wn.pts(), wt.left(),
295 0 : wt.right(), wt.y(), wt.xFlipped());
296 0 : debugShowLineIntersection(pts, wn, wt, ts);
297 0 : break;
298 : case SkIntersectionHelper::kQuad_Segment:
299 0 : pts = ts.quadHorizontal(wn.pts(), wt.left(),
300 0 : wt.right(), wt.y(), wt.xFlipped());
301 0 : debugShowQuadLineIntersection(pts, wn, wt, ts);
302 0 : break;
303 : case SkIntersectionHelper::kConic_Segment:
304 0 : pts = ts.conicHorizontal(wn.pts(), wn.weight(), wt.left(),
305 0 : wt.right(), wt.y(), wt.xFlipped());
306 0 : debugShowConicLineIntersection(pts, wn, wt, ts);
307 0 : break;
308 : case SkIntersectionHelper::kCubic_Segment:
309 0 : pts = ts.cubicHorizontal(wn.pts(), wt.left(),
310 0 : wt.right(), wt.y(), wt.xFlipped());
311 0 : debugShowCubicLineIntersection(pts, wn, wt, ts);
312 0 : break;
313 : default:
314 0 : SkASSERT(0);
315 : }
316 0 : break;
317 : case SkIntersectionHelper::kVerticalLine_Segment:
318 0 : swap = true;
319 0 : switch (wn.segmentType()) {
320 : case SkIntersectionHelper::kHorizontalLine_Segment:
321 : case SkIntersectionHelper::kVerticalLine_Segment:
322 : case SkIntersectionHelper::kLine_Segment: {
323 0 : pts = ts.lineVertical(wn.pts(), wt.top(),
324 0 : wt.bottom(), wt.x(), wt.yFlipped());
325 0 : debugShowLineIntersection(pts, wn, wt, ts);
326 0 : break;
327 : }
328 : case SkIntersectionHelper::kQuad_Segment: {
329 0 : pts = ts.quadVertical(wn.pts(), wt.top(),
330 0 : wt.bottom(), wt.x(), wt.yFlipped());
331 0 : debugShowQuadLineIntersection(pts, wn, wt, ts);
332 0 : break;
333 : }
334 : case SkIntersectionHelper::kConic_Segment: {
335 0 : pts = ts.conicVertical(wn.pts(), wn.weight(), wt.top(),
336 0 : wt.bottom(), wt.x(), wt.yFlipped());
337 0 : debugShowConicLineIntersection(pts, wn, wt, ts);
338 0 : break;
339 : }
340 : case SkIntersectionHelper::kCubic_Segment: {
341 0 : pts = ts.cubicVertical(wn.pts(), wt.top(),
342 0 : wt.bottom(), wt.x(), wt.yFlipped());
343 0 : debugShowCubicLineIntersection(pts, wn, wt, ts);
344 0 : break;
345 : }
346 : default:
347 0 : SkASSERT(0);
348 : }
349 0 : break;
350 : case SkIntersectionHelper::kLine_Segment:
351 0 : switch (wn.segmentType()) {
352 : case SkIntersectionHelper::kHorizontalLine_Segment:
353 0 : pts = ts.lineHorizontal(wt.pts(), wn.left(),
354 0 : wn.right(), wn.y(), wn.xFlipped());
355 0 : debugShowLineIntersection(pts, wt, wn, ts);
356 0 : break;
357 : case SkIntersectionHelper::kVerticalLine_Segment:
358 0 : pts = ts.lineVertical(wt.pts(), wn.top(),
359 0 : wn.bottom(), wn.x(), wn.yFlipped());
360 0 : debugShowLineIntersection(pts, wt, wn, ts);
361 0 : break;
362 : case SkIntersectionHelper::kLine_Segment:
363 0 : pts = ts.lineLine(wt.pts(), wn.pts());
364 0 : debugShowLineIntersection(pts, wt, wn, ts);
365 0 : break;
366 : case SkIntersectionHelper::kQuad_Segment:
367 0 : swap = true;
368 0 : pts = ts.quadLine(wn.pts(), wt.pts());
369 0 : debugShowQuadLineIntersection(pts, wn, wt, ts);
370 0 : break;
371 : case SkIntersectionHelper::kConic_Segment:
372 0 : swap = true;
373 0 : pts = ts.conicLine(wn.pts(), wn.weight(), wt.pts());
374 0 : debugShowConicLineIntersection(pts, wn, wt, ts);
375 0 : break;
376 : case SkIntersectionHelper::kCubic_Segment:
377 0 : swap = true;
378 0 : pts = ts.cubicLine(wn.pts(), wt.pts());
379 0 : debugShowCubicLineIntersection(pts, wn, wt, ts);
380 0 : break;
381 : default:
382 0 : SkASSERT(0);
383 : }
384 0 : break;
385 : case SkIntersectionHelper::kQuad_Segment:
386 0 : switch (wn.segmentType()) {
387 : case SkIntersectionHelper::kHorizontalLine_Segment:
388 0 : pts = ts.quadHorizontal(wt.pts(), wn.left(),
389 0 : wn.right(), wn.y(), wn.xFlipped());
390 0 : debugShowQuadLineIntersection(pts, wt, wn, ts);
391 0 : break;
392 : case SkIntersectionHelper::kVerticalLine_Segment:
393 0 : pts = ts.quadVertical(wt.pts(), wn.top(),
394 0 : wn.bottom(), wn.x(), wn.yFlipped());
395 0 : debugShowQuadLineIntersection(pts, wt, wn, ts);
396 0 : break;
397 : case SkIntersectionHelper::kLine_Segment:
398 0 : pts = ts.quadLine(wt.pts(), wn.pts());
399 0 : debugShowQuadLineIntersection(pts, wt, wn, ts);
400 0 : break;
401 : case SkIntersectionHelper::kQuad_Segment: {
402 0 : pts = ts.intersect(quad1.set(wt.pts()), quad2.set(wn.pts()));
403 0 : debugShowQuadIntersection(pts, wt, wn, ts);
404 0 : break;
405 : }
406 : case SkIntersectionHelper::kConic_Segment: {
407 0 : swap = true;
408 0 : pts = ts.intersect(conic2.set(wn.pts(), wn.weight()),
409 0 : quad1.set(wt.pts()));
410 0 : debugShowConicQuadIntersection(pts, wn, wt, ts);
411 0 : break;
412 : }
413 : case SkIntersectionHelper::kCubic_Segment: {
414 0 : swap = true;
415 0 : pts = ts.intersect(cubic2.set(wn.pts()), quad1.set(wt.pts()));
416 0 : debugShowCubicQuadIntersection(pts, wn, wt, ts);
417 0 : break;
418 : }
419 : default:
420 0 : SkASSERT(0);
421 : }
422 0 : break;
423 : case SkIntersectionHelper::kConic_Segment:
424 0 : switch (wn.segmentType()) {
425 : case SkIntersectionHelper::kHorizontalLine_Segment:
426 0 : pts = ts.conicHorizontal(wt.pts(), wt.weight(), wn.left(),
427 0 : wn.right(), wn.y(), wn.xFlipped());
428 0 : debugShowConicLineIntersection(pts, wt, wn, ts);
429 0 : break;
430 : case SkIntersectionHelper::kVerticalLine_Segment:
431 0 : pts = ts.conicVertical(wt.pts(), wt.weight(), wn.top(),
432 0 : wn.bottom(), wn.x(), wn.yFlipped());
433 0 : debugShowConicLineIntersection(pts, wt, wn, ts);
434 0 : break;
435 : case SkIntersectionHelper::kLine_Segment:
436 0 : pts = ts.conicLine(wt.pts(), wt.weight(), wn.pts());
437 0 : debugShowConicLineIntersection(pts, wt, wn, ts);
438 0 : break;
439 : case SkIntersectionHelper::kQuad_Segment: {
440 0 : pts = ts.intersect(conic1.set(wt.pts(), wt.weight()),
441 0 : quad2.set(wn.pts()));
442 0 : debugShowConicQuadIntersection(pts, wt, wn, ts);
443 0 : break;
444 : }
445 : case SkIntersectionHelper::kConic_Segment: {
446 0 : pts = ts.intersect(conic1.set(wt.pts(), wt.weight()),
447 0 : conic2.set(wn.pts(), wn.weight()));
448 0 : debugShowConicIntersection(pts, wt, wn, ts);
449 0 : break;
450 : }
451 : case SkIntersectionHelper::kCubic_Segment: {
452 0 : swap = true;
453 0 : pts = ts.intersect(cubic2.set(wn.pts()
454 : SkDEBUGPARAMS(ts.globalState())),
455 : conic1.set(wt.pts(), wt.weight()
456 0 : SkDEBUGPARAMS(ts.globalState())));
457 0 : debugShowCubicConicIntersection(pts, wn, wt, ts);
458 0 : break;
459 : }
460 : }
461 0 : break;
462 : case SkIntersectionHelper::kCubic_Segment:
463 0 : switch (wn.segmentType()) {
464 : case SkIntersectionHelper::kHorizontalLine_Segment:
465 0 : pts = ts.cubicHorizontal(wt.pts(), wn.left(),
466 0 : wn.right(), wn.y(), wn.xFlipped());
467 0 : debugShowCubicLineIntersection(pts, wt, wn, ts);
468 0 : break;
469 : case SkIntersectionHelper::kVerticalLine_Segment:
470 0 : pts = ts.cubicVertical(wt.pts(), wn.top(),
471 0 : wn.bottom(), wn.x(), wn.yFlipped());
472 0 : debugShowCubicLineIntersection(pts, wt, wn, ts);
473 0 : break;
474 : case SkIntersectionHelper::kLine_Segment:
475 0 : pts = ts.cubicLine(wt.pts(), wn.pts());
476 0 : debugShowCubicLineIntersection(pts, wt, wn, ts);
477 0 : break;
478 : case SkIntersectionHelper::kQuad_Segment: {
479 0 : pts = ts.intersect(cubic1.set(wt.pts()), quad2.set(wn.pts()));
480 0 : debugShowCubicQuadIntersection(pts, wt, wn, ts);
481 0 : break;
482 : }
483 : case SkIntersectionHelper::kConic_Segment: {
484 0 : pts = ts.intersect(cubic1.set(wt.pts()
485 : SkDEBUGPARAMS(ts.globalState())),
486 : conic2.set(wn.pts(), wn.weight()
487 0 : SkDEBUGPARAMS(ts.globalState())));
488 0 : debugShowCubicConicIntersection(pts, wt, wn, ts);
489 0 : break;
490 : }
491 : case SkIntersectionHelper::kCubic_Segment: {
492 0 : pts = ts.intersect(cubic1.set(wt.pts()), cubic2.set(wn.pts()));
493 0 : debugShowCubicIntersection(pts, wt, wn, ts);
494 0 : break;
495 : }
496 : default:
497 0 : SkASSERT(0);
498 : }
499 0 : break;
500 : default:
501 0 : SkASSERT(0);
502 : }
503 : #if DEBUG_T_SECT_LOOP_COUNT
504 : test->globalState()->debugAddLoopCount(&ts, wt, wn);
505 : #endif
506 0 : int coinIndex = -1;
507 : SkOpPtT* coinPtT[2];
508 0 : for (int pt = 0; pt < pts; ++pt) {
509 0 : SkASSERT(ts[0][pt] >= 0 && ts[0][pt] <= 1);
510 0 : SkASSERT(ts[1][pt] >= 0 && ts[1][pt] <= 1);
511 0 : wt.segment()->debugValidate();
512 0 : SkOpPtT* testTAt = wt.segment()->addT(ts[swap][pt]);
513 0 : wn.segment()->debugValidate();
514 0 : SkOpPtT* nextTAt = wn.segment()->addT(ts[!swap][pt]);
515 0 : if (!testTAt->contains(nextTAt)) {
516 0 : SkOpPtT* oppPrev = testTAt->oppPrev(nextTAt); // Returns nullptr if pair
517 0 : if (oppPrev) { // already share a pt-t loop.
518 0 : testTAt->span()->mergeMatches(nextTAt->span());
519 0 : testTAt->addOpp(nextTAt, oppPrev);
520 : }
521 0 : if (testTAt->fPt != nextTAt->fPt) {
522 0 : testTAt->span()->unaligned();
523 0 : nextTAt->span()->unaligned();
524 : }
525 0 : wt.segment()->debugValidate();
526 0 : wn.segment()->debugValidate();
527 : }
528 0 : if (!ts.isCoincident(pt)) {
529 0 : continue;
530 : }
531 0 : if (coinIndex < 0) {
532 0 : coinPtT[0] = testTAt;
533 0 : coinPtT[1] = nextTAt;
534 0 : coinIndex = pt;
535 0 : continue;
536 : }
537 0 : if (coinPtT[0]->span() == testTAt->span()) {
538 0 : coinIndex = -1;
539 0 : continue;
540 : }
541 0 : if (coinPtT[1]->span() == nextTAt->span()) {
542 0 : coinIndex = -1; // coincidence span collapsed
543 0 : continue;
544 : }
545 0 : if (swap) {
546 0 : SkTSwap(coinPtT[0], coinPtT[1]);
547 0 : SkTSwap(testTAt, nextTAt);
548 : }
549 0 : SkASSERT(coincidence->globalState()->debugSkipAssert()
550 : || coinPtT[0]->span()->t() < testTAt->span()->t());
551 0 : if (coinPtT[0]->span()->deleted()) {
552 0 : coinIndex = -1;
553 0 : continue;
554 : }
555 0 : if (testTAt->span()->deleted()) {
556 0 : coinIndex = -1;
557 0 : continue;
558 : }
559 0 : coincidence->add(coinPtT[0], testTAt, coinPtT[1], nextTAt);
560 0 : wt.segment()->debugValidate();
561 0 : wn.segment()->debugValidate();
562 0 : coinIndex = -1;
563 : }
564 0 : SkOPOBJASSERT(coincidence, coinIndex < 0); // expect coincidence to be paired
565 : } while (wn.advance());
566 : } while (wt.advance());
567 0 : return true;
568 : }
|