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
18class 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 */
25class SkPictureStateTree : public SkRefCnt {
26private:
27    struct Node;
28public:
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
127private:
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