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     * Playback helper
67     */
68    class Iterator {
69    public:
70        /** Returns the next offset into the picture stream, or kDrawComplete if complete. */
71        uint32_t draw();
72        static const uint32_t kDrawComplete = SK_MaxU32;
73        Iterator() : fPlaybackMatrix(), fValid(false) { }
74        bool isValid() const { return fValid; }
75    private:
76        Iterator(const SkTDArray<void*>& draws, SkCanvas* canvas, Node* root);
77        // The draws this iterator is associated with
78        const SkTDArray<void*>* fDraws;
79
80        // canvas this is playing into (so we can insert saves/restores as necessary)
81        SkCanvas* fCanvas;
82
83        // current state node
84        Node* fCurrentNode;
85
86        // List of nodes whose state we need to apply to reach TargetNode
87        SkTDArray<Node*> fNodes;
88
89        // The matrix of the canvas we're playing back into
90        const SkMatrix fPlaybackMatrix;
91
92        // Cache of current matrix, so we can avoid redundantly setting it
93        SkMatrix* fCurrentMatrix;
94
95        // current position in the array of draws
96        int fPlaybackIndex;
97        // Whether or not we need to do a save next iteration
98        bool fSave;
99
100        // Whether or not this is a valid iterator (the default public constructor sets this false)
101        bool fValid;
102
103        friend class SkPictureStateTree;
104    };
105
106private:
107
108    void appendNode(uint32_t offset);
109
110    SkChunkAlloc fAlloc;
111    Node* fRoot;
112
113    // The currently active state
114    Draw fCurrentState;
115    // A stack of states for tracking save/restores
116    SkDeque fStateStack;
117
118    // Represents a notable piece of state that requires an offset into the command buffer,
119    // corresponding to a clip/saveLayer/etc call, to apply.
120    struct Node {
121        Node* fParent;
122        uint32_t fOffset;
123        uint16_t fLevel;
124        uint16_t fFlags;
125        SkMatrix* fMatrix;
126        enum Flags {
127            kSave_Flag      = 0x1,
128            kSaveLayer_Flag = 0x2
129        };
130    };
131
132    typedef SkRefCnt INHERITED;
133};
134
135#endif
136