aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/ClipStackTest.cpp
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-06-11 11:01:48 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-06-11 11:01:48 +0000
commit6fbe54c663bd0eed6f6519c31a4c8e291db2613b (patch)
treeaee7c8f354f86f9d0d64e25deaa20cbf2396b4ad /tests/ClipStackTest.cpp
parent7fb5373fb76951b7e8b534f04d508dd51e21be6e (diff)
Compact the clipstack for kReplace_Op'd geometry
When adding a clip rect or clip path to the stack with the kReplace_Op operation, remove all previous elements within the same save frame (elements with fSaveCount equal to the current fSaveCount of the stack). This prevents unbounded growth of the clipstack for long-lived instances that gets reused. Addresses https://code.google.com/p/skia/issues/detail?id=748 R=robertphillips@google.com Author: fs@opera.com Review URL: https://chromiumcodereview.appspot.com/16160020 git-svn-id: http://skia.googlecode.com/svn/trunk@9502 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'tests/ClipStackTest.cpp')
-rw-r--r--tests/ClipStackTest.cpp103
1 files changed, 103 insertions, 0 deletions
diff --git a/tests/ClipStackTest.cpp b/tests/ClipStackTest.cpp
index 4de667367e..cbed19364f 100644
--- a/tests/ClipStackTest.cpp
+++ b/tests/ClipStackTest.cpp
@@ -392,6 +392,107 @@ static void test_rect_inverse_fill(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, bounds == rect);
}
+static void test_rect_replace(skiatest::Reporter* reporter) {
+ SkRect rect = SkRect::MakeWH(100, 100);
+ SkRect rect2 = SkRect::MakeXYWH(50, 50, 100, 100);
+
+ SkRect bound;
+ SkClipStack::BoundsType type;
+ bool isIntersectionOfRects;
+
+ // Adding a new rect with the replace operator should not increase
+ // the stack depth. BW replacing BW.
+ {
+ SkClipStack stack;
+ REPORTER_ASSERT(reporter, 0 == count(stack));
+ stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
+ REPORTER_ASSERT(reporter, 1 == count(stack));
+ stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
+ REPORTER_ASSERT(reporter, 1 == count(stack));
+ }
+
+ // Adding a new rect with the replace operator should not increase
+ // the stack depth. AA replacing AA.
+ {
+ SkClipStack stack;
+ REPORTER_ASSERT(reporter, 0 == count(stack));
+ stack.clipDevRect(rect, SkRegion::kReplace_Op, true);
+ REPORTER_ASSERT(reporter, 1 == count(stack));
+ stack.clipDevRect(rect, SkRegion::kReplace_Op, true);
+ REPORTER_ASSERT(reporter, 1 == count(stack));
+ }
+
+ // Adding a new rect with the replace operator should not increase
+ // the stack depth. BW replacing AA replacing BW.
+ {
+ SkClipStack stack;
+ REPORTER_ASSERT(reporter, 0 == count(stack));
+ stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
+ REPORTER_ASSERT(reporter, 1 == count(stack));
+ stack.clipDevRect(rect, SkRegion::kReplace_Op, true);
+ REPORTER_ASSERT(reporter, 1 == count(stack));
+ stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
+ REPORTER_ASSERT(reporter, 1 == count(stack));
+ }
+
+ // Make sure replace clip rects don't collapse too much.
+ {
+ SkClipStack stack;
+ stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
+ stack.clipDevRect(rect2, SkRegion::kIntersect_Op, false);
+ REPORTER_ASSERT(reporter, 1 == count(stack));
+
+ stack.save();
+ stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
+ REPORTER_ASSERT(reporter, 2 == count(stack));
+ stack.getBounds(&bound, &type, &isIntersectionOfRects);
+ REPORTER_ASSERT(reporter, bound == rect);
+ stack.restore();
+ REPORTER_ASSERT(reporter, 1 == count(stack));
+
+ stack.save();
+ stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
+ stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
+ REPORTER_ASSERT(reporter, 2 == count(stack));
+ stack.restore();
+ REPORTER_ASSERT(reporter, 1 == count(stack));
+
+ stack.save();
+ stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
+ stack.clipDevRect(rect2, SkRegion::kIntersect_Op, false);
+ stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
+ REPORTER_ASSERT(reporter, 2 == count(stack));
+ stack.restore();
+ REPORTER_ASSERT(reporter, 1 == count(stack));
+ }
+}
+
+// Simplified path-based version of test_rect_replace.
+static void test_path_replace(skiatest::Reporter* reporter) {
+ SkRect rect = SkRect::MakeWH(100, 100);
+ SkPath path;
+ path.addCircle(50, 50, 50);
+
+ // Replace operation doesn't grow the stack.
+ {
+ SkClipStack stack;
+ REPORTER_ASSERT(reporter, 0 == count(stack));
+ stack.clipDevPath(path, SkRegion::kReplace_Op, false);
+ REPORTER_ASSERT(reporter, 1 == count(stack));
+ stack.clipDevPath(path, SkRegion::kReplace_Op, false);
+ REPORTER_ASSERT(reporter, 1 == count(stack));
+ }
+
+ // Replacing rect with path.
+ {
+ SkClipStack stack;
+ stack.clipDevRect(rect, SkRegion::kReplace_Op, true);
+ REPORTER_ASSERT(reporter, 1 == count(stack));
+ stack.clipDevPath(path, SkRegion::kReplace_Op, true);
+ REPORTER_ASSERT(reporter, 1 == count(stack));
+ }
+}
+
// Test out SkClipStack's merging of rect clips. In particular exercise
// merging of aa vs. bw rects.
static void test_rect_merging(skiatest::Reporter* reporter) {
@@ -950,7 +1051,9 @@ static void TestClipStack(skiatest::Reporter* reporter) {
test_bounds(reporter, false); // once with paths
test_isWideOpen(reporter);
test_rect_merging(reporter);
+ test_rect_replace(reporter);
test_rect_inverse_fill(reporter);
+ test_path_replace(reporter);
test_quickContains(reporter);
#if SK_SUPPORT_GPU
test_reduced_clip_stack(reporter);