blob: 3004e1d0367aecaebb88f278fc5742e90f372208 [file] [log] [blame]
caryclarkef784fb2015-10-30 12:03:06 -07001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/core/SkMathPriv.h"
Chris Daltonde500372020-05-05 15:06:30 -06009#include "src/core/SkPathPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "tests/SubsetPath.h"
caryclarkef784fb2015-10-30 12:03:06 -070011
12SubsetPath::SubsetPath(const SkPath& path)
13 : fPath(path)
14 , fSubset(1) {
15}
16
17int 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
28bool 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
63SubsetContours::SubsetContours(const SkPath& path)
64 : SubsetPath(path) {
caryclarkef784fb2015-10-30 12:03:06 -070065 bool foundCurve = false;
66 int contourCount = 0;
Chris Daltonde500372020-05-05 15:06:30 -060067 for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) {
caryclarkef784fb2015-10-30 12:03:06 -070068 switch (verb) {
Chris Daltonde500372020-05-05 15:06:30 -060069 case SkPathVerb::kMove:
caryclarkef784fb2015-10-30 12:03:06 -070070 break;
Chris Daltonde500372020-05-05 15:06:30 -060071 case SkPathVerb::kLine:
72 case SkPathVerb::kQuad:
73 case SkPathVerb::kConic:
74 case SkPathVerb::kCubic:
caryclarkef784fb2015-10-30 12:03:06 -070075 foundCurve = true;
76 break;
Chris Daltonde500372020-05-05 15:06:30 -060077 case SkPathVerb::kClose:
caryclarkef784fb2015-10-30 12:03:06 -070078 ++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
93SkPath SubsetContours::getSubsetPath() const {
94 SkPath result;
95 result.setFillType(fPath.getFillType());
96 if (!fSelected.count()) {
97 return result;
98 }
caryclarkef784fb2015-10-30 12:03:06 -070099 int contourCount = 0;
100 bool enabled = fSelected[0];
101 bool addMoveTo = true;
Chris Daltonde500372020-05-05 15:06:30 -0600102 for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) {
caryclarkef784fb2015-10-30 12:03:06 -0700103 if (enabled && addMoveTo) {
104 result.moveTo(pts[0]);
105 addMoveTo = false;
106 }
107 switch (verb) {
Chris Daltonde500372020-05-05 15:06:30 -0600108 case SkPathVerb::kMove:
caryclarkef784fb2015-10-30 12:03:06 -0700109 break;
Chris Daltonde500372020-05-05 15:06:30 -0600110 case SkPathVerb::kLine:
caryclarkef784fb2015-10-30 12:03:06 -0700111 if (enabled) {
112 result.lineTo(pts[1]);
113 }
114 break;
Chris Daltonde500372020-05-05 15:06:30 -0600115 case SkPathVerb::kQuad:
caryclarkef784fb2015-10-30 12:03:06 -0700116 if (enabled) {
117 result.quadTo(pts[1], pts[2]);
118 }
119 break;
Chris Daltonde500372020-05-05 15:06:30 -0600120 case SkPathVerb::kConic:
caryclarkef784fb2015-10-30 12:03:06 -0700121 if (enabled) {
Chris Daltonde500372020-05-05 15:06:30 -0600122 result.conicTo(pts[1], pts[2], *w);
caryclarkef784fb2015-10-30 12:03:06 -0700123 }
124 break;
Chris Daltonde500372020-05-05 15:06:30 -0600125 case SkPathVerb::kCubic:
caryclarkef784fb2015-10-30 12:03:06 -0700126 if (enabled) {
127 result.cubicTo(pts[1], pts[2], pts[3]);
128 }
129 break;
Chris Daltonde500372020-05-05 15:06:30 -0600130 case SkPathVerb::kClose:
caryclarkef784fb2015-10-30 12:03:06 -0700131 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
148SubsetVerbs::SubsetVerbs(const SkPath& path)
149 : SubsetPath(path) {
caryclarkef784fb2015-10-30 12:03:06 -0700150 int verbCount = 0;
Chris Daltonde500372020-05-05 15:06:30 -0600151 for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) {
caryclarkef784fb2015-10-30 12:03:06 -0700152 switch (verb) {
Chris Daltonde500372020-05-05 15:06:30 -0600153 case SkPathVerb::kMove:
caryclarkef784fb2015-10-30 12:03:06 -0700154 break;
Chris Daltonde500372020-05-05 15:06:30 -0600155 case SkPathVerb::kLine:
156 case SkPathVerb::kQuad:
157 case SkPathVerb::kConic:
158 case SkPathVerb::kCubic:
caryclarkef784fb2015-10-30 12:03:06 -0700159 ++verbCount;
160 break;
Chris Daltonde500372020-05-05 15:06:30 -0600161 case SkPathVerb::kClose:
caryclarkef784fb2015-10-30 12:03:06 -0700162 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
174SkPath SubsetVerbs::getSubsetPath() const {
175 SkPath result;
176 result.setFillType(fPath.getFillType());
177 if (!fSelected.count()) {
178 return result;
179 }
caryclarkef784fb2015-10-30 12:03:06 -0700180 int verbIndex = 0;
181 bool addMoveTo = true;
182 bool addLineTo = false;
Chris Daltonde500372020-05-05 15:06:30 -0600183 for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) {
184 bool enabled = SkPathVerb::kLine <= verb && verb <= SkPathVerb::kCubic
Mike Klein22c1f372018-04-02 20:37:42 +0000185 ? fSelected[verbIndex++] : false;
caryclarkef784fb2015-10-30 12:03:06 -0700186 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) {
Chris Daltonde500372020-05-05 15:06:30 -0600196 case SkPathVerb::kMove:
caryclarkef784fb2015-10-30 12:03:06 -0700197 break;
Chris Daltonde500372020-05-05 15:06:30 -0600198 case SkPathVerb::kLine:
caryclarkef784fb2015-10-30 12:03:06 -0700199 if (enabled) {
200 result.lineTo(pts[1]);
201 }
202 break;
Chris Daltonde500372020-05-05 15:06:30 -0600203 case SkPathVerb::kQuad:
caryclarkef784fb2015-10-30 12:03:06 -0700204 if (enabled) {
205 result.quadTo(pts[1], pts[2]);
206 }
207 break;
Chris Daltonde500372020-05-05 15:06:30 -0600208 case SkPathVerb::kConic:
caryclarkef784fb2015-10-30 12:03:06 -0700209 if (enabled) {
Chris Daltonde500372020-05-05 15:06:30 -0600210 result.conicTo(pts[1], pts[2], *w);
caryclarkef784fb2015-10-30 12:03:06 -0700211 }
212 break;
Chris Daltonde500372020-05-05 15:06:30 -0600213 case SkPathVerb::kCubic:
caryclarkef784fb2015-10-30 12:03:06 -0700214 if (enabled) {
215 result.cubicTo(pts[1], pts[2], pts[3]);
216 }
217 break;
Chris Daltonde500372020-05-05 15:06:30 -0600218 case SkPathVerb::kClose:
caryclarkef784fb2015-10-30 12:03:06 -0700219 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}