ClipStackTest.cpp revision 6fbe54c663bd0eed6f6519c31a4c8e291db2613b
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
3956fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.orgstatic void test_rect_replace(skiatest::Reporter* reporter) {
3966fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    SkRect rect = SkRect::MakeWH(100, 100);
3976fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    SkRect rect2 = SkRect::MakeXYWH(50, 50, 100, 100);
3986fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
3996fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    SkRect bound;
4006fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    SkClipStack::BoundsType type;
4016fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    bool isIntersectionOfRects;
4026fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4036fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // Adding a new rect with the replace operator should not increase
4046fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // the stack depth. BW replacing BW.
4056fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    {
4066fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        SkClipStack stack;
4076fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 0 == count(stack));
4086fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4096fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4106fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4116fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4126fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    }
4136fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4146fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // Adding a new rect with the replace operator should not increase
4156fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // the stack depth. AA replacing AA.
4166fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    {
4176fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        SkClipStack stack;
4186fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 0 == count(stack));
4196fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, true);
4206fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4216fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, true);
4226fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4236fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    }
4246fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4256fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // Adding a new rect with the replace operator should not increase
4266fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // the stack depth. BW replacing AA replacing BW.
4276fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    {
4286fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        SkClipStack stack;
4296fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 0 == count(stack));
4306fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4316fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4326fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, true);
4336fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4346fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4356fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4366fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    }
4376fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4386fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // Make sure replace clip rects don't collapse too much.
4396fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    {
4406fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        SkClipStack stack;
4416fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4426fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect2, SkRegion::kIntersect_Op, false);
4436fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4446fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4456fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.save();
4466fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4476fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 2 == count(stack));
4486fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.getBounds(&bound, &type, &isIntersectionOfRects);
4496fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, bound == rect);
4506fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.restore();
4516fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4526fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4536fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.save();
4546fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4556fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4566fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 2 == count(stack));
4576fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.restore();
4586fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4596fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4606fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.save();
4616fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4626fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect2, SkRegion::kIntersect_Op, false);
4636fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4646fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 2 == count(stack));
4656fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.restore();
4666fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4676fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    }
4686fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org}
4696fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4706fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org// Simplified path-based version of test_rect_replace.
4716fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.orgstatic void test_path_replace(skiatest::Reporter* reporter) {
4726fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    SkRect rect = SkRect::MakeWH(100, 100);
4736fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    SkPath path;
4746fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    path.addCircle(50, 50, 50);
4756fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4766fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // Replace operation doesn't grow the stack.
4776fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    {
4786fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        SkClipStack stack;
4796fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 0 == count(stack));
4806fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevPath(path, SkRegion::kReplace_Op, false);
4816fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4826fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevPath(path, SkRegion::kReplace_Op, false);
4836fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4846fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    }
4856fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4866fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // Replacing rect with path.
4876fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    {
4886fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        SkClipStack stack;
4896fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, true);
4906fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4916fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevPath(path, SkRegion::kReplace_Op, true);
4926fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4936fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    }
4946fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org}
4956fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
49608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com// Test out SkClipStack's merging of rect clips. In particular exercise
49708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com// merging of aa vs. bw rects.
49808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.comstatic void test_rect_merging(skiatest::Reporter* reporter) {
49908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
50008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect overlapLeft  = SkRect::MakeLTRB(10, 10, 50, 50);
50108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect overlapRight = SkRect::MakeLTRB(40, 40, 80, 80);
50208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
50308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect nestedParent = SkRect::MakeLTRB(10, 10, 90, 90);
50408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect nestedChild  = SkRect::MakeLTRB(40, 40, 60, 60);
50508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
50608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect bound;
50708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkClipStack::BoundsType type;
50808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    bool isIntersectionOfRects;
50908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
51008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // all bw overlapping - should merge
51108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
51208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
51308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
51408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapLeft, SkRegion::kReplace_Op, false);
51508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
51608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, false);
51708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
51808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 1 == count(stack));
51908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
52008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
52108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
52208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, isIntersectionOfRects);
52308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
52408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
52508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // all aa overlapping - should merge
52608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
52708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
52808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
52908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapLeft, SkRegion::kReplace_Op, true);
53008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
53108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, true);
53208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
53308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 1 == count(stack));
53408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
53508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
53608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
53708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, isIntersectionOfRects);
53808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
53908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
54008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // mixed overlapping - should _not_ merge
54108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
54208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
54308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
54408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapLeft, SkRegion::kReplace_Op, true);
54508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
54608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, false);
54708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
54808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 2 == count(stack));
54908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
55008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
55108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
55208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, !isIntersectionOfRects);
55308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
55408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
55508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // mixed nested (bw inside aa) - should merge
55608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
55708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
55808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
55908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedParent, SkRegion::kReplace_Op, true);
56008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
56108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedChild, SkRegion::kIntersect_Op, false);
56208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
56308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 1 == count(stack));
56408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
56508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
56608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
56708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, isIntersectionOfRects);
56808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
56908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
57008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // mixed nested (aa inside bw) - should merge
57108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
57208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
57308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
57408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedParent, SkRegion::kReplace_Op, false);
57508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
57608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedChild, SkRegion::kIntersect_Op, true);
57708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
57808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 1 == count(stack));
57908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
58008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
58108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
58208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, isIntersectionOfRects);
58308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
58408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
58508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // reverse nested (aa inside bw) - should _not_ merge
58608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
58708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
58808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
58908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedChild, SkRegion::kReplace_Op, false);
59008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
59108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedParent, SkRegion::kIntersect_Op, true);
59208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
59308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 2 == count(stack));
59408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
59508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
59608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
59708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, !isIntersectionOfRects);
59808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
59908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com}
600cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
6018cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.orgstatic void test_quickContains(skiatest::Reporter* reporter) {
6028cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkRect testRect = SkRect::MakeLTRB(10, 10, 40, 40);
6038cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkRect insideRect = SkRect::MakeLTRB(20, 20, 30, 30);
6048cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkRect intersectingRect = SkRect::MakeLTRB(25, 25, 50, 50);
6058cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkRect outsideRect = SkRect::MakeLTRB(0, 0, 50, 50);
6068cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkRect nonIntersectingRect = SkRect::MakeLTRB(100, 100, 110, 110);
6078cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6088cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkPath insideCircle;
6098cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    insideCircle.addCircle(25, 25, 5);
6108cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkPath intersectingCircle;
6118cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    intersectingCircle.addCircle(25, 40, 10);
6128cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkPath outsideCircle;
6138cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    outsideCircle.addCircle(25, 25, 50);
6148cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkPath nonIntersectingCircle;
6158cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    nonIntersectingCircle.addCircle(100, 100, 5);
6168cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6178cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6188cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6198cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(outsideRect, SkRegion::kDifference_Op, false);
6208cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        // return false because quickContains currently does not care for kDifference_Op
6218cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6228cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
623306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
6248cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Replace Op tests
6258cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6268cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6278cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(outsideRect, SkRegion::kReplace_Op, false);
6288cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
6298cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6308cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6318cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6328cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6338cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(insideRect, SkRegion::kIntersect_Op, false);
6348cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.save(); // To prevent in-place substitution by replace OP
6358cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(outsideRect, SkRegion::kReplace_Op, false);
6368cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
6378cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.restore();
6388cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6398cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6408cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6418cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6428cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(outsideRect, SkRegion::kIntersect_Op, false);
6438cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.save(); // To prevent in-place substitution by replace OP
6448cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(insideRect, SkRegion::kReplace_Op, false);
6458cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6468cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.restore();
6478cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6488cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6498cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Verify proper traversal of multi-element clip
6508cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6518cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6528cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(insideRect, SkRegion::kIntersect_Op, false);
6538cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        // Use a path for second clip to prevent in-place intersection
6548cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(outsideCircle, SkRegion::kIntersect_Op, false);
6558cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6568cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6578cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6588cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Intersect Op tests with rectangles
6598cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6608cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6618cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(outsideRect, SkRegion::kIntersect_Op, false);
6628cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
6638cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6648cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6658cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6668cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6678cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(insideRect, SkRegion::kIntersect_Op, false);
6688cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6698cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6708cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6718cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6728cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6738cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(intersectingRect, SkRegion::kIntersect_Op, false);
6748cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6758cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6768cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6778cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6788cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6798cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(nonIntersectingRect, SkRegion::kIntersect_Op, false);
6808cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6818cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6828cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6838cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Intersect Op tests with circle paths
6848cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6858cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6868cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(outsideCircle, SkRegion::kIntersect_Op, false);
6878cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
6888cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6898cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6908cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6918cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6928cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(insideCircle, SkRegion::kIntersect_Op, false);
6938cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6948cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6958cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6968cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6978cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6988cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(intersectingCircle, SkRegion::kIntersect_Op, false);
6998cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
7008cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7018cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7028cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7038cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7048cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(nonIntersectingCircle, SkRegion::kIntersect_Op, false);
7058cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
7068cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7078cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7088cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Intersect Op tests with inverse filled rectangles
7098cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7108cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7118cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path;
7128cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.addRect(outsideRect);
7138cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
7148cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
7158cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
7168cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7178cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7188cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7198cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7208cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path;
7218cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.addRect(insideRect);
7228cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
7238cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
7248cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
7258cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7268cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7278cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7288cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7298cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path;
7308cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.addRect(intersectingRect);
7318cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
7328cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
7338cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
7348cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7358cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7368cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7378cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7388cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path;
7398cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.addRect(nonIntersectingRect);
7408cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
7418cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
7428cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
7438cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7448cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7458cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Intersect Op tests with inverse filled circles
7468cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7478cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7488cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path = outsideCircle;
7498cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
7508cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
7518cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
7528cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7538cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7548cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7558cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7568cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path = insideCircle;
7578cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
7588cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
7598cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
7608cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7618cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7628cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7638cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7648cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path = intersectingCircle;
7658cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
7668cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
7678cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
7688cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7698cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7708cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7718cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7728cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path = nonIntersectingCircle;
7738cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
7748cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
7758cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
7768cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7778cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org}
7788cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
77951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com///////////////////////////////////////////////////////////////////////////////////////////////////
78051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
781a4e13c85b23fe7530ae89a84ef671ebd5e451e80bsalomon@google.com#if SK_SUPPORT_GPU
782705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com// Functions that add a shape to the clip stack. The shape is computed from a rectangle.
783705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com// AA is always disabled since the clip stack reducer can cause changes in aa rasterization of the
784705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com// stack. A fractional edge repeated in different elements may be rasterized fewer times using the
785705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com// reduced stack.
786705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.comtypedef void (*AddElementFunc) (const SkRect& rect,
787705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com                                bool invert,
788705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com                                SkRegion::Op op,
789705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com                                SkClipStack* stack);
790705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com
791705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.comstatic void add_round_rect(const SkRect& rect, bool invert, SkRegion::Op op, SkClipStack* stack) {
79251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkPath path;
79351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkScalar rx = rect.width() / 10;
794705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    SkScalar ry = rect.height() / 20;
79551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    path.addRoundRect(rect, rx, ry);
796705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    if (invert) {
797705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        path.setFillType(SkPath::kInverseWinding_FillType);
798705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    }
799705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    stack->clipDevPath(path, op, false);
80051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com};
80151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
802705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.comstatic void add_rect(const SkRect& rect, bool invert, SkRegion::Op op, SkClipStack* stack) {
803705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    if (invert) {
804705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        SkPath path;
805705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        path.addRect(rect);
806705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        path.setFillType(SkPath::kInverseWinding_FillType);
807705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        stack->clipDevPath(path, op, false);
808705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    } else {
809705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        stack->clipDevRect(rect, op, false);
810705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    }
81151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com};
81251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
813705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.comstatic void add_oval(const SkRect& rect, bool invert, SkRegion::Op op, SkClipStack* stack) {
81451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkPath path;
81551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    path.addOval(rect);
816705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    if (invert) {
817705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        path.setFillType(SkPath::kInverseWinding_FillType);
818705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    }
819705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    stack->clipDevPath(path, op, false);
82051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com};
82151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
8228182fa0cac76e7e6d583aebba060229230516887bsalomon@google.comstatic void add_elem_to_stack(const SkClipStack::Element& element, SkClipStack* stack) {
8238182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    switch (element.getType()) {
8248182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        case SkClipStack::Element::kRect_Type:
8258182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            stack->clipDevRect(element.getRect(), element.getOp(), element.isAA());
8268182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            break;
8278182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        case SkClipStack::Element::kPath_Type:
8288182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            stack->clipDevPath(element.getPath(), element.getOp(), element.isAA());
8298182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            break;
8308182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        case SkClipStack::Element::kEmpty_Type:
8318182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            SkDEBUGFAIL("Why did the reducer produce an explicit empty.");
8328182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            stack->clipEmpty();
8338182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            break;
83451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    }
83551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com}
83651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
8378182fa0cac76e7e6d583aebba060229230516887bsalomon@google.comstatic void add_elem_to_region(const SkClipStack::Element& element,
83851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                               const SkIRect& bounds,
83951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                               SkRegion* region) {
84051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkRegion elemRegion;
84151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkRegion boundsRgn(bounds);
84251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
8438182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    switch (element.getType()) {
8448182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        case SkClipStack::Element::kRect_Type: {
8458182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            SkPath path;
8468182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            path.addRect(element.getRect());
8478182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            elemRegion.setPath(path, boundsRgn);
8488182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            break;
8498182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        }
8508182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        case SkClipStack::Element::kPath_Type:
8518182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            elemRegion.setPath(element.getPath(), boundsRgn);
8528182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            break;
8538182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        case SkClipStack::Element::kEmpty_Type:
85473b140a9f668c189b0682cc5f82d9fb57ff8bc15skia.committer@gmail.com            //
8558182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            region->setEmpty();
8568182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            return;
85751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    }
8588182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    region->op(elemRegion, element.getOp());
85951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com}
86051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
86151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com// This can assist with debugging the clip stack reduction code when the test below fails.
86205af1afd429808913683da75644e48bece12e820humper@google.comstatic inline void print_clip(const SkClipStack::Element& element) {
86351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const char* kOpStrs[] = {
86451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "DF",
86551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "IS",
86651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "UN",
86751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "XR",
86851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "RD",
86951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "RP",
87051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    };
8718182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    if (SkClipStack::Element::kEmpty_Type != element.getType()) {
8728182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        const SkRect& bounds = element.getBounds();
8738182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        bool isRect = SkClipStack::Element::kRect_Type == element.getType();
874705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        SkDebugf("%s %s %s [%f %f] x [%f %f]\n",
8758182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                 kOpStrs[element.getOp()],
8768182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                 (isRect ? "R" : "P"),
8778182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com                 (element.isInverseFilled() ? "I" : " "),
87851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                 bounds.fLeft, bounds.fRight, bounds.fTop, bounds.fBottom);
87951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    } else {
88051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkDebugf("EM\n");
88151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    }
88251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com}
88351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
88451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.comstatic void test_reduced_clip_stack(skiatest::Reporter* reporter) {
88551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // We construct random clip stacks, reduce them, and then rasterize both versions to verify that
8868ccf590b89cec1a5974b6f4b7b49ca67cc5036cfskia.committer@gmail.com    // they are equal.
88751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
88851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // All the clip elements will be contained within these bounds.
88951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const SkRect kBounds = SkRect::MakeWH(100, 100);
89051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
89151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    enum {
89251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        kNumTests = 200,
89351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        kMinElemsPerTest = 1,
89451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        kMaxElemsPerTest = 50,
89551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    };
89651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
89751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // min/max size of a clip element as a fraction of kBounds.
89851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const SkScalar kMinElemSizeFrac = SK_Scalar1 / 5;
89951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const SkScalar kMaxElemSizeFrac = SK_Scalar1;
90051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
90151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const SkRegion::Op kOps[] = {
90251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kDifference_Op,
90351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kIntersect_Op,
90451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kUnion_Op,
90551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kXOR_Op,
90651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kReverseDifference_Op,
90751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kReplace_Op,
90851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    };
90951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
91051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // Replace operations short-circuit the optimizer. We want to make sure that we test this code
91151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // path a little bit but we don't want it to prevent us from testing many longer traversals in
91251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // the optimizer.
91351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const int kReplaceDiv = 4 * kMaxElemsPerTest;
91451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
915705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    // We want to test inverse fills. However, they are quite rare in practice so don't over do it.
916705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    static const SkScalar kFractionInverted = SK_Scalar1 / kMaxElemsPerTest;
917705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com
91851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const AddElementFunc kElementFuncs[] = {
91951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        add_rect,
92051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        add_round_rect,
92151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        add_oval,
92251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    };
92351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
924c490f801b063a0837501feab3d12b73d71f46312jvanverth@google.com    SkMWCRandom r;
92551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
92651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    for (int i = 0; i < kNumTests; ++i) {
92751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        // Randomly generate a clip stack.
92851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkClipStack stack;
92951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        int numElems = r.nextRangeU(kMinElemsPerTest, kMaxElemsPerTest);
93051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        for (int e = 0; e < numElems; ++e) {
93151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            SkRegion::Op op = kOps[r.nextULessThan(SK_ARRAY_COUNT(kOps))];
93251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            if (op == SkRegion::kReplace_Op) {
93351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                if (r.nextU() % kReplaceDiv) {
93451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                    --e;
93551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                    continue;
93651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                }
93751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            }
9388ccf590b89cec1a5974b6f4b7b49ca67cc5036cfskia.committer@gmail.com
93951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            // saves can change the clip stack behavior when an element is added.
94051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            bool doSave = r.nextBool();
9418ccf590b89cec1a5974b6f4b7b49ca67cc5036cfskia.committer@gmail.com
94251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            SkSize size = SkSize::Make(
94351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                SkScalarFloorToScalar(SkScalarMul(kBounds.width(), r.nextRangeScalar(kMinElemSizeFrac, kMaxElemSizeFrac))),
94451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                SkScalarFloorToScalar(SkScalarMul(kBounds.height(), r.nextRangeScalar(kMinElemSizeFrac, kMaxElemSizeFrac))));
94551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
94651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            SkPoint xy = {SkScalarFloorToScalar(r.nextRangeScalar(kBounds.fLeft, kBounds.fRight - size.fWidth)),
94751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                          SkScalarFloorToScalar(r.nextRangeScalar(kBounds.fTop, kBounds.fBottom - size.fHeight))};
94851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
94951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            SkRect rect = SkRect::MakeXYWH(xy.fX, xy.fY, size.fWidth, size.fHeight);
95051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
951705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com            bool invert = r.nextBiasedBool(kFractionInverted);
952705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com            kElementFuncs[r.nextULessThan(SK_ARRAY_COUNT(kElementFuncs))](rect, invert, op, &stack);
95351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            if (doSave) {
95451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                stack.save();
95551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            }
95651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
95751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
958a444430281ea35cb76fb42516978b4a93221c2c7bsalomon@google.com        SkRect inflatedBounds = kBounds;
959a444430281ea35cb76fb42516978b4a93221c2c7bsalomon@google.com        inflatedBounds.outset(kBounds.width() / 2, kBounds.height() / 2);
960a444430281ea35cb76fb42516978b4a93221c2c7bsalomon@google.com        SkIRect inflatedIBounds;
961a444430281ea35cb76fb42516978b4a93221c2c7bsalomon@google.com        inflatedBounds.roundOut(&inflatedIBounds);
962a444430281ea35cb76fb42516978b4a93221c2c7bsalomon@google.com
9638182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        typedef GrReducedClip::ElementList ElementList;
96451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        // Get the reduced version of the stack.
9658182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        ElementList reducedClips;
966a444430281ea35cb76fb42516978b4a93221c2c7bsalomon@google.com
96751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        GrReducedClip::InitialState initial;
968c490f801b063a0837501feab3d12b73d71f46312jvanverth@google.com        SkIRect tBounds(inflatedIBounds);
96934cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com        SkIRect* tightBounds = r.nextBool() ? &tBounds : NULL;
97034cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com        GrReducedClip::ReduceClipStack(stack,
97134cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com                                       inflatedIBounds,
97234cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com                                       &reducedClips,
97334cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com                                       &initial,
97434cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com                                       tightBounds);
97551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
97651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        // Build a new clip stack based on the reduced clip elements
97751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkClipStack reducedStack;
97851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        if (GrReducedClip::kAllOut_InitialState == initial) {
97951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            // whether the result is bounded or not, the whole plane should start outside the clip.
98051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            reducedStack.clipEmpty();
98151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
9828182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        for (ElementList::Iter iter = reducedClips.headIter(); NULL != iter.get(); iter.next()) {
9838182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            add_elem_to_stack(*iter.get(), &reducedStack);
98451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
98551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
98634cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com        // GrReducedClipStack assumes that the final result is clipped to the returned bounds
98734cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com        if (NULL != tightBounds) {
98834cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com            reducedStack.clipDevRect(*tightBounds, SkRegion::kIntersect_Op);
98934cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com        }
99034cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com
99151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        // convert both the original stack and reduced stack to SkRegions and see if they're equal
99251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion region;
99351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion reducedRegion;
99451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
99551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        region.setRect(inflatedIBounds);
9968182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        const SkClipStack::Element* element;
99751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
9988182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        while ((element = iter.next())) {
9998182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            add_elem_to_region(*element, inflatedIBounds, &region);
100051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
100151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
100251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        reducedRegion.setRect(inflatedIBounds);
100351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        iter.reset(reducedStack, SkClipStack::Iter::kBottom_IterStart);
10048182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        while ((element = iter.next())) {
10058182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            add_elem_to_region(*element, inflatedIBounds, &reducedRegion);
100651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
100751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
100851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        REPORTER_ASSERT(reporter, region == reducedRegion);
100951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    }
101051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com}
101151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
1012a4e13c85b23fe7530ae89a84ef671ebd5e451e80bsalomon@google.com#endif
101351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com///////////////////////////////////////////////////////////////////////////////////////////////////
101451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
1015bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.comstatic void TestClipStack(skiatest::Reporter* reporter) {
1016bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    SkClipStack stack;
1017bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
101880214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 0 == stack.getSaveCount());
1019bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    assert_count(reporter, stack, 0);
1020bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
1021bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    static const SkIRect gRects[] = {
1022bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        { 0, 0, 100, 100 },
1023bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        { 25, 25, 125, 125 },
1024bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        { 0, 0, 1000, 1000 },
1025bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        { 0, 0, 75, 75 }
1026bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    };
1027bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gRects); i++) {
1028d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com        stack.clipDevRect(gRects[i], SkRegion::kIntersect_Op);
1029bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    }
1030bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
1031bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    // all of the above rects should have been intersected, leaving only 1 rect
103280214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter iter(stack);
10338182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* element = iter.next();
10342047f00e4698f83499ab91911999a65c21a951c9epoger@google.com    SkRect answer;
10352047f00e4698f83499ab91911999a65c21a951c9epoger@google.com    answer.iset(25, 25, 75, 75);
1036bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
10378182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    REPORTER_ASSERT(reporter, NULL != element);
10388182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    REPORTER_ASSERT(reporter, SkClipStack::Element::kRect_Type == element->getType());
10398182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    REPORTER_ASSERT(reporter, SkRegion::kIntersect_Op == element->getOp());
10408182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    REPORTER_ASSERT(reporter, element->getRect() == answer);
1041bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    // now check that we only had one in our iterator
1042bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    REPORTER_ASSERT(reporter, !iter.next());
1043bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
1044bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    stack.reset();
104580214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 0 == stack.getSaveCount());
1046bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    assert_count(reporter, stack, 0);
10471e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
10481e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    test_assign_and_comparison(reporter);
104980214e26c57c5fea954006400852e8999e201923robertphillips@google.com    test_iterators(reporter);
105008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    test_bounds(reporter, true);        // once with rects
105108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    test_bounds(reporter, false);       // once with paths
1052cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    test_isWideOpen(reporter);
105308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    test_rect_merging(reporter);
10546fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    test_rect_replace(reporter);
1055edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    test_rect_inverse_fill(reporter);
10566fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    test_path_replace(reporter);
10578cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    test_quickContains(reporter);
1058e7b3d29a1289e64130dd0ec905d94feedc9d1064bsalomon@google.com#if SK_SUPPORT_GPU
1059edb26fdb8349a727b226e90cbeab06cd25f5cac0bsalomon@google.com    test_reduced_clip_stack(reporter);
1060e7b3d29a1289e64130dd0ec905d94feedc9d1064bsalomon@google.com#endif
1061bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com}
1062bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
1063bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com#include "TestClassDef.h"
1064bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.comDEFINE_TESTCLASS("ClipStack", TestClipStackClass, TestClipStack)
1065