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 struct SkConic; 15 16 class SK_API 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 SK_WARN_UNUSED_RESULT getPosTan(SkScalar distance, SkPoint* position, 45 SkVector* tangent); 46 47 enum MatrixFlags { 48 kGetPosition_MatrixFlag = 0x01, 49 kGetTangent_MatrixFlag = 0x02, 50 kGetPosAndTan_MatrixFlag = kGetPosition_MatrixFlag | kGetTangent_MatrixFlag 51 }; 52 53 /** Pins distance to 0 <= distance <= getLength(), and then computes 54 the corresponding matrix (by calling getPosTan). 55 Returns false if there is no path, or a zero-length path was specified, in which case 56 matrix is unchanged. 57 */ 58 bool SK_WARN_UNUSED_RESULT getMatrix(SkScalar distance, SkMatrix* matrix, 59 MatrixFlags flags = kGetPosAndTan_MatrixFlag); 60 61 /** Given a start and stop distance, return in dst the intervening segment(s). 62 If the segment is zero-length, return false, else return true. 63 startD and stopD are pinned to legal values (0..getLength()). If startD <= stopD 64 then return false (and leave dst untouched). 65 Begin the segment with a moveTo if startWithMoveTo is true 66 */ 67 bool getSegment(SkScalar startD, SkScalar stopD, SkPath* dst, bool startWithMoveTo); 68 69 /** Return true if the current contour is closed() 70 */ 71 bool isClosed(); 72 73 /** Move to the next contour in the path. Return true if one exists, or false if 74 we're done with the path. 75 */ 76 bool nextContour(); 77 78 #ifdef SK_DEBUG 79 void dump(); 80 #endif 81 82 private: 83 SkPath::Iter fIter; 84 const SkPath* fPath; 85 SkScalar fLength; // relative to the current contour 86 int fFirstPtIndex; // relative to the current contour 87 bool fIsClosed; // relative to the current contour 88 bool fForceClosed; 89 90 struct Segment { 91 SkScalar fDistance; // total distance up to this point 92 unsigned fPtIndex : 15; // index into the fPts array 93 unsigned fTValue : 15; 94 unsigned fType : 2; 95 96 SkScalar getScalarT() const; 97 }; 98 SkTDArray<Segment> fSegments; 99 SkTDArray<SkPoint> fPts; // Points used to define the segments 100 101 static const Segment* NextSegment(const Segment*); 102 103 void buildSegments(); 104 SkScalar compute_quad_segs(const SkPoint pts[3], SkScalar distance, 105 int mint, int maxt, int ptIndex); 106 SkScalar compute_conic_segs(const SkConic&, SkScalar distance, int mint, int maxt, int ptIndex); 107 SkScalar compute_cubic_segs(const SkPoint pts[3], SkScalar distance, 108 int mint, int maxt, int ptIndex); 109 const Segment* distanceToSegment(SkScalar distance, SkScalar* t); 110 }; 111 112 #endif 113