OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 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 "GrPathUtils.h" | 8 #include "GrPathUtils.h" |
9 | 9 |
10 #include "GrPoint.h" | 10 #include "GrPoint.h" |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 break; | 180 break; |
181 default: | 181 default: |
182 break; | 182 break; |
183 } | 183 } |
184 first = false; | 184 first = false; |
185 } | 185 } |
186 return pointCount; | 186 return pointCount; |
187 } | 187 } |
188 | 188 |
189 void GrPathUtils::QuadUVMatrix::set(const GrPoint qPts[3]) { | 189 void GrPathUtils::QuadUVMatrix::set(const GrPoint qPts[3]) { |
190 // can't make this static, no cons :( | |
191 SkMatrix UVpts; | |
192 #ifndef SK_SCALAR_IS_FLOAT | 190 #ifndef SK_SCALAR_IS_FLOAT |
193 GrCrash("Expected scalar is float."); | 191 GrCrash("Expected scalar is float."); |
194 #endif | 192 #endif |
195 SkMatrix m; | 193 SkMatrix m; |
196 // We want M such that M * xy_pt = uv_pt | 194 // We want M such that M * xy_pt = uv_pt |
197 // We know M * control_pts = [0 1/2 1] | 195 // We know M * control_pts = [0 1/2 1] |
198 // [0 0 1] | 196 // [0 0 1] |
199 // [1 1 1] | 197 // [1 1 1] |
| 198 // And control_pts = [x0 x1 x2] |
| 199 // [y0 y1 y2] |
| 200 // [1 1 1 ] |
200 // We invert the control pt matrix and post concat to both sides to get M. | 201 // We invert the control pt matrix and post concat to both sides to get M. |
201 UVpts.setAll(0, SK_ScalarHalf, SK_Scalar1, | 202 // Using the known form of the control point matrix and the result, we can |
202 0, 0, SK_Scalar1, | 203 // optimize and improve precision. |
203 SkScalarToPersp(SK_Scalar1), | 204 |
204 SkScalarToPersp(SK_Scalar1), | 205 double x0 = qPts[0].fX; |
205 SkScalarToPersp(SK_Scalar1)); | 206 double y0 = qPts[0].fY; |
206 m.setAll(qPts[0].fX, qPts[1].fX, qPts[2].fX, | 207 double x1 = qPts[1].fX; |
207 qPts[0].fY, qPts[1].fY, qPts[2].fY, | 208 double y1 = qPts[1].fY; |
208 SkScalarToPersp(SK_Scalar1), | 209 double x2 = qPts[2].fX; |
209 SkScalarToPersp(SK_Scalar1), | 210 double y2 = qPts[2].fY; |
210 SkScalarToPersp(SK_Scalar1)); | 211 double det = x0*y1 - y0*x1 + x2*y0 - y2*x0 + x1*y2 - y1*x2; |
211 if (!m.invert(&m)) { | 212 |
| 213 if (!sk_float_isfinite(det) |
| 214 || SkScalarNearlyZero((float)det, SK_ScalarNearlyZero * SK_ScalarNearlyZ
ero)) { |
212 // The quad is degenerate. Hopefully this is rare. Find the pts that are | 215 // The quad is degenerate. Hopefully this is rare. Find the pts that are |
213 // farthest apart to compute a line (unless it is really a pt). | 216 // farthest apart to compute a line (unless it is really a pt). |
214 SkScalar maxD = qPts[0].distanceToSqd(qPts[1]); | 217 SkScalar maxD = qPts[0].distanceToSqd(qPts[1]); |
215 int maxEdge = 0; | 218 int maxEdge = 0; |
216 SkScalar d = qPts[1].distanceToSqd(qPts[2]); | 219 SkScalar d = qPts[1].distanceToSqd(qPts[2]); |
217 if (d > maxD) { | 220 if (d > maxD) { |
218 maxD = d; | 221 maxD = d; |
219 maxEdge = 1; | 222 maxEdge = 1; |
220 } | 223 } |
221 d = qPts[2].distanceToSqd(qPts[0]); | 224 d = qPts[2].distanceToSqd(qPts[0]); |
(...skipping 18 matching lines...) Expand all Loading... |
240 fM[3] = lineVec.fX; | 243 fM[3] = lineVec.fX; |
241 fM[4] = lineVec.fY; | 244 fM[4] = lineVec.fY; |
242 fM[5] = -lineVec.dot(qPts[maxEdge]); | 245 fM[5] = -lineVec.dot(qPts[maxEdge]); |
243 } else { | 246 } else { |
244 // It's a point. It should cover zero area. Just set the matrix such | 247 // It's a point. It should cover zero area. Just set the matrix such |
245 // that (u, v) will always be far away from the quad. | 248 // that (u, v) will always be far away from the quad. |
246 fM[0] = 0; fM[1] = 0; fM[2] = 100.f; | 249 fM[0] = 0; fM[1] = 0; fM[2] = 100.f; |
247 fM[3] = 0; fM[4] = 0; fM[5] = 100.f; | 250 fM[3] = 0; fM[4] = 0; fM[5] = 100.f; |
248 } | 251 } |
249 } else { | 252 } else { |
250 m.postConcat(UVpts); | 253 double scale = 1.0/det; |
| 254 |
| 255 // compute adjugate matrix |
| 256 double a0, a1, a2, a3, a4, a5, a6, a7, a8; |
| 257 a0 = y1-y2; |
| 258 a1 = x2-x1; |
| 259 a2 = x1*y2-x2*y1; |
| 260 |
| 261 a3 = y2-y0; |
| 262 a4 = x0-x2; |
| 263 a5 = x2*y0-x0*y2; |
| 264 |
| 265 a6 = y0-y1; |
| 266 a7 = x1-x0; |
| 267 a8 = x0*y1-x1*y0; |
| 268 |
| 269 // this performs the uv_pts*adjugate(control_pts) multiply, |
| 270 // then does the scale by 1/det afterwards to improve precision |
| 271 m[SkMatrix::kMScaleX] = (float)((0.5*a3 + a6)*scale); |
| 272 m[SkMatrix::kMSkewX] = (float)((0.5*a4 + a7)*scale); |
| 273 m[SkMatrix::kMTransX] = (float)((0.5*a5 + a8)*scale); |
| 274 |
| 275 m[SkMatrix::kMSkewY] = (float)(a6*scale); |
| 276 m[SkMatrix::kMScaleY] = (float)(a7*scale); |
| 277 m[SkMatrix::kMTransY] = (float)(a8*scale); |
| 278 |
| 279 m[SkMatrix::kMPersp0] = (float)((a0 + a3 + a6)*scale); |
| 280 m[SkMatrix::kMPersp1] = (float)((a1 + a4 + a7)*scale); |
| 281 m[SkMatrix::kMPersp2] = (float)((a2 + a5 + a8)*scale); |
251 | 282 |
252 // The matrix should not have perspective. | 283 // The matrix should not have perspective. |
253 SkDEBUGCODE(static const SkScalar gTOL = 1.f / 100.f); | 284 SkDEBUGCODE(static const SkScalar gTOL = 1.f / 100.f); |
254 SkASSERT(SkScalarAbs(m.get(SkMatrix::kMPersp0)) < gTOL); | 285 SkASSERT(SkScalarAbs(m.get(SkMatrix::kMPersp0)) < gTOL); |
255 SkASSERT(SkScalarAbs(m.get(SkMatrix::kMPersp1)) < gTOL); | 286 SkASSERT(SkScalarAbs(m.get(SkMatrix::kMPersp1)) < gTOL); |
256 | 287 |
257 // It may not be normalized to have 1.0 in the bottom right | 288 // It may not be normalized to have 1.0 in the bottom right |
258 float m33 = m.get(SkMatrix::kMPersp2); | 289 float m33 = m.get(SkMatrix::kMPersp2); |
259 if (1.f != m33) { | 290 if (1.f != m33) { |
260 m33 = 1.f / m33; | 291 m33 = 1.f / m33; |
(...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
831 set_loop_klm(d, controlK, controlL, controlM); | 862 set_loop_klm(d, controlK, controlL, controlM); |
832 } else if (kCusp_CubicType == cType) { | 863 } else if (kCusp_CubicType == cType) { |
833 SkASSERT(0.f == d[0]); | 864 SkASSERT(0.f == d[0]); |
834 set_cusp_klm(d, controlK, controlL, controlM); | 865 set_cusp_klm(d, controlK, controlL, controlM); |
835 } else if (kQuadratic_CubicType == cType) { | 866 } else if (kQuadratic_CubicType == cType) { |
836 set_quadratic_klm(d, controlK, controlL, controlM); | 867 set_quadratic_klm(d, controlK, controlL, controlM); |
837 } | 868 } |
838 | 869 |
839 calc_cubic_klm(p, controlK, controlL, controlM, klm, &klm[3], &klm[6]); | 870 calc_cubic_klm(p, controlK, controlL, controlM, klm, &klm[3], &klm[6]); |
840 } | 871 } |
OLD | NEW |