Coverage Report

Created: 2024-05-20 07:14

/src/skia/include/core/SkContourMeasure.h
Line
Count
Source
1
/*
2
 * Copyright 2018 Google Inc.
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 SkContourMeasure_DEFINED
9
#define SkContourMeasure_DEFINED
10
11
#include "include/core/SkPoint.h"
12
#include "include/core/SkRefCnt.h"
13
#include "include/core/SkScalar.h"
14
#include "include/private/base/SkAPI.h"
15
#include "include/private/base/SkTDArray.h"
16
17
#include <memory>
18
19
class SkMatrix;
20
class SkPath;
21
22
class SK_API SkContourMeasure : public SkRefCnt {
23
public:
24
    /** Return the length of the contour.
25
     */
26
241M
    SkScalar length() const { return fLength; }
27
28
    /** Pins distance to 0 <= distance <= length(), and then computes the corresponding
29
     *  position and tangent.
30
     */
31
    [[nodiscard]] bool getPosTan(SkScalar distance, SkPoint* position, SkVector* tangent) const;
32
33
    enum MatrixFlags {
34
        kGetPosition_MatrixFlag     = 0x01,
35
        kGetTangent_MatrixFlag      = 0x02,
36
        kGetPosAndTan_MatrixFlag    = kGetPosition_MatrixFlag | kGetTangent_MatrixFlag
37
    };
38
39
    /** Pins distance to 0 <= distance <= getLength(), and then computes
40
     the corresponding matrix (by calling getPosTan).
41
     Returns false if there is no path, or a zero-length path was specified, in which case
42
     matrix is unchanged.
43
     */
44
    [[nodiscard]] bool getMatrix(SkScalar distance, SkMatrix* matrix,
45
                                 MatrixFlags flags = kGetPosAndTan_MatrixFlag) const;
46
47
    /** Given a start and stop distance, return in dst the intervening segment(s).
48
     If the segment is zero-length, return false, else return true.
49
     startD and stopD are pinned to legal values (0..getLength()). If startD > stopD
50
     then return false (and leave dst untouched).
51
     Begin the segment with a moveTo if startWithMoveTo is true
52
     */
53
    [[nodiscard]] bool getSegment(SkScalar startD, SkScalar stopD, SkPath* dst,
54
                                  bool startWithMoveTo) const;
55
56
    /** Return true if the contour is closed()
57
     */
58
543k
    bool isClosed() const { return fIsClosed; }
59
60
private:
61
    struct Segment {
62
        SkScalar    fDistance;  // total distance up to this point
63
        unsigned    fPtIndex; // index into the fPts array
64
        unsigned    fTValue : 30;
65
        unsigned    fType : 2;  // actually the enum SkSegType
66
        // See SkPathMeasurePriv.h
67
68
        SkScalar getScalarT() const;
69
70
1.88M
        static const Segment* Next(const Segment* seg) {
71
1.88M
            unsigned ptIndex = seg->fPtIndex;
72
5.94M
            do {
73
5.94M
                ++seg;
74
5.94M
            } while (seg->fPtIndex == ptIndex);
75
1.88M
            return seg;
76
1.88M
        }
77
78
    };
79
80
    const SkTDArray<Segment>  fSegments;
81
    const SkTDArray<SkPoint>  fPts; // Points used to define the segments
82
83
    const SkScalar fLength;
84
    const bool fIsClosed;
85
86
    SkContourMeasure(SkTDArray<Segment>&& segs, SkTDArray<SkPoint>&& pts,
87
                     SkScalar length, bool isClosed);
88
872k
    ~SkContourMeasure() override {}
89
90
    const Segment* distanceToSegment(SkScalar distance, SkScalar* t) const;
91
92
    friend class SkContourMeasureIter;
93
    friend class SkPathMeasurePriv;
94
};
95
96
class SK_API SkContourMeasureIter {
97
public:
98
    SkContourMeasureIter();
99
    /**
100
     *  Initialize the Iter with a path.
101
     *  The parts of the path that are needed are copied, so the client is free to modify/delete
102
     *  the path after this call.
103
     *
104
     *  resScale controls the precision of the measure. values > 1 increase the
105
     *  precision (and possibly slow down the computation).
106
     */
107
    SkContourMeasureIter(const SkPath& path, bool forceClosed, SkScalar resScale = 1);
108
    ~SkContourMeasureIter();
109
110
    SkContourMeasureIter(SkContourMeasureIter&&);
111
    SkContourMeasureIter& operator=(SkContourMeasureIter&&);
112
113
    /**
114
     *  Reset the Iter with a path.
115
     *  The parts of the path that are needed are copied, so the client is free to modify/delete
116
     *  the path after this call.
117
     */
118
    void reset(const SkPath& path, bool forceClosed, SkScalar resScale = 1);
119
120
    /**
121
     *  Iterates through contours in path, returning a contour-measure object for each contour
122
     *  in the path. Returns null when it is done.
123
     *
124
     *  This only returns non-zero length contours, where a contour is the segments between
125
     *  a kMove_Verb and either ...
126
     *      - the next kMove_Verb
127
     *      - kClose_Verb (1 or more)
128
     *      - kDone_Verb
129
     *  If it encounters a zero-length contour, it is skipped.
130
     */
131
    sk_sp<SkContourMeasure> next();
132
133
private:
134
    class Impl;
135
136
    std::unique_ptr<Impl> fImpl;
137
};
138
139
#endif