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 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 tmpLine[1].fY -= cubic2[2 - start].fX - cubic2[t1Index].fX; | 296 tmpLine[1].fY -= cubic2[2 - start].fX - cubic2[t1Index].fX; |
297 SkIntersections impTs; | 297 SkIntersections impTs; |
298 impTs.allowNear(false); | 298 impTs.allowNear(false); |
299 impTs.intersectRay(cubic1, tmpLine); | 299 impTs.intersectRay(cubic1, tmpLine); |
300 for (int index = 0; index < impTs.used(); ++index) { | 300 for (int index = 0; index < impTs.used(); ++index) { |
301 SkDPoint realPt = impTs.pt(index); | 301 SkDPoint realPt = impTs.pt(index); |
302 if (!tmpLine[0].approximatelyEqual(realPt)) { | 302 if (!tmpLine[0].approximatelyEqual(realPt)) { |
303 continue; | 303 continue; |
304 } | 304 } |
305 if (swap) { | 305 if (swap) { |
306 insert(testT, impTs[0][index], tmpLine[0]); | 306 cubicInsert(testT, impTs[0][index], tmpLine[0], cubic2, cubic1); |
307 } else { | 307 } else { |
308 insert(impTs[0][index], testT, tmpLine[0]); | 308 cubicInsert(impTs[0][index], testT, tmpLine[0], cubic1, cubic2); |
309 } | 309 } |
310 return true; | 310 return true; |
311 } | 311 } |
312 return false; | 312 return false; |
313 } | 313 } |
314 | 314 |
| 315 |
| 316 void SkIntersections::cubicInsert(double one, double two, const SkDPoint& pt, |
| 317 const SkDCubic& cubic1, const SkDCubic& cubic2) { |
| 318 for (int index = 0; index < fUsed; ++index) { |
| 319 if (fT[0][index] == one) { |
| 320 double oldTwo = fT[1][index]; |
| 321 if (oldTwo == two) { |
| 322 return; |
| 323 } |
| 324 SkDPoint mid = cubic2.ptAtT((oldTwo + two) / 2); |
| 325 if (mid.approximatelyEqual(fPt[index])) { |
| 326 return; |
| 327 } |
| 328 } |
| 329 if (fT[1][index] == two) { |
| 330 SkDPoint mid = cubic1.ptAtT((fT[0][index] + two) / 2); |
| 331 if (mid.approximatelyEqual(fPt[index])) { |
| 332 return; |
| 333 } |
| 334 } |
| 335 } |
| 336 insert(one, two, pt); |
| 337 } |
| 338 |
315 void SkIntersections::cubicNearEnd(const SkDCubic& cubic1, bool start, const SkD
Cubic& cubic2, | 339 void SkIntersections::cubicNearEnd(const SkDCubic& cubic1, bool start, const SkD
Cubic& cubic2, |
316 const SkDRect& bounds2) { | 340 const SkDRect& bounds2) { |
317 SkDLine line; | 341 SkDLine line; |
318 int t1Index = start ? 0 : 3; | 342 int t1Index = start ? 0 : 3; |
319 double testT = (double) !start; | 343 double testT = (double) !start; |
320 // don't bother if the two cubics are connnected | 344 // don't bother if the two cubics are connnected |
321 static const int kPointsInCubic = 4; // FIXME: move to DCubic, replace '4' w
ith this | 345 static const int kPointsInCubic = 4; // FIXME: move to DCubic, replace '4' w
ith this |
322 static const int kMaxLineCubicIntersections = 3; | 346 static const int kMaxLineCubicIntersections = 3; |
323 SkSTArray<(kMaxLineCubicIntersections - 1) * kMaxLineCubicIntersections, dou
ble, true> tVals; | 347 SkSTArray<(kMaxLineCubicIntersections - 1) * kMaxLineCubicIntersections, dou
ble, true> tVals; |
324 line[0] = cubic1[t1Index]; | 348 line[0] = cubic1[t1Index]; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 double tMax1 = start ? LINE_FRACTION : 1; | 388 double tMax1 = start ? LINE_FRACTION : 1; |
365 int tIdx = 0; | 389 int tIdx = 0; |
366 do { | 390 do { |
367 int tLast = tIdx; | 391 int tLast = tIdx; |
368 while (tLast + 1 < tVals.count() && roughly_equal(tVals[tLast + 1], tVal
s[tIdx])) { | 392 while (tLast + 1 < tVals.count() && roughly_equal(tVals[tLast + 1], tVal
s[tIdx])) { |
369 ++tLast; | 393 ++tLast; |
370 } | 394 } |
371 double tMin2 = SkTMax(tVals[tIdx] - LINE_FRACTION, 0.0); | 395 double tMin2 = SkTMax(tVals[tIdx] - LINE_FRACTION, 0.0); |
372 double tMax2 = SkTMin(tVals[tLast] + LINE_FRACTION, 1.0); | 396 double tMax2 = SkTMin(tVals[tLast] + LINE_FRACTION, 1.0); |
373 int lastUsed = used(); | 397 int lastUsed = used(); |
374 ::intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, *this); | 398 if (start ? tMax1 < tMin2 : tMax2 < tMin1) { |
| 399 ::intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, *this); |
| 400 } |
375 if (lastUsed == used()) { | 401 if (lastUsed == used()) { |
376 tMin2 = SkTMax(tVals[tIdx] - (1.0 / SkDCubic::gPrecisionUnit), 0.0); | 402 tMin2 = SkTMax(tVals[tIdx] - (1.0 / SkDCubic::gPrecisionUnit), 0.0); |
377 tMax2 = SkTMin(tVals[tLast] + (1.0 / SkDCubic::gPrecisionUnit), 1.0)
; | 403 tMax2 = SkTMin(tVals[tLast] + (1.0 / SkDCubic::gPrecisionUnit), 1.0)
; |
378 ::intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, *this); | 404 if (start ? tMax1 < tMin2 : tMax2 < tMin1) { |
| 405 ::intersect(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, *this
); |
| 406 } |
379 } | 407 } |
380 tIdx = tLast + 1; | 408 tIdx = tLast + 1; |
381 } while (tIdx < tVals.count()); | 409 } while (tIdx < tVals.count()); |
382 return; | 410 return; |
383 } | 411 } |
384 | 412 |
385 const double CLOSE_ENOUGH = 0.001; | 413 const double CLOSE_ENOUGH = 0.001; |
386 | 414 |
387 static bool closeStart(const SkDCubic& cubic, int cubicIndex, SkIntersections& i
, SkDPoint& pt) { | 415 static bool closeStart(const SkDCubic& cubic, int cubicIndex, SkIntersections& i
, SkDPoint& pt) { |
388 if (i[cubicIndex][0] != 0 || i[cubicIndex][1] > CLOSE_ENOUGH) { | 416 if (i[cubicIndex][0] != 0 || i[cubicIndex][1] > CLOSE_ENOUGH) { |
(...skipping 25 matching lines...) Expand all Loading... |
414 } | 442 } |
415 for (int triTest = 0; triTest < 3; ++triTest) { | 443 for (int triTest = 0; triTest < 3; ++triTest) { |
416 double origX = endPt[triTest]->fX; | 444 double origX = endPt[triTest]->fX; |
417 double origY = endPt[triTest]->fY; | 445 double origY = endPt[triTest]->fY; |
418 int oppTest = triTest + 1; | 446 int oppTest = triTest + 1; |
419 if (3 == oppTest) { | 447 if (3 == oppTest) { |
420 oppTest = 0; | 448 oppTest = 0; |
421 } | 449 } |
422 double adj = endPt[oppTest]->fX - origX; | 450 double adj = endPt[oppTest]->fX - origX; |
423 double opp = endPt[oppTest]->fY - origY; | 451 double opp = endPt[oppTest]->fY - origY; |
| 452 if (adj == 0 && opp == 0) { // if the other point equals the test p
oint, ignore it |
| 453 continue; |
| 454 } |
424 double sign = (c1[oddMan].fY - origY) * adj - (c1[oddMan].fX - origX
) * opp; | 455 double sign = (c1[oddMan].fY - origY) * adj - (c1[oddMan].fX - origX
) * opp; |
425 if (approximately_zero(sign)) { | 456 if (approximately_zero(sign)) { |
426 goto tryNextHalfPlane; | 457 goto tryNextHalfPlane; |
427 } | 458 } |
428 for (int n = 0; n < 4; ++n) { | 459 for (int n = 0; n < 4; ++n) { |
429 double test = (c2[n].fY - origY) * adj - (c2[n].fX - origX) * op
p; | 460 double test = (c2[n].fY - origY) * adj - (c2[n].fX - origX) * op
p; |
430 if (test * sign > 0 && !precisely_zero(test)) { | 461 if (test * sign > 0 && !precisely_zero(test)) { |
431 goto tryNextHalfPlane; | 462 goto tryNextHalfPlane; |
432 } | 463 } |
433 } | 464 } |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 return fUsed; | 555 return fUsed; |
525 } | 556 } |
526 SkIntersections i; | 557 SkIntersections i; |
527 i.fAllowNear = false; | 558 i.fAllowNear = false; |
528 i.fMax = 9; | 559 i.fMax = 9; |
529 ::intersect(c1, 0, 1, c2, 0, 1, 1, i); | 560 ::intersect(c1, 0, 1, c2, 0, 1, 1, i); |
530 int compCount = i.used(); | 561 int compCount = i.used(); |
531 if (compCount) { | 562 if (compCount) { |
532 int exactCount = used(); | 563 int exactCount = used(); |
533 if (exactCount == 0) { | 564 if (exactCount == 0) { |
534 set(i); | 565 *this = i; |
535 } else { | 566 } else { |
536 // at least one is exact or near, and at least one was computed. Eli
minate duplicates | 567 // at least one is exact or near, and at least one was computed. Eli
minate duplicates |
537 for (int exIdx = 0; exIdx < exactCount; ++exIdx) { | 568 for (int exIdx = 0; exIdx < exactCount; ++exIdx) { |
538 for (int cpIdx = 0; cpIdx < compCount; ) { | 569 for (int cpIdx = 0; cpIdx < compCount; ) { |
539 if (fT[0][0] == i[0][0] && fT[1][0] == i[1][0]) { | 570 if (fT[0][0] == i[0][0] && fT[1][0] == i[1][0]) { |
540 i.removeOne(cpIdx); | 571 i.removeOne(cpIdx); |
541 --compCount; | 572 --compCount; |
542 continue; | 573 continue; |
543 } | 574 } |
544 double tAvg = (fT[0][exIdx] + i[0][cpIdx]) / 2; | 575 double tAvg = (fT[0][exIdx] + i[0][cpIdx]) / 2; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
652 } | 683 } |
653 (void) intersect(c, c); | 684 (void) intersect(c, c); |
654 if (used() > 0) { | 685 if (used() > 0) { |
655 SkASSERT(used() == 1); | 686 SkASSERT(used() == 1); |
656 if (fT[0][0] > fT[1][0]) { | 687 if (fT[0][0] > fT[1][0]) { |
657 swapPts(); | 688 swapPts(); |
658 } | 689 } |
659 } | 690 } |
660 return used(); | 691 return used(); |
661 } | 692 } |
OLD | NEW |