• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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