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 "SkGeometry.h" | 7 #include "SkGeometry.h" |
8 #include "SkOpEdgeBuilder.h" | 8 #include "SkOpEdgeBuilder.h" |
9 #include "SkReduceOrder.h" | 9 #include "SkReduceOrder.h" |
10 | 10 |
(...skipping 29 matching lines...) Expand all Loading... |
40 void SkOpEdgeBuilder::closeContour(const SkPoint& curveEnd, const SkPoint& curve
Start) { | 40 void SkOpEdgeBuilder::closeContour(const SkPoint& curveEnd, const SkPoint& curve
Start) { |
41 if (!SkDPoint::ApproximatelyEqual(curveEnd, curveStart)) { | 41 if (!SkDPoint::ApproximatelyEqual(curveEnd, curveStart)) { |
42 fPathVerbs.push_back(SkPath::kLine_Verb); | 42 fPathVerbs.push_back(SkPath::kLine_Verb); |
43 fPathPts.push_back_n(1, &curveStart); | 43 fPathPts.push_back_n(1, &curveStart); |
44 } else { | 44 } else { |
45 fPathPts[fPathPts.count() - 1] = curveStart; | 45 fPathPts[fPathPts.count() - 1] = curveStart; |
46 } | 46 } |
47 fPathVerbs.push_back(SkPath::kClose_Verb); | 47 fPathVerbs.push_back(SkPath::kClose_Verb); |
48 } | 48 } |
49 | 49 |
| 50 // very tiny points cause numerical instability : don't allow them |
| 51 static void force_small_to_zero(SkPoint* pt) { |
| 52 if (SkScalarAbs(pt->fX) < FLT_EPSILON_ORDERABLE_ERR) { |
| 53 pt->fX = 0; |
| 54 } |
| 55 if (SkScalarAbs(pt->fY) < FLT_EPSILON_ORDERABLE_ERR) { |
| 56 pt->fY = 0; |
| 57 } |
| 58 } |
| 59 |
| 60 |
50 int SkOpEdgeBuilder::preFetch() { | 61 int SkOpEdgeBuilder::preFetch() { |
51 if (!fPath->isFinite()) { | 62 if (!fPath->isFinite()) { |
52 fUnparseable = true; | 63 fUnparseable = true; |
53 return 0; | 64 return 0; |
54 } | 65 } |
55 SkAutoConicToQuads quadder; | 66 SkAutoConicToQuads quadder; |
56 const SkScalar quadderTol = SK_Scalar1 / 16; | 67 const SkScalar quadderTol = SK_Scalar1 / 16; |
57 SkPath::RawIter iter(*fPath); | 68 SkPath::RawIter iter(*fPath); |
58 SkPoint curveStart; | 69 SkPoint curveStart; |
59 SkPoint curve[4]; | 70 SkPoint curve[4]; |
60 SkPoint pts[4]; | 71 SkPoint pts[4]; |
61 SkPath::Verb verb; | 72 SkPath::Verb verb; |
62 bool lastCurve = false; | 73 bool lastCurve = false; |
63 do { | 74 do { |
64 verb = iter.next(pts); | 75 verb = iter.next(pts); |
65 switch (verb) { | 76 switch (verb) { |
66 case SkPath::kMove_Verb: | 77 case SkPath::kMove_Verb: |
67 if (!fAllowOpenContours && lastCurve) { | 78 if (!fAllowOpenContours && lastCurve) { |
68 closeContour(curve[0], curveStart); | 79 closeContour(curve[0], curveStart); |
69 } | 80 } |
70 fPathVerbs.push_back(verb); | 81 fPathVerbs.push_back(verb); |
| 82 force_small_to_zero(&pts[0]); |
71 fPathPts.push_back(pts[0]); | 83 fPathPts.push_back(pts[0]); |
72 curveStart = curve[0] = pts[0]; | 84 curveStart = curve[0] = pts[0]; |
73 lastCurve = false; | 85 lastCurve = false; |
74 continue; | 86 continue; |
75 case SkPath::kLine_Verb: | 87 case SkPath::kLine_Verb: |
| 88 force_small_to_zero(&pts[1]); |
76 if (SkDPoint::ApproximatelyEqual(curve[0], pts[1])) { | 89 if (SkDPoint::ApproximatelyEqual(curve[0], pts[1])) { |
77 uint8_t lastVerb = fPathVerbs.back(); | 90 uint8_t lastVerb = fPathVerbs.back(); |
78 if (lastVerb != SkPath::kLine_Verb && lastVerb != SkPath::kM
ove_Verb) { | 91 if (lastVerb != SkPath::kLine_Verb && lastVerb != SkPath::kM
ove_Verb) { |
79 fPathPts.back() = pts[1]; | 92 fPathPts.back() = pts[1]; |
80 } | 93 } |
81 continue; // skip degenerate points | 94 continue; // skip degenerate points |
82 } | 95 } |
83 break; | 96 break; |
84 case SkPath::kQuad_Verb: | 97 case SkPath::kQuad_Verb: |
| 98 force_small_to_zero(&pts[1]); |
| 99 force_small_to_zero(&pts[2]); |
85 curve[1] = pts[1]; | 100 curve[1] = pts[1]; |
86 curve[2] = pts[2]; | 101 curve[2] = pts[2]; |
87 verb = SkReduceOrder::Quad(curve, pts); | 102 verb = SkReduceOrder::Quad(curve, pts); |
88 if (verb == SkPath::kMove_Verb) { | 103 if (verb == SkPath::kMove_Verb) { |
89 continue; // skip degenerate points | 104 continue; // skip degenerate points |
90 } | 105 } |
91 break; | 106 break; |
92 case SkPath::kConic_Verb: { | 107 case SkPath::kConic_Verb: { |
93 const SkPoint* quadPts = quadder.computeQuads(pts, iter.coni
cWeight(), | 108 const SkPoint* quadPts = quadder.computeQuads(pts, iter.coni
cWeight(), |
94 quadderTol); | 109 quadderTol); |
95 const int nQuads = quadder.countQuads(); | 110 const int nQuads = quadder.countQuads(); |
96 for (int i = 0; i < nQuads; ++i) { | 111 for (int i = 0; i < nQuads; ++i) { |
97 fPathVerbs.push_back(SkPath::kQuad_Verb); | 112 fPathVerbs.push_back(SkPath::kQuad_Verb); |
98 } | 113 } |
99 fPathPts.push_back_n(nQuads * 2, quadPts); | 114 fPathPts.push_back_n(nQuads * 2, quadPts); |
100 curve[0] = quadPts[nQuads * 2 - 1]; | 115 curve[0] = quadPts[nQuads * 2 - 1]; |
101 lastCurve = true; | 116 lastCurve = true; |
102 } | 117 } |
103 continue; | 118 continue; |
104 case SkPath::kCubic_Verb: | 119 case SkPath::kCubic_Verb: |
| 120 force_small_to_zero(&pts[1]); |
| 121 force_small_to_zero(&pts[2]); |
| 122 force_small_to_zero(&pts[3]); |
105 curve[1] = pts[1]; | 123 curve[1] = pts[1]; |
106 curve[2] = pts[2]; | 124 curve[2] = pts[2]; |
107 curve[3] = pts[3]; | 125 curve[3] = pts[3]; |
108 verb = SkReduceOrder::Cubic(curve, pts); | 126 verb = SkReduceOrder::Cubic(curve, pts); |
109 if (verb == SkPath::kMove_Verb) { | 127 if (verb == SkPath::kMove_Verb) { |
110 continue; // skip degenerate points | 128 continue; // skip degenerate points |
111 } | 129 } |
112 break; | 130 break; |
113 case SkPath::kClose_Verb: | 131 case SkPath::kClose_Verb: |
114 closeContour(curve[0], curveStart); | 132 closeContour(curve[0], curveStart); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 return false; | 199 return false; |
182 } | 200 } |
183 pointsPtr += SkPathOpsVerbToPoints(verb); | 201 pointsPtr += SkPathOpsVerbToPoints(verb); |
184 SkASSERT(fCurrentContour); | 202 SkASSERT(fCurrentContour); |
185 } | 203 } |
186 if (fCurrentContour && !fAllowOpenContours && !close()) { | 204 if (fCurrentContour && !fAllowOpenContours && !close()) { |
187 return false; | 205 return false; |
188 } | 206 } |
189 return true; | 207 return true; |
190 } | 208 } |
OLD | NEW |