aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-12-04 14:06:06 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-12-04 14:06:06 +0000
commit8182fa0cac76e7e6d583aebba060229230516887 (patch)
tree9857caea2550f6bf3645bd1297a8eeb91bed7843 /src
parente659c2e820de0b8d12d81247ed4430022ded0a90 (diff)
Make SkClipStack::Iter use SkClipStack::Element.
R=robertphillips@google.com Review URL: https://codereview.appspot.com/6871051 git-svn-id: http://skia.googlecode.com/svn/trunk@6661 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r--src/core/SkCanvas.cpp50
-rw-r--r--src/core/SkClipStack.cpp104
-rw-r--r--src/core/SkTLList.h10
-rw-r--r--src/gpu/GrClipMaskManager.cpp320
-rw-r--r--src/gpu/GrClipMaskManager.h8
-rw-r--r--src/pdf/SkPDFDevice.cpp47
6 files changed, 229 insertions, 310 deletions
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index c38ed7639a..34310c8248 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -1194,15 +1194,23 @@ void SkCanvas::validateClip() const {
SkRasterClip tmpClip(ir);
SkClipStack::B2TIter iter(fClipStack);
- const SkClipStack::B2TIter::Clip* clip;
- while ((clip = iter.next()) != NULL) {
- if (clip->fPath) {
- clipPathHelper(this, &tmpClip, *clip->fPath, clip->fOp, clip->fDoAA);
- } else if (clip->fRect) {
- clip->fRect->round(&ir);
- tmpClip.op(ir, clip->fOp);
- } else {
- tmpClip.setEmpty();
+ const SkClipStack::Element* element;
+ while ((element = iter.next()) != NULL) {
+ switch (element->getType()) {
+ case SkClipStack::Element::kPath_Type:
+ clipPathHelper(this,
+ &tmpClip,
+ element->getPath(),
+ element->getOp(),
+ element->isAA());
+ break;
+ case SkClipStack::Element::kRect_Type:
+ element->getRect().round(&ir);
+ tmpClip.op(ir, element->getOp());
+ break;
+ case SkClipStack::Element::kEmpty_Type:
+ tmpClip.setEmpty();
+ break;
}
}
@@ -1216,16 +1224,20 @@ void SkCanvas::validateClip() const {
void SkCanvas::replayClips(ClipVisitor* visitor) const {
SkClipStack::B2TIter iter(fClipStack);
- const SkClipStack::B2TIter::Clip* clip;
-
- SkRect empty = { 0, 0, 0, 0 };
- while ((clip = iter.next()) != NULL) {
- if (clip->fPath) {
- visitor->clipPath(*clip->fPath, clip->fOp, clip->fDoAA);
- } else if (clip->fRect) {
- visitor->clipRect(*clip->fRect, clip->fOp, clip->fDoAA);
- } else {
- visitor->clipRect(empty, SkRegion::kIntersect_Op, false);
+ const SkClipStack::Element* element;
+
+ static const SkRect kEmpty = { 0, 0, 0, 0 };
+ while ((element = iter.next()) != NULL) {
+ switch (element->getType()) {
+ case SkClipStack::Element::kPath_Type:
+ visitor->clipPath(element->getPath(), element->getOp(), element->isAA());
+ break;
+ case SkClipStack::Element::kRect_Type:
+ visitor->clipRect(element->getRect(), element->getOp(), element->isAA());
+ break;
+ case SkClipStack::Element::kEmpty_Type:
+ visitor->clipRect(kEmpty, SkRegion::kIntersect_Op, false);
+ break;
}
}
}
diff --git a/src/core/SkClipStack.cpp b/src/core/SkClipStack.cpp
index 33cd41f802..107c20f116 100644
--- a/src/core/SkClipStack.cpp
+++ b/src/core/SkClipStack.cpp
@@ -24,28 +24,6 @@ void SkClipStack::Element::checkEmpty() const {
SkASSERT(fPath.isEmpty());
}
-bool SkClipStack::Element::operator==(const Element& b) const {
- if (fSaveCount != b.fSaveCount ||
- fOp != b.fOp ||
- fType != b.fType ||
- fDoAA != b.fDoAA) {
- return false;
- }
- switch (fType) {
- case kEmpty_Type:
- return true;
- case kRect_Type:
- return fRect == b.fRect;
- case kPath_Type:
- return fPath == b.fPath;
- }
- return false; // Silence the compiler.
-}
-
-bool SkClipStack::Element::operator!=(const Element& b) const {
- return !(*this == b);
-}
-
bool SkClipStack::Element::canBeIntersectedInPlace(int saveCount, SkRegion::Op op) const {
if (kEmpty_Type == fType &&
(SkRegion::kDifference_Op == op || SkRegion::kIntersect_Op == op)) {
@@ -622,92 +600,20 @@ bool SkClipStack::isWideOpen() const {
SkClipStack::Iter::Iter() : fStack(NULL) {
}
-bool operator==(const SkClipStack::Iter::Clip& a,
- const SkClipStack::Iter::Clip& b) {
- return a.fOp == b.fOp && a.fDoAA == b.fDoAA &&
- ((a.fRect == NULL && b.fRect == NULL) ||
- (a.fRect != NULL && b.fRect != NULL && *a.fRect == *b.fRect)) &&
- ((a.fPath == NULL && b.fPath == NULL) ||
- (a.fPath != NULL && b.fPath != NULL && *a.fPath == *b.fPath));
-}
-
-bool operator!=(const SkClipStack::Iter::Clip& a,
- const SkClipStack::Iter::Clip& b) {
- return !(a == b);
-}
-
-const SkRect& SkClipStack::Iter::Clip::getBounds() const {
- if (NULL != fRect) {
- return *fRect;
- } else if (NULL != fPath) {
- return fPath->getBounds();
- } else {
- static const SkRect kEmpty = {0, 0, 0, 0};
- return kEmpty;
- }
-}
-
-bool SkClipStack::Iter::Clip::contains(const SkRect& rect) const {
- if (NULL != fRect) {
- return fRect->contains(rect);
- } else if (NULL != fPath) {
- return fPath->conservativelyContainsRect(rect);
- } else {
- return false;
- }
-}
-
-bool SkClipStack::Iter::Clip::isInverseFilled() const {
- return NULL != fPath && fPath->isInverseFillType();
-}
-
SkClipStack::Iter::Iter(const SkClipStack& stack, IterStart startLoc)
: fStack(&stack) {
this->reset(stack, startLoc);
}
-const SkClipStack::Iter::Clip* SkClipStack::Iter::updateClip(
- const SkClipStack::Element* element) {
- switch (element->fType) {
- case SkClipStack::Element::kEmpty_Type:
- fClip.fRect = NULL;
- fClip.fPath = NULL;
- element->checkEmpty();
- break;
- case SkClipStack::Element::kRect_Type:
- fClip.fRect = &element->fRect;
- fClip.fPath = NULL;
- break;
- case SkClipStack::Element::kPath_Type:
- fClip.fRect = NULL;
- fClip.fPath = &element->fPath;
- break;
- }
- fClip.fOp = element->fOp;
- fClip.fDoAA = element->fDoAA;
- fClip.fGenID = element->fGenID;
- return &fClip;
+const SkClipStack::Element* SkClipStack::Iter::next() {
+ return (const SkClipStack::Element*)fIter.next();
}
-const SkClipStack::Iter::Clip* SkClipStack::Iter::next() {
- const SkClipStack::Element* element = (const SkClipStack::Element*)fIter.next();
- if (NULL == element) {
- return NULL;
- }
-
- return this->updateClip(element);
-}
-
-const SkClipStack::Iter::Clip* SkClipStack::Iter::prev() {
- const SkClipStack::Element* element = (const SkClipStack::Element*)fIter.prev();
- if (NULL == element) {
- return NULL;
- }
-
- return this->updateClip(element);
+const SkClipStack::Element* SkClipStack::Iter::prev() {
+ return (const SkClipStack::Element*)fIter.prev();
}
-const SkClipStack::Iter::Clip* SkClipStack::Iter::skipToTopmost(SkRegion::Op op) {
+const SkClipStack::Element* SkClipStack::Iter::skipToTopmost(SkRegion::Op op) {
if (NULL == fStack) {
return NULL;
diff --git a/src/core/SkTLList.h b/src/core/SkTLList.h
index 87fd52d32e..30d440fd4e 100644
--- a/src/core/SkTLList.h
+++ b/src/core/SkTLList.h
@@ -350,7 +350,13 @@ void *operator new(size_t, SkTLList<T>* list,
}
#define SkNEW_INSERT_IN_LLIST_BEFORE(list, location, type_name, args) \
- (new (list, SkTLList< type_name >::kBefore_Placement, location) type_name args)
+ (new ((list), SkTLList< type_name >::kBefore_Placement, (location)) type_name args)
#define SkNEW_INSERT_IN_LLIST_AFTER(list, location, type_name, args) \
- (new (list, SkTLList< type_name >::kAfter_Placement, location) type_name args)
+ (new ((list), SkTLList< type_name >::kAfter_Placement, (location)) type_name args)
+
+#define SkNEW_INSERT_AT_LLIST_HEAD(list, type_name, args) \
+ SkNEW_INSERT_IN_LLIST_BEFORE((list), (list)->headIter(), type_name, args)
+
+#define SkNEW_INSERT_AT_LLIST_TAIL(list, type_name, args) \
+ SkNEW_INSERT_IN_LLIST_AFTER((list), (list)->tailIter(), type_name, args) \ No newline at end of file
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index fdaa067c9d..64ead1a336 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -24,6 +24,7 @@ GR_DEFINE_RESOURCE_CACHE_DOMAIN(GrClipMaskManager, GetAlphaMaskDomain)
#define GR_AA_CLIP 1
#define GR_SW_CLIP 1
+typedef SkClipStack::Element Element;
////////////////////////////////////////////////////////////////////////////////
namespace GrReducedClip {
@@ -38,11 +39,11 @@ based on later intersect operations, and perhaps remove intersect-rects. We coul
take a rect in case the caller knows a bound on what is to be drawn through this clip.
*/
void GrReduceClipStack(const SkClipStack& stack,
- SkTDArray<SkClipStack::Iter::Clip>* resultClips,
+ ElementList* result,
SkRect* resultBounds,
bool* resultsAreBounded,
InitialState* initialState) {
- resultClips->reset();
+ result->reset();
if (stack.isWideOpen()) {
*initialState = kAllIn_InitialState;
@@ -56,15 +57,10 @@ void GrReduceClipStack(const SkClipStack& stack,
if (iior) {
*resultsAreBounded = true;
*initialState = kAllOut_InitialState;
- SkClipStack::Iter::Clip* clip = resultClips->append();
- // append doesn't call the default cons.
- *clip = SkClipStack::Iter::Clip();
-
- // iior should only be true if aa/non-aa status matches.
SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
- clip->fDoAA = iter.prev()->fDoAA;
- clip->fOp = SkRegion::kReplace_Op;
- clip->fRect = resultBounds;
+ // iior should only be true if aa/non-aa status matches among all elements.
+ bool doAA = iter.prev()->isAA();
+ SkNEW_INSERT_AT_LLIST_TAIL(result, Element, (*resultBounds, SkRegion::kReplace_Op, doAA));
return;
}
@@ -85,16 +81,16 @@ void GrReduceClipStack(const SkClipStack& stack,
SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
while ((kUnknown_InitialState == *initialState)) {
- const SkClipStack::Iter::Clip* clip = iter.prev();
- if (NULL == clip) {
+ const Element* element = iter.prev();
+ if (NULL == element) {
*initialState = kAllIn_InitialState;
break;
}
- if (SkClipStack::kEmptyGenID == clip->fGenID) {
+ if (SkClipStack::kEmptyGenID == element->getGenID()) {
*initialState = kAllOut_InitialState;
break;
}
- if (SkClipStack::kWideOpenGenID == clip->fGenID) {
+ if (SkClipStack::kWideOpenGenID == element->getGenID()) {
*initialState = kAllIn_InitialState;
break;
}
@@ -102,23 +98,23 @@ void GrReduceClipStack(const SkClipStack& stack,
bool skippable = false;
bool isFlip = false; // does this op just flip the in/out state of every point in the bounds
- switch (clip->fOp) {
+ switch (element->getOp()) {
case SkRegion::kDifference_Op:
if (*resultsAreBounded) {
// check if the shape subtracted either contains the entire bounds (and makes
// the clip empty) or is outside the bounds and therefore can be skipped.
- if (clip->isInverseFilled()) {
- if (clip->contains(*resultBounds)) {
+ if (element->isInverseFilled()) {
+ if (element->contains(*resultBounds)) {
skippable = true;
- } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+ } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
*initialState = kAllOut_InitialState;
skippable = true;
}
} else {
- if (clip->contains(*resultBounds)) {
+ if (element->contains(*resultBounds)) {
*initialState = kAllOut_InitialState;
skippable = true;
- } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+ } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
skippable = true;
}
}
@@ -132,17 +128,17 @@ void GrReduceClipStack(const SkClipStack& stack,
// check if the shape intersected contains the entire bounds and therefore can
// be skipped or it is outside the entire bounds and therefore makes the clip
// empty.
- if (clip->isInverseFilled()) {
- if (clip->contains(*resultBounds)) {
+ if (element->isInverseFilled()) {
+ if (element->contains(*resultBounds)) {
*initialState = kAllOut_InitialState;
skippable = true;
- } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+ } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
skippable = true;
}
} else {
- if (clip->contains(*resultBounds)) {
+ if (element->contains(*resultBounds)) {
skippable = true;
- } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+ } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
*initialState = kAllOut_InitialState;
skippable = true;
}
@@ -157,18 +153,18 @@ void GrReduceClipStack(const SkClipStack& stack,
// If the union-ed shape contains the entire bounds then after this element
// the bounds is entirely inside the clip. If the union-ed shape is outside the
// bounds then this op can be skipped.
- if (clip->isInverseFilled()) {
- if (clip->contains(*resultBounds)) {
+ if (element->isInverseFilled()) {
+ if (element->contains(*resultBounds)) {
skippable = true;
- } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+ } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
*initialState = kAllIn_InitialState;
skippable = true;
}
} else {
- if (clip->contains(*resultBounds)) {
+ if (element->contains(*resultBounds)) {
*initialState = kAllIn_InitialState;
skippable = true;
- } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+ } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
skippable = true;
}
}
@@ -183,16 +179,16 @@ void GrReduceClipStack(const SkClipStack& stack,
// to flip the inside/outside state of every point in the bounds. We may be
// able to take advantage of this in the forward pass. If the xor-ed shape
// doesn't intersect the bounds then it can be skipped.
- if (clip->isInverseFilled()) {
- if (clip->contains(*resultBounds)) {
+ if (element->isInverseFilled()) {
+ if (element->contains(*resultBounds)) {
skippable = true;
- } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+ } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
isFlip = true;
}
} else {
- if (clip->contains(*resultBounds)) {
+ if (element->contains(*resultBounds)) {
isFlip = true;
- } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+ } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
skippable = true;
}
}
@@ -207,17 +203,17 @@ void GrReduceClipStack(const SkClipStack& stack,
// the bounds then we know after this element is applied that the bounds will be
// all outside the current clip.B
if (*resultsAreBounded) {
- if (clip->isInverseFilled()) {
- if (clip->contains(*resultBounds)) {
+ if (element->isInverseFilled()) {
+ if (element->contains(*resultBounds)) {
*initialState = kAllOut_InitialState;
skippable = true;
- } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+ } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
isFlip = true;
}
} else {
- if (clip->contains(*resultBounds)) {
+ if (element->contains(*resultBounds)) {
isFlip = true;
- } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+ } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
*initialState = kAllOut_InitialState;
skippable = true;
}
@@ -233,19 +229,19 @@ void GrReduceClipStack(const SkClipStack& stack,
// or completely outside the bounds. In this latter case it can be skipped by
// setting the correct value for initialState.
if (*resultsAreBounded) {
- if (clip->isInverseFilled()) {
- if (clip->contains(*resultBounds)) {
+ if (element->isInverseFilled()) {
+ if (element->contains(*resultBounds)) {
*initialState = kAllOut_InitialState;
skippable = true;
- } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+ } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
*initialState = kAllIn_InitialState;
skippable = true;
}
} else {
- if (clip->contains(*resultBounds)) {
+ if (element->contains(*resultBounds)) {
*initialState = kAllIn_InitialState;
skippable = true;
- } else if (!SkRect::Intersects(clip->getBounds(), *resultBounds)) {
+ } else if (!SkRect::Intersects(element->getBounds(), *resultBounds)) {
*initialState = kAllOut_InitialState;
skippable = true;
}
@@ -261,32 +257,28 @@ void GrReduceClipStack(const SkClipStack& stack,
break;
}
if (!skippable) {
- SkClipStack::Iter::Clip* newClip = resultClips->prepend();
// if it is a flip, change it to a bounds-filling rect
if (isFlip) {
- SkASSERT(SkRegion::kXOR_Op == clip->fOp ||
- SkRegion::kReverseDifference_Op == clip->fOp);
- newClip->fPath = NULL;
- newClip->fRect = resultBounds;
- // assuming this is faster to perform on GPU with stenciling than xor.
- newClip->fOp = SkRegion::kReverseDifference_Op;
- newClip->fDoAA = false;
- newClip->fGenID = SkClipStack::kInvalidGenID;
+ SkASSERT(SkRegion::kXOR_Op == element->getOp() ||
+ SkRegion::kReverseDifference_Op == element->getOp());
+ SkNEW_INSERT_AT_LLIST_HEAD(result,
+ Element,
+ (*resultBounds, SkRegion::kReverseDifference_Op, false));
} else {
- *newClip = *clip;
+ result->addToHead(*element);
}
}
}
if ((kAllOut_InitialState == *initialState && !embiggens) ||
(kAllIn_InitialState == *initialState && !emsmallens)) {
- resultClips->reset();
+ result->reset();
} else {
int clipsToSkip = 0;
- while (1) {
- SkClipStack::Iter::Clip* clip = &(*resultClips)[clipsToSkip];
+ Element* element = result->headIter().get();
+ while (NULL != element) {
bool skippable = false;
- switch (clip->fOp) {
+ switch (element->getOp()) {
case SkRegion::kDifference_Op:
// subtracting from the empty set yields the empty set.
skippable = kAllOut_InitialState == *initialState;
@@ -301,13 +293,13 @@ void GrReduceClipStack(const SkClipStack& stack,
skippable = true;
} else {
// unioning the empty set with a shape is the shape.
- clip->fOp = SkRegion::kReplace_Op;
+ element->setOp(SkRegion::kReplace_Op);
}
break;
case SkRegion::kXOR_Op:
if (kAllOut_InitialState == *initialState) {
// xor could be changed to diff in the kAllIn case, not sure it's a win.
- clip->fOp = SkRegion::kReplace_Op;
+ element->setOp(SkRegion::kReplace_Op);
}
break;
case SkRegion::kReverseDifference_Op:
@@ -317,15 +309,15 @@ void GrReduceClipStack(const SkClipStack& stack,
*initialState = kAllOut_InitialState;
} else {
// this picks up flips inserted in the backwards pass.
- if (*resultsAreBounded && NULL != clip->fRect) {
- skippable = clip->isInverseFilled() ?
- !SkRect::Intersects(clip->getBounds(), *resultBounds) :
- clip->contains(*resultBounds);
+ if (*resultsAreBounded) {
+ skippable = element->isInverseFilled() ?
+ !SkRect::Intersects(element->getBounds(), *resultBounds) :
+ element->contains(*resultBounds);
}
if (skippable) {
*initialState = kAllIn_InitialState;
} else {
- clip->fOp = SkRegion::kReplace_Op;
+ element->setOp(SkRegion::kReplace_Op);
}
}
break;
@@ -341,13 +333,10 @@ void GrReduceClipStack(const SkClipStack& stack,
if (!skippable) {
break;
} else {
- ++clipsToSkip;
- if (clipsToSkip == resultClips->count()) {
- break;
- }
+ result->popHead();
+ element = result->headIter().get();
}
}
- resultClips->remove(0, clipsToSkip);
}
}
} // namespace GrReducedClip
@@ -413,12 +402,12 @@ bool requires_AA(const SkClipStack& clipIn) {
SkClipStack::Iter iter;
iter.reset(clipIn, SkClipStack::Iter::kBottom_IterStart);
- const SkClipStack::Iter::Clip* clip = NULL;
- for (clip = iter.skipToTopmost(SkRegion::kReplace_Op);
- NULL != clip;
- clip = iter.next()) {
+ const Element* element = NULL;
+ for (element = iter.skipToTopmost(SkRegion::kReplace_Op);
+ NULL != element;
+ element = iter.next()) {
- if (clip->fDoAA) {
+ if (element->isAA()) {
return true;
}
}
@@ -441,19 +430,19 @@ bool GrClipMaskManager::useSWOnlyPath(const SkClipStack& clipIn) {
bool useSW = false;
SkClipStack::Iter iter(clipIn, SkClipStack::Iter::kBottom_IterStart);
- const SkClipStack::Iter::Clip* clip = NULL;
+ const Element* element = NULL;
- for (clip = iter.skipToTopmost(SkRegion::kReplace_Op);
- NULL != clip;
- clip = iter.next()) {
+ for (element = iter.skipToTopmost(SkRegion::kReplace_Op);
+ NULL != element;
+ element = iter.next()) {
// rects can always be drawn directly w/o using the software path
// so only paths need to be checked
- if (NULL != clip->fPath &&
+ if (Element::kPath_Type == element->getType() &&
path_needs_SW_renderer(this->getContext(), fGpu,
- *clip->fPath,
- get_path_fill(*clip->fPath),
- clip->fDoAA)) {
+ element->getPath(),
+ get_path_fill(element->getPath()),
+ element->isAA())) {
useSW = true;
}
}
@@ -598,7 +587,7 @@ bool contains(const SkRect& canvContainer,
// determines how many elements at the head of the clip can be skipped and
// whether the initial clear should be to the inside- or outside-the-clip value,
// and what op should be used to draw the first element that isn't skipped.
-const SkClipStack::Iter::Clip* process_initial_clip_elements(
+const SkClipStack::Element* process_initial_clip_elements(
SkClipStack::Iter* iter,
const GrIRect& devBounds,
bool* clearToInside,
@@ -615,12 +604,12 @@ const SkClipStack::Iter::Clip* process_initial_clip_elements(
bool done = false;
*clearToInside = true;
- const SkClipStack::Iter::Clip* clip = NULL;
+ const SkClipStack::Element* element = NULL;
- for (clip = iter->skipToTopmost(SkRegion::kReplace_Op);
- NULL != clip && !done;
- clip = iter->next()) {
- switch (clip->fOp) {
+ for (element = iter->skipToTopmost(SkRegion::kReplace_Op);
+ NULL != element && !done;
+ element = iter->next()) {
+ switch (element->getOp()) {
case SkRegion::kReplace_Op:
// replace ignores everything previous
*firstOp = SkRegion::kReplace_Op;
@@ -630,8 +619,8 @@ const SkClipStack::Iter::Clip* process_initial_clip_elements(
case SkRegion::kIntersect_Op:
// if this element contains the entire bounds then we
// can skip it.
- if (NULL != clip->fRect &&
- contains(*clip->fRect, devBounds, clipData.fOrigin)) {
+ if (Element::kRect_Type == element->getType() &&
+ contains(element->getRect(), devBounds, clipData.fOrigin)) {
break;
}
// if everything is initially clearToInside then intersect is
@@ -674,7 +663,7 @@ const SkClipStack::Iter::Clip* process_initial_clip_elements(
break;
case SkRegion::kReverseDifference_Op:
// if all pixels are clearToInside then reverse difference
- // produces empty set. Otherise it is same as replace
+ // produces empty set. Otherwise it is same as replace
if (*clearToInside) {
*clearToInside = false;
} else {
@@ -692,7 +681,7 @@ const SkClipStack::Iter::Clip* process_initial_clip_elements(
break;
}
}
- return clip;
+ return element;
}
}
@@ -786,27 +775,31 @@ void device_to_canvas(SkRect* rect, const SkIPoint& origin) {
////////////////////////////////////////////////////////////////////////////////
bool GrClipMaskManager::drawClipShape(GrTexture* target,
- const SkClipStack::Iter::Clip* clip,
+ const SkClipStack::Element* element,
const GrIRect& resultBounds) {
GrDrawState* drawState = fGpu->drawState();
GrAssert(NULL != drawState);
drawState->setRenderTarget(target->asRenderTarget());
- if (NULL != clip->fRect) {
- if (clip->fDoAA) {
- getContext()->getAARectRenderer()->fillAARect(fGpu, fGpu,
- *clip->fRect,
- true);
- } else {
- fGpu->drawSimpleRect(*clip->fRect, NULL);
- }
- } else if (NULL != clip->fPath) {
- return draw_path(this->getContext(), fGpu,
- *clip->fPath,
- get_path_fill(*clip->fPath),
- clip->fDoAA,
- resultBounds);
+ switch (element->getType()) {
+ case Element::kRect_Type:
+ if (element->isAA()) {
+ getContext()->getAARectRenderer()->fillAARect(fGpu, fGpu, element->getRect(), true);
+ } else {
+ fGpu->drawSimpleRect(element->getRect(), NULL);
+ }
+ return true;
+ case Element::kPath_Type:
+ return draw_path(this->getContext(), fGpu,
+ element->getPath(),
+ get_path_fill(element->getPath()),
+ element->isAA(),
+ resultBounds);
+ default:
+ // something is wrong if we're trying to draw an empty element.
+ GrCrash("Unexpected element type");
+ return false;
}
return true;
}
@@ -951,11 +944,11 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
SkClipStack::Iter iter(*clipDataIn.fClipStack,
SkClipStack::Iter::kBottom_IterStart);
- const SkClipStack::Iter::Clip* clip = process_initial_clip_elements(&iter,
- *devResultBounds,
- &clearToInside,
- &firstOp,
- clipDataIn);
+ const Element* element = process_initial_clip_elements(&iter,
+ *devResultBounds,
+ &clearToInside,
+ &firstOp,
+ clipDataIn);
// The scratch texture that we are drawing into can be substantially larger than the mask. Only
// clear the part that we care about.
fGpu->clear(&maskResultBounds,
@@ -966,9 +959,9 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
GrAutoScratchTexture temp;
bool first = true;
// walk through each clip element and perform its set op
- for ( ; NULL != clip; clip = iter.next()) {
+ for ( ; NULL != element; element = iter.next()) {
- SkRegion::Op op = clip->fOp;
+ SkRegion::Op op = element->getOp();
if (first) {
first = false;
op = firstOp;
@@ -981,13 +974,13 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
}
setup_boolean_blendcoeffs(drawState, op);
- this->drawClipShape(accum, clip, *devResultBounds);
+ this->drawClipShape(accum, element, *devResultBounds);
} else if (SkRegion::kReverseDifference_Op == op ||
SkRegion::kIntersect_Op == op) {
// there is no point in intersecting a screen filling rectangle.
- if (SkRegion::kIntersect_Op == op && NULL != clip->fRect &&
- contains(*clip->fRect, *devResultBounds, clipDataIn.fOrigin)) {
+ if (SkRegion::kIntersect_Op == op && Element::kRect_Type == element->getType() &&
+ contains(element->getRect(), *devResultBounds, clipDataIn.fOrigin)) {
continue;
}
@@ -1001,7 +994,7 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
// mask buffer can be substantially larger than the actually clip stack element. We
// touch the minimum number of pixels necessary and use decal mode to combine it with
// the accumulator
- GrRect elementMaskBounds = clip->getBounds();
+ GrRect elementMaskBounds = element->getBounds();
elementMaskBounds.offset(clipToMaskOffset);
GrIRect elementMaskIBounds;
elementMaskBounds.roundOut(&elementMaskIBounds);
@@ -1010,7 +1003,7 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
fGpu->clear(&elementMaskIBounds, 0x00000000, temp.texture()->asRenderTarget());
setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op);
- this->drawClipShape(temp.texture(), clip, elementMaskIBounds);
+ this->drawClipShape(temp.texture(), element, elementMaskIBounds);
// Now draw into the accumulator using the real operation
// and the temp buffer as a texture
@@ -1019,7 +1012,7 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
// all the remaining ops can just be directly draw into
// the accumulation buffer
setup_boolean_blendcoeffs(drawState, op);
- this->drawClipShape(accum, clip, *devResultBounds);
+ this->drawClipShape(accum, element, *devResultBounds);
}
accumClearedToZero = false;
}
@@ -1096,25 +1089,25 @@ bool GrClipMaskManager::createStencilClipMask(const GrClipData& clipDataIn,
SkClipStack::Iter iter(*oldClipData->fClipStack,
SkClipStack::Iter::kBottom_IterStart);
- const SkClipStack::Iter::Clip* clip = process_initial_clip_elements(&iter,
- devRTRect,
- &clearToInside,
- &firstOp,
- clipDataIn);
+ const Element* element = process_initial_clip_elements(&iter,
+ devRTRect,
+ &clearToInside,
+ &firstOp,
+ clipDataIn);
fGpu->clearStencilClip(devClipBounds, clearToInside);
bool first = true;
// walk through each clip element and perform its set op
// with the existing clip.
- for ( ; NULL != clip; clip = iter.next()) {
+ for ( ; NULL != element; element = iter.next()) {
GrPathFill fill;
bool fillInverted = false;
// enabled at bottom of loop
drawState->disableState(GrGpu::kModifyStencilClip_StateBit);
// if the target is MSAA then we want MSAA enabled when the clip is soft
if (rt->isMultisampled()) {
- drawState->setState(GrDrawState::kHWAntialias_StateBit, clip->fDoAA);
+ drawState->setState(GrDrawState::kHWAntialias_StateBit, element->isAA());
}
// Can the clip element be drawn directly to the stencil buffer
@@ -1122,7 +1115,7 @@ bool GrClipMaskManager::createStencilClipMask(const GrClipData& clipDataIn,
// resolve in/out status?
bool canRenderDirectToStencil = false;
- SkRegion::Op op = clip->fOp;
+ SkRegion::Op op = element->getOp();
if (first) {
first = false;
op = firstOp;
@@ -1130,22 +1123,22 @@ bool GrClipMaskManager::createStencilClipMask(const GrClipData& clipDataIn,
GrPathRenderer* pr = NULL;
const SkPath* clipPath = NULL;
- if (NULL != clip->fRect) {
+ if (Element::kRect_Type == element->getType()) {
canRenderDirectToStencil = true;
fill = kEvenOdd_GrPathFill;
fillInverted = false;
// there is no point in intersecting a screen filling
// rectangle.
if (SkRegion::kIntersect_Op == op &&
- contains(*clip->fRect, devRTRect, oldClipData->fOrigin)) {
+ contains(element->getRect(), devRTRect, oldClipData->fOrigin)) {
continue;
}
} else {
- GrAssert(NULL != clip->fPath);
- fill = get_path_fill(*clip->fPath);
+ GrAssert(Element::kPath_Type == element->getType());
+ clipPath = &element->getPath();
+ fill = get_path_fill(*clipPath);
fillInverted = GrIsFillInverted(fill);
fill = GrNonInvertedFill(fill);
- clipPath = clip->fPath;
pr = this->getContext()->getPathRenderer(*clipPath, fill, fGpu, false, true);
if (NULL == pr) {
fGpu->setClip(oldClipData);
@@ -1180,10 +1173,11 @@ bool GrClipMaskManager::createStencilClipMask(const GrClipData& clipDataIn,
0x0000,
0xffff);
SET_RANDOM_COLOR
- if (NULL != clip->fRect) {
+ if (Element::kRect_Type == element->getType()) {
*drawState->stencil() = gDrawToStencil;
- fGpu->drawSimpleRect(*clip->fRect, NULL);
+ fGpu->drawSimpleRect(element->getRect(), NULL);
} else {
+ GrAssert(Element::kPath_Type == element->getType());
if (canRenderDirectToStencil) {
*drawState->stencil() = gDrawToStencil;
pr->drawPath(*clipPath, fill, fGpu, false);
@@ -1199,10 +1193,11 @@ bool GrClipMaskManager::createStencilClipMask(const GrClipData& clipDataIn,
for (int p = 0; p < passes; ++p) {
*drawState->stencil() = stencilSettings[p];
if (canDrawDirectToClip) {
- if (NULL != clip->fRect) {
+ if (Element::kRect_Type == element->getType()) {
SET_RANDOM_COLOR
- fGpu->drawSimpleRect(*clip->fRect, NULL);
+ fGpu->drawSimpleRect(element->getRect(), NULL);
} else {
+ GrAssert(Element::kPath_Type == element->getType());
SET_RANDOM_COLOR
pr->drawPath(*clipPath, fill, fGpu, false);
}
@@ -1464,18 +1459,18 @@ bool GrClipMaskManager::createSoftwareClipMask(const GrClipData& clipDataIn,
SkClipStack::Iter iter(*clipDataIn.fClipStack,
SkClipStack::Iter::kBottom_IterStart);
- const SkClipStack::Iter::Clip* clip = process_initial_clip_elements(&iter,
- *devResultBounds,
- &clearToInside,
- &firstOp,
- clipDataIn);
+ const Element* element = process_initial_clip_elements(&iter,
+ *devResultBounds,
+ &clearToInside,
+ &firstOp,
+ clipDataIn);
helper.clear(clearToInside ? 0xFF : 0x00);
bool first = true;
- for ( ; NULL != clip; clip = iter.next()) {
+ for ( ; NULL != element; element = iter.next()) {
- SkRegion::Op op = clip->fOp;
+ SkRegion::Op op = element->getOp();
if (first) {
first = false;
op = firstOp;
@@ -1499,20 +1494,20 @@ bool GrClipMaskManager::createSoftwareClipMask(const GrClipData& clipDataIn,
helper.draw(temp, SkRegion::kXOR_Op, false, 0xFF);
}
- if (NULL != clip->fRect) {
-
+ if (Element::kRect_Type == element->getType()) {
// convert the rect to a path so we can invert the fill
SkPath temp;
- temp.addRect(*clip->fRect);
+ temp.addRect(element->getRect());
helper.draw(temp, SkRegion::kReplace_Op,
- kInverseEvenOdd_GrPathFill, clip->fDoAA,
+ kInverseEvenOdd_GrPathFill, element->isAA(),
0x00);
- } else if (NULL != clip->fPath) {
- helper.draw(*clip->fPath,
+ } else {
+ GrAssert(Element::kPath_Type == element->getType());
+ helper.draw(element->getPath(),
SkRegion::kReplace_Op,
- invert_fill(get_path_fill(*clip->fPath)),
- clip->fDoAA,
+ invert_fill(get_path_fill(element->getPath())),
+ element->isAA(),
0x00);
}
@@ -1521,17 +1516,14 @@ bool GrClipMaskManager::createSoftwareClipMask(const GrClipData& clipDataIn,
// The other ops (union, xor, diff) only affect pixels inside
// the geometry so they can just be drawn normally
- if (NULL != clip->fRect) {
-
- helper.draw(*clip->fRect,
- op,
- clip->fDoAA, 0xFF);
-
- } else if (NULL != clip->fPath) {
- helper.draw(*clip->fPath,
+ if (Element::kRect_Type == element->getType()) {
+ helper.draw(element->getRect(), op, element->isAA(), 0xFF);
+ } else {
+ GrAssert(Element::kPath_Type == element->getType());
+ helper.draw(element->getPath(),
op,
- get_path_fill(*clip->fPath),
- clip->fDoAA, 0xFF);
+ get_path_fill(element->getPath()),
+ element->isAA(), 0xFF);
}
}
diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h
index 4894a3a70c..c3a1b5ee70 100644
--- a/src/gpu/GrClipMaskManager.h
+++ b/src/gpu/GrClipMaskManager.h
@@ -19,6 +19,7 @@
#include "SkDeque.h"
#include "SkPath.h"
#include "SkRefCnt.h"
+#include "SkTLList.h"
#include "GrClipMaskCache.h"
@@ -125,7 +126,7 @@ private:
bool useSWOnlyPath(const SkClipStack& clipIn);
bool drawClipShape(GrTexture* target,
- const SkClipStack::Iter::Clip* clip,
+ const SkClipStack::Element* element,
const GrIRect& resultBounds);
void mergeMask(GrTexture* dstMask,
@@ -157,9 +158,10 @@ private:
typedef GrNoncopyable INHERITED;
};
-
namespace GrReducedClip {
+typedef SkTLList<SkClipStack::Element> ElementList;
+
enum InitialState {
kAllIn_InitialState,
kAllOut_InitialState,
@@ -175,7 +177,7 @@ enum InitialState {
* may become a member function of SkClipStack when its interface is determined to be stable.
*/
void GrReduceClipStack(const SkClipStack& stack,
- SkTDArray<SkClipStack::Iter::Clip>* resultClips,
+ ElementList* result,
SkRect* resultBounds,
bool* resultsAreBounded,
InitialState* initialState);
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 929ca10508..0de011c63c 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -226,8 +226,8 @@ static void skip_clip_stack_prefix(const SkClipStack& prefix,
SkClipStack::B2TIter prefixIter(prefix);
iter->reset(stack, SkClipStack::Iter::kBottom_IterStart);
- const SkClipStack::B2TIter::Clip* prefixEntry;
- const SkClipStack::B2TIter::Clip* iterEntry;
+ const SkClipStack::Element* prefixEntry;
+ const SkClipStack::Element* iterEntry;
for (prefixEntry = prefixIter.next(); prefixEntry;
prefixEntry = prefixIter.next()) {
@@ -236,12 +236,9 @@ static void skip_clip_stack_prefix(const SkClipStack& prefix,
// Because of SkClipStack does internal intersection, the last clip
// entry may differ.
if (*prefixEntry != *iterEntry) {
- SkASSERT(prefixEntry->fOp == SkRegion::kIntersect_Op);
- SkASSERT(iterEntry->fOp == SkRegion::kIntersect_Op);
- SkASSERT((iterEntry->fRect == NULL) ==
- (prefixEntry->fRect == NULL));
- SkASSERT((iterEntry->fPath == NULL) ==
- (prefixEntry->fPath == NULL));
+ SkASSERT(prefixEntry->getOp() == SkRegion::kIntersect_Op);
+ SkASSERT(iterEntry->getOp() == SkRegion::kIntersect_Op);
+ SkASSERT(iterEntry->getType() == prefixEntry->getType());
// back up the iterator by one
iter->prev();
prefixEntry = prefixIter.next();
@@ -306,10 +303,9 @@ void GraphicStackState::updateClip(const SkClipStack& clipStack,
// If the clip stack does anything other than intersect or if it uses
// an inverse fill type, we have to fall back to the clip region.
bool needRegion = false;
- const SkClipStack::B2TIter::Clip* clipEntry;
+ const SkClipStack::Element* clipEntry;
for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
- if (clipEntry->fOp != SkRegion::kIntersect_Op ||
- (clipEntry->fPath && clipEntry->fPath->isInverseFillType())) {
+ if (clipEntry->getOp() != SkRegion::kIntersect_Op || clipEntry->isInverseFilled()) {
needRegion = true;
break;
}
@@ -323,19 +319,24 @@ void GraphicStackState::updateClip(const SkClipStack& clipStack,
skip_clip_stack_prefix(fEntries[0].fClipStack, clipStack, &iter);
SkMatrix transform;
transform.setTranslate(translation.fX, translation.fY);
- const SkClipStack::B2TIter::Clip* clipEntry;
+ const SkClipStack::Element* clipEntry;
for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
- SkASSERT(clipEntry->fOp == SkRegion::kIntersect_Op);
- if (clipEntry->fRect) {
- SkRect translatedClip;
- transform.mapRect(&translatedClip, *clipEntry->fRect);
- emit_clip(NULL, &translatedClip, fContentStream);
- } else if (clipEntry->fPath) {
- SkPath translatedPath;
- clipEntry->fPath->transform(transform, &translatedPath);
- emit_clip(&translatedPath, NULL, fContentStream);
- } else {
- SkASSERT(false);
+ SkASSERT(clipEntry->getOp() == SkRegion::kIntersect_Op);
+ switch (clipEntry->getType()) {
+ case SkClipStack::Element::kRect_Type: {
+ SkRect translatedClip;
+ transform.mapRect(&translatedClip, clipEntry->getRect());
+ emit_clip(NULL, &translatedClip, fContentStream);
+ break;
+ }
+ case SkClipStack::Element::kPath_Type: {
+ SkPath translatedPath;
+ clipEntry->getPath().transform(transform, &translatedPath);
+ emit_clip(&translatedPath, NULL, fContentStream);
+ break;
+ }
+ default:
+ SkASSERT(false);
}
}
}