ClipStackTest.cpp revision 8ccf590b89cec1a5974b6f4b7b49ca67cc5036cf
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com#include "Test.h"
9a4e13c85b23fe7530ae89a84ef671ebd5e451e80bsalomon@google.com#if SK_SUPPORT_GPU
10a4e13c85b23fe7530ae89a84ef671ebd5e451e80bsalomon@google.com    #include "GrClipMaskManager.h"
11a4e13c85b23fe7530ae89a84ef671ebd5e451e80bsalomon@google.com#endif
12bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com#include "SkClipStack.h"
131e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org#include "SkPath.h"
1451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com#include "SkRandom.h"
151e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org#include "SkRect.h"
1651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com#include "SkRegion.h"
1780214e26c57c5fea954006400852e8999e201923robertphillips@google.com
1880214e26c57c5fea954006400852e8999e201923robertphillips@google.com
191e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.orgstatic void test_assign_and_comparison(skiatest::Reporter* reporter) {
201e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkClipStack s;
21d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    bool doAA = false;
221e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
2380214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 0 == s.getSaveCount());
2480214e26c57c5fea954006400852e8999e201923robertphillips@google.com
251e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Build up a clip stack with a path, an empty clip, and a rect.
261e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
2780214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 1 == s.getSaveCount());
2880214e26c57c5fea954006400852e8999e201923robertphillips@google.com
291e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkPath p;
301e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    p.moveTo(5, 6);
311e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    p.lineTo(7, 8);
321e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    p.lineTo(5, 9);
331e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    p.close();
34d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevPath(p, SkRegion::kIntersect_Op, doAA);
351e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
361e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
3780214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == s.getSaveCount());
3880214e26c57c5fea954006400852e8999e201923robertphillips@google.com
391e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkRect r = SkRect::MakeLTRB(1, 2, 3, 4);
40d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kIntersect_Op, doAA);
411e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    r = SkRect::MakeLTRB(10, 11, 12, 13);
42d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kIntersect_Op, doAA);
431e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
441e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
4580214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 3 == s.getSaveCount());
4680214e26c57c5fea954006400852e8999e201923robertphillips@google.com
471e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    r = SkRect::MakeLTRB(14, 15, 16, 17);
48d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kUnion_Op, doAA);
491e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
501e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that assignment works.
511e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkClipStack copy = s;
521e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s == copy);
531e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
541e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that different save levels triggers not equal.
551e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
5680214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == s.getSaveCount());
571e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s != copy);
581e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
591e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that an equal, but not copied version is equal.
601e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
6180214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 3 == s.getSaveCount());
6280214e26c57c5fea954006400852e8999e201923robertphillips@google.com
631e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    r = SkRect::MakeLTRB(14, 15, 16, 17);
64d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kUnion_Op, doAA);
651e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s == copy);
661e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
671e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that a different op on one level triggers not equal.
681e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
6980214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == s.getSaveCount());
701e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
7180214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 3 == s.getSaveCount());
7280214e26c57c5fea954006400852e8999e201923robertphillips@google.com
731e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    r = SkRect::MakeLTRB(14, 15, 16, 17);
74d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kIntersect_Op, doAA);
751e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s != copy);
761e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
771e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that different state (clip type) triggers not equal.
784c4337291d873c4f27cb7903645863dc65b98a7btomhudson@google.com    // NO LONGER VALID: if a path contains only a rect, we turn
794c4337291d873c4f27cb7903645863dc65b98a7btomhudson@google.com    // it into a bare rect for performance reasons (working
804c4337291d873c4f27cb7903645863dc65b98a7btomhudson@google.com    // around Chromium/JavaScript bad pattern).
814c4337291d873c4f27cb7903645863dc65b98a7btomhudson@google.com/*
821e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
831e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
841e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkPath rp;
851e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    rp.addRect(r);
86d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevPath(rp, SkRegion::kUnion_Op, doAA);
871e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s != copy);
884c4337291d873c4f27cb7903645863dc65b98a7btomhudson@google.com*/
891e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
901e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that different rects triggers not equal.
911e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
9280214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == s.getSaveCount());
931e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
9480214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 3 == s.getSaveCount());
9580214e26c57c5fea954006400852e8999e201923robertphillips@google.com
961e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    r = SkRect::MakeLTRB(24, 25, 26, 27);
97d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevRect(r, SkRegion::kUnion_Op, doAA);
981e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s != copy);
991e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
1001e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Sanity check
1011e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
10280214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == s.getSaveCount());
10380214e26c57c5fea954006400852e8999e201923robertphillips@google.com
1041e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    copy.restore();
10580214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 2 == copy.getSaveCount());
1061e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s == copy);
1071e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
10880214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 1 == s.getSaveCount());
1091e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    copy.restore();
11080214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 1 == copy.getSaveCount());
1111e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s == copy);
1121e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
1131e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    // Test that different paths triggers not equal.
1141e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.restore();
11580214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 0 == s.getSaveCount());
1161e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    s.save();
11780214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 1 == s.getSaveCount());
11880214e26c57c5fea954006400852e8999e201923robertphillips@google.com
1191e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    p.addRect(r);
120d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com    s.clipDevPath(p, SkRegion::kIntersect_Op, doAA);
1211e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    REPORTER_ASSERT(reporter, s != copy);
1221e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org}
123bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
124bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.comstatic void assert_count(skiatest::Reporter* reporter, const SkClipStack& stack,
125bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com                         int count) {
12680214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter iter(stack);
127bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    int counter = 0;
128bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    while (iter.next()) {
129bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        counter += 1;
130bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    }
131bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    REPORTER_ASSERT(reporter, count == counter);
132bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com}
133bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
13408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com// Exercise the SkClipStack's bottom to top and bidirectional iterators
13508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com// (including the skipToTopmost functionality)
13680214e26c57c5fea954006400852e8999e201923robertphillips@google.comstatic void test_iterators(skiatest::Reporter* reporter) {
13780214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack stack;
13880214e26c57c5fea954006400852e8999e201923robertphillips@google.com
13980214e26c57c5fea954006400852e8999e201923robertphillips@google.com    static const SkRect gRects[] = {
14080214e26c57c5fea954006400852e8999e201923robertphillips@google.com        { 0,   0,  40,  40 },
14180214e26c57c5fea954006400852e8999e201923robertphillips@google.com        { 60,  0, 100,  40 },
14280214e26c57c5fea954006400852e8999e201923robertphillips@google.com        { 0,  60,  40, 100 },
14380214e26c57c5fea954006400852e8999e201923robertphillips@google.com        { 60, 60, 100, 100 }
14480214e26c57c5fea954006400852e8999e201923robertphillips@google.com    };
14580214e26c57c5fea954006400852e8999e201923robertphillips@google.com
14680214e26c57c5fea954006400852e8999e201923robertphillips@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gRects); i++) {
14780214e26c57c5fea954006400852e8999e201923robertphillips@google.com        // the union op will prevent these from being fused together
14880214e26c57c5fea954006400852e8999e201923robertphillips@google.com        stack.clipDevRect(gRects[i], SkRegion::kUnion_Op, false);
14980214e26c57c5fea954006400852e8999e201923robertphillips@google.com    }
15080214e26c57c5fea954006400852e8999e201923robertphillips@google.com
15180214e26c57c5fea954006400852e8999e201923robertphillips@google.com    assert_count(reporter, stack, 4);
15280214e26c57c5fea954006400852e8999e201923robertphillips@google.com
15380214e26c57c5fea954006400852e8999e201923robertphillips@google.com    // bottom to top iteration
15480214e26c57c5fea954006400852e8999e201923robertphillips@google.com    {
15580214e26c57c5fea954006400852e8999e201923robertphillips@google.com        const SkClipStack::B2TIter::Clip* clip = NULL;
15680214e26c57c5fea954006400852e8999e201923robertphillips@google.com
15780214e26c57c5fea954006400852e8999e201923robertphillips@google.com        SkClipStack::B2TIter iter(stack);
15880214e26c57c5fea954006400852e8999e201923robertphillips@google.com        int i;
15980214e26c57c5fea954006400852e8999e201923robertphillips@google.com
16080214e26c57c5fea954006400852e8999e201923robertphillips@google.com        for (i = 0, clip = iter.next(); clip; ++i, clip = iter.next()) {
16180214e26c57c5fea954006400852e8999e201923robertphillips@google.com            REPORTER_ASSERT(reporter, *clip->fRect == gRects[i]);
16280214e26c57c5fea954006400852e8999e201923robertphillips@google.com        }
16380214e26c57c5fea954006400852e8999e201923robertphillips@google.com
16480214e26c57c5fea954006400852e8999e201923robertphillips@google.com        SkASSERT(i == 4);
16580214e26c57c5fea954006400852e8999e201923robertphillips@google.com    }
16680214e26c57c5fea954006400852e8999e201923robertphillips@google.com
16780214e26c57c5fea954006400852e8999e201923robertphillips@google.com    // top to bottom iteration
16880214e26c57c5fea954006400852e8999e201923robertphillips@google.com    {
16980214e26c57c5fea954006400852e8999e201923robertphillips@google.com        const SkClipStack::Iter::Clip* clip = NULL;
17080214e26c57c5fea954006400852e8999e201923robertphillips@google.com
17180214e26c57c5fea954006400852e8999e201923robertphillips@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
17280214e26c57c5fea954006400852e8999e201923robertphillips@google.com        int i;
17380214e26c57c5fea954006400852e8999e201923robertphillips@google.com
17480214e26c57c5fea954006400852e8999e201923robertphillips@google.com        for (i = 3, clip = iter.prev(); clip; --i, clip = iter.prev()) {
17580214e26c57c5fea954006400852e8999e201923robertphillips@google.com            REPORTER_ASSERT(reporter, *clip->fRect == gRects[i]);
17680214e26c57c5fea954006400852e8999e201923robertphillips@google.com        }
17780214e26c57c5fea954006400852e8999e201923robertphillips@google.com
17880214e26c57c5fea954006400852e8999e201923robertphillips@google.com        SkASSERT(i == -1);
17980214e26c57c5fea954006400852e8999e201923robertphillips@google.com    }
18080214e26c57c5fea954006400852e8999e201923robertphillips@google.com
18180214e26c57c5fea954006400852e8999e201923robertphillips@google.com    // skipToTopmost
18280214e26c57c5fea954006400852e8999e201923robertphillips@google.com    {
18380214e26c57c5fea954006400852e8999e201923robertphillips@google.com        const SkClipStack::Iter::Clip*clip = NULL;
18480214e26c57c5fea954006400852e8999e201923robertphillips@google.com
18580214e26c57c5fea954006400852e8999e201923robertphillips@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
18680214e26c57c5fea954006400852e8999e201923robertphillips@google.com
18780214e26c57c5fea954006400852e8999e201923robertphillips@google.com        clip = iter.skipToTopmost(SkRegion::kUnion_Op);
18880214e26c57c5fea954006400852e8999e201923robertphillips@google.com        REPORTER_ASSERT(reporter, *clip->fRect == gRects[3]);
18980214e26c57c5fea954006400852e8999e201923robertphillips@google.com    }
19080214e26c57c5fea954006400852e8999e201923robertphillips@google.com}
19180214e26c57c5fea954006400852e8999e201923robertphillips@google.com
19208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com// Exercise the SkClipStack's getConservativeBounds computation
1934c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.comstatic void test_bounds(skiatest::Reporter* reporter, bool useRects) {
194607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
195607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    static const int gNumCases = 20;
196607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    static const SkRect gAnswerRectsBW[gNumCases] = {
197607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        // A op B
198607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 50, 50 },
199607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 50, 50 },
200607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 80, 80 },
201607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 80, 80 },
202607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 80, 80 },
203607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
204607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        // invA op B
205607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 80, 80 },
206607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
207607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
208607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
209607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 50, 50 },
210607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
211607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        // A op invB
212607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 50, 50 },
213607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 50, 50 },
214607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
215607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
216607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
217607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
218607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        // invA op invB
219607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
220607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 40, 40, 80, 80 },
221607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 0, 0, 100, 100 },
222607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 80, 80 },
223607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        { 10, 10, 50, 50 },
224607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    };
225607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
226607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    static const SkRegion::Op gOps[] = {
227607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        SkRegion::kIntersect_Op,
228607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        SkRegion::kDifference_Op,
229607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        SkRegion::kUnion_Op,
230607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        SkRegion::kXOR_Op,
231607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        SkRegion::kReverseDifference_Op
232607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    };
233607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
234607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    SkRect rectA, rectB;
235607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
236607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    rectA.iset(10, 10, 50, 50);
237607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    rectB.iset(40, 40, 80, 80);
238607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
239607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    SkPath clipA, clipB;
240607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
241607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    clipA.addRoundRect(rectA, SkIntToScalar(5), SkIntToScalar(5));
242607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    clipB.addRoundRect(rectB, SkIntToScalar(5), SkIntToScalar(5));
243607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
244607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    SkClipStack stack;
2457b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    SkRect devClipBound;
2464c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com    bool isIntersectionOfRects = false;
247607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
248607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    int testCase = 0;
2494c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com    int numBitTests = useRects ? 1 : 4;
2504c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com    for (int invBits = 0; invBits < numBitTests; ++invBits) {
251607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) {
252607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
253607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            stack.save();
254607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            bool doInvA = SkToBool(invBits & 1);
255607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            bool doInvB = SkToBool(invBits & 2);
256607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
257607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            clipA.setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType :
258607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com                                       SkPath::kEvenOdd_FillType);
259607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            clipB.setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType :
260607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com                                       SkPath::kEvenOdd_FillType);
261607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
2624c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com            if (useRects) {
2634c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                stack.clipDevRect(rectA, SkRegion::kIntersect_Op, false);
2644c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                stack.clipDevRect(rectB, gOps[op], false);
2654c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com            } else {
2664c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                stack.clipDevPath(clipA, SkRegion::kIntersect_Op, false);
2674c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                stack.clipDevPath(clipB, gOps[op], false);
2684c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com            }
269607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
270cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com            REPORTER_ASSERT(reporter, !stack.isWideOpen());
271cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
2727b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com            stack.getConservativeBounds(0, 0, 100, 100, &devClipBound,
2734c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                                        &isIntersectionOfRects);
2744c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com
2754c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com            if (useRects) {
276d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com                REPORTER_ASSERT(reporter, isIntersectionOfRects ==
2774c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                        (gOps[op] == SkRegion::kIntersect_Op));
2784c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com            } else {
2794c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                REPORTER_ASSERT(reporter, !isIntersectionOfRects);
2804c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com            }
281607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
282607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            SkASSERT(testCase < gNumCases);
2837b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com            REPORTER_ASSERT(reporter, devClipBound == gAnswerRectsBW[testCase]);
284607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            ++testCase;
285607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
286607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com            stack.restore();
287607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        }
288607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    }
289607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com}
290607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
291cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com// Test out 'isWideOpen' entry point
292cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.comstatic void test_isWideOpen(skiatest::Reporter* reporter) {
293cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
294cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    SkRect rectA, rectB;
295cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
296cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    rectA.iset(10, 10, 40, 40);
297cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    rectB.iset(50, 50, 80, 80);
298cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
299cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    // Stack should initially be wide open
300cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    {
301cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkClipStack stack;
302cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
303cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, stack.isWideOpen());
304cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    }
305cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
306cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    // Test out case where the user specifies a union that includes everything
307cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    {
308cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkClipStack stack;
309cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
310cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkPath clipA, clipB;
311cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
312cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        clipA.addRoundRect(rectA, SkIntToScalar(5), SkIntToScalar(5));
313cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        clipA.setFillType(SkPath::kInverseEvenOdd_FillType);
314cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
315cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        clipB.addRoundRect(rectB, SkIntToScalar(5), SkIntToScalar(5));
316cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        clipB.setFillType(SkPath::kInverseEvenOdd_FillType);
317cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
318cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.clipDevPath(clipA, SkRegion::kReplace_Op, false);
319cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.clipDevPath(clipB, SkRegion::kUnion_Op, false);
320cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
321cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, stack.isWideOpen());
322cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    }
323cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
324cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    // Test out union w/ a wide open clip
325cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    {
326cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkClipStack stack;
327cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
328cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.clipDevRect(rectA, SkRegion::kUnion_Op, false);
329cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
330cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, stack.isWideOpen());
331cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    }
332cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
333cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    // Test out empty difference from a wide open clip
334cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    {
335cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkClipStack stack;
336cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
337cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkRect emptyRect;
338cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        emptyRect.setEmpty();
339cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
340cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.clipDevRect(emptyRect, SkRegion::kDifference_Op, false);
341cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
342cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, stack.isWideOpen());
343cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    }
344cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
345cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    // Test out return to wide open
346cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    {
347cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        SkClipStack stack;
348cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
349cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.save();
350cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
351cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.clipDevRect(rectA, SkRegion::kReplace_Op, false);
352cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
353cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, !stack.isWideOpen());
354cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
355cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        stack.restore();
356cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
357cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        REPORTER_ASSERT(reporter, stack.isWideOpen());
358cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    }
359cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com}
360cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
361100abf49e10544bc4f436bf1f38e6929779621f4bsalomon@google.comstatic int count(const SkClipStack& stack) {
36208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
36308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkClipStack::Iter iter(stack, SkClipStack::Iter::kTop_IterStart);
36408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
36508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    const SkClipStack::Iter::Clip* clip = NULL;
36608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    int count = 0;
36708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
36808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    for (clip = iter.prev(); clip; clip = iter.prev(), ++count) {
36908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        ;
37008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
37108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
37208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    return count;
37308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com}
37408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
37508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com// Test out SkClipStack's merging of rect clips. In particular exercise
37608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com// merging of aa vs. bw rects.
37708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.comstatic void test_rect_merging(skiatest::Reporter* reporter) {
37808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
37908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect overlapLeft  = SkRect::MakeLTRB(10, 10, 50, 50);
38008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect overlapRight = SkRect::MakeLTRB(40, 40, 80, 80);
38108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
38208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect nestedParent = SkRect::MakeLTRB(10, 10, 90, 90);
38308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect nestedChild  = SkRect::MakeLTRB(40, 40, 60, 60);
38408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
38508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkRect bound;
38608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    SkClipStack::BoundsType type;
38708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    bool isIntersectionOfRects;
38808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
38908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // all bw overlapping - should merge
39008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
39108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
39208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
39308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapLeft, SkRegion::kReplace_Op, false);
39408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
39508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, false);
39608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
39708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 1 == count(stack));
39808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
39908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
40008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
40108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, isIntersectionOfRects);
40208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
40308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
40408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // all aa overlapping - should merge
40508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
40608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
40708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
40808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapLeft, SkRegion::kReplace_Op, true);
40908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
41008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, true);
41108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
41208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 1 == count(stack));
41308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
41408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
41508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
41608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, isIntersectionOfRects);
41708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
41808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
41908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // mixed overlapping - should _not_ merge
42008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
42108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
42208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
42308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapLeft, SkRegion::kReplace_Op, true);
42408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
42508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, false);
42608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
42708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 2 == count(stack));
42808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
42908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
43008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
43108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, !isIntersectionOfRects);
43208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
43308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
43408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // mixed nested (bw inside aa) - should merge
43508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
43608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
43708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
43808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedParent, SkRegion::kReplace_Op, true);
43908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
44008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedChild, SkRegion::kIntersect_Op, false);
44108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
44208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 1 == count(stack));
44308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
44408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
44508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
44608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, isIntersectionOfRects);
44708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
44808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
44908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // mixed nested (aa inside bw) - should merge
45008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
45108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
45208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
45308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedParent, SkRegion::kReplace_Op, false);
45408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
45508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedChild, SkRegion::kIntersect_Op, true);
45608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
45708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 1 == count(stack));
45808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
45908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
46008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
46108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, isIntersectionOfRects);
46208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
46308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
46408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    // reverse nested (aa inside bw) - should _not_ merge
46508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    {
46608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        SkClipStack stack;
46708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
46808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedChild, SkRegion::kReplace_Op, false);
46908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
47008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.clipDevRect(nestedParent, SkRegion::kIntersect_Op, true);
47108eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
47208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, 2 == count(stack));
47308eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
47408eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        stack.getBounds(&bound, &type, &isIntersectionOfRects);
47508eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
47608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com        REPORTER_ASSERT(reporter, !isIntersectionOfRects);
47708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
47808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com}
479cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
480e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
481e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com// This is similar to the above test but tests the iterator's ability to merge rects in the
482e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com// middle of a clip stack's sequence using nextCombined(). There is a save after every clip
483e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com// element to prevent the clip stack from merging the rectangles as they are added.
484e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.comstatic void test_iter_rect_merging(skiatest::Reporter* reporter) {
485e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
486e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    SkRect overlapLeft  = SkRect::MakeLTRB(10, 10, 50, 50);
487e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    SkRect overlapRight = SkRect::MakeLTRB(40, 40, 80, 80);
488e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
489e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    SkRect nestedParent = SkRect::MakeLTRB(10, 10, 90, 90);
490e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    SkRect nestedChild  = SkRect::MakeLTRB(40, 40, 60, 60);
491e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
492e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    SkRect farAway      = SkRect::MakeLTRB(1000, 1000, 1010, 1010);
493e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
494e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    SkRect overlapIntersect;
495e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    overlapIntersect.intersect(overlapLeft, overlapRight);
496e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
497e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    SkPath path1, path2;
498e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    path1.addCircle(SkIntToScalar(30), SkIntToScalar(30), SkIntToScalar(1000));
499e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    path2.addOval(SkRect::MakeWH(500, 600));
500e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
501e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    const SkClipStack::Iter::Clip* clip;
502e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
503e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    // call nextCombined with an empty clip stack
504e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    {
505e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        SkClipStack stack;
506e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
507e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, NULL == iter.nextCombined());
508e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    }
509e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
510e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    // two bw overlapping - should merge, bracketed by paths
511e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    {
512e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        SkClipStack stack;
513e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevPath(path1, SkRegion::kIntersect_Op, false); stack.save();
514e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
515e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevRect(overlapLeft, SkRegion::kIntersect_Op, false); stack.save();
516e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
517e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, false); stack.save();
518e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
519e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevPath(path2, SkRegion::kIntersect_Op, false); stack.save();
520e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
521e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
522e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
523e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
524e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, *clip->fPath == path1 && !clip->fDoAA);
525e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
526e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
527e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, !clip->fDoAA && *clip->fRect == overlapIntersect);
528e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
529e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
530e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, *clip->fPath == path2 && !clip->fDoAA);
531e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
532e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
533e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, NULL == clip);
534e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    }
535e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
536e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    // same as above but rects are aa and no final path.
537e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    {
538e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        SkClipStack stack;
539e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevPath(path1, SkRegion::kIntersect_Op, false); stack.save();
540e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
541e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevRect(overlapLeft, SkRegion::kIntersect_Op, true); stack.save();
542e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
543e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, true); stack.save();
544e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
545e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
546e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
547e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
548e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, *clip->fPath == path1 && !clip->fDoAA);
549e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
550e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
551e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, clip->fDoAA && *clip->fRect == overlapIntersect);
552e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
553e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
554e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, NULL == clip);
555e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    }
556e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
557e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    // mixed overlapping - no paths - should _not_ merge
558e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    {
559e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        SkClipStack stack;
560e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
561e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevRect(overlapLeft, SkRegion::kIntersect_Op, true); stack.save();
562e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, false); stack.save();
563e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
564e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
565e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
566e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
567e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, clip->fDoAA && *clip->fRect == overlapLeft);
568e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
569e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
570e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, !clip->fDoAA && *clip->fRect == overlapRight);
571e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
572e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
573e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, NULL == clip);
574e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    }
575e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
576e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    // three rects in a row where the third rect uses a non-intersect op.
577e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    {
578e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        SkClipStack stack;
579e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
580e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevRect(overlapLeft, SkRegion::kIntersect_Op, true); stack.save();
581e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, true); stack.save();
582e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevRect(nestedParent, SkRegion::kXOR_Op, true); stack.save();
583e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
584e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
585e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
586e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
587e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, clip->fDoAA && *clip->fRect == overlapIntersect);
588e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
589e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, clip->fDoAA && *clip->fRect == nestedParent);
590e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
591e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, NULL == clip);
592e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    }
593e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
594e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    // mixed nested (bw inside aa) - should merge
595e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    {
596e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        SkClipStack stack;
597e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevRect(nestedParent, SkRegion::kIntersect_Op, false); stack.save();
598e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
599e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevRect(nestedChild, SkRegion::kIntersect_Op, true); stack.save();
600e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
601e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
60272b2e6fff3f54c6aa80a98eab4c73f02a8cd450dskia.committer@gmail.com
603e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
604e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, clip->fDoAA && *clip->fRect == nestedChild);
605e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
606e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
607e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, NULL == clip);
608e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    }
609e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
610e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    // mixed nested (aa inside bw) - should merge
611e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    {
612e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        SkClipStack stack;
613e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevRect(nestedChild, SkRegion::kIntersect_Op, false); stack.save();
614e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
615e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevRect(nestedParent, SkRegion::kIntersect_Op, true); stack.save();
616e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
617e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
61872b2e6fff3f54c6aa80a98eab4c73f02a8cd450dskia.committer@gmail.com
619e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
620e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, !clip->fDoAA && *clip->fRect == nestedChild);
621e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
622e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
623e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, NULL == clip);
624e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    }
625e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
626e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    // three rect intersects in a row where result is empty after the second.
627e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    {
628e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        SkClipStack stack;
629e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
630e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevRect(overlapLeft, SkRegion::kIntersect_Op, false); stack.save();
631e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevRect(farAway, SkRegion::kIntersect_Op, false); stack.save();
632e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        stack.clipDevRect(overlapRight, SkRegion::kIntersect_Op, false); stack.save();
633e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
634e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
635e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
636e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
637e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, clip->fRect->isEmpty());
638e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
639e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
640e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, *clip->fRect == overlapRight);
641e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
642e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        clip = iter.nextCombined();
643e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com        REPORTER_ASSERT(reporter, NULL == clip);
644e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    }
645e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com}
646e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com
64751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com///////////////////////////////////////////////////////////////////////////////////////////////////
64851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
649a4e13c85b23fe7530ae89a84ef671ebd5e451e80bsalomon@google.com#if SK_SUPPORT_GPU
650a4e13c85b23fe7530ae89a84ef671ebd5e451e80bsalomon@google.com
65151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.comtypedef void (*AddElementFunc) (const SkRect& rect, bool aa, SkRegion::Op op, SkClipStack* stack);
65251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
65351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.comstatic void add_round_rect(const SkRect& rect, bool aa, SkRegion::Op op, SkClipStack* stack) {
65451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkPath path;
65551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkScalar rx = rect.width() / 10;
65651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkScalar ry = rect.width() / 20;
65751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    path.addRoundRect(rect, rx, ry);
65851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    stack->clipDevPath(path, op, aa);
65951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com};
66051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
66151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.comstatic void add_rect(const SkRect& rect, bool aa, SkRegion::Op op, SkClipStack* stack) {
66251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    stack->clipDevRect(rect, op, aa);
66351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com};
66451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
66551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.comstatic void add_oval(const SkRect& rect, bool aa, SkRegion::Op op, SkClipStack* stack) {
66651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkPath path;
66751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    path.addOval(rect);
66851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    stack->clipDevPath(path, op, aa);
66951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com};
67051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
67151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.comstatic void add_elem_to_stack(const SkClipStack::Iter::Clip& clip, SkClipStack* stack) {
67251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    if (NULL != clip.fPath) {
67351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        stack->clipDevPath(*clip.fPath, clip.fOp, clip.fDoAA);
67451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    } else if (NULL != clip.fRect) {
67551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        stack->clipDevRect(*clip.fRect, clip.fOp, clip.fDoAA);
67651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    }
67751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com}
67851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
67951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.comstatic void add_elem_to_region(const SkClipStack::Iter::Clip& clip,
68051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                               const SkIRect& bounds,
68151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                               SkRegion* region) {
68251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkRegion elemRegion;
68351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkRegion boundsRgn(bounds);
68451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
68551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    if (NULL != clip.fPath) {
68651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        elemRegion.setPath(*clip.fPath, boundsRgn);
68751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    } else if (NULL != clip.fRect) {
68851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkPath path;
68951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        path.addRect(*clip.fRect);
69051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        elemRegion.setPath(path, boundsRgn);
69151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    } else {
69251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        // TODO: Figure out why we sometimes get here in the reduced clip stack.
69351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        region->setEmpty();
69451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        return;
69551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    }
69651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    region->op(elemRegion, clip.fOp);
69751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com}
69851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
69951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com// This can assist with debugging the clip stack reduction code when the test below fails.
70051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.comstatic void print_clip(const SkClipStack::Iter::Clip& clip) {
70151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const char* kOpStrs[] = {
70251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "DF",
70351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "IS",
70451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "UN",
70551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "XR",
70651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "RD",
70751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        "RP",
70851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    };
70951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    if (clip.fRect || clip.fPath) {
71051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        const SkRect& bounds = clip.getBounds();
71151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkDebugf("%s %s [%f %f] x [%f %f]\n",
71251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                 kOpStrs[clip.fOp],
71351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                 (clip.fRect ? "R" : "P"),
71451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                 bounds.fLeft, bounds.fRight, bounds.fTop, bounds.fBottom);
71551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    } else {
71651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkDebugf("EM\n");
71751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    }
71851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com}
71951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
72051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.comstatic void test_reduced_clip_stack(skiatest::Reporter* reporter) {
72151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // We construct random clip stacks, reduce them, and then rasterize both versions to verify that
7228ccf590b89cec1a5974b6f4b7b49ca67cc5036cfskia.committer@gmail.com    // they are equal.
72351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
72451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // All the clip elements will be contained within these bounds.
72551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const SkRect kBounds = SkRect::MakeWH(100, 100);
72651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
72751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    enum {
72851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        kNumTests = 200,
72951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        kMinElemsPerTest = 1,
73051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        kMaxElemsPerTest = 50,
73151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    };
73251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
73351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // min/max size of a clip element as a fraction of kBounds.
73451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const SkScalar kMinElemSizeFrac = SK_Scalar1 / 5;
73551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const SkScalar kMaxElemSizeFrac = SK_Scalar1;
73651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
73751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const SkRegion::Op kOps[] = {
73851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kDifference_Op,
73951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kIntersect_Op,
74051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kUnion_Op,
74151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kXOR_Op,
74251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kReverseDifference_Op,
74351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion::kReplace_Op,
74451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    };
74551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
74651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // Replace operations short-circuit the optimizer. We want to make sure that we test this code
74751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // path a little bit but we don't want it to prevent us from testing many longer traversals in
74851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    // the optimizer.
74951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const int kReplaceDiv = 4 * kMaxElemsPerTest;
75051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
75151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    static const AddElementFunc kElementFuncs[] = {
75251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        add_rect,
75351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        add_round_rect,
75451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        add_oval,
75551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    };
75651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
75751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    SkRandom r;
75851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
75951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    for (int i = 0; i < kNumTests; ++i) {
76051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        // Randomly generate a clip stack.
76151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkClipStack stack;
76251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        int numElems = r.nextRangeU(kMinElemsPerTest, kMaxElemsPerTest);
76351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        for (int e = 0; e < numElems; ++e) {
76451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            SkRegion::Op op = kOps[r.nextULessThan(SK_ARRAY_COUNT(kOps))];
76551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            if (op == SkRegion::kReplace_Op) {
76651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                if (r.nextU() % kReplaceDiv) {
76751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                    --e;
76851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                    continue;
76951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                }
77051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            }
7718ccf590b89cec1a5974b6f4b7b49ca67cc5036cfskia.committer@gmail.com
77251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            // saves can change the clip stack behavior when an element is added.
77351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            bool doSave = r.nextBool();
7748ccf590b89cec1a5974b6f4b7b49ca67cc5036cfskia.committer@gmail.com
77551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            SkSize size = SkSize::Make(
77651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                SkScalarFloorToScalar(SkScalarMul(kBounds.width(), r.nextRangeScalar(kMinElemSizeFrac, kMaxElemSizeFrac))),
77751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                SkScalarFloorToScalar(SkScalarMul(kBounds.height(), r.nextRangeScalar(kMinElemSizeFrac, kMaxElemSizeFrac))));
77851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
77951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            SkPoint xy = {SkScalarFloorToScalar(r.nextRangeScalar(kBounds.fLeft, kBounds.fRight - size.fWidth)),
78051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                          SkScalarFloorToScalar(r.nextRangeScalar(kBounds.fTop, kBounds.fBottom - size.fHeight))};
78151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
78251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            SkRect rect = SkRect::MakeXYWH(xy.fX, xy.fY, size.fWidth, size.fHeight);
78351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
78451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            // AA is always disabled. The optimizer can cause changes in aa rasterization of the
78551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            // clip stack. A fractional edge repeated in different elements may be rasterized fewer
78651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            // times using the reduced stack.
78751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            kElementFuncs[r.nextULessThan(SK_ARRAY_COUNT(kElementFuncs))](rect, false, op, &stack);
78851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            if (doSave) {
78951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com                stack.save();
79051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            }
79151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
79251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
79351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        // Get the reduced version of the stack.
79451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkTDArray<SkClipStack::Iter::Clip> reducedClips;
79551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRect resultBounds;
79651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        bool bounded;
79751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        GrReducedClip::InitialState initial;
79851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        GrReducedClip::GrReduceClipStack(stack, &reducedClips, &resultBounds, &bounded, &initial);
79951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
80051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        // Build a new clip stack based on the reduced clip elements
80151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkClipStack reducedStack;
80251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        if (GrReducedClip::kAllOut_InitialState == initial) {
80351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            // whether the result is bounded or not, the whole plane should start outside the clip.
80451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            reducedStack.clipEmpty();
80551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
80651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        for (int c = 0; c < reducedClips.count(); ++c) {
80751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            add_elem_to_stack(reducedClips[c], &reducedStack);
80851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
80951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        if (bounded) {
81051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            // GrReduceClipStack() assumes that there is an implicit clip to the bounds
81151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            reducedStack.clipDevRect(resultBounds, SkRegion::kIntersect_Op, true);
81251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
81351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
81451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        // convert both the original stack and reduced stack to SkRegions and see if they're equal
81551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRect inflatedBounds = kBounds;
81651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        inflatedBounds.outset(kBounds.width() / 2, kBounds.height() / 2);
81751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkIRect inflatedIBounds;
81851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        inflatedBounds.roundOut(&inflatedIBounds);
81951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
82051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion region;
82151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkRegion reducedRegion;
82251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
82351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        region.setRect(inflatedIBounds);
82451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        const SkClipStack::Iter::Clip* clip;
82551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        SkClipStack::Iter iter(stack, SkClipStack::Iter::kBottom_IterStart);
82651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        while ((clip = iter.next())) {
82751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            add_elem_to_region(*clip, inflatedIBounds, &region);
82851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
82951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
83051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        reducedRegion.setRect(inflatedIBounds);
83151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        iter.reset(reducedStack, SkClipStack::Iter::kBottom_IterStart);
83251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        while ((clip = iter.next())) {
83351a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com            add_elem_to_region(*clip, inflatedIBounds, &reducedRegion);
83451a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        }
83551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
83651a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com        REPORTER_ASSERT(reporter, region == reducedRegion);
83751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    }
83851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com}
83951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
840a4e13c85b23fe7530ae89a84ef671ebd5e451e80bsalomon@google.com#endif
84151a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com///////////////////////////////////////////////////////////////////////////////////////////////////
84251a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com
843bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.comstatic void TestClipStack(skiatest::Reporter* reporter) {
844bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    SkClipStack stack;
845bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
84680214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 0 == stack.getSaveCount());
847bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    assert_count(reporter, stack, 0);
848bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
849bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    static const SkIRect gRects[] = {
850bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        { 0, 0, 100, 100 },
851bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        { 25, 25, 125, 125 },
852bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        { 0, 0, 1000, 1000 },
853bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com        { 0, 0, 75, 75 }
854bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    };
855bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    for (size_t i = 0; i < SK_ARRAY_COUNT(gRects); i++) {
856d9f2dea5328c9ab455852f2e4928cca7c71c6b05reed@google.com        stack.clipDevRect(gRects[i], SkRegion::kIntersect_Op);
857bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    }
858bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
859bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    // all of the above rects should have been intersected, leaving only 1 rect
86080214e26c57c5fea954006400852e8999e201923robertphillips@google.com    SkClipStack::B2TIter iter(stack);
86180214e26c57c5fea954006400852e8999e201923robertphillips@google.com    const SkClipStack::B2TIter::Clip* clip = iter.next();
8622047f00e4698f83499ab91911999a65c21a951c9epoger@google.com    SkRect answer;
8632047f00e4698f83499ab91911999a65c21a951c9epoger@google.com    answer.iset(25, 25, 75, 75);
864bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
865bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    REPORTER_ASSERT(reporter, clip);
866bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    REPORTER_ASSERT(reporter, clip->fRect);
867bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    REPORTER_ASSERT(reporter, !clip->fPath);
868bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    REPORTER_ASSERT(reporter, SkRegion::kIntersect_Op == clip->fOp);
869bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    REPORTER_ASSERT(reporter, *clip->fRect == answer);
870bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    // now check that we only had one in our iterator
871bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    REPORTER_ASSERT(reporter, !iter.next());
872bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
873bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    stack.reset();
87480214e26c57c5fea954006400852e8999e201923robertphillips@google.com    REPORTER_ASSERT(reporter, 0 == stack.getSaveCount());
875bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com    assert_count(reporter, stack, 0);
8761e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
8771e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    test_assign_and_comparison(reporter);
87880214e26c57c5fea954006400852e8999e201923robertphillips@google.com    test_iterators(reporter);
87908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    test_bounds(reporter, true);        // once with rects
88008eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    test_bounds(reporter, false);       // once with paths
881cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    test_isWideOpen(reporter);
88208eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    test_rect_merging(reporter);
883e8ca6c6e3a55634ac76efe5aceafaf8d669f43babsalomon@google.com    test_iter_rect_merging(reporter);
884e7b3d29a1289e64130dd0ec905d94feedc9d1064bsalomon@google.com#if SK_SUPPORT_GPU
88551a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com    test_reduced_clip_stack(reporter);
886e7b3d29a1289e64130dd0ec905d94feedc9d1064bsalomon@google.com#endif
887bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com}
888bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com
889bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.com#include "TestClassDef.h"
890bdee9fc778d4387d805d717f2cd7fc7074991fdbreed@google.comDEFINE_TESTCLASS("ClipStack", TestClipStackClass, TestClipStack)
891