ClipStackTest.cpp revision 8cdf0f52ff395d4053f7ed5c20861c42eba25d31
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com#include "Test.h"
9a4e13c85b23fe7530ae89a84ef671ebd5e451e80bsalomon@google.com#if SK_SUPPORT_GPU
10170bd792e17469769d145b7dc15dea6cd01b7966bsalomon@google.com    #include "GrReducedClip.h"
11a4e13c85b23fe7530ae89a84ef671ebd5e451e80bsalomon@google.com#endif
12bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com#include "SkClipStack.h"
131e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org#include "SkPath.h"
1451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com#include "SkRandom.h"
151e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org#include "SkRect.h"
1651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com#include "SkRegion.h"
1780214e26c57c5fea954006400852e8999e201923robertphillips@google.com
1880214e26c57c5fea954006400852e8999e201923robertphillips@google.com
191e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.orgstatic void test_assign_and_comparison(skiatest::Reporter* reporter) {
201e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkClipStack s;
21d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    bool doAA = false;
221e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
2380214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 0 == s.getSaveCount());
2480214e26c57c5fea954006400852e8999e201923robertphillips@google.com
251e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Build up a clip stack with a path, an empty clip, and a rect.
261e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
2780214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 1 == s.getSaveCount());
2880214e26c57c5fea954006400852e8999e201923robertphillips@google.com
291e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkPath p;
301e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    p.moveTo(5, 6);
311e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    p.lineTo(7, 8);
321e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    p.lineTo(5, 9);
331e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    p.close();
34d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevPath(p, SkRegion::kIntersect_Op, doAA);
351e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
361e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
3780214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == s.getSaveCount());
3880214e26c57c5fea954006400852e8999e201923robertphillips@google.com
391e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkRect r = SkRect::MakeLTRB(1, 2, 3, 4);
40d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kIntersect_Op, doAA);
411e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    r = SkRect::MakeLTRB(10, 11, 12, 13);
42d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kIntersect_Op, doAA);
431e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
441e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
4580214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 3 == s.getSaveCount());
4680214e26c57c5fea954006400852e8999e201923robertphillips@google.com
471e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    r = SkRect::MakeLTRB(14, 15, 16, 17);
48d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kUnion_Op, doAA);
491e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
501e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that assignment works.
511e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkClipStack copy = s;
521e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s == copy);
531e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
541e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that different save levels triggers not equal.
551e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
5680214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == s.getSaveCount());
571e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s != copy);
581e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
591e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that an equal, but not copied version is equal.
601e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
6180214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 3 == s.getSaveCount());
6280214e26c57c5fea954006400852e8999e201923robertphillips@google.com
631e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    r = SkRect::MakeLTRB(14, 15, 16, 17);
64d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kUnion_Op, doAA);
651e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s == copy);
661e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
671e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that a different op on one level triggers not equal.
681e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
6980214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == s.getSaveCount());
701e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
7180214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 3 == s.getSaveCount());
7280214e26c57c5fea954006400852e8999e201923robertphillips@google.com
731e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    r = SkRect::MakeLTRB(14, 15, 16, 17);
74d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kIntersect_Op, doAA);
751e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s != copy);
761e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
771e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that different state (clip type) triggers not equal.
784c4337291d873c4f27cb7903645863dc65b98a7btomhudson@google.com    // NO LONGER VALID: if a path contains only a rect, we turn
794c4337291d873c4f27cb7903645863dc65b98a7btomhudson@google.com    // it into a bare rect for performance reasons (working
804c4337291d873c4f27cb7903645863dc65b98a7btomhudson@google.com    // around Chromium/JavaScript bad pattern).
814c4337291d873c4f27cb7903645863dc65b98a7btomhudson@google.com/*
821e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
831e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
841e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkPath rp;
851e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    rp.addRect(r);
86d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevPath(rp, SkRegion::kUnion_Op, doAA);
871e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s != copy);
884c4337291d873c4f27cb7903645863dc65b98a7btomhudson@google.com*/
891e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
901e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that different rects triggers not equal.
911e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
9280214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == s.getSaveCount());
931e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
9480214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 3 == s.getSaveCount());
9580214e26c57c5fea954006400852e8999e201923robertphillips@google.com
961e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    r = SkRect::MakeLTRB(24, 25, 26, 27);
97d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kUnion_Op, doAA);
981e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s != copy);
991e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
1001e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Sanity check
1011e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
10280214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == s.getSaveCount());
10380214e26c57c5fea954006400852e8999e201923robertphillips@google.com
1041e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    copy.restore();
10580214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == copy.getSaveCount());
1061e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s == copy);
1071e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
10880214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 1 == s.getSaveCount());
1091e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    copy.restore();
11080214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 1 == copy.getSaveCount());
1111e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s == copy);
1121e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
1131e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that different paths triggers not equal.
1141e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
11580214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 0 == s.getSaveCount());
1161e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
11780214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 1 == s.getSaveCount());
11880214e26c57c5fea954006400852e8999e201923robertphillips@google.com
1191e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    p.addRect(r);
120d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevPath(p, SkRegion::kIntersect_Op, doAA);
1211e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s != copy);
1221e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org}
123bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
124bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.comstatic void assert_count(skiatest::Reporter* reporter, const SkClipStack& stack,
125bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com                         int count) {
12680214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter iter(stack);
127bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    int counter = 0;
128bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    while (iter.next()) {
129bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        counter += 1;
130bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    }
131bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    REPORTER_ASSERT(reporter, count == counter);
132bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com}
133bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
13408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com// Exercise the SkClipStack's bottom to top and bidirectional iterators
13508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com// (including the skipToTopmost functionality)
13680214e26c57c5fea954006400852e8999e201923robertphillips@google.comstatic void test_iterators(skiatest::Reporter* reporter) {
13780214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack stack;
13880214e26c57c5fea954006400852e8999e201923robertphillips@google.com
13980214e26c57c5fea954006400852e8999e201923robertphillips@google.com    static const SkRect gRects[] = {
14080214e26c57c5fea954006400852e8999e201923robertphillips@google.com        { 0,   0,  40,  40 },
14180214e26c57c5fea954006400852e8999e201923robertphillips@google.com        { 60,  0, 100,  40 },
14280214e26c57c5fea954006400852e8999e201923robertphillips@google.com        { 0,  60,  40, 100 },
14380214e26c57c5fea954006400852e8999e201923robertphillips@google.com        { 60, 60, 100, 100 }
14480214e26c57c5fea954006400852e8999e201923robertphillips@google.com    };
14580214e26c57c5fea954006400852e8999e201923robertphillips@google.com
14680214e26c57c5fea954006400852e8999e201923robertphillips@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gRects); i++) {
14780214e26c57c5fea954006400852e8999e201923robertphillips@google.com        // the union op will prevent these from being fused together
14880214e26c57c5fea954006400852e8999e201923robertphillips@google.com        stack.clipDevRect(gRects[i], SkRegion::kUnion_Op, false);
14980214e26c57c5fea954006400852e8999e201923robertphillips@google.com    }
15080214e26c57c5fea954006400852e8999e201923robertphillips@google.com
15180214e26c57c5fea954006400852e8999e201923robertphillips@google.com    assert_count(reporter, stack, 4);
15280214e26c57c5fea954006400852e8999e201923robertphillips@google.com
15380214e26c57c5fea954006400852e8999e201923robertphillips@google.com    // bottom to top iteration
15480214e26c57c5fea954006400852e8999e201923robertphillips@google.com    {
1558182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        const SkClipStack::Element* element = NULL;
15680214e26c57c5fea954006400852e8999e201923robertphillips@google.com
15780214e26c57c5fea954006400852e8999e201923robertphillips@google.com        SkClipStack::B2TIter iter(stack);
15880214e26c57c5fea954006400852e8999e201923robertphillips@google.com        int i;
15980214e26c57c5fea954006400852e8999e201923robertphillips@google.com
1608182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        for (i = 0, element = iter.next(); element; ++i, element = iter.next()) {
1618182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            REPORTER_ASSERT(reporter, SkClipStack::Element::kRect_Type == element->getType());
1628182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            REPORTER_ASSERT(reporter, element->getRect() == gRects[i]);
16380214e26c57c5fea954006400852e8999e201923robertphillips@google.com        }
16480214e26c57c5fea954006400852e8999e201923robertphillips@google.com
16580214e26c57c5fea954006400852e8999e201923robertphillips@google.com        SkASSERT(i == 4);
16680214e26c57c5fea954006400852e8999e201923robertphillips@google.com    }
16780214e26c57c5fea954006400852e8999e201923robertphillips@google.com
16880214e26c57c5fea954006400852e8999e201923robertphillips@google.com    // top to bottom iteration
16980214e26c57c5fea954006400852e8999e201923robertphillips@google.com    {
1708182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        const SkClipStack::Element* element = NULL;
17180214e26c57c5fea954006400852e8999e201923robertphillips@google.com
17280214e26c57c5fea954006400852e8999e201923robertphillips@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
17380214e26c57c5fea954006400852e8999e201923robertphillips@google.com        int i;
17480214e26c57c5fea954006400852e8999e201923robertphillips@google.com
1758182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        for (i = 3, element = iter.prev(); element; --i, element = iter.prev()) {
1768182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            REPORTER_ASSERT(reporter, SkClipStack::Element::kRect_Type == element->getType());
1778182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            REPORTER_ASSERT(reporter, element->getRect() == gRects[i]);
17880214e26c57c5fea954006400852e8999e201923robertphillips@google.com        }
17980214e26c57c5fea954006400852e8999e201923robertphillips@google.com
18080214e26c57c5fea954006400852e8999e201923robertphillips@google.com        SkASSERT(i == -1);
18180214e26c57c5fea954006400852e8999e201923robertphillips@google.com    }
18280214e26c57c5fea954006400852e8999e201923robertphillips@google.com
18380214e26c57c5fea954006400852e8999e201923robertphillips@google.com    // skipToTopmost
18480214e26c57c5fea954006400852e8999e201923robertphillips@google.com    {
1858182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        const SkClipStack::Element* element = NULL;
18680214e26c57c5fea954006400852e8999e201923robertphillips@google.com
18780214e26c57c5fea954006400852e8999e201923robertphillips@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
18880214e26c57c5fea954006400852e8999e201923robertphillips@google.com
1898182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        element = iter.skipToTopmost(SkRegion::kUnion_Op);
1908182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        REPORTER_ASSERT(reporter, SkClipStack::Element::kRect_Type == element->getType());
1918182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        REPORTER_ASSERT(reporter, element->getRect() == gRects[3]);
19280214e26c57c5fea954006400852e8999e201923robertphillips@google.com    }
19380214e26c57c5fea954006400852e8999e201923robertphillips@google.com}
19480214e26c57c5fea954006400852e8999e201923robertphillips@google.com
19508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com// Exercise the SkClipStack's getConservativeBounds computation
1964c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.comstatic void test_bounds(skiatest::Reporter* reporter, bool useRects) {
197607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
198607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    static const int gNumCases = 20;
199607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    static const SkRect gAnswerRectsBW[gNumCases] = {
200607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        // A op B
201607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 50, 50 },
202607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 50, 50 },
203607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 80, 80 },
204607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 80, 80 },
205607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 80, 80 },
206607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
207607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        // invA op B
208607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 80, 80 },
209607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
210607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
211607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
212607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 50, 50 },
213607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
214607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        // A op invB
215607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 50, 50 },
216607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 50, 50 },
217607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
218607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
219607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
220607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
221607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        // invA op invB
222607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
223607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 80, 80 },
224607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
225607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 80, 80 },
226607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 50, 50 },
227607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    };
228607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
229607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    static const SkRegion::Op gOps[] = {
230607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        SkRegion::kIntersect_Op,
231607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        SkRegion::kDifference_Op,
232607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        SkRegion::kUnion_Op,
233607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        SkRegion::kXOR_Op,
234607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        SkRegion::kReverseDifference_Op
235607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    };
236607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
237607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    SkRect rectA, rectB;
238607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
239607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    rectA.iset(10, 10, 50, 50);
240607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    rectB.iset(40, 40, 80, 80);
241607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
242607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    SkPath clipA, clipB;
243607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
244607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    clipA.addRoundRect(rectA, SkIntToScalar(5), SkIntToScalar(5));
245607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    clipB.addRoundRect(rectB, SkIntToScalar(5), SkIntToScalar(5));
246607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
247607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    SkClipStack stack;
2487b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    SkRect devClipBound;
2494c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com    bool isIntersectionOfRects = false;
250607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
251607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    int testCase = 0;
2524c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com    int numBitTests = useRects ? 1 : 4;
2534c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com    for (int invBits = 0; invBits < numBitTests; ++invBits) {
254607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
255607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
256607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            stack.save();
257607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            bool doInvA = SkToBool(invBits & 1);
258607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            bool doInvB = SkToBool(invBits & 2);
259607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
260607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            clipA.setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType :
261607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com                                       SkPath::kEvenOdd_FillType);
262607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            clipB.setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType :
263607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com                                       SkPath::kEvenOdd_FillType);
264607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
2654c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com            if (useRects) {
2664c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                stack.clipDevRect(rectA, SkRegion::kIntersect_Op, false);
2674c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                stack.clipDevRect(rectB, gOps[op], false);
2684c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com            } else {
2694c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                stack.clipDevPath(clipA, SkRegion::kIntersect_Op, false);
2704c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                stack.clipDevPath(clipB, gOps[op], false);
2714c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com            }
272607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
273cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com            REPORTER_ASSERT(reporter, !stack.isWideOpen());
274cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
2757b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com            stack.getConservativeBounds(0, 0, 100, 100, &devClipBound,
2764c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                                        &isIntersectionOfRects);
2774c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com
2784c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com            if (useRects) {
279d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com                REPORTER_ASSERT(reporter, isIntersectionOfRects ==
2804c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                        (gOps[op] == SkRegion::kIntersect_Op));
2814c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com            } else {
2824c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                REPORTER_ASSERT(reporter, !isIntersectionOfRects);
2834c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com            }
284607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
285607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            SkASSERT(testCase < gNumCases);
2867b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com            REPORTER_ASSERT(reporter, devClipBound == gAnswerRectsBW[testCase]);
287607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            ++testCase;
288607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
289607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            stack.restore();
290607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        }
291607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    }
292607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com}
293607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
294cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com// Test out 'isWideOpen' entry point
295cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.comstatic void test_isWideOpen(skiatest::Reporter* reporter) {
296cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
297cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    SkRect rectA, rectB;
298cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
299cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    rectA.iset(10, 10, 40, 40);
300cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    rectB.iset(50, 50, 80, 80);
301cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
302cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    // Stack should initially be wide open
303cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    {
304cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkClipStack stack;
305cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
306cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, stack.isWideOpen());
307cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    }
308cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
309cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    // Test out case where the user specifies a union that includes everything
310cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    {
311cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkClipStack stack;
312cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
313cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkPath clipA, clipB;
314cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
315cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        clipA.addRoundRect(rectA, SkIntToScalar(5), SkIntToScalar(5));
316cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        clipA.setFillType(SkPath::kInverseEvenOdd_FillType);
317cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
318cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        clipB.addRoundRect(rectB, SkIntToScalar(5), SkIntToScalar(5));
319cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        clipB.setFillType(SkPath::kInverseEvenOdd_FillType);
320cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
321cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.clipDevPath(clipA, SkRegion::kReplace_Op, false);
322cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.clipDevPath(clipB, SkRegion::kUnion_Op, false);
323cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
324cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, stack.isWideOpen());
325cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    }
326cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
327cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    // Test out union w/ a wide open clip
328cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    {
329cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkClipStack stack;
330cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
331cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.clipDevRect(rectA, SkRegion::kUnion_Op, false);
332cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
333cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, stack.isWideOpen());
334cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    }
335cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
336cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    // Test out empty difference from a wide open clip
337cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    {
338cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkClipStack stack;
339cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
340cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkRect emptyRect;
341cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        emptyRect.setEmpty();
342cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
343cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.clipDevRect(emptyRect, SkRegion::kDifference_Op, false);
344cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
345cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, stack.isWideOpen());
346cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    }
347cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
348cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    // Test out return to wide open
349cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    {
350cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkClipStack stack;
351cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
352cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.save();
353cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
354cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.clipDevRect(rectA, SkRegion::kReplace_Op, false);
355cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
356cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, !stack.isWideOpen());
357cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
358cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.restore();
359cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
360cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, stack.isWideOpen());
361cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    }
362cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com}
363cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
364100abf49e10544bc4f436bf1f38e6929779621f4bsalomon@google.comstatic int count(const SkClipStack& stack) {
36508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
36608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
36708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
3688182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* element = NULL;
36908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    int count = 0;
37008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
3718182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    for (element = iter.prev(); element; element = iter.prev(), ++count) {
37208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        ;
37308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
37408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
37508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    return count;
37608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com}
37708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
378edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.orgstatic void test_rect_inverse_fill(skiatest::Reporter* reporter) {
379edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    // non-intersecting rectangles
380edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    SkRect rect  = SkRect::MakeLTRB(0, 0, 10, 10);
381edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org
382edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    SkPath path;
383edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    path.addRect(rect);
384edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    path.toggleInverseFillType();
385edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    SkClipStack stack;
386edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
387edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org
388edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    SkRect bounds;
389edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    SkClipStack::BoundsType boundsType;
390edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    stack.getBounds(&bounds, &boundsType);
391edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    REPORTER_ASSERT(reporter, SkClipStack::kInsideOut_BoundsType == boundsType);
392edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    REPORTER_ASSERT(reporter, bounds == rect);
393edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org}
394edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org
39508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com// Test out SkClipStack's merging of rect clips. In particular exercise
39608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com// merging of aa vs. bw rects.
39708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.comstatic void test_rect_merging(skiatest::Reporter* reporter) {
39808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
39908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect overlapLeft  = SkRect::MakeLTRB(10, 10, 50, 50);
40008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect overlapRight = SkRect::MakeLTRB(40, 40, 80, 80);
40108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
40208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect nestedParent = SkRect::MakeLTRB(10, 10, 90, 90);
40308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect nestedChild  = SkRect::MakeLTRB(40, 40, 60, 60);
40408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
40508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect bound;
40608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkClipStack::BoundsType type;
40708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    bool isIntersectionOfRects;
40808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
40908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // all bw overlapping - should merge
41008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
41108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
41208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
41308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapLeft, SkRegion::kReplace_Op, false);
41408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
41508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, false);
41608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
41708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 1 == count(stack));
41808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
41908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
42008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
42108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, isIntersectionOfRects);
42208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
42308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
42408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // all aa overlapping - should merge
42508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
42608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
42708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
42808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapLeft, SkRegion::kReplace_Op, true);
42908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
43008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, true);
43108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
43208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 1 == count(stack));
43308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
43408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
43508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
43608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, isIntersectionOfRects);
43708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
43808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
43908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // mixed overlapping - should _not_ merge
44008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
44108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
44208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
44308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapLeft, SkRegion::kReplace_Op, true);
44408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
44508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, false);
44608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
44708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 2 == count(stack));
44808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
44908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
45008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
45108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, !isIntersectionOfRects);
45208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
45308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
45408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // mixed nested (bw inside aa) - should merge
45508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
45608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
45708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
45808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedParent, SkRegion::kReplace_Op, true);
45908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
46008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedChild, SkRegion::kIntersect_Op, false);
46108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
46208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 1 == count(stack));
46308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
46408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
46508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
46608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, isIntersectionOfRects);
46708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
46808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
46908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // mixed nested (aa inside bw) - should merge
47008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
47108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
47208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
47308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedParent, SkRegion::kReplace_Op, false);
47408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
47508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedChild, SkRegion::kIntersect_Op, true);
47608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
47708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 1 == count(stack));
47808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
47908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
48008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
48108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, isIntersectionOfRects);
48208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
48308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
48408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // reverse nested (aa inside bw) - should _not_ merge
48508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
48608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
48708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
48808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedChild, SkRegion::kReplace_Op, false);
48908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
49008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedParent, SkRegion::kIntersect_Op, true);
49108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
49208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 2 == count(stack));
49308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
49408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
49508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
49608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, !isIntersectionOfRects);
49708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
49808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com}
499cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
5008cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.orgstatic void test_quickContains(skiatest::Reporter* reporter) {
5018cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkRect testRect = SkRect::MakeLTRB(10, 10, 40, 40);
5028cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkRect insideRect = SkRect::MakeLTRB(20, 20, 30, 30);
5038cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkRect intersectingRect = SkRect::MakeLTRB(25, 25, 50, 50);
5048cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkRect outsideRect = SkRect::MakeLTRB(0, 0, 50, 50);
5058cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkRect nonIntersectingRect = SkRect::MakeLTRB(100, 100, 110, 110);
5068cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
5078cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkPath insideCircle;
5088cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    insideCircle.addCircle(25, 25, 5);
5098cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkPath intersectingCircle;
5108cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    intersectingCircle.addCircle(25, 40, 10);
5118cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkPath outsideCircle;
5128cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    outsideCircle.addCircle(25, 25, 50);
5138cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkPath nonIntersectingCircle;
5148cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    nonIntersectingCircle.addCircle(100, 100, 5);
5158cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
5168cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
5178cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
5188cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(outsideRect, SkRegion::kDifference_Op, false);
5198cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        // return false because quickContains currently does not care for kDifference_Op
5208cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
5218cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
5228cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
5238cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Replace Op tests
5248cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
5258cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
5268cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(outsideRect, SkRegion::kReplace_Op, false);
5278cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
5288cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
5298cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
5308cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
5318cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
5328cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(insideRect, SkRegion::kIntersect_Op, false);
5338cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.save(); // To prevent in-place substitution by replace OP
5348cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(outsideRect, SkRegion::kReplace_Op, false);
5358cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
5368cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.restore();
5378cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
5388cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
5398cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
5408cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
5418cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(outsideRect, SkRegion::kIntersect_Op, false);
5428cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.save(); // To prevent in-place substitution by replace OP
5438cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(insideRect, SkRegion::kReplace_Op, false);
5448cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
5458cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.restore();
5468cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
5478cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
5488cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Verify proper traversal of multi-element clip
5498cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
5508cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
5518cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(insideRect, SkRegion::kIntersect_Op, false);
5528cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        // Use a path for second clip to prevent in-place intersection
5538cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(outsideCircle, SkRegion::kIntersect_Op, false);
5548cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
5558cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
5568cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
5578cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Intersect Op tests with rectangles
5588cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
5598cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
5608cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(outsideRect, SkRegion::kIntersect_Op, false);
5618cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
5628cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
5638cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
5648cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
5658cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
5668cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(insideRect, SkRegion::kIntersect_Op, false);
5678cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
5688cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
5698cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
5708cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
5718cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
5728cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(intersectingRect, SkRegion::kIntersect_Op, false);
5738cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
5748cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
5758cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
5768cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
5778cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
5788cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(nonIntersectingRect, SkRegion::kIntersect_Op, false);
5798cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
5808cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
5818cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
5828cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Intersect Op tests with circle paths
5838cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
5848cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
5858cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(outsideCircle, SkRegion::kIntersect_Op, false);
5868cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
5878cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
5888cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
5898cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
5908cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
5918cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(insideCircle, SkRegion::kIntersect_Op, false);
5928cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
5938cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
5948cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
5958cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
5968cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
5978cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(intersectingCircle, SkRegion::kIntersect_Op, false);
5988cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
5998cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6008cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6018cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6028cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6038cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(nonIntersectingCircle, SkRegion::kIntersect_Op, false);
6048cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6058cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6068cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6078cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Intersect Op tests with inverse filled rectangles
6088cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6098cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6108cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path;
6118cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.addRect(outsideRect);
6128cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
6138cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
6148cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6158cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6168cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6178cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6188cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6198cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path;
6208cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.addRect(insideRect);
6218cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
6228cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
6238cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6248cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6258cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6268cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6278cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6288cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path;
6298cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.addRect(intersectingRect);
6308cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
6318cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
6328cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6338cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6348cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6358cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6368cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6378cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path;
6388cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.addRect(nonIntersectingRect);
6398cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
6408cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
6418cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
6428cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6438cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6448cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Intersect Op tests with inverse filled circles
6458cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6468cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6478cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path = outsideCircle;
6488cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
6498cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
6508cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6518cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6528cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6538cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6548cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6558cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path = insideCircle;
6568cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
6578cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
6588cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6598cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6608cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6618cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6628cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6638cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path = intersectingCircle;
6648cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
6658cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
6668cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6678cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6688cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6698cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6708cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6718cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path = nonIntersectingCircle;
6728cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
6738cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
6748cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
6758cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6768cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org}
6778cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
67851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com///////////////////////////////////////////////////////////////////////////////////////////////////
67951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
680a4e13c85b23fe7530ae89a84ef671ebd5e451e80bsalomon@google.com#if SK_SUPPORT_GPU
681705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com// Functions that add a shape to the clip stack. The shape is computed from a rectangle.
682705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com// AA is always disabled since the clip stack reducer can cause changes in aa rasterization of the
683705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com// stack. A fractional edge repeated in different elements may be rasterized fewer times using the
684705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com// reduced stack.
685705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.comtypedef void (*AddElementFunc) (const SkRect& rect,
686705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com                                bool invert,
687705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com                                SkRegion::Op op,
688705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com                                SkClipStack* stack);
689705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com
690705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.comstatic void add_round_rect(const SkRect& rect, bool invert, SkRegion::Op op, SkClipStack* stack) {
69151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkPath path;
69251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkScalar rx = rect.width() / 10;
693705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    SkScalar ry = rect.height() / 20;
69451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    path.addRoundRect(rect, rx, ry);
695705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    if (invert) {
696705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        path.setFillType(SkPath::kInverseWinding_FillType);
697705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    }
698705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    stack->clipDevPath(path, op, false);
69951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com};
70051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
701705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.comstatic void add_rect(const SkRect& rect, bool invert, SkRegion::Op op, SkClipStack* stack) {
702705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    if (invert) {
703705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        SkPath path;
704705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        path.addRect(rect);
705705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        path.setFillType(SkPath::kInverseWinding_FillType);
706705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        stack->clipDevPath(path, op, false);
707705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    } else {
708705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        stack->clipDevRect(rect, op, false);
709705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    }
71051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com};
71151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
712705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.comstatic void add_oval(const SkRect& rect, bool invert, SkRegion::Op op, SkClipStack* stack) {
71351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkPath path;
71451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    path.addOval(rect);
715705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    if (invert) {
716705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        path.setFillType(SkPath::kInverseWinding_FillType);
717705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    }
718705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    stack->clipDevPath(path, op, false);
71951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com};
72051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
7218182fa0cac76e7e6d583aebba060229230516887bsalomon@google.comstatic void add_elem_to_stack(const SkClipStack::Element& element, SkClipStack* stack) {
7228182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    switch (element.getType()) {
7238182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        case SkClipStack::Element::kRect_Type:
7248182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            stack->clipDevRect(element.getRect(), element.getOp(), element.isAA());
7258182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            break;
7268182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        case SkClipStack::Element::kPath_Type:
7278182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            stack->clipDevPath(element.getPath(), element.getOp(), element.isAA());
7288182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            break;
7298182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        case SkClipStack::Element::kEmpty_Type:
7308182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            SkDEBUGFAIL("Why did the reducer produce an explicit empty.");
7318182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            stack->clipEmpty();
7328182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            break;
73351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    }
73451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com}
73551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
7368182fa0cac76e7e6d583aebba060229230516887bsalomon@google.comstatic void add_elem_to_region(const SkClipStack::Element& element,
73751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                               const SkIRect& bounds,
73851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                               SkRegion* region) {
73951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkRegion elemRegion;
74051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkRegion boundsRgn(bounds);
74151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
7428182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    switch (element.getType()) {
7438182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        case SkClipStack::Element::kRect_Type: {
7448182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            SkPath path;
7458182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            path.addRect(element.getRect());
7468182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            elemRegion.setPath(path, boundsRgn);
7478182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            break;
7488182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        }
7498182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        case SkClipStack::Element::kPath_Type:
7508182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            elemRegion.setPath(element.getPath(), boundsRgn);
7518182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            break;
7528182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        case SkClipStack::Element::kEmpty_Type:
75373b140a9f668c189b0682cc5f82d9fb57ff8bc15skia.committer@gmail.com            //
7548182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            region->setEmpty();
7558182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            return;
75651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    }
7578182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    region->op(elemRegion, element.getOp());
75851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com}
75951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
76051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com// This can assist with debugging the clip stack reduction code when the test below fails.
7618182fa0cac76e7e6d583aebba060229230516887bsalomon@google.comstatic void print_clip(const SkClipStack::Element& element) {
76251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const char* kOpStrs[] = {
76351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "DF",
76451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "IS",
76551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "UN",
76651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "XR",
76751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "RD",
76851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "RP",
76951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    };
7708182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    if (SkClipStack::Element::kEmpty_Type != element.getType()) {
7718182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        const SkRect& bounds = element.getBounds();
7728182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        bool isRect = SkClipStack::Element::kRect_Type == element.getType();
773705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        SkDebugf("%s %s %s [%f %f] x [%f %f]\n",
7748182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                 kOpStrs[element.getOp()],
7758182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                 (isRect ? "R" : "P"),
7768182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                 (element.isInverseFilled() ? "I" : " "),
77751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                 bounds.fLeft, bounds.fRight, bounds.fTop, bounds.fBottom);
77851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    } else {
77951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkDebugf("EM\n");
78051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    }
78151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com}
78251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
78351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.comstatic void test_reduced_clip_stack(skiatest::Reporter* reporter) {
78451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // We construct random clip stacks, reduce them, and then rasterize both versions to verify that
7858ccf590b89cec1a5974b6f4b7b49ca67cc5036cfskia.committer@gmail.com    // they are equal.
78651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
78751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // All the clip elements will be contained within these bounds.
78851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const SkRect kBounds = SkRect::MakeWH(100, 100);
78951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
79051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    enum {
79151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        kNumTests = 200,
79251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        kMinElemsPerTest = 1,
79351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        kMaxElemsPerTest = 50,
79451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    };
79551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
79651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // min/max size of a clip element as a fraction of kBounds.
79751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const SkScalar kMinElemSizeFrac = SK_Scalar1 / 5;
79851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const SkScalar kMaxElemSizeFrac = SK_Scalar1;
79951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
80051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const SkRegion::Op kOps[] = {
80151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kDifference_Op,
80251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kIntersect_Op,
80351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kUnion_Op,
80451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kXOR_Op,
80551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kReverseDifference_Op,
80651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kReplace_Op,
80751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    };
80851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
80951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // Replace operations short-circuit the optimizer. We want to make sure that we test this code
81051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // path a little bit but we don't want it to prevent us from testing many longer traversals in
81151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // the optimizer.
81251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const int kReplaceDiv = 4 * kMaxElemsPerTest;
81351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
814705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    // We want to test inverse fills. However, they are quite rare in practice so don't over do it.
815705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    static const SkScalar kFractionInverted = SK_Scalar1 / kMaxElemsPerTest;
816705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com
81751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const AddElementFunc kElementFuncs[] = {
81851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        add_rect,
81951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        add_round_rect,
82051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        add_oval,
82151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    };
82251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
82351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkRandom r;
82451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
82551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    for (int i = 0; i < kNumTests; ++i) {
82651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        // Randomly generate a clip stack.
82751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkClipStack stack;
82851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        int numElems = r.nextRangeU(kMinElemsPerTest, kMaxElemsPerTest);
82951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        for (int e = 0; e < numElems; ++e) {
83051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            SkRegion::Op op = kOps[r.nextULessThan(SK_ARRAY_COUNT(kOps))];
83151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            if (op == SkRegion::kReplace_Op) {
83251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                if (r.nextU() % kReplaceDiv) {
83351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                    --e;
83451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                    continue;
83551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                }
83651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            }
8378ccf590b89cec1a5974b6f4b7b49ca67cc5036cfskia.committer@gmail.com
83851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            // saves can change the clip stack behavior when an element is added.
83951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            bool doSave = r.nextBool();
8408ccf590b89cec1a5974b6f4b7b49ca67cc5036cfskia.committer@gmail.com
84151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            SkSize size = SkSize::Make(
84251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                SkScalarFloorToScalar(SkScalarMul(kBounds.width(), r.nextRangeScalar(kMinElemSizeFrac, kMaxElemSizeFrac))),
84351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                SkScalarFloorToScalar(SkScalarMul(kBounds.height(), r.nextRangeScalar(kMinElemSizeFrac, kMaxElemSizeFrac))));
84451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
84551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            SkPoint xy = {SkScalarFloorToScalar(r.nextRangeScalar(kBounds.fLeft, kBounds.fRight - size.fWidth)),
84651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                          SkScalarFloorToScalar(r.nextRangeScalar(kBounds.fTop, kBounds.fBottom - size.fHeight))};
84751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
84851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            SkRect rect = SkRect::MakeXYWH(xy.fX, xy.fY, size.fWidth, size.fHeight);
84951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
850705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com            bool invert = r.nextBiasedBool(kFractionInverted);
851705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com            kElementFuncs[r.nextULessThan(SK_ARRAY_COUNT(kElementFuncs))](rect, invert, op, &stack);
85251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            if (doSave) {
85351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                stack.save();
85451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            }
85551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
85651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
857a444430281ea35cb76fb42516978b4a93221c2c7bsalomon@google.com        SkRect inflatedBounds = kBounds;
858a444430281ea35cb76fb42516978b4a93221c2c7bsalomon@google.com        inflatedBounds.outset(kBounds.width() / 2, kBounds.height() / 2);
859a444430281ea35cb76fb42516978b4a93221c2c7bsalomon@google.com        SkIRect inflatedIBounds;
860a444430281ea35cb76fb42516978b4a93221c2c7bsalomon@google.com        inflatedBounds.roundOut(&inflatedIBounds);
861a444430281ea35cb76fb42516978b4a93221c2c7bsalomon@google.com
8628182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        typedef GrReducedClip::ElementList ElementList;
86351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        // Get the reduced version of the stack.
8648182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        ElementList reducedClips;
865a444430281ea35cb76fb42516978b4a93221c2c7bsalomon@google.com
86651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        GrReducedClip::InitialState initial;
86734cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com        SkIRect tBounds;
86834cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com        SkIRect* tightBounds = r.nextBool() ? &tBounds : NULL;
86934cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com        GrReducedClip::ReduceClipStack(stack,
87034cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com                                       inflatedIBounds,
87134cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com                                       &reducedClips,
87234cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com                                       &initial,
87334cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com                                       tightBounds);
87451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
87551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        // Build a new clip stack based on the reduced clip elements
87651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkClipStack reducedStack;
87751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        if (GrReducedClip::kAllOut_InitialState == initial) {
87851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            // whether the result is bounded or not, the whole plane should start outside the clip.
87951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            reducedStack.clipEmpty();
88051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
8818182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        for (ElementList::Iter iter = reducedClips.headIter(); NULL != iter.get(); iter.next()) {
8828182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            add_elem_to_stack(*iter.get(), &reducedStack);
88351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
88451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
88534cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com        // GrReducedClipStack assumes that the final result is clipped to the returned bounds
88634cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com        if (NULL != tightBounds) {
88734cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com            reducedStack.clipDevRect(*tightBounds, SkRegion::kIntersect_Op);
88834cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com        }
88934cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com
89051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        // convert both the original stack and reduced stack to SkRegions and see if they're equal
89151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion region;
89251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion reducedRegion;
89351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
89451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        region.setRect(inflatedIBounds);
8958182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        const SkClipStack::Element* element;
89651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
8978182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        while ((element = iter.next())) {
8988182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            add_elem_to_region(*element, inflatedIBounds, &region);
89951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
90051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
90151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        reducedRegion.setRect(inflatedIBounds);
90251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        iter.reset(reducedStack, SkClipStack::Iter::kBottom_IterStart);
9038182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        while ((element = iter.next())) {
9048182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            add_elem_to_region(*element, inflatedIBounds, &reducedRegion);
90551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
90651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
90751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        REPORTER_ASSERT(reporter, region == reducedRegion);
90851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    }
90951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com}
91051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
911a4e13c85b23fe7530ae89a84ef671ebd5e451e80bsalomon@google.com#endif
91251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com///////////////////////////////////////////////////////////////////////////////////////////////////
91351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
914bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.comstatic void TestClipStack(skiatest::Reporter* reporter) {
915bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    SkClipStack stack;
916bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
91780214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 0 == stack.getSaveCount());
918bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    assert_count(reporter, stack, 0);
919bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
920bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    static const SkIRect gRects[] = {
921bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        { 0, 0, 100, 100 },
922bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        { 25, 25, 125, 125 },
923bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        { 0, 0, 1000, 1000 },
924bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        { 0, 0, 75, 75 }
925bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    };
926bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gRects); i++) {
927d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com        stack.clipDevRect(gRects[i], SkRegion::kIntersect_Op);
928bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    }
929bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
930bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    // all of the above rects should have been intersected, leaving only 1 rect
93180214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter iter(stack);
9328182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* element = iter.next();
9332047f00e4698f83499ab91911999a65c21a951c9epoger@google.com    SkRect answer;
9342047f00e4698f83499ab91911999a65c21a951c9epoger@google.com    answer.iset(25, 25, 75, 75);
935bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
9368182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    REPORTER_ASSERT(reporter, NULL != element);
9378182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    REPORTER_ASSERT(reporter, SkClipStack::Element::kRect_Type == element->getType());
9388182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    REPORTER_ASSERT(reporter, SkRegion::kIntersect_Op == element->getOp());
9398182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    REPORTER_ASSERT(reporter, element->getRect() == answer);
940bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    // now check that we only had one in our iterator
941bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    REPORTER_ASSERT(reporter, !iter.next());
942bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
943bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    stack.reset();
94480214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 0 == stack.getSaveCount());
945bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    assert_count(reporter, stack, 0);
9461e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
9471e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    test_assign_and_comparison(reporter);
94880214e26c57c5fea954006400852e8999e201923robertphillips@google.com    test_iterators(reporter);
94908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    test_bounds(reporter, true);        // once with rects
95008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    test_bounds(reporter, false);       // once with paths
951cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    test_isWideOpen(reporter);
95208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    test_rect_merging(reporter);
953edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    test_rect_inverse_fill(reporter);
9548cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    test_quickContains(reporter);
955e7b3d29a1289e64130dd0ec905d94feedc9d1064bsalomon@google.com#if SK_SUPPORT_GPU
956edb26fdb8349a727b226e90cbeab06cd25f5cac0bsalomon@google.com    test_reduced_clip_stack(reporter);
957e7b3d29a1289e64130dd0ec905d94feedc9d1064bsalomon@google.com#endif
958bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com}
959bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
960bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com#include "TestClassDef.h"
961bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.comDEFINE_TESTCLASS("ClipStack", TestClipStackClass, TestClipStack)
962