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 |