michael@0: /* michael@0: * Copyright 2006 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef SkPathMeasure_DEFINED michael@0: #define SkPathMeasure_DEFINED michael@0: michael@0: #include "SkPath.h" michael@0: #include "SkTDArray.h" michael@0: michael@0: class SK_API SkPathMeasure : SkNoncopyable { michael@0: public: michael@0: SkPathMeasure(); michael@0: /** Initialize the pathmeasure with the specified path. The path must remain valid michael@0: for the lifetime of the measure object, or until setPath() is called with michael@0: a different path (or null), since the measure object keeps a pointer to the michael@0: path object (does not copy its data). michael@0: */ michael@0: SkPathMeasure(const SkPath& path, bool forceClosed); michael@0: ~SkPathMeasure(); michael@0: michael@0: /** Reset the pathmeasure with the specified path. The path must remain valid michael@0: for the lifetime of the measure object, or until setPath() is called with michael@0: a different path (or null), since the measure object keeps a pointer to the michael@0: path object (does not copy its data). michael@0: */ michael@0: void setPath(const SkPath*, bool forceClosed); michael@0: michael@0: /** Return the total length of the current contour, or 0 if no path michael@0: is associated (e.g. resetPath(null)) michael@0: */ michael@0: SkScalar getLength(); michael@0: michael@0: /** Pins distance to 0 <= distance <= getLength(), and then computes michael@0: the corresponding position and tangent. michael@0: Returns false if there is no path, or a zero-length path was specified, in which case michael@0: position and tangent are unchanged. michael@0: */ michael@0: bool SK_WARN_UNUSED_RESULT getPosTan(SkScalar distance, SkPoint* position, michael@0: SkVector* tangent); michael@0: michael@0: enum MatrixFlags { michael@0: kGetPosition_MatrixFlag = 0x01, michael@0: kGetTangent_MatrixFlag = 0x02, michael@0: kGetPosAndTan_MatrixFlag = kGetPosition_MatrixFlag | kGetTangent_MatrixFlag michael@0: }; michael@0: michael@0: /** Pins distance to 0 <= distance <= getLength(), and then computes michael@0: the corresponding matrix (by calling getPosTan). michael@0: Returns false if there is no path, or a zero-length path was specified, in which case michael@0: matrix is unchanged. michael@0: */ michael@0: bool SK_WARN_UNUSED_RESULT getMatrix(SkScalar distance, SkMatrix* matrix, michael@0: MatrixFlags flags = kGetPosAndTan_MatrixFlag); michael@0: michael@0: /** Given a start and stop distance, return in dst the intervening segment(s). michael@0: If the segment is zero-length, return false, else return true. michael@0: startD and stopD are pinned to legal values (0..getLength()). If startD <= stopD michael@0: then return false (and leave dst untouched). michael@0: Begin the segment with a moveTo if startWithMoveTo is true michael@0: */ michael@0: bool getSegment(SkScalar startD, SkScalar stopD, SkPath* dst, bool startWithMoveTo); michael@0: michael@0: /** Return true if the current contour is closed() michael@0: */ michael@0: bool isClosed(); michael@0: michael@0: /** Move to the next contour in the path. Return true if one exists, or false if michael@0: we're done with the path. michael@0: */ michael@0: bool nextContour(); michael@0: michael@0: #ifdef SK_DEBUG michael@0: void dump(); michael@0: #endif michael@0: michael@0: private: michael@0: SkPath::Iter fIter; michael@0: const SkPath* fPath; michael@0: SkScalar fLength; // relative to the current contour michael@0: int fFirstPtIndex; // relative to the current contour michael@0: bool fIsClosed; // relative to the current contour michael@0: bool fForceClosed; michael@0: michael@0: struct Segment { michael@0: SkScalar fDistance; // total distance up to this point michael@0: unsigned fPtIndex : 15; // index into the fPts array michael@0: unsigned fTValue : 15; michael@0: unsigned fType : 2; michael@0: michael@0: SkScalar getScalarT() const; michael@0: }; michael@0: SkTDArray fSegments; michael@0: SkTDArray fPts; // Points used to define the segments michael@0: michael@0: static const Segment* NextSegment(const Segment*); michael@0: michael@0: void buildSegments(); michael@0: SkScalar compute_quad_segs(const SkPoint pts[3], SkScalar distance, michael@0: int mint, int maxt, int ptIndex); michael@0: SkScalar compute_cubic_segs(const SkPoint pts[3], SkScalar distance, michael@0: int mint, int maxt, int ptIndex); michael@0: const Segment* distanceToSegment(SkScalar distance, SkScalar* t); michael@0: }; michael@0: michael@0: #endif