• 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 "SubsetPath.h"
9 #include "SkMathPriv.h"
10 
SubsetPath(const SkPath & path)11 SubsetPath::SubsetPath(const SkPath& path)
12         : fPath(path)
13         , fSubset(1) {
14 }
15 
range(int * end) const16 int 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 
subset(bool testFailed,SkPath * sub)27 bool 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 
SubsetContours(const SkPath & path)62 SubsetContours::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 
getSubsetPath() const95 SkPath 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 
SubsetVerbs(const SkPath & path)153 SubsetVerbs::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 
getSubsetPath() const182 SkPath 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 }
242