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