diff options
author | reed <reed@google.com> | 2014-12-17 08:21:04 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-12-17 08:21:05 -0800 |
commit | 220f926d9d4b38a9018c922c095847bbd261f583 (patch) | |
tree | efce65017941c05999dffbc84c243b0fd14e8f77 /src/core/SkPathMeasure.cpp | |
parent | ed9f7a9220db8484af2216bd66701dc1043abb4b (diff) |
use conics
BUG=skia:
Review URL: https://codereview.chromium.org/455043002
Diffstat (limited to 'src/core/SkPathMeasure.cpp')
-rw-r--r-- | src/core/SkPathMeasure.cpp | 83 |
1 files changed, 73 insertions, 10 deletions
diff --git a/src/core/SkPathMeasure.cpp b/src/core/SkPathMeasure.cpp index 48f7571c07..9d16075326 100644 --- a/src/core/SkPathMeasure.cpp +++ b/src/core/SkPathMeasure.cpp @@ -12,11 +12,12 @@ #include "SkPath.h" #include "SkTSearch.h" -// these must be 0,1,2 since they are in our 2-bit field +// these must be 0,1,2,3 since they are in our 2-bit field enum { kLine_SegType, kQuad_SegType, - kCubic_SegType + kCubic_SegType, + kConic_SegType, }; #define kMaxTValue 32767 @@ -104,6 +105,30 @@ SkScalar SkPathMeasure::compute_quad_segs(const SkPoint pts[3], return distance; } +SkScalar SkPathMeasure::compute_conic_segs(const SkConic& conic, + SkScalar distance, int mint, int maxt, int ptIndex) { + if (tspan_big_enough(maxt - mint) && quad_too_curvy(conic.fPts)) { + SkConic tmp[2]; + conic.chop(tmp); + + int halft = (mint + maxt) >> 1; + distance = this->compute_conic_segs(tmp[0], distance, mint, halft, ptIndex); + distance = this->compute_conic_segs(tmp[1], distance, halft, maxt, ptIndex); + } else { + SkScalar d = SkPoint::Distance(conic.fPts[0], conic.fPts[2]); + SkScalar prevD = distance; + distance += d; + if (distance > prevD) { + Segment* seg = fSegments.append(); + seg->fDistance = distance; + seg->fPtIndex = ptIndex; + seg->fType = kConic_SegType; + seg->fTValue = maxt; + } + } + return distance; +} + SkScalar SkPathMeasure::compute_cubic_segs(const SkPoint pts[4], SkScalar distance, int mint, int maxt, int ptIndex) { if (tspan_big_enough(maxt - mint) && cubic_too_curvy(pts)) { @@ -147,9 +172,6 @@ void SkPathMeasure::buildSegments() { bool done = false; do { switch (fIter.next(pts)) { - case SkPath::kConic_Verb: - SkASSERT(0); - break; case SkPath::kMove_Verb: ptIndex += 1; fPts.append(1, pts); @@ -178,18 +200,30 @@ void SkPathMeasure::buildSegments() { case SkPath::kQuad_Verb: { SkScalar prevD = distance; - distance = this->compute_quad_segs(pts, distance, 0, - kMaxTValue, ptIndex); + distance = this->compute_quad_segs(pts, distance, 0, kMaxTValue, ptIndex); if (distance > prevD) { fPts.append(2, pts + 1); ptIndex += 2; } } break; + case SkPath::kConic_Verb: { + const SkConic conic(pts, fIter.conicWeight()); + SkScalar prevD = distance; + distance = this->compute_conic_segs(conic, distance, 0, kMaxTValue, ptIndex); + if (distance > prevD) { + // we store the conic weight in our next point, followed by the last 2 pts + // thus to reconstitue a conic, you'd need to say + // SkConic(pts[0], pts[2], pts[3], weight = pts[1].fX) + fPts.append()->set(conic.fW, 0); + fPts.append(2, pts + 1); + ptIndex += 3; + } + } break; + case SkPath::kCubic_Verb: { SkScalar prevD = distance; - distance = this->compute_cubic_segs(pts, distance, 0, - kMaxTValue, ptIndex); + distance = this->compute_cubic_segs(pts, distance, 0, kMaxTValue, ptIndex); if (distance > prevD) { fPts.append(3, pts + 1); ptIndex += 3; @@ -256,6 +290,12 @@ static void compute_pos_tan(const SkPoint pts[], int segType, tangent->normalize(); } break; + case kConic_SegType: { + SkConic(pts[0], pts[2], pts[3], pts[1].fX).evalAt(t, pos, tangent); + if (tangent) { + tangent->normalize(); + } + } break; case kCubic_SegType: SkEvalCubicAt(pts, t, pos, tangent, NULL); if (tangent) { @@ -277,7 +317,7 @@ static void seg_to(const SkPoint pts[], int segType, return; // should we report this, to undo a moveTo? } - SkPoint tmp0[7], tmp1[7]; + SkPoint tmp0[7], tmp1[7]; switch (segType) { case kLine_SegType: @@ -307,6 +347,29 @@ static void seg_to(const SkPoint pts[], int segType, } } break; + case kConic_SegType: { + SkConic conic(pts[0], pts[2], pts[3], pts[1].fX); + + if (0 == startT) { + if (SK_Scalar1 == stopT) { + dst->conicTo(conic.fPts[1], conic.fPts[2], conic.fW); + } else { + SkConic tmp[2]; + conic.chopAt(stopT, tmp); + dst->conicTo(tmp[0].fPts[1], tmp[0].fPts[2], tmp[0].fW); + } + } else { + SkConic tmp1[2]; + conic.chopAt(startT, tmp1); + if (SK_Scalar1 == stopT) { + dst->conicTo(tmp1[1].fPts[1], tmp1[1].fPts[2], tmp1[1].fW); + } else { + SkConic tmp2[2]; + tmp1[1].chopAt((stopT - startT) / (SK_Scalar1 - startT), tmp2); + dst->conicTo(tmp2[0].fPts[1], tmp2[0].fPts[2], tmp2[0].fW); + } + } + } break; case kCubic_SegType: if (0 == startT) { if (SK_Scalar1 == stopT) { |