180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc.
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkClipStack.h"
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPath.h"
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkThread.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <new>
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// 0-2 are reserved for invalid, empty & wide-open
16363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic const int32_t kFirstUnreservedGenID = 3;
17363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerint32_t SkClipStack::gGenID = kFirstUnreservedGenID;
18363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
19363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkClipStack::Element::invertShapeFillType() {
20363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    switch (fType) {
21363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kRect_Type:
22363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fPath.reset();
23363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fPath.addRect(fRect);
24363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fPath.setFillType(SkPath::kInverseWinding_FillType);
25363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fType = kPath_Type;
26363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
27363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kPath_Type:
28363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fPath.toggleInverseFillType();
29363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kEmpty_Type:
30363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
32363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkClipStack::Element::checkEmpty() const {
35363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(fFiniteBound.isEmpty());
36363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(kNormal_BoundsType == fFiniteBoundType);
37363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(!fIsIntersectionOfRects);
38363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(kEmptyGenID == fGenID);
39363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(fPath.isEmpty());
40363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool SkClipStack::Element::canBeIntersectedInPlace(int saveCount, SkRegion::Op op) const {
43363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (kEmpty_Type == fType &&
44363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        (SkRegion::kDifference_Op == op || SkRegion::kIntersect_Op == op)) {
45363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return true;
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
47363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // Only clips within the same save/restore frame (as captured by
48363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // the save count) can be merged
49363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return  fSaveCount == saveCount &&
50363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkRegion::kIntersect_Op == op &&
51363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            (SkRegion::kIntersect_Op == fOp || SkRegion::kReplace_Op == fOp);
52363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
54363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool SkClipStack::Element::rectRectIntersectAllowed(const SkRect& newR, bool newAA) const {
55363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(kRect_Type == fType);
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
57363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (fDoAA == newAA) {
58363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // if the AA setting is the same there is no issue
59363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return true;
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
62363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (!SkRect::Intersects(fRect, newR)) {
63363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // The calling code will correctly set the result to the empty clip
64363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return true;
65363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
67363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (fRect.contains(newR)) {
68363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // if the new rect carves out a portion of the old one there is no
69363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // issue
70363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return true;
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
73363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // So either the two overlap in some complex manner or newR contains oldR.
74363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // In the first, case the edges will require different AA. In the second,
75363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // the AA setting that would be carried forward is incorrect (e.g., oldR
76363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // is AA while newR is BW but since newR contains oldR, oldR will be
77363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // drawn BW) since the new AA setting will predominate.
78363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return false;
79363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
81363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger// a mirror of combineBoundsRevDiff
82363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkClipStack::Element::combineBoundsDiff(FillCombo combination, const SkRect& prevFinite) {
83363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    switch (combination) {
84363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kInvPrev_InvCur_FillCombo:
85363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // In this case the only pixels that can remain set
86363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // are inside the current clip rect since the extensions
87363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // to infinity of both clips cancel out and whatever
88363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // is outside of the current clip is removed
89363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBoundType = kNormal_BoundsType;
90363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
91363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kInvPrev_Cur_FillCombo:
92363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // In this case the current op is finite so the only pixels
93363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // that aren't set are whatever isn't set in the previous
94363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // clip and whatever this clip carves out
95363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBound.join(prevFinite);
96363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBoundType = kInsideOut_BoundsType;
97363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
98363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kPrev_InvCur_FillCombo:
99363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // In this case everything outside of this clip's bound
100363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // is erased, so the only pixels that can remain set
101363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // occur w/in the intersection of the two finite bounds
102363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            if (!fFiniteBound.intersect(prevFinite)) {
103363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                fFiniteBound.setEmpty();
104363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                fGenID = kEmptyGenID;
105363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
106363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBoundType = kNormal_BoundsType;
107363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
108363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kPrev_Cur_FillCombo:
109363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // The most conservative result bound is that of the
110363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // prior clip. This could be wildly incorrect if the
111363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // second clip either exactly matches the first clip
112363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // (which should yield the empty set) or reduces the
113363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // size of the prior bound (e.g., if the second clip
114363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // exactly matched the bottom half of the prior clip).
115363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // We ignore these two possibilities.
116363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBound = prevFinite;
117363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
118363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        default:
119363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkDEBUGFAIL("SkClipStack::Element::combineBoundsDiff Invalid fill combination");
120363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
122363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
124363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkClipStack::Element::combineBoundsXOR(int combination, const SkRect& prevFinite) {
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
126363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    switch (combination) {
127363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kInvPrev_Cur_FillCombo:       // fall through
128363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kPrev_InvCur_FillCombo:
129363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // With only one of the clips inverted the result will always
130363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // extend to infinity. The only pixels that may be un-writeable
131363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // lie within the union of the two finite bounds
132363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBound.join(prevFinite);
133363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBoundType = kInsideOut_BoundsType;
134363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
135363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kInvPrev_InvCur_FillCombo:
136363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // The only pixels that can survive are within the
137363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // union of the two bounding boxes since the extensions
138363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // to infinity of both clips cancel out
139363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // fall through!
140363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kPrev_Cur_FillCombo:
141363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // The most conservative bound for xor is the
142363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // union of the two bounds. If the two clips exactly overlapped
143363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // the xor could yield the empty set. Similarly the xor
144363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // could reduce the size of the original clip's bound (e.g.,
145363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // if the second clip exactly matched the bottom half of the
146363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // first clip). We ignore these two cases.
147363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBound.join(prevFinite);
148363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBoundType = kNormal_BoundsType;
149363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
150363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        default:
151363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkDEBUGFAIL("SkClipStack::Element::combineBoundsXOR Invalid fill combination");
152363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
154363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
156363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger// a mirror of combineBoundsIntersection
157363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkClipStack::Element::combineBoundsUnion(int combination, const SkRect& prevFinite) {
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
159363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    switch (combination) {
160363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kInvPrev_InvCur_FillCombo:
161363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            if (!fFiniteBound.intersect(prevFinite)) {
162363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                fFiniteBound.setEmpty();
163363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                fGenID = kWideOpenGenID;
164363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
165363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBoundType = kInsideOut_BoundsType;
166363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
167363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kInvPrev_Cur_FillCombo:
168363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // The only pixels that won't be drawable are inside
169363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // the prior clip's finite bound
170363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBound = prevFinite;
171363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBoundType = kInsideOut_BoundsType;
172363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
173363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kPrev_InvCur_FillCombo:
174363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // The only pixels that won't be drawable are inside
175363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // this clip's finite bound
176363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
177363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kPrev_Cur_FillCombo:
178363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBound.join(prevFinite);
179363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
180363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        default:
181363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkDEBUGFAIL("SkClipStack::Element::combineBoundsUnion Invalid fill combination");
182363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
184363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
186363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger// a mirror of combineBoundsUnion
187363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkClipStack::Element::combineBoundsIntersection(int combination, const SkRect& prevFinite) {
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
189363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    switch (combination) {
190363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kInvPrev_InvCur_FillCombo:
191363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // The only pixels that aren't writable in this case
192363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // occur in the union of the two finite bounds
193363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBound.join(prevFinite);
194363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBoundType = kInsideOut_BoundsType;
195363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
196363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kInvPrev_Cur_FillCombo:
197363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // In this case the only pixels that will remain writeable
198363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // are within the current clip
199363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
200363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kPrev_InvCur_FillCombo:
201363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // In this case the only pixels that will remain writeable
202363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // are with the previous clip
203363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBound = prevFinite;
204363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBoundType = kNormal_BoundsType;
205363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
206363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kPrev_Cur_FillCombo:
207363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            if (!fFiniteBound.intersect(prevFinite)) {
208363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                fFiniteBound.setEmpty();
209363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                fGenID = kEmptyGenID;
210363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
211363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
212363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        default:
213363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkDEBUGFAIL("SkClipStack::Element::combineBoundsIntersection Invalid fill combination");
214363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
21580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
216363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
21780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
218363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger// a mirror of combineBoundsDiff
219363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkClipStack::Element::combineBoundsRevDiff(int combination, const SkRect& prevFinite) {
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
221363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    switch (combination) {
222363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kInvPrev_InvCur_FillCombo:
223363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // The only pixels that can survive are in the
224363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // previous bound since the extensions to infinity in
225363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // both clips cancel out
226363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBound = prevFinite;
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            fFiniteBoundType = kNormal_BoundsType;
228363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
229363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kInvPrev_Cur_FillCombo:
230363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            if (!fFiniteBound.intersect(prevFinite)) {
231363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                fFiniteBound.setEmpty();
232363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                fGenID = kEmptyGenID;
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
234363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBoundType = kNormal_BoundsType;
235363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
236363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kPrev_InvCur_FillCombo:
237363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBound.join(prevFinite);
238363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBoundType = kInsideOut_BoundsType;
239363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
240363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case kPrev_Cur_FillCombo:
241363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // Fall through - as with the kDifference_Op case, the
242363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // most conservative result bound is the bound of the
243363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // current clip. The prior clip could reduce the size of this
244363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // bound (as in the kDifference_Op case) but we are ignoring
245363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // those cases.
246363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
247363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        default:
248363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkDEBUGFAIL("SkClipStack::Element::combineBoundsRevDiff Invalid fill combination");
249363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
250363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
251363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
253363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkClipStack::Element::updateBoundAndGenID(const Element* prior) {
254363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // We set this first here but we may overwrite it later if we determine that the clip is
255363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // either wide-open or empty.
256363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    fGenID = GetNextGenID();
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
258363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // First, optimistically update the current Element's bound information
259363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // with the current clip's bound
260363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    fIsIntersectionOfRects = false;
261363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (kRect_Type == fType) {
262363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fFiniteBound = fRect;
263363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fFiniteBoundType = kNormal_BoundsType;
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
265363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (SkRegion::kReplace_Op == fOp ||
266363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            (SkRegion::kIntersect_Op == fOp && NULL == prior) ||
267363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            (SkRegion::kIntersect_Op == fOp && prior->fIsIntersectionOfRects &&
268363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                prior->rectRectIntersectAllowed(fRect, fDoAA))) {
269363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fIsIntersectionOfRects = true;
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
272363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    } else {
273363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkASSERT(kPath_Type == fType);
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
275363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fFiniteBound = fPath.getBounds();
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
277363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (fPath.isInverseFillType()) {
278363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBoundType = kInsideOut_BoundsType;
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
280363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBoundType = kNormal_BoundsType;
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
282363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
284363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (!fDoAA) {
285363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // Here we mimic a non-anti-aliased scanline system. If there is
286363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // no anti-aliasing we can integerize the bounding box to exclude
287363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // fractional parts that won't be rendered.
288363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // Note: the left edge is handled slightly differently below. We
289363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // are a bit more generous in the rounding since we don't want to
290363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // risk missing the left pixels when fLeft is very close to .5
291363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        fFiniteBound.set(SkIntToScalar(SkScalarFloorToInt(fFiniteBound.fLeft+0.45f)),
292363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                         SkIntToScalar(SkScalarRound(fFiniteBound.fTop)),
293363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                         SkIntToScalar(SkScalarRound(fFiniteBound.fRight)),
294363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                         SkIntToScalar(SkScalarRound(fFiniteBound.fBottom)));
295363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
296363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
297363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // Now determine the previous Element's bound information taking into
298363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // account that there may be no previous clip
299363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkRect prevFinite;
300363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkClipStack::BoundsType prevType;
301363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
302363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (NULL == prior) {
303363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // no prior clip means the entire plane is writable
304363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        prevFinite.setEmpty();   // there are no pixels that cannot be drawn to
305363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        prevType = kInsideOut_BoundsType;
306363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    } else {
307363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        prevFinite = prior->fFiniteBound;
308363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        prevType = prior->fFiniteBoundType;
309363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
311363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    FillCombo combination = kPrev_Cur_FillCombo;
312363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (kInsideOut_BoundsType == fFiniteBoundType) {
313363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        combination = (FillCombo) (combination | 0x01);
314363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
315363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (kInsideOut_BoundsType == prevType) {
316363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        combination = (FillCombo) (combination | 0x02);
317363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
319363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(kInvPrev_InvCur_FillCombo == combination ||
320363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                kInvPrev_Cur_FillCombo == combination ||
321363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                kPrev_InvCur_FillCombo == combination ||
322363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                kPrev_Cur_FillCombo == combination);
323363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
324363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // Now integrate with clip with the prior clips
325363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    switch (fOp) {
326363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case SkRegion::kDifference_Op:
327363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->combineBoundsDiff(combination, prevFinite);
328363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
329363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case SkRegion::kXOR_Op:
330363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->combineBoundsXOR(combination, prevFinite);
331363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
332363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case SkRegion::kUnion_Op:
333363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->combineBoundsUnion(combination, prevFinite);
334363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
335363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case SkRegion::kIntersect_Op:
336363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->combineBoundsIntersection(combination, prevFinite);
337363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
338363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case SkRegion::kReverseDifference_Op:
339363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->combineBoundsRevDiff(combination, prevFinite);
340363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
341363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        case SkRegion::kReplace_Op:
342363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // Replace just ignores everything prior
343363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // The current clip's bound information is already filled in
344363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // so nothing to do
345363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
346363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        default:
347363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkDebugf("SkRegion::Op error/n");
348363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            SkASSERT(0);
349363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
35080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
351363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
353363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger// This constant determines how many Element's are allocated together as a block in
35480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// the deque. As such it needs to balance allocating too much memory vs.
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// incurring allocation/deallocation thrashing. It should roughly correspond to
35680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// the deepest save/restore stack we expect to see.
357363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerstatic const int kDefaultElementAllocCnt = 8;
35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkClipStack::SkClipStack()
360363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    : fDeque(sizeof(Element), kDefaultElementAllocCnt)
36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    , fSaveCount(0) {
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkClipStack::SkClipStack(const SkClipStack& b)
365363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    : fDeque(sizeof(Element), kDefaultElementAllocCnt) {
36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    *this = b;
36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkClipStack::SkClipStack(const SkRect& r)
370363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    : fDeque(sizeof(Element), kDefaultElementAllocCnt)
37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    , fSaveCount(0) {
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!r.isEmpty()) {
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->clipDevRect(r, SkRegion::kReplace_Op, false);
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkClipStack::SkClipStack(const SkIRect& r)
378363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    : fDeque(sizeof(Element), kDefaultElementAllocCnt)
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    , fSaveCount(0) {
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!r.isEmpty()) {
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkRect temp;
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        temp.set(r);
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->clipDevRect(temp, SkRegion::kReplace_Op, false);
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkClipStack::~SkClipStack() {
38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    reset();
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkClipStack& SkClipStack::operator=(const SkClipStack& b) {
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (this == &b) {
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return *this;
39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    reset();
39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fSaveCount = b.fSaveCount;
39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDeque::F2BIter recIter(b.fDeque);
399363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (const Element* element = (const Element*)recIter.next();
400363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger         element != NULL;
401363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger         element = (const Element*)recIter.next()) {
402363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        new (fDeque.push_back()) Element(*element);
40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return *this;
40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkClipStack::operator==(const SkClipStack& b) const {
40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fSaveCount != b.fSaveCount ||
41080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDeque.count() != b.fDeque.count()) {
41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
41280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
41380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDeque::F2BIter myIter(fDeque);
41480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDeque::F2BIter bIter(b.fDeque);
415363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const Element* myElement = (const Element*)myIter.next();
416363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const Element* bElement = (const Element*)bIter.next();
41780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
418363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    while (myElement != NULL && bElement != NULL) {
419363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (*myElement != *bElement) {
42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
42180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
422363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        myElement = (const Element*)myIter.next();
423363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        bElement = (const Element*)bIter.next();
42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
425363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return myElement == NULL && bElement == NULL;
42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkClipStack::reset() {
42980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // We used a placement new for each object in fDeque, so we're responsible
43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // for calling the destructor on each of them as well.
43180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (!fDeque.empty()) {
432363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        Element* element = (Element*)fDeque.back();
433363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        element->~Element();
43480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDeque.pop_back();
43580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
43680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fSaveCount = 0;
43880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
43980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkClipStack::save() {
44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fSaveCount += 1;
44280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
44380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkClipStack::restore() {
44580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fSaveCount -= 1;
44680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    while (!fDeque.empty()) {
447363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        Element* element = (Element*)fDeque.back();
448363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (element->fSaveCount <= fSaveCount) {
44980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
45080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
451363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->purgeClip(element);
452363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        element->~Element();
45380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fDeque.pop_back();
45480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
45580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
45680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
45780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkClipStack::getBounds(SkRect* canvFiniteBound,
45880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            BoundsType* boundType,
45980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                            bool* isIntersectionOfRects) const {
46080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(NULL != canvFiniteBound && NULL != boundType);
46180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
462363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    Element* element = (Element*)fDeque.back();
46380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
464363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (NULL == element) {
46580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // the clip is wide open - the infinite plane w/ no pixels un-writeable
46680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        canvFiniteBound->setEmpty();
46780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *boundType = kInsideOut_BoundsType;
46880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL != isIntersectionOfRects) {
46980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            *isIntersectionOfRects = false;
47080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
47180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
47280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
47380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
474363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    *canvFiniteBound = element->fFiniteBound;
475363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    *boundType = element->fFiniteBoundType;
47680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL != isIntersectionOfRects) {
477363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        *isIntersectionOfRects = element->fIsIntersectionOfRects;
47880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
47980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
48080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
48180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkClipStack::intersectRectWithClip(SkRect* rect) const {
48280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(NULL != rect);
48380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
48480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect bounds;
48580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkClipStack::BoundsType bt;
48680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->getBounds(&bounds, &bt);
48780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (bt == SkClipStack::kInsideOut_BoundsType) {
48880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (bounds.contains(*rect)) {
48980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
49080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
49180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // If rect's x values are both within bound's x range we
49280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // could clip here. Same for y. But we don't bother to check.
49380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return true;
49480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
49580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
49680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return rect->intersect(bounds);
49780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
49880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
49980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
500363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerbool SkClipStack::quickContains(const SkRect& rect) const {
501363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
502363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    Iter iter(*this, Iter::kTop_IterStart);
503363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const Element* element = iter.prev();
504363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    while (element != NULL) {
505363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (SkRegion::kIntersect_Op != element->getOp() && SkRegion::kReplace_Op != element->getOp())
506363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            return false;
507363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (element->isInverseFilled()) {
508363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // Part of 'rect' could be trimmed off by the inverse-filled clip element
509363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            if (SkRect::Intersects(element->getBounds(), rect)) {
510363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                return false;
511363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
512363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        } else {
513363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            if (!element->contains(rect)) {
514363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                return false;
515363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
516363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
517363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (SkRegion::kReplace_Op == element->getOp()) {
518363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            break;
519363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
520363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        element = iter.prev();
521363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
522363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return true;
523363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger}
52480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
525363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkClipStack::clipDevRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
52680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
52780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Use reverse iterator instead of back because Rect path may need previous
52880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDeque::Iter iter(fDeque, SkDeque::Iter::kBack_IterStart);
529363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    Element* element = (Element*) iter.prev();
53080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
531363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (element && element->canBeIntersectedInPlace(fSaveCount, op)) {
532363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        switch (element->fType) {
533363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            case Element::kEmpty_Type:
534363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                element->checkEmpty();
53580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return;
536363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            case Element::kRect_Type:
537363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                if (element->rectRectIntersectAllowed(rect, doAA)) {
538363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    this->purgeClip(element);
539363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    if (!element->fRect.intersect(rect)) {
540363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                        element->setEmpty();
54180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                        return;
54280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    }
54380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
544363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    element->fDoAA = doAA;
545363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    Element* prev = (Element*) iter.prev();
546363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    element->updateBoundAndGenID(prev);
54780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return;
54880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
54980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
550363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            case Element::kPath_Type:
551363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                if (!SkRect::Intersects(element->fPath.getBounds(), rect)) {
552363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    this->purgeClip(element);
553363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    element->setEmpty();
55480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return;
55580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
55680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
55780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
55880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
559363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    new (fDeque.push_back()) Element(fSaveCount, rect, op, doAA);
560363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    ((Element*) fDeque.back())->updateBoundAndGenID(element);
56180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
562363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (element && element->fSaveCount == fSaveCount) {
563363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->purgeClip(element);
56480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
56580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
56680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
56780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkClipStack::clipDevPath(const SkPath& path, SkRegion::Op op, bool doAA) {
56880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect alt;
569363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (path.isRect(&alt) && !path.isInverseFillType()) {
57080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return this->clipDevRect(alt, op, doAA);
57180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
57280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
573363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    Element* element = (Element*)fDeque.back();
574363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (element && element->canBeIntersectedInPlace(fSaveCount, op)) {
57580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkRect& pathBounds = path.getBounds();
576363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        switch (element->fType) {
577363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            case Element::kEmpty_Type:
578363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                element->checkEmpty();
57980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return;
580363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            case Element::kRect_Type:
581363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                if (!SkRect::Intersects(element->fRect, pathBounds)) {
582363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    this->purgeClip(element);
583363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    element->setEmpty();
58480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return;
58580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
58680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
587363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            case Element::kPath_Type:
588363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                if (!SkRect::Intersects(element->fPath.getBounds(), pathBounds)) {
589363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    this->purgeClip(element);
590363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    element->setEmpty();
59180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    return;
59280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
59380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                break;
59480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
59580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
596363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    new (fDeque.push_back()) Element(fSaveCount, path, op, doAA);
597363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    ((Element*) fDeque.back())->updateBoundAndGenID(element);
59880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
599363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (element && element->fSaveCount == fSaveCount) {
600363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->purgeClip(element);
60180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
60280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
60380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
60480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkClipStack::clipEmpty() {
60580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
606363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    Element* element = (Element*) fDeque.back();
60780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
608363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (element && element->canBeIntersectedInPlace(fSaveCount, SkRegion::kIntersect_Op)) {
609363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        switch (element->fType) {
610363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            case Element::kEmpty_Type:
611363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                element->checkEmpty();
61280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return;
613363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            case Element::kRect_Type:
614363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            case Element::kPath_Type:
615363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                this->purgeClip(element);
616363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                element->setEmpty();
61780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return;
61880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
61980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
620363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    new (fDeque.push_back()) Element(fSaveCount);
62180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
622363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (element && element->fSaveCount == fSaveCount) {
623363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        this->purgeClip(element);
62480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
625363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    ((Element*)fDeque.back())->fGenID = kEmptyGenID;
62680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
62780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
62880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool SkClipStack::isWideOpen() const {
62980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (0 == fDeque.count()) {
63080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return true;
63180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
63280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
633363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const Element* back = (const Element*) fDeque.back();
634363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return kWideOpenGenID == back->fGenID ||
635363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger           (kInsideOut_BoundsType == back->fFiniteBoundType && back->fFiniteBound.isEmpty());
63680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
63780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
63880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru///////////////////////////////////////////////////////////////////////////////
63980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
64080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkClipStack::Iter::Iter() : fStack(NULL) {
64180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
64280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
64380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruSkClipStack::Iter::Iter(const SkClipStack& stack, IterStart startLoc)
64480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    : fStack(&stack) {
64580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->reset(stack, startLoc);
64680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
64780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
648363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerconst SkClipStack::Element* SkClipStack::Iter::next() {
649363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return (const SkClipStack::Element*)fIter.next();
65080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
65180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
652363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerconst SkClipStack::Element* SkClipStack::Iter::prev() {
653363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return (const SkClipStack::Element*)fIter.prev();
65480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
65580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
656363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerconst SkClipStack::Element* SkClipStack::Iter::skipToTopmost(SkRegion::Op op) {
65780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
65880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == fStack) {
65980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
66080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
66180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
66280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fIter.reset(fStack->fDeque, SkDeque::Iter::kBack_IterStart);
66380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
664363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    const SkClipStack::Element* element = NULL;
66580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
666363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    for (element = (const SkClipStack::Element*) fIter.prev();
667363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger         NULL != element;
668363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger         element = (const SkClipStack::Element*) fIter.prev()) {
66980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
670363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (op == element->fOp) {
67180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // The Deque's iterator is actually one pace ahead of the
672363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // returned value. So while "element" is the element we want to
67380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // return, the iterator is actually pointing at (and will
67480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // return on the next "next" or "prev" call) the element
67580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // in front of it in the deque. Bump the iterator forward a
67680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            // step so we get the expected result.
67780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (NULL == fIter.next()) {
67880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                // The reverse iterator has run off the front of the deque
67980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                // (i.e., the "op" clip is the first clip) and can't
68080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                // recover. Reset the iterator to start at the front.
68180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                fIter.reset(fStack->fDeque, SkDeque::Iter::kFront_IterStart);
68280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
68380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
68480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
68580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
68680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
687363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (NULL == element) {
68880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // There were no "op" clips
68980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fIter.reset(fStack->fDeque, SkDeque::Iter::kFront_IterStart);
69080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
69180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
69280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return this->next();
69380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
69480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
69580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkClipStack::Iter::reset(const SkClipStack& stack, IterStart startLoc) {
69680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fStack = &stack;
69780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fIter.reset(stack.fDeque, static_cast<SkDeque::Iter::IterStart>(startLoc));
69880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
69980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
70080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// helper method
70180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkClipStack::getConservativeBounds(int offsetX,
70280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        int offsetY,
70380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        int maxWidth,
70480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        int maxHeight,
70580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        SkRect* devBounds,
70680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                        bool* isIntersectionOfRects) const {
70780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(NULL != devBounds);
70880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
70980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    devBounds->setLTRB(0, 0,
71080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                       SkIntToScalar(maxWidth), SkIntToScalar(maxHeight));
71180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
71280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkRect temp;
71380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkClipStack::BoundsType boundType;
71480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
71580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // temp starts off in canvas space here
71680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    this->getBounds(&temp, &boundType, isIntersectionOfRects);
71780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (SkClipStack::kInsideOut_BoundsType == boundType) {
71880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return;
71980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
72080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
72180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // but is converted to device space here
72280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    temp.offset(SkIntToScalar(offsetX), SkIntToScalar(offsetY));
72380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
72480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!devBounds->intersect(temp)) {
72580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        devBounds->setEmpty();
72680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
72780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
72880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
72980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkClipStack::addPurgeClipCallback(PFPurgeClipCB callback, void* data) const {
73080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ClipCallbackData temp = { callback, data };
73180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fCallbackData.append(1, &temp);
73280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
73380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
73480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid SkClipStack::removePurgeClipCallback(PFPurgeClipCB callback, void* data) const {
73580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ClipCallbackData temp = { callback, data };
73680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int index = fCallbackData.find(temp);
73780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (index >= 0) {
73880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        fCallbackData.removeShuffle(index);
73980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
74080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
74180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
742363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger// The clip state represented by 'element' will never be used again. Purge it.
743363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergervoid SkClipStack::purgeClip(Element* element) {
744363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkASSERT(NULL != element);
745363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    if (element->fGenID >= 0 && element->fGenID < kFirstUnreservedGenID) {
746363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        return;
747363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    }
74880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
74980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < fCallbackData.count(); ++i) {
750363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        (*fCallbackData[i].fCallback)(element->fGenID, fCallbackData[i].fData);
75180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
75280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
753363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // Invalidate element's gen ID so handlers can detect already handled records
754363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    element->fGenID = kInvalidGenID;
75580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
75680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
75780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t SkClipStack::GetNextGenID() {
758363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    // TODO: handle overflow.
75980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return sk_atomic_inc(&gGenID);
76080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
76180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
76280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruint32_t SkClipStack::getTopmostGenID() const {
76380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
76480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fDeque.empty()) {
76580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return kInvalidGenID;
76680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
76780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
768363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    Element* element = (Element*)fDeque.back();
769363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    return element->fGenID;
77080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
771