| OLD | NEW | 
|---|
| 1 |  | 
| 2 /* | 1 /* | 
| 3  * Copyright 2011 Google Inc. | 2  * Copyright 2011 Google Inc. | 
| 4  * | 3  * | 
| 5  * Use of this source code is governed by a BSD-style license that can be | 4  * Use of this source code is governed by a BSD-style license that can be | 
| 6  * found in the LICENSE file. | 5  * found in the LICENSE file. | 
| 7  */ | 6  */ | 
|  | 7 | 
| 8 #ifndef SkClipStack_DEFINED | 8 #ifndef SkClipStack_DEFINED | 
| 9 #define SkClipStack_DEFINED | 9 #define SkClipStack_DEFINED | 
| 10 | 10 | 
|  | 11 #include "SkCanvas.h" | 
| 11 #include "SkDeque.h" | 12 #include "SkDeque.h" | 
| 12 #include "SkPath.h" | 13 #include "SkPath.h" | 
| 13 #include "SkRect.h" | 14 #include "SkRect.h" | 
| 14 #include "SkRRect.h" | 15 #include "SkRRect.h" | 
| 15 #include "SkRegion.h" | 16 #include "SkRegion.h" | 
| 16 #include "SkTLazy.h" | 17 #include "SkTLazy.h" | 
| 17 | 18 | 
| 18 class SkCanvasClipVisitor; | 19 class SkCanvasClipVisitor; | 
| 19 | 20 | 
| 20 // Because a single save/restore state can have multiple clips, this class | 21 // Because a single save/restore state can have multiple clips, this class | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
| 46             //!< This element combines a round-rect with the current clip using 
     a set operation | 47             //!< This element combines a round-rect with the current clip using 
     a set operation | 
| 47             kRRect_Type, | 48             kRRect_Type, | 
| 48             //!< This element combines a path with the current clip using a set 
     operation | 49             //!< This element combines a path with the current clip using a set 
     operation | 
| 49             kPath_Type, | 50             kPath_Type, | 
| 50 | 51 | 
| 51             kLastType = kPath_Type | 52             kLastType = kPath_Type | 
| 52         }; | 53         }; | 
| 53         static const int kTypeCnt = kLastType + 1; | 54         static const int kTypeCnt = kLastType + 1; | 
| 54 | 55 | 
| 55         Element() { | 56         Element() { | 
| 56             this->initCommon(0, SkRegion::kReplace_Op, false); | 57             this->initCommon(0, SkCanvas::kReplace_Op, false); | 
| 57             this->setEmpty(); | 58             this->setEmpty(); | 
| 58         } | 59         } | 
| 59 | 60 | 
| 60         Element(const Element&); | 61         Element(const Element&); | 
| 61 | 62 | 
| 62         Element(const SkRect& rect, SkRegion::Op op, bool doAA) { | 63         Element(const SkRect& rect, SkCanvas::ClipOp op, bool doAA) { | 
| 63             this->initRect(0, rect, op, doAA); | 64             this->initRect(0, rect, op, doAA); | 
| 64         } | 65         } | 
| 65 | 66 | 
| 66         Element(const SkRRect& rrect, SkRegion::Op op, bool doAA) { | 67         Element(const SkRRect& rrect, SkCanvas::ClipOp op, bool doAA) { | 
| 67             this->initRRect(0, rrect, op, doAA); | 68             this->initRRect(0, rrect, op, doAA); | 
| 68         } | 69         } | 
| 69 | 70 | 
| 70         Element(const SkPath& path, SkRegion::Op op, bool doAA) { | 71         Element(const SkPath& path, SkCanvas::ClipOp op, bool doAA) { | 
| 71             this->initPath(0, path, op, doAA); | 72             this->initPath(0, path, op, doAA); | 
| 72         } | 73         } | 
| 73 | 74 | 
| 74         bool operator== (const Element& element) const; | 75         bool operator== (const Element& element) const; | 
| 75         bool operator!= (const Element& element) const { return !(*this == eleme
     nt); } | 76         bool operator!= (const Element& element) const { return !(*this == eleme
     nt); } | 
