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