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#ifndef SkClipStack_DEFINED
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkClipStack_DEFINED
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkDeque.h"
12363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkPath.h"
13363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkRect.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkRegion.h"
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTDArray.h"
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Because a single save/restore state can have multiple clips, this class
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// stores the stack depth (fSaveCount) and clips (fDeque) separately.
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// Each clip in fDeque stores the stack state to which it belongs
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// (i.e., the fSaveCount in force when it was added). Restores are thus
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// implemented by removing clips from fDeque that have an fSaveCount larger
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru// then the freshly decremented count.
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SK_API SkClipStack {
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
26363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    enum BoundsType {
27363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // The bounding box contains all the pixels that can be written to
28363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        kNormal_BoundsType,
29363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // The bounding box contains all the pixels that cannot be written to.
30363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // The real bound extends out to infinity and all the pixels outside
31363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // of the bound can be written to. Note that some of the pixels inside
32363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // the bound may also be writeable but all pixels that cannot be
33363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // written to are guaranteed to be inside.
34363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        kInsideOut_BoundsType
35363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    };
36363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
37363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    class Element {
38363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    public:
39363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        enum Type {
40363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            //!< This element makes the clip empty (regardless of previous elements).
41363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            kEmpty_Type,
42363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            //!< This element combines a rect with the current clip using a set operation
43363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            kRect_Type,
44363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            //!< This element combines a path with the current clip using a set operation
45363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            kPath_Type,
46363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        };
47363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
48363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        Element() {
49363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->initCommon(0, SkRegion::kReplace_Op, false);
50363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->setEmpty();
51363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
52363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
53363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        Element(const SkRect& rect, SkRegion::Op op, bool doAA) {
54363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->initRect(0, rect, op, doAA);
55363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
56363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
57363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        Element(const SkPath& path, SkRegion::Op op, bool doAA) {
58363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->initPath(0, path, op, doAA);
59363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
60363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
61363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        bool operator== (const Element& element) const {
62363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            if (this == &element) {
63363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                return true;
64363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
65363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            if (fOp != element.fOp ||
66363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                fType != element.fType ||
67363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                fDoAA != element.fDoAA ||
68363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                fSaveCount != element.fSaveCount) {
69363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                return false;
70363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
71363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            switch (fType) {
72363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                case kPath_Type:
73363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    return fPath == element.fPath;
74363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                case kRect_Type:
75363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    return fRect == element.fRect;
76363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                case kEmpty_Type:
77363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    return true;
78363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                default:
79363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    SkDEBUGFAIL("Unexpected type.");
80363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    return false;
81363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
82363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
83363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        bool operator!= (const Element& element) const { return !(*this == element); }
84363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
85363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        //!< Call to get the type of the clip element.
86363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        Type getType() const { return fType; }
87363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
88363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        //!< Call if getType() is kPath to get the path.
89363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        const SkPath& getPath() const { return fPath; }
90363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
91363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        //!< Call if getType() is kRect to get the rect.
92363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        const SkRect& getRect() const { return fRect; }
93363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
94363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        //!< Call if getType() is not kEmpty to get the set operation used to combine this element.
95363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkRegion::Op getOp() const { return fOp; }
96363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
97363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        /** If getType() is not kEmpty this indicates whether the clip shape should be anti-aliased
98363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            when it is rasterized. */
99363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        bool isAA() const { return fDoAA; }
100363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
101363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        //!< Inverts the fill of the clip shape. Note that a kEmpty element remains kEmpty.
102363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        void invertShapeFillType();
103363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
104363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        //!< Sets the set operation represented by the element.
105363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        void setOp(SkRegion::Op op) { fOp = op; }
106363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
107363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        /** The GenID can be used by clip stack clients to cache representations of the clip. The
108363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            ID corresponds to the set of clip elements up to and including this element within the
109363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            stack not to the element itself. That is the same clip path in different stacks will
110363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            have a different ID since the elements produce different clip result in the context of
111363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            their stacks. */
112910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger        int32_t getGenID() const { SkASSERT(kInvalidGenID != fGenID); return fGenID; }
113363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
114363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        /**
115363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger         * Gets the bounds of the clip element, either the rect or path bounds. (Whether the shape
116363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger         * is inverse filled is not considered.)
117363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger         */
118363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        const SkRect& getBounds() const {
119363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            static const SkRect kEmpty = { 0, 0, 0, 0 };
120363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            switch (fType) {
121363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                case kRect_Type:
122363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    return fRect;
123363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                case kPath_Type:
124363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    return fPath.getBounds();
125363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                case kEmpty_Type:
126363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    return kEmpty;
127363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                default:
128363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    SkDEBUGFAIL("Unexpected type.");
129363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    return kEmpty;
130363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
131363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
132363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
133363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        /**
134363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger         * Conservatively checks whether the clip shape contains the rect param. (Whether the shape
135363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger         * is inverse filled is not considered.)
136363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger         */
137363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        bool contains(const SkRect& rect) const {
138363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            switch (fType) {
139363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                case kRect_Type:
140363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    return fRect.contains(rect);
141363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                case kPath_Type:
142363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    return fPath.conservativelyContainsRect(rect);
143363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                case kEmpty_Type:
144363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    return false;
145363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                default:
146363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    SkDEBUGFAIL("Unexpected type.");
147363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger                    return false;
148363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            }
149363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
150363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
151363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        /**
152363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger         * Is the clip shape inverse filled.
153363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger         */
154363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        bool isInverseFilled() const {
155363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            return kPath_Type == fType && fPath.isInverseFillType();
156363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
157363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
158363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    private:
159363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        friend class SkClipStack;
160363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
161363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkPath          fPath;
162363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkRect          fRect;
163363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        int             fSaveCount; // save count of stack when this element was added.
164363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkRegion::Op    fOp;
165363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        Type            fType;
166363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        bool            fDoAA;
167363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
168363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        /* fFiniteBoundType and fFiniteBound are used to incrementally update the clip stack's
169363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger           bound. When fFiniteBoundType is kNormal_BoundsType, fFiniteBound represents the
170363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger           conservative bounding box of the pixels that aren't clipped (i.e., any pixels that can be
171363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger           drawn to are inside the bound). When fFiniteBoundType is kInsideOut_BoundsType (which
172363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger           occurs when a clip is inverse filled), fFiniteBound represents the conservative bounding
173363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger           box of the pixels that _are_ clipped (i.e., any pixels that cannot be drawn to are inside
174363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger           the bound). When fFiniteBoundType is kInsideOut_BoundsType the actual bound is the
175363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger           infinite plane. This behavior of fFiniteBoundType and fFiniteBound is required so that we
176363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger           can capture the cancelling out of the extensions to infinity when two inverse filled
177363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger           clips are Booleaned together. */
178363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkClipStack::BoundsType fFiniteBoundType;
179363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        SkRect                  fFiniteBound;
180363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
181363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // When element is applied to the previous elements in the stack is the result known to be
182363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // equivalent to a single rect intersection? IIOW, is the clip effectively a rectangle.
183363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        bool                    fIsIntersectionOfRects;
184363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
185363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        int                     fGenID;
186363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
187363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        Element(int saveCount) {
188363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->initCommon(saveCount, SkRegion::kReplace_Op, false);
189363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->setEmpty();
190363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
191363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
192363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        Element(int saveCount, const SkRect& rect, SkRegion::Op op, bool doAA) {
193363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->initRect(saveCount, rect, op, doAA);
194363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
195363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
196363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        Element(int saveCount, const SkPath& path, SkRegion::Op op, bool doAA) {
197363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->initPath(saveCount, path, op, doAA);
198363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
199363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
200363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        void initCommon(int saveCount, SkRegion::Op op, bool doAA) {
201363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fSaveCount = saveCount;
202363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fOp = op;
203363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fDoAA = doAA;
204363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // A default of inside-out and empty bounds means the bounds are effectively void as it
205363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            // indicates that nothing is known to be outside the clip.
206363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBoundType = kInsideOut_BoundsType;
207363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBound.setEmpty();
208363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fIsIntersectionOfRects = false;
209363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fGenID = kInvalidGenID;
210363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
211363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
212363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        void initRect(int saveCount, const SkRect& rect, SkRegion::Op op, bool doAA) {
213363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fRect = rect;
214363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fType = kRect_Type;
215363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->initCommon(saveCount, op, doAA);
216363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
217363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
218363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        void initPath(int saveCount, const SkPath& path, SkRegion::Op op, bool doAA) {
219363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fPath = path;
220363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fType = kPath_Type;
221363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            this->initCommon(saveCount, op, doAA);
222363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
223363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
224363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        void setEmpty() {
225363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fType = kEmpty_Type;
226363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBound.setEmpty();
227363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fFiniteBoundType = kNormal_BoundsType;
228363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fIsIntersectionOfRects = false;
229363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fRect.setEmpty();
230363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fPath.reset();
231363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            fGenID = kEmptyGenID;
232363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        }
233363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
234363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // All Element methods below are only used within SkClipStack.cpp
235363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        inline void checkEmpty() const;
236363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        inline bool canBeIntersectedInPlace(int saveCount, SkRegion::Op op) const;
237363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        /* This method checks to see if two rect clips can be safely merged into one. The issue here
238363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger          is that to be strictly correct all the edges of the resulting rect must have the same
239363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger          anti-aliasing. */
240363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        bool rectRectIntersectAllowed(const SkRect& newR, bool newAA) const;
241363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        /** Determines possible finite bounds for the Element given the previous element of the
242363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            stack */
243363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        void updateBoundAndGenID(const Element* prior);
244363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // The different combination of fill & inverse fill when combining bounding boxes
245363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        enum FillCombo {
246363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            kPrev_Cur_FillCombo,
247363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            kPrev_InvCur_FillCombo,
248363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            kInvPrev_Cur_FillCombo,
249363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger            kInvPrev_InvCur_FillCombo
250363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        };
251363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        // per-set operation functions used by updateBoundAndGenID().
252363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        inline void combineBoundsDiff(FillCombo combination, const SkRect& prevFinite);
253363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        inline void combineBoundsXOR(int combination, const SkRect& prevFinite);
254363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        inline void combineBoundsUnion(int combination, const SkRect& prevFinite);
255363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        inline void combineBoundsIntersection(int combination, const SkRect& prevFinite);
256363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        inline void combineBoundsRevDiff(int combination, const SkRect& prevFinite);
257363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    };
258363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkClipStack();
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkClipStack(const SkClipStack& b);
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    explicit SkClipStack(const SkRect& r);
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    explicit SkClipStack(const SkIRect& r);
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    ~SkClipStack();
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkClipStack& operator=(const SkClipStack& b);
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool operator==(const SkClipStack& b) const;
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool operator!=(const SkClipStack& b) const { return !(*this == b); }
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void reset();
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int getSaveCount() const { return fSaveCount; }
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void save();
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void restore();
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * getBounds places the current finite bound in its first parameter. In its
27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * second, it indicates which kind of bound is being returned. If
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * 'canvFiniteBound' is a normal bounding box then it encloses all writeable
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * pixels. If 'canvFiniteBound' is an inside out bounding box then it
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * encloses all the un-writeable pixels and the true/normal bound is the
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * infinite plane. isIntersectionOfRects is an optional parameter
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * that is true if 'canvFiniteBound' resulted from an intersection of rects.
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void getBounds(SkRect* canvFiniteBound,
28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                   BoundsType* boundType,
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                   bool* isIntersectionOfRects = NULL) const;
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * Takes an input rect in device space and conservatively clips it to the
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * clip-stack. If false is returned then the rect does not intersect the
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * clip and is unmodified.
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool intersectRectWithClip(SkRect* devRect) const;
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
295363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    /**
296363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * Returns true if the input rect in device space is entirely contained
297363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * by the clip. A return value of false does not guarantee that the rect
298363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * is not contained by the clip.
299363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     */
300363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    bool quickContains(const SkRect& devRect) const;
301363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void clipDevRect(const SkIRect& ir, SkRegion::Op op) {
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkRect r;
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        r.set(ir);
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        this->clipDevRect(r, op, false);
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
30780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void clipDevRect(const SkRect&, SkRegion::Op, bool doAA);
30880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void clipDevPath(const SkPath&, SkRegion::Op, bool doAA);
30980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // An optimized version of clipDevRect(emptyRect, kIntersect, ...)
31080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void clipEmpty();
31180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
31380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * isWideOpen returns true if the clip state corresponds to the infinite
31480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * plane (i.e., draws are not limited at all)
31580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    bool isWideOpen() const;
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
31980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * The generation ID has three reserved values to indicate special
320363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger     * (potentially ignorable) cases
32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
322910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger    static const int32_t kInvalidGenID = 0;     //!< Invalid id that is never returned by
323910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                                                //!< SkClipStack. Useful when caching clips
324910f694aefb0b671dd8522a9afe9b6be645701c1Derek Sollenberger                                                //!< based on GenID.
32580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const int32_t kEmptyGenID = 1;       // no pixels writeable
32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static const int32_t kWideOpenGenID = 2;    // all pixels writeable
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int32_t getTopmostGenID() const;
32980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic:
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    class Iter {
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    public:
33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        enum IterStart {
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            kBottom_IterStart = SkDeque::Iter::kFront_IterStart,
33580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            kTop_IterStart = SkDeque::Iter::kBack_IterStart
33680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        };
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        /**
33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru         * Creates an uninitialized iterator. Must be reset()
34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru         */
34180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Iter();
34280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        Iter(const SkClipStack& stack, IterStart startLoc);
34480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
34580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        /**
346363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger         *  Return the clip element for this iterator. If next()/prev() returns NULL, then the
347363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger         *  iterator is done.
34880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru         */
349363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        const Element* next();
350363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        const Element* prev();
35180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        /**
353363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger         * Moves the iterator to the topmost element with the specified RegionOp and returns that
354363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger         * element. If no clip element with that op is found, the first element is returned.
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru         */
356363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        const Element* skipToTopmost(SkRegion::Op op);
35780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
35880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        /**
35980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru         * Restarts the iterator on a clip stack.
36080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru         */
36180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        void reset(const SkClipStack& stack, IterStart startLoc);
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    private:
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        const SkClipStack* fStack;
36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkDeque::Iter      fIter;
36680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    };
36780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
36980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * The B2TIter iterates from the bottom of the stack to the top.
37080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * It inherits privately from Iter to prevent access to reverse iteration.
37180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
37280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    class B2TIter : private Iter {
37380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    public:
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        B2TIter() {}
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        /**
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru         * Wrap Iter's 2 parameter ctor to force initialization to the
37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru         * beginning of the deque/bottom of the stack
37980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru         */
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        B2TIter(const SkClipStack& stack)
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        : INHERITED(stack, kBottom_IterStart) {
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        using Iter::next;
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        /**
38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru         * Wrap Iter::reset to force initialization to the
38880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru         * beginning of the deque/bottom of the stack
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru         */
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        void reset(const SkClipStack& stack) {
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            this->INHERITED::reset(stack, kBottom_IterStart);
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    private:
39580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        typedef Iter INHERITED;
39780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    };
39880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
39980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
40080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * GetConservativeBounds returns a conservative bound of the current clip.
40180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * Since this could be the infinite plane (if inverse fills were involved) the
40280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * maxWidth and maxHeight parameters can be used to limit the returned bound
40380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * to the expected drawing area. Similarly, the offsetX and offsetY parameters
40480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * allow the caller to offset the returned bound to account for translated
40580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * drawing areas (i.e., those resulting from a saveLayer). For finite bounds,
40680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * the translation (+offsetX, +offsetY) is applied before the clamp to the
40780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * maximum rectangle: [0,maxWidth) x [0,maxHeight).
40880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * isIntersectionOfRects is an optional parameter that is true when
40980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * 'devBounds' is the result of an intersection of rects. In this case
41080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * 'devBounds' is the exact answer/clip.
41180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
41280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    void getConservativeBounds(int offsetX,
41380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                               int offsetY,
41480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                               int maxWidth,
41580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                               int maxHeight,
41680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                               SkRect* devBounds,
41780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                               bool* isIntersectionOfRects = NULL) const;
41880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
41980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate:
42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    friend class Iter;
42180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkDeque fDeque;
42380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int     fSaveCount;
42480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
42580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Generation ID for the clip stack. This is incremented for each
42680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // clipDevRect and clipDevPath call. 0 is reserved to indicate an
42780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // invalid ID.
42880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static int32_t     gGenID;
42980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
43080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    /**
43158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger     * Restore the stack back to the specified save count.
43258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger     */
43358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    void restoreTo(int saveCount);
43458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger
43558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger    /**
43680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     * Return the next unique generation ID.
43780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru     */
43880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    static int32_t GetNextGenID();
43980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
44080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
44180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
442