| 76 | 77 | 
| 77         //!< Call to get the type of the clip element. | 78         //!< Call to get the type of the clip element. | 
| 78         Type getType() const { return fType; } | 79         Type getType() const { return fType; } | 
| 79 | 80 | 
| 80         //!< Call to get the save count associated with this clip element. | 81         //!< Call to get the save count associated with this clip element. | 
| 81         int getSaveCount() const { return fSaveCount; } | 82         int getSaveCount() const { return fSaveCount; } | 
| 82 | 83 | 
| 83         //!< Call if getType() is kPath to get the path. | 84         //!< Call if getType() is kPath to get the path. | 
| 84         const SkPath& getPath() const { SkASSERT(kPath_Type == fType); return *f
     Path.get(); } | 85         const SkPath& getPath() const { SkASSERT(kPath_Type == fType); return *f
     Path.get(); } | 
| 85 | 86 | 
| 86         //!< Call if getType() is kRRect to get the round-rect. | 87         //!< Call if getType() is kRRect to get the round-rect. | 
| 87         const SkRRect& getRRect() const { SkASSERT(kRRect_Type == fType); return
      fRRect; } | 88         const SkRRect& getRRect() const { SkASSERT(kRRect_Type == fType); return
      fRRect; } | 
| 88 | 89 | 
| 89         //!< Call if getType() is kRect to get the rect. | 90         //!< Call if getType() is kRect to get the rect. | 
| 90         const SkRect& getRect() const { | 91         const SkRect& getRect() const { | 
| 91             SkASSERT(kRect_Type == fType && (fRRect.isRect() || fRRect.isEmpty()
     )); | 92             SkASSERT(kRect_Type == fType && (fRRect.isRect() || fRRect.isEmpty()
     )); | 
| 92             return fRRect.getBounds(); | 93             return fRRect.getBounds(); | 
| 93         } | 94         } | 
| 94 | 95 | 
| 95         //!< Call if getType() is not kEmpty to get the set operation used to co
     mbine this element. | 96         //!< Call if getType() is not kEmpty to get the set operation used to co
     mbine this element. | 
| 96         SkRegion::Op getOp() const { return fOp; } | 97         SkCanvas::ClipOp getOp() const { return fOp; } | 
| 97 | 98 | 
| 98         //!< Call to get the element as a path, regardless of its type. | 99         //!< Call to get the element as a path, regardless of its type. | 
| 99         void asPath(SkPath* path) const; | 100         void asPath(SkPath* path) const; | 
| 100 | 101 | 
| 101         //!< Call if getType() is not kPath to get the element as a round rect. | 102         //!< Call if getType() is not kPath to get the element as a round rect. | 
| 102         const SkRRect& asRRect() const { SkASSERT(kPath_Type != fType); return f
     RRect; } | 103         const SkRRect& asRRect() const { SkASSERT(kPath_Type != fType); return f
     RRect; } | 
| 103 | 104 | 
| 104         /** If getType() is not kEmpty this indicates whether the clip shape sho
     uld be anti-aliased | 105         /** If getType() is not kEmpty this indicates whether the clip shape sho
     uld be anti-aliased | 
| 105             when it is rasterized. */ | 106             when it is rasterized. */ | 
| 106         bool isAA() const { return fDoAA; } | 107         bool isAA() const { return fDoAA; } | 
| 107 | 108 | 
| 108         //!< Inverts the fill of the clip shape. Note that a kEmpty element rema
     ins kEmpty. | 109         //!< Inverts the fill of the clip shape. Note that a kEmpty element rema
     ins kEmpty. | 
