| 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 |