diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-11-29 21:05:13 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-11-29 21:05:13 +0000 |
commit | 8a98e3bd18f1a8914cbfe1461e1ff47f51286556 (patch) | |
tree | a2130c43113c0ad09d3ddae85ff7982a2e8a4d51 /include/core | |
parent | 2d47a21b27035798d53de4d5cb8ac7c03534ab27 (diff) |
Make SkClipStack::Element public.
R=robertphillips@google.com
Review URL: https://codereview.appspot.com/6858096
git-svn-id: http://skia.googlecode.com/svn/trunk@6617 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'include/core')
-rw-r--r-- | include/core/SkClipStack.h | 179 |
1 files changed, 163 insertions, 16 deletions
diff --git a/include/core/SkClipStack.h b/include/core/SkClipStack.h index 7b3078d8e4..eb825a9876 100644 --- a/include/core/SkClipStack.h +++ b/include/core/SkClipStack.h @@ -9,11 +9,11 @@ #define SkClipStack_DEFINED #include "SkDeque.h" +#include "SkPath.h" +#include "SkRect.h" #include "SkRegion.h" #include "SkTDArray.h" -struct SkRect; -class SkPath; // Because a single save/restore state can have multiple clips, this class // stores the stack depth (fSaveCount) and clips (fDeque) separately. @@ -23,6 +23,167 @@ class SkPath; // then the freshly decremented count. class SK_API SkClipStack { public: + enum BoundsType { + // The bounding box contains all the pixels that can be written to + kNormal_BoundsType, + // The bounding box contains all the pixels that cannot be written to. + // The real bound extends out to infinity and all the pixels outside + // of the bound can be written to. Note that some of the pixels inside + // the bound may also be writeable but all pixels that cannot be + // written to are guaranteed to be inside. + kInsideOut_BoundsType + }; + + class Element { + public: + enum Type { + //!< This element makes the clip empty (regardless of previous elements). + kEmpty_Type, + //!< This element combines a rect with the current clip using a set operation + kRect_Type, + //!< This element combines a path with the current clip using a set operation + kPath_Type, + }; + + Element() { + this->initCommon(0, SkRegion::kReplace_Op, false); + this->setEmpty(); + } + + Element(const SkRect& rect, SkRegion::Op op, bool doAA) { + this->initRect(0, rect, op, doAA); + } + + Element(const SkPath& path, SkRegion::Op op, bool doAA) { + this->initPath(0, path, op, doAA); + } + + //!< Call to get the type of the clip element. + Type getType() const { return fType; } + + //!< Call if getType() is kPath to get the path. + const SkPath& getPath() const { return fPath; } + + //!< Call if getType() is kRect to get the rect. + const SkRect& getRect() const { return fRect; } + + //!< Call if getType() is not kEmpty to get the set operation used to combine this element. + SkRegion::Op getOp() const { return fOp; } + + /** If getType() is not kEmpty this indicates whether the clip shape should be anti-aliased + when it is rasterized. */ + bool isAA() const { return fDoAA; } + + /** The GenID can be used by clip stack clients to cache representations of the clip. The + ID corresponds to the set of clip elements up to and including this element within the + stack not to the element itself. That is the same clip path in different stacks will + have a different ID since the elements produce different clip result in the context of + their stacks. */ + int32_t getGenID() const { return fGenID; } + + private: + friend class SkClipStack; + + SkPath fPath; + SkRect fRect; + int fSaveCount; // save count of stack when this element was added. + SkRegion::Op fOp; + Type fType; + bool fDoAA; + + /* fFiniteBoundType and fFiniteBound are used to incrementally update the clip stack's + bound. When fFiniteBoundType is kNormal_BoundsType, fFiniteBound represents the + conservative bounding box of the pixels that aren't clipped (i.e., any pixels that can be + drawn to are inside the bound). When fFiniteBoundType is kInsideOut_BoundsType (which + occurs when a clip is inverse filled), fFiniteBound represents the conservative bounding + box of the pixels that _are_ clipped (i.e., any pixels that cannot be drawn to are inside + the bound). When fFiniteBoundType is kInsideOut_BoundsType the actual bound is the + infinite plane. This behavior of fFiniteBoundType and fFiniteBound is required so that we + can capture the cancelling out of the extensions to infinity when two inverse filled + clips are Booleaned together. */ + SkClipStack::BoundsType fFiniteBoundType; + SkRect fFiniteBound; + + // When element is applied to the previous elements in the stack is the result known to be + // equivalent to a single rect intersection? IIOW, is the clip effectively a rectangle. + bool fIsIntersectionOfRects; + + int fGenID; + + Element(int saveCount) { + this->initCommon(saveCount, SkRegion::kReplace_Op, false); + this->setEmpty(); + } + + Element(int saveCount, const SkRect& rect, SkRegion::Op op, bool doAA) { + this->initRect(saveCount, rect, op, doAA); + } + + Element(int saveCount, const SkPath& path, SkRegion::Op op, bool doAA) { + this->initPath(saveCount, path, op, doAA); + } + + void initCommon(int saveCount, SkRegion::Op op, bool doAA) { + fSaveCount = saveCount; + fOp = op; + fDoAA = doAA; + // A default of inside-out and empty bounds means the bounds are effectively void as it + // indicates that nothing is known to be outside the clip. + fFiniteBoundType = kInsideOut_BoundsType; + fFiniteBound.setEmpty(); + fIsIntersectionOfRects = false; + fGenID = kInvalidGenID; + } + + void initRect(int saveCount, const SkRect& rect, SkRegion::Op op, bool doAA) { + fRect = rect; + fType = kRect_Type; + this->initCommon(saveCount, op, doAA); + } + + void initPath(int saveCount, const SkPath& path, SkRegion::Op op, bool doAA) { + fPath = path; + fType = kPath_Type; + this->initCommon(saveCount, op, doAA); + } + + void setEmpty() { + fType = kEmpty_Type; + fFiniteBound.setEmpty(); + fFiniteBoundType = kNormal_BoundsType; + fIsIntersectionOfRects = false; + fRect.setEmpty(); + fPath.reset(); + fGenID = kEmptyGenID; + } + + // All Element methods below are only used within SkClipStack.cpp + inline void checkEmpty() const; + inline bool operator==(const Element& b) const; + inline bool operator!=(const Element& b) const; + inline bool canBeIntersectedInPlace(int saveCount, SkRegion::Op op) const; + /* This method checks to see if two rect clips can be safely merged into one. The issue here + is that to be strictly correct all the edges of the resulting rect must have the same + anti-aliasing. */ + bool rectRectIntersectAllowed(const SkRect& newR, bool newAA) const; + /** Determines possible finite bounds for the Element given the previous element of the + stack */ + void updateBoundAndGenID(const Element* prior); + // The different combination of fill & inverse fill when combining bounding boxes + enum FillCombo { + kPrev_Cur_FillCombo, + kPrev_InvCur_FillCombo, + kInvPrev_Cur_FillCombo, + kInvPrev_InvCur_FillCombo + }; + // per-set operation functions used by updateBoundAndGenID(). + inline void combineBoundsDiff(FillCombo combination, const SkRect& prevFinite); + inline void combineBoundsXOR(int combination, const SkRect& prevFinite); + inline void combineBoundsUnion(int combination, const SkRect& prevFinite); + inline void combineBoundsIntersection(int combination, const SkRect& prevFinite); + inline void combineBoundsRevDiff(int combination, const SkRect& prevFinite); + }; + SkClipStack(); SkClipStack(const SkClipStack& b); explicit SkClipStack(const SkRect& r); @@ -39,17 +200,6 @@ public: void save(); void restore(); - enum BoundsType { - // The bounding box contains all the pixels that can be written to - kNormal_BoundsType, - // The bounding box contains all the pixels that cannot be written to. - // The real bound extends out to infinity and all the pixels outside - // of the bound can be written to. Note that some of the pixels inside - // the bound may also be writeable but all pixels that cannot be - // written to are guaranteed to be inside. - kInsideOut_BoundsType - }; - /** * getBounds places the current finite bound in its first parameter. In its * second, it indicates which kind of bound is being returned. If @@ -111,9 +261,6 @@ public: int32_t getTopmostGenID() const; -private: - struct Element; - public: class Iter { public: |