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