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