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