| 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 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 #endif | 114 #endif |
| 115 SkIntersections locals; | 115 SkIntersections locals; |
| 116 intersectWithOrder(s1.fQuad, o1, s2.fQuad, o2, locals); | 116 intersectWithOrder(s1.fQuad, o1, s2.fQuad, o2, locals); |
| 117 double coStart[2] = { -1 }; | 117 double coStart[2] = { -1 }; |
| 118 SkDPoint coPoint; | 118 SkDPoint coPoint; |
| 119 int tCount = locals.used(); | 119 int tCount = locals.used(); |
| 120 for (int tIdx = 0; tIdx < tCount; ++tIdx) { | 120 for (int tIdx = 0; tIdx < tCount; ++tIdx) { |
| 121 double to1 = t1Start + (t1 - t1Start) * locals[0][tIdx]; | 121 double to1 = t1Start + (t1 - t1Start) * locals[0][tIdx]; |
| 122 double to2 = t2Start + (t2 - t2Start) * locals[1][tIdx]; | 122 double to2 = t2Start + (t2 - t2Start) * locals[1][tIdx]; |
| 123 // if the computed t is not sufficiently precise, iterate | 123 // if the computed t is not sufficiently precise, iterate |
| 124 SkDPoint p1 = cubic1.xyAtT(to1); | 124 SkDPoint p1 = cubic1.ptAtT(to1); |
| 125 SkDPoint p2 = cubic2.xyAtT(to2); | 125 SkDPoint p2 = cubic2.ptAtT(to2); |
| 126 if (p1.approximatelyEqual(p2)) { | 126 if (p1.approximatelyEqual(p2)) { |
| 127 if (locals.isCoincident(tIdx)) { | 127 if (locals.isCoincident(tIdx)) { |
| 128 if (coStart[0] < 0) { | 128 if (coStart[0] < 0) { |
| 129 coStart[0] = to1; | 129 coStart[0] = to1; |
| 130 coStart[1] = to2; | 130 coStart[1] = to2; |
| 131 coPoint = p1; | 131 coPoint = p1; |
| 132 } else { | 132 } else { |
| 133 i.insertCoincidentPair(coStart[0], to1, coStart[1],
to2, coPoint, p1); | 133 i.insertCoincidentPair(coStart[0], to1, coStart[1],
to2, coPoint, p1); |
| 134 coStart[0] = -1; | 134 coStart[0] = -1; |
| 135 } | 135 } |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 #endif | 382 #endif |
| 383 return; | 383 return; |
| 384 } | 384 } |
| 385 | 385 |
| 386 const double CLOSE_ENOUGH = 0.001; | 386 const double CLOSE_ENOUGH = 0.001; |
| 387 | 387 |
| 388 static bool closeStart(const SkDCubic& cubic, int cubicIndex, SkIntersections& i
, SkDPoint& pt) { | 388 static bool closeStart(const SkDCubic& cubic, int cubicIndex, SkIntersections& i
, SkDPoint& pt) { |
| 389 if (i[cubicIndex][0] != 0 || i[cubicIndex][1] > CLOSE_ENOUGH) { | 389 if (i[cubicIndex][0] != 0 || i[cubicIndex][1] > CLOSE_ENOUGH) { |
| 390 return false; | 390 return false; |
| 391 } | 391 } |
| 392 pt = cubic.xyAtT((i[cubicIndex][0] + i[cubicIndex][1]) / 2); | 392 pt = cubic.ptAtT((i[cubicIndex][0] + i[cubicIndex][1]) / 2); |
| 393 return true; | 393 return true; |
| 394 } | 394 } |
| 395 | 395 |
| 396 static bool closeEnd(const SkDCubic& cubic, int cubicIndex, SkIntersections& i,
SkDPoint& pt) { | 396 static bool closeEnd(const SkDCubic& cubic, int cubicIndex, SkIntersections& i,
SkDPoint& pt) { |
| 397 int last = i.used() - 1; | 397 int last = i.used() - 1; |
| 398 if (i[cubicIndex][last] != 1 || i[cubicIndex][last - 1] < 1 - CLOSE_ENOUGH)
{ | 398 if (i[cubicIndex][last] != 1 || i[cubicIndex][last - 1] < 1 - CLOSE_ENOUGH)
{ |
| 399 return false; | 399 return false; |
| 400 } | 400 } |
| 401 pt = cubic.xyAtT((i[cubicIndex][last] + i[cubicIndex][last - 1]) / 2); | 401 pt = cubic.ptAtT((i[cubicIndex][last] + i[cubicIndex][last - 1]) / 2); |
| 402 return true; | 402 return true; |
| 403 } | 403 } |
| 404 | 404 |
| 405 int SkIntersections::intersect(const SkDCubic& c1, const SkDCubic& c2) { | 405 int SkIntersections::intersect(const SkDCubic& c1, const SkDCubic& c2) { |
| 406 ::intersect(c1, 0, 1, c2, 0, 1, 1, *this); | 406 ::intersect(c1, 0, 1, c2, 0, 1, 1, *this); |
| 407 // FIXME: pass in cached bounds from caller | 407 // FIXME: pass in cached bounds from caller |
| 408 SkDRect c1Bounds, c2Bounds; | 408 SkDRect c1Bounds, c2Bounds; |
| 409 c1Bounds.setBounds(c1); // OPTIMIZE use setRawBounds ? | 409 c1Bounds.setBounds(c1); // OPTIMIZE use setRawBounds ? |
| 410 c2Bounds.setBounds(c2); | 410 c2Bounds.setBounds(c2); |
| 411 intersectEnd(c1, false, c2, c2Bounds, *this); | 411 intersectEnd(c1, false, c2, c2Bounds, *this); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 433 removeOne(used() - 2); | 433 removeOne(used() - 2); |
| 434 } | 434 } |
| 435 // vet the pairs of t values to see if the mid value is also on the curve. I
f so, mark | 435 // vet the pairs of t values to see if the mid value is also on the curve. I
f so, mark |
| 436 // the span as coincident | 436 // the span as coincident |
| 437 if (fUsed >= 2 && !coincidentUsed()) { | 437 if (fUsed >= 2 && !coincidentUsed()) { |
| 438 int last = fUsed - 1; | 438 int last = fUsed - 1; |
| 439 int match = 0; | 439 int match = 0; |
| 440 for (int index = 0; index < last; ++index) { | 440 for (int index = 0; index < last; ++index) { |
| 441 double mid1 = (fT[0][index] + fT[0][index + 1]) / 2; | 441 double mid1 = (fT[0][index] + fT[0][index + 1]) / 2; |
| 442 double mid2 = (fT[1][index] + fT[1][index + 1]) / 2; | 442 double mid2 = (fT[1][index] + fT[1][index + 1]) / 2; |
| 443 pt[0] = c1.xyAtT(mid1); | 443 pt[0] = c1.ptAtT(mid1); |
| 444 pt[1] = c2.xyAtT(mid2); | 444 pt[1] = c2.ptAtT(mid2); |
| 445 if (pt[0].approximatelyEqual(pt[1])) { | 445 if (pt[0].approximatelyEqual(pt[1])) { |
| 446 match |= 1 << index; | 446 match |= 1 << index; |
| 447 } | 447 } |
| 448 } | 448 } |
| 449 if (match) { | 449 if (match) { |
| 450 if (((match + 1) & match) != 0) { | 450 if (((match + 1) & match) != 0) { |
| 451 SkDebugf("%s coincident hole\n", __FUNCTION__); | 451 SkDebugf("%s coincident hole\n", __FUNCTION__); |
| 452 } | 452 } |
| 453 // for now, assume that everything from start to finish is coinciden
t | 453 // for now, assume that everything from start to finish is coinciden
t |
| 454 if (fUsed > 2) { | 454 if (fUsed > 2) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 } | 487 } |
| 488 (void) intersect(c, c); | 488 (void) intersect(c, c); |
| 489 if (used() > 0) { | 489 if (used() > 0) { |
| 490 SkASSERT(used() == 1); | 490 SkASSERT(used() == 1); |
| 491 if (fT[0][0] > fT[1][0]) { | 491 if (fT[0][0] > fT[1][0]) { |
| 492 swapPts(); | 492 swapPts(); |
| 493 } | 493 } |
| 494 } | 494 } |
| 495 return used(); | 495 return used(); |
| 496 } | 496 } |
| OLD | NEW |