diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-12-04 14:06:06 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-12-04 14:06:06 +0000 |
commit | 8182fa0cac76e7e6d583aebba060229230516887 (patch) | |
tree | 9857caea2550f6bf3645bd1297a8eeb91bed7843 /src | |
parent | e659c2e820de0b8d12d81247ed4430022ded0a90 (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.cpp | 50 | ||||
-rw-r--r-- | src/core/SkClipStack.cpp | 104 | ||||
-rw-r--r-- | src/core/SkTLList.h | 10 | ||||
-rw-r--r-- | src/gpu/GrClipMaskManager.cpp | 320 | ||||
-rw-r--r-- | src/gpu/GrClipMaskManager.h | 8 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 47 |
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); } } } |