123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- /*
- * Copyright 2010 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
- #ifndef SkRasterClip_DEFINED
- #define SkRasterClip_DEFINED
- #include "include/core/SkRegion.h"
- #include "include/private/SkMacros.h"
- #include "src/core/SkAAClip.h"
- class SkRRect;
- class SkConservativeClip {
- SkIRect fBounds;
- const SkIRect* fClipRestrictionRect;
- inline void applyClipRestriction(SkRegion::Op op, SkIRect* bounds) {
- if (op >= SkRegion::kUnion_Op && fClipRestrictionRect
- && !fClipRestrictionRect->isEmpty()) {
- if (!bounds->intersect(*fClipRestrictionRect)) {
- bounds->setEmpty();
- }
- }
- }
- public:
- SkConservativeClip() : fBounds(SkIRect::MakeEmpty()), fClipRestrictionRect(nullptr) {}
- bool isEmpty() const { return fBounds.isEmpty(); }
- bool isRect() const { return true; }
- const SkIRect& getBounds() const { return fBounds; }
- void setEmpty() { fBounds.setEmpty(); }
- void setRect(const SkIRect& r) { fBounds = r; }
- void setDeviceClipRestriction(const SkIRect* rect) {
- fClipRestrictionRect = rect;
- }
- void opRect(const SkRect&, const SkMatrix&, const SkIRect& limit, SkRegion::Op, bool isAA);
- void opRRect(const SkRRect&, const SkMatrix&, const SkIRect& limit, SkRegion::Op, bool isAA);
- void opPath(const SkPath&, const SkMatrix&, const SkIRect& limit, SkRegion::Op, bool isAA);
- void opRegion(const SkRegion&, SkRegion::Op);
- void opIRect(const SkIRect&, SkRegion::Op);
- };
- /**
- * Wraps a SkRegion and SkAAClip, so we have a single object that can represent either our
- * BW or antialiased clips.
- *
- * This class is optimized for the raster backend of canvas, but can be expense to keep up2date,
- * so it supports a runtime option (force-conservative-rects) to turn it into a super-fast
- * rect-only tracker. The gpu backend uses this since it does not need the result (it uses
- * SkClipStack instead).
- */
- class SkRasterClip {
- public:
- SkRasterClip();
- SkRasterClip(const SkIRect&);
- SkRasterClip(const SkRegion&);
- SkRasterClip(const SkRasterClip&);
- ~SkRasterClip();
- // Only compares the current state. Does not compare isForceConservativeRects(), so that field
- // could be different but this could still return true.
- bool operator==(const SkRasterClip&) const;
- bool operator!=(const SkRasterClip& other) const {
- return !(*this == other);
- }
- bool isBW() const { return fIsBW; }
- bool isAA() const { return !fIsBW; }
- const SkRegion& bwRgn() const { SkASSERT(fIsBW); return fBW; }
- const SkAAClip& aaRgn() const { SkASSERT(!fIsBW); return fAA; }
- bool isEmpty() const {
- SkASSERT(this->computeIsEmpty() == fIsEmpty);
- return fIsEmpty;
- }
- bool isRect() const {
- SkASSERT(this->computeIsRect() == fIsRect);
- return fIsRect;
- }
- bool isComplex() const;
- const SkIRect& getBounds() const;
- bool setEmpty();
- bool setRect(const SkIRect&);
- bool op(const SkIRect&, SkRegion::Op);
- bool op(const SkRegion&, SkRegion::Op);
- bool op(const SkRect&, const SkMatrix& matrix, const SkIRect&, SkRegion::Op, bool doAA);
- bool op(const SkRRect&, const SkMatrix& matrix, const SkIRect&, SkRegion::Op, bool doAA);
- bool op(const SkPath&, const SkMatrix& matrix, const SkIRect&, SkRegion::Op, bool doAA);
- void translate(int dx, int dy, SkRasterClip* dst) const;
- void translate(int dx, int dy) {
- this->translate(dx, dy, this);
- }
- bool quickContains(const SkIRect& rect) const;
- bool quickContains(int left, int top, int right, int bottom) const {
- return quickContains(SkIRect::MakeLTRB(left, top, right, bottom));
- }
- /**
- * Return true if this region is empty, or if the specified rectangle does
- * not intersect the region. Returning false is not a guarantee that they
- * intersect, but returning true is a guarantee that they do not.
- */
- bool quickReject(const SkIRect& rect) const {
- return !SkIRect::Intersects(this->getBounds(), rect);
- }
- // hack for SkCanvas::getTotalClip
- const SkRegion& forceGetBW();
- #ifdef SK_DEBUG
- void validate() const;
- #else
- void validate() const {}
- #endif
- void setDeviceClipRestriction(const SkIRect* rect) {
- fClipRestrictionRect = rect;
- }
- private:
- SkRegion fBW;
- SkAAClip fAA;
- bool fIsBW;
- // these 2 are caches based on querying the right obj based on fIsBW
- bool fIsEmpty;
- bool fIsRect;
- const SkIRect* fClipRestrictionRect = nullptr;
- bool computeIsEmpty() const {
- return fIsBW ? fBW.isEmpty() : fAA.isEmpty();
- }
- bool computeIsRect() const {
- return fIsBW ? fBW.isRect() : fAA.isRect();
- }
- bool updateCacheAndReturnNonEmpty(bool detectAARect = true) {
- fIsEmpty = this->computeIsEmpty();
- // detect that our computed AA is really just a (hard-edged) rect
- if (detectAARect && !fIsEmpty && !fIsBW && fAA.isRect()) {
- fBW.setRect(fAA.getBounds());
- fAA.setEmpty(); // don't need this guy anymore
- fIsBW = true;
- }
- fIsRect = this->computeIsRect();
- return !fIsEmpty;
- }
- void convertToAA();
- bool setPath(const SkPath& path, const SkRegion& clip, bool doAA);
- bool setPath(const SkPath& path, const SkIRect& clip, bool doAA);
- bool op(const SkRasterClip&, SkRegion::Op);
- bool setConservativeRect(const SkRect& r, const SkIRect& clipR, bool isInverse);
- inline void applyClipRestriction(SkRegion::Op op, SkIRect* bounds) {
- if (op >= SkRegion::kUnion_Op && fClipRestrictionRect
- && !fClipRestrictionRect->isEmpty()) {
- if (!bounds->intersect(*fClipRestrictionRect)) {
- bounds->setEmpty();
- }
- }
- }
- inline void applyClipRestriction(SkRegion::Op op, SkRect* bounds) {
- if (op >= SkRegion::kUnion_Op && fClipRestrictionRect
- && !fClipRestrictionRect->isEmpty()) {
- if (!bounds->intersect(SkRect::Make(*fClipRestrictionRect))) {
- bounds->setEmpty();
- }
- }
- }
- };
- class SkAutoRasterClipValidate : SkNoncopyable {
- public:
- SkAutoRasterClipValidate(const SkRasterClip& rc) : fRC(rc) {
- fRC.validate();
- }
- ~SkAutoRasterClipValidate() {
- fRC.validate();
- }
- private:
- const SkRasterClip& fRC;
- };
- #define SkAutoRasterClipValidate(...) SK_REQUIRE_LOCAL_VAR(SkAutoRasterClipValidate)
- #ifdef SK_DEBUG
- #define AUTO_RASTERCLIP_VALIDATE(rc) SkAutoRasterClipValidate arcv(rc)
- #else
- #define AUTO_RASTERCLIP_VALIDATE(rc)
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- /**
- * Encapsulates the logic of deciding if we need to change/wrap the blitter
- * for aaclipping. If so, getRgn and getBlitter return modified values. If
- * not, they return the raw blitter and (bw) clip region.
- *
- * We need to keep the constructor/destructor cost as small as possible, so we
- * can freely put this guy on the stack, and not pay too much for the case when
- * we're really BW anyways.
- */
- class SkAAClipBlitterWrapper {
- public:
- SkAAClipBlitterWrapper();
- SkAAClipBlitterWrapper(const SkRasterClip&, SkBlitter*);
- SkAAClipBlitterWrapper(const SkAAClip*, SkBlitter*);
- void init(const SkRasterClip&, SkBlitter*);
- const SkIRect& getBounds() const {
- SkASSERT(fClipRgn);
- return fClipRgn->getBounds();
- }
- const SkRegion& getRgn() const {
- SkASSERT(fClipRgn);
- return *fClipRgn;
- }
- SkBlitter* getBlitter() {
- SkASSERT(fBlitter);
- return fBlitter;
- }
- private:
- SkRegion fBWRgn;
- SkAAClipBlitter fAABlitter;
- // what we return
- const SkRegion* fClipRgn;
- SkBlitter* fBlitter;
- };
- #endif
|