1 | /* |
---|---|
2 | * Copyright 2020 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 GrMidpointContourParser_DEFINED |
9 | #define GrMidpointContourParser_DEFINED |
10 | |
11 | #include "src/core/SkPathPriv.h" |
12 | |
13 | // Parses out each contour in a path and tracks the midpoint. Example usage: |
14 | // |
15 | // SkTPathContourParser parser; |
16 | // while (parser.parseNextContour()) { |
17 | // SkPoint midpoint = parser.currentMidpoint(); |
18 | // for (auto [verb, pts] : parser.currentContour()) { |
19 | // ... |
20 | // } |
21 | // } |
22 | // |
23 | class GrMidpointContourParser { |
24 | public: |
25 | GrMidpointContourParser(const SkPath& path) |
26 | : fPath(path) |
27 | , fVerbs(SkPathPriv::VerbData(fPath)) |
28 | , fNumRemainingVerbs(fPath.countVerbs()) |
29 | , fPoints(SkPathPriv::PointData(fPath)) {} |
30 | // Advances the internal state to the next contour in the path. Returns false if there are no |
31 | // more contours. |
32 | bool parseNextContour() { |
33 | bool hasGeometry = false; |
34 | for (; fVerbsIdx < fNumRemainingVerbs; ++fVerbsIdx) { |
35 | switch (fVerbs[fVerbsIdx]) { |
36 | case SkPath::kMove_Verb: |
37 | if (!hasGeometry) { |
38 | fMidpoint = fPoints[fPtsIdx]; |
39 | fMidpointWeight = 1; |
40 | this->advance(); |
41 | ++fPtsIdx; |
42 | continue; |
43 | } |
44 | return true; |
45 | default: |
46 | continue; |
47 | case SkPath::kLine_Verb: |
48 | ++fPtsIdx; |
49 | break; |
50 | case SkPath::kQuad_Verb: |
51 | case SkPath::kConic_Verb: |
52 | fPtsIdx += 2; |
53 | break; |
54 | case SkPath::kCubic_Verb: |
55 | fPtsIdx += 3; |
56 | break; |
57 | } |
58 | fMidpoint += fPoints[fPtsIdx - 1]; |
59 | ++fMidpointWeight; |
60 | hasGeometry = true; |
61 | } |
62 | return hasGeometry; |
63 | } |
64 | |
65 | // Allows for iterating the current contour using a range-for loop. |
66 | SkPathPriv::Iterate currentContour() { |
67 | return SkPathPriv::Iterate(fVerbs, fVerbs + fVerbsIdx, fPoints, nullptr); |
68 | } |
69 | |
70 | SkPoint currentMidpoint() { return fMidpoint * (1.f / fMidpointWeight); } |
71 | |
72 | private: |
73 | void advance() { |
74 | fVerbs += fVerbsIdx; |
75 | fNumRemainingVerbs -= fVerbsIdx; |
76 | fVerbsIdx = 0; |
77 | fPoints += fPtsIdx; |
78 | fPtsIdx = 0; |
79 | } |
80 | |
81 | const SkPath& fPath; |
82 | |
83 | const uint8_t* fVerbs; |
84 | int fNumRemainingVerbs = 0; |
85 | int fVerbsIdx = 0; |
86 | |
87 | const SkPoint* fPoints; |
88 | int fPtsIdx = 0; |
89 | |
90 | SkPoint fMidpoint; |
91 | int fMidpointWeight; |
92 | }; |
93 | |
94 | #endif |
95 |