Coverage Report

Created: 2024-05-20 07:14

/src/skia/src/gpu/tessellate/MidpointContourParser.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2022 Google LLC.
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 skgpu_tessellate_MidpointContourParser_DEFINED
9
#define skgpu_tessellate_MidpointContourParser_DEFINED
10
11
#include "include/core/SkPath.h"
12
#include "include/core/SkPoint.h"
13
#include "src/core/SkPathPriv.h"
14
15
#include <cstdint>
16
17
namespace skgpu::tess {
18
19
// Parses out each contour in a path and tracks the midpoint. Example usage:
20
//
21
//   MidpointContourParser parser;
22
//   while (parser.parseNextContour()) {
23
//       SkPoint midpoint = parser.currentMidpoint();
24
//       for (auto [verb, pts] : parser.currentContour()) {
25
//           ...
26
//       }
27
//   }
28
//
29
class MidpointContourParser {
30
public:
31
    MidpointContourParser(const SkPath& path)
32
            : fPath(path)
33
            , fVerbs(SkPathPriv::VerbData(fPath))
34
            , fNumRemainingVerbs(fPath.countVerbs())
35
            , fPoints(SkPathPriv::PointData(fPath))
36
0
            , fWeights(SkPathPriv::ConicWeightData(fPath)) {}
37
    // Advances the internal state to the next contour in the path. Returns false if there are no
38
    // more contours.
39
0
    bool parseNextContour() {
40
0
        bool hasGeometry = false;
41
0
        for (; fVerbsIdx < fNumRemainingVerbs; ++fVerbsIdx) {
42
0
            switch (fVerbs[fVerbsIdx]) {
43
0
                case SkPath::kMove_Verb:
44
0
                    if (!hasGeometry) {
45
0
                        fMidpoint = {0,0};
46
0
                        fMidpointWeight = 0;
47
0
                        this->advance();  // Resets fPtsIdx to 0 and advances fPoints.
48
0
                        fPtsIdx = 1;  // Increment fPtsIdx past the kMove.
49
0
                        continue;
50
0
                    }
51
0
                    if (fPoints[0] != fPoints[fPtsIdx - 1]) {
52
                        // There's an implicit close at the end. Add the start point to our mean.
53
0
                        fMidpoint += fPoints[0];
54
0
                        ++fMidpointWeight;
55
0
                    }
56
0
                    return true;
57
0
                default:
58
0
                    continue;
59
0
                case SkPath::kLine_Verb:
60
0
                    ++fPtsIdx;
61
0
                    break;
62
0
                case SkPath::kConic_Verb:
63
0
                    ++fWtsIdx;
64
0
                    [[fallthrough]];
65
0
                case SkPath::kQuad_Verb:
66
0
                    fPtsIdx += 2;
67
0
                    break;
68
0
                case SkPath::kCubic_Verb:
69
0
                    fPtsIdx += 3;
70
0
                    break;
71
0
            }
72
0
            fMidpoint += fPoints[fPtsIdx - 1];
73
0
            ++fMidpointWeight;
74
0
            hasGeometry = true;
75
0
        }
76
0
        if (hasGeometry && fPoints[0] != fPoints[fPtsIdx - 1]) {
77
            // There's an implicit close at the end. Add the start point to our mean.
78
0
            fMidpoint += fPoints[0];
79
0
            ++fMidpointWeight;
80
0
        }
81
0
        return hasGeometry;
82
0
    }
83
84
    // Allows for iterating the current contour using a range-for loop.
85
0
    SkPathPriv::Iterate currentContour() {
86
0
        return SkPathPriv::Iterate(fVerbs, fVerbs + fVerbsIdx, fPoints, fWeights);
87
0
    }
88
89
0
    SkPoint currentMidpoint() { return fMidpoint * (1.f / fMidpointWeight); }
90
91
private:
92
0
    void advance() {
93
0
        fVerbs += fVerbsIdx;
94
0
        fNumRemainingVerbs -= fVerbsIdx;
95
0
        fVerbsIdx = 0;
96
0
        fPoints += fPtsIdx;
97
0
        fPtsIdx = 0;
98
0
        fWeights += fWtsIdx;
99
0
        fWtsIdx = 0;
100
0
    }
101
102
    const SkPath& fPath;
103
104
    const uint8_t* fVerbs;
105
    int fNumRemainingVerbs = 0;
106
    int fVerbsIdx = 0;
107
108
    const SkPoint* fPoints;
109
    int fPtsIdx = 0;
110
111
    const float* fWeights;
112
    int fWtsIdx = 0;
113
114
    SkPoint fMidpoint;
115
    int fMidpointWeight;
116
};
117
118
}  // namespace skgpu::tess
119
120
#endif // skgpu_tessellate_MidpointContourParser_DEFINED