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