OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 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 | 7 |
8 #include "SkCurveMeasure.h" | 8 #include "SkCurveMeasure.h" |
9 #include "SkGeometry.h" | 9 #include "SkGeometry.h" |
10 | 10 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 const Sk8f (&xCoeff)[3], | 70 const Sk8f (&xCoeff)[3], |
71 const Sk8f (&yCoeff)[3], | 71 const Sk8f (&yCoeff)[3], |
72 const SkSegType segType) { | 72 const SkSegType segType) { |
73 Sk8f x; | 73 Sk8f x; |
74 Sk8f y; | 74 Sk8f y; |
75 switch (segType) { | 75 switch (segType) { |
76 case kQuad_SegType: | 76 case kQuad_SegType: |
77 x = xCoeff[0]*ts + xCoeff[1]; | 77 x = xCoeff[0]*ts + xCoeff[1]; |
78 y = yCoeff[0]*ts + yCoeff[1]; | 78 y = yCoeff[0]*ts + yCoeff[1]; |
79 break; | 79 break; |
80 case kLine_SegType: | |
81 // length of line derivative is constant | |
82 // and we precompute it in the constructor | |
83 return xCoeff[0]; | |
84 case kCubic_SegType: | 80 case kCubic_SegType: |
85 x = (xCoeff[0]*ts + xCoeff[1])*ts + xCoeff[2]; | 81 x = (xCoeff[0]*ts + xCoeff[1])*ts + xCoeff[2]; |
86 y = (yCoeff[0]*ts + yCoeff[1])*ts + yCoeff[2]; | 82 y = (yCoeff[0]*ts + yCoeff[1])*ts + yCoeff[2]; |
87 break; | 83 break; |
88 case kConic_SegType: | 84 case kConic_SegType: |
89 UNIMPLEMENTED; | 85 UNIMPLEMENTED; |
90 break; | 86 break; |
91 default: | 87 default: |
92 UNIMPLEMENTED; | 88 UNIMPLEMENTED; |
93 } | 89 } |
(...skipping 16 matching lines...) Expand all Loading... |
110 float Cy = pts[2].y(); | 106 float Cy = pts[2].y(); |
111 | 107 |
112 // precompute coefficients for derivative | 108 // precompute coefficients for derivative |
113 xCoeff[0] = Sk8f(2.0f*(Ax - 2*Bx + Cx)); | 109 xCoeff[0] = Sk8f(2.0f*(Ax - 2*Bx + Cx)); |
114 xCoeff[1] = Sk8f(2.0f*(Bx - Ax)); | 110 xCoeff[1] = Sk8f(2.0f*(Bx - Ax)); |
115 | 111 |
116 yCoeff[0] = Sk8f(2.0f*(Ay - 2*By + Cy)); | 112 yCoeff[0] = Sk8f(2.0f*(Ay - 2*By + Cy)); |
117 yCoeff[1] = Sk8f(2.0f*(By - Ay)); | 113 yCoeff[1] = Sk8f(2.0f*(By - Ay)); |
118 } | 114 } |
119 break; | 115 break; |
120 case kLine_SegType: { | |
121 // the length of the derivative of a line is constant | |
122 // we put in in both coeff arrays for consistency's sake | |
123 SkScalar length = (pts[1] - pts[0]).length(); | |
124 xCoeff[0] = Sk8f(length); | |
125 yCoeff[0] = Sk8f(length); | |
126 } | |
127 break; | |
128 case kCubic_SegType: | 116 case kCubic_SegType: |
129 { | 117 { |
130 float Ax = pts[0].x(); | 118 float Ax = pts[0].x(); |
131 float Bx = pts[1].x(); | 119 float Bx = pts[1].x(); |
132 float Cx = pts[2].x(); | 120 float Cx = pts[2].x(); |
133 float Dx = pts[3].x(); | 121 float Dx = pts[3].x(); |
134 float Ay = pts[0].y(); | 122 float Ay = pts[0].y(); |
135 float By = pts[1].y(); | 123 float By = pts[1].y(); |
136 float Cy = pts[2].y(); | 124 float Cy = pts[2].y(); |
137 float Dy = pts[3].y(); | 125 float Dy = pts[3].y(); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 : fSegType(segType) { | 164 : fSegType(segType) { |
177 switch (fSegType) { | 165 switch (fSegType) { |
178 case SkSegType::kQuad_SegType: | 166 case SkSegType::kQuad_SegType: |
179 for (size_t i = 0; i < 3; i++) { | 167 for (size_t i = 0; i < 3; i++) { |
180 fPts[i] = pts[i]; | 168 fPts[i] = pts[i]; |
181 } | 169 } |
182 break; | 170 break; |
183 case SkSegType::kLine_SegType: | 171 case SkSegType::kLine_SegType: |
184 fPts[0] = pts[0]; | 172 fPts[0] = pts[0]; |
185 fPts[1] = pts[1]; | 173 fPts[1] = pts[1]; |
| 174 fLength = (fPts[1] - fPts[0]).length(); |
186 break; | 175 break; |
187 case SkSegType::kCubic_SegType: | 176 case SkSegType::kCubic_SegType: |
188 for (size_t i = 0; i < 4; i++) { | 177 for (size_t i = 0; i < 4; i++) { |
189 fPts[i] = pts[i]; | 178 fPts[i] = pts[i]; |
190 } | 179 } |
191 break; | 180 break; |
192 case SkSegType::kConic_SegType: | 181 case SkSegType::kConic_SegType: |
193 for (size_t i = 0; i < 4; i++) { | 182 for (size_t i = 0; i < 4; i++) { |
194 fPts[i] = pts[i]; | 183 fPts[i] = pts[i]; |
195 } | 184 } |
196 break; | 185 break; |
197 default: | 186 default: |
198 UNIMPLEMENTED; | 187 UNIMPLEMENTED; |
199 break; | 188 break; |
200 } | 189 } |
201 fIntegrator = ArcLengthIntegrator(fPts, fSegType); | 190 if (kLine_SegType != segType) { |
| 191 fIntegrator = ArcLengthIntegrator(fPts, fSegType); |
| 192 } |
202 } | 193 } |
203 | 194 |
204 SkScalar SkCurveMeasure::getLength() { | 195 SkScalar SkCurveMeasure::getLength() { |
205 if (-1.0f == fLength) { | 196 if (-1.0f == fLength) { |
206 fLength = fIntegrator.computeLength(1.0f); | 197 fLength = fIntegrator.computeLength(1.0f); |
207 } | 198 } |
208 return fLength; | 199 return fLength; |
209 } | 200 } |
210 | 201 |
211 // Given an arc length targetLength, we want to determine what t | 202 // Given an arc length targetLength, we want to determine what t |
212 // gives us the corresponding arc length along the curve. | 203 // gives us the corresponding arc length along the curve. |
213 // We do this by letting the arc length integral := f(t) and | 204 // We do this by letting the arc length integral := f(t) and |
214 // solving for the root of the equation f(t) - targetLength = 0 | 205 // solving for the root of the equation f(t) - targetLength = 0 |
215 // using Newton's method and lerp-bisection. | 206 // using Newton's method and lerp-bisection. |
216 // The computationally expensive parts are the integral approximation | 207 // The computationally expensive parts are the integral approximation |
217 // at each step, and computing the derivative of the arc length integral, | 208 // at each step, and computing the derivative of the arc length integral, |
218 // which is equal to the length of the tangent (so we have to do a sqrt). | 209 // which is equal to the length of the tangent (so we have to do a sqrt). |
219 | 210 |
220 SkScalar SkCurveMeasure::getTime(SkScalar targetLength) { | 211 SkScalar SkCurveMeasure::getTime(SkScalar targetLength) { |
221 if (targetLength == 0.0f) { | 212 if (targetLength == 0.0f) { |
222 return 0.0f; | 213 return 0.0f; |
223 } | 214 } |
224 | 215 |
225 SkScalar currentLength = getLength(); | 216 SkScalar currentLength = getLength(); |
226 | 217 |
227 if (SkScalarNearlyEqual(targetLength, currentLength)) { | 218 if (SkScalarNearlyEqual(targetLength, currentLength)) { |
228 return 1.0f; | 219 return 1.0f; |
229 } | 220 } |
| 221 if (kLine_SegType == fSegType) { |
| 222 return targetLength / currentLength; |
| 223 } |
230 | 224 |
231 // initial estimate of t is percentage of total length | 225 // initial estimate of t is percentage of total length |
232 SkScalar currentT = targetLength / currentLength; | 226 SkScalar currentT = targetLength / currentLength; |
233 SkScalar prevT = -1.0f; | 227 SkScalar prevT = -1.0f; |
234 SkScalar newT; | 228 SkScalar newT; |
235 | 229 |
236 SkScalar minT = 0.0f; | 230 SkScalar minT = 0.0f; |
237 SkScalar maxT = 1.0f; | 231 SkScalar maxT = 1.0f; |
238 | 232 |
239 int iterations = 0; | 233 int iterations = 0; |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 if (time) { | 301 if (time) { |
308 *time = t; | 302 *time = t; |
309 } | 303 } |
310 if (pos) { | 304 if (pos) { |
311 *pos = evaluate(fPts, fSegType, t); | 305 *pos = evaluate(fPts, fSegType, t); |
312 } | 306 } |
313 if (tan) { | 307 if (tan) { |
314 *tan = evaluateDerivative(fPts, fSegType, t); | 308 *tan = evaluateDerivative(fPts, fSegType, t); |
315 } | 309 } |
316 } | 310 } |
OLD | NEW |