| 109         void invertShapeFillType(); | 110         void invertShapeFillType(); | 
| 110 | 111 | 
| 111         //!< Sets the set operation represented by the element. | 112         //!< Sets the set operation represented by the element. | 
| 112         void setOp(SkRegion::Op op) { fOp = op; } | 113         void setOp(SkCanvas::ClipOp op) { fOp = op; } | 
| 113 | 114 | 
| 114         /** The GenID can be used by clip stack clients to cache representations
      of the clip. The | 115         /** The GenID can be used by clip stack clients to cache representations
      of the clip. The | 
| 115             ID corresponds to the set of clip elements up to and including this 
     element within the | 116             ID corresponds to the set of clip elements up to and including this 
     element within the | 
| 116             stack not to the element itself. That is the same clip path in diffe
     rent stacks will | 117             stack not to the element itself. That is the same clip path in diffe
     rent stacks will | 
| 117             have a different ID since the elements produce different clip result
      in the context of | 118             have a different ID since the elements produce different clip result
      in the context of | 
| 118             their stacks. */ | 119             their stacks. */ | 
| 119         int32_t getGenID() const { SkASSERT(kInvalidGenID != fGenID); return fGe
     nID; } | 120         int32_t getGenID() const { SkASSERT(kInvalidGenID != fGenID); return fGe
     nID; } | 
| 120 | 121 | 
| 121         /** | 122         /** | 
| 122          * Gets the bounds of the clip element, either the rect or path bounds. 
     (Whether the shape | 123          * Gets the bounds of the clip element, either the rect or path bounds. 
     (Whether the shape | 
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 194          */ | 195          */ | 
| 195         void dump() const; | 196         void dump() const; | 
| 196 #endif | 197 #endif | 
| 197 | 198 | 
| 198     private: | 199     private: | 
| 199         friend class SkClipStack; | 200         friend class SkClipStack; | 
| 200 | 201 | 
| 201         SkTLazy<SkPath> fPath; | 202         SkTLazy<SkPath> fPath; | 
| 202         SkRRect         fRRect; | 203         SkRRect         fRRect; | 
| 203         int             fSaveCount; // save count of stack when this element was
      added. | 204         int             fSaveCount; // save count of stack when this element was
      added. | 
| 204         SkRegion::Op    fOp; | 205         SkCanvas::ClipOp fOp; | 
| 205         Type            fType; | 206         Type            fType; | 
| 206         bool            fDoAA; | 207         bool            fDoAA; | 
| 207 | 208 | 
| 208         /* fFiniteBoundType and fFiniteBound are used to incrementally update th
     e clip stack's | 209         /* fFiniteBoundType and fFiniteBound are used to incrementally update th
     e clip stack's | 
| 209            bound. When fFiniteBoundType is kNormal_BoundsType, fFiniteBound repr
     esents the | 210            bound. When fFiniteBoundType is kNormal_BoundsType, fFiniteBound repr
     esents the | 
| 210            conservative bounding box of the pixels that aren't clipped (i.e., an
     y pixels that can be | 211            conservative bounding box of the pixels that aren't clipped (i.e., an
     y pixels that can be | 
| 211            drawn to are inside the bound). When fFiniteBoundType is kInsideOut_B
     oundsType (which | 212            drawn to are inside the bound). When fFiniteBoundType is kInsideOut_B
     oundsType (which | 
| 212            occurs when a clip is inverse filled), fFiniteBound represents the co
     nservative bounding | 213            occurs when a clip is inverse filled), fFiniteBound represents the co
     nservative bounding | 
| 213            box of the pixels that _are_ clipped (i.e., any pixels that cannot be
      drawn to are inside | 214            box of the pixels that _are_ clipped (i.e., any pixels that cannot be
      drawn to are inside | 
| 214            the bound). When fFiniteBoundType is kInsideOut_BoundsType the actual
      bound is the | 215            the bound). When fFiniteBoundType is kInsideOut_BoundsType the actual
      bound is the | 
| 215            infinite plane. This behavior of fFiniteBoundType and fFiniteBound is
      required so that we | 216            infinite plane. This behavior of fFiniteBoundType and fFiniteBound is
      required so that we | 
| 216            can capture the cancelling out of the extensions to infinity when two
      inverse filled | 217            can capture the cancelling out of the extensions to infinity when two
      inverse filled | 
| 217            clips are Booleaned together. */ | 218            clips are Booleaned together. */ | 
| 218         SkClipStack::BoundsType fFiniteBoundType; | 219         SkClipStack::BoundsType fFiniteBoundType; | 
| 219         SkRect                  fFiniteBound; | 220         SkRect                  fFiniteBound; | 
| 220 | 221 | 
| 221         // When element is applied to the previous elements in the stack is the 
     result known to be | 222         // When element is applied to the previous elements in the stack is the 
     result known to be | 
