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 "SkIntersections.h" |
7 #include "SkLineParameters.h" | 8 #include "SkLineParameters.h" |
8 #include "SkPathOpsCubic.h" | 9 #include "SkPathOpsCubic.h" |
9 #include "SkPathOpsQuad.h" | 10 #include "SkPathOpsQuad.h" |
10 #include "SkPathOpsTriangle.h" | 11 #include "SkPathOpsTriangle.h" |
11 | 12 |
12 // from http://blog.gludion.com/2009/08/distance-to-quadratic-bezier-curve.html | 13 // from http://blog.gludion.com/2009/08/distance-to-quadratic-bezier-curve.html |
13 // (currently only used by testing) | 14 // (currently only used by testing) |
14 double SkDQuad::nearestT(const SkDPoint& pt) const { | 15 double SkDQuad::nearestT(const SkDPoint& pt) const { |
15 SkDVector pos = fPts[0] - pt; | 16 SkDVector pos = fPts[0] - pt; |
16 // search points P of bezier curve with PM.(dP / dt) = 0 | 17 // search points P of bezier curve with PM.(dP / dt) = 0 |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 double ay = dst[0].fY = interp_quad_coords(&fPts[0].fY, t1); | 214 double ay = dst[0].fY = interp_quad_coords(&fPts[0].fY, t1); |
214 double dx = interp_quad_coords(&fPts[0].fX, (t1 + t2) / 2); | 215 double dx = interp_quad_coords(&fPts[0].fX, (t1 + t2) / 2); |
215 double dy = interp_quad_coords(&fPts[0].fY, (t1 + t2) / 2); | 216 double dy = interp_quad_coords(&fPts[0].fY, (t1 + t2) / 2); |
216 double cx = dst[2].fX = interp_quad_coords(&fPts[0].fX, t2); | 217 double cx = dst[2].fX = interp_quad_coords(&fPts[0].fX, t2); |
217 double cy = dst[2].fY = interp_quad_coords(&fPts[0].fY, t2); | 218 double cy = dst[2].fY = interp_quad_coords(&fPts[0].fY, t2); |
218 /* bx = */ dst[1].fX = 2*dx - (ax + cx)/2; | 219 /* bx = */ dst[1].fX = 2*dx - (ax + cx)/2; |
219 /* by = */ dst[1].fY = 2*dy - (ay + cy)/2; | 220 /* by = */ dst[1].fY = 2*dy - (ay + cy)/2; |
220 return dst; | 221 return dst; |
221 } | 222 } |
222 | 223 |
| 224 void SkDQuad::align(int endIndex, SkDPoint* dstPt) const { |
| 225 if (fPts[endIndex].fX == fPts[1].fX) { |
| 226 dstPt->fX = fPts[endIndex].fX; |
| 227 } |
| 228 if (fPts[endIndex].fY == fPts[1].fY) { |
| 229 dstPt->fY = fPts[endIndex].fY; |
| 230 } |
| 231 } |
| 232 |
223 SkDPoint SkDQuad::subDivide(const SkDPoint& a, const SkDPoint& c, double t1, dou
ble t2) const { | 233 SkDPoint SkDQuad::subDivide(const SkDPoint& a, const SkDPoint& c, double t1, dou
ble t2) const { |
| 234 SkASSERT(t1 != t2); |
224 SkDPoint b; | 235 SkDPoint b; |
| 236 #if 0 |
| 237 // this approach assumes that the control point computed directly is accurat
e enough |
225 double dx = interp_quad_coords(&fPts[0].fX, (t1 + t2) / 2); | 238 double dx = interp_quad_coords(&fPts[0].fX, (t1 + t2) / 2); |
226 double dy = interp_quad_coords(&fPts[0].fY, (t1 + t2) / 2); | 239 double dy = interp_quad_coords(&fPts[0].fY, (t1 + t2) / 2); |
227 b.fX = 2 * dx - (a.fX + c.fX) / 2; | 240 b.fX = 2 * dx - (a.fX + c.fX) / 2; |
228 b.fY = 2 * dy - (a.fY + c.fY) / 2; | 241 b.fY = 2 * dy - (a.fY + c.fY) / 2; |
| 242 #else |
| 243 SkDQuad sub = subDivide(t1, t2); |
| 244 SkDLine b0 = {{a, sub[1] + (a - sub[0])}}; |
| 245 SkDLine b1 = {{c, sub[1] + (c - sub[2])}}; |
| 246 SkIntersections i; |
| 247 i.intersectRay(b0, b1); |
| 248 if (i.used() == 1) { |
| 249 b = i.pt(0); |
| 250 } else { |
| 251 SkASSERT(i.used() == 2 || i.used() == 0); |
| 252 b = SkDPoint::Mid(b0[1], b1[1]); |
| 253 } |
| 254 #endif |
| 255 if (t1 == 0 || t2 == 0) { |
| 256 align(0, &b); |
| 257 } |
| 258 if (t1 == 1 || t2 == 1) { |
| 259 align(2, &b); |
| 260 } |
| 261 if (precisely_subdivide_equal(b.fX, a.fX)) { |
| 262 b.fX = a.fX; |
| 263 } else if (precisely_subdivide_equal(b.fX, c.fX)) { |
| 264 b.fX = c.fX; |
| 265 } |
| 266 if (precisely_subdivide_equal(b.fY, a.fY)) { |
| 267 b.fY = a.fY; |
| 268 } else if (precisely_subdivide_equal(b.fY, c.fY)) { |
| 269 b.fY = c.fY; |
| 270 } |
229 return b; | 271 return b; |
230 } | 272 } |
231 | 273 |
232 /* classic one t subdivision */ | 274 /* classic one t subdivision */ |
233 static void interp_quad_coords(const double* src, double* dst, double t) { | 275 static void interp_quad_coords(const double* src, double* dst, double t) { |
234 double ab = SkDInterp(src[0], src[2], t); | 276 double ab = SkDInterp(src[0], src[2], t); |
235 double bc = SkDInterp(src[2], src[4], t); | 277 double bc = SkDInterp(src[2], src[4], t); |
236 dst[0] = src[0]; | 278 dst[0] = src[0]; |
237 dst[2] = ab; | 279 dst[2] = ab; |
238 dst[4] = SkDInterp(ab, bc, t); | 280 dst[4] = SkDInterp(ab, bc, t); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
284 * c = C | 326 * c = C |
285 */ | 327 */ |
286 void SkDQuad::SetABC(const double* quad, double* a, double* b, double* c) { | 328 void SkDQuad::SetABC(const double* quad, double* a, double* b, double* c) { |
287 *a = quad[0]; // a = A | 329 *a = quad[0]; // a = A |
288 *b = 2 * quad[2]; // b = 2*B | 330 *b = 2 * quad[2]; // b = 2*B |
289 *c = quad[4]; // c = C | 331 *c = quad[4]; // c = C |
290 *b -= *c; // b = 2*B - C | 332 *b -= *c; // b = 2*B - C |
291 *a -= *b; // a = A - 2*B + C | 333 *a -= *b; // a = A - 2*B + C |
292 *b -= *c; // b = 2*B - 2*C | 334 *b -= *c; // b = 2*B - 2*C |
293 } | 335 } |
OLD | NEW |