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