• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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