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