Home | History | Annotate | Download | only in core
      1 #include "SkClipStack.h"
      2 #include "SkPath.h"
      3 #include <new>
      4 
      5 struct SkClipStack::Rec {
      6     enum State {
      7         kEmpty_State,
      8         kRect_State,
      9         kPath_State
     10     };
     11 
     12     SkPath          fPath;
     13     SkRect          fRect;
     14     int             fSaveCount;
     15     SkRegion::Op    fOp;
     16     State           fState;
     17 
     18     Rec(int saveCount, const SkRect& rect, SkRegion::Op op) : fRect(rect) {
     19         fSaveCount = saveCount;
     20         fOp = op;
     21         fState = kRect_State;
     22     }
     23 
     24     Rec(int saveCount, const SkPath& path, SkRegion::Op op) : fPath(path) {
     25         fSaveCount = saveCount;
     26         fOp = op;
     27         fState = kPath_State;
     28     }
     29 
     30     bool operator==(const Rec& b) const {
     31         if (fSaveCount != b.fSaveCount || fOp != b.fOp || fState != b.fState) {
     32             return false;
     33         }
     34         switch (fState) {
     35             case kEmpty_State:
     36                 return true;
     37             case kRect_State:
     38                 return fRect == b.fRect;
     39             case kPath_State:
     40                 return fPath == b.fPath;
     41         }
     42         return false;  // Silence the compiler.
     43     }
     44 
     45     bool operator!=(const Rec& b) const {
     46         return !(*this == b);
     47     }
     48 
     49 
     50     /**
     51      *  Returns true if this Rec can be intersected in place with a new clip
     52      */
     53     bool canBeIntersected(int saveCount, SkRegion::Op op) const {
     54         if (kEmpty_State == fState && (
     55                     SkRegion::kDifference_Op == op ||
     56                     SkRegion::kIntersect_Op == op)) {
     57             return true;
     58         }
     59         return  fSaveCount == saveCount &&
     60                 SkRegion::kIntersect_Op == fOp &&
     61                 SkRegion::kIntersect_Op == op;
     62     }
     63 };
     64 
     65 SkClipStack::SkClipStack() : fDeque(sizeof(Rec)) {
     66     fSaveCount = 0;
     67 }
     68 
     69 SkClipStack::SkClipStack(const SkClipStack& b) : fDeque(sizeof(Rec)) {
     70     *this = b;
     71 }
     72 
     73 SkClipStack& SkClipStack::operator=(const SkClipStack& b) {
     74     if (this == &b) {
     75         return *this;
     76     }
     77     reset();
     78 
     79     fSaveCount = b.fSaveCount;
     80     SkDeque::F2BIter recIter(b.fDeque);
     81     for (const Rec* rec = (const Rec*)recIter.next();
     82             rec != NULL;
     83             rec = (const Rec*)recIter.next()) {
     84         new (fDeque.push_back()) Rec(*rec);
     85     }
     86 
     87     return *this;
     88 }
     89 
     90 bool SkClipStack::operator==(const SkClipStack& b) const {
     91     if (fSaveCount != b.fSaveCount || fDeque.count() != b.fDeque.count()) {
     92         return false;
     93     }
     94     SkDeque::F2BIter myIter(fDeque);
     95     SkDeque::F2BIter bIter(b.fDeque);
     96     const Rec* myRec = (const Rec*)myIter.next();
     97     const Rec* bRec = (const Rec*)bIter.next();
     98 
     99     while (myRec != NULL && bRec != NULL) {
    100         if (*myRec != *bRec) {
    101             return false;
    102         }
    103         myRec = (const Rec*)myIter.next();
    104         bRec = (const Rec*)bIter.next();
    105     }
    106     return myRec == NULL && bRec == NULL;
    107 }
    108 
    109 void SkClipStack::reset() {
    110     // don't have a reset() on SkDeque, so fake it here
    111     fDeque.~SkDeque();
    112     new (&fDeque) SkDeque(sizeof(Rec));
    113 
    114     fSaveCount = 0;
    115 }
    116 
    117 void SkClipStack::save() {
    118     fSaveCount += 1;
    119 }
    120 
    121 void SkClipStack::restore() {
    122     fSaveCount -= 1;
    123     while (!fDeque.empty()) {
    124         Rec* rec = (Rec*)fDeque.back();
    125         if (rec->fSaveCount <= fSaveCount) {
    126             break;
    127         }
    128         rec->~Rec();
    129         fDeque.pop_back();
    130     }
    131 }
    132 
    133 void SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op) {
    134     Rec* rec = (Rec*)fDeque.back();
    135     if (rec && rec->canBeIntersected(fSaveCount, op)) {
    136         switch (rec->fState) {
    137             case Rec::kEmpty_State:
    138                 return;
    139             case Rec::kRect_State:
    140                 if (!rec->fRect.intersect(rect)) {
    141                     rec->fState = Rec::kEmpty_State;
    142                 }
    143                 return;
    144             case Rec::kPath_State:
    145                 if (!SkRect::Intersects(rec->fPath.getBounds(), rect)) {
    146                     rec->fState = Rec::kEmpty_State;
    147                     return;
    148                 }
    149                 break;
    150         }
    151     }
    152     new (fDeque.push_back()) Rec(fSaveCount, rect, op);
    153 }
    154 
    155 void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op) {
    156     Rec* rec = (Rec*)fDeque.back();
    157     if (rec && rec->canBeIntersected(fSaveCount, op)) {
    158         const SkRect& pathBounds = path.getBounds();
    159         switch (rec->fState) {
    160             case Rec::kEmpty_State:
    161                 return;
    162             case Rec::kRect_State:
    163                 if (!SkRect::Intersects(rec->fRect, pathBounds)) {
    164                     rec->fState = Rec::kEmpty_State;
    165                     return;
    166                 }
    167                 break;
    168             case Rec::kPath_State:
    169                 if (!SkRect::Intersects(rec->fPath.getBounds(), pathBounds)) {
    170                     rec->fState = Rec::kEmpty_State;
    171                     return;
    172                 }
    173                 break;
    174         }
    175     }
    176     new (fDeque.push_back()) Rec(fSaveCount, path, op);
    177 }
    178 
    179 ///////////////////////////////////////////////////////////////////////////////
    180 
    181 SkClipStack::B2FIter::B2FIter() {
    182 }
    183 
    184 bool operator==(const SkClipStack::B2FIter::Clip& a,
    185                const SkClipStack::B2FIter::Clip& b) {
    186     return a.fOp == b.fOp &&
    187            ((a.fRect == NULL && b.fRect == NULL) || *a.fRect == *b.fRect) &&
    188            ((a.fPath == NULL && b.fPath == NULL) || *a.fPath == *b.fPath);
    189 }
    190 
    191 bool operator!=(const SkClipStack::B2FIter::Clip& a,
    192                const SkClipStack::B2FIter::Clip& b) {
    193     return !(a == b);
    194 }
    195 
    196 SkClipStack::B2FIter::B2FIter(const SkClipStack& stack) {
    197     this->reset(stack);
    198 }
    199 
    200 const SkClipStack::B2FIter::Clip* SkClipStack::B2FIter::next() {
    201     const SkClipStack::Rec* rec = (const SkClipStack::Rec*)fIter.next();
    202     if (NULL == rec) {
    203         return NULL;
    204     }
    205 
    206     switch (rec->fState) {
    207         case SkClipStack::Rec::kEmpty_State:
    208             fClip.fRect = NULL;
    209             fClip.fPath = NULL;
    210             break;
    211         case SkClipStack::Rec::kRect_State:
    212             fClip.fRect = &rec->fRect;
    213             fClip.fPath = NULL;
    214             break;
    215         case SkClipStack::Rec::kPath_State:
    216             fClip.fRect = NULL;
    217             fClip.fPath = &rec->fPath;
    218             break;
    219     }
    220     fClip.fOp = rec->fOp;
    221     return &fClip;
    222 }
    223 
    224 void SkClipStack::B2FIter::reset(const SkClipStack& stack) {
    225     fIter.reset(stack.fDeque);
    226 }
    227