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" |
11 #include "SkGeometry.h" | 11 #include "SkGeometry.h" |
12 #include "SkPath.h" | 12 #include "SkPath.h" |
13 #include "SkTSearch.h" | 13 #include "SkTSearch.h" |
14 | 14 |
15 // these must be 0,1,2,3 since they are in our 2-bit field | 15 // these must be 0,1,2,3 since they are in our 2-bit field |
16 enum { | 16 enum { |
17 kLine_SegType, | 17 kLine_SegType, |
18 kQuad_SegType, | 18 kQuad_SegType, |
19 kCubic_SegType, | 19 kCubic_SegType, |
20 kConic_SegType, | 20 kConic_SegType, |
21 }; | 21 }; |
22 | 22 |
23 #ifdef SK_SUPPORT_LEGACY_PATH_MEASURE_TVALUE | |
24 #define kMaxTValue 32767 | |
25 #else | |
26 #define kMaxTValue 0x3FFFFFFF | 23 #define kMaxTValue 0x3FFFFFFF |
27 #endif | |
28 | 24 |
29 static inline SkScalar tValue2Scalar(int t) { | 25 static inline SkScalar tValue2Scalar(int t) { |
30 SkASSERT((unsigned)t <= kMaxTValue); | 26 SkASSERT((unsigned)t <= kMaxTValue); |
31 #ifdef SK_SUPPORT_LEGACY_PATH_MEASURE_TVALUE | |
32 return t * 3.05185e-5f; // t / 32767 | |
33 #else | |
34 const SkScalar kMaxTReciprocal = 1.0f / kMaxTValue; | 27 const SkScalar kMaxTReciprocal = 1.0f / kMaxTValue; |
35 return t * kMaxTReciprocal; | 28 return t * kMaxTReciprocal; |
36 #endif | |
37 } | 29 } |
38 | 30 |
39 SkScalar SkPathMeasure::Segment::getScalarT() const { | 31 SkScalar SkPathMeasure::Segment::getScalarT() const { |
40 return tValue2Scalar(fTValue); | 32 return tValue2Scalar(fTValue); |
41 } | 33 } |
42 | 34 |
43 const SkPathMeasure::Segment* SkPathMeasure::NextSegment(const Segment* seg) { | 35 const SkPathMeasure::Segment* SkPathMeasure::NextSegment(const Segment* seg) { |
44 unsigned ptIndex = seg->fPtIndex; | 36 unsigned ptIndex = seg->fPtIndex; |
45 | 37 |
46 do { | 38 do { |
(...skipping 19 matching lines...) Expand all Loading... |
66 // diff = -a/4 + b/2 - c/4 | 58 // diff = -a/4 + b/2 - c/4 |
67 SkScalar dx = SkScalarHalf(pts[1].fX) - | 59 SkScalar dx = SkScalarHalf(pts[1].fX) - |
68 SkScalarHalf(SkScalarHalf(pts[0].fX + pts[2].fX)); | 60 SkScalarHalf(SkScalarHalf(pts[0].fX + pts[2].fX)); |
69 SkScalar dy = SkScalarHalf(pts[1].fY) - | 61 SkScalar dy = SkScalarHalf(pts[1].fY) - |
70 SkScalarHalf(SkScalarHalf(pts[0].fY + pts[2].fY)); | 62 SkScalarHalf(SkScalarHalf(pts[0].fY + pts[2].fY)); |
71 | 63 |
72 SkScalar dist = SkMaxScalar(SkScalarAbs(dx), SkScalarAbs(dy)); | 64 SkScalar dist = SkMaxScalar(SkScalarAbs(dx), SkScalarAbs(dy)); |
73 return dist > fTolerance; | 65 return dist > fTolerance; |
74 } | 66 } |
75 | 67 |
76 #ifndef SK_SUPPORT_LEGACY_CONIC_MEASURE | |
77 bool SkPathMeasure::conic_too_curvy(const SkPoint& firstPt, const SkPoint& midTP
t, | 68 bool SkPathMeasure::conic_too_curvy(const SkPoint& firstPt, const SkPoint& midTP
t, |
78 const SkPoint& lastPt) { | 69 const SkPoint& lastPt) { |
79 SkPoint midEnds = firstPt + lastPt; | 70 SkPoint midEnds = firstPt + lastPt; |
80 midEnds *= 0.5f; | 71 midEnds *= 0.5f; |
81 SkVector dxy = midTPt - midEnds; | 72 SkVector dxy = midTPt - midEnds; |
82 SkScalar dist = SkMaxScalar(SkScalarAbs(dxy.fX), SkScalarAbs(dxy.fY)); | 73 SkScalar dist = SkMaxScalar(SkScalarAbs(dxy.fX), SkScalarAbs(dxy.fY)); |
83 return dist > fTolerance; | 74 return dist > fTolerance; |
84 } | 75 } |
85 #endif | |
86 | 76 |
87 bool SkPathMeasure::cheap_dist_exceeds_limit(const SkPoint& pt, | 77 bool SkPathMeasure::cheap_dist_exceeds_limit(const SkPoint& pt, |
88 SkScalar x, SkScalar y) { | 78 SkScalar x, SkScalar y) { |
89 SkScalar dist = SkMaxScalar(SkScalarAbs(x - pt.fX), SkScalarAbs(y - pt.fY)); | 79 SkScalar dist = SkMaxScalar(SkScalarAbs(x - pt.fX), SkScalarAbs(y - pt.fY)); |
90 // just made up the 1/2 | 80 // just made up the 1/2 |
91 return dist > fTolerance; | 81 return dist > fTolerance; |
92 } | 82 } |
93 | 83 |
94 bool SkPathMeasure::cubic_too_curvy(const SkPoint pts[4]) { | 84 bool SkPathMeasure::cubic_too_curvy(const SkPoint pts[4]) { |
95 return cheap_dist_exceeds_limit(pts[1], | 85 return cheap_dist_exceeds_limit(pts[1], |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 Segment* seg = fSegments.append(); | 160 Segment* seg = fSegments.append(); |
171 seg->fDistance = distance; | 161 seg->fDistance = distance; |
172 seg->fPtIndex = ptIndex; | 162 seg->fPtIndex = ptIndex; |
173 seg->fType = kQuad_SegType; | 163 seg->fType = kQuad_SegType; |
174 seg->fTValue = maxt; | 164 seg->fTValue = maxt; |
175 } | 165 } |
176 } | 166 } |
177 return distance; | 167 return distance; |
178 } | 168 } |
179 | 169 |
180 #ifdef SK_SUPPORT_LEGACY_CONIC_MEASURE | |
181 SkScalar SkPathMeasure::compute_conic_segs(const SkConic& conic, | |
182 SkScalar distance, int mint, int maxt
, int ptIndex) { | |
183 if (tspan_big_enough(maxt - mint) && quad_too_curvy(conic.fPts)) { | |
184 SkConic tmp[2]; | |
185 conic.chop(tmp); | |
186 | |
187 int halft = (mint + maxt) >> 1; | |
188 distance = this->compute_conic_segs(tmp[0], distance, mint, halft, ptInd
ex); | |
189 distance = this->compute_conic_segs(tmp[1], distance, halft, maxt, ptInd
ex); | |
190 } else { | |
191 SkScalar d = SkPoint::Distance(conic.fPts[0], conic.fPts[2]); | |
192 SkScalar prevD = distance; | |
193 distance += d; | |
194 if (distance > prevD) { | |
195 Segment* seg = fSegments.append(); | |
196 seg->fDistance = distance; | |
197 seg->fPtIndex = ptIndex; | |
198 seg->fType = kConic_SegType; | |
199 seg->fTValue = maxt; | |
200 } | |
201 } | |
202 return distance; | |
203 } | |
204 #else | |
205 SkScalar SkPathMeasure::compute_conic_segs(const SkConic& conic, SkScalar distan
ce, | 170 SkScalar SkPathMeasure::compute_conic_segs(const SkConic& conic, SkScalar distan
ce, |
206 int mint, const SkPoint& minPt, | 171 int mint, const SkPoint& minPt, |
207 int maxt, const SkPoint& maxPt, int p
tIndex) { | 172 int maxt, const SkPoint& maxPt, int p
tIndex) { |
208 int halft = (mint + maxt) >> 1; | 173 int halft = (mint + maxt) >> 1; |
209 SkPoint halfPt = conic.evalAt(tValue2Scalar(halft)); | 174 SkPoint halfPt = conic.evalAt(tValue2Scalar(halft)); |
210 if (tspan_big_enough(maxt - mint) && conic_too_curvy(minPt, halfPt, maxPt))
{ | 175 if (tspan_big_enough(maxt - mint) && conic_too_curvy(minPt, halfPt, maxPt))
{ |
211 distance = this->compute_conic_segs(conic, distance, mint, minPt, halft,
halfPt, ptIndex); | 176 distance = this->compute_conic_segs(conic, distance, mint, minPt, halft,
halfPt, ptIndex); |
212 distance = this->compute_conic_segs(conic, distance, halft, halfPt, maxt
, maxPt, ptIndex); | 177 distance = this->compute_conic_segs(conic, distance, halft, halfPt, maxt
, maxPt, ptIndex); |
213 } else { | 178 } else { |
214 SkScalar d = SkPoint::Distance(minPt, maxPt); | 179 SkScalar d = SkPoint::Distance(minPt, maxPt); |
215 SkScalar prevD = distance; | 180 SkScalar prevD = distance; |
216 distance += d; | 181 distance += d; |
217 if (distance > prevD) { | 182 if (distance > prevD) { |
218 Segment* seg = fSegments.append(); | 183 Segment* seg = fSegments.append(); |
219 seg->fDistance = distance; | 184 seg->fDistance = distance; |
220 seg->fPtIndex = ptIndex; | 185 seg->fPtIndex = ptIndex; |
221 seg->fType = kConic_SegType; | 186 seg->fType = kConic_SegType; |
222 seg->fTValue = maxt; | 187 seg->fTValue = maxt; |
223 } | 188 } |
224 } | 189 } |
225 return distance; | 190 return distance; |
226 } | 191 } |
227 #endif | |
228 | 192 |
229 SkScalar SkPathMeasure::compute_cubic_segs(const SkPoint pts[4], | 193 SkScalar SkPathMeasure::compute_cubic_segs(const SkPoint pts[4], |
230 SkScalar distance, int mint, int maxt, int ptIndex) { | 194 SkScalar distance, int mint, int maxt, int ptIndex) { |
231 if (tspan_big_enough(maxt - mint) && cubic_too_curvy(pts)) { | 195 if (tspan_big_enough(maxt - mint) && cubic_too_curvy(pts)) { |
232 SkPoint tmp[7]; | 196 SkPoint tmp[7]; |
233 int halft = (mint + maxt) >> 1; | 197 int halft = (mint + maxt) >> 1; |
234 | 198 |
235 SkChopCubicAtHalf(pts, tmp); | 199 SkChopCubicAtHalf(pts, tmp); |
236 distance = this->compute_cubic_segs(tmp, distance, mint, halft, ptIndex)
; | 200 distance = this->compute_cubic_segs(tmp, distance, mint, halft, ptIndex)
; |
237 distance = this->compute_cubic_segs(&tmp[3], distance, halft, maxt, ptIn
dex); | 201 distance = this->compute_cubic_segs(&tmp[3], distance, halft, maxt, ptIn
dex); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 } | 276 } |
313 if (distance > prevD) { | 277 if (distance > prevD) { |
314 fPts.append(2, pts + 1); | 278 fPts.append(2, pts + 1); |
315 ptIndex += 2; | 279 ptIndex += 2; |
316 } | 280 } |
317 } break; | 281 } break; |
318 | 282 |
319 case SkPath::kConic_Verb: { | 283 case SkPath::kConic_Verb: { |
320 const SkConic conic(pts, fIter.conicWeight()); | 284 const SkConic conic(pts, fIter.conicWeight()); |
321 SkScalar prevD = distance; | 285 SkScalar prevD = distance; |
322 #ifdef SK_SUPPORT_LEGACY_CONIC_MEASURE | |
323 distance = this->compute_conic_segs(conic, distance, 0, kMaxTVal
ue, ptIndex); | |
324 #else | |
325 distance = this->compute_conic_segs(conic, distance, 0, conic.fP
ts[0], | 286 distance = this->compute_conic_segs(conic, distance, 0, conic.fP
ts[0], |
326 kMaxTValue, conic.fPts[2], p
tIndex); | 287 kMaxTValue, conic.fPts[2], p
tIndex); |
327 #endif | |
328 if (distance > prevD) { | 288 if (distance > prevD) { |
329 // we store the conic weight in our next point, followed by
the last 2 pts | 289 // we store the conic weight in our next point, followed by
the last 2 pts |
330 // thus to reconstitue a conic, you'd need to say | 290 // thus to reconstitue a conic, you'd need to say |
331 // SkConic(pts[0], pts[2], pts[3], weight = pts[1].fX) | 291 // SkConic(pts[0], pts[2], pts[3], weight = pts[1].fX) |
332 fPts.append()->set(conic.fW, 0); | 292 fPts.append()->set(conic.fW, 0); |
333 fPts.append(2, pts + 1); | 293 fPts.append(2, pts + 1); |
334 ptIndex += 3; | 294 ptIndex += 3; |
335 } | 295 } |
336 } break; | 296 } break; |
337 | 297 |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
470 | 430 |
471 if (0 == startT) { | 431 if (0 == startT) { |
472 if (SK_Scalar1 == stopT) { | 432 if (SK_Scalar1 == stopT) { |
473 dst->conicTo(conic.fPts[1], conic.fPts[2], conic.fW); | 433 dst->conicTo(conic.fPts[1], conic.fPts[2], conic.fW); |
474 } else { | 434 } else { |
475 SkConic tmp[2]; | 435 SkConic tmp[2]; |
476 conic.chopAt(stopT, tmp); | 436 conic.chopAt(stopT, tmp); |
477 dst->conicTo(tmp[0].fPts[1], tmp[0].fPts[2], tmp[0].fW); | 437 dst->conicTo(tmp[0].fPts[1], tmp[0].fPts[2], tmp[0].fW); |
478 } | 438 } |
479 } else { | 439 } else { |
480 #ifdef SK_SUPPORT_LEGACY_CONIC_MEASURE | |
481 SkConic tmp1[2]; | |
482 conic.chopAt(startT, tmp1); | |
483 if (SK_Scalar1 == stopT) { | |
484 dst->conicTo(tmp1[1].fPts[1], tmp1[1].fPts[2], tmp1[1].fW); | |
485 } else { | |
486 SkConic tmp2[2]; | |
487 tmp1[1].chopAt((stopT - startT) / (SK_Scalar1 - startT), tmp
2); | |
488 dst->conicTo(tmp2[0].fPts[1], tmp2[0].fPts[2], tmp2[0].fW); | |
489 } | |
490 #else | |
491 if (SK_Scalar1 == stopT) { | 440 if (SK_Scalar1 == stopT) { |
492 SkConic tmp1[2]; | 441 SkConic tmp1[2]; |
493 conic.chopAt(startT, tmp1); | 442 conic.chopAt(startT, tmp1); |
494 dst->conicTo(tmp1[1].fPts[1], tmp1[1].fPts[2], tmp1[1].fW); | 443 dst->conicTo(tmp1[1].fPts[1], tmp1[1].fPts[2], tmp1[1].fW); |
495 } else { | 444 } else { |
496 SkConic tmp; | 445 SkConic tmp; |
497 conic.chopAt(startT, stopT, &tmp); | 446 conic.chopAt(startT, stopT, &tmp); |
498 dst->conicTo(tmp.fPts[1], tmp.fPts[2], tmp.fW); | 447 dst->conicTo(tmp.fPts[1], tmp.fPts[2], tmp.fW); |
499 } | 448 } |
500 #endif | |
501 } | 449 } |
502 } break; | 450 } break; |
503 case kCubic_SegType: | 451 case kCubic_SegType: |
504 if (0 == startT) { | 452 if (0 == startT) { |
505 if (SK_Scalar1 == stopT) { | 453 if (SK_Scalar1 == stopT) { |
506 dst->cubicTo(pts[1], pts[2], pts[3]); | 454 dst->cubicTo(pts[1], pts[2], pts[3]); |
507 } else { | 455 } else { |
508 SkChopCubicAt(pts, tmp0, stopT); | 456 SkChopCubicAt(pts, tmp0, stopT); |
509 dst->cubicTo(tmp0[1], tmp0[2], tmp0[3]); | 457 dst->cubicTo(tmp0[1], tmp0[2], tmp0[3]); |
510 } | 458 } |
(...skipping 19 matching lines...) Expand all Loading... |
530 SkPathMeasure::SkPathMeasure() { | 478 SkPathMeasure::SkPathMeasure() { |
531 fPath = nullptr; | 479 fPath = nullptr; |
532 fTolerance = CHEAP_DIST_LIMIT; | 480 fTolerance = CHEAP_DIST_LIMIT; |
533 fLength = -1; // signal we need to compute it | 481 fLength = -1; // signal we need to compute it |
534 fForceClosed = false; | 482 fForceClosed = false; |
535 fFirstPtIndex = -1; | 483 fFirstPtIndex = -1; |
536 } | 484 } |
537 | 485 |
538 SkPathMeasure::SkPathMeasure(const SkPath& path, bool forceClosed, SkScalar resS
cale) { | 486 SkPathMeasure::SkPathMeasure(const SkPath& path, bool forceClosed, SkScalar resS
cale) { |
539 fPath = &path; | 487 fPath = &path; |
540 #ifdef SK_SUPPORT_LEGACY_DASH_MEASURE | |
541 fTolerance = CHEAP_DIST_LIMIT; | |
542 #else | |
543 fTolerance = CHEAP_DIST_LIMIT * SkScalarInvert(resScale); | 488 fTolerance = CHEAP_DIST_LIMIT * SkScalarInvert(resScale); |
544 #endif | |
545 fLength = -1; // signal we need to compute it | 489 fLength = -1; // signal we need to compute it |
546 fForceClosed = forceClosed; | 490 fForceClosed = forceClosed; |
547 fFirstPtIndex = -1; | 491 fFirstPtIndex = -1; |
548 | 492 |
549 fIter.setPath(path, forceClosed); | 493 fIter.setPath(path, forceClosed); |
550 } | 494 } |
551 | 495 |
552 SkPathMeasure::~SkPathMeasure() {} | 496 SkPathMeasure::~SkPathMeasure() {} |
553 | 497 |
554 /** Assign a new path, or null to have none. | 498 /** Assign a new path, or null to have none. |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
756 | 700 |
757 for (int i = 0; i < fSegments.count(); i++) { | 701 for (int i = 0; i < fSegments.count(); i++) { |
758 const Segment* seg = &fSegments[i]; | 702 const Segment* seg = &fSegments[i]; |
759 SkDebugf("pathmeas: seg[%d] distance=%g, point=%d, t=%g, type=%d\n", | 703 SkDebugf("pathmeas: seg[%d] distance=%g, point=%d, t=%g, type=%d\n", |
760 i, seg->fDistance, seg->fPtIndex, seg->getScalarT(), | 704 i, seg->fDistance, seg->fPtIndex, seg->getScalarT(), |
761 seg->fType); | 705 seg->fType); |
762 } | 706 } |
763 } | 707 } |
764 | 708 |
765 #endif | 709 #endif |
OLD | NEW |