| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2008 The Android Open Source Project | 2 * Copyright 2008 The Android Open Source Project |
| 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 "SkStrokerPriv.h" | 8 #include "SkStrokerPriv.h" |
| 9 #include "SkGeometry.h" | 9 #include "SkGeometry.h" |
| 10 #include "SkPathPriv.h" | 10 #include "SkPathPriv.h" |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 289 fOuter.close(); | 289 fOuter.close(); |
| 290 // now add fInner as its own contour | 290 // now add fInner as its own contour |
| 291 fInner.getLastPt(&pt); | 291 fInner.getLastPt(&pt); |
| 292 fOuter.moveTo(pt.fX, pt.fY); | 292 fOuter.moveTo(pt.fX, pt.fY); |
| 293 fOuter.reversePathTo(fInner); | 293 fOuter.reversePathTo(fInner); |
| 294 fOuter.close(); | 294 fOuter.close(); |
| 295 } else { // add caps to start and end | 295 } else { // add caps to start and end |
| 296 // cap the end | 296 // cap the end |
| 297 fInner.getLastPt(&pt); | 297 fInner.getLastPt(&pt); |
| 298 fCapper(&fOuter, fPrevPt, fPrevNormal, pt, | 298 fCapper(&fOuter, fPrevPt, fPrevNormal, pt, |
| 299 currIsLine ? &fInner : NULL); | 299 currIsLine ? &fInner : nullptr); |
| 300 fOuter.reversePathTo(fInner); | 300 fOuter.reversePathTo(fInner); |
| 301 // cap the start | 301 // cap the start |
| 302 fCapper(&fOuter, fFirstPt, -fFirstNormal, fFirstOuterPt, | 302 fCapper(&fOuter, fFirstPt, -fFirstNormal, fFirstOuterPt, |
| 303 fPrevIsLine ? &fInner : NULL); | 303 fPrevIsLine ? &fInner : nullptr); |
| 304 fOuter.close(); | 304 fOuter.close(); |
| 305 } | 305 } |
| 306 } | 306 } |
| 307 // since we may re-use fInner, we rewind instead of reset, to save on | 307 // since we may re-use fInner, we rewind instead of reset, to save on |
| 308 // reallocating its internal storage. | 308 // reallocating its internal storage. |
| 309 fInner.rewind(); | 309 fInner.rewind(); |
| 310 fSegmentCount = -1; | 310 fSegmentCount = -1; |
| 311 } | 311 } |
| 312 | 312 |
| 313 /////////////////////////////////////////////////////////////////////////////// | 313 /////////////////////////////////////////////////////////////////////////////// |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 546 *tangentPtPtr = degenerateAB ? &cubic[2] : &cubic[1]; | 546 *tangentPtPtr = degenerateAB ? &cubic[2] : &cubic[1]; |
| 547 return kQuad_ReductionType; | 547 return kQuad_ReductionType; |
| 548 } | 548 } |
| 549 SkScalar tValues[3]; | 549 SkScalar tValues[3]; |
| 550 int count = SkFindCubicMaxCurvature(cubic, tValues); | 550 int count = SkFindCubicMaxCurvature(cubic, tValues); |
| 551 if (count == 0) { | 551 if (count == 0) { |
| 552 return kLine_ReductionType; | 552 return kLine_ReductionType; |
| 553 } | 553 } |
| 554 for (int index = 0; index < count; ++index) { | 554 for (int index = 0; index < count; ++index) { |
| 555 SkScalar t = tValues[index]; | 555 SkScalar t = tValues[index]; |
| 556 SkEvalCubicAt(cubic, t, &reduction[index], NULL, NULL); | 556 SkEvalCubicAt(cubic, t, &reduction[index], nullptr, nullptr); |
| 557 } | 557 } |
| 558 static_assert(kQuad_ReductionType + 1 == kDegenerate_ReductionType, "enum_ou
t_of_whack"); | 558 static_assert(kQuad_ReductionType + 1 == kDegenerate_ReductionType, "enum_ou
t_of_whack"); |
| 559 static_assert(kQuad_ReductionType + 2 == kDegenerate2_ReductionType, "enum_o
ut_of_whack"); | 559 static_assert(kQuad_ReductionType + 2 == kDegenerate2_ReductionType, "enum_o
ut_of_whack"); |
| 560 static_assert(kQuad_ReductionType + 3 == kDegenerate3_ReductionType, "enum_o
ut_of_whack"); | 560 static_assert(kQuad_ReductionType + 3 == kDegenerate3_ReductionType, "enum_o
ut_of_whack"); |
| 561 | 561 |
| 562 return (ReductionType) (kQuad_ReductionType + count); | 562 return (ReductionType) (kQuad_ReductionType + count); |
| 563 } | 563 } |
| 564 | 564 |
| 565 SkPathStroker::ReductionType SkPathStroker::CheckConicLinear(const SkConic& coni
c, | 565 SkPathStroker::ReductionType SkPathStroker::CheckConicLinear(const SkConic& coni
c, |
| 566 SkPoint* reduction) { | 566 SkPoint* reduction) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 582 } | 582 } |
| 583 #else // but for now, use extrema instead | 583 #else // but for now, use extrema instead |
| 584 SkScalar xT = 0, yT = 0; | 584 SkScalar xT = 0, yT = 0; |
| 585 (void) conic.findXExtrema(&xT); | 585 (void) conic.findXExtrema(&xT); |
| 586 (void) conic.findYExtrema(&yT); | 586 (void) conic.findYExtrema(&yT); |
| 587 SkScalar t = SkTMax(xT, yT); | 587 SkScalar t = SkTMax(xT, yT); |
| 588 if (0 == t) { | 588 if (0 == t) { |
| 589 return kLine_ReductionType; | 589 return kLine_ReductionType; |
| 590 } | 590 } |
| 591 #endif | 591 #endif |
| 592 conic.evalAt(t, reduction, NULL); | 592 conic.evalAt(t, reduction, nullptr); |
| 593 return kDegenerate_ReductionType; | 593 return kDegenerate_ReductionType; |
| 594 } | 594 } |
| 595 | 595 |
| 596 SkPathStroker::ReductionType SkPathStroker::CheckQuadLinear(const SkPoint quad[3
], | 596 SkPathStroker::ReductionType SkPathStroker::CheckQuadLinear(const SkPoint quad[3
], |
| 597 SkPoint* reduction) { | 597 SkPoint* reduction) { |
| 598 bool degenerateAB = degenerate_vector(quad[1] - quad[0]); | 598 bool degenerateAB = degenerate_vector(quad[1] - quad[0]); |
| 599 bool degenerateBC = degenerate_vector(quad[2] - quad[1]); | 599 bool degenerateBC = degenerate_vector(quad[2] - quad[1]); |
| 600 if (degenerateAB & degenerateBC) { | 600 if (degenerateAB & degenerateBC) { |
| 601 return kPoint_ReductionType; | 601 return kPoint_ReductionType; |
| 602 } | 602 } |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 731 quadPts->fEndSet = true; | 731 quadPts->fEndSet = true; |
| 732 } | 732 } |
| 733 } | 733 } |
| 734 | 734 |
| 735 | 735 |
| 736 // Given a cubic and t, return the point on curve, its perpendicular, and the pe
rpendicular tangent. | 736 // Given a cubic and t, return the point on curve, its perpendicular, and the pe
rpendicular tangent. |
| 737 // Returns false if the perpendicular could not be computed (because the derivat
ive collapsed to 0) | 737 // Returns false if the perpendicular could not be computed (because the derivat
ive collapsed to 0) |
| 738 bool SkPathStroker::cubicPerpRay(const SkPoint cubic[4], SkScalar t, SkPoint* tP
t, SkPoint* onPt, | 738 bool SkPathStroker::cubicPerpRay(const SkPoint cubic[4], SkScalar t, SkPoint* tP
t, SkPoint* onPt, |
| 739 SkPoint* tangent) const { | 739 SkPoint* tangent) const { |
| 740 SkVector dxy; | 740 SkVector dxy; |
| 741 SkEvalCubicAt(cubic, t, tPt, &dxy, NULL); | 741 SkEvalCubicAt(cubic, t, tPt, &dxy, nullptr); |
| 742 if (dxy.fX == 0 && dxy.fY == 0) { | 742 if (dxy.fX == 0 && dxy.fY == 0) { |
| 743 if (SkScalarNearlyZero(t)) { | 743 if (SkScalarNearlyZero(t)) { |
| 744 dxy = cubic[2] - cubic[0]; | 744 dxy = cubic[2] - cubic[0]; |
| 745 } else if (SkScalarNearlyZero(1 - t)) { | 745 } else if (SkScalarNearlyZero(1 - t)) { |
| 746 dxy = cubic[3] - cubic[1]; | 746 dxy = cubic[3] - cubic[1]; |
| 747 } else { | 747 } else { |
| 748 return false; | 748 return false; |
| 749 } | 749 } |
| 750 if (dxy.fX == 0 && dxy.fY == 0) { | 750 if (dxy.fX == 0 && dxy.fY == 0) { |
| 751 dxy = cubic[3] - cubic[0]; | 751 dxy = cubic[3] - cubic[0]; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 772 return false; | 772 return false; |
| 773 } | 773 } |
| 774 quadPts->fEndSet = true; | 774 quadPts->fEndSet = true; |
| 775 } | 775 } |
| 776 return true; | 776 return true; |
| 777 } | 777 } |
| 778 | 778 |
| 779 bool SkPathStroker::cubicQuadMid(const SkPoint cubic[4], const SkQuadConstruct*
quadPts, | 779 bool SkPathStroker::cubicQuadMid(const SkPoint cubic[4], const SkQuadConstruct*
quadPts, |
| 780 SkPoint* mid) const { | 780 SkPoint* mid) const { |
| 781 SkPoint cubicMidPt; | 781 SkPoint cubicMidPt; |
| 782 return this->cubicPerpRay(cubic, quadPts->fMidT, &cubicMidPt, mid, NULL); | 782 return this->cubicPerpRay(cubic, quadPts->fMidT, &cubicMidPt, mid, nullptr); |
| 783 } | 783 } |
| 784 | 784 |
| 785 // Given a quad and t, return the point on curve, its perpendicular, and the per
pendicular tangent. | 785 // Given a quad and t, return the point on curve, its perpendicular, and the per
pendicular tangent. |
| 786 void SkPathStroker::quadPerpRay(const SkPoint quad[3], SkScalar t, SkPoint* tPt,
SkPoint* onPt, | 786 void SkPathStroker::quadPerpRay(const SkPoint quad[3], SkScalar t, SkPoint* tPt,
SkPoint* onPt, |
| 787 SkPoint* tangent) const { | 787 SkPoint* tangent) const { |
| 788 SkVector dxy; | 788 SkVector dxy; |
| 789 SkEvalQuadAt(quad, t, tPt, &dxy); | 789 SkEvalQuadAt(quad, t, tPt, &dxy); |
| 790 if (dxy.fX == 0 && dxy.fY == 0) { | 790 if (dxy.fX == 0 && dxy.fY == 0) { |
| 791 dxy = quad[2] - quad[0]; | 791 dxy = quad[2] - quad[0]; |
| 792 } | 792 } |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 969 if (!this->cubicQuadEnds(cubic, quadPts)) { | 969 if (!this->cubicQuadEnds(cubic, quadPts)) { |
| 970 return kNormalError_ResultType; | 970 return kNormalError_ResultType; |
| 971 } | 971 } |
| 972 ResultType resultType = this->intersectRay(quadPts, kCtrlPt_RayType | 972 ResultType resultType = this->intersectRay(quadPts, kCtrlPt_RayType |
| 973 STROKER_DEBUG_PARAMS(fRecursionDepth) ); | 973 STROKER_DEBUG_PARAMS(fRecursionDepth) ); |
| 974 if (resultType != kQuad_ResultType) { | 974 if (resultType != kQuad_ResultType) { |
| 975 return resultType; | 975 return resultType; |
| 976 } | 976 } |
| 977 // project a ray from the curve to the stroke | 977 // project a ray from the curve to the stroke |
| 978 SkPoint ray[2]; // points near midpoint on quad, midpoint on cubic | 978 SkPoint ray[2]; // points near midpoint on quad, midpoint on cubic |
| 979 if (!this->cubicPerpRay(cubic, quadPts->fMidT, &ray[1], &ray[0], NULL)) { | 979 if (!this->cubicPerpRay(cubic, quadPts->fMidT, &ray[1], &ray[0], nullptr)) { |
| 980 return kNormalError_ResultType; | 980 return kNormalError_ResultType; |
| 981 } | 981 } |
| 982 return this->strokeCloseEnough(quadPts->fQuad, ray, quadPts | 982 return this->strokeCloseEnough(quadPts->fQuad, ray, quadPts |
| 983 STROKER_DEBUG_PARAMS(fRecursionDepth)); | 983 STROKER_DEBUG_PARAMS(fRecursionDepth)); |
| 984 } | 984 } |
| 985 | 985 |
| 986 SkPathStroker::ResultType SkPathStroker::compareQuadConic(const SkConic& conic, | 986 SkPathStroker::ResultType SkPathStroker::compareQuadConic(const SkConic& conic, |
| 987 SkQuadConstruct* quadPts) const { | 987 SkQuadConstruct* quadPts) const { |
| 988 // get the quadratic approximation of the stroke | 988 // get the quadratic approximation of the stroke |
| 989 this->conicQuadEnds(conic, quadPts); | 989 this->conicQuadEnds(conic, quadPts); |
| 990 ResultType resultType = this->intersectRay(quadPts, kCtrlPt_RayType | 990 ResultType resultType = this->intersectRay(quadPts, kCtrlPt_RayType |
| 991 STROKER_DEBUG_PARAMS(fRecursionDepth) ); | 991 STROKER_DEBUG_PARAMS(fRecursionDepth) ); |
| 992 if (resultType != kQuad_ResultType) { | 992 if (resultType != kQuad_ResultType) { |
| 993 return resultType; | 993 return resultType; |
| 994 } | 994 } |
| 995 // project a ray from the curve to the stroke | 995 // project a ray from the curve to the stroke |
| 996 SkPoint ray[2]; // points near midpoint on quad, midpoint on conic | 996 SkPoint ray[2]; // points near midpoint on quad, midpoint on conic |
| 997 this->conicPerpRay(conic, quadPts->fMidT, &ray[1], &ray[0], NULL); | 997 this->conicPerpRay(conic, quadPts->fMidT, &ray[1], &ray[0], nullptr); |
| 998 return this->strokeCloseEnough(quadPts->fQuad, ray, quadPts | 998 return this->strokeCloseEnough(quadPts->fQuad, ray, quadPts |
| 999 STROKER_DEBUG_PARAMS(fRecursionDepth)); | 999 STROKER_DEBUG_PARAMS(fRecursionDepth)); |
| 1000 } | 1000 } |
| 1001 | 1001 |
| 1002 SkPathStroker::ResultType SkPathStroker::compareQuadQuad(const SkPoint quad[3], | 1002 SkPathStroker::ResultType SkPathStroker::compareQuadQuad(const SkPoint quad[3], |
| 1003 SkQuadConstruct* quadPts) { | 1003 SkQuadConstruct* quadPts) { |
| 1004 // get the quadratic approximation of the stroke | 1004 // get the quadratic approximation of the stroke |
| 1005 if (!quadPts->fStartSet) { | 1005 if (!quadPts->fStartSet) { |
| 1006 SkPoint quadStartPt; | 1006 SkPoint quadStartPt; |
| 1007 this->quadPerpRay(quad, quadPts->fStartT, &quadStartPt, &quadPts->fQuad[
0], | 1007 this->quadPerpRay(quad, quadPts->fStartT, &quadStartPt, &quadPts->fQuad[
0], |
| 1008 &quadPts->fTangentStart); | 1008 &quadPts->fTangentStart); |
| 1009 quadPts->fStartSet = true; | 1009 quadPts->fStartSet = true; |
| 1010 } | 1010 } |
| 1011 if (!quadPts->fEndSet) { | 1011 if (!quadPts->fEndSet) { |
| 1012 SkPoint quadEndPt; | 1012 SkPoint quadEndPt; |
| 1013 this->quadPerpRay(quad, quadPts->fEndT, &quadEndPt, &quadPts->fQuad[2], | 1013 this->quadPerpRay(quad, quadPts->fEndT, &quadEndPt, &quadPts->fQuad[2], |
| 1014 &quadPts->fTangentEnd); | 1014 &quadPts->fTangentEnd); |
| 1015 quadPts->fEndSet = true; | 1015 quadPts->fEndSet = true; |
| 1016 } | 1016 } |
| 1017 ResultType resultType = this->intersectRay(quadPts, kCtrlPt_RayType | 1017 ResultType resultType = this->intersectRay(quadPts, kCtrlPt_RayType |
| 1018 STROKER_DEBUG_PARAMS(fRecursionDepth)); | 1018 STROKER_DEBUG_PARAMS(fRecursionDepth)); |
| 1019 if (resultType != kQuad_ResultType) { | 1019 if (resultType != kQuad_ResultType) { |
| 1020 return resultType; | 1020 return resultType; |
| 1021 } | 1021 } |
| 1022 // project a ray from the curve to the stroke | 1022 // project a ray from the curve to the stroke |
| 1023 SkPoint ray[2]; | 1023 SkPoint ray[2]; |
| 1024 this->quadPerpRay(quad, quadPts->fMidT, &ray[1], &ray[0], NULL); | 1024 this->quadPerpRay(quad, quadPts->fMidT, &ray[1], &ray[0], nullptr); |
| 1025 return this->strokeCloseEnough(quadPts->fQuad, ray, quadPts | 1025 return this->strokeCloseEnough(quadPts->fQuad, ray, quadPts |
| 1026 STROKER_DEBUG_PARAMS(fRecursionDepth)); | 1026 STROKER_DEBUG_PARAMS(fRecursionDepth)); |
| 1027 } | 1027 } |
| 1028 | 1028 |
| 1029 void SkPathStroker::addDegenerateLine(const SkQuadConstruct* quadPts) { | 1029 void SkPathStroker::addDegenerateLine(const SkQuadConstruct* quadPts) { |
| 1030 const SkPoint* quad = quadPts->fQuad; | 1030 const SkPoint* quad = quadPts->fQuad; |
| 1031 SkPath* path = fStrokeType == kOuter_StrokeType ? &fOuter : &fInner; | 1031 SkPath* path = fStrokeType == kOuter_StrokeType ? &fOuter : &fInner; |
| 1032 path->lineTo(quad[2].fX, quad[2].fY); | 1032 path->lineTo(quad[2].fX, quad[2].fY); |
| 1033 } | 1033 } |
| 1034 | 1034 |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1422 pts[3].set(r.fRight, outer.fBottom); | 1422 pts[3].set(r.fRight, outer.fBottom); |
| 1423 pts[2].set(r.fLeft, outer.fBottom); | 1423 pts[2].set(r.fLeft, outer.fBottom); |
| 1424 pts[1].set(outer.fLeft, r.fBottom); | 1424 pts[1].set(outer.fLeft, r.fBottom); |
| 1425 pts[0].set(outer.fLeft, r.fTop); | 1425 pts[0].set(outer.fLeft, r.fTop); |
| 1426 } | 1426 } |
| 1427 path->addPoly(pts, 8, true); | 1427 path->addPoly(pts, 8, true); |
| 1428 } | 1428 } |
| 1429 | 1429 |
| 1430 void SkStroke::strokeRect(const SkRect& origRect, SkPath* dst, | 1430 void SkStroke::strokeRect(const SkRect& origRect, SkPath* dst, |
| 1431 SkPath::Direction dir) const { | 1431 SkPath::Direction dir) const { |
| 1432 SkASSERT(dst != NULL); | 1432 SkASSERT(dst != nullptr); |
| 1433 dst->reset(); | 1433 dst->reset(); |
| 1434 | 1434 |
| 1435 SkScalar radius = SkScalarHalf(fWidth); | 1435 SkScalar radius = SkScalarHalf(fWidth); |
| 1436 if (radius <= 0) { | 1436 if (radius <= 0) { |
| 1437 return; | 1437 return; |
| 1438 } | 1438 } |
| 1439 | 1439 |
| 1440 SkScalar rw = origRect.width(); | 1440 SkScalar rw = origRect.width(); |
| 1441 SkScalar rh = origRect.height(); | 1441 SkScalar rh = origRect.height(); |
| 1442 if ((rw < 0) ^ (rh < 0)) { | 1442 if ((rw < 0) ^ (rh < 0)) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1469 default: | 1469 default: |
| 1470 break; | 1470 break; |
| 1471 } | 1471 } |
| 1472 | 1472 |
| 1473 if (fWidth < SkMinScalar(rw, rh) && !fDoFill) { | 1473 if (fWidth < SkMinScalar(rw, rh) && !fDoFill) { |
| 1474 r = rect; | 1474 r = rect; |
| 1475 r.inset(radius, radius); | 1475 r.inset(radius, radius); |
| 1476 dst->addRect(r, reverse_direction(dir)); | 1476 dst->addRect(r, reverse_direction(dir)); |
| 1477 } | 1477 } |
| 1478 } | 1478 } |
| OLD | NEW |