diff options
-rw-r--r-- | include/core/SkClipStack.h | 27 | ||||
-rw-r--r-- | include/gpu/SkGr.h | 4 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 8 | ||||
-rw-r--r-- | src/core/SkClipStack.cpp | 2 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 14 | ||||
-rw-r--r-- | tests/ClipStackTest.cpp | 94 |
6 files changed, 118 insertions, 31 deletions
diff --git a/include/core/SkClipStack.h b/include/core/SkClipStack.h index 60c4421103..daeb82629a 100644 --- a/include/core/SkClipStack.h +++ b/include/core/SkClipStack.h @@ -45,8 +45,8 @@ public: class Iter { public: enum IterStart { - kFront_IterStart = SkDeque::Iter::kFront_IterStart, - kBack_IterStart = SkDeque::Iter::kBack_IterStart + kBottom_IterStart = SkDeque::Iter::kFront_IterStart, + kTop_IterStart = SkDeque::Iter::kBack_IterStart }; /** @@ -80,11 +80,11 @@ public: const Clip* prev(); /** - * Moves the iterator to the last clip with the specified RegionOp + * Moves the iterator to the topmost clip with the specified RegionOp * and returns that clip. If no clip with that op is found, * returns NULL. */ - const Clip* skipToLast(SkRegion::Op op); + const Clip* skipToTopmost(SkRegion::Op op); /** * Restarts the iterator on a clip stack. @@ -103,17 +103,20 @@ public: const Clip* updateClip(const SkClipStack::Rec* rec); }; - // Inherit privately from Iter to prevent access to reverse iteration - class B2FIter : private Iter { + /** + * The B2TIter iterates from the bottom of the stack to the top. + * It inherits privately from Iter to prevent access to reverse iteration. + */ + class B2TIter : private Iter { public: - B2FIter() {} + B2TIter() {} /** * Wrap Iter's 2 parameter ctor to force initialization to the - * beginning of the deque + * beginning of the deque/bottom of the stack */ - B2FIter(const SkClipStack& stack) - : INHERITED(stack, kFront_IterStart) { + B2TIter(const SkClipStack& stack) + : INHERITED(stack, kBottom_IterStart) { } using Iter::Clip; @@ -121,10 +124,10 @@ public: /** * Wrap Iter::reset to force initialization to the - * beginning of the deque + * beginning of the deque/bottom of the stack */ void reset(const SkClipStack& stack) { - this->INHERITED::reset(stack, kFront_IterStart); + this->INHERITED::reset(stack, kBottom_IterStart); } private: diff --git a/include/gpu/SkGr.h b/include/gpu/SkGr.h index 975a1bad44..ea79c63342 100644 --- a/include/gpu/SkGr.h +++ b/include/gpu/SkGr.h @@ -127,10 +127,10 @@ public: private: const SkClipStack* fClipStack; - SkClipStack::B2FIter fIter; + SkClipStack::B2TIter fIter; // SkClipStack's auto advances on each get // so we store the current pos here. - const SkClipStack::B2FIter::Clip* fCurr; + const SkClipStack::B2TIter::Clip* fCurr; }; class SkGlyphCache; diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 567e5f5c15..4b0c1d9a74 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -1212,8 +1212,8 @@ void SkCanvas::validateClip() const { ir.set(0, 0, device->width(), device->height()); SkRasterClip tmpClip(ir); - SkClipStack::B2FIter iter(fClipStack); - const SkClipStack::B2FIter::Clip* clip; + 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); @@ -1234,8 +1234,8 @@ void SkCanvas::validateClip() const { #endif void SkCanvas::replayClips(ClipVisitor* visitor) const { - SkClipStack::B2FIter iter(fClipStack); - const SkClipStack::B2FIter::Clip* clip; + SkClipStack::B2TIter iter(fClipStack); + const SkClipStack::B2TIter::Clip* clip; SkRect empty = { 0, 0, 0, 0 }; while ((clip = iter.next()) != NULL) { diff --git a/src/core/SkClipStack.cpp b/src/core/SkClipStack.cpp index f7ddc97891..429d4c0e17 100644 --- a/src/core/SkClipStack.cpp +++ b/src/core/SkClipStack.cpp @@ -263,7 +263,7 @@ const SkClipStack::Iter::Clip* SkClipStack::Iter::prev() { return this->updateClip(rec); } -const SkClipStack::Iter::Clip* SkClipStack::Iter::skipToLast(SkRegion::Op op) { +const SkClipStack::Iter::Clip* SkClipStack::Iter::skipToTopmost(SkRegion::Op op) { if (NULL == fStack) { return NULL; diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index 691ee26f24..7b774b77a2 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -217,17 +217,17 @@ void GraphicStackState::pop() { fStackDepth--; } -// This function initializes iter to be an interator on the "stack" argument +// This function initializes iter to be an iterator on the "stack" argument // and then skips over the leading entries as specified in prefix. It requires // and asserts that "prefix" will be a prefix to "stack." static void skip_clip_stack_prefix(const SkClipStack& prefix, const SkClipStack& stack, SkClipStack::Iter* iter) { - SkClipStack::B2FIter prefixIter(prefix); - iter->reset(stack, SkClipStack::Iter::kFront_IterStart); + SkClipStack::B2TIter prefixIter(prefix); + iter->reset(stack, SkClipStack::Iter::kBottom_IterStart); - const SkClipStack::B2FIter::Clip* prefixEntry; - const SkClipStack::B2FIter::Clip* iterEntry; + const SkClipStack::B2TIter::Clip* prefixEntry; + const SkClipStack::B2TIter::Clip* iterEntry; for (prefixEntry = prefixIter.next(); prefixEntry; prefixEntry = prefixIter.next()) { @@ -306,7 +306,7 @@ 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::B2FIter::Clip* clipEntry; + const SkClipStack::B2TIter::Clip* clipEntry; for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) { if (clipEntry->fOp != SkRegion::kIntersect_Op || (clipEntry->fPath && clipEntry->fPath->isInverseFillType())) { @@ -323,7 +323,7 @@ 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::B2FIter::Clip* clipEntry; + const SkClipStack::B2TIter::Clip* clipEntry; for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) { SkASSERT(clipEntry->fOp == SkRegion::kIntersect_Op); if (clipEntry->fRect) { diff --git a/tests/ClipStackTest.cpp b/tests/ClipStackTest.cpp index a1e8323116..85a999797a 100644 --- a/tests/ClipStackTest.cpp +++ b/tests/ClipStackTest.cpp @@ -10,12 +10,18 @@ #include "SkPath.h" #include "SkRect.h" + + static void test_assign_and_comparison(skiatest::Reporter* reporter) { SkClipStack s; bool doAA = false; + REPORTER_ASSERT(reporter, 0 == s.getSaveCount()); + // Build up a clip stack with a path, an empty clip, and a rect. s.save(); + REPORTER_ASSERT(reporter, 1 == s.getSaveCount()); + SkPath p; p.moveTo(5, 6); p.lineTo(7, 8); @@ -24,12 +30,16 @@ static void test_assign_and_comparison(skiatest::Reporter* reporter) { s.clipDevPath(p, SkRegion::kIntersect_Op, doAA); s.save(); + REPORTER_ASSERT(reporter, 2 == s.getSaveCount()); + SkRect r = SkRect::MakeLTRB(1, 2, 3, 4); s.clipDevRect(r, SkRegion::kIntersect_Op, doAA); r = SkRect::MakeLTRB(10, 11, 12, 13); s.clipDevRect(r, SkRegion::kIntersect_Op, doAA); s.save(); + REPORTER_ASSERT(reporter, 3 == s.getSaveCount()); + r = SkRect::MakeLTRB(14, 15, 16, 17); s.clipDevRect(r, SkRegion::kUnion_Op, doAA); @@ -39,17 +49,23 @@ static void test_assign_and_comparison(skiatest::Reporter* reporter) { // Test that different save levels triggers not equal. s.restore(); + REPORTER_ASSERT(reporter, 2 == s.getSaveCount()); REPORTER_ASSERT(reporter, s != copy); // Test that an equal, but not copied version is equal. s.save(); + REPORTER_ASSERT(reporter, 3 == s.getSaveCount()); + r = SkRect::MakeLTRB(14, 15, 16, 17); s.clipDevRect(r, SkRegion::kUnion_Op, doAA); REPORTER_ASSERT(reporter, s == copy); // Test that a different op on one level triggers not equal. s.restore(); + REPORTER_ASSERT(reporter, 2 == s.getSaveCount()); s.save(); + REPORTER_ASSERT(reporter, 3 == s.getSaveCount()); + r = SkRect::MakeLTRB(14, 15, 16, 17); s.clipDevRect(r, SkRegion::kIntersect_Op, doAA); REPORTER_ASSERT(reporter, s != copy); @@ -69,22 +85,33 @@ static void test_assign_and_comparison(skiatest::Reporter* reporter) { // Test that different rects triggers not equal. s.restore(); + REPORTER_ASSERT(reporter, 2 == s.getSaveCount()); s.save(); + REPORTER_ASSERT(reporter, 3 == s.getSaveCount()); + r = SkRect::MakeLTRB(24, 25, 26, 27); s.clipDevRect(r, SkRegion::kUnion_Op, doAA); REPORTER_ASSERT(reporter, s != copy); // Sanity check s.restore(); + REPORTER_ASSERT(reporter, 2 == s.getSaveCount()); + copy.restore(); + REPORTER_ASSERT(reporter, 2 == copy.getSaveCount()); REPORTER_ASSERT(reporter, s == copy); s.restore(); + REPORTER_ASSERT(reporter, 1 == s.getSaveCount()); copy.restore(); + REPORTER_ASSERT(reporter, 1 == copy.getSaveCount()); REPORTER_ASSERT(reporter, s == copy); // Test that different paths triggers not equal. s.restore(); + REPORTER_ASSERT(reporter, 0 == s.getSaveCount()); s.save(); + REPORTER_ASSERT(reporter, 1 == s.getSaveCount()); + p.addRect(r); s.clipDevPath(p, SkRegion::kIntersect_Op, doAA); REPORTER_ASSERT(reporter, s != copy); @@ -92,9 +119,7 @@ static void test_assign_and_comparison(skiatest::Reporter* reporter) { static void assert_count(skiatest::Reporter* reporter, const SkClipStack& stack, int count) { - REPORTER_ASSERT(reporter, count == stack.getSaveCount()); - - SkClipStack::B2FIter iter(stack); + SkClipStack::B2TIter iter(stack); int counter = 0; while (iter.next()) { counter += 1; @@ -102,9 +127,66 @@ static void assert_count(skiatest::Reporter* reporter, const SkClipStack& stack, REPORTER_ASSERT(reporter, count == counter); } +static void test_iterators(skiatest::Reporter* reporter) { + SkClipStack stack; + + static const SkRect gRects[] = { + { 0, 0, 40, 40 }, + { 60, 0, 100, 40 }, + { 0, 60, 40, 100 }, + { 60, 60, 100, 100 } + }; + + for (size_t i = 0; i < SK_ARRAY_COUNT(gRects); i++) { + // the union op will prevent these from being fused together + stack.clipDevRect(gRects[i], SkRegion::kUnion_Op, false); + } + + assert_count(reporter, stack, 4); + + // bottom to top iteration + { + const SkClipStack::B2TIter::Clip* clip = NULL; + + SkClipStack::B2TIter iter(stack); + int i; + + for (i = 0, clip = iter.next(); clip; ++i, clip = iter.next()) { + REPORTER_ASSERT(reporter, *clip->fRect == gRects[i]); + } + + SkASSERT(i == 4); + } + + // top to bottom iteration + { + const SkClipStack::Iter::Clip* clip = NULL; + + SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart); + int i; + + for (i = 3, clip = iter.prev(); clip; --i, clip = iter.prev()) { + REPORTER_ASSERT(reporter, *clip->fRect == gRects[i]); + } + + SkASSERT(i == -1); + } + + // skipToTopmost + { + const SkClipStack::Iter::Clip*clip = NULL; + + SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart); + + clip = iter.skipToTopmost(SkRegion::kUnion_Op); + REPORTER_ASSERT(reporter, *clip->fRect == gRects[3]); + } +} + static void TestClipStack(skiatest::Reporter* reporter) { SkClipStack stack; + REPORTER_ASSERT(reporter, 0 == stack.getSaveCount()); assert_count(reporter, stack, 0); static const SkIRect gRects[] = { @@ -118,8 +200,8 @@ static void TestClipStack(skiatest::Reporter* reporter) { } // all of the above rects should have been intersected, leaving only 1 rect - SkClipStack::B2FIter iter(stack); - const SkClipStack::B2FIter::Clip* clip = iter.next(); + SkClipStack::B2TIter iter(stack); + const SkClipStack::B2TIter::Clip* clip = iter.next(); SkRect answer; answer.iset(25, 25, 75, 75); @@ -132,9 +214,11 @@ static void TestClipStack(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, !iter.next()); stack.reset(); + REPORTER_ASSERT(reporter, 0 == stack.getSaveCount()); assert_count(reporter, stack, 0); test_assign_and_comparison(reporter); + test_iterators(reporter); } #include "TestClassDef.h" |