michael@0: /* michael@0: * Copyright 2010 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef SkRasterClip_DEFINED michael@0: #define SkRasterClip_DEFINED michael@0: michael@0: #include "SkRegion.h" michael@0: #include "SkAAClip.h" michael@0: michael@0: class SkRasterClip { michael@0: public: michael@0: SkRasterClip(); michael@0: SkRasterClip(const SkIRect&); michael@0: SkRasterClip(const SkRasterClip&); michael@0: ~SkRasterClip(); michael@0: michael@0: bool isBW() const { return fIsBW; } michael@0: bool isAA() const { return !fIsBW; } michael@0: const SkRegion& bwRgn() const { SkASSERT(fIsBW); return fBW; } michael@0: const SkAAClip& aaRgn() const { SkASSERT(!fIsBW); return fAA; } michael@0: michael@0: bool isEmpty() const { michael@0: SkASSERT(this->computeIsEmpty() == fIsEmpty); michael@0: return fIsEmpty; michael@0: } michael@0: michael@0: bool isRect() const { michael@0: SkASSERT(this->computeIsRect() == fIsRect); michael@0: return fIsRect; michael@0: } michael@0: michael@0: bool isComplex() const; michael@0: const SkIRect& getBounds() const; michael@0: michael@0: bool setEmpty(); michael@0: bool setRect(const SkIRect&); michael@0: michael@0: bool setPath(const SkPath& path, const SkRegion& clip, bool doAA); michael@0: bool setPath(const SkPath& path, const SkIRect& clip, bool doAA); michael@0: michael@0: bool op(const SkIRect&, SkRegion::Op); michael@0: bool op(const SkRegion&, SkRegion::Op); michael@0: bool op(const SkRasterClip&, SkRegion::Op); michael@0: bool op(const SkRect&, SkRegion::Op, bool doAA); michael@0: michael@0: void translate(int dx, int dy, SkRasterClip* dst) const; michael@0: void translate(int dx, int dy) { michael@0: this->translate(dx, dy, this); michael@0: } michael@0: michael@0: bool quickContains(const SkIRect& rect) const; michael@0: bool quickContains(int left, int top, int right, int bottom) const { michael@0: return quickContains(SkIRect::MakeLTRB(left, top, right, bottom)); michael@0: } michael@0: michael@0: /** michael@0: * Return true if this region is empty, or if the specified rectangle does michael@0: * not intersect the region. Returning false is not a guarantee that they michael@0: * intersect, but returning true is a guarantee that they do not. michael@0: */ michael@0: bool quickReject(const SkIRect& rect) const { michael@0: return this->isEmpty() || rect.isEmpty() || michael@0: !SkIRect::Intersects(this->getBounds(), rect); michael@0: } michael@0: michael@0: // hack for SkCanvas::getTotalClip michael@0: const SkRegion& forceGetBW(); michael@0: michael@0: #ifdef SK_DEBUG michael@0: void validate() const; michael@0: #else michael@0: void validate() const {} michael@0: #endif michael@0: michael@0: private: michael@0: SkRegion fBW; michael@0: SkAAClip fAA; michael@0: bool fIsBW; michael@0: // these 2 are caches based on querying the right obj based on fIsBW michael@0: bool fIsEmpty; michael@0: bool fIsRect; michael@0: michael@0: bool computeIsEmpty() const { michael@0: return fIsBW ? fBW.isEmpty() : fAA.isEmpty(); michael@0: } michael@0: michael@0: bool computeIsRect() const { michael@0: return fIsBW ? fBW.isRect() : false; michael@0: } michael@0: michael@0: bool updateCacheAndReturnNonEmpty() { michael@0: fIsEmpty = this->computeIsEmpty(); michael@0: fIsRect = this->computeIsRect(); michael@0: return !fIsEmpty; michael@0: } michael@0: michael@0: void convertToAA(); michael@0: }; michael@0: michael@0: class SkAutoRasterClipValidate : SkNoncopyable { michael@0: public: michael@0: SkAutoRasterClipValidate(const SkRasterClip& rc) : fRC(rc) { michael@0: fRC.validate(); michael@0: } michael@0: ~SkAutoRasterClipValidate() { michael@0: fRC.validate(); michael@0: } michael@0: private: michael@0: const SkRasterClip& fRC; michael@0: }; michael@0: #define SkAutoRasterClipValidate(...) SK_REQUIRE_LOCAL_VAR(SkAutoRasterClipValidate) michael@0: michael@0: #ifdef SK_DEBUG michael@0: #define AUTO_RASTERCLIP_VALIDATE(rc) SkAutoRasterClipValidate arcv(rc) michael@0: #else michael@0: #define AUTO_RASTERCLIP_VALIDATE(rc) michael@0: #endif michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: /** michael@0: * Encapsulates the logic of deciding if we need to change/wrap the blitter michael@0: * for aaclipping. If so, getRgn and getBlitter return modified values. If michael@0: * not, they return the raw blitter and (bw) clip region. michael@0: * michael@0: * We need to keep the constructor/destructor cost as small as possible, so we michael@0: * can freely put this guy on the stack, and not pay too much for the case when michael@0: * we're really BW anyways. michael@0: */ michael@0: class SkAAClipBlitterWrapper { michael@0: public: michael@0: SkAAClipBlitterWrapper(); michael@0: SkAAClipBlitterWrapper(const SkRasterClip&, SkBlitter*); michael@0: SkAAClipBlitterWrapper(const SkAAClip*, SkBlitter*); michael@0: michael@0: void init(const SkRasterClip&, SkBlitter*); michael@0: michael@0: const SkIRect& getBounds() const { michael@0: SkASSERT(fClipRgn); michael@0: return fClipRgn->getBounds(); michael@0: } michael@0: const SkRegion& getRgn() const { michael@0: SkASSERT(fClipRgn); michael@0: return *fClipRgn; michael@0: } michael@0: SkBlitter* getBlitter() { michael@0: SkASSERT(fBlitter); michael@0: return fBlitter; michael@0: } michael@0: michael@0: private: michael@0: SkRegion fBWRgn; michael@0: SkAAClipBlitter fAABlitter; michael@0: // what we return michael@0: const SkRegion* fClipRgn; michael@0: SkBlitter* fBlitter; michael@0: }; michael@0: michael@0: #endif