| /* | |
| * Copyright 2012 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef SkPictureStateTree_DEFINED | |
| #define SkPictureStateTree_DEFINED | |
| #include "SkTDArray.h" | |
| #include "SkChunkAlloc.h" | |
| #include "SkDeque.h" | |
| #include "SkMatrix.h" | |
| #include "SkRefCnt.h" | |
| class SkCanvas; | |
| /** | |
| * Provides an interface that, given a sequence of draws into an SkPicture with corresponding | |
| * offsets, allows for playback of an arbitrary subset of the draws (note that Z-order is only | |
| * guaranteed if the draws are explicitly sorted). | |
| */ | |
| class SkPictureStateTree : public SkRefCnt { | |
| private: | |
| struct Node; | |
| public: | |
| SK_DECLARE_INST_COUNT(SkPictureStateTree) | |
| /** | |
| * A draw call, stores offset into command buffer, a pointer to the matrix, and a pointer to | |
| * the node in the tree that corresponds to its clip/layer state | |
| */ | |
| struct Draw { | |
| SkMatrix* fMatrix; | |
| Node* fNode; | |
| uint32_t fOffset; | |
| bool operator<(const Draw& other) const { return fOffset < other.fOffset; } | |
| }; | |
| class Iterator; | |
| SkPictureStateTree(); | |
| ~SkPictureStateTree(); | |
| /** | |
| * Creates and returns a struct representing a draw at the given offset. | |
| */ | |
| Draw* appendDraw(size_t offset); | |
| /** | |
| * Given a list of draws, and a canvas, initialize an iterator that produces the correct | |
| * sequence of offsets into the command buffer to carry out those calls with correct | |
| * matrix/clip state. This handles saves/restores, and does all necessary matrix setup. | |
| */ | |
| void initIterator(SkPictureStateTree::Iterator* iter, | |
| const SkTDArray<void*>& draws, | |
| SkCanvas* canvas); | |
| void appendSave(); | |
| void appendSaveLayer(size_t offset); | |
| void appendRestore(); | |
| void appendTransform(const SkMatrix& trans); | |
| void appendClip(size_t offset); | |
| /** | |
| * Call this immediately after an appendRestore call that is associated | |
| * a save or saveLayer that was removed from the command stream | |
| * due to a command pattern optimization in SkPicture. | |
| */ | |
| void saveCollapsed(); | |
| /** | |
| * Playback helper | |
| */ | |
| class Iterator { | |
| public: | |
| /** Returns the next op offset needed to create the drawing state | |
| required by the queued up draw operation or the offset of the queued | |
| up draw operation itself. In the latter case, the next draw operation | |
| will move into the queued up slot. | |
| It retuns kDrawComplete when done. | |
| TODO: this might be better named nextOp | |
| */ | |
| uint32_t nextDraw(); | |
| static const uint32_t kDrawComplete = SK_MaxU32; | |
| Iterator() : fValid(false) { } | |
| bool isValid() const { return fValid; } | |
| private: | |
| void init(const SkTDArray<void*>& draws, SkCanvas* canvas, Node* root); | |
| void setCurrentMatrix(const SkMatrix*); | |
| // The draws this iterator is associated with | |
| const SkTDArray<void*>* fDraws; | |
| // canvas this is playing into (so we can insert saves/restores as necessary) | |
| SkCanvas* fCanvas; | |
| // current state node | |
| Node* fCurrentNode; | |
| // List of nodes whose state we need to apply to reach TargetNode | |
| SkTDArray<Node*> fNodes; | |
| // The matrix of the canvas we're playing back into | |
| SkMatrix fPlaybackMatrix; | |
| // Cache of current matrix, so we can avoid redundantly setting it | |
| const SkMatrix* fCurrentMatrix; | |
| // current position in the array of draws | |
| int fPlaybackIndex; | |
| // Whether or not we need to do a save next iteration | |
| bool fSave; | |
| // Whether or not this is a valid iterator (the default public constructor sets this false) | |
| bool fValid; | |
| uint32_t finish(); | |
| friend class SkPictureStateTree; | |
| }; | |
| private: | |
| void appendNode(size_t offset); | |
| SkChunkAlloc fAlloc; | |
| // Needed by saveCollapsed() because nodes do not currently store | |
| // references to their children. If they did, we could just retrieve the | |
| // last added child. | |
| Node* fLastRestoredNode; | |
| // The currently active state | |
| Draw fCurrentState; | |
| // A stack of states for tracking save/restores | |
| SkDeque fStateStack; | |
| // Represents a notable piece of state that requires an offset into the command buffer, | |
| // corresponding to a clip/saveLayer/etc call, to apply. | |
| struct Node { | |
| Node* fParent; | |
| uint32_t fOffset; | |
| uint16_t fLevel; | |
| uint16_t fFlags; | |
| SkMatrix* fMatrix; | |
| enum Flags { | |
| kSave_Flag = 0x1, | |
| kSaveLayer_Flag = 0x2 | |
| }; | |
| }; | |
| Node fRoot; | |
| SkMatrix fRootMatrix; | |
| typedef SkRefCnt INHERITED; | |
| }; | |
| #endif |