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 10 SubsetPath::SubsetPath(const SkPath& path) 11 : fPath(path) 12 , fSubset(1) { 13 } 14 15 int 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 26 bool 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 61 SubsetContours::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 94 SkPath 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 152 SubsetVerbs::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 181 SkPath 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 } 241