/* * 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(uint32_t offset); /** * Given a list of draws, and a canvas, returns 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. */ Iterator getIterator(const SkTDArray& draws, SkCanvas* canvas); void appendSave(); void appendSaveLayer(uint32_t offset); void appendRestore(); void appendTransform(const SkMatrix& trans); void appendClip(uint32_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 offset into the picture stream, or kDrawComplete if complete. */ uint32_t draw(); static const uint32_t kDrawComplete = SK_MaxU32; Iterator() : fPlaybackMatrix(), fValid(false) { } bool isValid() const { return fValid; } private: Iterator(const SkTDArray& draws, SkCanvas* canvas, Node* root); // The draws this iterator is associated with const SkTDArray* 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 fNodes; // The matrix of the canvas we're playing back into const SkMatrix fPlaybackMatrix; // Cache of current matrix, so we can avoid redundantly setting it 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; friend class SkPictureStateTree; }; private: void appendNode(uint32_t offset); SkChunkAlloc fAlloc; Node* fRoot; // 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 }; }; typedef SkRefCnt INHERITED; }; #endif