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