Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2010 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 #ifndef SkRasterClip_DEFINED
      9 #define SkRasterClip_DEFINED
     10 
     11 #include "SkRegion.h"
     12 #include "SkAAClip.h"
     13 
     14 class SkRasterClip {
     15 public:
     16     SkRasterClip(bool forceConservativeRects = false);
     17     SkRasterClip(const SkIRect&, bool forceConservativeRects = false);
     18     SkRasterClip(const SkRasterClip&);
     19     ~SkRasterClip();
     20 
     21     bool isForceConservativeRects() const { return fForceConservativeRects; }
     22 
     23     bool isBW() const { return fIsBW; }
     24     bool isAA() const { return !fIsBW; }
     25     const SkRegion& bwRgn() const { SkASSERT(fIsBW); return fBW; }
     26     const SkAAClip& aaRgn() const { SkASSERT(!fIsBW); return fAA; }
     27 
     28     bool isEmpty() const {
     29         SkASSERT(this->computeIsEmpty() == fIsEmpty);
     30         return fIsEmpty;
     31     }
     32 
     33     bool isRect() const {
     34         SkASSERT(this->computeIsRect() == fIsRect);
     35         return fIsRect;
     36     }
     37 
     38     bool isComplex() const;
     39     const SkIRect& getBounds() const;
     40 
     41     bool setEmpty();
     42     bool setRect(const SkIRect&);
     43 
     44     bool op(const SkIRect&, SkRegion::Op);
     45     bool op(const SkRegion&, SkRegion::Op);
     46     bool op(const SkRect&, const SkISize&, SkRegion::Op, bool doAA);
     47     bool op(const SkPath&, const SkISize&, SkRegion::Op, bool doAA);
     48 
     49     void translate(int dx, int dy, SkRasterClip* dst) const;
     50     void translate(int dx, int dy) {
     51         this->translate(dx, dy, this);
     52     }
     53 
     54     bool quickContains(const SkIRect& rect) const;
     55     bool quickContains(int left, int top, int right, int bottom) const {
     56         return quickContains(SkIRect::MakeLTRB(left, top, right, bottom));
     57     }
     58 
     59     /**
     60      *  Return true if this region is empty, or if the specified rectangle does
     61      *  not intersect the region. Returning false is not a guarantee that they
     62      *  intersect, but returning true is a guarantee that they do not.
     63      */
     64     bool quickReject(const SkIRect& rect) const {
     65         return !SkIRect::Intersects(this->getBounds(), rect);
     66     }
     67 
     68     // hack for SkCanvas::getTotalClip
     69     const SkRegion& forceGetBW();
     70 
     71 #ifdef SK_DEBUG
     72     void validate() const;
     73 #else
     74     void validate() const {}
     75 #endif
     76 
     77 private:
     78     SkRegion    fBW;
     79     SkAAClip    fAA;
     80     bool        fForceConservativeRects;
     81     bool        fIsBW;
     82     // these 2 are caches based on querying the right obj based on fIsBW
     83     bool        fIsEmpty;
     84     bool        fIsRect;
     85 
     86     bool computeIsEmpty() const {
     87         return fIsBW ? fBW.isEmpty() : fAA.isEmpty();
     88     }
     89 
     90     bool computeIsRect() const {
     91         return fIsBW ? fBW.isRect() : fAA.isRect();
     92     }
     93 
     94     bool updateCacheAndReturnNonEmpty(bool detectAARect = true) {
     95         fIsEmpty = this->computeIsEmpty();
     96 
     97         // detect that our computed AA is really just a (hard-edged) rect
     98         if (detectAARect && !fIsEmpty && !fIsBW && fAA.isRect()) {
     99             fBW.setRect(fAA.getBounds());
    100             fAA.setEmpty(); // don't need this guy anymore
    101             fIsBW = true;
    102         }
    103 
    104         fIsRect = this->computeIsRect();
    105         return !fIsEmpty;
    106     }
    107 
    108     void convertToAA();
    109 
    110     bool setPath(const SkPath& path, const SkRegion& clip, bool doAA);
    111     bool setPath(const SkPath& path, const SkIRect& clip, bool doAA);
    112     bool op(const SkRasterClip&, SkRegion::Op);
    113     bool setConservativeRect(const SkRect& r, const SkIRect& clipR, bool isInverse);
    114 };
    115 
    116 class SkAutoRasterClipValidate : SkNoncopyable {
    117 public:
    118     SkAutoRasterClipValidate(const SkRasterClip& rc) : fRC(rc) {
    119         fRC.validate();
    120     }
    121     ~SkAutoRasterClipValidate() {
    122         fRC.validate();
    123     }
    124 private:
    125     const SkRasterClip& fRC;
    126 };
    127 #define SkAutoRasterClipValidate(...) SK_REQUIRE_LOCAL_VAR(SkAutoRasterClipValidate)
    128 
    129 #ifdef SK_DEBUG
    130     #define AUTO_RASTERCLIP_VALIDATE(rc)    SkAutoRasterClipValidate arcv(rc)
    131 #else
    132     #define AUTO_RASTERCLIP_VALIDATE(rc)
    133 #endif
    134 
    135 ///////////////////////////////////////////////////////////////////////////////
    136 
    137 /**
    138  *  Encapsulates the logic of deciding if we need to change/wrap the blitter
    139  *  for aaclipping. If so, getRgn and getBlitter return modified values. If
    140  *  not, they return the raw blitter and (bw) clip region.
    141  *
    142  *  We need to keep the constructor/destructor cost as small as possible, so we
    143  *  can freely put this guy on the stack, and not pay too much for the case when
    144  *  we're really BW anyways.
    145  */
    146 class SkAAClipBlitterWrapper {
    147 public:
    148     SkAAClipBlitterWrapper();
    149     SkAAClipBlitterWrapper(const SkRasterClip&, SkBlitter*);
    150     SkAAClipBlitterWrapper(const SkAAClip*, SkBlitter*);
    151 
    152     void init(const SkRasterClip&, SkBlitter*);
    153 
    154     const SkIRect& getBounds() const {
    155         SkASSERT(fClipRgn);
    156         return fClipRgn->getBounds();
    157     }
    158     const SkRegion& getRgn() const {
    159         SkASSERT(fClipRgn);
    160         return *fClipRgn;
    161     }
    162     SkBlitter* getBlitter() {
    163         SkASSERT(fBlitter);
    164         return fBlitter;
    165     }
    166 
    167 private:
    168     SkRegion        fBWRgn;
    169     SkAAClipBlitter fAABlitter;
    170     // what we return
    171     const SkRegion* fClipRgn;
    172     SkBlitter* fBlitter;
    173 };
    174 
    175 #endif
    176