11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2008 The Android Open Source Project
40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPathMeasure.h"
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkGeometry.h"
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPath.h"
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTSearch.h"
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// these must be 0,1,2 since they are in our 2-bit field
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectenum {
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kLine_SegType,
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kQuad_SegType,
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kCubic_SegType
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define kMaxTValue  32767
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline SkScalar tValue2Scalar(int t) {
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((unsigned)t <= kMaxTValue);
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_SCALAR_IS_FLOAT
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return t * 3.05185e-5f; // t / 32767
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else
300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return (t + (t >> 14)) << 1;
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkPathMeasure::Segment::getScalarT() const {
350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return tValue2Scalar(fTValue);
360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectconst SkPathMeasure::Segment* SkPathMeasure::NextSegment(const Segment* seg) {
390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned ptIndex = seg->fPtIndex;
400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    do {
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        ++seg;
430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } while (seg->fPtIndex == ptIndex);
440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return seg;
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline int tspan_big_enough(int tspan) {
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((unsigned)tspan <= kMaxTValue);
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return tspan >> 10;
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if 0
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline bool tangents_too_curvy(const SkVector& tan0, SkVector& tan1) {
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static const SkScalar kFlatEnoughTangentDotProd = SK_Scalar1 * 99 / 100;
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(kFlatEnoughTangentDotProd > 0 &&
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project             kFlatEnoughTangentDotProd < SK_Scalar1);
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkPoint::DotProduct(tan0, tan1) < kFlatEnoughTangentDotProd;
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// can't use tangents, since we need [0..1..................2] to be seen
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// as definitely not a line (it is when drawn, but not parametrically)
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// so we compare midpoints
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define CHEAP_DIST_LIMIT    (SK_Scalar1/2)  // just made this value up
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic bool quad_too_curvy(const SkPoint pts[3]) {
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // diff = (a/4 + b/2 + c/4) - (a/2 + c/2)
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // diff = -a/4 + b/2 - c/4
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar dx = SkScalarHalf(pts[1].fX) -
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        SkScalarHalf(SkScalarHalf(pts[0].fX + pts[2].fX));
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar dy = SkScalarHalf(pts[1].fY) -
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        SkScalarHalf(SkScalarHalf(pts[0].fY + pts[2].fY));
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar dist = SkMaxScalar(SkScalarAbs(dx), SkScalarAbs(dy));
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return dist > CHEAP_DIST_LIMIT;
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic bool cheap_dist_exceeds_limit(const SkPoint& pt,
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                     SkScalar x, SkScalar y) {
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar dist = SkMaxScalar(SkScalarAbs(x - pt.fX), SkScalarAbs(y - pt.fY));
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // just made up the 1/2
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return dist > CHEAP_DIST_LIMIT;
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic bool cubic_too_curvy(const SkPoint pts[4]) {
900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return  cheap_dist_exceeds_limit(pts[1],
910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                         SkScalarInterp(pts[0].fX, pts[3].fX, SK_Scalar1/3),
920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                         SkScalarInterp(pts[0].fY, pts[3].fY, SK_Scalar1/3))
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                         ||
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            cheap_dist_exceeds_limit(pts[2],
950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                         SkScalarInterp(pts[0].fX, pts[3].fX, SK_Scalar1*2/3),
960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                         SkScalarInterp(pts[0].fY, pts[3].fY, SK_Scalar1*2/3));
970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkPathMeasure::compute_quad_segs(const SkPoint pts[3],
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                          SkScalar distance, int mint, int maxt, int ptIndex) {
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (tspan_big_enough(maxt - mint) && quad_too_curvy(pts)) {
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkPoint tmp[5];
1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int     halft = (mint + maxt) >> 1;
1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkChopQuadAtHalf(pts, tmp);
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        distance = this->compute_quad_segs(tmp, distance, mint, halft, ptIndex);
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        distance = this->compute_quad_segs(&tmp[2], distance, halft, maxt, ptIndex);
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } else {
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScalar d = SkPoint::Distance(pts[0], pts[2]);
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(d >= 0);
1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (!SkScalarNearlyZero(d)) {
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            distance += d;
1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            Segment* seg = fSegments.append();
1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            seg->fDistance = distance;
1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            seg->fPtIndex = ptIndex;
1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            seg->fType = kQuad_SegType;
1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            seg->fTValue = maxt;
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return distance;
1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkPathMeasure::compute_cubic_segs(const SkPoint pts[4],
1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                           SkScalar distance, int mint, int maxt, int ptIndex) {
1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (tspan_big_enough(maxt - mint) && cubic_too_curvy(pts)) {
1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkPoint tmp[7];
1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int     halft = (mint + maxt) >> 1;
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkChopCubicAtHalf(pts, tmp);
1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        distance = this->compute_cubic_segs(tmp, distance, mint, halft, ptIndex);
1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        distance = this->compute_cubic_segs(&tmp[3], distance, halft, maxt, ptIndex);
1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } else {
1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScalar d = SkPoint::Distance(pts[0], pts[3]);
1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(d >= 0);
1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (!SkScalarNearlyZero(d)) {
1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            distance += d;
1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            Segment* seg = fSegments.append();
1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            seg->fDistance = distance;
1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            seg->fPtIndex = ptIndex;
1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            seg->fType = kCubic_SegType;
1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            seg->fTValue = maxt;
1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return distance;
1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathMeasure::buildSegments() {
1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPoint         pts[4];
1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int             ptIndex = fFirstPtIndex;
1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar        d, distance = 0;
1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool            isClosed = fForceClosed;
1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool            firstMoveTo = ptIndex < 0;
1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    Segment*        seg;
1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fSegments.reset();
1564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    bool done = false;
1574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    do {
1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        switch (fIter.next(pts)) {
1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            case SkPath::kMove_Verb:
1604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                ptIndex += 1;
1614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                fPts.append(1, pts);
1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (!firstMoveTo) {
1634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    done = true;
1644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                    break;
1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
1664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                firstMoveTo = false;
1674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                break;
1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            case SkPath::kLine_Verb:
1700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                d = SkPoint::Distance(pts[0], pts[1]);
1710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(d >= 0);
1724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                distance += d;
1734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                seg = fSegments.append();
1744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                seg->fDistance = distance;
1754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                seg->fPtIndex = ptIndex;
1764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                seg->fType = kLine_SegType;
1774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                seg->fTValue = kMaxTValue;
1784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                fPts.append(1, pts + 1);
1794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                ptIndex++;
1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
1810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            case SkPath::kQuad_Verb:
1830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                distance = this->compute_quad_segs(pts, distance, 0,
1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                                   kMaxTValue, ptIndex);
1854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                fPts.append(2, pts + 1);
1860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                ptIndex += 2;
1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            case SkPath::kCubic_Verb:
1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                distance = this->compute_cubic_segs(pts, distance, 0,
1910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                                    kMaxTValue, ptIndex);
1924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                fPts.append(3, pts + 1);
1930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                ptIndex += 3;
1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            case SkPath::kClose_Verb:
1970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                isClosed = true;
1980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
1990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            case SkPath::kDone_Verb:
2014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                done = true;
2024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                break;
2030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
2044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    } while (!done);
2054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
2060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fLength = distance;
2070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fIsClosed = isClosed;
2084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fFirstPtIndex = ptIndex;
2090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
2110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
2120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const Segment* seg = fSegments.begin();
2130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const Segment* stop = fSegments.end();
2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        unsigned        ptIndex = 0;
2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScalar        distance = 0;
2160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        while (seg < stop) {
2180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(seg->fDistance > distance);
2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(seg->fPtIndex >= ptIndex);
2200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(seg->fTValue > 0);
2210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const Segment* s = seg;
2230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            while (s < stop - 1 && s[0].fPtIndex == s[1].fPtIndex) {
2240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(s[0].fType == s[1].fType);
2250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(s[0].fTValue < s[1].fTValue);
2260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                s += 1;
2270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
2280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            distance = seg->fDistance;
2300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            ptIndex = seg->fPtIndex;
2310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            seg += 1;
2320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
2330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    //  SkDebugf("\n");
2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
2360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic void compute_pos_tan(const SkTDArray<SkPoint>& segmentPts, int ptIndex,
2390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    int segType, SkScalar t, SkPoint* pos, SkVector* tangent) {
2404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    const SkPoint*  pts = &segmentPts[ptIndex];
2410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    switch (segType) {
2430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kLine_SegType:
2440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (pos) {
2454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                pos->set(SkScalarInterp(pts[0].fX, pts[1].fX, t),
2464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                        SkScalarInterp(pts[0].fY, pts[1].fY, t));
2470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
2480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (tangent) {
2494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                tangent->setNormalize(pts[1].fX - pts[0].fX, pts[1].fY - pts[0].fY);
2500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
2510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kQuad_SegType:
2530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkEvalQuadAt(pts, t, pos, tangent);
2540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (tangent) {
2550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                tangent->normalize();
2560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
2570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kCubic_SegType:
2590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkEvalCubicAt(pts, t, pos, tangent, NULL);
2600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (tangent) {
2610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                tangent->normalize();
2620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
2630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        default:
2651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkDEBUGFAIL("unknown segType");
2660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic void seg_to(const SkTDArray<SkPoint>& segmentPts, int ptIndex,
2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                   int segType, SkScalar startT, SkScalar stopT, SkPath* dst) {
2710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(startT >= 0 && startT <= SK_Scalar1);
2720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(stopT >= 0 && stopT <= SK_Scalar1);
2730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(startT <= stopT);
2740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (SkScalarNearlyZero(stopT - startT)) {
2760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return;
2770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    const SkPoint*  pts = &segmentPts[ptIndex];
2800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPoint         tmp0[7], tmp1[7];
2810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    switch (segType) {
2830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kLine_SegType:
2840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (stopT == kMaxTValue) {
2854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                dst->lineTo(pts[1]);
2860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } else {
2874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                dst->lineTo(SkScalarInterp(pts[0].fX, pts[1].fX, stopT),
2884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                            SkScalarInterp(pts[0].fY, pts[1].fY, stopT));
2890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
2900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kQuad_SegType:
2920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (startT == 0) {
2930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (stopT == SK_Scalar1) {
2940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    dst->quadTo(pts[1], pts[2]);
2950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                } else {
2960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkChopQuadAt(pts, tmp0, stopT);
2970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    dst->quadTo(tmp0[1], tmp0[2]);
2980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
2990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } else {
3000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkChopQuadAt(pts, tmp0, startT);
3010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (stopT == SK_Scalar1) {
3020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    dst->quadTo(tmp0[3], tmp0[4]);
3030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                } else {
3040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkChopQuadAt(&tmp0[2], tmp1, SkScalarDiv(stopT - startT,
3050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                                         SK_Scalar1 - startT));
3060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    dst->quadTo(tmp1[1], tmp1[2]);
3070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
3080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
3090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
3100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kCubic_SegType:
3110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (startT == 0) {
3120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (stopT == SK_Scalar1) {
3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    dst->cubicTo(pts[1], pts[2], pts[3]);
3140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                } else {
3150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkChopCubicAt(pts, tmp0, stopT);
3160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    dst->cubicTo(tmp0[1], tmp0[2], tmp0[3]);
3170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
3180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } else {
3190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkChopCubicAt(pts, tmp0, startT);
3200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (stopT == SK_Scalar1) {
3210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    dst->cubicTo(tmp0[4], tmp0[5], tmp0[6]);
3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                } else {
3230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkChopCubicAt(&tmp0[3], tmp1, SkScalarDiv(stopT - startT,
3240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                                        SK_Scalar1 - startT));
3250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    dst->cubicTo(tmp1[1], tmp1[2], tmp1[3]);
3260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
3270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
3280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
3290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        default:
3301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkDEBUGFAIL("unknown segType");
3310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            sk_throw();
3320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project////////////////////////////////////////////////////////////////////////////////
3360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project////////////////////////////////////////////////////////////////////////////////
3370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPathMeasure::SkPathMeasure() {
3390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPath = NULL;
3400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fLength = -1;   // signal we need to compute it
3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fForceClosed = false;
3420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fFirstPtIndex = -1;
3430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPathMeasure::SkPathMeasure(const SkPath& path, bool forceClosed) {
3460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPath = &path;
3470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fLength = -1;   // signal we need to compute it
3480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fForceClosed = forceClosed;
3490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fFirstPtIndex = -1;
3500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fIter.setPath(path, forceClosed);
3520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPathMeasure::~SkPathMeasure() {}
3550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Assign a new path, or null to have none.
3570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
3580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathMeasure::setPath(const SkPath* path, bool forceClosed) {
3590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPath = path;
3600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fLength = -1;   // signal we need to compute it
3610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fForceClosed = forceClosed;
3620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fFirstPtIndex = -1;
3630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (path) {
3650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fIter.setPath(*path, forceClosed);
3660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fSegments.reset();
3684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    fPts.reset();
3690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkPathMeasure::getLength() {
3720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fPath == NULL) {
3730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
3740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fLength < 0) {
3760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        this->buildSegments();
3770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(fLength >= 0);
3790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return fLength;
3800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectconst SkPathMeasure::Segment* SkPathMeasure::distanceToSegment(
3830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                            SkScalar distance, SkScalar* t) {
3840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDEBUGCODE(SkScalar length = ) this->getLength();
3850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(distance >= 0 && distance <= length);
3860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const Segment*  seg = fSegments.begin();
3880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int             count = fSegments.count();
3890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int index = SkTSearch<SkScalar>(&seg->fDistance, count, distance,
3910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                    sizeof(Segment));
3920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // don't care if we hit an exact match or not, so we xor index if it is negative
3930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    index ^= (index >> 31);
3940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    seg = &seg[index];
3950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // now interpolate t-values with the prev segment (if possible)
3970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar    startT = 0, startD = 0;
3980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // check if the prev segment is legal, and references the same set of points
3990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (index > 0) {
4000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        startD = seg[-1].fDistance;
4010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (seg[-1].fPtIndex == seg->fPtIndex) {
4020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(seg[-1].fType == seg->fType);
4030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            startT = seg[-1].getScalarT();
4040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
4050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(seg->getScalarT() > startT);
4080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(distance >= startD);
4090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(seg->fDistance > startD);
4100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *t = startT + SkScalarMulDiv(seg->getScalarT() - startT,
4120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                 distance - startD,
4130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                 seg->fDistance - startD);
4140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return seg;
4150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPathMeasure::getPosTan(SkScalar distance, SkPoint* pos,
4180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                              SkVector* tangent) {
4190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(fPath);
4200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fPath == NULL) {
4210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
4220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar    length = this->getLength(); // call this to force computing it
4250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int         count = fSegments.count();
4260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (count == 0 || length == 0) {
4284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        return false;
4290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // pin the distance to a legal range
4320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (distance < 0) {
4330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        distance = 0;
4340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } else if (distance > length) {
4350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        distance = length;
4360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar        t;
4390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const Segment*  seg = this->distanceToSegment(distance, &t);
4400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    compute_pos_tan(fPts, seg->fPtIndex, seg->fType, t, pos, tangent);
4420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return true;
4430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPathMeasure::getMatrix(SkScalar distance, SkMatrix* matrix,
4460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                              MatrixFlags flags) {
4470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPoint     position;
4480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkVector    tangent;
4490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (this->getPosTan(distance, &position, &tangent)) {
4510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (matrix) {
4520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (flags & kGetTangent_MatrixFlag) {
4530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                matrix->setSinCos(tangent.fY, tangent.fX, 0, 0);
4540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } else {
4550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                matrix->reset();
4560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
4570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (flags & kGetPosition_MatrixFlag) {
4580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                matrix->postTranslate(position.fX, position.fY);
4590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
4600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
4610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;
4620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return false;
4640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPathMeasure::getSegment(SkScalar startD, SkScalar stopD, SkPath* dst,
4670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                               bool startWithMoveTo) {
4680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(dst);
4690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar length = this->getLength();    // ensure we have built our segments
4710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (startD < 0) {
4730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        startD = 0;
4740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (stopD > length) {
4760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        stopD = length;
4770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (startD >= stopD) {
4790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
4800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkPoint  p;
4830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar startT, stopT;
4840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const Segment* seg = this->distanceToSegment(startD, &startT);
4850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const Segment* stopSeg = this->distanceToSegment(stopD, &stopT);
4860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(seg <= stopSeg);
4870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (startWithMoveTo) {
4894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        compute_pos_tan(fPts, seg->fPtIndex, seg->fType, startT, &p, NULL);
4900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        dst->moveTo(p);
4910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (seg->fPtIndex == stopSeg->fPtIndex) {
4944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        seg_to(fPts, seg->fPtIndex, seg->fType, startT, stopT, dst);
4950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } else {
4960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        do {
4974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            seg_to(fPts, seg->fPtIndex, seg->fType, startT, SK_Scalar1, dst);
4980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            seg = SkPathMeasure::NextSegment(seg);
4990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            startT = 0;
5000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } while (seg->fPtIndex < stopSeg->fPtIndex);
5014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        seg_to(fPts, seg->fPtIndex, seg->fType, 0, stopT, dst);
5020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return true;
5040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPathMeasure::isClosed() {
5070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    (void)this->getLength();
5080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return fIsClosed;
5090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Move to the next contour in the path. Return true if one exists, or false if
5120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    we're done with the path.
5130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/
5140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPathMeasure::nextContour() {
5150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fLength = -1;
5160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return this->getLength() > 0;
5170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
5200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project///////////////////////////////////////////////////////////////////////////////
5210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
5230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathMeasure::dump() {
5250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDebugf("pathmeas: length=%g, segs=%d\n", fLength, fSegments.count());
5260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    for (int i = 0; i < fSegments.count(); i++) {
5280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const Segment* seg = &fSegments[i];
5290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkDebugf("pathmeas: seg[%d] distance=%g, point=%d, t=%g, type=%d\n",
5300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                i, seg->fDistance, seg->fPtIndex, seg->getScalarT(),
5310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                 seg->fType);
5320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
5330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
536