Home | History | Annotate | Download | only in tests
      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