blob: f6e606f0c06decf56fca3af6c5d052d1cf3eade2 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2006 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00006 */
7
8#ifndef SkPathMeasure_DEFINED
9#define SkPathMeasure_DEFINED
10
11#include "SkPath.h"
12#include "SkTDArray.h"
13
reed220f9262014-12-17 08:21:04 -080014struct SkConic;
15
reed@google.comd0280562013-05-08 13:25:02 +000016class SK_API SkPathMeasure : SkNoncopyable {
reed@android.com8a1c16f2008-12-17 15:59:43 +000017public:
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 */
reed@google.comf3edf9f2012-04-12 19:44:38 +000032 void setPath(const SkPath*, bool forceClosed);
reed@android.com8a1c16f2008-12-17 15:59:43 +000033
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 */
rmistry@google.comfbfcd562012-08-23 18:09:54 +000044 bool SK_WARN_UNUSED_RESULT getPosTan(SkScalar distance, SkPoint* position,
reed@google.comf3edf9f2012-04-12 19:44:38 +000045 SkVector* tangent);
reed@android.com8a1c16f2008-12-17 15:59:43 +000046
47 enum MatrixFlags {
48 kGetPosition_MatrixFlag = 0x01,
49 kGetTangent_MatrixFlag = 0x02,
50 kGetPosAndTan_MatrixFlag = kGetPosition_MatrixFlag | kGetTangent_MatrixFlag
51 };
reed@google.comf3edf9f2012-04-12 19:44:38 +000052
reed@android.com8a1c16f2008-12-17 15:59:43 +000053 /** 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 */
rmistry@google.comfbfcd562012-08-23 18:09:54 +000058 bool SK_WARN_UNUSED_RESULT getMatrix(SkScalar distance, SkMatrix* matrix,
reed@google.comf3edf9f2012-04-12 19:44:38 +000059 MatrixFlags flags = kGetPosAndTan_MatrixFlag);
60
reed@android.com8a1c16f2008-12-17 15:59:43 +000061 /** 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();
reed@android.com8a1c16f2008-12-17 15:59:43 +000080#endif
81
82private:
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
schenney@chromium.orgf4b07322012-01-18 18:06:10 +000092 unsigned fPtIndex : 15; // index into the fPts array
reed@android.com8a1c16f2008-12-17 15:59:43 +000093 unsigned fTValue : 15;
94 unsigned fType : 2;
95
96 SkScalar getScalarT() const;
97 };
98 SkTDArray<Segment> fSegments;
schenney@chromium.orgf4b07322012-01-18 18:06:10 +000099 SkTDArray<SkPoint> fPts; // Points used to define the segments
reed@android.com8a1c16f2008-12-17 15:59:43 +0000100
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);
reed220f9262014-12-17 08:21:04 -0800106 SkScalar compute_conic_segs(const SkConic&, SkScalar distance, int mint, int maxt, int ptIndex);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000107 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