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 |