| Index: src/core/SkPathMeasure.cpp
|
| diff --git a/src/core/SkPathMeasure.cpp b/src/core/SkPathMeasure.cpp
|
| index 48f7571c0749861aa723306a782a8205228f459d..9d1607532655ddea061104da37b07d683ddb666b 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) {
|
|
|