| 222         // equivalent to a single rect intersection? IIOW, is the clip effective
     ly a rectangle. | 223         // equivalent to a single rect intersection? IIOW, is the clip effective
     ly a rectangle. | 
| 223         bool                    fIsIntersectionOfRects; | 224         bool                    fIsIntersectionOfRects; | 
| 224 | 225 | 
| 225         int                     fGenID; | 226         int                     fGenID; | 
| 226 | 227 | 
| 227         Element(int saveCount) { | 228         Element(int saveCount) { | 
| 228             this->initCommon(saveCount, SkRegion::kReplace_Op, false); | 229             this->initCommon(saveCount, SkCanvas::kReplace_Op, false); | 
| 229             this->setEmpty(); | 230             this->setEmpty(); | 
| 230         } | 231         } | 
| 231 | 232 | 
| 232         Element(int saveCount, const SkRRect& rrect, SkRegion::Op op, bool doAA)
      { | 233         Element(int saveCount, const SkRRect& rrect, SkCanvas::ClipOp op, bool d
     oAA) { | 
| 233             this->initRRect(saveCount, rrect, op, doAA); | 234             this->initRRect(saveCount, rrect, op, doAA); | 
| 234         } | 235         } | 
| 235 | 236 | 
| 236         Element(int saveCount, const SkRect& rect, SkRegion::Op op, bool doAA) { | 237         Element(int saveCount, const SkRect& rect, SkCanvas::ClipOp op, bool doA
     A) { | 
| 237             this->initRect(saveCount, rect, op, doAA); | 238             this->initRect(saveCount, rect, op, doAA); | 
| 238         } | 239         } | 
| 239 | 240 | 
| 240         Element(int saveCount, const SkPath& path, SkRegion::Op op, bool doAA) { | 241         Element(int saveCount, const SkPath& path, SkCanvas::ClipOp op, bool doA
     A) { | 
| 241             this->initPath(saveCount, path, op, doAA); | 242             this->initPath(saveCount, path, op, doAA); | 
| 242         } | 243         } | 
| 243 | 244 | 
| 244         void initCommon(int saveCount, SkRegion::Op op, bool doAA) { | 245         void initCommon(int saveCount, SkCanvas::ClipOp op, bool doAA) { | 
| 245             fSaveCount = saveCount; | 246             fSaveCount = saveCount; | 
| 246             fOp = op; | 247             fOp = op; | 
| 247             fDoAA = doAA; | 248             fDoAA = doAA; | 
| 248             // A default of inside-out and empty bounds means the bounds are eff
     ectively void as it | 249             // A default of inside-out and empty bounds means the bounds are eff
     ectively void as it | 
| 249             // indicates that nothing is known to be outside the clip. | 250             // indicates that nothing is known to be outside the clip. | 
| 250             fFiniteBoundType = kInsideOut_BoundsType; | 251             fFiniteBoundType = kInsideOut_BoundsType; | 
| 251             fFiniteBound.setEmpty(); | 252             fFiniteBound.setEmpty(); | 
| 252             fIsIntersectionOfRects = false; | 253             fIsIntersectionOfRects = false; | 
| 253             fGenID = kInvalidGenID; | 254             fGenID = kInvalidGenID; | 
| 254         } | 255         } | 
| 255 | 256 | 
| 256         void initRect(int saveCount, const SkRect& rect, SkRegion::Op op, bool d
     oAA) { | 257         void initRect(int saveCount, const SkRect& rect, SkCanvas::ClipOp op, bo
     ol doAA) { | 
| 257             fRRect.setRect(rect); | 258             fRRect.setRect(rect); | 
| 258             fType = kRect_Type; | 259             fType = kRect_Type; | 
| 259             this->initCommon(saveCount, op, doAA); | 260             this->initCommon(saveCount, op, doAA); | 
| 260         } | 261         } | 
| 261 | 262 | 
| 262         void initRRect(int saveCount, const SkRRect& rrect, SkRegion::Op op, boo
     l doAA) { | 263         void initRRect(int saveCount, const SkRRect& rrect, SkCanvas::ClipOp op,
      bool doAA) { | 
| 263             SkRRect::Type type = rrect.getType(); | 264             SkRRect::Type type = rrect.getType(); | 
| 264             fRRect = rrect; | 265             fRRect = rrect; | 
| 265             if (SkRRect::kRect_Type == type || SkRRect::kEmpty_Type == type) { | 266             if (SkRRect::kRect_Type == type || SkRRect::kEmpty_Type == type) { | 
| 266                 fType = kRect_Type; | 267                 fType = kRect_Type; | 
| 267             } else { | 268             } else { | 
| 268                 fType = kRRect_Type; | 269                 fType = kRRect_Type; | 
| 269             } | 270             } | 
| 270             this->initCommon(saveCount, op, doAA); | 271             this->initCommon(saveCount, op, doAA); | 
| 271         } | 272         } | 
| 272 | 273 | 
| 273         void initPath(int saveCount, const SkPath& path, SkRegion::Op op, bool d
     oAA); | 274         void initPath(int saveCount, const SkPath& path, SkCanvas::ClipOp op, bo
     ol doAA); | 
