| 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 |