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