| 274 | 275 | 
| 275         void setEmpty(); | 276         void setEmpty(); | 
| 276 | 277 | 
| 277         // All Element methods below are only used within SkClipStack.cpp | 278         // All Element methods below are only used within SkClipStack.cpp | 
| 278         inline void checkEmpty() const; | 279         inline void checkEmpty() const; | 
| 279         inline bool canBeIntersectedInPlace(int saveCount, SkRegion::Op op) cons
     t; | 280         inline bool canBeIntersectedInPlace(int saveCount, SkCanvas::ClipOp op) 
     const; | 
| 280         /* This method checks to see if two rect clips can be safely merged into
      one. The issue here | 281         /* This method checks to see if two rect clips can be safely merged into
      one. The issue here | 
| 281           is that to be strictly correct all the edges of the resulting rect mus
     t have the same | 282           is that to be strictly correct all the edges of the resulting rect mus
     t have the same | 
| 282           anti-aliasing. */ | 283           anti-aliasing. */ | 
| 283         bool rectRectIntersectAllowed(const SkRect& newR, bool newAA) const; | 284         bool rectRectIntersectAllowed(const SkRect& newR, bool newAA) const; | 
| 284         /** Determines possible finite bounds for the Element given the previous
      element of the | 285         /** Determines possible finite bounds for the Element given the previous
      element of the | 
| 285             stack */ | 286             stack */ | 
| 286         void updateBoundAndGenID(const Element* prior); | 287         void updateBoundAndGenID(const Element* prior); | 
| 287         // The different combination of fill & inverse fill when combining bound
     ing boxes | 288         // The different combination of fill & inverse fill when combining bound
     ing boxes | 
