SkAddIntersections.cpp revision 30b9fdd6a1d607bde20c793af65b5e2e8a1737ca
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 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 74static 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 135static 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 175static 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 195static 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 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 228static 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 240static 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 248static void debugShowCubicConicIntersection(int , const SkIntersectionHelper& , 249 const SkIntersectionHelper& , const SkIntersections& ) { 250} 251 252static void debugShowCubicIntersection(int , const SkIntersectionHelper& , 253 const SkIntersectionHelper& , const SkIntersections& ) { 254} 255#endif 256 257bool AddIntersectTs(SkOpContour* test, SkOpContour* next, SkOpCoincidence* coincidence) { 258 if (test != next) { 259 if (AlmostLessUlps(test->bounds().fBottom, next->bounds().fTop)) { 260 return false; 261 } 262 // OPTIMIZATION: outset contour bounds a smidgen instead? 263 if (!SkPathOpsBounds::Intersects(test->bounds(), next->bounds())) { 264 return true; 265 } 266 } 267 SkIntersectionHelper wt; 268 wt.init(test); 269 do { 270 SkIntersectionHelper wn; 271 wn.init(next); 272 test->debugValidate(); 273 next->debugValidate(); 274 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; 282 SkIntersections ts { SkDEBUGCODE(test->globalState()) }; 283 bool swap = false; 284 SkDQuad quad1, quad2; 285 SkDConic conic1, conic2; 286 SkDCubic cubic1, cubic2; 287 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: 293 case SkIntersectionHelper::kLine_Segment: 294 pts = ts.lineHorizontal(wn.pts(), wt.left(), 295 wt.right(), wt.y(), wt.xFlipped()); 296 debugShowLineIntersection(pts, wn, wt, ts); 297 break; 298 case SkIntersectionHelper::kQuad_Segment: 299 pts = ts.quadHorizontal(wn.pts(), wt.left(), 300 wt.right(), wt.y(), wt.xFlipped()); 301 debugShowQuadLineIntersection(pts, wn, wt, ts); 302 break; 303 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: 309 pts = ts.cubicHorizontal(wn.pts(), wt.left(), 310 wt.right(), wt.y(), wt.xFlipped()); 311 debugShowCubicLineIntersection(pts, wn, wt, ts); 312 break; 313 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()); 325 debugShowLineIntersection(pts, wn, wt, ts); 326 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 } 334 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 } 340 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; 362 case SkIntersectionHelper::kLine_Segment: 363 pts = ts.lineLine(wt.pts(), wn.pts()); 364 debugShowLineIntersection(pts, wt, wn, ts); 365 break; 366 case SkIntersectionHelper::kQuad_Segment: 367 swap = true; 368 pts = ts.quadLine(wn.pts(), wt.pts()); 369 debugShowQuadLineIntersection(pts, wn, wt, ts); 370 break; 371 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: 377 swap = true; 378 pts = ts.cubicLine(wn.pts(), wt.pts()); 379 debugShowCubicLineIntersection(pts, wn, wt, ts); 380 break; 381 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; 397 case SkIntersectionHelper::kLine_Segment: 398 pts = ts.quadLine(wt.pts(), wn.pts()); 399 debugShowQuadLineIntersection(pts, wt, wn, ts); 400 break; 401 case SkIntersectionHelper::kQuad_Segment: { 402 pts = ts.intersect(quad1.set(wt.pts()), quad2.set(wn.pts())); 403 debugShowQuadIntersection(pts, wt, wn, ts); 404 break; 405 } 406 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 } 413 case SkIntersectionHelper::kCubic_Segment: { 414 swap = true; 415 pts = ts.intersect(cubic2.set(wn.pts()), quad1.set(wt.pts())); 416 debugShowCubicQuadIntersection(pts, wn, wt, ts); 417 break; 418 } 419 default: 420 SkASSERT(0); 421 } 422 break; 423 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; 453 pts = ts.intersect(cubic2.set(wn.pts()), 454 conic1.set(wt.pts(), wt.weight())); 455 debugShowCubicConicIntersection(pts, wn, wt, ts); 456 break; 457 } 458 } 459 break; 460 case SkIntersectionHelper::kCubic_Segment: 461 switch (wn.segmentType()) { 462 case SkIntersectionHelper::kHorizontalLine_Segment: 463 pts = ts.cubicHorizontal(wt.pts(), wn.left(), 464 wn.right(), wn.y(), wn.xFlipped()); 465 debugShowCubicLineIntersection(pts, wt, wn, ts); 466 break; 467 case SkIntersectionHelper::kVerticalLine_Segment: 468 pts = ts.cubicVertical(wt.pts(), wn.top(), 469 wn.bottom(), wn.x(), wn.yFlipped()); 470 debugShowCubicLineIntersection(pts, wt, wn, ts); 471 break; 472 case SkIntersectionHelper::kLine_Segment: 473 pts = ts.cubicLine(wt.pts(), wn.pts()); 474 debugShowCubicLineIntersection(pts, wt, wn, ts); 475 break; 476 case SkIntersectionHelper::kQuad_Segment: { 477 pts = ts.intersect(cubic1.set(wt.pts()), quad2.set(wn.pts())); 478 debugShowCubicQuadIntersection(pts, wt, wn, ts); 479 break; 480 } 481 case SkIntersectionHelper::kConic_Segment: { 482 pts = ts.intersect(cubic1.set(wt.pts()), 483 conic2.set(wn.pts(), wn.weight())); 484 debugShowCubicConicIntersection(pts, wt, wn, ts); 485 break; 486 } 487 case SkIntersectionHelper::kCubic_Segment: { 488 pts = ts.intersect(cubic1.set(wt.pts()), cubic2.set(wn.pts())); 489 debugShowCubicIntersection(pts, wt, wn, ts); 490 break; 491 } 492 default: 493 SkASSERT(0); 494 } 495 break; 496 default: 497 SkASSERT(0); 498 } 499#if DEBUG_T_SECT_LOOP_COUNT 500 test->globalState()->debugAddLoopCount(&ts, wt, wn); 501#endif 502 int coinIndex = -1; 503 SkOpPtT* coinPtT[2]; 504 for (int pt = 0; pt < pts; ++pt) { 505 SkASSERT(ts[0][pt] >= 0 && ts[0][pt] <= 1); 506 SkASSERT(ts[1][pt] >= 0 && ts[1][pt] <= 1); 507 wt.segment()->debugValidate(); 508 SkOpPtT* testTAt = wt.segment()->addT(ts[swap][pt]); 509 wn.segment()->debugValidate(); 510 SkOpPtT* nextTAt = wn.segment()->addT(ts[!swap][pt]); 511 if (!testTAt->contains(nextTAt)) { 512 SkOpPtT* oppPrev = testTAt->oppPrev(nextTAt); // Returns nullptr if pair 513 if (oppPrev) { // already shares a pt-t loop. 514 testTAt->span()->mergeMatches(nextTAt->span()); 515 testTAt->addOpp(nextTAt, oppPrev); 516 } 517 if (testTAt->fPt != nextTAt->fPt) { 518 testTAt->span()->unaligned(); 519 nextTAt->span()->unaligned(); 520 } 521 wt.segment()->debugValidate(); 522 wn.segment()->debugValidate(); 523 } 524 if (!ts.isCoincident(pt)) { 525 continue; 526 } 527 if (coinIndex < 0) { 528 coinPtT[0] = testTAt; 529 coinPtT[1] = nextTAt; 530 coinIndex = pt; 531 continue; 532 } 533 if (coinPtT[0]->span() == testTAt->span()) { 534 coinIndex = -1; 535 continue; 536 } 537 if (coinPtT[1]->span() == nextTAt->span()) { 538 coinIndex = -1; // coincidence span collapsed 539 continue; 540 } 541 if (swap) { 542 SkTSwap(coinPtT[0], coinPtT[1]); 543 SkTSwap(testTAt, nextTAt); 544 } 545 SkASSERT(coinPtT[0]->span()->t() < testTAt->span()->t()); 546 coincidence->add(coinPtT[0], testTAt, coinPtT[1], nextTAt); 547 wt.segment()->debugValidate(); 548 wn.segment()->debugValidate(); 549 coinIndex = -1; 550 } 551 SkASSERT(coinIndex < 0); // expect coincidence to be paired 552 } while (wn.advance()); 553 } while (wt.advance()); 554 return true; 555} 556