1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
7e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.org
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
181e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.orgstatic void test_assign_and_comparison(skiatest::Reporter* reporter) {
191e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkClipStack s;
20d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    bool doAA = false;
211e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
2280214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 0 == s.getSaveCount());
2380214e26c57c5fea954006400852e8999e201923robertphillips@google.com
241e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Build up a clip stack with a path, an empty clip, and a rect.
251e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
2680214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 1 == s.getSaveCount());
2780214e26c57c5fea954006400852e8999e201923robertphillips@google.com
281e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkPath p;
291e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    p.moveTo(5, 6);
301e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    p.lineTo(7, 8);
311e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    p.lineTo(5, 9);
321e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    p.close();
33d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevPath(p, SkRegion::kIntersect_Op, doAA);
341e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
351e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
3680214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == s.getSaveCount());
3780214e26c57c5fea954006400852e8999e201923robertphillips@google.com
381e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkRect r = SkRect::MakeLTRB(1, 2, 3, 4);
39d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kIntersect_Op, doAA);
401e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    r = SkRect::MakeLTRB(10, 11, 12, 13);
41d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kIntersect_Op, doAA);
421e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
431e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
4480214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 3 == s.getSaveCount());
4580214e26c57c5fea954006400852e8999e201923robertphillips@google.com
461e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    r = SkRect::MakeLTRB(14, 15, 16, 17);
47d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kUnion_Op, doAA);
481e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
491e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that assignment works.
501e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkClipStack copy = s;
511e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s == copy);
521e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
531e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that different save levels triggers not equal.
541e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
5580214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == s.getSaveCount());
561e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s != copy);
571e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
581e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that an equal, but not copied version is equal.
591e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
6080214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 3 == s.getSaveCount());
611e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    r = SkRect::MakeLTRB(14, 15, 16, 17);
62d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kUnion_Op, doAA);
631e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s == copy);
641e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
651e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that a different op on one level triggers not equal.
661e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
6780214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == s.getSaveCount());
681e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
6980214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 3 == s.getSaveCount());
701e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    r = SkRect::MakeLTRB(14, 15, 16, 17);
71d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kIntersect_Op, doAA);
721e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s != copy);
731e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
74e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    // Test that version constructed with rect-path rather than a rect is still considered equal.
751e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
761e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
771e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkPath rp;
781e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    rp.addRect(r);
79d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevPath(rp, SkRegion::kUnion_Op, doAA);
80e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    REPORTER_ASSERT(reporter, s == copy);
811e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
821e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that different rects triggers not equal.
831e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
8480214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == s.getSaveCount());
851e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
8680214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 3 == s.getSaveCount());
8780214e26c57c5fea954006400852e8999e201923robertphillips@google.com
881e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    r = SkRect::MakeLTRB(24, 25, 26, 27);
89d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kUnion_Op, doAA);
901e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s != copy);
911e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
921e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Sanity check
931e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
9480214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == s.getSaveCount());
9580214e26c57c5fea954006400852e8999e201923robertphillips@google.com
961e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    copy.restore();
9780214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == copy.getSaveCount());
981e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s == copy);
991e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
10080214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 1 == s.getSaveCount());
1011e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    copy.restore();
10280214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 1 == copy.getSaveCount());
1031e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s == copy);
1041e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
1051e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that different paths triggers not equal.
1061e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
10780214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 0 == s.getSaveCount());
1081e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
10980214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 1 == s.getSaveCount());
11080214e26c57c5fea954006400852e8999e201923robertphillips@google.com
1111e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    p.addRect(r);
112d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevPath(p, SkRegion::kIntersect_Op, doAA);
1131e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s != copy);
1141e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org}
115bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
116bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.comstatic void assert_count(skiatest::Reporter* reporter, const SkClipStack& stack,
117bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com                         int count) {
11880214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter iter(stack);
119bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    int counter = 0;
120bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    while (iter.next()) {
121bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        counter += 1;
122bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    }
123bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    REPORTER_ASSERT(reporter, count == counter);
124bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com}
125bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
12608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com// Exercise the SkClipStack's bottom to top and bidirectional iterators
12708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com// (including the skipToTopmost functionality)
12880214e26c57c5fea954006400852e8999e201923robertphillips@google.comstatic void test_iterators(skiatest::Reporter* reporter) {
12980214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack stack;
13080214e26c57c5fea954006400852e8999e201923robertphillips@google.com
13180214e26c57c5fea954006400852e8999e201923robertphillips@google.com    static const SkRect gRects[] = {
13280214e26c57c5fea954006400852e8999e201923robertphillips@google.com        { 0,   0,  40,  40 },
13380214e26c57c5fea954006400852e8999e201923robertphillips@google.com        { 60,  0, 100,  40 },
13480214e26c57c5fea954006400852e8999e201923robertphillips@google.com        { 0,  60,  40, 100 },
13580214e26c57c5fea954006400852e8999e201923robertphillips@google.com        { 60, 60, 100, 100 }
13680214e26c57c5fea954006400852e8999e201923robertphillips@google.com    };
13780214e26c57c5fea954006400852e8999e201923robertphillips@google.com
13880214e26c57c5fea954006400852e8999e201923robertphillips@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gRects); i++) {
13980214e26c57c5fea954006400852e8999e201923robertphillips@google.com        // the union op will prevent these from being fused together
14080214e26c57c5fea954006400852e8999e201923robertphillips@google.com        stack.clipDevRect(gRects[i], SkRegion::kUnion_Op, false);
14180214e26c57c5fea954006400852e8999e201923robertphillips@google.com    }
14280214e26c57c5fea954006400852e8999e201923robertphillips@google.com
14380214e26c57c5fea954006400852e8999e201923robertphillips@google.com    assert_count(reporter, stack, 4);
14480214e26c57c5fea954006400852e8999e201923robertphillips@google.com
14580214e26c57c5fea954006400852e8999e201923robertphillips@google.com    // bottom to top iteration
14680214e26c57c5fea954006400852e8999e201923robertphillips@google.com    {
1472880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        const SkClipStack::Element* element = nullptr;
14880214e26c57c5fea954006400852e8999e201923robertphillips@google.com
14980214e26c57c5fea954006400852e8999e201923robertphillips@google.com        SkClipStack::B2TIter iter(stack);
15080214e26c57c5fea954006400852e8999e201923robertphillips@google.com        int i;
15180214e26c57c5fea954006400852e8999e201923robertphillips@google.com
1528182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        for (i = 0, element = iter.next(); element; ++i, element = iter.next()) {
1538182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            REPORTER_ASSERT(reporter, SkClipStack::Element::kRect_Type == element->getType());
1548182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            REPORTER_ASSERT(reporter, element->getRect() == gRects[i]);
15580214e26c57c5fea954006400852e8999e201923robertphillips@google.com        }
15680214e26c57c5fea954006400852e8999e201923robertphillips@google.com
15780214e26c57c5fea954006400852e8999e201923robertphillips@google.com        SkASSERT(i == 4);
15880214e26c57c5fea954006400852e8999e201923robertphillips@google.com    }
15980214e26c57c5fea954006400852e8999e201923robertphillips@google.com
16080214e26c57c5fea954006400852e8999e201923robertphillips@google.com    // top to bottom iteration
16180214e26c57c5fea954006400852e8999e201923robertphillips@google.com    {
1622880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        const SkClipStack::Element* element = nullptr;
16380214e26c57c5fea954006400852e8999e201923robertphillips@google.com
16480214e26c57c5fea954006400852e8999e201923robertphillips@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
16580214e26c57c5fea954006400852e8999e201923robertphillips@google.com        int i;
16680214e26c57c5fea954006400852e8999e201923robertphillips@google.com
1678182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        for (i = 3, element = iter.prev(); element; --i, element = iter.prev()) {
1688182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            REPORTER_ASSERT(reporter, SkClipStack::Element::kRect_Type == element->getType());
1698182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            REPORTER_ASSERT(reporter, element->getRect() == gRects[i]);
17080214e26c57c5fea954006400852e8999e201923robertphillips@google.com        }
17180214e26c57c5fea954006400852e8999e201923robertphillips@google.com
17280214e26c57c5fea954006400852e8999e201923robertphillips@google.com        SkASSERT(i == -1);
17380214e26c57c5fea954006400852e8999e201923robertphillips@google.com    }
17480214e26c57c5fea954006400852e8999e201923robertphillips@google.com
17580214e26c57c5fea954006400852e8999e201923robertphillips@google.com    // skipToTopmost
17680214e26c57c5fea954006400852e8999e201923robertphillips@google.com    {
1772880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        const SkClipStack::Element* element = nullptr;
17880214e26c57c5fea954006400852e8999e201923robertphillips@google.com
17980214e26c57c5fea954006400852e8999e201923robertphillips@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
18080214e26c57c5fea954006400852e8999e201923robertphillips@google.com
1818182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        element = iter.skipToTopmost(SkRegion::kUnion_Op);
1828182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        REPORTER_ASSERT(reporter, SkClipStack::Element::kRect_Type == element->getType());
1838182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        REPORTER_ASSERT(reporter, element->getRect() == gRects[3]);
18480214e26c57c5fea954006400852e8999e201923robertphillips@google.com    }
18580214e26c57c5fea954006400852e8999e201923robertphillips@google.com}
18680214e26c57c5fea954006400852e8999e201923robertphillips@google.com
18708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com// Exercise the SkClipStack's getConservativeBounds computation
188e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.orgstatic void test_bounds(skiatest::Reporter* reporter, SkClipStack::Element::Type primType) {
189607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    static const int gNumCases = 20;
190607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    static const SkRect gAnswerRectsBW[gNumCases] = {
191607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        // A op B
192607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 50, 50 },
193607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 50, 50 },
194607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 80, 80 },
195607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 80, 80 },
196607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 80, 80 },
197607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
198607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        // invA op B
199607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 80, 80 },
200607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
201607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
202607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
203607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 50, 50 },
204607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
205607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        // A op invB
206607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 50, 50 },
207607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 50, 50 },
208607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
209607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
210607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
211607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
212607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        // invA op invB
213607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
214607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 80, 80 },
215607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
216607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 80, 80 },
217607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 50, 50 },
218607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    };
219607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
220607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    static const SkRegion::Op gOps[] = {
221607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        SkRegion::kIntersect_Op,
222607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        SkRegion::kDifference_Op,
223607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        SkRegion::kUnion_Op,
224607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        SkRegion::kXOR_Op,
225607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        SkRegion::kReverseDifference_Op
226607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    };
227607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
228607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    SkRect rectA, rectB;
229607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
230607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    rectA.iset(10, 10, 50, 50);
231607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    rectB.iset(40, 40, 80, 80);
232607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
233e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    SkRRect rrectA, rrectB;
234e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    rrectA.setOval(rectA);
235e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    rrectB.setRectXY(rectB, SkIntToScalar(1), SkIntToScalar(2));
236607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
237e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    SkPath pathA, pathB;
238e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org
239e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    pathA.addRoundRect(rectA, SkIntToScalar(5), SkIntToScalar(5));
240e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    pathB.addRoundRect(rectB, SkIntToScalar(5), SkIntToScalar(5));
241607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
242607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    SkClipStack stack;
2437b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    SkRect devClipBound;
2444c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com    bool isIntersectionOfRects = false;
245607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
246607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    int testCase = 0;
247e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    int numBitTests = SkClipStack::Element::kPath_Type == primType ? 4 : 1;
2484c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com    for (int invBits = 0; invBits < numBitTests; ++invBits) {
249607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
250607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
251607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            stack.save();
252607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            bool doInvA = SkToBool(invBits & 1);
253607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            bool doInvB = SkToBool(invBits & 2);
254607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
255e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            pathA.setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType :
256607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com                                       SkPath::kEvenOdd_FillType);
257e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            pathB.setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType :
258607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com                                       SkPath::kEvenOdd_FillType);
259607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
260e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            switch (primType) {
261e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                case SkClipStack::Element::kEmpty_Type:
262e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                    SkDEBUGFAIL("Don't call this with kEmpty.");
263e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                    break;
264e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                case SkClipStack::Element::kRect_Type:
265e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                    stack.clipDevRect(rectA, SkRegion::kIntersect_Op, false);
266e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                    stack.clipDevRect(rectB, gOps[op], false);
267e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                    break;
268e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                case SkClipStack::Element::kRRect_Type:
269e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                    stack.clipDevRRect(rrectA, SkRegion::kIntersect_Op, false);
270e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                    stack.clipDevRRect(rrectB, gOps[op], false);
271e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                    break;
272e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                case SkClipStack::Element::kPath_Type:
273e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                    stack.clipDevPath(pathA, SkRegion::kIntersect_Op, false);
274e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                    stack.clipDevPath(pathB, gOps[op], false);
275e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                    break;
2764c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com            }
277607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
278cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com            REPORTER_ASSERT(reporter, !stack.isWideOpen());
279d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID != stack.getTopmostGenID());
280cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
2817b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com            stack.getConservativeBounds(0, 0, 100, 100, &devClipBound,
2824c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                                        &isIntersectionOfRects);
2834c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com
284e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            if (SkClipStack::Element::kRect_Type == primType) {
285d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com                REPORTER_ASSERT(reporter, isIntersectionOfRects ==
2864c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                        (gOps[op] == SkRegion::kIntersect_Op));
2874c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com            } else {
2884c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                REPORTER_ASSERT(reporter, !isIntersectionOfRects);
2894c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com            }
290607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
291607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            SkASSERT(testCase < gNumCases);
2927b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com            REPORTER_ASSERT(reporter, devClipBound == gAnswerRectsBW[testCase]);
293607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            ++testCase;
294607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
295607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            stack.restore();
296607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        }
297607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    }
298607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com}
299607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
300cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com// Test out 'isWideOpen' entry point
301cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.comstatic void test_isWideOpen(skiatest::Reporter* reporter) {
302d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    {
303d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        // Empty stack is wide open. Wide open stack means that gen id is wide open.
304d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        SkClipStack stack;
305d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        REPORTER_ASSERT(reporter, stack.isWideOpen());
306d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID == stack.getTopmostGenID());
307d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    }
308cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
309cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    SkRect rectA, rectB;
310cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
311cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    rectA.iset(10, 10, 40, 40);
312cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    rectB.iset(50, 50, 80, 80);
313cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
314cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    // Stack should initially be wide open
315cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    {
316cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkClipStack stack;
317cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
318cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, stack.isWideOpen());
319d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID == stack.getTopmostGenID());
320cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    }
321cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
322cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    // Test out case where the user specifies a union that includes everything
323cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    {
324cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkClipStack stack;
325cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
326cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkPath clipA, clipB;
327cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
328cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        clipA.addRoundRect(rectA, SkIntToScalar(5), SkIntToScalar(5));
329cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        clipA.setFillType(SkPath::kInverseEvenOdd_FillType);
330cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
331cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        clipB.addRoundRect(rectB, SkIntToScalar(5), SkIntToScalar(5));
332cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        clipB.setFillType(SkPath::kInverseEvenOdd_FillType);
333cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
334cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.clipDevPath(clipA, SkRegion::kReplace_Op, false);
335cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.clipDevPath(clipB, SkRegion::kUnion_Op, false);
336cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
337cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, stack.isWideOpen());
338d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID == stack.getTopmostGenID());
339cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    }
340cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
341cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    // Test out union w/ a wide open clip
342cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    {
343cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkClipStack stack;
344cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
345cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.clipDevRect(rectA, SkRegion::kUnion_Op, false);
346cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
347cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, stack.isWideOpen());
348d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID == stack.getTopmostGenID());
349cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    }
350cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
351cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    // Test out empty difference from a wide open clip
352cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    {
353cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkClipStack stack;
354cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
355cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkRect emptyRect;
356cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        emptyRect.setEmpty();
357cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
358cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.clipDevRect(emptyRect, SkRegion::kDifference_Op, false);
359cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
360cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, stack.isWideOpen());
361d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID == stack.getTopmostGenID());
362cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    }
363cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
364cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    // Test out return to wide open
365cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    {
366cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkClipStack stack;
367cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
368cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.save();
369cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
370cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.clipDevRect(rectA, SkRegion::kReplace_Op, false);
371cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
372cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, !stack.isWideOpen());
373d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID != stack.getTopmostGenID());
374cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
375cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.restore();
376cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
377cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, stack.isWideOpen());
378d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        REPORTER_ASSERT(reporter, SkClipStack::kWideOpenGenID == stack.getTopmostGenID());
379cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    }
380cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com}
381cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
382100abf49e10544bc4f436bf1f38e6929779621f4bsalomon@google.comstatic int count(const SkClipStack& stack) {
38308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
38408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
38508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
3862880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    const SkClipStack::Element* element = nullptr;
38708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    int count = 0;
38808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
3898182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    for (element = iter.prev(); element; element = iter.prev(), ++count) {
39008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        ;
39108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
39208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
39308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    return count;
39408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com}
39508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
396edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.orgstatic void test_rect_inverse_fill(skiatest::Reporter* reporter) {
397edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    // non-intersecting rectangles
398edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    SkRect rect  = SkRect::MakeLTRB(0, 0, 10, 10);
399edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org
400edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    SkPath path;
401edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    path.addRect(rect);
402edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    path.toggleInverseFillType();
403edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    SkClipStack stack;
404edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
405edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org
406edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    SkRect bounds;
407edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    SkClipStack::BoundsType boundsType;
408edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    stack.getBounds(&bounds, &boundsType);
409edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    REPORTER_ASSERT(reporter, SkClipStack::kInsideOut_BoundsType == boundsType);
410edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    REPORTER_ASSERT(reporter, bounds == rect);
411edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org}
412edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org
4136fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.orgstatic void test_rect_replace(skiatest::Reporter* reporter) {
4146fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    SkRect rect = SkRect::MakeWH(100, 100);
4156fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    SkRect rect2 = SkRect::MakeXYWH(50, 50, 100, 100);
4166fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4176fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    SkRect bound;
4186fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    SkClipStack::BoundsType type;
4196fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    bool isIntersectionOfRects;
4206fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4216fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // Adding a new rect with the replace operator should not increase
4226fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // the stack depth. BW replacing BW.
4236fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    {
4246fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        SkClipStack stack;
4256fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 0 == count(stack));
4266fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4276fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4286fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4296fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4306fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    }
4316fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4326fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // Adding a new rect with the replace operator should not increase
4336fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // the stack depth. AA replacing AA.
4346fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    {
4356fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        SkClipStack stack;
4366fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 0 == count(stack));
4376fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, true);
4386fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4396fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, true);
4406fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4416fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    }
4426fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4436fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // Adding a new rect with the replace operator should not increase
4446fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // the stack depth. BW replacing AA replacing BW.
4456fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    {
4466fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        SkClipStack stack;
4476fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 0 == count(stack));
4486fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4496fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4506fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, true);
4516fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4526fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4536fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4546fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    }
4556fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4566fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // Make sure replace clip rects don't collapse too much.
4576fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    {
4586fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        SkClipStack stack;
4596fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4606fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect2, SkRegion::kIntersect_Op, false);
4616fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4626fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4636fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.save();
4646fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4656fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 2 == count(stack));
4666fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.getBounds(&bound, &type, &isIntersectionOfRects);
4676fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, bound == rect);
4686fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.restore();
4696fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4706fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4716fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.save();
4726fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4736fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4746fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 2 == count(stack));
4756fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.restore();
4766fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4776fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4786fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.save();
4796fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4806fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect2, SkRegion::kIntersect_Op, false);
4816fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, false);
4826fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 2 == count(stack));
4836fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.restore();
4846fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
4856fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    }
4866fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org}
4876fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4886fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org// Simplified path-based version of test_rect_replace.
4896fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.orgstatic void test_path_replace(skiatest::Reporter* reporter) {
4906fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    SkRect rect = SkRect::MakeWH(100, 100);
4916fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    SkPath path;
4926fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    path.addCircle(50, 50, 50);
4936fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
4946fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // Replace operation doesn't grow the stack.
4956fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    {
4966fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        SkClipStack stack;
4976fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 0 == count(stack));
4986fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevPath(path, SkRegion::kReplace_Op, false);
4996fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
5006fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevPath(path, SkRegion::kReplace_Op, false);
5016fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
5026fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    }
5036fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
5046fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    // Replacing rect with path.
5056fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    {
5066fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        SkClipStack stack;
5076fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevRect(rect, SkRegion::kReplace_Op, true);
5086fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
5096fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        stack.clipDevPath(path, SkRegion::kReplace_Op, true);
5106fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        REPORTER_ASSERT(reporter, 1 == count(stack));
5116fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    }
5126fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org}
5136fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
51408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com// Test out SkClipStack's merging of rect clips. In particular exercise
51508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com// merging of aa vs. bw rects.
51608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.comstatic void test_rect_merging(skiatest::Reporter* reporter) {
51708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
51808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect overlapLeft  = SkRect::MakeLTRB(10, 10, 50, 50);
51908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect overlapRight = SkRect::MakeLTRB(40, 40, 80, 80);
52008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
52108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect nestedParent = SkRect::MakeLTRB(10, 10, 90, 90);
52208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect nestedChild  = SkRect::MakeLTRB(40, 40, 60, 60);
52308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
52408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect bound;
52508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkClipStack::BoundsType type;
52608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    bool isIntersectionOfRects;
52708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
52808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // all bw overlapping - should merge
52908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
53008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
53108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
53208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapLeft, SkRegion::kReplace_Op, false);
53308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
53408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, false);
53508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
53608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 1 == count(stack));
53708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
53808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
53908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
54008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, isIntersectionOfRects);
54108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
54208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
54308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // all aa overlapping - should merge
54408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
54508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
54608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
54708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapLeft, SkRegion::kReplace_Op, true);
54808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
54908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, true);
55008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
55108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 1 == count(stack));
55208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
55308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
55408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
55508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, isIntersectionOfRects);
55608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
55708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
55808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // mixed overlapping - should _not_ merge
55908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
56008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
56108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
56208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapLeft, SkRegion::kReplace_Op, true);
56308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
56408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, false);
56508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
56608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 2 == count(stack));
56708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
56808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
56908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
57008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, !isIntersectionOfRects);
57108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
57208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
57308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // mixed nested (bw inside aa) - should merge
57408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
57508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
57608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
57708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedParent, SkRegion::kReplace_Op, true);
57808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
57908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedChild, SkRegion::kIntersect_Op, false);
58008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
58108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 1 == count(stack));
58208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
58308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
58408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
58508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, isIntersectionOfRects);
58608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
58708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
58808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // mixed nested (aa inside bw) - should merge
58908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
59008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
59108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
59208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedParent, SkRegion::kReplace_Op, false);
59308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
59408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedChild, SkRegion::kIntersect_Op, true);
59508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
59608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 1 == count(stack));
59708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
59808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
59908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
60008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, isIntersectionOfRects);
60108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
60208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
60308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // reverse nested (aa inside bw) - should _not_ merge
60408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
60508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
60608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
60708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedChild, SkRegion::kReplace_Op, false);
60808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
60908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedParent, SkRegion::kIntersect_Op, true);
61008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
61108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 2 == count(stack));
61208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
61308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
61408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
61508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, !isIntersectionOfRects);
61608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
61708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com}
618cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
6198cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.orgstatic void test_quickContains(skiatest::Reporter* reporter) {
6208cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkRect testRect = SkRect::MakeLTRB(10, 10, 40, 40);
6218cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkRect insideRect = SkRect::MakeLTRB(20, 20, 30, 30);
6228cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkRect intersectingRect = SkRect::MakeLTRB(25, 25, 50, 50);
6238cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkRect outsideRect = SkRect::MakeLTRB(0, 0, 50, 50);
6248cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkRect nonIntersectingRect = SkRect::MakeLTRB(100, 100, 110, 110);
6258cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6268cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkPath insideCircle;
6278cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    insideCircle.addCircle(25, 25, 5);
6288cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkPath intersectingCircle;
6298cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    intersectingCircle.addCircle(25, 40, 10);
6308cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkPath outsideCircle;
6318cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    outsideCircle.addCircle(25, 25, 50);
6328cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    SkPath nonIntersectingCircle;
6338cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    nonIntersectingCircle.addCircle(100, 100, 5);
6348cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6358cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6368cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6378cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(outsideRect, SkRegion::kDifference_Op, false);
6388cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        // return false because quickContains currently does not care for kDifference_Op
6398cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6408cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
641306ab9d5de38f2a547fd1d69aedbe69b5c6617ccskia.committer@gmail.com
6428cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Replace Op tests
6438cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6448cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6458cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(outsideRect, SkRegion::kReplace_Op, false);
6468cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
6478cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6488cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6498cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6508cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6518cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(insideRect, SkRegion::kIntersect_Op, false);
6528cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.save(); // To prevent in-place substitution by replace OP
6538cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(outsideRect, SkRegion::kReplace_Op, false);
6548cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
6558cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.restore();
6568cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6578cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6588cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6598cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6608cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(outsideRect, SkRegion::kIntersect_Op, false);
6618cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.save(); // To prevent in-place substitution by replace OP
6628cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(insideRect, SkRegion::kReplace_Op, false);
6638cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6648cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.restore();
6658cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6668cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6678cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Verify proper traversal of multi-element clip
6688cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6698cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6708cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(insideRect, SkRegion::kIntersect_Op, false);
6718cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        // Use a path for second clip to prevent in-place intersection
6728cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(outsideCircle, SkRegion::kIntersect_Op, false);
6738cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6748cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6758cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6768cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Intersect Op tests with rectangles
6778cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6788cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6798cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(outsideRect, SkRegion::kIntersect_Op, false);
6808cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
6818cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6828cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6838cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6848cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6858cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(insideRect, SkRegion::kIntersect_Op, false);
6868cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6878cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6888cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6898cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6908cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6918cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(intersectingRect, SkRegion::kIntersect_Op, false);
6928cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6938cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6948cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6958cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
6968cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
6978cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevRect(nonIntersectingRect, SkRegion::kIntersect_Op, false);
6988cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
6998cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7008cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7018cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Intersect Op tests with circle paths
7028cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7038cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7048cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(outsideCircle, SkRegion::kIntersect_Op, false);
7058cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
7068cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7078cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7088cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7098cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7108cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(insideCircle, SkRegion::kIntersect_Op, false);
7118cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
7128cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7138cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7148cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7158cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7168cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(intersectingCircle, SkRegion::kIntersect_Op, false);
7178cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
7188cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7198cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7208cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7218cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7228cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(nonIntersectingCircle, SkRegion::kIntersect_Op, false);
7238cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
7248cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7258cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7268cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Intersect Op tests with inverse filled rectangles
7278cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7288cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7298cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path;
7308cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.addRect(outsideRect);
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(insideRect);
7408cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
7418cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
7428cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
7438cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7448cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7458cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7468cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7478cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path;
7488cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.addRect(intersectingRect);
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;
7578cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.addRect(nonIntersectingRect);
7588cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
7598cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
7608cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
7618cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7628cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7638cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    // Intersect Op tests with inverse filled circles
7648cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7658cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7668cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path = outsideCircle;
7678cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
7688cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
7698cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
7708cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7718cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7728cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7738cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7748cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path = insideCircle;
7758cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
7768cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
7778cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
7788cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7798cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7808cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7818cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7828cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path = intersectingCircle;
7838cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
7848cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
7858cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, false == stack.quickContains(testRect));
7868cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7878cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
7888cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    {
7898cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkClipStack stack;
7908cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        SkPath path = nonIntersectingCircle;
7918cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        path.toggleInverseFillType();
7928cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        stack.clipDevPath(path, SkRegion::kIntersect_Op, false);
7938cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        REPORTER_ASSERT(reporter, true == stack.quickContains(testRect));
7948cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
7958cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org}
7968cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
79751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com///////////////////////////////////////////////////////////////////////////////////////////////////
79851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
799a4e13c85b23fe7530ae89a84ef671ebd5e451e80bsalomon@google.com#if SK_SUPPORT_GPU
800705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com// Functions that add a shape to the clip stack. The shape is computed from a rectangle.
801705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com// AA is always disabled since the clip stack reducer can cause changes in aa rasterization of the
802705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com// stack. A fractional edge repeated in different elements may be rasterized fewer times using the
803705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com// reduced stack.
804705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.comtypedef void (*AddElementFunc) (const SkRect& rect,
805705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com                                bool invert,
806705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com                                SkRegion::Op op,
807705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com                                SkClipStack* stack);
808705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com
809705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.comstatic void add_round_rect(const SkRect& rect, bool invert, SkRegion::Op op, SkClipStack* stack) {
81051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkScalar rx = rect.width() / 10;
811705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    SkScalar ry = rect.height() / 20;
812705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    if (invert) {
813e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        SkPath path;
814e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        path.addRoundRect(rect, rx, ry);
815705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        path.setFillType(SkPath::kInverseWinding_FillType);
816e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        stack->clipDevPath(path, op, false);
817e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    } else {
818e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        SkRRect rrect;
819e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        rrect.setRectXY(rect, rx, ry);
820e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        stack->clipDevRRect(rrect, op, false);
821705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    }
82251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com};
82351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
824705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.comstatic void add_rect(const SkRect& rect, bool invert, SkRegion::Op op, SkClipStack* stack) {
825705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    if (invert) {
826705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        SkPath path;
827705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        path.addRect(rect);
828705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        path.setFillType(SkPath::kInverseWinding_FillType);
829705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        stack->clipDevPath(path, op, false);
830705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    } else {
831705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        stack->clipDevRect(rect, op, false);
832705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    }
83351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com};
83451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
835705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.comstatic void add_oval(const SkRect& rect, bool invert, SkRegion::Op op, SkClipStack* stack) {
83651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkPath path;
83751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    path.addOval(rect);
838705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    if (invert) {
839705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com        path.setFillType(SkPath::kInverseWinding_FillType);
840705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    }
841705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    stack->clipDevPath(path, op, false);
84251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com};
84351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
8448182fa0cac76e7e6d583aebba060229230516887bsalomon@google.comstatic void add_elem_to_stack(const SkClipStack::Element& element, SkClipStack* stack) {
8458182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    switch (element.getType()) {
8468182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        case SkClipStack::Element::kRect_Type:
8478182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            stack->clipDevRect(element.getRect(), element.getOp(), element.isAA());
8488182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            break;
849e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        case SkClipStack::Element::kRRect_Type:
850e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            stack->clipDevRRect(element.getRRect(), element.getOp(), element.isAA());
851e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            break;
8528182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        case SkClipStack::Element::kPath_Type:
8538182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            stack->clipDevPath(element.getPath(), element.getOp(), element.isAA());
8548182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            break;
8558182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        case SkClipStack::Element::kEmpty_Type:
8568182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            SkDEBUGFAIL("Why did the reducer produce an explicit empty.");
8578182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            stack->clipEmpty();
8588182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            break;
85951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    }
86051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com}
86151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
8628182fa0cac76e7e6d583aebba060229230516887bsalomon@google.comstatic void add_elem_to_region(const SkClipStack::Element& element,
86351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                               const SkIRect& bounds,
86451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                               SkRegion* region) {
86551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkRegion elemRegion;
86651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkRegion boundsRgn(bounds);
867e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    SkPath path;
86851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
8698182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    switch (element.getType()) {
870e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        case SkClipStack::Element::kEmpty_Type:
871e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            elemRegion.setEmpty();
8728182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            break;
873e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        default:
874e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            element.asPath(&path);
875e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            elemRegion.setPath(path, boundsRgn);
8768182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            break;
87751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    }
8788182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    region->op(elemRegion, element.getOp());
87951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com}
88051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
88151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.comstatic void test_reduced_clip_stack(skiatest::Reporter* reporter) {
88251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // We construct random clip stacks, reduce them, and then rasterize both versions to verify that
8838ccf590b89cec1a5974b6f4b7b49ca67cc5036cfskia.committer@gmail.com    // they are equal.
88451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
88551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // All the clip elements will be contained within these bounds.
88651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const SkRect kBounds = SkRect::MakeWH(100, 100);
88751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
88851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    enum {
88951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        kNumTests = 200,
89051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        kMinElemsPerTest = 1,
89151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        kMaxElemsPerTest = 50,
89251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    };
89351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
89451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // min/max size of a clip element as a fraction of kBounds.
89551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const SkScalar kMinElemSizeFrac = SK_Scalar1 / 5;
89651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const SkScalar kMaxElemSizeFrac = SK_Scalar1;
89751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
89851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const SkRegion::Op kOps[] = {
89951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kDifference_Op,
90051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kIntersect_Op,
90151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kUnion_Op,
90251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kXOR_Op,
90351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kReverseDifference_Op,
90451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kReplace_Op,
90551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    };
90651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
90751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // Replace operations short-circuit the optimizer. We want to make sure that we test this code
90851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // path a little bit but we don't want it to prevent us from testing many longer traversals in
90951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // the optimizer.
91051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const int kReplaceDiv = 4 * kMaxElemsPerTest;
91151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
912705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    // We want to test inverse fills. However, they are quite rare in practice so don't over do it.
913705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com    static const SkScalar kFractionInverted = SK_Scalar1 / kMaxElemsPerTest;
914705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com
91551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const AddElementFunc kElementFuncs[] = {
91651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        add_rect,
91751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        add_round_rect,
91851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        add_oval,
91951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    };
92051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
921e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.org    SkRandom r;
92251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
92351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    for (int i = 0; i < kNumTests; ++i) {
92451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        // Randomly generate a clip stack.
92551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkClipStack stack;
92651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        int numElems = r.nextRangeU(kMinElemsPerTest, kMaxElemsPerTest);
92751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        for (int e = 0; e < numElems; ++e) {
92851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            SkRegion::Op op = kOps[r.nextULessThan(SK_ARRAY_COUNT(kOps))];
92951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            if (op == SkRegion::kReplace_Op) {
93051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                if (r.nextU() % kReplaceDiv) {
93151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                    --e;
93251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                    continue;
93351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                }
93451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            }
9358ccf590b89cec1a5974b6f4b7b49ca67cc5036cfskia.committer@gmail.com
93651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            // saves can change the clip stack behavior when an element is added.
93751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            bool doSave = r.nextBool();
9388ccf590b89cec1a5974b6f4b7b49ca67cc5036cfskia.committer@gmail.com
93951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            SkSize size = SkSize::Make(
94051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                SkScalarFloorToScalar(SkScalarMul(kBounds.width(), r.nextRangeScalar(kMinElemSizeFrac, kMaxElemSizeFrac))),
94151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                SkScalarFloorToScalar(SkScalarMul(kBounds.height(), r.nextRangeScalar(kMinElemSizeFrac, kMaxElemSizeFrac))));
94251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
94351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            SkPoint xy = {SkScalarFloorToScalar(r.nextRangeScalar(kBounds.fLeft, kBounds.fRight - size.fWidth)),
94451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                          SkScalarFloorToScalar(r.nextRangeScalar(kBounds.fTop, kBounds.fBottom - size.fHeight))};
94551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
94651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            SkRect rect = SkRect::MakeXYWH(xy.fX, xy.fY, size.fWidth, size.fHeight);
94751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
948705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com            bool invert = r.nextBiasedBool(kFractionInverted);
949e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org
950705e84094494613a4659fcabe29f76eb003f9809bsalomon@google.com            kElementFuncs[r.nextULessThan(SK_ARRAY_COUNT(kElementFuncs))](rect, invert, op, &stack);
95151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            if (doSave) {
95251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                stack.save();
95351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            }
95451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
95551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
956a444430281ea35cb76fb42516978b4a93221c2c7bsalomon@google.com        SkRect inflatedBounds = kBounds;
957a444430281ea35cb76fb42516978b4a93221c2c7bsalomon@google.com        inflatedBounds.outset(kBounds.width() / 2, kBounds.height() / 2);
958a444430281ea35cb76fb42516978b4a93221c2c7bsalomon@google.com        SkIRect inflatedIBounds;
959a444430281ea35cb76fb42516978b4a93221c2c7bsalomon@google.com        inflatedBounds.roundOut(&inflatedIBounds);
960a444430281ea35cb76fb42516978b4a93221c2c7bsalomon@google.com
9618182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        typedef GrReducedClip::ElementList ElementList;
96251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        // Get the reduced version of the stack.
9638182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        ElementList reducedClips;
964d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        int32_t reducedGenID;
96551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        GrReducedClip::InitialState initial;
966c490f801b063a0837501feab3d12b73d71f46312jvanverth@google.com        SkIRect tBounds(inflatedIBounds);
9672880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        SkIRect* tightBounds = r.nextBool() ? &tBounds : nullptr;
96834cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com        GrReducedClip::ReduceClipStack(stack,
96934cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com                                       inflatedIBounds,
97034cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com                                       &reducedClips,
971d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org                                       &reducedGenID,
97234cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com                                       &initial,
97334cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com                                       tightBounds);
97451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
975d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        REPORTER_ASSERT(reporter, SkClipStack::kInvalidGenID != reducedGenID);
976d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
97751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        // Build a new clip stack based on the reduced clip elements
97851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkClipStack reducedStack;
97951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        if (GrReducedClip::kAllOut_InitialState == initial) {
98051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            // whether the result is bounded or not, the whole plane should start outside the clip.
98151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            reducedStack.clipEmpty();
98251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
98349f085dddff10473b6ebf832a974288300224e60bsalomon        for (ElementList::Iter iter = reducedClips.headIter(); iter.get(); iter.next()) {
9848182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            add_elem_to_stack(*iter.get(), &reducedStack);
98551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
98651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
98734cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com        // GrReducedClipStack assumes that the final result is clipped to the returned bounds
98849f085dddff10473b6ebf832a974288300224e60bsalomon        if (tightBounds) {
98934cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com            reducedStack.clipDevRect(*tightBounds, SkRegion::kIntersect_Op);
99034cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com        }
99134cd70a5810b3cf37b44de1ce080a911a8b342c8bsalomon@google.com
99251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        // convert both the original stack and reduced stack to SkRegions and see if they're equal
99351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion region;
99451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion reducedRegion;
99551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
99651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        region.setRect(inflatedIBounds);
9978182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        const SkClipStack::Element* element;
99851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
9998182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        while ((element = iter.next())) {
10008182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            add_elem_to_region(*element, inflatedIBounds, &region);
100151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
100251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
100351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        reducedRegion.setRect(inflatedIBounds);
100451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        iter.reset(reducedStack, SkClipStack::Iter::kBottom_IterStart);
10058182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com        while ((element = iter.next())) {
10068182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com            add_elem_to_region(*element, inflatedIBounds, &reducedRegion);
100751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
1008e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        SkString testCase;
1009e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        testCase.printf("Iteration %d", i);
1010e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        REPORTER_ASSERT_MESSAGE(reporter, region == reducedRegion, testCase.c_str());
101151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    }
101251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com}
101351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
1014d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org#if defined(WIN32)
1015d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    #define SUPPRESS_VISIBILITY_WARNING
1016d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org#else
1017d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    #define SUPPRESS_VISIBILITY_WARNING __attribute__((visibility("hidden")))
1018d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org#endif
1019d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1020d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.orgstatic void test_reduced_clip_stack_genid(skiatest::Reporter* reporter) {
1021d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    {
1022d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        SkClipStack stack;
1023d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        stack.clipDevRect(SkRect::MakeXYWH(0, 0, 100, 100), SkRegion::kReplace_Op, true);
1024d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        stack.clipDevRect(SkRect::MakeXYWH(0, 0, SkScalar(50.3), SkScalar(50.3)), SkRegion::kReplace_Op, true);
1025d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        SkIRect inflatedIBounds = SkIRect::MakeXYWH(0, 0, 100, 100);
1026d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1027d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        GrReducedClip::ElementList reducedClips;
1028d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        int32_t reducedGenID;
1029d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        GrReducedClip::InitialState initial;
1030d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        SkIRect tightBounds;
1031d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1032d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        GrReducedClip::ReduceClipStack(stack,
1033d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org                                       inflatedIBounds,
1034d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org                                       &reducedClips,
1035d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org                                       &reducedGenID,
1036d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org                                       &initial,
1037d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org                                       &tightBounds);
1038d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1039d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        REPORTER_ASSERT(reporter, reducedClips.count() == 1);
1040d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        // Clips will be cached based on the generation id. Make sure the gen id is valid.
1041d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        REPORTER_ASSERT(reporter, SkClipStack::kInvalidGenID != reducedGenID);
1042d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    }
1043d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    {
1044d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        SkClipStack stack;
1045d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1046d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        // Create a clip with following 25.3, 25.3 boxes which are 25 apart:
1047d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        //  A  B
1048d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        //  C  D
1049d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1050d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        stack.clipDevRect(SkRect::MakeXYWH(0, 0, SkScalar(25.3), SkScalar(25.3)), SkRegion::kReplace_Op, true);
1051d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        int32_t genIDA = stack.getTopmostGenID();
1052d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        stack.clipDevRect(SkRect::MakeXYWH(50, 0, SkScalar(25.3), SkScalar(25.3)), SkRegion::kUnion_Op, true);
1053d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        int32_t genIDB = stack.getTopmostGenID();
1054d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        stack.clipDevRect(SkRect::MakeXYWH(0, 50, SkScalar(25.3), SkScalar(25.3)), SkRegion::kUnion_Op, true);
1055d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        int32_t genIDC = stack.getTopmostGenID();
1056d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        stack.clipDevRect(SkRect::MakeXYWH(50, 50, SkScalar(25.3), SkScalar(25.3)), SkRegion::kUnion_Op, true);
1057d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        int32_t genIDD = stack.getTopmostGenID();
1058d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1059d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1060d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org#define XYWH SkIRect::MakeXYWH
1061d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1062d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        SkIRect unused;
1063d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        unused.setEmpty();
1064d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        SkIRect stackBounds = XYWH(0, 0, 76, 76);
1065d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1066d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        // The base test is to test each rect in two ways:
1067d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        // 1) The box dimensions. (Should reduce to "all in", no elements).
1068d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        // 2) A bit over the box dimensions.
1069d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        // In the case 2, test that the generation id is what is expected.
1070d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        // The rects are of fractional size so that case 2 never gets optimized to an empty element
1071d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        // list.
1072d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1073d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        // Not passing in tighter bounds is tested for consistency.
1074d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        static const struct SUPPRESS_VISIBILITY_WARNING {
1075d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            SkIRect testBounds;
1076d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            int reducedClipCount;
1077d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            int32_t reducedGenID;
1078d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            GrReducedClip::InitialState initialState;
1079d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            SkIRect tighterBounds; // If this is empty, the query will not pass tighter bounds
1080d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            // parameter.
1081d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        } testCases[] = {
1082d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            // Rect A.
1083d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(0, 0, 25, 25), 0, SkClipStack::kWideOpenGenID, GrReducedClip::kAllIn_InitialState, XYWH(0, 0, 25, 25) },
1084d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(0, 0, 25, 25), 0, SkClipStack::kWideOpenGenID, GrReducedClip::kAllIn_InitialState, unused },
1085d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(0, 0, 27, 27), 1, genIDA, GrReducedClip::kAllOut_InitialState, XYWH(0, 0, 27, 27)},
1086d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(0, 0, 27, 27), 1, genIDA, GrReducedClip::kAllOut_InitialState, unused },
1087d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1088d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            // Rect B.
1089d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(50, 0, 25, 25), 0, SkClipStack::kWideOpenGenID, GrReducedClip::kAllIn_InitialState, XYWH(50, 0, 25, 25) },
1090d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(50, 0, 25, 25), 0, SkClipStack::kWideOpenGenID, GrReducedClip::kAllIn_InitialState, unused },
1091d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(50, 0, 27, 27), 1, genIDB, GrReducedClip::kAllOut_InitialState, XYWH(50, 0, 26, 27) },
1092d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(50, 0, 27, 27), 1, genIDB, GrReducedClip::kAllOut_InitialState, unused },
1093d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1094d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            // Rect C.
1095d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(0, 50, 25, 25), 0, SkClipStack::kWideOpenGenID, GrReducedClip::kAllIn_InitialState, XYWH(0, 50, 25, 25) },
1096d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(0, 50, 25, 25), 0, SkClipStack::kWideOpenGenID, GrReducedClip::kAllIn_InitialState, unused },
1097d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(0, 50, 27, 27), 1, genIDC, GrReducedClip::kAllOut_InitialState, XYWH(0, 50, 27, 26) },
1098d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(0, 50, 27, 27), 1, genIDC, GrReducedClip::kAllOut_InitialState, unused },
1099d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1100d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            // Rect D.
1101d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(50, 50, 25, 25), 0, SkClipStack::kWideOpenGenID, GrReducedClip::kAllIn_InitialState, unused },
1102d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(50, 50, 25, 25), 0, SkClipStack::kWideOpenGenID, GrReducedClip::kAllIn_InitialState, XYWH(50, 50, 25, 25)},
1103d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(50, 50, 27, 27), 1, genIDD, GrReducedClip::kAllOut_InitialState, unused },
1104d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(50, 50, 27, 27), 1, genIDD, GrReducedClip::kAllOut_InitialState,  XYWH(50, 50, 26, 26)},
1105d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1106d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            // Other tests:
1107d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(0, 0, 100, 100), 4, genIDD, GrReducedClip::kAllOut_InitialState, unused },
1108d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(0, 0, 100, 100), 4, genIDD, GrReducedClip::kAllOut_InitialState, stackBounds },
1109d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1110d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            // Rect in the middle, touches none.
1111d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(26, 26, 24, 24), 0, SkClipStack::kEmptyGenID, GrReducedClip::kAllOut_InitialState, unused },
1112d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(26, 26, 24, 24), 0, SkClipStack::kEmptyGenID, GrReducedClip::kAllOut_InitialState, XYWH(26, 26, 24, 24) },
1113d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1114d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            // Rect in the middle, touches all the rects. GenID is the last rect.
1115d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(24, 24, 27, 27), 4, genIDD, GrReducedClip::kAllOut_InitialState, unused },
1116d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            { XYWH(24, 24, 27, 27), 4, genIDD, GrReducedClip::kAllOut_InitialState, XYWH(24, 24, 27, 27) },
1117d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        };
1118d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1119d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org#undef XYWH
1120d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1121d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        for (size_t i = 0; i < SK_ARRAY_COUNT(testCases); ++i) {
1122d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            GrReducedClip::ElementList reducedClips;
1123d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            int32_t reducedGenID;
1124d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            GrReducedClip::InitialState initial;
1125d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            SkIRect tightBounds;
1126d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1127d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            GrReducedClip::ReduceClipStack(stack,
1128d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org                                           testCases[i].testBounds,
1129d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org                                           &reducedClips,
1130d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org                                           &reducedGenID,
1131d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org                                           &initial,
11322880df2609eba09b555ca37be04b6ad89290c765Tom Hudson                                           testCases[i].tighterBounds.isEmpty() ? nullptr : &tightBounds);
1133d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1134d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            REPORTER_ASSERT(reporter, reducedClips.count() == testCases[i].reducedClipCount);
1135d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            SkASSERT(reducedClips.count() == testCases[i].reducedClipCount);
1136d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            REPORTER_ASSERT(reporter, reducedGenID == testCases[i].reducedGenID);
1137d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            SkASSERT(reducedGenID == testCases[i].reducedGenID);
1138d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            REPORTER_ASSERT(reporter, initial == testCases[i].initialState);
1139d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            SkASSERT(initial == testCases[i].initialState);
1140d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            if (!testCases[i].tighterBounds.isEmpty()) {
1141d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org                REPORTER_ASSERT(reporter, tightBounds == testCases[i].tighterBounds);
1142d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org                SkASSERT(tightBounds == testCases[i].tighterBounds);
1143d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org            }
1144d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        }
1145d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    }
1146d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org}
1147d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1148d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.orgstatic void test_reduced_clip_stack_no_aa_crash(skiatest::Reporter* reporter) {
1149d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    SkClipStack stack;
1150d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 100, 100), SkRegion::kReplace_Op);
1151d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    stack.clipDevRect(SkIRect::MakeXYWH(0, 0, 50, 50), SkRegion::kReplace_Op);
1152d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    SkIRect inflatedIBounds = SkIRect::MakeXYWH(0, 0, 100, 100);
1153d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1154d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    GrReducedClip::ElementList reducedClips;
1155d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    int32_t reducedGenID;
1156d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    GrReducedClip::InitialState initial;
1157d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    SkIRect tightBounds;
1158d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1159d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    // At the time, this would crash.
1160d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    GrReducedClip::ReduceClipStack(stack,
1161d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org                                   inflatedIBounds,
1162d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org                                   &reducedClips,
1163d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org                                   &reducedGenID,
1164d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org                                   &initial,
1165d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org                                   &tightBounds);
1166d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1167d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    REPORTER_ASSERT(reporter, 0 == reducedClips.count());
1168d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org}
1169d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
1170a4e13c85b23fe7530ae89a84ef671ebd5e451e80bsalomon@google.com#endif
117151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
1172e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.orgDEF_TEST(ClipStack, reporter) {
1173bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    SkClipStack stack;
1174bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
117580214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 0 == stack.getSaveCount());
1176bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    assert_count(reporter, stack, 0);
1177bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
1178bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    static const SkIRect gRects[] = {
1179bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        { 0, 0, 100, 100 },
1180bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        { 25, 25, 125, 125 },
1181bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        { 0, 0, 1000, 1000 },
1182bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        { 0, 0, 75, 75 }
1183bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    };
1184bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gRects); i++) {
1185d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com        stack.clipDevRect(gRects[i], SkRegion::kIntersect_Op);
1186bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    }
1187bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
1188bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    // all of the above rects should have been intersected, leaving only 1 rect
118980214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter iter(stack);
11908182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    const SkClipStack::Element* element = iter.next();
11912047f00e4698f83499ab91911999a65c21a951c9epoger@google.com    SkRect answer;
11922047f00e4698f83499ab91911999a65c21a951c9epoger@google.com    answer.iset(25, 25, 75, 75);
1193bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
119449f085dddff10473b6ebf832a974288300224e60bsalomon    REPORTER_ASSERT(reporter, element);
11958182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    REPORTER_ASSERT(reporter, SkClipStack::Element::kRect_Type == element->getType());
11968182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    REPORTER_ASSERT(reporter, SkRegion::kIntersect_Op == element->getOp());
11978182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    REPORTER_ASSERT(reporter, element->getRect() == answer);
1198bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    // now check that we only had one in our iterator
1199bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    REPORTER_ASSERT(reporter, !iter.next());
1200bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
1201bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    stack.reset();
120280214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 0 == stack.getSaveCount());
1203bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    assert_count(reporter, stack, 0);
12041e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
12051e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    test_assign_and_comparison(reporter);
120680214e26c57c5fea954006400852e8999e201923robertphillips@google.com    test_iterators(reporter);
1207e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    test_bounds(reporter, SkClipStack::Element::kRect_Type);
1208e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    test_bounds(reporter, SkClipStack::Element::kRRect_Type);
1209e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    test_bounds(reporter, SkClipStack::Element::kPath_Type);
1210cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    test_isWideOpen(reporter);
121108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    test_rect_merging(reporter);
12126fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    test_rect_replace(reporter);
1213edf32d5b0e7694833287024e03da38521a0adf05junov@chromium.org    test_rect_inverse_fill(reporter);
12146fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    test_path_replace(reporter);
12158cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    test_quickContains(reporter);
1216e7b3d29a1289e64130dd0ec905d94feedc9d1064bsalomon@google.com#if SK_SUPPORT_GPU
1217edb26fdb8349a727b226e90cbeab06cd25f5cac0bsalomon@google.com    test_reduced_clip_stack(reporter);
1218d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    test_reduced_clip_stack_genid(reporter);
1219d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    test_reduced_clip_stack_no_aa_crash(reporter);
1220e7b3d29a1289e64130dd0ec905d94feedc9d1064bsalomon@google.com#endif
1221bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com}
1222