| 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 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 | 166 |
| 167 enum StrokeType { | 167 enum StrokeType { |
| 168 kOuter_StrokeType = 1, // use sign-opposite values later to flip pe
rpendicular axis | 168 kOuter_StrokeType = 1, // use sign-opposite values later to flip pe
rpendicular axis |
| 169 kInner_StrokeType = -1 | 169 kInner_StrokeType = -1 |
| 170 } fStrokeType; | 170 } fStrokeType; |
| 171 | 171 |
| 172 enum ResultType { | 172 enum ResultType { |
| 173 kSplit_ResultType, // the caller should split the quad stroke i
n two | 173 kSplit_ResultType, // the caller should split the quad stroke i
n two |
| 174 kDegenerate_ResultType, // the caller should add a line | 174 kDegenerate_ResultType, // the caller should add a line |
| 175 kQuad_ResultType, // the caller should (continue to try to) ad
d a quad stroke | 175 kQuad_ResultType, // the caller should (continue to try to) ad
d a quad stroke |
| 176 kNormalError_ResultType, // the cubic's normal couldn't be computed -
- abort | |
| 177 }; | 176 }; |
| 178 | 177 |
| 179 enum ReductionType { | 178 enum ReductionType { |
| 180 kPoint_ReductionType, // all curve points are practically identica
l | 179 kPoint_ReductionType, // all curve points are practically identica
l |
| 181 kLine_ReductionType, // the control point is on the line between
the ends | 180 kLine_ReductionType, // the control point is on the line between
the ends |
| 182 kQuad_ReductionType, // the control point is outside the line bet
ween the ends | 181 kQuad_ReductionType, // the control point is outside the line bet
ween the ends |
| 183 kDegenerate_ReductionType, // the control point is on the line but outs
ide the ends | 182 kDegenerate_ReductionType, // the control point is on the line but outs
ide the ends |
| 184 kDegenerate2_ReductionType, // two control points are on the line but ou
tside ends (cubic) | 183 kDegenerate2_ReductionType, // two control points are on the line but ou
tside ends (cubic) |
| 185 kDegenerate3_ReductionType, // three areas of max curvature found (for c
ubic) | 184 kDegenerate3_ReductionType, // three areas of max curvature found (for c
ubic) |
| 186 }; | 185 }; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 200 const SkPoint** tanPtPtr); | 199 const SkPoint** tanPtPtr); |
| 201 static ReductionType CheckQuadLinear(const SkPoint quad[3], SkPoint* reducti
on); | 200 static ReductionType CheckQuadLinear(const SkPoint quad[3], SkPoint* reducti
on); |
| 202 ResultType compareQuadConic(const SkConic& , SkQuadConstruct* ) const; | 201 ResultType compareQuadConic(const SkConic& , SkQuadConstruct* ) const; |
| 203 ResultType compareQuadCubic(const SkPoint cubic[4], SkQuadConstruct* ); | 202 ResultType compareQuadCubic(const SkPoint cubic[4], SkQuadConstruct* ); |
| 204 ResultType compareQuadQuad(const SkPoint quad[3], SkQuadConstruct* ); | 203 ResultType compareQuadQuad(const SkPoint quad[3], SkQuadConstruct* ); |
| 205 void conicPerpRay(const SkConic& , SkScalar t, SkPoint* tPt, SkPoint* onPt, | 204 void conicPerpRay(const SkConic& , SkScalar t, SkPoint* tPt, SkPoint* onPt, |
| 206 SkPoint* tangent) const; | 205 SkPoint* tangent) const; |
| 207 void conicQuadEnds(const SkConic& , SkQuadConstruct* ) const; | 206 void conicQuadEnds(const SkConic& , SkQuadConstruct* ) const; |
| 208 bool conicStroke(const SkConic& , SkQuadConstruct* ); | 207 bool conicStroke(const SkConic& , SkQuadConstruct* ); |
| 209 bool cubicMidOnLine(const SkPoint cubic[4], const SkQuadConstruct* ) const; | 208 bool cubicMidOnLine(const SkPoint cubic[4], const SkQuadConstruct* ) const; |
| 210 bool cubicPerpRay(const SkPoint cubic[4], SkScalar t, SkPoint* tPt, SkPoint*
onPt, | 209 void cubicPerpRay(const SkPoint cubic[4], SkScalar t, SkPoint* tPt, SkPoint*
onPt, |
| 211 SkPoint* tangent) const; | 210 SkPoint* tangent) const; |
| 212 bool cubicQuadEnds(const SkPoint cubic[4], SkQuadConstruct* ); | 211 void cubicQuadEnds(const SkPoint cubic[4], SkQuadConstruct* ); |
| 213 bool cubicQuadMid(const SkPoint cubic[4], const SkQuadConstruct* , SkPoint*
mid) const; | 212 void cubicQuadMid(const SkPoint cubic[4], const SkQuadConstruct* , SkPoint*
mid) const; |
| 214 bool cubicStroke(const SkPoint cubic[4], SkQuadConstruct* ); | 213 bool cubicStroke(const SkPoint cubic[4], SkQuadConstruct* ); |
| 215 void init(StrokeType strokeType, SkQuadConstruct* , SkScalar tStart, SkScala
r tEnd); | 214 void init(StrokeType strokeType, SkQuadConstruct* , SkScalar tStart, SkScala
r tEnd); |
| 216 ResultType intersectRay(SkQuadConstruct* , IntersectRayType STROKER_DEBUG_P
ARAMS(int) ) const; | 215 ResultType intersectRay(SkQuadConstruct* , IntersectRayType STROKER_DEBUG_P
ARAMS(int) ) const; |
| 217 bool ptInQuadBounds(const SkPoint quad[3], const SkPoint& pt) const; | 216 bool ptInQuadBounds(const SkPoint quad[3], const SkPoint& pt) const; |
| 218 void quadPerpRay(const SkPoint quad[3], SkScalar t, SkPoint* tPt, SkPoint* o
nPt, | 217 void quadPerpRay(const SkPoint quad[3], SkScalar t, SkPoint* tPt, SkPoint* o
nPt, |
| 219 SkPoint* tangent) const; | 218 SkPoint* tangent) const; |
| 220 bool quadStroke(const SkPoint quad[3], SkQuadConstruct* ); | 219 bool quadStroke(const SkPoint quad[3], SkQuadConstruct* ); |
| 221 void setConicEndNormal(const SkConic& , | 220 void setConicEndNormal(const SkConic& , |
| 222 const SkVector& normalAB, const SkVector& unitNormalA
B, | 221 const SkVector& normalAB, const SkVector& unitNormalA
B, |
| 223 SkVector* normalBC, SkVector* unitNormalBC); | 222 SkVector* normalBC, SkVector* unitNormalBC); |
| (...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 779 if (!quadPts->fEndSet) { | 778 if (!quadPts->fEndSet) { |
| 780 SkPoint conicEndPt; | 779 SkPoint conicEndPt; |
| 781 this->conicPerpRay(conic, quadPts->fEndT, &conicEndPt, &quadPts->fQuad[2
], | 780 this->conicPerpRay(conic, quadPts->fEndT, &conicEndPt, &quadPts->fQuad[2
], |
| 782 &quadPts->fTangentEnd); | 781 &quadPts->fTangentEnd); |
| 783 quadPts->fEndSet = true; | 782 quadPts->fEndSet = true; |
| 784 } | 783 } |
| 785 } | 784 } |
| 786 | 785 |
| 787 | 786 |
| 788 // Given a cubic and t, return the point on curve, its perpendicular, and the pe
rpendicular tangent. | 787 // Given a cubic and t, return the point on curve, its perpendicular, and the pe
rpendicular tangent. |
| 789 // Returns false if the perpendicular could not be computed (because the derivat
ive collapsed to 0) | 788 void SkPathStroker::cubicPerpRay(const SkPoint cubic[4], SkScalar t, SkPoint* tP
t, SkPoint* onPt, |
| 790 bool SkPathStroker::cubicPerpRay(const SkPoint cubic[4], SkScalar t, SkPoint* tP
t, SkPoint* onPt, | |
| 791 SkPoint* tangent) const { | 789 SkPoint* tangent) const { |
| 792 SkVector dxy; | 790 SkVector dxy; |
| 791 SkPoint chopped[7]; |
| 793 SkEvalCubicAt(cubic, t, tPt, &dxy, nullptr); | 792 SkEvalCubicAt(cubic, t, tPt, &dxy, nullptr); |
| 794 if (dxy.fX == 0 && dxy.fY == 0) { | 793 if (dxy.fX == 0 && dxy.fY == 0) { |
| 794 const SkPoint* cPts = cubic; |
| 795 if (SkScalarNearlyZero(t)) { | 795 if (SkScalarNearlyZero(t)) { |
| 796 dxy = cubic[2] - cubic[0]; | 796 dxy = cubic[2] - cubic[0]; |
| 797 } else if (SkScalarNearlyZero(1 - t)) { | 797 } else if (SkScalarNearlyZero(1 - t)) { |
| 798 dxy = cubic[3] - cubic[1]; | 798 dxy = cubic[3] - cubic[1]; |
| 799 } else { | 799 } else { |
| 800 return false; | 800 // If the cubic inflection falls on the cusp, subdivide the cubic |
| 801 // to find the tangent at that point. |
| 802 SkChopCubicAt(cubic, chopped, t); |
| 803 dxy = chopped[3] - chopped[2]; |
| 804 if (dxy.fX == 0 && dxy.fY == 0) { |
| 805 dxy = chopped[3] - chopped[1]; |
| 806 cPts = chopped; |
| 807 } |
| 801 } | 808 } |
| 802 if (dxy.fX == 0 && dxy.fY == 0) { | 809 if (dxy.fX == 0 && dxy.fY == 0) { |
| 803 dxy = cubic[3] - cubic[0]; | 810 dxy = cPts[3] - cPts[0]; |
| 804 } | 811 } |
| 805 } | 812 } |
| 806 setRayPts(*tPt, &dxy, onPt, tangent); | 813 setRayPts(*tPt, &dxy, onPt, tangent); |
| 807 return true; | |
| 808 } | 814 } |
| 809 | 815 |
| 810 // Given a cubic and a t range, find the start and end if they haven't been foun
d already. | 816 // Given a cubic and a t range, find the start and end if they haven't been foun
d already. |
| 811 bool SkPathStroker::cubicQuadEnds(const SkPoint cubic[4], SkQuadConstruct* quadP
ts) { | 817 void SkPathStroker::cubicQuadEnds(const SkPoint cubic[4], SkQuadConstruct* quadP
ts) { |
| 812 if (!quadPts->fStartSet) { | 818 if (!quadPts->fStartSet) { |
| 813 SkPoint cubicStartPt; | 819 SkPoint cubicStartPt; |
| 814 if (!this->cubicPerpRay(cubic, quadPts->fStartT, &cubicStartPt, &quadPts
->fQuad[0], | 820 this->cubicPerpRay(cubic, quadPts->fStartT, &cubicStartPt, &quadPts->fQu
ad[0], |
| 815 &quadPts->fTangentStart)) { | 821 &quadPts->fTangentStart); |
| 816 return false; | |
| 817 } | |
| 818 quadPts->fStartSet = true; | 822 quadPts->fStartSet = true; |
| 819 } | 823 } |
| 820 if (!quadPts->fEndSet) { | 824 if (!quadPts->fEndSet) { |
| 821 SkPoint cubicEndPt; | 825 SkPoint cubicEndPt; |
| 822 if (!this->cubicPerpRay(cubic, quadPts->fEndT, &cubicEndPt, &quadPts->fQ
uad[2], | 826 this->cubicPerpRay(cubic, quadPts->fEndT, &cubicEndPt, &quadPts->fQuad[2
], |
| 823 &quadPts->fTangentEnd)) { | 827 &quadPts->fTangentEnd); |
| 824 return false; | |
| 825 } | |
| 826 quadPts->fEndSet = true; | 828 quadPts->fEndSet = true; |
| 827 } | 829 } |
| 828 return true; | |
| 829 } | 830 } |
| 830 | 831 |
| 831 bool SkPathStroker::cubicQuadMid(const SkPoint cubic[4], const SkQuadConstruct*
quadPts, | 832 void SkPathStroker::cubicQuadMid(const SkPoint cubic[4], const SkQuadConstruct*
quadPts, |
| 832 SkPoint* mid) const { | 833 SkPoint* mid) const { |
| 833 SkPoint cubicMidPt; | 834 SkPoint cubicMidPt; |
| 834 return this->cubicPerpRay(cubic, quadPts->fMidT, &cubicMidPt, mid, nullptr); | 835 this->cubicPerpRay(cubic, quadPts->fMidT, &cubicMidPt, mid, nullptr); |
| 835 } | 836 } |
| 836 | 837 |
| 837 // Given a quad and t, return the point on curve, its perpendicular, and the per
pendicular tangent. | 838 // Given a quad and t, return the point on curve, its perpendicular, and the per
pendicular tangent. |
| 838 void SkPathStroker::quadPerpRay(const SkPoint quad[3], SkScalar t, SkPoint* tPt,
SkPoint* onPt, | 839 void SkPathStroker::quadPerpRay(const SkPoint quad[3], SkScalar t, SkPoint* tPt,
SkPoint* onPt, |
| 839 SkPoint* tangent) const { | 840 SkPoint* tangent) const { |
| 840 SkVector dxy; | 841 SkVector dxy; |
| 841 SkEvalQuadAt(quad, t, tPt, &dxy); | 842 SkEvalQuadAt(quad, t, tPt, &dxy); |
| 842 if (dxy.fX == 0 && dxy.fY == 0) { | 843 if (dxy.fX == 0 && dxy.fY == 0) { |
| 843 dxy = quad[2] - quad[0]; | 844 dxy = quad[2] - quad[0]; |
| 844 } | 845 } |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 898 } | 899 } |
| 899 quadPts->fOppositeTangents = aLen.dot(bLen) < 0; | 900 quadPts->fOppositeTangents = aLen.dot(bLen) < 0; |
| 900 // if the lines are parallel, straight line is good enough | 901 // if the lines are parallel, straight line is good enough |
| 901 return STROKER_RESULT(kDegenerate_ResultType, depth, quadPts, | 902 return STROKER_RESULT(kDegenerate_ResultType, depth, quadPts, |
| 902 "SkScalarNearlyZero(denom=%g)", denom); | 903 "SkScalarNearlyZero(denom=%g)", denom); |
| 903 } | 904 } |
| 904 | 905 |
| 905 // Given a cubic and a t-range, determine if the stroke can be described by a qu
adratic. | 906 // Given a cubic and a t-range, determine if the stroke can be described by a qu
adratic. |
| 906 SkPathStroker::ResultType SkPathStroker::tangentsMeet(const SkPoint cubic[4], | 907 SkPathStroker::ResultType SkPathStroker::tangentsMeet(const SkPoint cubic[4], |
| 907 SkQuadConstruct* quadPts) { | 908 SkQuadConstruct* quadPts) { |
| 908 if (!this->cubicQuadEnds(cubic, quadPts)) { | 909 this->cubicQuadEnds(cubic, quadPts); |
| 909 return kNormalError_ResultType; | |
| 910 } | |
| 911 return this->intersectRay(quadPts, kResultType_RayType STROKER_DEBUG_PARAMS
(fRecursionDepth)); | 910 return this->intersectRay(quadPts, kResultType_RayType STROKER_DEBUG_PARAMS
(fRecursionDepth)); |
| 912 } | 911 } |
| 913 | 912 |
| 914 // Intersect the line with the quad and return the t values on the quad where th
e line crosses. | 913 // Intersect the line with the quad and return the t values on the quad where th
e line crosses. |
| 915 static int intersect_quad_ray(const SkPoint line[2], const SkPoint quad[3], SkSc
alar roots[2]) { | 914 static int intersect_quad_ray(const SkPoint line[2], const SkPoint quad[3], SkSc
alar roots[2]) { |
| 916 SkVector vec = line[1] - line[0]; | 915 SkVector vec = line[1] - line[0]; |
| 917 SkScalar r[3]; | 916 SkScalar r[3]; |
| 918 for (int n = 0; n < 3; ++n) { | 917 for (int n = 0; n < 3; ++n) { |
| 919 r[n] = (quad[n].fY - line[0].fY) * vec.fX - (quad[n].fX - line[0].fX) *
vec.fY; | 918 r[n] = (quad[n].fY - line[0].fY) * vec.fX - (quad[n].fX - line[0].fX) *
vec.fY; |
| 920 } | 919 } |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1012 "points_within_dist(ray[0]=%g,%g, quadPt=%g,%g, error=%g)", | 1011 "points_within_dist(ray[0]=%g,%g, quadPt=%g,%g, error=%g)", |
| 1013 ray[0].fX, ray[0].fY, quadPt.fX, quadPt.fY, error); | 1012 ray[0].fX, ray[0].fY, quadPt.fX, quadPt.fY, error); |
| 1014 } | 1013 } |
| 1015 // otherwise, subdivide | 1014 // otherwise, subdivide |
| 1016 return STROKER_RESULT(kSplit_ResultType, depth, quadPts, "%s", "fall through
"); | 1015 return STROKER_RESULT(kSplit_ResultType, depth, quadPts, "%s", "fall through
"); |
| 1017 } | 1016 } |
| 1018 | 1017 |
| 1019 SkPathStroker::ResultType SkPathStroker::compareQuadCubic(const SkPoint cubic[4]
, | 1018 SkPathStroker::ResultType SkPathStroker::compareQuadCubic(const SkPoint cubic[4]
, |
| 1020 SkQuadConstruct* quadPts) { | 1019 SkQuadConstruct* quadPts) { |
| 1021 // get the quadratic approximation of the stroke | 1020 // get the quadratic approximation of the stroke |
| 1022 if (!this->cubicQuadEnds(cubic, quadPts)) { | 1021 this->cubicQuadEnds(cubic, quadPts); |
| 1023 return kNormalError_ResultType; | |
| 1024 } | |
| 1025 ResultType resultType = this->intersectRay(quadPts, kCtrlPt_RayType | 1022 ResultType resultType = this->intersectRay(quadPts, kCtrlPt_RayType |
| 1026 STROKER_DEBUG_PARAMS(fRecursionDepth) ); | 1023 STROKER_DEBUG_PARAMS(fRecursionDepth) ); |
| 1027 if (resultType != kQuad_ResultType) { | 1024 if (resultType != kQuad_ResultType) { |
| 1028 return resultType; | 1025 return resultType; |
| 1029 } | 1026 } |
| 1030 // project a ray from the curve to the stroke | 1027 // project a ray from the curve to the stroke |
| 1031 SkPoint ray[2]; // points near midpoint on quad, midpoint on cubic | 1028 SkPoint ray[2]; // points near midpoint on quad, midpoint on cubic |
| 1032 if (!this->cubicPerpRay(cubic, quadPts->fMidT, &ray[1], &ray[0], nullptr)) { | 1029 this->cubicPerpRay(cubic, quadPts->fMidT, &ray[1], &ray[0], nullptr); |
| 1033 return kNormalError_ResultType; | |
| 1034 } | |
| 1035 return this->strokeCloseEnough(quadPts->fQuad, ray, quadPts | 1030 return this->strokeCloseEnough(quadPts->fQuad, ray, quadPts |
| 1036 STROKER_DEBUG_PARAMS(fRecursionDepth)); | 1031 STROKER_DEBUG_PARAMS(fRecursionDepth)); |
| 1037 } | 1032 } |
| 1038 | 1033 |
| 1039 SkPathStroker::ResultType SkPathStroker::compareQuadConic(const SkConic& conic, | 1034 SkPathStroker::ResultType SkPathStroker::compareQuadConic(const SkConic& conic, |
| 1040 SkQuadConstruct* quadPts) const { | 1035 SkQuadConstruct* quadPts) const { |
| 1041 // get the quadratic approximation of the stroke | 1036 // get the quadratic approximation of the stroke |
| 1042 this->conicQuadEnds(conic, quadPts); | 1037 this->conicQuadEnds(conic, quadPts); |
| 1043 ResultType resultType = this->intersectRay(quadPts, kCtrlPt_RayType | 1038 ResultType resultType = this->intersectRay(quadPts, kCtrlPt_RayType |
| 1044 STROKER_DEBUG_PARAMS(fRecursionDepth) ); | 1039 STROKER_DEBUG_PARAMS(fRecursionDepth) ); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1080 } | 1075 } |
| 1081 | 1076 |
| 1082 void SkPathStroker::addDegenerateLine(const SkQuadConstruct* quadPts) { | 1077 void SkPathStroker::addDegenerateLine(const SkQuadConstruct* quadPts) { |
| 1083 const SkPoint* quad = quadPts->fQuad; | 1078 const SkPoint* quad = quadPts->fQuad; |
| 1084 SkPath* path = fStrokeType == kOuter_StrokeType ? &fOuter : &fInner; | 1079 SkPath* path = fStrokeType == kOuter_StrokeType ? &fOuter : &fInner; |
| 1085 path->lineTo(quad[2].fX, quad[2].fY); | 1080 path->lineTo(quad[2].fX, quad[2].fY); |
| 1086 } | 1081 } |
| 1087 | 1082 |
| 1088 bool SkPathStroker::cubicMidOnLine(const SkPoint cubic[4], const SkQuadConstruct
* quadPts) const { | 1083 bool SkPathStroker::cubicMidOnLine(const SkPoint cubic[4], const SkQuadConstruct
* quadPts) const { |
| 1089 SkPoint strokeMid; | 1084 SkPoint strokeMid; |
| 1090 if (!cubicQuadMid(cubic, quadPts, &strokeMid)) { | 1085 this->cubicQuadMid(cubic, quadPts, &strokeMid); |
| 1091 return false; | |
| 1092 } | |
| 1093 SkScalar dist = pt_to_line(strokeMid, quadPts->fQuad[0], quadPts->fQuad[2]); | 1086 SkScalar dist = pt_to_line(strokeMid, quadPts->fQuad[0], quadPts->fQuad[2]); |
| 1094 return dist < fInvResScaleSquared; | 1087 return dist < fInvResScaleSquared; |
| 1095 } | 1088 } |
| 1096 | 1089 |
| 1097 bool SkPathStroker::cubicStroke(const SkPoint cubic[4], SkQuadConstruct* quadPts
) { | 1090 bool SkPathStroker::cubicStroke(const SkPoint cubic[4], SkQuadConstruct* quadPts
) { |
| 1098 if (!fFoundTangents) { | 1091 if (!fFoundTangents) { |
| 1099 ResultType resultType = this->tangentsMeet(cubic, quadPts); | 1092 ResultType resultType = this->tangentsMeet(cubic, quadPts); |
| 1100 if (kQuad_ResultType != resultType) { | 1093 if (kQuad_ResultType != resultType) { |
| 1101 if (kNormalError_ResultType == resultType) { | |
| 1102 return false; | |
| 1103 } | |
| 1104 if ((kDegenerate_ResultType == resultType | 1094 if ((kDegenerate_ResultType == resultType |
| 1105 || points_within_dist(quadPts->fQuad[0], quadPts->fQuad[2], | 1095 || points_within_dist(quadPts->fQuad[0], quadPts->fQuad[2], |
| 1106 fInvResScale)) && cubicMidOnLine(cubic, quadPts)) { | 1096 fInvResScale)) && cubicMidOnLine(cubic, quadPts)) { |
| 1107 addDegenerateLine(quadPts); | 1097 addDegenerateLine(quadPts); |
| 1108 return true; | 1098 return true; |
| 1109 } | 1099 } |
| 1110 } else { | 1100 } else { |
| 1111 fFoundTangents = true; | 1101 fFoundTangents = true; |
| 1112 } | 1102 } |
| 1113 } | 1103 } |
| 1114 if (fFoundTangents) { | 1104 if (fFoundTangents) { |
| 1115 ResultType resultType = this->compareQuadCubic(cubic, quadPts); | 1105 ResultType resultType = this->compareQuadCubic(cubic, quadPts); |
| 1116 if (kQuad_ResultType == resultType) { | 1106 if (kQuad_ResultType == resultType) { |
| 1117 SkPath* path = fStrokeType == kOuter_StrokeType ? &fOuter : &fInner; | 1107 SkPath* path = fStrokeType == kOuter_StrokeType ? &fOuter : &fInner; |
| 1118 const SkPoint* stroke = quadPts->fQuad; | 1108 const SkPoint* stroke = quadPts->fQuad; |
| 1119 path->quadTo(stroke[1].fX, stroke[1].fY, stroke[2].fX, stroke[2].fY)
; | 1109 path->quadTo(stroke[1].fX, stroke[1].fY, stroke[2].fX, stroke[2].fY)
; |
| 1120 return true; | 1110 return true; |
| 1121 } | 1111 } |
| 1122 if (kDegenerate_ResultType == resultType) { | 1112 if (kDegenerate_ResultType == resultType) { |
| 1123 if (!quadPts->fOppositeTangents) { | 1113 if (!quadPts->fOppositeTangents) { |
| 1124 addDegenerateLine(quadPts); | 1114 addDegenerateLine(quadPts); |
| 1125 return true; | 1115 return true; |
| 1126 } | 1116 } |
| 1127 } | 1117 } |
| 1128 if (kNormalError_ResultType == resultType) { | |
| 1129 return false; | |
| 1130 } | |
| 1131 } | 1118 } |
| 1132 if (!SkScalarIsFinite(quadPts->fQuad[2].fX) || !SkScalarIsFinite(quadPts->fQ
uad[2].fY)) { | 1119 if (!SkScalarIsFinite(quadPts->fQuad[2].fX) || !SkScalarIsFinite(quadPts->fQ
uad[2].fY)) { |
| 1133 return false; // just abort if projected quad isn't representable | 1120 return false; // just abort if projected quad isn't representable |
| 1134 } | 1121 } |
| 1135 SkDEBUGCODE(gMaxRecursion[fFoundTangents] = SkTMax(gMaxRecursion[fFoundTange
nts], | 1122 SkDEBUGCODE(gMaxRecursion[fFoundTangents] = SkTMax(gMaxRecursion[fFoundTange
nts], |
| 1136 fRecursionDepth + 1)); | 1123 fRecursionDepth + 1)); |
| 1137 if (++fRecursionDepth > kRecursiveLimits[fFoundTangents]) { | 1124 if (++fRecursionDepth > kRecursiveLimits[fFoundTangents]) { |
| 1138 return false; // just abort if projected quad isn't representable | 1125 return false; // just abort if projected quad isn't representable |
| 1139 } | 1126 } |
| 1140 SkQuadConstruct half; | 1127 SkQuadConstruct half; |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1537 default: | 1524 default: |
| 1538 break; | 1525 break; |
| 1539 } | 1526 } |
| 1540 | 1527 |
| 1541 if (fWidth < SkMinScalar(rw, rh) && !fDoFill) { | 1528 if (fWidth < SkMinScalar(rw, rh) && !fDoFill) { |
| 1542 r = rect; | 1529 r = rect; |
| 1543 r.inset(radius, radius); | 1530 r.inset(radius, radius); |
| 1544 dst->addRect(r, reverse_direction(dir)); | 1531 dst->addRect(r, reverse_direction(dir)); |
| 1545 } | 1532 } |
| 1546 } | 1533 } |
| OLD | NEW |