aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/core
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-11-29 21:05:13 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-11-29 21:05:13 +0000
commit8a98e3bd18f1a8914cbfe1461e1ff47f51286556 (patch)
treea2130c43113c0ad09d3ddae85ff7982a2e8a4d51 /include/core
parent2d47a21b27035798d53de4d5cb8ac7c03534ab27 (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.h179
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: