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, returns an iterator that produces the correct sequence 54 * of offsets into the command buffer to carry out those calls with correct matrix/clip state. 55 * This handles saves/restores, and does all necessary matrix setup. 56 */ 57 Iterator getIterator(const SkTDArray<void*>& draws, SkCanvas* canvas); 58 59 void appendSave(); 60 void appendSaveLayer(size_t offset); 61 void appendRestore(); 62 void appendTransform(const SkMatrix& trans); 63 void appendClip(size_t offset); 64 65 /** 66 * Call this immediately after an appendRestore call that is associated 67 * a save or saveLayer that was removed from the command stream 68 * due to a command pattern optimization in SkPicture. 69 */ 70 void saveCollapsed(); 71 72 /** 73 * Playback helper 74 */ 75 class Iterator { 76 public: 77 /** Returns the next op offset needed to create the drawing state 78 required by the queued up draw operation or the offset of the queued 79 up draw operation itself. In the latter case, the next draw operation 80 will move into the queued up slot. 81 It retuns kDrawComplete when done. 82 TODO: this might be better named nextOp 83 */ 84 uint32_t nextDraw(); 85 static const uint32_t kDrawComplete = SK_MaxU32; 86 Iterator() : fPlaybackMatrix(), fValid(false) { } 87 bool isValid() const { return fValid; } 88 89 private: 90 Iterator(const SkTDArray<void*>& draws, SkCanvas* canvas, Node* root); 91 92 void setCurrentMatrix(const SkMatrix*); 93 94 // The draws this iterator is associated with 95 const SkTDArray<void*>* fDraws; 96 97 // canvas this is playing into (so we can insert saves/restores as necessary) 98 SkCanvas* fCanvas; 99 100 // current state node 101 Node* fCurrentNode; 102 103 // List of nodes whose state we need to apply to reach TargetNode 104 SkTDArray<Node*> fNodes; 105 106 // The matrix of the canvas we're playing back into 107 const SkMatrix fPlaybackMatrix; 108 109 // Cache of current matrix, so we can avoid redundantly setting it 110 const SkMatrix* fCurrentMatrix; 111 112 // current position in the array of draws 113 int fPlaybackIndex; 114 // Whether or not we need to do a save next iteration 115 bool fSave; 116 117 // Whether or not this is a valid iterator (the default public constructor sets this false) 118 bool fValid; 119 120 uint32_t finish(); 121 122 friend class SkPictureStateTree; 123 }; 124 125 private: 126 127 void appendNode(size_t offset); 128 129 SkChunkAlloc fAlloc; 130 // Needed by saveCollapsed() because nodes do not currently store 131 // references to their children. If they did, we could just retrieve the 132 // last added child. 133 Node* fLastRestoredNode; 134 135 // The currently active state 136 Draw fCurrentState; 137 // A stack of states for tracking save/restores 138 SkDeque fStateStack; 139 140 // Represents a notable piece of state that requires an offset into the command buffer, 141 // corresponding to a clip/saveLayer/etc call, to apply. 142 struct Node { 143 Node* fParent; 144 uint32_t fOffset; 145 uint16_t fLevel; 146 uint16_t fFlags; 147 SkMatrix* fMatrix; 148 enum Flags { 149 kSave_Flag = 0x1, 150 kSaveLayer_Flag = 0x2 151 }; 152 }; 153 154 Node fRoot; 155 SkMatrix fRootMatrix; 156 157 typedef SkRefCnt INHERITED; 158 }; 159 160 #endif 161