xref: /aosp_15_r20/external/skia/tests/SubsetPath.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2015 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 #include "include/core/SkPathTypes.h"
9 #include "include/core/SkPoint.h"
10 #include "include/core/SkTypes.h"
11 #include "include/private/base/SkDebug.h"
12 #include "src/base/SkMathPriv.h"
13 #include "src/core/SkPathPriv.h"
14 #include "tests/SubsetPath.h"
15 
SubsetPath(const SkPath & path)16 SubsetPath::SubsetPath(const SkPath& path)
17         : fPath(path)
18         , fSubset(1) {
19 }
20 
range(int * end) const21 int SubsetPath::range(int* end) const {
22     int leadingZero = SkCLZ(fSubset);
23     int parts = 1 << (31 - leadingZero);
24     int partIndex = fSubset - parts;
25     SkASSERT(partIndex >= 0);
26     int count = fSelected.size();
27     int start = count * partIndex / parts;
28     *end = count * (partIndex + 1) / parts;
29     return start;
30 }
31 
subset(bool testFailed,SkPath * sub)32 bool SubsetPath::subset(bool testFailed, SkPath* sub) {
33     int start, end;
34     if (!testFailed) {
35         start = range(&end);
36         for (; start < end; ++start) {
37             fSelected[start] = true;
38         }
39     }
40     do {
41         do {
42             ++fSubset;
43             start = range(&end);
44  //           SkDebugf("%d s=%d e=%d t=%d\n", fSubset, start, end, fTries);
45             if (end - start > 1) {
46                 fTries = fSelected.size();
47             } else if (end - start == 1) {
48                 if (--fTries <= 0) {
49                     return false;
50                 }
51             }
52         } while (start == end);
53     } while (!fSelected[start]);
54     for (; start < end; ++start) {
55         fSelected[start] = false;
56     }
57 #if 1
58     SkDebugf("selected: ");
59     for (int index = 0; index < fSelected.size(); ++index) {
60         SkDebugf("%c", fSelected[index] ? 'x' : '-');
61     }
62 #endif
63     *sub = getSubsetPath();
64     return true;
65 }
66 
SubsetContours(const SkPath & path)67 SubsetContours::SubsetContours(const SkPath& path)
68         : SubsetPath(path) {
69     bool foundCurve = false;
70     int contourCount = 0;
71     for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) {
72         switch (verb) {
73             case SkPathVerb::kMove:
74                 break;
75             case SkPathVerb::kLine:
76             case SkPathVerb::kQuad:
77             case SkPathVerb::kConic:
78             case SkPathVerb::kCubic:
79                 foundCurve = true;
80                 break;
81             case SkPathVerb::kClose:
82                 ++contourCount;
83                 foundCurve = false;
84                 break;
85             default:
86                 SkDEBUGFAIL("bad verb");
87                 return;
88         }
89     }
90     contourCount += foundCurve;
91     for (int index = 0; index < contourCount; ++index) {
92         *fSelected.append() = true;
93     }
94     fTries = contourCount;
95 }
96 
getSubsetPath() const97 SkPath SubsetContours::getSubsetPath() const {
98     SkPath result;
99     result.setFillType(fPath.getFillType());
100     if (!fSelected.size()) {
101         return result;
102     }
103     int contourCount = 0;
104     bool enabled = fSelected[0];
105     bool addMoveTo = true;
106     for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) {
107         if (enabled && addMoveTo) {
108             result.moveTo(pts[0]);
109             addMoveTo = false;
110         }
111         switch (verb) {
112             case SkPathVerb::kMove:
113                 break;
114             case SkPathVerb::kLine:
115                 if (enabled) {
116                     result.lineTo(pts[1]);
117                 }
118                 break;
119             case SkPathVerb::kQuad:
120                 if (enabled) {
121                     result.quadTo(pts[1], pts[2]);
122                 }
123                 break;
124             case SkPathVerb::kConic:
125                 if (enabled) {
126                     result.conicTo(pts[1], pts[2], *w);
127                 }
128                 break;
129             case SkPathVerb::kCubic:
130                  if (enabled) {
131                     result.cubicTo(pts[1], pts[2], pts[3]);
132                 }
133                 break;
134             case SkPathVerb::kClose:
135                 if (enabled) {
136                     result.close();
137                 }
138                 if (++contourCount >= fSelected.size()) {
139                     break;
140                 }
141                 enabled = fSelected[contourCount];
142                 addMoveTo = true;
143                 continue;
144             default:
145                 SkDEBUGFAIL("bad verb");
146                 return result;
147         }
148     }
149     return result;
150 }
151 
SubsetVerbs(const SkPath & path)152 SubsetVerbs::SubsetVerbs(const SkPath& path)
153         : SubsetPath(path) {
154     int verbCount = 0;
155     for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) {
156         switch (verb) {
157             case SkPathVerb::kMove:
158                 break;
159             case SkPathVerb::kLine:
160             case SkPathVerb::kQuad:
161             case SkPathVerb::kConic:
162             case SkPathVerb::kCubic:
163                 ++verbCount;
164                 break;
165             case SkPathVerb::kClose:
166                 break;
167             default:
168                 SkDEBUGFAIL("bad verb");
169                 return;
170         }
171     }
172     for (int index = 0; index < verbCount; ++index) {
173         *fSelected.append() = true;
174     }
175     fTries = verbCount;
176 }
177 
getSubsetPath() const178 SkPath SubsetVerbs::getSubsetPath() const {
179     SkPath result;
180     result.setFillType(fPath.getFillType());
181     if (!fSelected.size()) {
182         return result;
183     }
184     int verbIndex = 0;
185     bool addMoveTo = true;
186     bool addLineTo = false;
187     for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) {
188         bool enabled = SkPathVerb::kLine <= verb && verb <= SkPathVerb::kCubic
189             ? fSelected[verbIndex++] : false;
190         if (enabled) {
191             if (addMoveTo) {
192                 result.moveTo(pts[0]);
193                 addMoveTo = false;
194             } else if (addLineTo) {
195                 result.lineTo(pts[0]);
196                 addLineTo = false;
197             }
198         }
199         switch (verb) {
200             case SkPathVerb::kMove:
201                 break;
202             case SkPathVerb::kLine:
203                 if (enabled) {
204                     result.lineTo(pts[1]);
205                 }
206                 break;
207             case SkPathVerb::kQuad:
208                 if (enabled) {
209                     result.quadTo(pts[1], pts[2]);
210                 }
211                 break;
212             case SkPathVerb::kConic:
213                 if (enabled) {
214                     result.conicTo(pts[1], pts[2], *w);
215                 }
216                 break;
217             case SkPathVerb::kCubic:
218                  if (enabled) {
219                     result.cubicTo(pts[1], pts[2], pts[3]);
220                 }
221                 break;
222             case SkPathVerb::kClose:
223                 result.close();
224                 addMoveTo = true;
225                 addLineTo = false;
226                 continue;
227             default:
228                 SkDEBUGFAIL("bad verb");
229                 return result;
230         }
231         addLineTo = !enabled;
232     }
233     return result;
234 }
235