LCOV - code coverage report
Current view: directory - gfx/skia/src/core - SkPathMeasure.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 289 0 0.0 %
Date: 2012-06-02 Functions: 25 0 0.0 %

       1                 : 
       2                 : /*
       3                 :  * Copyright 2008 The Android Open Source Project
       4                 :  *
       5                 :  * Use of this source code is governed by a BSD-style license that can be
       6                 :  * found in the LICENSE file.
       7                 :  */
       8                 : 
       9                 : 
      10                 : #include "SkPathMeasure.h"
      11                 : #include "SkGeometry.h"
      12                 : #include "SkPath.h"
      13                 : #include "SkTSearch.h"
      14                 : 
      15                 : // these must be 0,1,2 since they are in our 2-bit field
      16                 : enum {
      17                 :     kLine_SegType,
      18                 :     kCloseLine_SegType,
      19                 :     kQuad_SegType,
      20                 :     kCubic_SegType
      21                 : };
      22                 : 
      23                 : #define kMaxTValue  32767
      24                 : 
      25               0 : static inline SkScalar tValue2Scalar(int t) {
      26               0 :     SkASSERT((unsigned)t <= kMaxTValue);
      27                 : 
      28                 : #ifdef SK_SCALAR_IS_FLOAT
      29               0 :     return t * 3.05185e-5f; // t / 32767
      30                 : #else
      31                 :     return (t + (t >> 14)) << 1;
      32                 : #endif
      33                 : }
      34                 : 
      35               0 : SkScalar SkPathMeasure::Segment::getScalarT() const {
      36               0 :     return tValue2Scalar(fTValue);
      37                 : }
      38                 : 
      39               0 : const SkPathMeasure::Segment* SkPathMeasure::NextSegment(const Segment* seg) {
      40               0 :     unsigned ptIndex = seg->fPtIndex;
      41                 : 
      42               0 :     do {
      43               0 :         ++seg;
      44                 :     } while (seg->fPtIndex == ptIndex);
      45               0 :     return seg;
      46                 : }
      47                 : 
      48                 : ///////////////////////////////////////////////////////////////////////////////
      49                 : 
      50               0 : static inline int tspan_big_enough(int tspan) {
      51               0 :     SkASSERT((unsigned)tspan <= kMaxTValue);
      52               0 :     return tspan >> 10;
      53                 : }
      54                 : 
      55                 : #if 0
      56                 : static inline bool tangents_too_curvy(const SkVector& tan0, SkVector& tan1) {
      57                 :     static const SkScalar kFlatEnoughTangentDotProd = SK_Scalar1 * 99 / 100;
      58                 : 
      59                 :     SkASSERT(kFlatEnoughTangentDotProd > 0 &&
      60                 :              kFlatEnoughTangentDotProd < SK_Scalar1);
      61                 : 
      62                 :     return SkPoint::DotProduct(tan0, tan1) < kFlatEnoughTangentDotProd;
      63                 : }
      64                 : #endif
      65                 : 
      66                 : // can't use tangents, since we need [0..1..................2] to be seen
      67                 : // as definitely not a line (it is when drawn, but not parametrically)
      68                 : // so we compare midpoints
      69                 : #define CHEAP_DIST_LIMIT    (SK_Scalar1/2)  // just made this value up
      70                 : 
      71               0 : static bool quad_too_curvy(const SkPoint pts[3]) {
      72                 :     // diff = (a/4 + b/2 + c/4) - (a/2 + c/2)
      73                 :     // diff = -a/4 + b/2 - c/4
      74               0 :     SkScalar dx = SkScalarHalf(pts[1].fX) -
      75               0 :                         SkScalarHalf(SkScalarHalf(pts[0].fX + pts[2].fX));
      76               0 :     SkScalar dy = SkScalarHalf(pts[1].fY) -
      77               0 :                         SkScalarHalf(SkScalarHalf(pts[0].fY + pts[2].fY));
      78                 : 
      79               0 :     SkScalar dist = SkMaxScalar(SkScalarAbs(dx), SkScalarAbs(dy));
      80               0 :     return dist > CHEAP_DIST_LIMIT;
      81                 : }
      82                 : 
      83               0 : static bool cheap_dist_exceeds_limit(const SkPoint& pt,
      84                 :                                      SkScalar x, SkScalar y) {
      85               0 :     SkScalar dist = SkMaxScalar(SkScalarAbs(x - pt.fX), SkScalarAbs(y - pt.fY));
      86                 :     // just made up the 1/2
      87               0 :     return dist > CHEAP_DIST_LIMIT;
      88                 : }
      89                 : 
      90               0 : static bool cubic_too_curvy(const SkPoint pts[4]) {
      91               0 :     return  cheap_dist_exceeds_limit(pts[1],
      92               0 :                          SkScalarInterp(pts[0].fX, pts[3].fX, SK_Scalar1/3),
      93               0 :                          SkScalarInterp(pts[0].fY, pts[3].fY, SK_Scalar1/3))
      94                 :                          ||
      95               0 :             cheap_dist_exceeds_limit(pts[2],
      96               0 :                          SkScalarInterp(pts[0].fX, pts[3].fX, SK_Scalar1*2/3),
      97               0 :                          SkScalarInterp(pts[0].fY, pts[3].fY, SK_Scalar1*2/3));
      98                 : }
      99                 : 
     100               0 : SkScalar SkPathMeasure::compute_quad_segs(const SkPoint pts[3],
     101                 :                           SkScalar distance, int mint, int maxt, int ptIndex) {
     102               0 :     if (tspan_big_enough(maxt - mint) && quad_too_curvy(pts)) {
     103                 :         SkPoint tmp[5];
     104               0 :         int     halft = (mint + maxt) >> 1;
     105                 : 
     106               0 :         SkChopQuadAtHalf(pts, tmp);
     107               0 :         distance = this->compute_quad_segs(tmp, distance, mint, halft, ptIndex);
     108               0 :         distance = this->compute_quad_segs(&tmp[2], distance, halft, maxt, ptIndex);
     109                 :     } else {
     110               0 :         SkScalar d = SkPoint::Distance(pts[0], pts[2]);
     111               0 :         SkASSERT(d >= 0);
     112               0 :         if (!SkScalarNearlyZero(d)) {
     113               0 :             distance += d;
     114               0 :             Segment* seg = fSegments.append();
     115               0 :             seg->fDistance = distance;
     116               0 :             seg->fPtIndex = ptIndex;
     117               0 :             seg->fType = kQuad_SegType;
     118               0 :             seg->fTValue = maxt;
     119                 :         }
     120                 :     }
     121               0 :     return distance;
     122                 : }
     123                 : 
     124               0 : SkScalar SkPathMeasure::compute_cubic_segs(const SkPoint pts[4],
     125                 :                            SkScalar distance, int mint, int maxt, int ptIndex) {
     126               0 :     if (tspan_big_enough(maxt - mint) && cubic_too_curvy(pts)) {
     127                 :         SkPoint tmp[7];
     128               0 :         int     halft = (mint + maxt) >> 1;
     129                 : 
     130               0 :         SkChopCubicAtHalf(pts, tmp);
     131               0 :         distance = this->compute_cubic_segs(tmp, distance, mint, halft, ptIndex);
     132               0 :         distance = this->compute_cubic_segs(&tmp[3], distance, halft, maxt, ptIndex);
     133                 :     } else {
     134               0 :         SkScalar d = SkPoint::Distance(pts[0], pts[3]);
     135               0 :         SkASSERT(d >= 0);
     136               0 :         if (!SkScalarNearlyZero(d)) {
     137               0 :             distance += d;
     138               0 :             Segment* seg = fSegments.append();
     139               0 :             seg->fDistance = distance;
     140               0 :             seg->fPtIndex = ptIndex;
     141               0 :             seg->fType = kCubic_SegType;
     142               0 :             seg->fTValue = maxt;
     143                 :         }
     144                 :     }
     145               0 :     return distance;
     146                 : }
     147                 : 
     148               0 : void SkPathMeasure::buildSegments() {
     149                 :     SkPoint         pts[4];
     150               0 :     int             ptIndex = fFirstPtIndex;
     151               0 :     SkScalar        d, distance = 0;
     152               0 :     bool            isClosed = fForceClosed;
     153               0 :     bool            firstMoveTo = ptIndex < 0;
     154                 :     Segment*        seg;
     155                 : 
     156               0 :     fSegments.reset();
     157               0 :     for (;;) {
     158               0 :         switch (fIter.next(pts)) {
     159                 :             case SkPath::kMove_Verb:
     160               0 :                 if (!firstMoveTo) {
     161               0 :                     goto DONE;
     162                 :                 }
     163               0 :             ptIndex += 1;
     164               0 :             firstMoveTo = false;
     165               0 :             break;
     166                 : 
     167                 :             case SkPath::kLine_Verb:
     168               0 :                 d = SkPoint::Distance(pts[0], pts[1]);
     169               0 :                 SkASSERT(d >= 0);
     170               0 :                 if (!SkScalarNearlyZero(d)) {
     171               0 :                     distance += d;
     172               0 :                     seg = fSegments.append();
     173               0 :                     seg->fDistance = distance;
     174               0 :                     seg->fPtIndex = ptIndex;
     175               0 :                     seg->fType = fIter.isCloseLine() ?
     176               0 :                                     kCloseLine_SegType : kLine_SegType;
     177               0 :                     seg->fTValue = kMaxTValue;
     178                 :                 }
     179               0 :                 ptIndex += !fIter.isCloseLine();
     180               0 :                 break;
     181                 : 
     182                 :             case SkPath::kQuad_Verb:
     183                 :                 distance = this->compute_quad_segs(pts, distance, 0,
     184               0 :                                                    kMaxTValue, ptIndex);
     185               0 :                 ptIndex += 2;
     186               0 :                 break;
     187                 : 
     188                 :             case SkPath::kCubic_Verb:
     189                 :                 distance = this->compute_cubic_segs(pts, distance, 0,
     190               0 :                                                     kMaxTValue, ptIndex);
     191               0 :                 ptIndex += 3;
     192               0 :                 break;
     193                 : 
     194                 :             case SkPath::kClose_Verb:
     195               0 :                 isClosed = true;
     196               0 :                 break;
     197                 :                 
     198                 :             case SkPath::kDone_Verb:
     199               0 :                 goto DONE;
     200                 :         }
     201                 :     }
     202                 : DONE:
     203               0 :     fLength = distance;
     204               0 :     fIsClosed = isClosed;
     205               0 :     fFirstPtIndex = ptIndex + 1;
     206                 : 
     207                 : #ifdef SK_DEBUG
     208                 :     {
     209               0 :         const Segment* seg = fSegments.begin();
     210               0 :         const Segment* stop = fSegments.end();
     211               0 :         unsigned        ptIndex = 0;
     212               0 :         SkScalar        distance = 0;
     213                 : 
     214               0 :         while (seg < stop) {
     215               0 :             SkASSERT(seg->fDistance > distance);
     216               0 :             SkASSERT(seg->fPtIndex >= ptIndex);
     217               0 :             SkASSERT(seg->fTValue > 0);
     218                 : 
     219               0 :             const Segment* s = seg;
     220               0 :             while (s < stop - 1 && s[0].fPtIndex == s[1].fPtIndex) {
     221               0 :                 SkASSERT(s[0].fType == s[1].fType);
     222               0 :                 SkASSERT(s[0].fTValue < s[1].fTValue);
     223               0 :                 s += 1;
     224                 :             }
     225                 : 
     226               0 :             distance = seg->fDistance;
     227               0 :             ptIndex = seg->fPtIndex;
     228               0 :             seg += 1;
     229                 :         }
     230                 :     //  SkDebugf("\n");
     231                 :     }
     232                 : #endif
     233               0 : }
     234                 : 
     235                 : // marked as a friend in SkPath.h
     236               0 : const SkPoint* sk_get_path_points(const SkPath& path, int index) {
     237               0 :     return &path.fPts[index];
     238                 : }
     239                 : 
     240               0 : static void compute_pos_tan(const SkPath& path, int firstPtIndex, int ptIndex,
     241                 :                     int segType, SkScalar t, SkPoint* pos, SkVector* tangent) {
     242               0 :     const SkPoint*  pts = sk_get_path_points(path, ptIndex);
     243                 : 
     244               0 :     switch (segType) {
     245                 :         case kLine_SegType:
     246                 :         case kCloseLine_SegType: {
     247                 :             const SkPoint* endp = (segType == kLine_SegType) ?
     248                 :                                     &pts[1] :
     249               0 :                                     sk_get_path_points(path, firstPtIndex);
     250                 : 
     251               0 :             if (pos) {
     252                 :                 pos->set(SkScalarInterp(pts[0].fX, endp->fX, t),
     253               0 :                         SkScalarInterp(pts[0].fY, endp->fY, t));
     254                 :             }
     255               0 :             if (tangent) {
     256               0 :                 tangent->setNormalize(endp->fX - pts[0].fX, endp->fY - pts[0].fY);
     257                 :             }
     258               0 :             break;
     259                 :         }
     260                 :         case kQuad_SegType:
     261               0 :             SkEvalQuadAt(pts, t, pos, tangent);
     262               0 :             if (tangent) {
     263               0 :                 tangent->normalize();
     264                 :             }
     265               0 :             break;
     266                 :         case kCubic_SegType:
     267               0 :             SkEvalCubicAt(pts, t, pos, tangent, NULL);
     268               0 :             if (tangent) {
     269               0 :                 tangent->normalize();
     270                 :             }
     271               0 :             break;
     272                 :         default:
     273               0 :             SkDEBUGFAIL("unknown segType");
     274                 :     }
     275               0 : }
     276                 : 
     277               0 : static void seg_to(const SkPath& src, int firstPtIndex, int ptIndex,
     278                 :                    int segType, SkScalar startT, SkScalar stopT, SkPath* dst) {
     279               0 :     SkASSERT(startT >= 0 && startT <= SK_Scalar1);
     280               0 :     SkASSERT(stopT >= 0 && stopT <= SK_Scalar1);
     281               0 :     SkASSERT(startT <= stopT);
     282                 : 
     283               0 :     if (SkScalarNearlyZero(stopT - startT)) {
     284               0 :         return;
     285                 :     }
     286                 : 
     287               0 :     const SkPoint*  pts = sk_get_path_points(src, ptIndex);
     288                 :     SkPoint         tmp0[7], tmp1[7];
     289                 : 
     290               0 :     switch (segType) {
     291                 :         case kLine_SegType:
     292                 :         case kCloseLine_SegType: {
     293                 :             const SkPoint* endp = (segType == kLine_SegType) ?
     294                 :                                     &pts[1] :
     295               0 :                                     sk_get_path_points(src, firstPtIndex);
     296                 : 
     297               0 :             if (stopT == kMaxTValue) {
     298               0 :                 dst->lineTo(*endp);
     299                 :             } else {
     300                 :                 dst->lineTo(SkScalarInterp(pts[0].fX, endp->fX, stopT),
     301               0 :                             SkScalarInterp(pts[0].fY, endp->fY, stopT));
     302                 :             }
     303               0 :             break;
     304                 :         }
     305                 :         case kQuad_SegType:
     306               0 :             if (startT == 0) {
     307               0 :                 if (stopT == SK_Scalar1) {
     308               0 :                     dst->quadTo(pts[1], pts[2]);
     309                 :                 } else {
     310               0 :                     SkChopQuadAt(pts, tmp0, stopT);
     311               0 :                     dst->quadTo(tmp0[1], tmp0[2]);
     312                 :                 }
     313                 :             } else {
     314               0 :                 SkChopQuadAt(pts, tmp0, startT);
     315               0 :                 if (stopT == SK_Scalar1) {
     316               0 :                     dst->quadTo(tmp0[3], tmp0[4]);
     317                 :                 } else {
     318                 :                     SkChopQuadAt(&tmp0[2], tmp1, SkScalarDiv(stopT - startT,
     319               0 :                                                          SK_Scalar1 - startT));
     320               0 :                     dst->quadTo(tmp1[1], tmp1[2]);
     321                 :                 }
     322                 :             }
     323               0 :             break;
     324                 :         case kCubic_SegType:
     325               0 :             if (startT == 0) {
     326               0 :                 if (stopT == SK_Scalar1) {
     327               0 :                     dst->cubicTo(pts[1], pts[2], pts[3]);
     328                 :                 } else {
     329               0 :                     SkChopCubicAt(pts, tmp0, stopT);
     330               0 :                     dst->cubicTo(tmp0[1], tmp0[2], tmp0[3]);
     331                 :                 }
     332                 :             } else {
     333               0 :                 SkChopCubicAt(pts, tmp0, startT);
     334               0 :                 if (stopT == SK_Scalar1) {
     335               0 :                     dst->cubicTo(tmp0[4], tmp0[5], tmp0[6]);
     336                 :                 } else {
     337                 :                     SkChopCubicAt(&tmp0[3], tmp1, SkScalarDiv(stopT - startT,
     338               0 :                                                         SK_Scalar1 - startT));
     339               0 :                     dst->cubicTo(tmp1[1], tmp1[2], tmp1[3]);
     340                 :                 }
     341                 :             }
     342               0 :             break;
     343                 :         default:
     344               0 :             SkDEBUGFAIL("unknown segType");
     345               0 :             sk_throw();
     346                 :     }
     347                 : }
     348                 : 
     349                 : ////////////////////////////////////////////////////////////////////////////////
     350                 : ////////////////////////////////////////////////////////////////////////////////
     351                 : 
     352               0 : SkPathMeasure::SkPathMeasure() {
     353               0 :     fPath = NULL;
     354               0 :     fLength = -1;   // signal we need to compute it
     355               0 :     fForceClosed = false;
     356               0 :     fFirstPtIndex = -1;
     357               0 : }
     358                 : 
     359               0 : SkPathMeasure::SkPathMeasure(const SkPath& path, bool forceClosed) {
     360               0 :     fPath = &path;
     361               0 :     fLength = -1;   // signal we need to compute it
     362               0 :     fForceClosed = forceClosed;
     363               0 :     fFirstPtIndex = -1;
     364                 : 
     365               0 :     fIter.setPath(path, forceClosed);
     366               0 : }
     367                 : 
     368               0 : SkPathMeasure::~SkPathMeasure() {}
     369                 : 
     370                 : /** Assign a new path, or null to have none.
     371                 : */
     372               0 : void SkPathMeasure::setPath(const SkPath* path, bool forceClosed) {
     373               0 :     fPath = path;
     374               0 :     fLength = -1;   // signal we need to compute it
     375               0 :     fForceClosed = forceClosed;
     376               0 :     fFirstPtIndex = -1;
     377                 : 
     378               0 :     if (path) {
     379               0 :         fIter.setPath(*path, forceClosed);
     380                 :     }
     381               0 :     fSegments.reset();
     382               0 : }
     383                 : 
     384               0 : SkScalar SkPathMeasure::getLength() {
     385               0 :     if (fPath == NULL) {
     386               0 :         return 0;
     387                 :     }
     388               0 :     if (fLength < 0) {
     389               0 :         this->buildSegments();
     390                 :     }
     391               0 :     SkASSERT(fLength >= 0);
     392               0 :     return fLength;
     393                 : }
     394                 : 
     395               0 : const SkPathMeasure::Segment* SkPathMeasure::distanceToSegment(
     396                 :                                             SkScalar distance, SkScalar* t) {
     397               0 :     SkDEBUGCODE(SkScalar length = ) this->getLength();
     398               0 :     SkASSERT(distance >= 0 && distance <= length);
     399                 : 
     400               0 :     const Segment*  seg = fSegments.begin();
     401               0 :     int             count = fSegments.count();
     402                 : 
     403                 :     int index = SkTSearch<SkScalar>(&seg->fDistance, count, distance,
     404               0 :                                     sizeof(Segment));
     405                 :     // don't care if we hit an exact match or not, so we xor index if it is negative
     406               0 :     index ^= (index >> 31);
     407               0 :     seg = &seg[index];
     408                 : 
     409                 :     // now interpolate t-values with the prev segment (if possible)
     410               0 :     SkScalar    startT = 0, startD = 0;
     411                 :     // check if the prev segment is legal, and references the same set of points
     412               0 :     if (index > 0) {
     413               0 :         startD = seg[-1].fDistance;
     414               0 :         if (seg[-1].fPtIndex == seg->fPtIndex) {
     415               0 :             SkASSERT(seg[-1].fType == seg->fType);
     416               0 :             startT = seg[-1].getScalarT();
     417                 :         }
     418                 :     }
     419                 : 
     420               0 :     SkASSERT(seg->getScalarT() > startT);
     421               0 :     SkASSERT(distance >= startD);
     422               0 :     SkASSERT(seg->fDistance > startD);
     423                 : 
     424               0 :     *t = startT + SkScalarMulDiv(seg->getScalarT() - startT,
     425                 :                                  distance - startD,
     426               0 :                                  seg->fDistance - startD);
     427               0 :     return seg;
     428                 : }
     429                 : 
     430               0 : bool SkPathMeasure::getPosTan(SkScalar distance, SkPoint* pos,
     431                 :                               SkVector* tangent) {
     432               0 :     SkASSERT(fPath);
     433               0 :     if (fPath == NULL) {
     434                 :     EMPTY:
     435               0 :         return false;
     436                 :     }
     437                 : 
     438               0 :     SkScalar    length = this->getLength(); // call this to force computing it
     439               0 :     int         count = fSegments.count();
     440                 : 
     441               0 :     if (count == 0 || length == 0) {
     442                 :         goto EMPTY;
     443                 :     }
     444                 : 
     445                 :     // pin the distance to a legal range
     446               0 :     if (distance < 0) {
     447               0 :         distance = 0;
     448               0 :     } else if (distance > length) {
     449               0 :         distance = length;
     450                 :     }
     451                 :     
     452                 :     SkScalar        t;
     453               0 :     const Segment*  seg = this->distanceToSegment(distance, &t);
     454                 : 
     455               0 :     compute_pos_tan(*fPath, fSegments[0].fPtIndex, seg->fPtIndex, seg->fType,
     456               0 :                     t, pos, tangent);
     457               0 :     return true;
     458                 : }
     459                 : 
     460               0 : bool SkPathMeasure::getMatrix(SkScalar distance, SkMatrix* matrix,
     461                 :                               MatrixFlags flags) {
     462                 :     SkPoint     position;
     463                 :     SkVector    tangent;
     464                 : 
     465               0 :     if (this->getPosTan(distance, &position, &tangent)) {
     466               0 :         if (matrix) {
     467               0 :             if (flags & kGetTangent_MatrixFlag) {
     468               0 :                 matrix->setSinCos(tangent.fY, tangent.fX, 0, 0);
     469                 :             } else {
     470               0 :                 matrix->reset();
     471                 :             }
     472               0 :             if (flags & kGetPosition_MatrixFlag) {
     473               0 :                 matrix->postTranslate(position.fX, position.fY);
     474                 :             }
     475                 :         }
     476               0 :         return true;
     477                 :     }
     478               0 :     return false;
     479                 : }
     480                 : 
     481               0 : bool SkPathMeasure::getSegment(SkScalar startD, SkScalar stopD, SkPath* dst,
     482                 :                                bool startWithMoveTo) {
     483               0 :     SkASSERT(dst);
     484                 : 
     485               0 :     SkScalar length = this->getLength();    // ensure we have built our segments
     486                 : 
     487               0 :     if (startD < 0) {
     488               0 :         startD = 0;
     489                 :     }
     490               0 :     if (stopD > length) {
     491               0 :         stopD = length;
     492                 :     }
     493               0 :     if (startD >= stopD) {
     494               0 :         return false;
     495                 :     }
     496                 : 
     497                 :     SkPoint  p;
     498                 :     SkScalar startT, stopT;
     499               0 :     const Segment* seg = this->distanceToSegment(startD, &startT);
     500               0 :     const Segment* stopSeg = this->distanceToSegment(stopD, &stopT);
     501               0 :     SkASSERT(seg <= stopSeg);
     502                 : 
     503               0 :     if (startWithMoveTo) {
     504               0 :         compute_pos_tan(*fPath, fSegments[0].fPtIndex, seg->fPtIndex,
     505               0 :                         seg->fType, startT, &p, NULL);
     506               0 :         dst->moveTo(p);
     507                 :     }
     508                 : 
     509               0 :     if (seg->fPtIndex == stopSeg->fPtIndex) {
     510               0 :         seg_to(*fPath, fSegments[0].fPtIndex, seg->fPtIndex, seg->fType,
     511               0 :                startT, stopT, dst);
     512                 :     } else {
     513               0 :         do {
     514               0 :             seg_to(*fPath, fSegments[0].fPtIndex, seg->fPtIndex, seg->fType,
     515               0 :                    startT, SK_Scalar1, dst);
     516               0 :             seg = SkPathMeasure::NextSegment(seg);
     517               0 :             startT = 0;
     518                 :         } while (seg->fPtIndex < stopSeg->fPtIndex);
     519               0 :         seg_to(*fPath, fSegments[0].fPtIndex, seg->fPtIndex, seg->fType,
     520               0 :                0, stopT, dst);
     521                 :     }
     522               0 :     return true;
     523                 : }
     524                 : 
     525               0 : bool SkPathMeasure::isClosed() {
     526               0 :     (void)this->getLength();
     527               0 :     return fIsClosed;
     528                 : }
     529                 : 
     530                 : /** Move to the next contour in the path. Return true if one exists, or false if
     531                 :     we're done with the path.
     532                 : */
     533               0 : bool SkPathMeasure::nextContour() {
     534               0 :     fLength = -1;
     535               0 :     return this->getLength() > 0;
     536                 : }
     537                 : 
     538                 : ///////////////////////////////////////////////////////////////////////////////
     539                 : ///////////////////////////////////////////////////////////////////////////////
     540                 : 
     541                 : #ifdef SK_DEBUG
     542                 : 
     543               0 : void SkPathMeasure::dump() {
     544               0 :     SkDebugf("pathmeas: length=%g, segs=%d\n", fLength, fSegments.count());
     545                 : 
     546               0 :     for (int i = 0; i < fSegments.count(); i++) {
     547               0 :         const Segment* seg = &fSegments[i];
     548                 :         SkDebugf("pathmeas: seg[%d] distance=%g, point=%d, t=%g, type=%d\n",
     549               0 :                 i, seg->fDistance, seg->fPtIndex, seg->getScalarT(),
     550               0 :                  seg->fType);
     551                 :     }
     552               0 : }
     553                 : 
     554                 : #endif

Generated by: LCOV version 1.7