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(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;
80        Iterator() : fPlaybackMatrix(), fValid(false) { }
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
113private:
114
115    void appendNode(uint32_t offset);
116
117    SkChunkAlloc fAlloc;
118    Node* fRoot;
119    // Needed by saveCollapsed() because nodes do not currently store
120    // references to their children.  If they did, we could just retrieve the
121    // last added child.
122    Node* fLastRestoredNode;
123
124    // The currently active state
125    Draw fCurrentState;
126    // A stack of states for tracking save/restores
127    SkDeque fStateStack;
128
129    // Represents a notable piece of state that requires an offset into the command buffer,
130    // corresponding to a clip/saveLayer/etc call, to apply.
131    struct Node {
132        Node* fParent;
133        uint32_t fOffset;
134        uint16_t fLevel;
135        uint16_t fFlags;
136        SkMatrix* fMatrix;
137        enum Flags {
138            kSave_Flag      = 0x1,
139            kSaveLayer_Flag = 0x2
140        };
141    };
142
143    typedef SkRefCnt INHERITED;
144};
145
146#endif
147