OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2008 The Android Open Source Project | 3 * Copyright 2008 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #include "SkPathMeasure.h" | 10 #include "SkPathMeasure.h" |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 static bool cubic_too_curvy(const SkPoint pts[4]) { | 83 static bool cubic_too_curvy(const SkPoint pts[4]) { |
84 return cheap_dist_exceeds_limit(pts[1], | 84 return cheap_dist_exceeds_limit(pts[1], |
85 SkScalarInterp(pts[0].fX, pts[3].fX, SK_Scalar1/3), | 85 SkScalarInterp(pts[0].fX, pts[3].fX, SK_Scalar1/3), |
86 SkScalarInterp(pts[0].fY, pts[3].fY, SK_Scalar1/3)) | 86 SkScalarInterp(pts[0].fY, pts[3].fY, SK_Scalar1/3)) |
87 || | 87 || |
88 cheap_dist_exceeds_limit(pts[2], | 88 cheap_dist_exceeds_limit(pts[2], |
89 SkScalarInterp(pts[0].fX, pts[3].fX, SK_Scalar1*2/3), | 89 SkScalarInterp(pts[0].fX, pts[3].fX, SK_Scalar1*2/3), |
90 SkScalarInterp(pts[0].fY, pts[3].fY, SK_Scalar1*2/3)); | 90 SkScalarInterp(pts[0].fY, pts[3].fY, SK_Scalar1*2/3)); |
91 } | 91 } |
92 | 92 |
| 93 /* from http://www.malczak.linuxpl.com/blog/quadratic-bezier-curve-length/ */ |
| 94 static SkScalar compute_quad_len(const SkPoint pts[3]) { |
| 95 SkPoint a,b; |
| 96 a.fX = pts[0].fX - 2 * pts[1].fX + pts[2].fX; |
| 97 a.fY = pts[0].fY - 2 * pts[1].fY + pts[2].fY; |
| 98 b.fX = 2 * (pts[1].fX - pts[0].fX); |
| 99 b.fY = 2 * (pts[1].fY - pts[0].fY); |
| 100 SkScalar A = 4 * (a.fX * a.fX + a.fY * a.fY); |
| 101 SkScalar B = 4 * (a.fX * b.fX + a.fY * b.fY); |
| 102 SkScalar C = b.fX * b.fX + b.fY * b.fY; |
| 103 |
| 104 SkScalar Sabc = 2 * SkScalarSqrt(A + B + C); |
| 105 SkScalar A_2 = SkScalarSqrt(A); |
| 106 SkScalar A_32 = 2 * A * A_2; |
| 107 SkScalar C_2 = 2 * SkScalarSqrt(C); |
| 108 SkScalar BA = B / A_2; |
| 109 |
| 110 return (A_32 * Sabc + A_2 * B * (Sabc - C_2) + |
| 111 (4 * C * A - B * B) * SkScalarLog((2 * A_2 + BA + Sabc) / (BA + C_2)
)) / (4 * A_32); |
| 112 } |
| 113 |
| 114 |
93 SkScalar SkPathMeasure::compute_quad_segs(const SkPoint pts[3], | 115 SkScalar SkPathMeasure::compute_quad_segs(const SkPoint pts[3], |
94 SkScalar distance, int mint, int maxt, int ptIndex) { | 116 SkScalar distance, int mint, int maxt, int ptIndex) { |
95 if (tspan_big_enough(maxt - mint) && quad_too_curvy(pts)) { | 117 if (tspan_big_enough(maxt - mint) && quad_too_curvy(pts)) { |
96 SkPoint tmp[5]; | 118 SkPoint tmp[5]; |
97 int halft = (mint + maxt) >> 1; | 119 int halft = (mint + maxt) >> 1; |
98 | 120 |
99 SkChopQuadAtHalf(pts, tmp); | 121 SkChopQuadAtHalf(pts, tmp); |
100 distance = this->compute_quad_segs(tmp, distance, mint, halft, ptIndex); | 122 distance = this->compute_quad_segs(tmp, distance, mint, halft, ptIndex); |
101 distance = this->compute_quad_segs(&tmp[2], distance, halft, maxt, ptInd
ex); | 123 distance = this->compute_quad_segs(&tmp[2], distance, halft, maxt, ptInd
ex); |
102 } else { | 124 } else { |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 seg->fPtIndex = ptIndex; | 224 seg->fPtIndex = ptIndex; |
203 seg->fType = kLine_SegType; | 225 seg->fType = kLine_SegType; |
204 seg->fTValue = kMaxTValue; | 226 seg->fTValue = kMaxTValue; |
205 fPts.append(1, pts + 1); | 227 fPts.append(1, pts + 1); |
206 ptIndex++; | 228 ptIndex++; |
207 } | 229 } |
208 } break; | 230 } break; |
209 | 231 |
210 case SkPath::kQuad_Verb: { | 232 case SkPath::kQuad_Verb: { |
211 SkScalar prevD = distance; | 233 SkScalar prevD = distance; |
212 distance = this->compute_quad_segs(pts, distance, 0, kMaxTValue,
ptIndex); | 234 if (false) { |
| 235 SkScalar length = compute_quad_len(pts); |
| 236 if (length) { |
| 237 distance += length; |
| 238 Segment* seg = fSegments.append(); |
| 239 seg->fDistance = distance; |
| 240 seg->fPtIndex = ptIndex; |
| 241 seg->fType = kQuad_SegType; |
| 242 seg->fTValue = kMaxTValue; |
| 243 } |
| 244 } else { |
| 245 distance = this->compute_quad_segs(pts, distance, 0, kMaxTVa
lue, ptIndex); |
| 246 } |
213 if (distance > prevD) { | 247 if (distance > prevD) { |
214 fPts.append(2, pts + 1); | 248 fPts.append(2, pts + 1); |
215 ptIndex += 2; | 249 ptIndex += 2; |
216 } | 250 } |
217 } break; | 251 } break; |
218 | 252 |
219 case SkPath::kConic_Verb: { | 253 case SkPath::kConic_Verb: { |
220 const SkConic conic(pts, fIter.conicWeight()); | 254 const SkConic conic(pts, fIter.conicWeight()); |
221 SkScalar prevD = distance; | 255 SkScalar prevD = distance; |
222 distance = this->compute_conic_segs(conic, distance, 0, kMaxTVal
ue, ptIndex); | 256 distance = this->compute_conic_segs(conic, distance, 0, kMaxTVal
ue, ptIndex); |
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
633 | 667 |
634 for (int i = 0; i < fSegments.count(); i++) { | 668 for (int i = 0; i < fSegments.count(); i++) { |
635 const Segment* seg = &fSegments[i]; | 669 const Segment* seg = &fSegments[i]; |
636 SkDebugf("pathmeas: seg[%d] distance=%g, point=%d, t=%g, type=%d\n", | 670 SkDebugf("pathmeas: seg[%d] distance=%g, point=%d, t=%g, type=%d\n", |
637 i, seg->fDistance, seg->fPtIndex, seg->getScalarT(), | 671 i, seg->fDistance, seg->fPtIndex, seg->getScalarT(), |
638 seg->fType); | 672 seg->fType); |
639 } | 673 } |
640 } | 674 } |
641 | 675 |
642 #endif | 676 #endif |
OLD | NEW |