1 2 /* 3 * Copyright 2012 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 #ifndef SkPictureStateTree_DEFINED 10 #define SkPictureStateTree_DEFINED 11 12 #include "SkTDArray.h" 13 #include "SkChunkAlloc.h" 14 #include "SkDeque.h" 15 #include "SkMatrix.h" 16 #include "SkRefCnt.h" 17 18 class SkCanvas; 19 20 /** 21 * Provides an interface that, given a sequence of draws into an SkPicture with corresponding 22 * offsets, allows for playback of an arbitrary subset of the draws (note that Z-order is only 23 * guaranteed if the draws are explicitly sorted). 24 */ 25 class SkPictureStateTree : public SkRefCnt { 26 private: 27 struct Node; 28 public: 29 SK_DECLARE_INST_COUNT(SkPictureStateTree) 30 31 /** 32 * A draw call, stores offset into command buffer, a pointer to the matrix, and a pointer to 33 * the node in the tree that corresponds to its clip/layer state 34 */ 35 struct Draw { 36 SkMatrix* fMatrix; 37 Node* fNode; 38 uint32_t fOffset; 39 bool operator<(const Draw& other) const { return fOffset < other.fOffset; } 40 }; 41 42 class Iterator; 43 44 SkPictureStateTree(); 45 ~SkPictureStateTree(); 46 47 /** 48 * Creates and returns a struct representing a draw at the given offset. 49 */ 50 Draw* appendDraw(size_t offset); 51 52 /** 53 * Given a list of draws, and a canvas, initialize an iterator that produces the correct 54 * sequence of offsets into the command buffer to carry out those calls with correct 55 * matrix/clip state. This handles saves/restores, and does all necessary matrix setup. 56 */ 57 void initIterator(SkPictureStateTree::Iterator* iter, 58 const SkTDArray<void*>& draws, 59 SkCanvas* canvas); 60 61 void appendSave(); 62 void appendSaveLayer(size_t offset); 63 void appendRestore(); 64 void appendTransform(const SkMatrix& trans); 65 void appendClip(size_t offset); 66 67 /** 68 * Call this immediately after an appendRestore call that is associated 69 * a save or saveLayer that was removed from the command stream 70 * due to a command pattern optimization in SkPicture. 71 */ 72 void saveCollapsed(); 73 74 /** 75 * Playback helper 76 */ 77 class Iterator { 78 public: 79 /** Returns the next op offset needed to create the drawing state 80 required by the queued up draw operation or the offset of the queued 81 up draw operation itself. In the latter case, the next draw operation 82 will move into the queued up slot. 83 It retuns kDrawComplete when done. 84 TODO: this might be better named nextOp 85 */ 86 uint32_t nextDraw(); 87 static const uint32_t kDrawComplete = SK_MaxU32; 88 Iterator() : fValid(false) { } 89 bool isValid() const { return fValid; } 90 91 private: 92 void init(const SkTDArray<void*>& draws, SkCanvas* canvas, Node* root); 93 94 void setCurrentMatrix(const SkMatrix*); 95 96 // The draws this iterator is associated with 97 const SkTDArray<void*>* fDraws; 98 99 // canvas this is playing into (so we can insert saves/restores as necessary) 100 SkCanvas* fCanvas; 101 102 // current state node 103 Node* fCurrentNode; 104 105 // List of nodes whose state we need to apply to reach TargetNode 106 SkTDArray<Node*> fNodes; 107 108 // The matrix of the canvas we're playing back into 109 SkMatrix fPlaybackMatrix; 110 111 // Cache of current matrix, so we can avoid redundantly setting it 112 const SkMatrix* fCurrentMatrix; 113 114 // current position in the array of draws 115 int fPlaybackIndex; 116 // Whether or not we need to do a save next iteration 117 bool fSave; 118 119 // Whether or not this is a valid iterator (the default public constructor sets this false) 120 bool fValid; 121 122 uint32_t finish(); 123 124 friend class SkPictureStateTree; 125 }; 126 127 private: 128 129 void appendNode(size_t offset); 130 131 SkChunkAlloc fAlloc; 132 // Needed by saveCollapsed() because nodes do not currently store 133 // references to their children. If they did, we could just retrieve the 134 // last added child. 135 Node* fLastRestoredNode; 136 137 // The currently active state 138 Draw fCurrentState; 139 // A stack of states for tracking save/restores 140 SkDeque fStateStack; 141 142 // Represents a notable piece of state that requires an offset into the command buffer, 143 // corresponding to a clip/saveLayer/etc call, to apply. 144 struct Node { 145 Node* fParent; 146 uint32_t fOffset; 147 uint16_t fLevel; 148 uint16_t fFlags; 149 SkMatrix* fMatrix; 150 enum Flags { 151 kSave_Flag = 0x1, 152 kSaveLayer_Flag = 0x2 153 }; 154 }; 155 156 Node fRoot; 157 SkMatrix fRootMatrix; 158 159 typedef SkRefCnt INHERITED; 160 }; 161 162 #endif 163