1 2 /* 3 * Copyright 2006 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 #ifndef SkPathMeasure_DEFINED 11 #define SkPathMeasure_DEFINED 12 13 #include "SkPath.h" 14 #include "SkTDArray.h" 15 16 class SkPathMeasure : SkNoncopyable { 17 public: 18 SkPathMeasure(); 19 /** Initialize the pathmeasure with the specified path. The path must remain valid 20 for the lifetime of the measure object, or until setPath() is called with 21 a different path (or null), since the measure object keeps a pointer to the 22 path object (does not copy its data). 23 */ 24 SkPathMeasure(const SkPath& path, bool forceClosed); 25 ~SkPathMeasure(); 26 27 /** Reset the pathmeasure with the specified path. The path must remain valid 28 for the lifetime of the measure object, or until setPath() is called with 29 a different path (or null), since the measure object keeps a pointer to the 30 path object (does not copy its data). 31 */ 32 void setPath(const SkPath*, bool forceClosed); 33 34 /** Return the total length of the current contour, or 0 if no path 35 is associated (e.g. resetPath(null)) 36 */ 37 SkScalar getLength(); 38 39 /** Pins distance to 0 <= distance <= getLength(), and then computes 40 the corresponding position and tangent. 41 Returns false if there is no path, or a zero-length path was specified, in which case 42 position and tangent are unchanged. 43 */ 44 bool getPosTan(SkScalar distance, SkPoint* position, SkVector* tangent); 45 46 enum MatrixFlags { 47 kGetPosition_MatrixFlag = 0x01, 48 kGetTangent_MatrixFlag = 0x02, 49 kGetPosAndTan_MatrixFlag = kGetPosition_MatrixFlag | kGetTangent_MatrixFlag 50 }; 51 /** Pins distance to 0 <= distance <= getLength(), and then computes 52 the corresponding matrix (by calling getPosTan). 53 Returns false if there is no path, or a zero-length path was specified, in which case 54 matrix is unchanged. 55 */ 56 bool getMatrix(SkScalar distance, SkMatrix* matrix, MatrixFlags flags = kGetPosAndTan_MatrixFlag); 57 /** Given a start and stop distance, return in dst the intervening segment(s). 58 If the segment is zero-length, return false, else return true. 59 startD and stopD are pinned to legal values (0..getLength()). If startD <= stopD 60 then return false (and leave dst untouched). 61 Begin the segment with a moveTo if startWithMoveTo is true 62 */ 63 bool getSegment(SkScalar startD, SkScalar stopD, SkPath* dst, bool startWithMoveTo); 64 65 /** Return true if the current contour is closed() 66 */ 67 bool isClosed(); 68 69 /** Move to the next contour in the path. Return true if one exists, or false if 70 we're done with the path. 71 */ 72 bool nextContour(); 73 74 #ifdef SK_DEBUG 75 void dump(); 76 #endif 77 78 private: 79 SkPath::Iter fIter; 80 const SkPath* fPath; 81 SkScalar fLength; // relative to the current contour 82 int fFirstPtIndex; // relative to the current contour 83 bool fIsClosed; // relative to the current contour 84 bool fForceClosed; 85 86 struct Segment { 87 SkScalar fDistance; // total distance up to this point 88 unsigned fPtIndex : 15; // index into the fPts array 89 unsigned fTValue : 15; 90 unsigned fType : 2; 91 92 SkScalar getScalarT() const; 93 }; 94 SkTDArray<Segment> fSegments; 95 SkTDArray<SkPoint> fPts; // Points used to define the segments 96 97 static const Segment* NextSegment(const Segment*); 98 99 void buildSegments(); 100 SkScalar compute_quad_segs(const SkPoint pts[3], SkScalar distance, 101 int mint, int maxt, int ptIndex); 102 SkScalar compute_cubic_segs(const SkPoint pts[3], SkScalar distance, 103 int mint, int maxt, int ptIndex); 104 const Segment* distanceToSegment(SkScalar distance, SkScalar* t); 105 }; 106 107 #endif 108