LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkClipStack.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 99 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 31 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2011 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #ifndef SkClipStack_DEFINED
       9             : #define SkClipStack_DEFINED
      10             : 
      11             : #include "../private/SkMessageBus.h"
      12             : #include "SkCanvas.h"
      13             : #include "SkDeque.h"
      14             : #include "SkPath.h"
      15             : #include "SkRRect.h"
      16             : #include "SkRect.h"
      17             : #include "SkRegion.h"
      18             : #include "SkTLazy.h"
      19             : 
      20             : #if SK_SUPPORT_GPU
      21             : #include "GrResourceKey.h"
      22             : #endif
      23             : 
      24             : #ifdef SK_SUPPORT_OBSOLETE_REPLAYCLIP
      25             : class SkCanvasClipVisitor;
      26             : #endif
      27             : 
      28             : // Because a single save/restore state can have multiple clips, this class
      29             : // stores the stack depth (fSaveCount) and clips (fDeque) separately.
      30             : // Each clip in fDeque stores the stack state to which it belongs
      31             : // (i.e., the fSaveCount in force when it was added). Restores are thus
      32             : // implemented by removing clips from fDeque that have an fSaveCount larger
      33             : // then the freshly decremented count.
      34             : class SkClipStack {
      35             : public:
      36             :     enum BoundsType {
      37             :         // The bounding box contains all the pixels that can be written to
      38             :         kNormal_BoundsType,
      39             :         // The bounding box contains all the pixels that cannot be written to.
      40             :         // The real bound extends out to infinity and all the pixels outside
      41             :         // of the bound can be written to. Note that some of the pixels inside
      42             :         // the bound may also be writeable but all pixels that cannot be
      43             :         // written to are guaranteed to be inside.
      44             :         kInsideOut_BoundsType
      45             :     };
      46             : 
      47             :     class Element {
      48             :     public:
      49             :         enum Type {
      50             :             //!< This element makes the clip empty (regardless of previous elements).
      51             :             kEmpty_Type,
      52             :             //!< This element combines a rect with the current clip using a set operation
      53             :             kRect_Type,
      54             :             //!< This element combines a round-rect with the current clip using a set operation
      55             :             kRRect_Type,
      56             :             //!< This element combines a path with the current clip using a set operation
      57             :             kPath_Type,
      58             : 
      59             :             kLastType = kPath_Type
      60             :         };
      61             :         static const int kTypeCnt = kLastType + 1;
      62             : 
      63             :         Element() {
      64             :             this->initCommon(0, SkClipOp::kReplace_deprecated, false);
      65             :             this->setEmpty();
      66             :         }
      67             : 
      68             :         Element(const Element&);
      69             : 
      70           0 :         Element(const SkRect& rect, SkClipOp op, bool doAA) {
      71           0 :             this->initRect(0, rect, op, doAA);
      72           0 :         }
      73             : 
      74             :         Element(const SkRRect& rrect, SkClipOp op, bool doAA) {
      75             :             this->initRRect(0, rrect, op, doAA);
      76             :         }
      77             : 
      78             :         Element(const SkPath& path, SkClipOp op, bool doAA) {
      79             :             this->initPath(0, path, op, doAA);
      80             :         }
      81             : 
      82           0 :         ~Element() {
      83             : #if SK_SUPPORT_GPU
      84           0 :             for (int i = 0; i < fMessages.count(); ++i) {
      85           0 :                 SkMessageBus<GrUniqueKeyInvalidatedMessage>::Post(*fMessages[i]);
      86             :             }
      87             : #endif
      88           0 :         }
      89             : 
      90             :         bool operator== (const Element& element) const;
      91           0 :         bool operator!= (const Element& element) const { return !(*this == element); }
      92             : 
      93             :         //!< Call to get the type of the clip element.
      94           0 :         Type getType() const { return fType; }
      95             : 
      96             :         //!< Call to get the save count associated with this clip element.
      97             :         int getSaveCount() const { return fSaveCount; }
      98             : 
      99             :         //!< Call if getType() is kPath to get the path.
     100           0 :         const SkPath& getPath() const { SkASSERT(kPath_Type == fType); return *fPath.get(); }
     101             : 
     102             :         //!< Call if getType() is kRRect to get the round-rect.
     103           0 :         const SkRRect& getRRect() const { SkASSERT(kRRect_Type == fType); return fRRect; }
     104             : 
     105             :         //!< Call if getType() is kRect to get the rect.
     106           0 :         const SkRect& getRect() const {
     107           0 :             SkASSERT(kRect_Type == fType && (fRRect.isRect() || fRRect.isEmpty()));
     108           0 :             return fRRect.getBounds();
     109             :         }
     110             : 
     111             :         //!< Call if getType() is not kEmpty to get the set operation used to combine this element.
     112           0 :         SkClipOp getOp() const { return fOp; }
     113             : 
     114             :         //!< Call to get the element as a path, regardless of its type.
     115             :         void asPath(SkPath* path) const;
     116             : 
     117             :         //!< Call if getType() is not kPath to get the element as a round rect.
     118           0 :         const SkRRect& asRRect() const { SkASSERT(kPath_Type != fType); return fRRect; }
     119             : 
     120             :         /** If getType() is not kEmpty this indicates whether the clip shape should be anti-aliased
     121             :             when it is rasterized. */
     122           0 :         bool isAA() const { return fDoAA; }
     123             : 
     124             :         //!< Inverts the fill of the clip shape. Note that a kEmpty element remains kEmpty.
     125             :         void invertShapeFillType();
     126             : 
     127             :         //!< Sets the set operation represented by the element.
     128           0 :         void setOp(SkClipOp op) { fOp = op; }
     129             : 
     130             :         /** The GenID can be used by clip stack clients to cache representations of the clip. The
     131             :             ID corresponds to the set of clip elements up to and including this element within the
     132             :             stack not to the element itself. That is the same clip path in different stacks will
     133             :             have a different ID since the elements produce different clip result in the context of
     134             :             their stacks. */
     135           0 :         int32_t getGenID() const { SkASSERT(kInvalidGenID != fGenID); return fGenID; }
     136             : 
     137             :         /**
     138             :          * Gets the bounds of the clip element, either the rect or path bounds. (Whether the shape
     139             :          * is inverse filled is not considered.)
     140             :          */
     141           0 :         const SkRect& getBounds() const {
     142             :             static const SkRect kEmpty = { 0, 0, 0, 0 };
     143           0 :             switch (fType) {
     144             :                 case kRect_Type:  // fallthrough
     145             :                 case kRRect_Type:
     146           0 :                     return fRRect.getBounds();
     147             :                 case kPath_Type:
     148           0 :                     return fPath.get()->getBounds();
     149             :                 case kEmpty_Type:
     150           0 :                     return kEmpty;
     151             :                 default:
     152           0 :                     SkDEBUGFAIL("Unexpected type.");
     153           0 :                     return kEmpty;
     154             :             }
     155             :         }
     156             : 
     157             :         /**
     158             :          * Conservatively checks whether the clip shape contains the rect param. (Whether the shape
     159             :          * is inverse filled is not considered.)
     160             :          */
     161           0 :         bool contains(const SkRect& rect) const {
     162           0 :             switch (fType) {
     163             :                 case kRect_Type:
     164           0 :                     return this->getRect().contains(rect);
     165             :                 case kRRect_Type:
     166           0 :                     return fRRect.contains(rect);
     167             :                 case kPath_Type:
     168           0 :                     return fPath.get()->conservativelyContainsRect(rect);
     169             :                 case kEmpty_Type:
     170           0 :                     return false;
     171             :                 default:
     172           0 :                     SkDEBUGFAIL("Unexpected type.");
     173           0 :                     return false;
     174             :             }
     175             :         }
     176             : 
     177           0 :         bool contains(const SkRRect& rrect) const {
     178           0 :             switch (fType) {
     179             :                 case kRect_Type:
     180           0 :                     return this->getRect().contains(rrect.getBounds());
     181             :                 case kRRect_Type:
     182             :                     // We don't currently have a generalized rrect-rrect containment.
     183           0 :                     return fRRect.contains(rrect.getBounds()) || rrect == fRRect;
     184             :                 case kPath_Type:
     185           0 :                     return fPath.get()->conservativelyContainsRect(rrect.getBounds());
     186             :                 case kEmpty_Type:
     187           0 :                     return false;
     188             :                 default:
     189           0 :                     SkDEBUGFAIL("Unexpected type.");
     190           0 :                     return false;
     191             :             }
     192             :         }
     193             : 
     194             :         /**
     195             :          * Is the clip shape inverse filled.
     196             :          */
     197           0 :         bool isInverseFilled() const {
     198           0 :             return kPath_Type == fType && fPath.get()->isInverseFillType();
     199             :         }
     200             : 
     201             : #ifdef SK_SUPPORT_OBSOLETE_REPLAYCLIP
     202             :         /**
     203             :         * Replay this clip into the visitor.
     204             :         */
     205             :         void replay(SkCanvasClipVisitor*) const;
     206             : #endif
     207             : 
     208             : #ifdef SK_DEBUG
     209             :         /**
     210             :          * Dumps the element to SkDebugf. This is intended for Skia development debugging
     211             :          * Don't rely on the existence of this function or the formatting of its output.
     212             :          */
     213             :         void dump() const;
     214             : #endif
     215             : 
     216             : #if SK_SUPPORT_GPU
     217             :         /**
     218             :          * This is used to purge any GPU resource cache items that become unreachable when
     219             :          * the element is destroyed because their key is based on this element's gen ID.
     220             :          */
     221           0 :         void addResourceInvalidationMessage(
     222             :                 std::unique_ptr<GrUniqueKeyInvalidatedMessage> msg) const {
     223           0 :             fMessages.emplace_back(std::move(msg));
     224           0 :         }
     225             : #endif
     226             : 
     227             :     private:
     228             :         friend class SkClipStack;
     229             : 
     230             :         SkTLazy<SkPath> fPath;
     231             :         SkRRect fRRect;
     232             :         int fSaveCount;  // save count of stack when this element was added.
     233             :         SkClipOp fOp;
     234             :         Type fType;
     235             :         bool fDoAA;
     236             : 
     237             :         /* fFiniteBoundType and fFiniteBound are used to incrementally update the clip stack's
     238             :            bound. When fFiniteBoundType is kNormal_BoundsType, fFiniteBound represents the
     239             :            conservative bounding box of the pixels that aren't clipped (i.e., any pixels that can be
     240             :            drawn to are inside the bound). When fFiniteBoundType is kInsideOut_BoundsType (which
     241             :            occurs when a clip is inverse filled), fFiniteBound represents the conservative bounding
     242             :            box of the pixels that _are_ clipped (i.e., any pixels that cannot be drawn to are inside
     243             :            the bound). When fFiniteBoundType is kInsideOut_BoundsType the actual bound is the
     244             :            infinite plane. This behavior of fFiniteBoundType and fFiniteBound is required so that we
     245             :            can capture the cancelling out of the extensions to infinity when two inverse filled
     246             :            clips are Booleaned together. */
     247             :         SkClipStack::BoundsType fFiniteBoundType;
     248             :         SkRect fFiniteBound;
     249             : 
     250             :         // When element is applied to the previous elements in the stack is the result known to be
     251             :         // equivalent to a single rect intersection? IIOW, is the clip effectively a rectangle.
     252             :         bool fIsIntersectionOfRects;
     253             : 
     254             :         int fGenID;
     255             : #if SK_SUPPORT_GPU
     256             :         mutable SkTArray<std::unique_ptr<GrUniqueKeyInvalidatedMessage>> fMessages;
     257             : #endif
     258           0 :         Element(int saveCount) {
     259           0 :             this->initCommon(saveCount, SkClipOp::kReplace_deprecated, false);
     260           0 :             this->setEmpty();
     261           0 :         }
     262             : 
     263           0 :         Element(int saveCount, const SkRRect& rrect, SkClipOp op, bool doAA) {
     264           0 :             this->initRRect(saveCount, rrect, op, doAA);
     265           0 :         }
     266             : 
     267           0 :         Element(int saveCount, const SkRect& rect, SkClipOp op, bool doAA) {
     268           0 :             this->initRect(saveCount, rect, op, doAA);
     269           0 :         }
     270             : 
     271           0 :         Element(int saveCount, const SkPath& path, SkClipOp op, bool doAA) {
     272           0 :             this->initPath(saveCount, path, op, doAA);
     273           0 :         }
     274             : 
     275           0 :         void initCommon(int saveCount, SkClipOp op, bool doAA) {
     276           0 :             fSaveCount = saveCount;
     277           0 :             fOp = op;
     278           0 :             fDoAA = doAA;
     279             :             // A default of inside-out and empty bounds means the bounds are effectively void as it
     280             :             // indicates that nothing is known to be outside the clip.
     281           0 :             fFiniteBoundType = kInsideOut_BoundsType;
     282           0 :             fFiniteBound.setEmpty();
     283           0 :             fIsIntersectionOfRects = false;
     284           0 :             fGenID = kInvalidGenID;
     285           0 :         }
     286             : 
     287           0 :         void initRect(int saveCount, const SkRect& rect, SkClipOp op, bool doAA) {
     288           0 :             fRRect.setRect(rect);
     289           0 :             fType = kRect_Type;
     290           0 :             this->initCommon(saveCount, op, doAA);
     291           0 :         }
     292             : 
     293           0 :         void initRRect(int saveCount, const SkRRect& rrect, SkClipOp op, bool doAA) {
     294           0 :             SkRRect::Type type = rrect.getType();
     295           0 :             fRRect = rrect;
     296           0 :             if (SkRRect::kRect_Type == type || SkRRect::kEmpty_Type == type) {
     297           0 :                 fType = kRect_Type;
     298             :             } else {
     299           0 :                 fType = kRRect_Type;
     300             :             }
     301           0 :             this->initCommon(saveCount, op, doAA);
     302           0 :         }
     303             : 
     304             :         void initPath(int saveCount, const SkPath& path, SkClipOp op, bool doAA);
     305             : 
     306             :         void setEmpty();
     307             : 
     308             :         // All Element methods below are only used within SkClipStack.cpp
     309             :         inline void checkEmpty() const;
     310             :         inline bool canBeIntersectedInPlace(int saveCount, SkClipOp op) const;
     311             :         /* This method checks to see if two rect clips can be safely merged into one. The issue here
     312             :           is that to be strictly correct all the edges of the resulting rect must have the same
     313             :           anti-aliasing. */
     314             :         bool rectRectIntersectAllowed(const SkRect& newR, bool newAA) const;
     315             :         /** Determines possible finite bounds for the Element given the previous element of the
     316             :             stack */
     317             :         void updateBoundAndGenID(const Element* prior);
     318             :         // The different combination of fill & inverse fill when combining bounding boxes
     319             :         enum FillCombo {
     320             :             kPrev_Cur_FillCombo,
     321             :             kPrev_InvCur_FillCombo,
     322             :             kInvPrev_Cur_FillCombo,
     323             :             kInvPrev_InvCur_FillCombo
     324             :         };
     325             :         // per-set operation functions used by updateBoundAndGenID().
     326             :         inline void combineBoundsDiff(FillCombo combination, const SkRect& prevFinite);
     327             :         inline void combineBoundsXOR(int combination, const SkRect& prevFinite);
     328             :         inline void combineBoundsUnion(int combination, const SkRect& prevFinite);
     329             :         inline void combineBoundsIntersection(int combination, const SkRect& prevFinite);
     330             :         inline void combineBoundsRevDiff(int combination, const SkRect& prevFinite);
     331             :     };
     332             : 
     333             :     SkClipStack();
     334             :     SkClipStack(void* storage, size_t size);
     335             :     SkClipStack(const SkClipStack& b);
     336             :     ~SkClipStack();
     337             : 
     338             :     SkClipStack& operator=(const SkClipStack& b);
     339             :     bool operator==(const SkClipStack& b) const;
     340             :     bool operator!=(const SkClipStack& b) const { return !(*this == b); }
     341             : 
     342             :     void reset();
     343             : 
     344             :     int getSaveCount() const { return fSaveCount; }
     345             :     void save();
     346             :     void restore();
     347             : 
     348             :     class AutoRestore {
     349             :     public:
     350             :         AutoRestore(SkClipStack* cs, bool doSave)
     351             :             : fCS(cs), fSaveCount(cs->getSaveCount())
     352             :         {
     353             :             if (doSave) {
     354             :                 fCS->save();
     355             :             }
     356             :         }
     357             :         ~AutoRestore() {
     358             :             SkASSERT(fCS->getSaveCount() >= fSaveCount);  // no underflow
     359             :             while (fCS->getSaveCount() > fSaveCount) {
     360             :                 fCS->restore();
     361             :             }
     362             :         }
     363             : 
     364             :     private:
     365             :         SkClipStack* fCS;
     366             :         const int    fSaveCount;
     367             :     };
     368             : 
     369             :     /**
     370             :      * getBounds places the current finite bound in its first parameter. In its
     371             :      * second, it indicates which kind of bound is being returned. If
     372             :      * 'canvFiniteBound' is a normal bounding box then it encloses all writeable
     373             :      * pixels. If 'canvFiniteBound' is an inside out bounding box then it
     374             :      * encloses all the un-writeable pixels and the true/normal bound is the
     375             :      * infinite plane. isIntersectionOfRects is an optional parameter
     376             :      * that is true if 'canvFiniteBound' resulted from an intersection of rects.
     377             :      */
     378             :     void getBounds(SkRect* canvFiniteBound,
     379             :                    BoundsType* boundType,
     380             :                    bool* isIntersectionOfRects = NULL) const;
     381             : 
     382             :     SkRect bounds(const SkIRect& deviceBounds) const;
     383             :     bool isEmpty(const SkIRect& deviceBounds) const;
     384             : 
     385             :     /**
     386             :      * Returns true if the input (r)rect in device space is entirely contained
     387             :      * by the clip. A return value of false does not guarantee that the (r)rect
     388             :      * is not contained by the clip.
     389             :      */
     390           0 :     bool quickContains(const SkRect& devRect) const {
     391           0 :         return this->isWideOpen() || this->internalQuickContains(devRect);
     392             :     }
     393             : 
     394           0 :     bool quickContains(const SkRRect& devRRect) const {
     395           0 :         return this->isWideOpen() || this->internalQuickContains(devRRect);
     396             :     }
     397             : 
     398             :     /**
     399             :      * Flattens the clip stack into a single SkPath. Returns true if any of
     400             :      * the clip stack components requires anti-aliasing.
     401             :      */
     402             :     bool asPath(SkPath* path) const;
     403             : 
     404           0 :     void clipDevRect(const SkIRect& ir, SkClipOp op) {
     405             :         SkRect r;
     406           0 :         r.set(ir);
     407           0 :         this->clipRect(r, SkMatrix::I(), op, false);
     408           0 :     }
     409             :     void clipRect(const SkRect&, const SkMatrix& matrix, SkClipOp, bool doAA);
     410             :     void clipRRect(const SkRRect&, const SkMatrix& matrix, SkClipOp, bool doAA);
     411             :     void clipPath(const SkPath&, const SkMatrix& matrix, SkClipOp, bool doAA);
     412             :     // An optimized version of clipDevRect(emptyRect, kIntersect, ...)
     413             :     void clipEmpty();
     414           0 :     void setDeviceClipRestriction(const SkIRect& rect) {
     415           0 :         fClipRestrictionRect = SkRect::Make(rect);
     416           0 :     }
     417             : 
     418             :     /**
     419             :      * isWideOpen returns true if the clip state corresponds to the infinite
     420             :      * plane (i.e., draws are not limited at all)
     421             :      */
     422           0 :     bool isWideOpen() const { return this->getTopmostGenID() == kWideOpenGenID; }
     423             : 
     424             :     /**
     425             :      * This method quickly and conservatively determines whether the entire stack is equivalent to
     426             :      * intersection with a rrect given a bounds, where the rrect must not contain the entire bounds.
     427             :      *
     428             :      * @param bounds   A bounds on what will be drawn through the clip. The clip only need be
     429             :      *                 equivalent to a intersection with a rrect for draws within the bounds. The
     430             :      *                 returned rrect must intersect the bounds but need not be contained by the
     431             :      *                 bounds.
     432             :      * @param rrect    If return is true rrect will contain the rrect equivalent to the stack.
     433             :      * @param aa       If return is true aa will indicate whether the equivalent rrect clip is
     434             :      *                 antialiased.
     435             :      * @return true if the stack is equivalent to a single rrect intersect clip, false otherwise.
     436             :      */
     437             :     bool isRRect(const SkRect& bounds, SkRRect* rrect, bool* aa) const;
     438             : 
     439             :     /**
     440             :      * The generation ID has three reserved values to indicate special
     441             :      * (potentially ignorable) cases
     442             :      */
     443             :     static const int32_t kInvalidGenID = 0;     //!< Invalid id that is never returned by
     444             :                                                 //!< SkClipStack. Useful when caching clips
     445             :                                                 //!< based on GenID.
     446             :     static const int32_t kEmptyGenID = 1;       // no pixels writeable
     447             :     static const int32_t kWideOpenGenID = 2;    // all pixels writeable
     448             : 
     449             :     int32_t getTopmostGenID() const;
     450             : 
     451             : #ifdef SK_DEBUG
     452             :     /**
     453             :      * Dumps the contents of the clip stack to SkDebugf. This is intended for Skia development
     454             :      * debugging. Don't rely on the existence of this function or the formatting of its output.
     455             :      */
     456             :     void dump() const;
     457             : #endif
     458             : 
     459             : public:
     460             :     class Iter {
     461             :     public:
     462             :         enum IterStart {
     463             :             kBottom_IterStart = SkDeque::Iter::kFront_IterStart,
     464             :             kTop_IterStart = SkDeque::Iter::kBack_IterStart
     465             :         };
     466             : 
     467             :         /**
     468             :          * Creates an uninitialized iterator. Must be reset()
     469             :          */
     470             :         Iter();
     471             : 
     472             :         Iter(const SkClipStack& stack, IterStart startLoc);
     473             : 
     474             :         /**
     475             :          *  Return the clip element for this iterator. If next()/prev() returns NULL, then the
     476             :          *  iterator is done.
     477             :          */
     478             :         const Element* next();
     479             :         const Element* prev();
     480             : 
     481             :         /**
     482             :          * Moves the iterator to the topmost element with the specified RegionOp and returns that
     483             :          * element. If no clip element with that op is found, the first element is returned.
     484             :          */
     485             :         const Element* skipToTopmost(SkClipOp op);
     486             : 
     487             :         /**
     488             :          * Restarts the iterator on a clip stack.
     489             :          */
     490             :         void reset(const SkClipStack& stack, IterStart startLoc);
     491             : 
     492             :     private:
     493             :         const SkClipStack* fStack;
     494             :         SkDeque::Iter      fIter;
     495             :     };
     496             : 
     497             :     /**
     498             :      * The B2TIter iterates from the bottom of the stack to the top.
     499             :      * It inherits privately from Iter to prevent access to reverse iteration.
     500             :      */
     501             :     class B2TIter : private Iter {
     502             :     public:
     503             :         B2TIter() {}
     504             : 
     505             :         /**
     506             :          * Wrap Iter's 2 parameter ctor to force initialization to the
     507             :          * beginning of the deque/bottom of the stack
     508             :          */
     509           0 :         B2TIter(const SkClipStack& stack)
     510           0 :         : INHERITED(stack, kBottom_IterStart) {
     511           0 :         }
     512             : 
     513             :         using Iter::next;
     514             : 
     515             :         /**
     516             :          * Wrap Iter::reset to force initialization to the
     517             :          * beginning of the deque/bottom of the stack
     518             :          */
     519             :         void reset(const SkClipStack& stack) {
     520             :             this->INHERITED::reset(stack, kBottom_IterStart);
     521             :         }
     522             : 
     523             :     private:
     524             : 
     525             :         typedef Iter INHERITED;
     526             :     };
     527             : 
     528             :     /**
     529             :      * GetConservativeBounds returns a conservative bound of the current clip.
     530             :      * Since this could be the infinite plane (if inverse fills were involved) the
     531             :      * maxWidth and maxHeight parameters can be used to limit the returned bound
     532             :      * to the expected drawing area. Similarly, the offsetX and offsetY parameters
     533             :      * allow the caller to offset the returned bound to account for translated
     534             :      * drawing areas (i.e., those resulting from a saveLayer). For finite bounds,
     535             :      * the translation (+offsetX, +offsetY) is applied before the clamp to the
     536             :      * maximum rectangle: [0,maxWidth) x [0,maxHeight).
     537             :      * isIntersectionOfRects is an optional parameter that is true when
     538             :      * 'devBounds' is the result of an intersection of rects. In this case
     539             :      * 'devBounds' is the exact answer/clip.
     540             :      */
     541             :     void getConservativeBounds(int offsetX,
     542             :                                int offsetY,
     543             :                                int maxWidth,
     544             :                                int maxHeight,
     545             :                                SkRect* devBounds,
     546             :                                bool* isIntersectionOfRects = NULL) const;
     547             : 
     548             : private:
     549             :     friend class Iter;
     550             : 
     551             :     SkDeque fDeque;
     552             :     int     fSaveCount;
     553             : 
     554             :     // Generation ID for the clip stack. This is incremented for each
     555             :     // clipDevRect and clipDevPath call. 0 is reserved to indicate an
     556             :     // invalid ID.
     557             :     static int32_t     gGenID;
     558             :     SkRect fClipRestrictionRect = SkRect::MakeEmpty();
     559             : 
     560             :     bool internalQuickContains(const SkRect& devRect) const;
     561             :     bool internalQuickContains(const SkRRect& devRRect) const;
     562             : 
     563             :     /**
     564             :      * Helper for clipDevPath, etc.
     565             :      */
     566             :     void pushElement(const Element& element);
     567             : 
     568             :     /**
     569             :      * Restore the stack back to the specified save count.
     570             :      */
     571             :     void restoreTo(int saveCount);
     572             : 
     573           0 :     inline bool hasClipRestriction(SkClipOp op) {
     574           0 :         return op >= SkClipOp::kUnion_deprecated && !fClipRestrictionRect.isEmpty();
     575             :     }
     576             : 
     577             :     /**
     578             :      * Return the next unique generation ID.
     579             :      */
     580             :     static int32_t GetNextGenID();
     581             : };
     582             : 
     583             : #endif

Generated by: LCOV version 1.13