SkClipStack.cpp revision 02802f64ea0b1fc9223386328a95280b74092c94
156c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks/*
256c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks * Copyright 2011 Google Inc.
356c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks *
456c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks * Use of this source code is governed by a BSD-style license that can be
556c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks * found in the LICENSE file.
656c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks */
756c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks
856c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks#include "SkCanvas.h"
956c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks#include "SkClipStack.h"
1056c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks#include "SkPath.h"
117df30109963092559d3760c0661a020f9daf1030The Android Open Source Project#include "SkPathOps.h"
127df30109963092559d3760c0661a020f9daf1030The Android Open Source Project#include "SkThread.h"
137df30109963092559d3760c0661a020f9daf1030The Android Open Source Project
147df30109963092559d3760c0661a020f9daf1030The Android Open Source Project#include <new>
157df30109963092559d3760c0661a020f9daf1030The Android Open Source Project
167df30109963092559d3760c0661a020f9daf1030The Android Open Source Project
177df30109963092559d3760c0661a020f9daf1030The Android Open Source Project// 0-2 are reserved for invalid, empty & wide-open
187df30109963092559d3760c0661a020f9daf1030The Android Open Source Projectstatic const int32_t kFirstUnreservedGenID = 3;
197df30109963092559d3760c0661a020f9daf1030The Android Open Source Projectint32_t SkClipStack::gGenID = kFirstUnreservedGenID;
207df30109963092559d3760c0661a020f9daf1030The Android Open Source Project
217df30109963092559d3760c0661a020f9daf1030The Android Open Source ProjectSkClipStack::Element::Element(const Element& that) {
227df30109963092559d3760c0661a020f9daf1030The Android Open Source Project    switch (that.getType()) {
2356c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kEmpty_Type:
2456c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            fPath.reset();
2556c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            break;
2656c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kRect_Type: // Rect uses rrect
2756c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kRRect_Type:
2856c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            fPath.reset();
2956c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            fRRect = that.fRRect;
3056c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            break;
3156c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kPath_Type:
3256c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            fPath.set(that.getPath());
3356c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            break;
3456c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    }
3556c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks
3656c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    fSaveCount = that.fSaveCount;
3756c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    fOp = that.fOp;
3856c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    fType = that.fType;
3956c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    fDoAA = that.fDoAA;
4056c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    fFiniteBoundType = that.fFiniteBoundType;
4156c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    fFiniteBound = that.fFiniteBound;
4256c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    fIsIntersectionOfRects = that.fIsIntersectionOfRects;
4356c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    fGenID = that.fGenID;
4456c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks}
4556c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks
4656c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparksbool SkClipStack::Element::operator== (const Element& element) const {
4756c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    if (this == &element) {
4856c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        return true;
4956c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    }
5056c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    if (fOp != element.fOp ||
5156c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        fType != element.fType ||
5256c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        fDoAA != element.fDoAA ||
5356c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        fSaveCount != element.fSaveCount) {
5456c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        return false;
5556c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    }
5656c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    switch (fType) {
5756c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kPath_Type:
5856c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            return this->getPath() == element.getPath();
5956c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kRRect_Type:
6056c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            return fRRect == element.fRRect;
6156c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kRect_Type:
6256c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            return this->getRect() == element.getRect();
6356c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kEmpty_Type:
6456c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            return true;
6556c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        default:
6656c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            SkDEBUGFAIL("Unexpected type.");
6756c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            return false;
6856c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    }
6956c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks}
7056c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks
7156c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparksvoid SkClipStack::Element::replay(SkCanvasClipVisitor* visitor) const {
7256c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    static const SkRect kEmptyRect = { 0, 0, 0, 0 };
7356c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks
7456c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    switch (fType) {
7556c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kPath_Type:
7656c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            visitor->clipPath(this->getPath(), this->getOp(), this->isAA());
7756c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            break;
7856c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kRRect_Type:
7956c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            visitor->clipRRect(this->getRRect(), this->getOp(), this->isAA());
8056c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            break;
8156c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kRect_Type:
8256c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            visitor->clipRect(this->getRect(), this->getOp(), this->isAA());
8356c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            break;
8456c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kEmpty_Type:
8556c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            visitor->clipRect(kEmptyRect, SkRegion::kIntersect_Op, false);
8656c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            break;
8756c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    }
8856c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks}
8956c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks
9056c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparksvoid SkClipStack::Element::invertShapeFillType() {
9156c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    switch (fType) {
9256c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kRect_Type:
9356c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            fPath.init();
9456c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            fPath.get()->addRect(this->getRect());
9556c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            fPath.get()->setFillType(SkPath::kInverseEvenOdd_FillType);
9656c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            fType = kPath_Type;
9756c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            break;
9856c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kRRect_Type:
9956c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            fPath.init();
10056c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            fPath.get()->addRRect(fRRect);
10156c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            fPath.get()->setFillType(SkPath::kInverseEvenOdd_FillType);
10256c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            fType = kPath_Type;
10356c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            break;
10456c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kPath_Type:
10556c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            fPath.get()->toggleInverseFillType();
10656c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            break;
10756c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kEmpty_Type:
10856c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            // Should this set to an empty, inverse filled path?
10956c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            break;
11056c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    }
11156c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks}
11256c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks
11356c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparksvoid SkClipStack::Element::initPath(int saveCount, const SkPath& path, SkRegion::Op op,
11456c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks                                    bool doAA) {
11556c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    if (!path.isInverseFillType()) {
11656c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        SkRect r;
11756c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        if (path.isRect(&r)) {
11856c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            this->initRect(saveCount, r, op, doAA);
11956c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            return;
12056c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        }
12156c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        SkRect ovalRect;
12256c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        if (path.isOval(&ovalRect)) {
12356c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            SkRRect rrect;
12456c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            rrect.setOval(ovalRect);
12556c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            this->initRRect(saveCount, rrect, op, doAA);
12656c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            return;
12756c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        }
12856c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    }
12956c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    fPath.set(path);
13056c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    fPath.get()->setIsVolatile(true);
13156c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    fType = kPath_Type;
13256c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    this->initCommon(saveCount, op, doAA);
13356c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks}
13456c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks
13556c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparksvoid SkClipStack::Element::asPath(SkPath* path) const {
13656c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    switch (fType) {
13756c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kEmpty_Type:
13856c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            path->reset();
13956c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            break;
14056c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kRect_Type:
14156c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            path->reset();
14256c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            path->addRect(this->getRect());
14356c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            break;
14456c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kRRect_Type:
14556c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            path->reset();
14656c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            path->addRRect(fRRect);
14756c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            break;
14856c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks        case kPath_Type:
14956c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            *path = *fPath.get();
15056c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks            break;
15156c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    }
15256c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    path->setIsVolatile(true);
15356c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks}
15456c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks
15556c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparksvoid SkClipStack::Element::setEmpty() {
15656c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    fType = kEmpty_Type;
15756c99cd2c2c1e6ab038dac5fced5b92ccf11ff6cDave Sparks    fFiniteBound.setEmpty();
158    fFiniteBoundType = kNormal_BoundsType;
159    fIsIntersectionOfRects = false;
160    fRRect.setEmpty();
161    fPath.reset();
162    fGenID = kEmptyGenID;
163    SkDEBUGCODE(this->checkEmpty();)
164}
165
166void SkClipStack::Element::checkEmpty() const {
167    SkASSERT(fFiniteBound.isEmpty());
168    SkASSERT(kNormal_BoundsType == fFiniteBoundType);
169    SkASSERT(!fIsIntersectionOfRects);
170    SkASSERT(kEmptyGenID == fGenID);
171    SkASSERT(!fPath.isValid());
172}
173
174bool SkClipStack::Element::canBeIntersectedInPlace(int saveCount, SkRegion::Op op) const {
175    if (kEmpty_Type == fType &&
176        (SkRegion::kDifference_Op == op || SkRegion::kIntersect_Op == op)) {
177        return true;
178    }
179    // Only clips within the same save/restore frame (as captured by
180    // the save count) can be merged
181    return  fSaveCount == saveCount &&
182            SkRegion::kIntersect_Op == op &&
183            (SkRegion::kIntersect_Op == fOp || SkRegion::kReplace_Op == fOp);
184}
185
186bool SkClipStack::Element::rectRectIntersectAllowed(const SkRect& newR, bool newAA) const {
187    SkASSERT(kRect_Type == fType);
188
189    if (fDoAA == newAA) {
190        // if the AA setting is the same there is no issue
191        return true;
192    }
193
194    if (!SkRect::Intersects(this->getRect(), newR)) {
195        // The calling code will correctly set the result to the empty clip
196        return true;
197    }
198
199    if (this->getRect().contains(newR)) {
200        // if the new rect carves out a portion of the old one there is no
201        // issue
202        return true;
203    }
204
205    // So either the two overlap in some complex manner or newR contains oldR.
206    // In the first, case the edges will require different AA. In the second,
207    // the AA setting that would be carried forward is incorrect (e.g., oldR
208    // is AA while newR is BW but since newR contains oldR, oldR will be
209    // drawn BW) since the new AA setting will predominate.
210    return false;
211}
212
213// a mirror of combineBoundsRevDiff
214void SkClipStack::Element::combineBoundsDiff(FillCombo combination, const SkRect& prevFinite) {
215    switch (combination) {
216        case kInvPrev_InvCur_FillCombo:
217            // In this case the only pixels that can remain set
218            // are inside the current clip rect since the extensions
219            // to infinity of both clips cancel out and whatever
220            // is outside of the current clip is removed
221            fFiniteBoundType = kNormal_BoundsType;
222            break;
223        case kInvPrev_Cur_FillCombo:
224            // In this case the current op is finite so the only pixels
225            // that aren't set are whatever isn't set in the previous
226            // clip and whatever this clip carves out
227            fFiniteBound.join(prevFinite);
228            fFiniteBoundType = kInsideOut_BoundsType;
229            break;
230        case kPrev_InvCur_FillCombo:
231            // In this case everything outside of this clip's bound
232            // is erased, so the only pixels that can remain set
233            // occur w/in the intersection of the two finite bounds
234            if (!fFiniteBound.intersect(prevFinite)) {
235                this->setEmpty();
236            } else {
237                fFiniteBoundType = kNormal_BoundsType;
238            }
239            break;
240        case kPrev_Cur_FillCombo:
241            // The most conservative result bound is that of the
242            // prior clip. This could be wildly incorrect if the
243            // second clip either exactly matches the first clip
244            // (which should yield the empty set) or reduces the
245            // size of the prior bound (e.g., if the second clip
246            // exactly matched the bottom half of the prior clip).
247            // We ignore these two possibilities.
248            fFiniteBound = prevFinite;
249            break;
250        default:
251            SkDEBUGFAIL("SkClipStack::Element::combineBoundsDiff Invalid fill combination");
252            break;
253    }
254}
255
256void SkClipStack::Element::combineBoundsXOR(int combination, const SkRect& prevFinite) {
257
258    switch (combination) {
259        case kInvPrev_Cur_FillCombo:       // fall through
260        case kPrev_InvCur_FillCombo:
261            // With only one of the clips inverted the result will always
262            // extend to infinity. The only pixels that may be un-writeable
263            // lie within the union of the two finite bounds
264            fFiniteBound.join(prevFinite);
265            fFiniteBoundType = kInsideOut_BoundsType;
266            break;
267        case kInvPrev_InvCur_FillCombo:
268            // The only pixels that can survive are within the
269            // union of the two bounding boxes since the extensions
270            // to infinity of both clips cancel out
271            // fall through!
272        case kPrev_Cur_FillCombo:
273            // The most conservative bound for xor is the
274            // union of the two bounds. If the two clips exactly overlapped
275            // the xor could yield the empty set. Similarly the xor
276            // could reduce the size of the original clip's bound (e.g.,
277            // if the second clip exactly matched the bottom half of the
278            // first clip). We ignore these two cases.
279            fFiniteBound.join(prevFinite);
280            fFiniteBoundType = kNormal_BoundsType;
281            break;
282        default:
283            SkDEBUGFAIL("SkClipStack::Element::combineBoundsXOR Invalid fill combination");
284            break;
285    }
286}
287
288// a mirror of combineBoundsIntersection
289void SkClipStack::Element::combineBoundsUnion(int combination, const SkRect& prevFinite) {
290
291    switch (combination) {
292        case kInvPrev_InvCur_FillCombo:
293            if (!fFiniteBound.intersect(prevFinite)) {
294                fFiniteBound.setEmpty();
295                fGenID = kWideOpenGenID;
296            }
297            fFiniteBoundType = kInsideOut_BoundsType;
298            break;
299        case kInvPrev_Cur_FillCombo:
300            // The only pixels that won't be drawable are inside
301            // the prior clip's finite bound
302            fFiniteBound = prevFinite;
303            fFiniteBoundType = kInsideOut_BoundsType;
304            break;
305        case kPrev_InvCur_FillCombo:
306            // The only pixels that won't be drawable are inside
307            // this clip's finite bound
308            break;
309        case kPrev_Cur_FillCombo:
310            fFiniteBound.join(prevFinite);
311            break;
312        default:
313            SkDEBUGFAIL("SkClipStack::Element::combineBoundsUnion Invalid fill combination");
314            break;
315    }
316}
317
318// a mirror of combineBoundsUnion
319void SkClipStack::Element::combineBoundsIntersection(int combination, const SkRect& prevFinite) {
320
321    switch (combination) {
322        case kInvPrev_InvCur_FillCombo:
323            // The only pixels that aren't writable in this case
324            // occur in the union of the two finite bounds
325            fFiniteBound.join(prevFinite);
326            fFiniteBoundType = kInsideOut_BoundsType;
327            break;
328        case kInvPrev_Cur_FillCombo:
329            // In this case the only pixels that will remain writeable
330            // are within the current clip
331            break;
332        case kPrev_InvCur_FillCombo:
333            // In this case the only pixels that will remain writeable
334            // are with the previous clip
335            fFiniteBound = prevFinite;
336            fFiniteBoundType = kNormal_BoundsType;
337            break;
338        case kPrev_Cur_FillCombo:
339            if (!fFiniteBound.intersect(prevFinite)) {
340                this->setEmpty();
341            }
342            break;
343        default:
344            SkDEBUGFAIL("SkClipStack::Element::combineBoundsIntersection Invalid fill combination");
345            break;
346    }
347}
348
349// a mirror of combineBoundsDiff
350void SkClipStack::Element::combineBoundsRevDiff(int combination, const SkRect& prevFinite) {
351
352    switch (combination) {
353        case kInvPrev_InvCur_FillCombo:
354            // The only pixels that can survive are in the
355            // previous bound since the extensions to infinity in
356            // both clips cancel out
357            fFiniteBound = prevFinite;
358            fFiniteBoundType = kNormal_BoundsType;
359            break;
360        case kInvPrev_Cur_FillCombo:
361            if (!fFiniteBound.intersect(prevFinite)) {
362                this->setEmpty();
363            } else {
364                fFiniteBoundType = kNormal_BoundsType;
365            }
366            break;
367        case kPrev_InvCur_FillCombo:
368            fFiniteBound.join(prevFinite);
369            fFiniteBoundType = kInsideOut_BoundsType;
370            break;
371        case kPrev_Cur_FillCombo:
372            // Fall through - as with the kDifference_Op case, the
373            // most conservative result bound is the bound of the
374            // current clip. The prior clip could reduce the size of this
375            // bound (as in the kDifference_Op case) but we are ignoring
376            // those cases.
377            break;
378        default:
379            SkDEBUGFAIL("SkClipStack::Element::combineBoundsRevDiff Invalid fill combination");
380            break;
381    }
382}
383
384void SkClipStack::Element::updateBoundAndGenID(const Element* prior) {
385    // We set this first here but we may overwrite it later if we determine that the clip is
386    // either wide-open or empty.
387    fGenID = GetNextGenID();
388
389    // First, optimistically update the current Element's bound information
390    // with the current clip's bound
391    fIsIntersectionOfRects = false;
392    switch (fType) {
393        case kRect_Type:
394            fFiniteBound = this->getRect();
395            fFiniteBoundType = kNormal_BoundsType;
396
397            if (SkRegion::kReplace_Op == fOp ||
398                (SkRegion::kIntersect_Op == fOp && NULL == prior) ||
399                (SkRegion::kIntersect_Op == fOp && prior->fIsIntersectionOfRects &&
400                    prior->rectRectIntersectAllowed(this->getRect(), fDoAA))) {
401                fIsIntersectionOfRects = true;
402            }
403            break;
404        case kRRect_Type:
405            fFiniteBound = fRRect.getBounds();
406            fFiniteBoundType = kNormal_BoundsType;
407            break;
408        case kPath_Type:
409            fFiniteBound = fPath.get()->getBounds();
410
411            if (fPath.get()->isInverseFillType()) {
412                fFiniteBoundType = kInsideOut_BoundsType;
413            } else {
414                fFiniteBoundType = kNormal_BoundsType;
415            }
416            break;
417        case kEmpty_Type:
418            SkDEBUGFAIL("We shouldn't get here with an empty element.");
419            break;
420    }
421
422    if (!fDoAA) {
423        fFiniteBound.set(SkScalarFloorToScalar(fFiniteBound.fLeft+0.45f),
424                         SkScalarRoundToScalar(fFiniteBound.fTop),
425                         SkScalarRoundToScalar(fFiniteBound.fRight),
426                         SkScalarRoundToScalar(fFiniteBound.fBottom));
427    }
428
429    // Now determine the previous Element's bound information taking into
430    // account that there may be no previous clip
431    SkRect prevFinite;
432    SkClipStack::BoundsType prevType;
433
434    if (NULL == prior) {
435        // no prior clip means the entire plane is writable
436        prevFinite.setEmpty();   // there are no pixels that cannot be drawn to
437        prevType = kInsideOut_BoundsType;
438    } else {
439        prevFinite = prior->fFiniteBound;
440        prevType = prior->fFiniteBoundType;
441    }
442
443    FillCombo combination = kPrev_Cur_FillCombo;
444    if (kInsideOut_BoundsType == fFiniteBoundType) {
445        combination = (FillCombo) (combination | 0x01);
446    }
447    if (kInsideOut_BoundsType == prevType) {
448        combination = (FillCombo) (combination | 0x02);
449    }
450
451    SkASSERT(kInvPrev_InvCur_FillCombo == combination ||
452                kInvPrev_Cur_FillCombo == combination ||
453                kPrev_InvCur_FillCombo == combination ||
454                kPrev_Cur_FillCombo == combination);
455
456    // Now integrate with clip with the prior clips
457    switch (fOp) {
458        case SkRegion::kDifference_Op:
459            this->combineBoundsDiff(combination, prevFinite);
460            break;
461        case SkRegion::kXOR_Op:
462            this->combineBoundsXOR(combination, prevFinite);
463            break;
464        case SkRegion::kUnion_Op:
465            this->combineBoundsUnion(combination, prevFinite);
466            break;
467        case SkRegion::kIntersect_Op:
468            this->combineBoundsIntersection(combination, prevFinite);
469            break;
470        case SkRegion::kReverseDifference_Op:
471            this->combineBoundsRevDiff(combination, prevFinite);
472            break;
473        case SkRegion::kReplace_Op:
474            // Replace just ignores everything prior
475            // The current clip's bound information is already filled in
476            // so nothing to do
477            break;
478        default:
479            SkDebugf("SkRegion::Op error\n");
480            SkASSERT(0);
481            break;
482    }
483}
484
485// This constant determines how many Element's are allocated together as a block in
486// the deque. As such it needs to balance allocating too much memory vs.
487// incurring allocation/deallocation thrashing. It should roughly correspond to
488// the deepest save/restore stack we expect to see.
489static const int kDefaultElementAllocCnt = 8;
490
491SkClipStack::SkClipStack()
492    : fDeque(sizeof(Element), kDefaultElementAllocCnt)
493    , fSaveCount(0) {
494}
495
496SkClipStack::SkClipStack(const SkClipStack& b)
497    : fDeque(sizeof(Element), kDefaultElementAllocCnt) {
498    *this = b;
499}
500
501SkClipStack::SkClipStack(const SkRect& r)
502    : fDeque(sizeof(Element), kDefaultElementAllocCnt)
503    , fSaveCount(0) {
504    if (!r.isEmpty()) {
505        this->clipDevRect(r, SkRegion::kReplace_Op, false);
506    }
507}
508
509SkClipStack::SkClipStack(const SkIRect& r)
510    : fDeque(sizeof(Element), kDefaultElementAllocCnt)
511    , fSaveCount(0) {
512    if (!r.isEmpty()) {
513        SkRect temp;
514        temp.set(r);
515        this->clipDevRect(temp, SkRegion::kReplace_Op, false);
516    }
517}
518
519SkClipStack::~SkClipStack() {
520    reset();
521}
522
523SkClipStack& SkClipStack::operator=(const SkClipStack& b) {
524    if (this == &b) {
525        return *this;
526    }
527    reset();
528
529    fSaveCount = b.fSaveCount;
530    SkDeque::F2BIter recIter(b.fDeque);
531    for (const Element* element = (const Element*)recIter.next();
532         element != NULL;
533         element = (const Element*)recIter.next()) {
534        new (fDeque.push_back()) Element(*element);
535    }
536
537    return *this;
538}
539
540bool SkClipStack::operator==(const SkClipStack& b) const {
541    if (this->getTopmostGenID() == b.getTopmostGenID()) {
542        return true;
543    }
544    if (fSaveCount != b.fSaveCount ||
545        fDeque.count() != b.fDeque.count()) {
546        return false;
547    }
548    SkDeque::F2BIter myIter(fDeque);
549    SkDeque::F2BIter bIter(b.fDeque);
550    const Element* myElement = (const Element*)myIter.next();
551    const Element* bElement = (const Element*)bIter.next();
552
553    while (myElement != NULL && bElement != NULL) {
554        if (*myElement != *bElement) {
555            return false;
556        }
557        myElement = (const Element*)myIter.next();
558        bElement = (const Element*)bIter.next();
559    }
560    return myElement == NULL && bElement == NULL;
561}
562
563void SkClipStack::reset() {
564    // We used a placement new for each object in fDeque, so we're responsible
565    // for calling the destructor on each of them as well.
566    while (!fDeque.empty()) {
567        Element* element = (Element*)fDeque.back();
568        element->~Element();
569        fDeque.pop_back();
570    }
571
572    fSaveCount = 0;
573}
574
575void SkClipStack::save() {
576    fSaveCount += 1;
577}
578
579void SkClipStack::restore() {
580    fSaveCount -= 1;
581    restoreTo(fSaveCount);
582}
583
584void SkClipStack::restoreTo(int saveCount) {
585    while (!fDeque.empty()) {
586        Element* element = (Element*)fDeque.back();
587        if (element->fSaveCount <= saveCount) {
588            break;
589        }
590        element->~Element();
591        fDeque.pop_back();
592    }
593}
594
595void SkClipStack::getBounds(SkRect* canvFiniteBound,
596                            BoundsType* boundType,
597                            bool* isIntersectionOfRects) const {
598    SkASSERT(canvFiniteBound && boundType);
599
600    Element* element = (Element*)fDeque.back();
601
602    if (NULL == element) {
603        // the clip is wide open - the infinite plane w/ no pixels un-writeable
604        canvFiniteBound->setEmpty();
605        *boundType = kInsideOut_BoundsType;
606        if (isIntersectionOfRects) {
607            *isIntersectionOfRects = false;
608        }
609        return;
610    }
611
612    *canvFiniteBound = element->fFiniteBound;
613    *boundType = element->fFiniteBoundType;
614    if (isIntersectionOfRects) {
615        *isIntersectionOfRects = element->fIsIntersectionOfRects;
616    }
617}
618
619bool SkClipStack::quickContains(const SkRect& rect) const {
620
621    Iter iter(*this, Iter::kTop_IterStart);
622    const Element* element = iter.prev();
623    while (element != NULL) {
624        if (SkRegion::kIntersect_Op != element->getOp() && SkRegion::kReplace_Op != element->getOp())
625            return false;
626        if (element->isInverseFilled()) {
627            // Part of 'rect' could be trimmed off by the inverse-filled clip element
628            if (SkRect::Intersects(element->getBounds(), rect)) {
629                return false;
630            }
631        } else {
632            if (!element->contains(rect)) {
633                return false;
634            }
635        }
636        if (SkRegion::kReplace_Op == element->getOp()) {
637            break;
638        }
639        element = iter.prev();
640    }
641    return true;
642}
643
644bool SkClipStack::asPath(SkPath *path) const {
645    bool isAA = false;
646
647    path->reset();
648    path->setFillType(SkPath::kInverseEvenOdd_FillType);
649
650    SkClipStack::Iter iter(*this, SkClipStack::Iter::kBottom_IterStart);
651    while (const SkClipStack::Element* element = iter.next()) {
652        SkPath operand;
653        if (element->getType() != SkClipStack::Element::kEmpty_Type) {
654            element->asPath(&operand);
655        }
656
657        SkRegion::Op elementOp = element->getOp();
658        if (elementOp == SkRegion::kReplace_Op) {
659            *path = operand;
660        } else {
661            Op(*path, operand, (SkPathOp)elementOp, path);
662        }
663
664        // if the prev and curr clips disagree about aa -vs- not, favor the aa request.
665        // perhaps we need an API change to avoid this sort of mixed-signals about
666        // clipping.
667        isAA = (isAA || element->isAA());
668    }
669
670    return isAA;
671}
672
673void SkClipStack::pushElement(const Element& element) {
674    // Use reverse iterator instead of back because Rect path may need previous
675    SkDeque::Iter iter(fDeque, SkDeque::Iter::kBack_IterStart);
676    Element* prior = (Element*) iter.prev();
677
678    if (prior) {
679        if (prior->canBeIntersectedInPlace(fSaveCount, element.getOp())) {
680            switch (prior->fType) {
681                case Element::kEmpty_Type:
682                    SkDEBUGCODE(prior->checkEmpty();)
683                    return;
684                case Element::kRect_Type:
685                    if (Element::kRect_Type == element.getType()) {
686                        if (prior->rectRectIntersectAllowed(element.getRect(), element.isAA())) {
687                            SkRect isectRect;
688                            if (!isectRect.intersect(prior->getRect(), element.getRect())) {
689                                prior->setEmpty();
690                                return;
691                            }
692
693                            prior->fRRect.setRect(isectRect);
694                            prior->fDoAA = element.isAA();
695                            Element* priorPrior = (Element*) iter.prev();
696                            prior->updateBoundAndGenID(priorPrior);
697                            return;
698                        }
699                        break;
700                    }
701                    // fallthrough
702                default:
703                    if (!SkRect::Intersects(prior->getBounds(), element.getBounds())) {
704                        prior->setEmpty();
705                        return;
706                    }
707                    break;
708            }
709        } else if (SkRegion::kReplace_Op == element.getOp()) {
710            this->restoreTo(fSaveCount - 1);
711            prior = (Element*) fDeque.back();
712        }
713    }
714    Element* newElement = SkNEW_PLACEMENT_ARGS(fDeque.push_back(), Element, (element));
715    newElement->updateBoundAndGenID(prior);
716}
717
718void SkClipStack::clipDevRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
719    Element element(fSaveCount, rrect, op, doAA);
720    this->pushElement(element);
721}
722
723void SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
724    Element element(fSaveCount, rect, op, doAA);
725    this->pushElement(element);
726}
727
728void SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) {
729    Element element(fSaveCount, path, op, doAA);
730    this->pushElement(element);
731}
732
733void SkClipStack::clipEmpty() {
734    Element* element = (Element*) fDeque.back();
735
736    if (element && element->canBeIntersectedInPlace(fSaveCount, SkRegion::kIntersect_Op)) {
737        element->setEmpty();
738    }
739    new (fDeque.push_back()) Element(fSaveCount);
740
741    ((Element*)fDeque.back())->fGenID = kEmptyGenID;
742}
743
744bool SkClipStack::isWideOpen() const {
745    return this->getTopmostGenID() == kWideOpenGenID;
746}
747
748///////////////////////////////////////////////////////////////////////////////
749
750SkClipStack::Iter::Iter() : fStack(NULL) {
751}
752
753SkClipStack::Iter::Iter(const SkClipStack& stack, IterStart startLoc)
754    : fStack(&stack) {
755    this->reset(stack, startLoc);
756}
757
758const SkClipStack::Element* SkClipStack::Iter::next() {
759    return (const SkClipStack::Element*)fIter.next();
760}
761
762const SkClipStack::Element* SkClipStack::Iter::prev() {
763    return (const SkClipStack::Element*)fIter.prev();
764}
765
766const SkClipStack::Element* SkClipStack::Iter::skipToTopmost(SkRegion::Op op) {
767
768    if (NULL == fStack) {
769        return NULL;
770    }
771
772    fIter.reset(fStack->fDeque, SkDeque::Iter::kBack_IterStart);
773
774    const SkClipStack::Element* element = NULL;
775
776    for (element = (const SkClipStack::Element*) fIter.prev();
777         element;
778         element = (const SkClipStack::Element*) fIter.prev()) {
779
780        if (op == element->fOp) {
781            // The Deque's iterator is actually one pace ahead of the
782            // returned value. So while "element" is the element we want to
783            // return, the iterator is actually pointing at (and will
784            // return on the next "next" or "prev" call) the element
785            // in front of it in the deque. Bump the iterator forward a
786            // step so we get the expected result.
787            if (NULL == fIter.next()) {
788                // The reverse iterator has run off the front of the deque
789                // (i.e., the "op" clip is the first clip) and can't
790                // recover. Reset the iterator to start at the front.
791                fIter.reset(fStack->fDeque, SkDeque::Iter::kFront_IterStart);
792            }
793            break;
794        }
795    }
796
797    if (NULL == element) {
798        // There were no "op" clips
799        fIter.reset(fStack->fDeque, SkDeque::Iter::kFront_IterStart);
800    }
801
802    return this->next();
803}
804
805void SkClipStack::Iter::reset(const SkClipStack& stack, IterStart startLoc) {
806    fStack = &stack;
807    fIter.reset(stack.fDeque, static_cast<SkDeque::Iter::IterStart>(startLoc));
808}
809
810// helper method
811void SkClipStack::getConservativeBounds(int offsetX,
812                                        int offsetY,
813                                        int maxWidth,
814                                        int maxHeight,
815                                        SkRect* devBounds,
816                                        bool* isIntersectionOfRects) const {
817    SkASSERT(devBounds);
818
819    devBounds->setLTRB(0, 0,
820                       SkIntToScalar(maxWidth), SkIntToScalar(maxHeight));
821
822    SkRect temp;
823    SkClipStack::BoundsType boundType;
824
825    // temp starts off in canvas space here
826    this->getBounds(&temp, &boundType, isIntersectionOfRects);
827    if (SkClipStack::kInsideOut_BoundsType == boundType) {
828        return;
829    }
830
831    // but is converted to device space here
832    temp.offset(SkIntToScalar(offsetX), SkIntToScalar(offsetY));
833
834    if (!devBounds->intersect(temp)) {
835        devBounds->setEmpty();
836    }
837}
838
839int32_t SkClipStack::GetNextGenID() {
840    // TODO: handle overflow.
841    return sk_atomic_inc(&gGenID);
842}
843
844int32_t SkClipStack::getTopmostGenID() const {
845    if (fDeque.empty()) {
846        return kWideOpenGenID;
847    }
848
849    const Element* back = static_cast<const Element*>(fDeque.back());
850    if (kInsideOut_BoundsType == back->fFiniteBoundType && back->fFiniteBound.isEmpty()) {
851        return kWideOpenGenID;
852    }
853
854    return back->getGenID();
855}
856
857#ifdef SK_DEVELOPER
858void SkClipStack::Element::dump() const {
859    static const char* kTypeStrings[] = {
860        "empty",
861        "rect",
862        "rrect",
863        "path"
864    };
865    SK_COMPILE_ASSERT(0 == kEmpty_Type, type_str);
866    SK_COMPILE_ASSERT(1 == kRect_Type, type_str);
867    SK_COMPILE_ASSERT(2 == kRRect_Type, type_str);
868    SK_COMPILE_ASSERT(3 == kPath_Type, type_str);
869    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(kTypeStrings) == kTypeCnt, type_str);
870
871    static const char* kOpStrings[] = {
872        "difference",
873        "intersect",
874        "union",
875        "xor",
876        "reverse-difference",
877        "replace",
878    };
879    SK_COMPILE_ASSERT(0 == SkRegion::kDifference_Op, op_str);
880    SK_COMPILE_ASSERT(1 == SkRegion::kIntersect_Op, op_str);
881    SK_COMPILE_ASSERT(2 == SkRegion::kUnion_Op, op_str);
882    SK_COMPILE_ASSERT(3 == SkRegion::kXOR_Op, op_str);
883    SK_COMPILE_ASSERT(4 == SkRegion::kReverseDifference_Op, op_str);
884    SK_COMPILE_ASSERT(5 == SkRegion::kReplace_Op, op_str);
885    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(kOpStrings) == SkRegion::kOpCnt, op_str);
886
887    SkDebugf("Type: %s, Op: %s, AA: %s, Save Count: %d\n", kTypeStrings[fType],
888             kOpStrings[fOp], (fDoAA ? "yes" : "no"), fSaveCount);
889    switch (fType) {
890        case kEmpty_Type:
891            SkDebugf("\n");
892            break;
893        case kRect_Type:
894            this->getRect().dump();
895            SkDebugf("\n");
896            break;
897        case kRRect_Type:
898            this->getRRect().dump();
899            SkDebugf("\n");
900            break;
901        case kPath_Type:
902            this->getPath().dump(NULL, true, false);
903            break;
904    }
905}
906
907void SkClipStack::dump() const {
908    B2TIter iter(*this);
909    const Element* e;
910    while ((e = iter.next())) {
911        e->dump();
912        SkDebugf("\n");
913    }
914}
915#endif
916