1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
7c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita
8c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita#include "SkCanvas.h"
95c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com#include "SkClipStack.h"
105c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com#include "SkPath.h"
1146f935002c2b25331e552520dc7b1a912e12dfdcrobertphillips@google.com#include "SkThread.h"
1246f935002c2b25331e552520dc7b1a912e12dfdcrobertphillips@google.com
135c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com#include <new>
145c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
15607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
1646f935002c2b25331e552520dc7b1a912e12dfdcrobertphillips@google.com// 0-2 are reserved for invalid, empty & wide-open
17edb26fdb8349a727b226e90cbeab06cd25f5cac0bsalomon@google.comstatic const int32_t kFirstUnreservedGenID = 3;
18edb26fdb8349a727b226e90cbeab06cd25f5cac0bsalomon@google.comint32_t SkClipStack::gGenID = kFirstUnreservedGenID;
1946f935002c2b25331e552520dc7b1a912e12dfdcrobertphillips@google.com
206f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.orgSkClipStack::Element::Element(const Element& that) {
216f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org    switch (that.getType()) {
226f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org        case kEmpty_Type:
236f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            fPath.reset();
246f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            break;
256f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org        case kRect_Type: // Rect uses rrect
266f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org        case kRRect_Type:
276f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            fPath.reset();
286f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            fRRect = that.fRRect;
296f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            break;
306f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org        case kPath_Type:
316f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            fPath.set(that.getPath());
326f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            break;
336f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org    }
346f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org
356f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org    fSaveCount = that.fSaveCount;
366f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org    fOp = that.fOp;
376f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org    fType = that.fType;
386f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org    fDoAA = that.fDoAA;
396f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org    fFiniteBoundType = that.fFiniteBoundType;
406f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org    fFiniteBound = that.fFiniteBound;
416f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org    fIsIntersectionOfRects = that.fIsIntersectionOfRects;
426f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org    fGenID = that.fGenID;
436f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org}
446f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org
45e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.orgbool SkClipStack::Element::operator== (const Element& element) const {
46e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    if (this == &element) {
47e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        return true;
48e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    }
49e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    if (fOp != element.fOp ||
50e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        fType != element.fType ||
51e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        fDoAA != element.fDoAA ||
52e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        fSaveCount != element.fSaveCount) {
53e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        return false;
54e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    }
55e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    switch (fType) {
56e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        case kPath_Type:
576f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            return this->getPath() == element.getPath();
58e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        case kRRect_Type:
59e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            return fRRect == element.fRRect;
60e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        case kRect_Type:
61032a52fd4ceda001e44b80ff0462b570817bfe6fcommit-bot@chromium.org            return this->getRect() == element.getRect();
62e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        case kEmpty_Type:
63e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            return true;
64e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        default:
65e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            SkDEBUGFAIL("Unexpected type.");
66e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            return false;
67e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    }
68e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org}
69e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org
70c3b589a24eb4d567a906189f882c259ecf5c2f58fmalitavoid SkClipStack::Element::replay(SkCanvasClipVisitor* visitor) const {
71c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita    static const SkRect kEmptyRect = { 0, 0, 0, 0 };
72c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita
73c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita    switch (fType) {
74c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita        case kPath_Type:
75c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita            visitor->clipPath(this->getPath(), this->getOp(), this->isAA());
76c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita            break;
77c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita        case kRRect_Type:
78c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita            visitor->clipRRect(this->getRRect(), this->getOp(), this->isAA());
79c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita            break;
80c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita        case kRect_Type:
81c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita            visitor->clipRect(this->getRect(), this->getOp(), this->isAA());
82c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita            break;
83c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita        case kEmpty_Type:
84c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita            visitor->clipRect(kEmptyRect, SkRegion::kIntersect_Op, false);
85c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita            break;
86c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita    }
87c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita}
88c3b589a24eb4d567a906189f882c259ecf5c2f58fmalita
89c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.comvoid SkClipStack::Element::invertShapeFillType() {
90c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com    switch (fType) {
91c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com        case kRect_Type:
926f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            fPath.init();
936f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            fPath.get()->addRect(this->getRect());
946f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            fPath.get()->setFillType(SkPath::kInverseEvenOdd_FillType);
95e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            fType = kPath_Type;
96e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            break;
97e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        case kRRect_Type:
986f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            fPath.init();
996f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            fPath.get()->addRRect(fRRect);
1006f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            fPath.get()->setFillType(SkPath::kInverseEvenOdd_FillType);
101c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com            fType = kPath_Type;
102c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com            break;
103c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com        case kPath_Type:
1046f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            fPath.get()->toggleInverseFillType();
105e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            break;
106c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com        case kEmpty_Type:
107e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            // Should this set to an empty, inverse filled path?
108e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            break;
109e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    }
110e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org}
111e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org
112e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.orgvoid SkClipStack::Element::initPath(int saveCount, const SkPath& path, SkRegion::Op op,
113e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                                    bool doAA) {
114e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    if (!path.isInverseFillType()) {
115e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        if (SkPath::kNone_PathAsRect != path.asRect()) {
116e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            this->initRect(saveCount, path.getBounds(), op, doAA);
117e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            return;
118e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        }
119e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        SkRect ovalRect;
120e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        if (path.isOval(&ovalRect)) {
121e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            SkRRect rrect;
122e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            rrect.setOval(ovalRect);
123e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            this->initRRect(saveCount, rrect, op, doAA);
124e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            return;
125e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        }
126e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    }
1276f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org    fPath.set(path);
128e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    fType = kPath_Type;
129e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    this->initCommon(saveCount, op, doAA);
130e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org}
131e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org
132e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.orgvoid SkClipStack::Element::asPath(SkPath* path) const {
133e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    switch (fType) {
134e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        case kEmpty_Type:
135e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            path->reset();
136e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            break;
137e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        case kRect_Type:
138e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            path->reset();
139032a52fd4ceda001e44b80ff0462b570817bfe6fcommit-bot@chromium.org            path->addRect(this->getRect());
140e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            break;
141e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        case kRRect_Type:
142e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            path->reset();
143e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            path->addRRect(fRRect);
144e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            break;
145e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        case kPath_Type:
1466f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            *path = *fPath.get();
147c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com            break;
148c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com    }
149c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com}
150c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com
1519cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.orgvoid SkClipStack::Element::setEmpty() {
1529cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org    fType = kEmpty_Type;
1539cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org    fFiniteBound.setEmpty();
1549cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org    fFiniteBoundType = kNormal_BoundsType;
1559cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org    fIsIntersectionOfRects = false;
1569cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org    fRRect.setEmpty();
1579cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org    fPath.reset();
1589cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org    fGenID = kEmptyGenID;
1599cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org    SkDEBUGCODE(this->checkEmpty();)
1609cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org}
1619cb671a0017e8f2906e8351ff35efcd6d8fbf7b0commit-bot@chromium.org
1628a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.comvoid SkClipStack::Element::checkEmpty() const {
1638a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    SkASSERT(fFiniteBound.isEmpty());
1648a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    SkASSERT(kNormal_BoundsType == fFiniteBoundType);
1658a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    SkASSERT(!fIsIntersectionOfRects);
1668a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    SkASSERT(kEmptyGenID == fGenID);
1676f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org    SkASSERT(!fPath.isValid());
1688a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com}
1698a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com
1708a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.combool SkClipStack::Element::canBeIntersectedInPlace(int saveCount, SkRegion::Op op) const {
1718a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    if (kEmpty_Type == fType &&
1728a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        (SkRegion::kDifference_Op == op || SkRegion::kIntersect_Op == op)) {
1738a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        return true;
17446f935002c2b25331e552520dc7b1a912e12dfdcrobertphillips@google.com    }
1758a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    // Only clips within the same save/restore frame (as captured by
1768a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    // the save count) can be merged
1778a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    return  fSaveCount == saveCount &&
1788a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            SkRegion::kIntersect_Op == op &&
1798a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            (SkRegion::kIntersect_Op == fOp || SkRegion::kReplace_Op == fOp);
1808a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com}
1818a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com
1828a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.combool SkClipStack::Element::rectRectIntersectAllowed(const SkRect& newR, bool newAA) const {
1838a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    SkASSERT(kRect_Type == fType);
1848a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com
1858a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    if (fDoAA == newAA) {
1868a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        // if the AA setting is the same there is no issue
1878a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        return true;
18808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
18908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
190032a52fd4ceda001e44b80ff0462b570817bfe6fcommit-bot@chromium.org    if (!SkRect::Intersects(this->getRect(), newR)) {
1918a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        // The calling code will correctly set the result to the empty clip
1928a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        return true;
1931e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    }
1941e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
195032a52fd4ceda001e44b80ff0462b570817bfe6fcommit-bot@chromium.org    if (this->getRect().contains(newR)) {
1968a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        // if the new rect carves out a portion of the old one there is no
1978a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        // issue
1988a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        return true;
1991e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    }
2001e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
2018a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    // So either the two overlap in some complex manner or newR contains oldR.
2028a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    // In the first, case the edges will require different AA. In the second,
2038a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    // the AA setting that would be carried forward is incorrect (e.g., oldR
2048a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    // is AA while newR is BW but since newR contains oldR, oldR will be
2058a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    // drawn BW) since the new AA setting will predominate.
2068a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    return false;
2078a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com}
2088a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com
2098a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com// a mirror of combineBoundsRevDiff
2108a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.comvoid SkClipStack::Element::combineBoundsDiff(FillCombo combination, const SkRect& prevFinite) {
2118a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    switch (combination) {
2128a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kInvPrev_InvCur_FillCombo:
2138a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // In this case the only pixels that can remain set
2148a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // are inside the current clip rect since the extensions
2158a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // to infinity of both clips cancel out and whatever
2168a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // is outside of the current clip is removed
2178a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBoundType = kNormal_BoundsType;
2188a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
2198a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kInvPrev_Cur_FillCombo:
2208a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // In this case the current op is finite so the only pixels
2218a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // that aren't set are whatever isn't set in the previous
2228a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // clip and whatever this clip carves out
2238a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBound.join(prevFinite);
2248a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBoundType = kInsideOut_BoundsType;
2258a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
2268a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kPrev_InvCur_FillCombo:
2278a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // In this case everything outside of this clip's bound
2288a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // is erased, so the only pixels that can remain set
2298a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // occur w/in the intersection of the two finite bounds
2308a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            if (!fFiniteBound.intersect(prevFinite)) {
231e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                this->setEmpty();
232e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            } else {
233e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                fFiniteBoundType = kNormal_BoundsType;
2348a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            }
2358a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
2368a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kPrev_Cur_FillCombo:
2378a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // The most conservative result bound is that of the
2388a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // prior clip. This could be wildly incorrect if the
2398a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // second clip either exactly matches the first clip
2408a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // (which should yield the empty set) or reduces the
2418a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // size of the prior bound (e.g., if the second clip
2428a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // exactly matched the bottom half of the prior clip).
2438a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // We ignore these two possibilities.
2448a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBound = prevFinite;
2458a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
2468a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        default:
2478a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            SkDEBUGFAIL("SkClipStack::Element::combineBoundsDiff Invalid fill combination");
2488a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
24908eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com    }
2508a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com}
2518a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com
2528a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.comvoid SkClipStack::Element::combineBoundsXOR(int combination, const SkRect& prevFinite) {
2538a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com
2548a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    switch (combination) {
2558a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kInvPrev_Cur_FillCombo:       // fall through
2568a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kPrev_InvCur_FillCombo:
2578a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // With only one of the clips inverted the result will always
2588a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // extend to infinity. The only pixels that may be un-writeable
2598a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // lie within the union of the two finite bounds
2608a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBound.join(prevFinite);
2618a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBoundType = kInsideOut_BoundsType;
2628a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
2638a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kInvPrev_InvCur_FillCombo:
2648a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // The only pixels that can survive are within the
2658a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // union of the two bounding boxes since the extensions
2668a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // to infinity of both clips cancel out
2678a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // fall through!
2688a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kPrev_Cur_FillCombo:
2698a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // The most conservative bound for xor is the
2708a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // union of the two bounds. If the two clips exactly overlapped
2718a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // the xor could yield the empty set. Similarly the xor
2728a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // could reduce the size of the original clip's bound (e.g.,
2738a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // if the second clip exactly matched the bottom half of the
2748a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // first clip). We ignore these two cases.
2758a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBound.join(prevFinite);
2768a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBoundType = kNormal_BoundsType;
2778a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
2788a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        default:
2798a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            SkDEBUGFAIL("SkClipStack::Element::combineBoundsXOR Invalid fill combination");
2808a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
2815c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    }
2828a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com}
283607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
2848a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com// a mirror of combineBoundsIntersection
2858a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.comvoid SkClipStack::Element::combineBoundsUnion(int combination, const SkRect& prevFinite) {
28608eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com
2878a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    switch (combination) {
2888a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kInvPrev_InvCur_FillCombo:
2898a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            if (!fFiniteBound.intersect(prevFinite)) {
2908a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com                fFiniteBound.setEmpty();
2918a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com                fGenID = kWideOpenGenID;
2928a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            }
2938a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBoundType = kInsideOut_BoundsType;
2948a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
2958a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kInvPrev_Cur_FillCombo:
2968a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // The only pixels that won't be drawable are inside
2978a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // the prior clip's finite bound
2988a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBound = prevFinite;
2998a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBoundType = kInsideOut_BoundsType;
3008a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
3018a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kPrev_InvCur_FillCombo:
3028a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // The only pixels that won't be drawable are inside
3038a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // this clip's finite bound
3048a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
3058a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kPrev_Cur_FillCombo:
3068a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBound.join(prevFinite);
3078a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
3088a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        default:
3098a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            SkDEBUGFAIL("SkClipStack::Element::combineBoundsUnion Invalid fill combination");
3108a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
311607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    }
3128a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com}
3138a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com
3148a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com// a mirror of combineBoundsUnion
3158a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.comvoid SkClipStack::Element::combineBoundsIntersection(int combination, const SkRect& prevFinite) {
3168a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com
3178a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    switch (combination) {
3188a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kInvPrev_InvCur_FillCombo:
3198a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // The only pixels that aren't writable in this case
3208a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // occur in the union of the two finite bounds
3218a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBound.join(prevFinite);
3228a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBoundType = kInsideOut_BoundsType;
3238a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
3248a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kInvPrev_Cur_FillCombo:
3258a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // In this case the only pixels that will remain writeable
3268a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // are within the current clip
3278a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
3288a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kPrev_InvCur_FillCombo:
3298a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // In this case the only pixels that will remain writeable
3308a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // are with the previous clip
3318a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBound = prevFinite;
3328a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBoundType = kNormal_BoundsType;
3338a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
3348a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kPrev_Cur_FillCombo:
3358a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            if (!fFiniteBound.intersect(prevFinite)) {
336e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                this->setEmpty();
3378a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            }
3388a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
3398a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        default:
3408a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            SkDEBUGFAIL("SkClipStack::Element::combineBoundsIntersection Invalid fill combination");
3418a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
342607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    }
3438a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com}
344607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
3458a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com// a mirror of combineBoundsDiff
3468a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.comvoid SkClipStack::Element::combineBoundsRevDiff(int combination, const SkRect& prevFinite) {
347607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
3488a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    switch (combination) {
3498a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kInvPrev_InvCur_FillCombo:
3508a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // The only pixels that can survive are in the
3518a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // previous bound since the extensions to infinity in
3528a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // both clips cancel out
3538a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBound = prevFinite;
3548a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBoundType = kNormal_BoundsType;
3558a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
3568a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kInvPrev_Cur_FillCombo:
3578a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            if (!fFiniteBound.intersect(prevFinite)) {
358e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                this->setEmpty();
359e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            } else {
360e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                fFiniteBoundType = kNormal_BoundsType;
3618a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            }
3628a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
3638a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kPrev_InvCur_FillCombo:
3648a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBound.join(prevFinite);
3658a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBoundType = kInsideOut_BoundsType;
3668a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
3678a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case kPrev_Cur_FillCombo:
3688a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // Fall through - as with the kDifference_Op case, the
3698a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // most conservative result bound is the bound of the
3708a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // current clip. The prior clip could reduce the size of this
3718a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // bound (as in the kDifference_Op case) but we are ignoring
3728a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // those cases.
3738a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
3748a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        default:
3758a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            SkDEBUGFAIL("SkClipStack::Element::combineBoundsRevDiff Invalid fill combination");
3768a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
377607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    }
3788a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com}
3798a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com
3808a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.comvoid SkClipStack::Element::updateBoundAndGenID(const Element* prior) {
3818a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    // We set this first here but we may overwrite it later if we determine that the clip is
3828a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    // either wide-open or empty.
3838a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    fGenID = GetNextGenID();
3848a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com
3858a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    // First, optimistically update the current Element's bound information
3868a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    // with the current clip's bound
3878a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    fIsIntersectionOfRects = false;
388e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    switch (fType) {
389e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        case kRect_Type:
390032a52fd4ceda001e44b80ff0462b570817bfe6fcommit-bot@chromium.org            fFiniteBound = this->getRect();
391e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            fFiniteBoundType = kNormal_BoundsType;
3924c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com
393e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            if (SkRegion::kReplace_Op == fOp ||
394e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                (SkRegion::kIntersect_Op == fOp && NULL == prior) ||
395e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                (SkRegion::kIntersect_Op == fOp && prior->fIsIntersectionOfRects &&
396032a52fd4ceda001e44b80ff0462b570817bfe6fcommit-bot@chromium.org                    prior->rectRectIntersectAllowed(this->getRect(), fDoAA))) {
397e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                fIsIntersectionOfRects = true;
398e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            }
399e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            break;
400e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        case kRRect_Type:
401e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            fFiniteBound = fRRect.getBounds();
4028a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            fFiniteBoundType = kNormal_BoundsType;
403e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            break;
404e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        case kPath_Type:
4056f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            fFiniteBound = fPath.get()->getBounds();
406e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org
4076f954b956fc5c36ebbcac404d93ba9349fb0355fcommit-bot@chromium.org            if (fPath.get()->isInverseFillType()) {
408e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                fFiniteBoundType = kInsideOut_BoundsType;
409e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            } else {
410e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                fFiniteBoundType = kNormal_BoundsType;
411e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            }
412e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            break;
413e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        case kEmpty_Type:
414e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            SkDEBUGFAIL("We shouldn't get here with an empty element.");
415e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            break;
4168a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    }
417607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
4188a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    if (!fDoAA) {
4198a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        // Here we mimic a non-anti-aliased scanline system. If there is
4208a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        // no anti-aliasing we can integerize the bounding box to exclude
4218a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        // fractional parts that won't be rendered.
4228a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        // Note: the left edge is handled slightly differently below. We
4238a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        // are a bit more generous in the rounding since we don't want to
4248a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        // risk missing the left pixels when fLeft is very close to .5
425e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com        fFiniteBound.set(SkScalarFloorToScalar(fFiniteBound.fLeft+0.45f),
426e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com                         SkScalarRoundToScalar(fFiniteBound.fTop),
427e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com                         SkScalarRoundToScalar(fFiniteBound.fRight),
428e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com                         SkScalarRoundToScalar(fFiniteBound.fBottom));
4298a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    }
430607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
4318a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    // Now determine the previous Element's bound information taking into
4328a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    // account that there may be no previous clip
4338a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    SkRect prevFinite;
4348a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    SkClipStack::BoundsType prevType;
4358a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com
4368a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    if (NULL == prior) {
4378a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        // no prior clip means the entire plane is writable
4388a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        prevFinite.setEmpty();   // there are no pixels that cannot be drawn to
4398a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        prevType = kInsideOut_BoundsType;
4408a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    } else {
4418a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        prevFinite = prior->fFiniteBound;
4428a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        prevType = prior->fFiniteBoundType;
4438a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    }
444607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
4458a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    FillCombo combination = kPrev_Cur_FillCombo;
4468a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    if (kInsideOut_BoundsType == fFiniteBoundType) {
4478a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        combination = (FillCombo) (combination | 0x01);
4488a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    }
4498a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    if (kInsideOut_BoundsType == prevType) {
4508a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        combination = (FillCombo) (combination | 0x02);
4518a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    }
452607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
4538a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    SkASSERT(kInvPrev_InvCur_FillCombo == combination ||
4548a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com                kInvPrev_Cur_FillCombo == combination ||
4558a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com                kPrev_InvCur_FillCombo == combination ||
4568a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com                kPrev_Cur_FillCombo == combination);
4578a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com
4588a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    // Now integrate with clip with the prior clips
4598a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com    switch (fOp) {
4608a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case SkRegion::kDifference_Op:
4618a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            this->combineBoundsDiff(combination, prevFinite);
4628a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
4638a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case SkRegion::kXOR_Op:
4648a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            this->combineBoundsXOR(combination, prevFinite);
4658a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
4668a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case SkRegion::kUnion_Op:
4678a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            this->combineBoundsUnion(combination, prevFinite);
4688a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
4698a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case SkRegion::kIntersect_Op:
4708a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            this->combineBoundsIntersection(combination, prevFinite);
4718a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
4728a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case SkRegion::kReverseDifference_Op:
4738a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            this->combineBoundsRevDiff(combination, prevFinite);
4748a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
4758a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        case SkRegion::kReplace_Op:
4768a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // Replace just ignores everything prior
4778a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // The current clip's bound information is already filled in
4788a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            // so nothing to do
4798a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
4808a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com        default:
481e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            SkDebugf("SkRegion::Op error\n");
4828a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            SkASSERT(0);
4838a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com            break;
484607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    }
4858a98e3bd18f1a8914cbfe1461e1ff47f51286556bsalomon@google.com}
4865c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
4879128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com// This constant determines how many Element's are allocated together as a block in
488f9a90847820a8ec4a3c97a2b544c622e3ca6b09arobertphillips@google.com// the deque. As such it needs to balance allocating too much memory vs.
489f9a90847820a8ec4a3c97a2b544c622e3ca6b09arobertphillips@google.com// incurring allocation/deallocation thrashing. It should roughly correspond to
490f9a90847820a8ec4a3c97a2b544c622e3ca6b09arobertphillips@google.com// the deepest save/restore stack we expect to see.
4919128edc700ce1b722f1290c585af829542f98a33bsalomon@google.comstatic const int kDefaultElementAllocCnt = 8;
49246f935002c2b25331e552520dc7b1a912e12dfdcrobertphillips@google.com
493fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.comSkClipStack::SkClipStack()
4949128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    : fDeque(sizeof(Element), kDefaultElementAllocCnt)
49546f935002c2b25331e552520dc7b1a912e12dfdcrobertphillips@google.com    , fSaveCount(0) {
4965c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com}
4975c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
498fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.comSkClipStack::SkClipStack(const SkClipStack& b)
4999128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    : fDeque(sizeof(Element), kDefaultElementAllocCnt) {
5001e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    *this = b;
5011e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org}
5021e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
503fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.comSkClipStack::SkClipStack(const SkRect& r)
5049128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    : fDeque(sizeof(Element), kDefaultElementAllocCnt)
50546f935002c2b25331e552520dc7b1a912e12dfdcrobertphillips@google.com    , fSaveCount(0) {
506cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    if (!r.isEmpty()) {
507cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com        this->clipDevRect(r, SkRegion::kReplace_Op, false);
508cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com    }
509cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com}
510cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
511fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.comSkClipStack::SkClipStack(const SkIRect& r)
5129128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    : fDeque(sizeof(Element), kDefaultElementAllocCnt)
51346f935002c2b25331e552520dc7b1a912e12dfdcrobertphillips@google.com    , fSaveCount(0) {
514641f8b19a6799b6d73ac17b9c2d2f8a5e6f5ad4drobertphillips@google.com    if (!r.isEmpty()) {
515641f8b19a6799b6d73ac17b9c2d2f8a5e6f5ad4drobertphillips@google.com        SkRect temp;
516641f8b19a6799b6d73ac17b9c2d2f8a5e6f5ad4drobertphillips@google.com        temp.set(r);
517641f8b19a6799b6d73ac17b9c2d2f8a5e6f5ad4drobertphillips@google.com        this->clipDevRect(temp, SkRegion::kReplace_Op, false);
518641f8b19a6799b6d73ac17b9c2d2f8a5e6f5ad4drobertphillips@google.com    }
519641f8b19a6799b6d73ac17b9c2d2f8a5e6f5ad4drobertphillips@google.com}
520641f8b19a6799b6d73ac17b9c2d2f8a5e6f5ad4drobertphillips@google.com
521610f716b00f214e4899a102c1bbc1d6a323e114evandebo@chromium.orgSkClipStack::~SkClipStack() {
522610f716b00f214e4899a102c1bbc1d6a323e114evandebo@chromium.org    reset();
523610f716b00f214e4899a102c1bbc1d6a323e114evandebo@chromium.org}
524610f716b00f214e4899a102c1bbc1d6a323e114evandebo@chromium.org
5251e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.orgSkClipStack& SkClipStack::operator=(const SkClipStack& b) {
5261e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    if (this == &b) {
5271e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org        return *this;
5281e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    }
5291e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    reset();
5301e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
5311e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    fSaveCount = b.fSaveCount;
5321e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkDeque::F2BIter recIter(b.fDeque);
5339128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    for (const Element* element = (const Element*)recIter.next();
5349128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com         element != NULL;
5359128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com         element = (const Element*)recIter.next()) {
5369128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com        new (fDeque.push_back()) Element(*element);
5371e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    }
5381e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
5391e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    return *this;
5401e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org}
5411e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
5421e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.orgbool SkClipStack::operator==(const SkClipStack& b) const {
54386b39f311e174ddbd0d2f8de8d18dd45a8a2334fcommit-bot@chromium.org    if (this->getTopmostGenID() == b.getTopmostGenID()) {
54486b39f311e174ddbd0d2f8de8d18dd45a8a2334fcommit-bot@chromium.org        return true;
54586b39f311e174ddbd0d2f8de8d18dd45a8a2334fcommit-bot@chromium.org    }
546fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    if (fSaveCount != b.fSaveCount ||
54746f935002c2b25331e552520dc7b1a912e12dfdcrobertphillips@google.com        fDeque.count() != b.fDeque.count()) {
5481e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org        return false;
5491e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    }
5501e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkDeque::F2BIter myIter(fDeque);
5511e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    SkDeque::F2BIter bIter(b.fDeque);
5529128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    const Element* myElement = (const Element*)myIter.next();
5539128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    const Element* bElement = (const Element*)bIter.next();
5541e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
5559128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    while (myElement != NULL && bElement != NULL) {
5569128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com        if (*myElement != *bElement) {
5571e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org            return false;
5581e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org        }
5599128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com        myElement = (const Element*)myIter.next();
5609128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com        bElement = (const Element*)bIter.next();
5611e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org    }
5629128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    return myElement == NULL && bElement == NULL;
5631e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org}
5641e1c36f4f89ad39e1d248edb745919e493242c68vandebo@chromium.org
5655c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.comvoid SkClipStack::reset() {
566610f716b00f214e4899a102c1bbc1d6a323e114evandebo@chromium.org    // We used a placement new for each object in fDeque, so we're responsible
567610f716b00f214e4899a102c1bbc1d6a323e114evandebo@chromium.org    // for calling the destructor on each of them as well.
568610f716b00f214e4899a102c1bbc1d6a323e114evandebo@chromium.org    while (!fDeque.empty()) {
5699128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com        Element* element = (Element*)fDeque.back();
5709128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com        element->~Element();
571610f716b00f214e4899a102c1bbc1d6a323e114evandebo@chromium.org        fDeque.pop_back();
572610f716b00f214e4899a102c1bbc1d6a323e114evandebo@chromium.org    }
5735c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
5745c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    fSaveCount = 0;
5755c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com}
5765c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
5775c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.comvoid SkClipStack::save() {
5785c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    fSaveCount += 1;
5795c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com}
5805c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
5815c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.comvoid SkClipStack::restore() {
5825c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    fSaveCount -= 1;
5836fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org    restoreTo(fSaveCount);
5846fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org}
5856fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org
5866fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.orgvoid SkClipStack::restoreTo(int saveCount) {
5875c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    while (!fDeque.empty()) {
5889128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com        Element* element = (Element*)fDeque.back();
5896fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org        if (element->fSaveCount <= saveCount) {
5905c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com            break;
5915c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com        }
5929128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com        element->~Element();
5935c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com        fDeque.pop_back();
5945c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    }
5955c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com}
5965c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
597fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.comvoid SkClipStack::getBounds(SkRect* canvFiniteBound,
5984c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                            BoundsType* boundType,
5994c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                            bool* isIntersectionOfRects) const {
60049f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(canvFiniteBound && boundType);
601607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
6029128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    Element* element = (Element*)fDeque.back();
603607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
6049128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    if (NULL == element) {
605607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        // the clip is wide open - the infinite plane w/ no pixels un-writeable
6067b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com        canvFiniteBound->setEmpty();
607607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        *boundType = kInsideOut_BoundsType;
60849f085dddff10473b6ebf832a974288300224e60bsalomon        if (isIntersectionOfRects) {
6094c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com            *isIntersectionOfRects = false;
6104c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com        }
611607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        return;
612607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    }
613607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
6149128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    *canvFiniteBound = element->fFiniteBound;
6159128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    *boundType = element->fFiniteBoundType;
61649f085dddff10473b6ebf832a974288300224e60bsalomon    if (isIntersectionOfRects) {
6179128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com        *isIntersectionOfRects = element->fIsIntersectionOfRects;
6184c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com    }
619607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com}
620607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
6213ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.combool SkClipStack::intersectRectWithClip(SkRect* rect) const {
62249f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(rect);
6233ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com
6243ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com    SkRect bounds;
6253ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com    SkClipStack::BoundsType bt;
6263ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com    this->getBounds(&bounds, &bt);
6273ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com    if (bt == SkClipStack::kInsideOut_BoundsType) {
6283ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com        if (bounds.contains(*rect)) {
6293ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com            return false;
6303ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com        } else {
6313ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com            // If rect's x values are both within bound's x range we
6323ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com            // could clip here. Same for y. But we don't bother to check.
6333ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com            return true;
6343ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com        }
6355b6f91643d3ad1bdcdd65329d656f0fc43174be3skia.committer@gmail.com    } else {
6363ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com        return rect->intersect(bounds);
6373ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com    }
6383ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com}
6393ab43d5c5b4d77f46dd0266618f92e5fefce2021bsalomon@google.com
6408cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.orgbool SkClipStack::quickContains(const SkRect& rect) const {
6418cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
6428cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    Iter iter(*this, Iter::kTop_IterStart);
6438cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    const Element* element = iter.prev();
6448cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    while (element != NULL) {
6458cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        if (SkRegion::kIntersect_Op != element->getOp() && SkRegion::kReplace_Op != element->getOp())
6468cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org            return false;
6478cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        if (element->isInverseFilled()) {
6488cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org            // Part of 'rect' could be trimmed off by the inverse-filled clip element
6498cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org            if (SkRect::Intersects(element->getBounds(), rect)) {
6508cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org                return false;
6518cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org            }
6528cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        } else {
6538cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org            if (!element->contains(rect)) {
6548cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org                return false;
6558cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org            }
6568cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        }
6578cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        if (SkRegion::kReplace_Op == element->getOp()) {
6588cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org            break;
6598cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        }
6608cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org        element = iter.prev();
6618cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    }
6628cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org    return true;
6638cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org}
6648cdf0f52ff395d4053f7ed5c20861c42eba25d31junov@chromium.org
665e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.orgvoid SkClipStack::pushElement(const Element& element) {
66663ae1cfb10d0d14722df59cba0012f8a4370c090robertphillips@google.com    // Use reverse iterator instead of back because Rect path may need previous
6674c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com    SkDeque::Iter iter(fDeque, SkDeque::Iter::kBack_IterStart);
668e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    Element* prior = (Element*) iter.prev();
6694c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com
67049f085dddff10473b6ebf832a974288300224e60bsalomon    if (prior) {
671e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        if (prior->canBeIntersectedInPlace(fSaveCount, element.getOp())) {
672e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            switch (prior->fType) {
6736fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org                case Element::kEmpty_Type:
674e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                    SkDEBUGCODE(prior->checkEmpty();)
6756fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org                    return;
6766fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org                case Element::kRect_Type:
677e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                    if (Element::kRect_Type == element.getType()) {
678e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                        if (prior->rectRectIntersectAllowed(element.getRect(), element.isAA())) {
679032a52fd4ceda001e44b80ff0462b570817bfe6fcommit-bot@chromium.org                            SkRect isectRect;
680032a52fd4ceda001e44b80ff0462b570817bfe6fcommit-bot@chromium.org                            if (!isectRect.intersect(prior->getRect(), element.getRect())) {
681e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                                prior->setEmpty();
682e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                                return;
683e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                            }
684e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org
685032a52fd4ceda001e44b80ff0462b570817bfe6fcommit-bot@chromium.org                            prior->fRRect.setRect(isectRect);
686e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                            prior->fDoAA = element.isAA();
687e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                            Element* priorPrior = (Element*) iter.prev();
688e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                            prior->updateBoundAndGenID(priorPrior);
6896fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org                            return;
6906fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org                        }
691e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                        break;
6926fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org                    }
693e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                    // fallthrough
694e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                default:
695e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                    if (!SkRect::Intersects(prior->getBounds(), element.getBounds())) {
696e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org                        prior->setEmpty();
69708eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com                        return;
69808eacc144711cd5d33513b2fba7a635ad28b7208robertphillips@google.com                    }
6996fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org                    break;
7006fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org            }
701e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        } else if (SkRegion::kReplace_Op == element.getOp()) {
7026fbe54c663bd0eed6f6519c31a4c8e291db2613bcommit-bot@chromium.org            this->restoreTo(fSaveCount - 1);
703e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org            prior = (Element*) fDeque.back();
7045c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com        }
7055c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com    }
706e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    Element* newElement = SkNEW_PLACEMENT_ARGS(fDeque.push_back(), Element, (element));
707e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    newElement->updateBoundAndGenID(prior);
7085c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com}
7095c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
710e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.orgvoid SkClipStack::clipDevRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
711e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    Element element(fSaveCount, rrect, op, doAA);
712e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    this->pushElement(element);
713e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org}
71446f935002c2b25331e552520dc7b1a912e12dfdcrobertphillips@google.com
715e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.orgvoid SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
716e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    Element element(fSaveCount, rect, op, doAA);
717e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    this->pushElement(element);
7185c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com}
7195c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
720e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.orgvoid SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) {
721e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    Element element(fSaveCount, path, op, doAA);
722e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org    this->pushElement(element);
723e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org}
72463ae1cfb10d0d14722df59cba0012f8a4370c090robertphillips@google.com
725e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.orgvoid SkClipStack::clipEmpty() {
7269128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    Element* element = (Element*) fDeque.back();
72763ae1cfb10d0d14722df59cba0012f8a4370c090robertphillips@google.com
7289128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    if (element && element->canBeIntersectedInPlace(fSaveCount, SkRegion::kIntersect_Op)) {
729e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org        element->setEmpty();
7300557d9ea94d5435a9072c9b4141a05190d648442reed@google.com    }
7319128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    new (fDeque.push_back()) Element(fSaveCount);
732fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
7339128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    ((Element*)fDeque.back())->fGenID = kEmptyGenID;
7340557d9ea94d5435a9072c9b4141a05190d648442reed@google.com}
7350557d9ea94d5435a9072c9b4141a05190d648442reed@google.com
736fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.combool SkClipStack::isWideOpen() const {
737d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    return this->getTopmostGenID() == kWideOpenGenID;
738cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com}
739cc6493bbef7c9c2adf4b1ed8701e2ed015ae745drobertphillips@google.com
7405c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com///////////////////////////////////////////////////////////////////////////////
7415c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
7425836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.comSkClipStack::Iter::Iter() : fStack(NULL) {
743d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com}
744d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com
7455836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.comSkClipStack::Iter::Iter(const SkClipStack& stack, IterStart startLoc)
7465836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com    : fStack(&stack) {
74752cb2c7cdf87f1e7d4b5d24b3609aaa514a26c10robertphillips@google.com    this->reset(stack, startLoc);
7485c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com}
7495c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com
7508182fa0cac76e7e6d583aebba060229230516887bsalomon@google.comconst SkClipStack::Element* SkClipStack::Iter::next() {
7518182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    return (const SkClipStack::Element*)fIter.next();
7525c3d1471e4908706cd053a5e2ea9ded3a6c2eaebreed@google.com}
753d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com
7548182fa0cac76e7e6d583aebba060229230516887bsalomon@google.comconst SkClipStack::Element* SkClipStack::Iter::prev() {
7558182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com    return (const SkClipStack::Element*)fIter.prev();
75652cb2c7cdf87f1e7d4b5d24b3609aaa514a26c10robertphillips@google.com}
75752cb2c7cdf87f1e7d4b5d24b3609aaa514a26c10robertphillips@google.com
7588182fa0cac76e7e6d583aebba060229230516887bsalomon@google.comconst SkClipStack::Element* SkClipStack::Iter::skipToTopmost(SkRegion::Op op) {
7595836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com
7605836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com    if (NULL == fStack) {
7615836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com        return NULL;
7625836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com    }
7635836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com
7645836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com    fIter.reset(fStack->fDeque, SkDeque::Iter::kBack_IterStart);
7655836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com
7669128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    const SkClipStack::Element* element = NULL;
7675836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com
7689128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    for (element = (const SkClipStack::Element*) fIter.prev();
76949f085dddff10473b6ebf832a974288300224e60bsalomon         element;
7709128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com         element = (const SkClipStack::Element*) fIter.prev()) {
7715836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com
7729128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com        if (op == element->fOp) {
7735836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com            // The Deque's iterator is actually one pace ahead of the
7749128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com            // returned value. So while "element" is the element we want to
7755836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com            // return, the iterator is actually pointing at (and will
7765836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com            // return on the next "next" or "prev" call) the element
777fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            // in front of it in the deque. Bump the iterator forward a
7785836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com            // step so we get the expected result.
7795836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com            if (NULL == fIter.next()) {
7805836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com                // The reverse iterator has run off the front of the deque
7815836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com                // (i.e., the "op" clip is the first clip) and can't
7825836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com                // recover. Reset the iterator to start at the front.
7835836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com                fIter.reset(fStack->fDeque, SkDeque::Iter::kFront_IterStart);
7845836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com            }
7855836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com            break;
7865836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com        }
7875836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com    }
7885836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com
7899128edc700ce1b722f1290c585af829542f98a33bsalomon@google.com    if (NULL == element) {
7905836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com        // There were no "op" clips
7915836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com        fIter.reset(fStack->fDeque, SkDeque::Iter::kFront_IterStart);
7925836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com    }
7935836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com
7945836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com    return this->next();
7955836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com}
7965836b6dec5563e6273099fcf23984dd3818a168frobertphillips@google.com
79752cb2c7cdf87f1e7d4b5d24b3609aaa514a26c10robertphillips@google.comvoid SkClipStack::Iter::reset(const SkClipStack& stack, IterStart startLoc) {
798a6f11c4f717961070cd6fc5e60c361db14c5c4f3robertphillips@google.com    fStack = &stack;
79952cb2c7cdf87f1e7d4b5d24b3609aaa514a26c10robertphillips@google.com    fIter.reset(stack.fDeque, static_cast<SkDeque::Iter::IterStart>(startLoc));
800d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com}
801607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
802607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com// helper method
803607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.comvoid SkClipStack::getConservativeBounds(int offsetX,
804607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com                                        int offsetY,
805607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com                                        int maxWidth,
806607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com                                        int maxHeight,
8077b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com                                        SkRect* devBounds,
8084c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com                                        bool* isIntersectionOfRects) const {
80949f085dddff10473b6ebf832a974288300224e60bsalomon    SkASSERT(devBounds);
810607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
811fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    devBounds->setLTRB(0, 0,
8127b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com                       SkIntToScalar(maxWidth), SkIntToScalar(maxHeight));
813607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
814607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    SkRect temp;
815607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    SkClipStack::BoundsType boundType;
816fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
8177b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    // temp starts off in canvas space here
8184c2a2f7c5e8ec77771153f94c454adf21fd33805robertphillips@google.com    this->getBounds(&temp, &boundType, isIntersectionOfRects);
819607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    if (SkClipStack::kInsideOut_BoundsType == boundType) {
820607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com        return;
821607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    }
822607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
8237b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    // but is converted to device space here
824607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    temp.offset(SkIntToScalar(offsetX), SkIntToScalar(offsetY));
825607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com
8267b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com    if (!devBounds->intersect(temp)) {
8277b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com        devBounds->setEmpty();
828607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com    }
829607fe077c893fdb230e29631be096de614a14e2arobertphillips@google.com}
83046f935002c2b25331e552520dc7b1a912e12dfdcrobertphillips@google.com
83146f935002c2b25331e552520dc7b1a912e12dfdcrobertphillips@google.comint32_t SkClipStack::GetNextGenID() {
832edb26fdb8349a727b226e90cbeab06cd25f5cac0bsalomon@google.com    // TODO: handle overflow.
83346f935002c2b25331e552520dc7b1a912e12dfdcrobertphillips@google.com    return sk_atomic_inc(&gGenID);
83446f935002c2b25331e552520dc7b1a912e12dfdcrobertphillips@google.com}
83573e71023a05393ef0aa12bf3644a1c704feeec0crobertphillips@google.com
83673e71023a05393ef0aa12bf3644a1c704feeec0crobertphillips@google.comint32_t SkClipStack::getTopmostGenID() const {
837f0784bde753feaff601f703089872fc1af265328reed@google.com    if (fDeque.empty()) {
838d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        return kWideOpenGenID;
839679eb674fc064993d534df4d48a4ddaff4e33e06commit-bot@chromium.org    }
840679eb674fc064993d534df4d48a4ddaff4e33e06commit-bot@chromium.org
841d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    const Element* back = static_cast<const Element*>(fDeque.back());
842d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    if (kInsideOut_BoundsType == back->fFiniteBoundType && back->fFiniteBound.isEmpty()) {
843d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org        return kWideOpenGenID;
844d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    }
845d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org
846d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org    return back->getGenID();
84773e71023a05393ef0aa12bf3644a1c704feeec0crobertphillips@google.com}
848b6b02526438d6839481fb40ccf610d28f7652397bsalomon
849b6b02526438d6839481fb40ccf610d28f7652397bsalomon#ifdef SK_DEVELOPER
850b6b02526438d6839481fb40ccf610d28f7652397bsalomonvoid SkClipStack::Element::dump() const {
851b6b02526438d6839481fb40ccf610d28f7652397bsalomon    static const char* kTypeStrings[] = {
852b6b02526438d6839481fb40ccf610d28f7652397bsalomon        "empty",
853b6b02526438d6839481fb40ccf610d28f7652397bsalomon        "rect",
854b6b02526438d6839481fb40ccf610d28f7652397bsalomon        "rrect",
855b6b02526438d6839481fb40ccf610d28f7652397bsalomon        "path"
856b6b02526438d6839481fb40ccf610d28f7652397bsalomon    };
857b6b02526438d6839481fb40ccf610d28f7652397bsalomon    SK_COMPILE_ASSERT(0 == kEmpty_Type, type_str);
858b6b02526438d6839481fb40ccf610d28f7652397bsalomon    SK_COMPILE_ASSERT(1 == kRect_Type, type_str);
859b6b02526438d6839481fb40ccf610d28f7652397bsalomon    SK_COMPILE_ASSERT(2 == kRRect_Type, type_str);
860b6b02526438d6839481fb40ccf610d28f7652397bsalomon    SK_COMPILE_ASSERT(3 == kPath_Type, type_str);
861b6b02526438d6839481fb40ccf610d28f7652397bsalomon    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(kTypeStrings) == kTypeCnt, type_str);
862b6b02526438d6839481fb40ccf610d28f7652397bsalomon
863b6b02526438d6839481fb40ccf610d28f7652397bsalomon    static const char* kOpStrings[] = {
864b6b02526438d6839481fb40ccf610d28f7652397bsalomon        "difference",
865b6b02526438d6839481fb40ccf610d28f7652397bsalomon        "intersect",
866b6b02526438d6839481fb40ccf610d28f7652397bsalomon        "union",
867b6b02526438d6839481fb40ccf610d28f7652397bsalomon        "xor",
868b6b02526438d6839481fb40ccf610d28f7652397bsalomon        "reverse-difference",
869b6b02526438d6839481fb40ccf610d28f7652397bsalomon        "replace",
870b6b02526438d6839481fb40ccf610d28f7652397bsalomon    };
871b6b02526438d6839481fb40ccf610d28f7652397bsalomon    SK_COMPILE_ASSERT(0 == SkRegion::kDifference_Op, op_str);
872b6b02526438d6839481fb40ccf610d28f7652397bsalomon    SK_COMPILE_ASSERT(1 == SkRegion::kIntersect_Op, op_str);
873b6b02526438d6839481fb40ccf610d28f7652397bsalomon    SK_COMPILE_ASSERT(2 == SkRegion::kUnion_Op, op_str);
874b6b02526438d6839481fb40ccf610d28f7652397bsalomon    SK_COMPILE_ASSERT(3 == SkRegion::kXOR_Op, op_str);
875b6b02526438d6839481fb40ccf610d28f7652397bsalomon    SK_COMPILE_ASSERT(4 == SkRegion::kReverseDifference_Op, op_str);
876b6b02526438d6839481fb40ccf610d28f7652397bsalomon    SK_COMPILE_ASSERT(5 == SkRegion::kReplace_Op, op_str);
877b6b02526438d6839481fb40ccf610d28f7652397bsalomon    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(kOpStrings) == SkRegion::kOpCnt, op_str);
878b6b02526438d6839481fb40ccf610d28f7652397bsalomon
879b6b02526438d6839481fb40ccf610d28f7652397bsalomon    SkDebugf("Type: %s, Op: %s, AA: %s, Save Count: %d\n", kTypeStrings[fType],
880b6b02526438d6839481fb40ccf610d28f7652397bsalomon             kOpStrings[fOp], (fDoAA ? "yes" : "no"), fSaveCount);
881b6b02526438d6839481fb40ccf610d28f7652397bsalomon    switch (fType) {
882b6b02526438d6839481fb40ccf610d28f7652397bsalomon        case kEmpty_Type:
883b6b02526438d6839481fb40ccf610d28f7652397bsalomon            SkDebugf("\n");
884b6b02526438d6839481fb40ccf610d28f7652397bsalomon            break;
885b6b02526438d6839481fb40ccf610d28f7652397bsalomon        case kRect_Type:
886b6b02526438d6839481fb40ccf610d28f7652397bsalomon            this->getRect().dump();
887b6b02526438d6839481fb40ccf610d28f7652397bsalomon            SkDebugf("\n");
888b6b02526438d6839481fb40ccf610d28f7652397bsalomon            break;
889b6b02526438d6839481fb40ccf610d28f7652397bsalomon        case kRRect_Type:
890b6b02526438d6839481fb40ccf610d28f7652397bsalomon            this->getRRect().dump();
891b6b02526438d6839481fb40ccf610d28f7652397bsalomon            SkDebugf("\n");
892b6b02526438d6839481fb40ccf610d28f7652397bsalomon            break;
893b6b02526438d6839481fb40ccf610d28f7652397bsalomon        case kPath_Type:
894e956259c5a4f71768afb34ec032eaed49dcbe9f2caryclark            this->getPath().dump(NULL, true, false);
895b6b02526438d6839481fb40ccf610d28f7652397bsalomon            break;
896b6b02526438d6839481fb40ccf610d28f7652397bsalomon    }
897b6b02526438d6839481fb40ccf610d28f7652397bsalomon}
898b6b02526438d6839481fb40ccf610d28f7652397bsalomon
899b6b02526438d6839481fb40ccf610d28f7652397bsalomonvoid SkClipStack::dump() const {
900b6b02526438d6839481fb40ccf610d28f7652397bsalomon    B2TIter iter(*this);
901b6b02526438d6839481fb40ccf610d28f7652397bsalomon    const Element* e;
902b6b02526438d6839481fb40ccf610d28f7652397bsalomon    while ((e = iter.next())) {
903b6b02526438d6839481fb40ccf610d28f7652397bsalomon        e->dump();
904b6b02526438d6839481fb40ccf610d28f7652397bsalomon        SkDebugf("\n");
905b6b02526438d6839481fb40ccf610d28f7652397bsalomon    }
906b6b02526438d6839481fb40ccf610d28f7652397bsalomon}
907b6b02526438d6839481fb40ccf610d28f7652397bsalomon#endif
908