| 288         enum FillCombo { | 289         enum FillCombo { | 
| 289             kPrev_Cur_FillCombo, | 290             kPrev_Cur_FillCombo, | 
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 340     bool quickContains(const SkRRect& devRRect) const { | 341     bool quickContains(const SkRRect& devRRect) const { | 
| 341         return this->isWideOpen() || this->internalQuickContains(devRRect); | 342         return this->isWideOpen() || this->internalQuickContains(devRRect); | 
| 342     } | 343     } | 
| 343 | 344 | 
| 344     /** | 345     /** | 
| 345      * Flattens the clip stack into a single SkPath. Returns true if any of | 346      * Flattens the clip stack into a single SkPath. Returns true if any of | 
| 346      * the clip stack components requires anti-aliasing. | 347      * the clip stack components requires anti-aliasing. | 
| 347      */ | 348      */ | 
| 348     bool asPath(SkPath* path) const; | 349     bool asPath(SkPath* path) const; | 
| 349 | 350 | 
| 350     void clipDevRect(const SkIRect& ir, SkRegion::Op op) { | 351     void clipDevRect(const SkIRect& ir, SkCanvas::ClipOp op) { | 
| 351         SkRect r; | 352         SkRect r; | 
| 352         r.set(ir); | 353         r.set(ir); | 
| 353         this->clipDevRect(r, op, false); | 354         this->clipDevRect(r, op, false); | 
| 354     } | 355     } | 
| 355     void clipDevRect(const SkRect&, SkRegion::Op, bool doAA); | 356     void clipDevRect(const SkRect&, SkCanvas::ClipOp, bool doAA); | 
| 356     void clipDevRRect(const SkRRect&, SkRegion::Op, bool doAA); | 357     void clipDevRRect(const SkRRect&, SkCanvas::ClipOp, bool doAA); | 
| 357     void clipDevPath(const SkPath&, SkRegion::Op, bool doAA); | 358     void clipDevPath(const SkPath&, SkCanvas::ClipOp, bool doAA); | 
| 358     // An optimized version of clipDevRect(emptyRect, kIntersect, ...) | 359     // An optimized version of clipDevRect(emptyRect, kIntersect, ...) | 
| 359     void clipEmpty(); | 360     void clipEmpty(); | 
| 360 | 361 | 
| 361     /** | 362     /** | 
| 362      * isWideOpen returns true if the clip state corresponds to the infinite | 363      * isWideOpen returns true if the clip state corresponds to the infinite | 
| 363      * plane (i.e., draws are not limited at all) | 364      * plane (i.e., draws are not limited at all) | 
| 364      */ | 365      */ | 
| 365     bool isWideOpen() const { return this->getTopmostGenID() == kWideOpenGenID; 
     } | 366     bool isWideOpen() const { return this->getTopmostGenID() == kWideOpenGenID; 
     } | 
| 366 | 367 | 
| 367     /** | 368     /** | 
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 418          *  Return the clip element for this iterator. If next()/prev() returns 
     NULL, then the | 419          *  Return the clip element for this iterator. If next()/prev() returns 
     NULL, then the | 
| 419          *  iterator is done. | 420          *  iterator is done. | 
| 420          */ | 421          */ | 
| 421         const Element* next(); | 422         const Element* next(); | 
| 422         const Element* prev(); | 423         const Element* prev(); | 
| 423 | 424 | 
| 424         /** | 425         /** | 
| 425          * Moves the iterator to the topmost element with the specified RegionOp
      and returns that | 426          * Moves the iterator to the topmost element with the specified RegionOp
      and returns that | 
| 426          * element. If no clip element with that op is found, the first element 
     is returned. | 427          * element. If no clip element with that op is found, the first element 
     is returned. | 
| 427          */ | 428          */ | 
| 428         const Element* skipToTopmost(SkRegion::Op op); | 429         const Element* skipToTopmost(SkCanvas::ClipOp op); | 
| 429 | 430 | 
| 430         /** | 431         /** | 
| 431          * Restarts the iterator on a clip stack. | 432          * Restarts the iterator on a clip stack. | 
| 432          */ | 433          */ | 
| 433         void reset(const SkClipStack& stack, IterStart startLoc); | 434         void reset(const SkClipStack& stack, IterStart startLoc); | 
| 434 | 435 | 
| 435     private: | 436     private: | 
| 436         const SkClipStack* fStack; | 437         const SkClipStack* fStack; | 
| 437         SkDeque::Iter      fIter; | 438         SkDeque::Iter      fIter; | 
| 438     }; | 439     }; | 
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 512      */ | 513      */ | 
| 513     void restoreTo(int saveCount); | 514     void restoreTo(int saveCount); | 
| 514 | 515 | 
| 515     /** | 516     /** | 
| 516      * Return the next unique generation ID. | 517      * Return the next unique generation ID. | 
| 517      */ | 518      */ | 
| 518     static int32_t GetNextGenID(); | 519     static int32_t GetNextGenID(); | 
| 519 }; | 520 }; | 
| 520 | 521 | 
| 521 #endif | 522 #endif | 
| OLD | NEW | 
|---|