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 "SkIntersections.h" |
8 #include "SkLineParameters.h" | 8 #include "SkLineParameters.h" |
9 #include "SkPathOpsCubic.h" | 9 #include "SkPathOpsCubic.h" |
10 #include "SkPathOpsCurve.h" | 10 #include "SkPathOpsCurve.h" |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 2 0 -2 -1 0 | 66 2 0 -2 -1 0 |
67 */ | 67 */ |
68 void SkDQuad::otherPts(int oddMan, const SkDPoint* endPt[2]) const { | 68 void SkDQuad::otherPts(int oddMan, const SkDPoint* endPt[2]) const { |
69 for (int opp = 1; opp < kPointCount; ++opp) { | 69 for (int opp = 1; opp < kPointCount; ++opp) { |
70 int end = (oddMan ^ opp) - oddMan; // choose a value not equal to oddMa
n | 70 int end = (oddMan ^ opp) - oddMan; // choose a value not equal to oddMa
n |
71 end &= ~(end >> 2); // if the value went negative, set it to zero | 71 end &= ~(end >> 2); // if the value went negative, set it to zero |
72 endPt[opp - 1] = &fPts[end]; | 72 endPt[opp - 1] = &fPts[end]; |
73 } | 73 } |
74 } | 74 } |
75 | 75 |
76 // from http://blog.gludion.com/2009/08/distance-to-quadratic-bezier-curve.html | |
77 // (currently only used by testing) | |
78 double SkDQuad::nearestT(const SkDPoint& pt) const { | |
79 SkDVector pos = fPts[0] - pt; | |
80 // search points P of bezier curve with PM.(dP / dt) = 0 | |
81 // a calculus leads to a 3d degree equation : | |
82 SkDVector A = fPts[1] - fPts[0]; | |
83 SkDVector B = fPts[2] - fPts[1]; | |
84 B -= A; | |
85 double a = B.dot(B); | |
86 double b = 3 * A.dot(B); | |
87 double c = 2 * A.dot(A) + pos.dot(B); | |
88 double d = pos.dot(A); | |
89 double ts[3]; | |
90 int roots = SkDCubic::RootsValidT(a, b, c, d, ts); | |
91 double d0 = pt.distanceSquared(fPts[0]); | |
92 double d2 = pt.distanceSquared(fPts[2]); | |
93 double distMin = SkTMin(d0, d2); | |
94 int bestIndex = -1; | |
95 for (int index = 0; index < roots; ++index) { | |
96 SkDPoint onQuad = ptAtT(ts[index]); | |
97 double dist = pt.distanceSquared(onQuad); | |
98 if (distMin > dist) { | |
99 distMin = dist; | |
100 bestIndex = index; | |
101 } | |
102 } | |
103 if (bestIndex >= 0) { | |
104 return ts[bestIndex]; | |
105 } | |
106 return d0 < d2 ? 0 : 1; | |
107 } | |
108 | |
109 int SkDQuad::AddValidTs(double s[], int realRoots, double* t) { | 76 int SkDQuad::AddValidTs(double s[], int realRoots, double* t) { |
110 int foundRoots = 0; | 77 int foundRoots = 0; |
111 for (int index = 0; index < realRoots; ++index) { | 78 for (int index = 0; index < realRoots; ++index) { |
112 double tValue = s[index]; | 79 double tValue = s[index]; |
113 if (approximately_zero_or_more(tValue) && approximately_one_or_less(tVal
ue)) { | 80 if (approximately_zero_or_more(tValue) && approximately_one_or_less(tVal
ue)) { |
114 if (approximately_less_than_zero(tValue)) { | 81 if (approximately_less_than_zero(tValue)) { |
115 tValue = 0; | 82 tValue = 0; |
116 } else if (approximately_greater_than_one(tValue)) { | 83 } else if (approximately_greater_than_one(tValue)) { |
117 tValue = 1; | 84 tValue = 1; |
118 } | 85 } |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 lineParameters.normalize(); | 148 lineParameters.normalize(); |
182 double distance = lineParameters.controlPtDistance(*this); | 149 double distance = lineParameters.controlPtDistance(*this); |
183 double tiniest = SkTMin(SkTMin(SkTMin(SkTMin(SkTMin(fPts[0].fX, fPts[0].fY), | 150 double tiniest = SkTMin(SkTMin(SkTMin(SkTMin(SkTMin(fPts[0].fX, fPts[0].fY), |
184 fPts[1].fX), fPts[1].fY), fPts[2].fX), fPts[2].fY); | 151 fPts[1].fX), fPts[1].fY), fPts[2].fX), fPts[2].fY); |
185 double largest = SkTMax(SkTMax(SkTMax(SkTMax(SkTMax(fPts[0].fX, fPts[0].fY), | 152 double largest = SkTMax(SkTMax(SkTMax(SkTMax(SkTMax(fPts[0].fX, fPts[0].fY), |
186 fPts[1].fX), fPts[1].fY), fPts[2].fX), fPts[2].fY); | 153 fPts[1].fX), fPts[1].fY), fPts[2].fX), fPts[2].fY); |
187 largest = SkTMax(largest, -tiniest); | 154 largest = SkTMax(largest, -tiniest); |
188 return approximately_zero_when_compared_to(distance, largest); | 155 return approximately_zero_when_compared_to(distance, largest); |
189 } | 156 } |
190 | 157 |
191 SkDConic SkDQuad::toConic() const { | |
192 SkDConic conic; | |
193 memcpy(conic.fPts.fPts, fPts, sizeof(fPts)); | |
194 conic.fWeight = 1; | |
195 return conic; | |
196 } | |
197 | |
198 SkDCubic SkDQuad::toCubic() const { | |
199 SkDCubic cubic; | |
200 cubic[0] = fPts[0]; | |
201 cubic[2] = fPts[1]; | |
202 cubic[3] = fPts[2]; | |
203 cubic[1].fX = (cubic[0].fX + cubic[2].fX * 2) / 3; | |
204 cubic[1].fY = (cubic[0].fY + cubic[2].fY * 2) / 3; | |
205 cubic[2].fX = (cubic[3].fX + cubic[2].fX * 2) / 3; | |
206 cubic[2].fY = (cubic[3].fY + cubic[2].fY * 2) / 3; | |
207 return cubic; | |
208 } | |
209 | |
210 SkDVector SkDQuad::dxdyAtT(double t) const { | 158 SkDVector SkDQuad::dxdyAtT(double t) const { |
211 double a = t - 1; | 159 double a = t - 1; |
212 double b = 1 - 2 * t; | 160 double b = 1 - 2 * t; |
213 double c = t; | 161 double c = t; |
214 SkDVector result = { a * fPts[0].fX + b * fPts[1].fX + c * fPts[2].fX, | 162 SkDVector result = { a * fPts[0].fX + b * fPts[1].fX + c * fPts[2].fX, |
215 a * fPts[0].fY + b * fPts[1].fY + c * fPts[2].fY }; | 163 a * fPts[0].fY + b * fPts[1].fY + c * fPts[2].fY }; |
216 return result; | 164 return result; |
217 } | 165 } |
218 | 166 |
219 // OPTIMIZE: assert if caller passes in t == 0 / t == 1 ? | 167 // OPTIMIZE: assert if caller passes in t == 0 / t == 1 ? |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 } | 287 } |
340 | 288 |
341 SkDQuadPair SkDQuad::chopAt(double t) const | 289 SkDQuadPair SkDQuad::chopAt(double t) const |
342 { | 290 { |
343 SkDQuadPair dst; | 291 SkDQuadPair dst; |
344 interp_quad_coords(&fPts[0].fX, &dst.pts[0].fX, t); | 292 interp_quad_coords(&fPts[0].fX, &dst.pts[0].fX, t); |
345 interp_quad_coords(&fPts[0].fY, &dst.pts[0].fY, t); | 293 interp_quad_coords(&fPts[0].fY, &dst.pts[0].fY, t); |
346 return dst; | 294 return dst; |
347 } | 295 } |
348 | 296 |
349 bool SkDQuad::Clockwise(const SkOpCurve& edge, bool* swap) { | |
350 SkDQuad temp; | |
351 double sum = (edge[0].fX - edge[kPointLast].fX) * (edge[0].fY + edge[kPointL
ast].fY); | |
352 for (int idx = 0; idx < kPointLast; ++idx){ | |
353 sum += (edge[idx + 1].fX - edge[idx].fX) * (edge[idx + 1].fY + edge[idx]
.fY); | |
354 } | |
355 temp.set(edge.fPts); | |
356 *swap = sum > 0 && !temp.monotonicInY(); | |
357 return sum <= 0; | |
358 } | |
359 | |
360 static int valid_unit_divide(double numer, double denom, double* ratio) | 297 static int valid_unit_divide(double numer, double denom, double* ratio) |
361 { | 298 { |
362 if (numer < 0) { | 299 if (numer < 0) { |
363 numer = -numer; | 300 numer = -numer; |
364 denom = -denom; | 301 denom = -denom; |
365 } | 302 } |
366 if (denom == 0 || numer == 0 || numer >= denom) { | 303 if (denom == 0 || numer == 0 || numer >= denom) { |
367 return 0; | 304 return 0; |
368 } | 305 } |
369 double r = numer / denom; | 306 double r = numer / denom; |
(...skipping 26 matching lines...) Expand all Loading... |
396 * c = C | 333 * c = C |
397 */ | 334 */ |
398 void SkDQuad::SetABC(const double* quad, double* a, double* b, double* c) { | 335 void SkDQuad::SetABC(const double* quad, double* a, double* b, double* c) { |
399 *a = quad[0]; // a = A | 336 *a = quad[0]; // a = A |
400 *b = 2 * quad[2]; // b = 2*B | 337 *b = 2 * quad[2]; // b = 2*B |
401 *c = quad[4]; // c = C | 338 *c = quad[4]; // c = C |
402 *b -= *c; // b = 2*B - C | 339 *b -= *c; // b = 2*B - C |
403 *a -= *b; // a = A - 2*B + C | 340 *a -= *b; // a = A - 2*B + C |
404 *b -= *c; // b = 2*B - 2*C | 341 *b -= *c; // b = 2*B - 2*C |
405 } | 342 } |
OLD | NEW |