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