| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkIntersections.h" | 8 #include "SkIntersections.h" |
| 9 #include "SkPathOpsCubic.h" | 9 #include "SkPathOpsCubic.h" |
| 10 #include "SkPathOpsLine.h" | 10 #include "SkPathOpsLine.h" |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 285 int t1Index = start ? 0 : 3; | 285 int t1Index = start ? 0 : 3; |
| 286 double testT = (double) !start; | 286 double testT = (double) !start; |
| 287 bool swap = swapped(); | 287 bool swap = swapped(); |
| 288 // quad/quad at this point checks to see if exact matches have already been
found | 288 // quad/quad at this point checks to see if exact matches have already been
found |
| 289 // cubic/cubic can't reject so easily since cubics can intersect same point
more than once | 289 // cubic/cubic can't reject so easily since cubics can intersect same point
more than once |
| 290 SkDLine tmpLine; | 290 SkDLine tmpLine; |
| 291 tmpLine[0] = tmpLine[1] = cubic2[t1Index]; | 291 tmpLine[0] = tmpLine[1] = cubic2[t1Index]; |
| 292 tmpLine[1].fX += cubic2[2 - start].fY - cubic2[t1Index].fY; | 292 tmpLine[1].fX += cubic2[2 - start].fY - cubic2[t1Index].fY; |
| 293 tmpLine[1].fY -= cubic2[2 - start].fX - cubic2[t1Index].fX; | 293 tmpLine[1].fY -= cubic2[2 - start].fX - cubic2[t1Index].fX; |
| 294 SkIntersections impTs; | 294 SkIntersections impTs; |
| 295 impTs.allowNear(false); |
| 295 impTs.intersectRay(cubic1, tmpLine); | 296 impTs.intersectRay(cubic1, tmpLine); |
| 296 for (int index = 0; index < impTs.used(); ++index) { | 297 for (int index = 0; index < impTs.used(); ++index) { |
| 297 SkDPoint realPt = impTs.pt(index); | 298 SkDPoint realPt = impTs.pt(index); |
| 298 if (!tmpLine[0].approximatelyEqual(realPt)) { | 299 if (!tmpLine[0].approximatelyEqual(realPt)) { |
| 299 continue; | 300 continue; |
| 300 } | 301 } |
| 301 if (swap) { | 302 if (swap) { |
| 302 insert(testT, impTs[0][index], tmpLine[0]); | 303 insert(testT, impTs[0][index], tmpLine[0]); |
| 303 } else { | 304 } else { |
| 304 insert(impTs[0][index], testT, tmpLine[0]); | 305 insert(impTs[0][index], testT, tmpLine[0]); |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 439 if (fMax == 0) { | 440 if (fMax == 0) { |
| 440 fMax = 9; | 441 fMax = 9; |
| 441 } | 442 } |
| 442 bool selfIntersect = &c1 == &c2; | 443 bool selfIntersect = &c1 == &c2; |
| 443 if (selfIntersect) { | 444 if (selfIntersect) { |
| 444 if (c1[0].approximatelyEqual(c1[3])) { | 445 if (c1[0].approximatelyEqual(c1[3])) { |
| 445 insert(0, 1, c1[0]); | 446 insert(0, 1, c1[0]); |
| 446 return fUsed; | 447 return fUsed; |
| 447 } | 448 } |
| 448 } else { | 449 } else { |
| 450 // OPTIMIZATION: set exact end bits here to avoid cubic exact end later |
| 449 for (int i1 = 0; i1 < 4; i1 += 3) { | 451 for (int i1 = 0; i1 < 4; i1 += 3) { |
| 450 for (int i2 = 0; i2 < 4; i2 += 3) { | 452 for (int i2 = 0; i2 < 4; i2 += 3) { |
| 451 if (c1[i1].approximatelyEqual(c2[i2])) { | 453 if (c1[i1].approximatelyEqual(c2[i2])) { |
| 452 insert(i1 >> 1, i2 >> 1, c1[i1]); | 454 insert(i1 >> 1, i2 >> 1, c1[i1]); |
| 453 } | 455 } |
| 454 } | 456 } |
| 455 } | 457 } |
| 456 } | 458 } |
| 457 SkASSERT(fUsed < 4); | 459 SkASSERT(fUsed < 4); |
| 458 if (!selfIntersect) { | 460 if (!selfIntersect) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 476 swap(); | 478 swap(); |
| 477 exactEndBits |= cubicExactEnd(c2, false, c1) << 2; | 479 exactEndBits |= cubicExactEnd(c2, false, c1) << 2; |
| 478 exactEndBits |= cubicExactEnd(c2, true, c1) << 3; | 480 exactEndBits |= cubicExactEnd(c2, true, c1) << 3; |
| 479 swap(); | 481 swap(); |
| 480 } | 482 } |
| 481 if (cubicCheckCoincidence(c1, c2)) { | 483 if (cubicCheckCoincidence(c1, c2)) { |
| 482 SkASSERT(!selfIntersect); | 484 SkASSERT(!selfIntersect); |
| 483 return fUsed; | 485 return fUsed; |
| 484 } | 486 } |
| 485 // FIXME: pass in cached bounds from caller | 487 // FIXME: pass in cached bounds from caller |
| 486 SkDRect c1Bounds, c2Bounds; | 488 SkDRect c2Bounds; |
| 487 c1Bounds.setBounds(c1); // OPTIMIZE use setRawBounds ? | |
| 488 c2Bounds.setBounds(c2); | 489 c2Bounds.setBounds(c2); |
| 489 if (!(exactEndBits & 1)) { | 490 if (!(exactEndBits & 4)) { |
| 490 cubicNearEnd(c1, false, c2, c2Bounds); | 491 cubicNearEnd(c1, false, c2, c2Bounds); |
| 491 } | 492 } |
| 492 if (!(exactEndBits & 2)) { | 493 if (!(exactEndBits & 8)) { |
| 493 cubicNearEnd(c1, true, c2, c2Bounds); | 494 cubicNearEnd(c1, true, c2, c2Bounds); |
| 494 } | 495 } |
| 495 if (!selfIntersect) { | 496 if (!selfIntersect) { |
| 497 SkDRect c1Bounds; |
| 498 c1Bounds.setBounds(c1); // OPTIMIZE use setRawBounds ? |
| 496 swap(); | 499 swap(); |
| 497 if (!(exactEndBits & 4)) { | 500 if (!(exactEndBits & 1)) { |
| 498 cubicNearEnd(c2, false, c1, c1Bounds); | 501 cubicNearEnd(c2, false, c1, c1Bounds); |
| 499 } | 502 } |
| 500 if (!(exactEndBits & 8)) { | 503 if (!(exactEndBits & 2)) { |
| 501 cubicNearEnd(c2, true, c1, c1Bounds); | 504 cubicNearEnd(c2, true, c1, c1Bounds); |
| 502 } | 505 } |
| 503 swap(); | 506 swap(); |
| 504 } | 507 } |
| 505 if (cubicCheckCoincidence(c1, c2)) { | 508 if (cubicCheckCoincidence(c1, c2)) { |
| 506 SkASSERT(!selfIntersect); | 509 SkASSERT(!selfIntersect); |
| 507 return fUsed; | 510 return fUsed; |
| 508 } | 511 } |
| 509 ::intersect(c1, 0, 1, c2, 0, 1, 1, *this); | 512 SkIntersections i; |
| 513 i.fAllowNear = false; |
| 514 i.fMax = 9; |
| 515 ::intersect(c1, 0, 1, c2, 0, 1, 1, i); |
| 516 int compCount = i.used(); |
| 517 if (compCount) { |
| 518 int exactCount = used(); |
| 519 if (exactCount == 0) { |
| 520 set(i); |
| 521 } else { |
| 522 // at least one is exact or near, and at least one was computed. Eli
minate duplicates |
| 523 for (int exIdx = 0; exIdx < exactCount; ++exIdx) { |
| 524 for (int cpIdx = 0; cpIdx < compCount; ) { |
| 525 if (fT[0][0] == i[0][0] && fT[1][0] == i[1][0]) { |
| 526 i.removeOne(cpIdx); |
| 527 --compCount; |
| 528 continue; |
| 529 } |
| 530 double tAvg = (fT[0][exIdx] + i[0][cpIdx]) / 2; |
| 531 SkDPoint pt = c1.ptAtT(tAvg); |
| 532 if (!pt.approximatelyEqual(fPt[exIdx])) { |
| 533 ++cpIdx; |
| 534 continue; |
| 535 } |
| 536 tAvg = (fT[1][exIdx] + i[1][cpIdx]) / 2; |
| 537 pt = c2.ptAtT(tAvg); |
| 538 if (!pt.approximatelyEqual(fPt[exIdx])) { |
| 539 ++cpIdx; |
| 540 continue; |
| 541 } |
| 542 i.removeOne(cpIdx); |
| 543 --compCount; |
| 544 } |
| 545 } |
| 546 // if mid t evaluates to nearly the same point, skip the t |
| 547 for (int cpIdx = 0; cpIdx < compCount - 1; ) { |
| 548 double tAvg = (fT[0][cpIdx] + i[0][cpIdx + 1]) / 2; |
| 549 SkDPoint pt = c1.ptAtT(tAvg); |
| 550 if (!pt.approximatelyEqual(fPt[cpIdx])) { |
| 551 ++cpIdx; |
| 552 continue; |
| 553 } |
| 554 tAvg = (fT[1][cpIdx] + i[1][cpIdx + 1]) / 2; |
| 555 pt = c2.ptAtT(tAvg); |
| 556 if (!pt.approximatelyEqual(fPt[cpIdx])) { |
| 557 ++cpIdx; |
| 558 continue; |
| 559 } |
| 560 i.removeOne(cpIdx); |
| 561 --compCount; |
| 562 } |
| 563 // in addition to adding below missing function, think about how to
say |
| 564 append(i); |
| 565 } |
| 566 } |
| 510 // If an end point and a second point very close to the end is returned, the
second | 567 // If an end point and a second point very close to the end is returned, the
second |
| 511 // point may have been detected because the approximate quads | 568 // point may have been detected because the approximate quads |
| 512 // intersected at the end and close to it. Verify that the second point is v
alid. | 569 // intersected at the end and close to it. Verify that the second point is v
alid. |
| 513 if (fUsed <= 1) { | 570 if (fUsed <= 1) { |
| 514 return fUsed; | 571 return fUsed; |
| 515 } | 572 } |
| 516 SkDPoint pt[2]; | 573 SkDPoint pt[2]; |
| 517 if (closeStart(c1, 0, *this, pt[0]) && closeStart(c2, 1, *this, pt[1]) | 574 if (closeStart(c1, 0, *this, pt[0]) && closeStart(c2, 1, *this, pt[1]) |
| 518 && pt[0].approximatelyEqual(pt[1])) { | 575 && pt[0].approximatelyEqual(pt[1])) { |
| 519 removeOne(1); | 576 removeOne(1); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 } | 638 } |
| 582 (void) intersect(c, c); | 639 (void) intersect(c, c); |
| 583 if (used() > 0) { | 640 if (used() > 0) { |
| 584 SkASSERT(used() == 1); | 641 SkASSERT(used() == 1); |
| 585 if (fT[0][0] > fT[1][0]) { | 642 if (fT[0][0] > fT[1][0]) { |
| 586 swapPts(); | 643 swapPts(); |
| 587 } | 644 } |
| 588 } | 645 } |
| 589 return used(); | 646 return used(); |
| 590 } | 647 } |
| OLD | NEW |