| 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 #include "SkOpAngle.h" | 7 #include "SkOpAngle.h" |
| 8 #include "SkOpSegment.h" | 8 #include "SkOpSegment.h" |
| 9 #include "SkPathOpsCurve.h" | 9 #include "SkPathOpsCurve.h" |
| 10 #include "SkTSort.h" | 10 #include "SkTSort.h" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 20 | 26 | 55 20 | 26 |
| 56 21 | 25 | 56 21 | 25 |
| 57 22 23 24 | 57 22 23 24 |
| 58 */ | 58 */ |
| 59 | 59 |
| 60 // return true if lh < this < rh | 60 // return true if lh < this < rh |
| 61 bool SkOpAngle::after(SkOpAngle* test) { | 61 bool SkOpAngle::after(SkOpAngle* test) { |
| 62 SkOpAngle* lh = test; | 62 SkOpAngle* lh = test; |
| 63 SkOpAngle* rh = lh->fNext; | 63 SkOpAngle* rh = lh->fNext; |
| 64 SkASSERT(lh != rh); | 64 SkASSERT(lh != rh); |
| 65 fCurvePart = fOriginalCurvePart; |
| 66 lh->fCurvePart = lh->fOriginalCurvePart; |
| 67 lh->fCurvePart.offset(lh->segment()->verb(), fCurvePart[0] - lh->fCurvePart[
0]); |
| 68 rh->fCurvePart = rh->fOriginalCurvePart; |
| 69 rh->fCurvePart.offset(rh->segment()->verb(), fCurvePart[0] - rh->fCurvePart[
0]); |
| 70 |
| 65 #if DEBUG_ANGLE | 71 #if DEBUG_ANGLE |
| 66 SkString bugOut; | 72 SkString bugOut; |
| 67 bugOut.printf("%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g" | 73 bugOut.printf("%s [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g" |
| 68 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g" | 74 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g" |
| 69 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g ", __FUNCTION__, | 75 " < [%d/%d] %d/%d tStart=%1.9g tEnd=%1.9g ", __FUNCTION__, |
| 70 lh->segment()->debugID(), lh->debugID(), lh->fSectorStart, lh->fSect
orEnd, | 76 lh->segment()->debugID(), lh->debugID(), lh->fSectorStart, lh->fSect
orEnd, |
| 71 lh->fStart->t(), lh->fEnd->t(), | 77 lh->fStart->t(), lh->fEnd->t(), |
| 72 segment()->debugID(), debugID(), fSectorStart, fSectorEnd, fStart->t
(), fEnd->t(), | 78 segment()->debugID(), debugID(), fSectorStart, fSectorEnd, fStart->t
(), fEnd->t(), |
| 73 rh->segment()->debugID(), rh->debugID(), rh->fSectorStart, rh->fSect
orEnd, | 79 rh->segment()->debugID(), rh->debugID(), rh->fSectorStart, rh->fSect
orEnd, |
| 74 rh->fStart->t(), rh->fEnd->t()); | 80 rh->fStart->t(), rh->fEnd->t()); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 // FIXME : once all variants are understood, rewrite this more simply | 149 // FIXME : once all variants are understood, rewrite this more simply |
| 144 if (ltOrder == 0 && lrOrder == 0) { | 150 if (ltOrder == 0 && lrOrder == 0) { |
| 145 SkASSERT(trOrder < 0); | 151 SkASSERT(trOrder < 0); |
| 146 // FIXME : once this is verified to work, remove one opposite angle call | 152 // FIXME : once this is verified to work, remove one opposite angle call |
| 147 SkDEBUGCODE(bool lrOpposite = lh->oppositePlanes(rh)); | 153 SkDEBUGCODE(bool lrOpposite = lh->oppositePlanes(rh)); |
| 148 bool ltOpposite = lh->oppositePlanes(this); | 154 bool ltOpposite = lh->oppositePlanes(this); |
| 149 SkASSERT(lrOpposite != ltOpposite); | 155 SkASSERT(lrOpposite != ltOpposite); |
| 150 return COMPARE_RESULT(8, ltOpposite); | 156 return COMPARE_RESULT(8, ltOpposite); |
| 151 } else if (ltOrder == 1 && trOrder == 0) { | 157 } else if (ltOrder == 1 && trOrder == 0) { |
| 152 SkASSERT(lrOrder < 0); | 158 SkASSERT(lrOrder < 0); |
| 153 SkDEBUGCODE(bool ltOpposite = lh->oppositePlanes(this)); | |
| 154 bool trOpposite = oppositePlanes(rh); | 159 bool trOpposite = oppositePlanes(rh); |
| 155 SkASSERT(ltOpposite != trOpposite); | |
| 156 return COMPARE_RESULT(9, trOpposite); | 160 return COMPARE_RESULT(9, trOpposite); |
| 157 } else if (lrOrder == 1 && trOrder == 1) { | 161 } else if (lrOrder == 1 && trOrder == 1) { |
| 158 SkASSERT(ltOrder < 0); | 162 SkASSERT(ltOrder < 0); |
| 159 SkDEBUGCODE(bool trOpposite = oppositePlanes(rh)); | 163 SkDEBUGCODE(bool trOpposite = oppositePlanes(rh)); |
| 160 bool lrOpposite = lh->oppositePlanes(rh); | 164 bool lrOpposite = lh->oppositePlanes(rh); |
| 161 SkASSERT(lrOpposite != trOpposite); | 165 SkASSERT(lrOpposite != trOpposite); |
| 162 return COMPARE_RESULT(10, lrOpposite); | 166 return COMPARE_RESULT(10, lrOpposite); |
| 163 } | 167 } |
| 164 if (lrOrder < 0) { | 168 if (lrOrder < 0) { |
| 165 if (ltOrder < 0) { | 169 if (ltOrder < 0) { |
| 166 return COMPARE_RESULT(11, trOrder); | 170 return COMPARE_RESULT(11, trOrder); |
| 167 } | 171 } |
| 168 return COMPARE_RESULT(12, ltOrder); | 172 return COMPARE_RESULT(12, ltOrder); |
| 169 } | 173 } |
| 170 return COMPARE_RESULT(13, !lrOrder); | 174 return COMPARE_RESULT(13, !lrOrder); |
| 171 } | 175 } |
| 172 | 176 |
| 173 // given a line, see if the opposite curve's convex hull is all on one side | 177 // given a line, see if the opposite curve's convex hull is all on one side |
| 174 // returns -1=not on one side 0=this CW of test 1=this CCW of test | 178 // returns -1=not on one side 0=this CW of test 1=this CCW of test |
| 175 int SkOpAngle::allOnOneSide(const SkOpAngle* test) { | 179 int SkOpAngle::allOnOneSide(const SkOpAngle* test) { |
| 176 SkASSERT(!fIsCurve); | 180 SkASSERT(!fIsCurve); |
| 177 SkASSERT(test->fIsCurve); | 181 SkASSERT(test->fIsCurve); |
| 178 const SkDPoint& origin = test->fCurvePart[0]; | 182 SkDPoint origin = fCurvePart[0]; |
| 179 SkVector line; | 183 SkDVector line = fCurvePart[1] - origin; |
| 180 if (segment()->verb() == SkPath::kLine_Verb) { | |
| 181 const SkPoint* linePts = segment()->pts(); | |
| 182 int lineStart = fStart->t() < fEnd->t() ? 0 : 1; | |
| 183 line = linePts[lineStart ^ 1] - linePts[lineStart]; | |
| 184 } else { | |
| 185 line = (fCurvePart[1] - fCurvePart[0]).asSkVector(); | |
| 186 } | |
| 187 float crosses[3]; | 184 float crosses[3]; |
| 188 SkPath::Verb testVerb = test->segment()->verb(); | 185 SkPath::Verb testVerb = test->segment()->verb(); |
| 189 int iMax = SkPathOpsVerbToPoints(testVerb); | 186 int iMax = SkPathOpsVerbToPoints(testVerb); |
| 190 // SkASSERT(origin == test.fCurveHalf[0]); | 187 // SkASSERT(origin == test.fCurveHalf[0]); |
| 191 const SkDCurve& testCurve = test->fCurvePart; | 188 const SkDCurve& testCurve = test->fCurvePart; |
| 192 for (int index = 1; index <= iMax; ++index) { | 189 for (int index = 1; index <= iMax; ++index) { |
| 193 float xy1 = (float) (line.fX * (testCurve[index].fY - origin.fY)); | 190 float xy1 = (float) (line.fX * (testCurve[index].fY - origin.fY)); |
| 194 float xy2 = (float) (line.fY * (testCurve[index].fX - origin.fX)); | 191 float xy2 = (float) (line.fY * (testCurve[index].fX - origin.fX)); |
| 195 crosses[index - 1] = AlmostEqualUlps(xy1, xy2) ? 0 : xy1 - xy2; | 192 crosses[index - 1] = AlmostEqualUlps(xy1, xy2) ? 0 : xy1 - xy2; |
| 196 } | 193 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 scratch[1] = rh->fCurvePart[1] - rh->fCurvePart[0]; | 234 scratch[1] = rh->fCurvePart[1] - rh->fCurvePart[0]; |
| 238 tweep = &scratch[1]; | 235 tweep = &scratch[1]; |
| 239 } | 236 } |
| 240 double s0xt0 = sweep->crossCheck(*tweep); | 237 double s0xt0 = sweep->crossCheck(*tweep); |
| 241 if (tangentsDiverge(rh, s0xt0)) { | 238 if (tangentsDiverge(rh, s0xt0)) { |
| 242 return s0xt0 < 0; | 239 return s0xt0 < 0; |
| 243 } | 240 } |
| 244 // compute the perpendicular to the endpoints and see where it intersects th
e opposite curve | 241 // compute the perpendicular to the endpoints and see where it intersects th
e opposite curve |
| 245 // if the intersections within the t range, do a cross check on those | 242 // if the intersections within the t range, do a cross check on those |
| 246 bool inside; | 243 bool inside; |
| 247 if (!fCurvePart[SkPathOpsVerbToPoints(this->segment()->verb())].approximatel
yEqual( | 244 if (!fEnd->contains(rh->fEnd)) { |
| 248 rh->fCurvePart[SkPathOpsVerbToPoints(rh->segment()->verb())])) { | |
| 249 if (this->endToSide(rh, &inside)) { | 245 if (this->endToSide(rh, &inside)) { |
| 250 return inside; | 246 return inside; |
| 251 } | 247 } |
| 252 if (rh->endToSide(this, &inside)) { | 248 if (rh->endToSide(this, &inside)) { |
| 253 return !inside; | 249 return !inside; |
| 254 } | 250 } |
| 255 } | 251 } |
| 256 if (this->midToSide(rh, &inside)) { | 252 if (this->midToSide(rh, &inside)) { |
| 257 return inside; | 253 return inside; |
| 258 } | 254 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 273 | 269 |
| 274 // the original angle is too short to get meaningful sector information | 270 // the original angle is too short to get meaningful sector information |
| 275 // lengthen it until it is long enough to be meaningful or leave it unset if len
gthening it | 271 // lengthen it until it is long enough to be meaningful or leave it unset if len
gthening it |
| 276 // would cause it to intersect one of the adjacent angles | 272 // would cause it to intersect one of the adjacent angles |
| 277 bool SkOpAngle::computeSector() { | 273 bool SkOpAngle::computeSector() { |
| 278 if (fComputedSector) { | 274 if (fComputedSector) { |
| 279 return !fUnorderable; | 275 return !fUnorderable; |
| 280 } | 276 } |
| 281 fComputedSector = true; | 277 fComputedSector = true; |
| 282 bool stepUp = fStart->t() < fEnd->t(); | 278 bool stepUp = fStart->t() < fEnd->t(); |
| 283 const SkOpSpanBase* checkEnd = fEnd; | 279 SkOpSpanBase* checkEnd = fEnd; |
| 284 if (checkEnd->final() && stepUp) { | 280 if (checkEnd->final() && stepUp) { |
| 285 fUnorderable = true; | 281 fUnorderable = true; |
| 286 return false; | 282 return false; |
| 287 } | 283 } |
| 288 do { | 284 do { |
| 289 // advance end | 285 // advance end |
| 290 const SkOpSegment* other = checkEnd->segment(); | 286 const SkOpSegment* other = checkEnd->segment(); |
| 291 const SkOpSpanBase* oSpan = other->head(); | 287 const SkOpSpanBase* oSpan = other->head(); |
| 292 do { | 288 do { |
| 293 if (oSpan->segment() != segment()) { | 289 if (oSpan->segment() != segment()) { |
| 294 continue; | 290 continue; |
| 295 } | 291 } |
| 296 if (oSpan == checkEnd) { | 292 if (oSpan == checkEnd) { |
| 297 continue; | 293 continue; |
| 298 } | 294 } |
| 299 if (!approximately_equal(oSpan->t(), checkEnd->t())) { | 295 if (!approximately_equal(oSpan->t(), checkEnd->t())) { |
| 300 continue; | 296 continue; |
| 301 } | 297 } |
| 302 goto recomputeSector; | 298 goto recomputeSector; |
| 303 } while (!oSpan->final() && (oSpan = oSpan->upCast()->next())); | 299 } while (!oSpan->final() && (oSpan = oSpan->upCast()->next())); |
| 304 checkEnd = stepUp ? !checkEnd->final() | 300 checkEnd = stepUp ? !checkEnd->final() |
| 305 ? checkEnd->upCast()->next() : nullptr | 301 ? checkEnd->upCast()->next() : nullptr |
| 306 : checkEnd->prev(); | 302 : checkEnd->prev(); |
| 307 } while (checkEnd); | 303 } while (checkEnd); |
| 308 recomputeSector: | 304 recomputeSector: |
| 309 SkOpSpanBase* computedEnd = stepUp ? checkEnd ? checkEnd->prev() : fEnd->seg
ment()->head() | 305 SkOpSpanBase* computedEnd = stepUp ? checkEnd ? checkEnd->prev() : fEnd->seg
ment()->head() |
| 310 : checkEnd ? checkEnd->upCast()->next() : fEnd->segment()->tail(); | 306 : checkEnd ? checkEnd->upCast()->next() : fEnd->segment()->tail(); |
| 311 if (checkEnd == fEnd || computedEnd == fEnd || computedEnd == fStart) { | 307 if (checkEnd == fEnd || computedEnd == fEnd || computedEnd == fStart) { |
| 312 fUnorderable = true; | 308 fUnorderable = true; |
| 313 return false; | 309 return false; |
| 314 } | 310 } |
| 315 if (stepUp != (fStart->t() < computedEnd->t())) { | 311 if (stepUp != (fStart->t() < computedEnd->t())) { |
| 316 fUnorderable = true; | 312 fUnorderable = true; |
| 317 return false; | 313 return false; |
| 318 } | 314 } |
| 319 SkOpSpanBase* saveEnd = fEnd; | 315 SkOpSpanBase* saveEnd = fEnd; |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 return sqrt(longest) / dist; | 387 return sqrt(longest) / dist; |
| 392 } | 388 } |
| 393 | 389 |
| 394 bool SkOpAngle::endsIntersect(SkOpAngle* rh) { | 390 bool SkOpAngle::endsIntersect(SkOpAngle* rh) { |
| 395 SkPath::Verb lVerb = this->segment()->verb(); | 391 SkPath::Verb lVerb = this->segment()->verb(); |
| 396 SkPath::Verb rVerb = rh->segment()->verb(); | 392 SkPath::Verb rVerb = rh->segment()->verb(); |
| 397 int lPts = SkPathOpsVerbToPoints(lVerb); | 393 int lPts = SkPathOpsVerbToPoints(lVerb); |
| 398 int rPts = SkPathOpsVerbToPoints(rVerb); | 394 int rPts = SkPathOpsVerbToPoints(rVerb); |
| 399 SkDLine rays[] = {{{this->fCurvePart[0], rh->fCurvePart[rPts]}}, | 395 SkDLine rays[] = {{{this->fCurvePart[0], rh->fCurvePart[rPts]}}, |
| 400 {{this->fCurvePart[0], this->fCurvePart[lPts]}}}; | 396 {{this->fCurvePart[0], this->fCurvePart[lPts]}}}; |
| 401 if (rays[0][1] == rays[1][1]) { | 397 if (this->fEnd->contains(rh->fEnd)) { |
| 402 return checkParallel(rh); | 398 return checkParallel(rh); |
| 403 } | 399 } |
| 404 double smallTs[2] = {-1, -1}; | 400 double smallTs[2] = {-1, -1}; |
| 405 bool limited[2] = {false, false}; | 401 bool limited[2] = {false, false}; |
| 406 for (int index = 0; index < 2; ++index) { | 402 for (int index = 0; index < 2; ++index) { |
| 407 SkPath::Verb cVerb = index ? rVerb : lVerb; | 403 SkPath::Verb cVerb = index ? rVerb : lVerb; |
| 408 // if the curve is a line, then the line and the ray intersect only at t
heir crossing | 404 // if the curve is a line, then the line and the ray intersect only at t
heir crossing |
| 409 if (cVerb == SkPath::kLine_Verb) { | 405 if (cVerb == SkPath::kLine_Verb) { |
| 410 continue; | 406 continue; |
| 411 } | 407 } |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 531 const SkDCurve& curve = rh->fCurvePart; | 527 const SkDCurve& curve = rh->fCurvePart; |
| 532 int oppPts = SkPathOpsVerbToPoints(oppVerb); | 528 int oppPts = SkPathOpsVerbToPoints(oppVerb); |
| 533 for (int idx2 = 0; idx2 <= oppPts; ++idx2) { | 529 for (int idx2 = 0; idx2 <= oppPts; ++idx2) { |
| 534 minX = SkTMin(minX, curve[idx2].fX); | 530 minX = SkTMin(minX, curve[idx2].fX); |
| 535 minY = SkTMin(minY, curve[idx2].fY); | 531 minY = SkTMin(minY, curve[idx2].fY); |
| 536 maxX = SkTMax(maxX, curve[idx2].fX); | 532 maxX = SkTMax(maxX, curve[idx2].fX); |
| 537 maxY = SkTMax(maxY, curve[idx2].fY); | 533 maxY = SkTMax(maxY, curve[idx2].fY); |
| 538 } | 534 } |
| 539 double maxWidth = SkTMax(maxX - minX, maxY - minY); | 535 double maxWidth = SkTMax(maxX - minX, maxY - minY); |
| 540 endDist /= maxWidth; | 536 endDist /= maxWidth; |
| 541 if (endDist < 5e-11) { // empirically found | 537 if (endDist < 5e-12) { // empirically found |
| 542 return false; | 538 return false; |
| 543 } | 539 } |
| 544 const SkDPoint* endPt = &rayEnd[0]; | 540 const SkDPoint* endPt = &rayEnd[0]; |
| 545 SkDPoint oppPt = iEnd.pt(closestEnd); | 541 SkDPoint oppPt = iEnd.pt(closestEnd); |
| 546 SkDVector vLeft = *endPt - start; | 542 SkDVector vLeft = *endPt - start; |
| 547 SkDVector vRight = oppPt - start; | 543 SkDVector vRight = oppPt - start; |
| 548 double dir = vLeft.crossCheck(vRight); | 544 double dir = vLeft.crossNoNormalCheck(vRight); |
| 549 if (!dir) { | 545 if (!dir) { |
| 550 return false; | 546 return false; |
| 551 } | 547 } |
| 552 *inside = dir < 0; | 548 *inside = dir < 0; |
| 553 return true; | 549 return true; |
| 554 } | 550 } |
| 555 | 551 |
| 556 /* y<0 y==0 y>0 x<0 x==0 x>0 xy<0 xy==0 xy>0 | 552 /* y<0 y==0 y>0 x<0 x==0 x>0 xy<0 xy==0 xy>0 |
| 557 0 x x x | 553 0 x x x |
| 558 1 x x x | 554 1 x x x |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 778 double rx_y = rightX * leftY; | 774 double rx_y = rightX * leftY; |
| 779 if (x_ry == rx_y) { | 775 if (x_ry == rx_y) { |
| 780 if (leftX * rightX < 0 || leftY * rightY < 0) { | 776 if (leftX * rightX < 0 || leftY * rightY < 0) { |
| 781 return true; // exactly 180 degrees apart | 777 return true; // exactly 180 degrees apart |
| 782 } | 778 } |
| 783 goto unorderable; | 779 goto unorderable; |
| 784 } | 780 } |
| 785 SkASSERT(x_ry != rx_y); // indicates an undetected coincidence -- wo
rth finding earlier | 781 SkASSERT(x_ry != rx_y); // indicates an undetected coincidence -- wo
rth finding earlier |
| 786 return x_ry < rx_y; | 782 return x_ry < rx_y; |
| 787 } | 783 } |
| 788 if ((result = allOnOneSide(rh)) >= 0) { | 784 if ((result = this->allOnOneSide(rh)) >= 0) { |
| 789 return result; | 785 return result; |
| 790 } | 786 } |
| 791 if (fUnorderable || approximately_zero(rh->fSide)) { | 787 if (fUnorderable || approximately_zero(rh->fSide)) { |
| 792 goto unorderable; | 788 goto unorderable; |
| 793 } | 789 } |
| 794 } else if (!rh->fIsCurve) { | 790 } else if (!rh->fIsCurve) { |
| 795 if ((result = rh->allOnOneSide(this)) >= 0) { | 791 if ((result = rh->allOnOneSide(this)) >= 0) { |
| 796 return !result; | 792 return !result; |
| 797 } | 793 } |
| 798 if (rh->fUnorderable || approximately_zero(fSide)) { | 794 if (rh->fUnorderable || approximately_zero(fSide)) { |
| 799 goto unorderable; | 795 goto unorderable; |
| 800 } | 796 } |
| 801 } | 797 } else if ((result = this->convexHullOverlaps(rh)) >= 0) { |
| 802 if ((result = convexHullOverlaps(rh)) >= 0) { | |
| 803 return result; | 798 return result; |
| 804 } | 799 } |
| 805 return endsIntersect(rh); | 800 return this->endsIntersect(rh); |
| 806 unorderable: | 801 unorderable: |
| 807 fUnorderable = true; | 802 fUnorderable = true; |
| 808 rh->fUnorderable = true; | 803 rh->fUnorderable = true; |
| 809 return true; | 804 return true; |
| 810 } | 805 } |
| 811 | 806 |
| 812 // OPTIMIZE: if this shows up in a profile, add a previous pointer | 807 // OPTIMIZE: if this shows up in a profile, add a previous pointer |
| 813 // as is, this should be rarely called | 808 // as is, this should be rarely called |
| 814 SkOpAngle* SkOpAngle::previous() const { | 809 SkOpAngle* SkOpAngle::previous() const { |
| 815 SkOpAngle* last = fNext; | 810 SkOpAngle* last = fNext; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 839 | 834 |
| 840 void SkOpAngle::setCurveHullSweep() { | 835 void SkOpAngle::setCurveHullSweep() { |
| 841 fUnorderedSweep = false; | 836 fUnorderedSweep = false; |
| 842 fSweep[0] = fCurvePart[1] - fCurvePart[0]; | 837 fSweep[0] = fCurvePart[1] - fCurvePart[0]; |
| 843 const SkOpSegment* segment = fStart->segment(); | 838 const SkOpSegment* segment = fStart->segment(); |
| 844 if (SkPath::kLine_Verb == segment->verb()) { | 839 if (SkPath::kLine_Verb == segment->verb()) { |
| 845 fSweep[1] = fSweep[0]; | 840 fSweep[1] = fSweep[0]; |
| 846 return; | 841 return; |
| 847 } | 842 } |
| 848 fSweep[1] = fCurvePart[2] - fCurvePart[0]; | 843 fSweep[1] = fCurvePart[2] - fCurvePart[0]; |
| 844 // OPTIMIZE: I do the following float check a lot -- probably need a |
| 845 // central place for this val-is-small-compared-to-curve check |
| 846 double maxVal = 0; |
| 847 for (int index = 0; index < SkPathOpsVerbToPoints(segment->verb()); ++index)
{ |
| 848 maxVal = SkTMax(maxVal, SkTMax(SkTAbs(fCurvePart[index].fX), |
| 849 SkTAbs(fCurvePart[index].fY))); |
| 850 } |
| 851 |
| 849 if (SkPath::kCubic_Verb != segment->verb()) { | 852 if (SkPath::kCubic_Verb != segment->verb()) { |
| 850 if (!fSweep[0].fX && !fSweep[0].fY) { | 853 if (roughly_zero_when_compared_to(fSweep[0].fX, maxVal) |
| 854 && roughly_zero_when_compared_to(fSweep[0].fY, maxVal)) { |
| 851 fSweep[0] = fSweep[1]; | 855 fSweep[0] = fSweep[1]; |
| 852 } | 856 } |
| 853 return; | 857 return; |
| 854 } | 858 } |
| 855 SkDVector thirdSweep = fCurvePart[3] - fCurvePart[0]; | 859 SkDVector thirdSweep = fCurvePart[3] - fCurvePart[0]; |
| 856 if (fSweep[0].fX == 0 && fSweep[0].fY == 0) { | 860 if (fSweep[0].fX == 0 && fSweep[0].fY == 0) { |
| 857 fSweep[0] = fSweep[1]; | 861 fSweep[0] = fSweep[1]; |
| 858 fSweep[1] = thirdSweep; | 862 fSweep[1] = thirdSweep; |
| 859 if (fSweep[0].fX == 0 && fSweep[0].fY == 0) { | 863 if (roughly_zero_when_compared_to(fSweep[0].fX, maxVal) |
| 864 && roughly_zero_when_compared_to(fSweep[0].fY, maxVal)) { |
| 860 fSweep[0] = fSweep[1]; | 865 fSweep[0] = fSweep[1]; |
| 861 fCurvePart[1] = fCurvePart[3]; | 866 fCurvePart[1] = fCurvePart[3]; |
| 862 fIsCurve = false; | 867 fIsCurve = false; |
| 863 } | 868 } |
| 864 return; | 869 return; |
| 865 } | 870 } |
| 866 double s1x3 = fSweep[0].crossCheck(thirdSweep); | 871 double s1x3 = fSweep[0].crossCheck(thirdSweep); |
| 867 double s3x2 = thirdSweep.crossCheck(fSweep[1]); | 872 double s3x2 = thirdSweep.crossCheck(fSweep[1]); |
| 868 if (s1x3 * s3x2 >= 0) { // if third vector is on or between first two vecto
rs | 873 if (s1x3 * s3x2 >= 0) { // if third vector is on or between first two vecto
rs |
| 869 return; | 874 return; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 887 fUnorderable = true; | 892 fUnorderable = true; |
| 888 return; | 893 return; |
| 889 } | 894 } |
| 890 const SkOpSegment* segment = fStart->segment(); | 895 const SkOpSegment* segment = fStart->segment(); |
| 891 const SkPoint* pts = segment->pts(); | 896 const SkPoint* pts = segment->pts(); |
| 892 SkDEBUGCODE(fCurvePart.fVerb = SkPath::kCubic_Verb); | 897 SkDEBUGCODE(fCurvePart.fVerb = SkPath::kCubic_Verb); |
| 893 SkDEBUGCODE(fCurvePart[2].fX = fCurvePart[2].fY = fCurvePart[3].fX = fCurveP
art[3].fY | 898 SkDEBUGCODE(fCurvePart[2].fX = fCurvePart[2].fY = fCurvePart[3].fX = fCurveP
art[3].fY |
| 894 = SK_ScalarNaN); | 899 = SK_ScalarNaN); |
| 895 SkDEBUGCODE(fCurvePart.fVerb = segment->verb()); | 900 SkDEBUGCODE(fCurvePart.fVerb = segment->verb()); |
| 896 segment->subDivide(fStart, fEnd, &fCurvePart); | 901 segment->subDivide(fStart, fEnd, &fCurvePart); |
| 902 fOriginalCurvePart = fCurvePart; |
| 897 setCurveHullSweep(); | 903 setCurveHullSweep(); |
| 898 const SkPath::Verb verb = segment->verb(); | 904 const SkPath::Verb verb = segment->verb(); |
| 899 if (verb != SkPath::kLine_Verb | 905 if (verb != SkPath::kLine_Verb |
| 900 && !(fIsCurve = fSweep[0].crossCheck(fSweep[1]) != 0)) { | 906 && !(fIsCurve = fSweep[0].crossCheck(fSweep[1]) != 0)) { |
| 901 SkDLine lineHalf; | 907 SkDLine lineHalf; |
| 902 lineHalf[0].set(fCurvePart[0].asSkPoint()); | 908 lineHalf[0].set(fCurvePart[0].asSkPoint()); |
| 903 lineHalf[1].set(fCurvePart[SkPathOpsVerbToPoints(verb)].asSkPoint()); | 909 lineHalf[1].set(fCurvePart[SkPathOpsVerbToPoints(verb)].asSkPoint()); |
| 904 fTangentHalf.lineEndPoints(lineHalf); | 910 fTangentHalf.lineEndPoints(lineHalf); |
| 905 fSide = 0; | 911 fSide = 0; |
| 906 } | 912 } |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1042 double s0dt0 = sweep[0].dot(tweep[0]); | 1048 double s0dt0 = sweep[0].dot(tweep[0]); |
| 1043 if (!s0dt0) { | 1049 if (!s0dt0) { |
| 1044 return true; | 1050 return true; |
| 1045 } | 1051 } |
| 1046 SkASSERT(s0dt0 != 0); | 1052 SkASSERT(s0dt0 != 0); |
| 1047 double m = s0xt0 / s0dt0; | 1053 double m = s0xt0 / s0dt0; |
| 1048 double sDist = sweep[0].length() * m; | 1054 double sDist = sweep[0].length() * m; |
| 1049 double tDist = tweep[0].length() * m; | 1055 double tDist = tweep[0].length() * m; |
| 1050 bool useS = fabs(sDist) < fabs(tDist); | 1056 bool useS = fabs(sDist) < fabs(tDist); |
| 1051 double mFactor = fabs(useS ? this->distEndRatio(sDist) : rh->distEndRatio(tD
ist)); | 1057 double mFactor = fabs(useS ? this->distEndRatio(sDist) : rh->distEndRatio(tD
ist)); |
| 1052 return mFactor < 2400; // empirically found limit | 1058 return mFactor < 50; // empirically found limit |
| 1053 } | 1059 } |
| OLD | NEW |