• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(uint32_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(uint32_t offset);
61     void appendRestore();
62     void appendTransform(const SkMatrix& trans);
63     void appendClip(uint32_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 offset into the picture stream, or kDrawComplete if complete. */
78         uint32_t draw();
79         static const uint32_t kDrawComplete = SK_MaxU32;
Iterator()80         Iterator() : fPlaybackMatrix(), fValid(false) { }
isValid()81         bool isValid() const { return fValid; }
82     private:
83         Iterator(const SkTDArray<void*>& draws, SkCanvas* canvas, Node* root);
84         // The draws this iterator is associated with
85         const SkTDArray<void*>* fDraws;
86 
87         // canvas this is playing into (so we can insert saves/restores as necessary)
88         SkCanvas* fCanvas;
89 
90         // current state node
91         Node* fCurrentNode;
92 
93         // List of nodes whose state we need to apply to reach TargetNode
94         SkTDArray<Node*> fNodes;
95 
96         // The matrix of the canvas we're playing back into
97         const SkMatrix fPlaybackMatrix;
98 
99         // Cache of current matrix, so we can avoid redundantly setting it
100         SkMatrix* fCurrentMatrix;
101 
102         // current position in the array of draws
103         int fPlaybackIndex;
104         // Whether or not we need to do a save next iteration
105         bool fSave;
106 
107         // Whether or not this is a valid iterator (the default public constructor sets this false)
108         bool fValid;
109 
110         friend class SkPictureStateTree;
111     };
112 
113 private:
114 
115     void appendNode(uint32_t offset);
116 
117     SkChunkAlloc fAlloc;
118     // Needed by saveCollapsed() because nodes do not currently store
119     // references to their children.  If they did, we could just retrieve the
120     // last added child.
121     Node* fLastRestoredNode;
122 
123     // The currently active state
124     Draw fCurrentState;
125     // A stack of states for tracking save/restores
126     SkDeque fStateStack;
127 
128     // Represents a notable piece of state that requires an offset into the command buffer,
129     // corresponding to a clip/saveLayer/etc call, to apply.
130     struct Node {
131         Node* fParent;
132         uint32_t fOffset;
133         uint16_t fLevel;
134         uint16_t fFlags;
135         SkMatrix* fMatrix;
136         enum Flags {
137             kSave_Flag      = 0x1,
138             kSaveLayer_Flag = 0x2
139         };
140     };
141 
142     Node fRoot;
143     SkMatrix fRootMatrix;
144 
145     typedef SkRefCnt INHERITED;
146 };
147 
148 #endif
149