aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkPictureStateTree.h
blob: ab467cf5b947d9d113515efe03c8129f02869dc6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkPictureStateTree_DEFINED
#define SkPictureStateTree_DEFINED

#include "SkTDArray.h"
#include "SkChunkAlloc.h"
#include "SkDeque.h"
#include "SkMatrix.h"
#include "SkRefCnt.h"

class SkCanvas;

/**
 * Provides an interface that, given a sequence of draws into an SkPicture with corresponding
 * offsets, allows for playback of an arbitrary subset of the draws (note that Z-order is only
 * guaranteed if the draws are explicitly sorted).
 */
class SkPictureStateTree : public SkRefCnt {
private:
    struct Node;
public:
    SK_DECLARE_INST_COUNT(SkPictureStateTree)

    /**
     * A draw call, stores offset into command buffer, a pointer to the matrix, and a pointer to
     * the node in the tree that corresponds to its clip/layer state
     */
    struct Draw {
        SkMatrix* fMatrix;
        Node* fNode;
        uint32_t fOffset;
        bool operator<(const Draw& other) { return fOffset < other.fOffset; }
    };

    class Iterator;

    SkPictureStateTree();
    ~SkPictureStateTree();

    /**
     * Creates and returns a struct representing a draw at the given offset.
     */
    Draw* appendDraw(uint32_t offset);

    /**
     * Given a list of draws, and a canvas, returns an iterator that produces the correct sequence
     * of offsets into the command buffer to carry out those calls with correct matrix/clip state.
     * This handles saves/restores, and does all necessary matrix setup.
     */
    Iterator getIterator(const SkTDArray<void*>& draws, SkCanvas* canvas);

    void appendSave();
    void appendSaveLayer(uint32_t offset);
    void appendRestore();
    void appendTransform(const SkMatrix& trans);
    void appendClip(uint32_t offset);

    /**
     * Playback helper
     */
    class Iterator {
    public:
        /** Returns the next offset into the picture stream, or kDrawComplete if complete. */
        uint32_t draw();
        static const uint32_t kDrawComplete = SK_MaxU32;
        Iterator() : fPlaybackMatrix(), fValid(false) { }
        bool isValid() const { return fValid; }
    private:
        Iterator(const SkTDArray<void*>& draws, SkCanvas* canvas, Node* root);
        // The draws this iterator is associated with
        const SkTDArray<void*>* fDraws;

        // canvas this is playing into (so we can insert saves/restores as necessary)
        SkCanvas* fCanvas;

        // current state node
        Node* fCurrentNode;

        // List of nodes whose state we need to apply to reach TargetNode
        SkTDArray<Node*> fNodes;

        // The matrix of the canvas we're playing back into
        const SkMatrix fPlaybackMatrix;

        // Cache of current matrix, so we can avoid redundantly setting it
        SkMatrix* fCurrentMatrix;

        // current position in the array of draws
        int fPlaybackIndex;
        // Whether or not we need to do a save next iteration
        bool fSave;

        // Whether or not this is a valid iterator (the default public constructor sets this false)
        bool fValid;

        friend class SkPictureStateTree;
    };

private:

    void appendNode(uint32_t offset);

    SkChunkAlloc fAlloc;
    Node* fRoot;

    // The currently active state
    Draw fCurrentState;
    // A stack of states for tracking save/restores
    SkDeque fStateStack;

    // Represents a notable piece of state that requires an offset into the command buffer,
    // corresponding to a clip/saveLayer/etc call, to apply.
    struct Node {
        Node* fParent;
        uint32_t fOffset;
        uint16_t fLevel;
        uint16_t fFlags;
        SkMatrix* fMatrix;
        enum Flags {
            kSave_Flag      = 0x1,
            kSaveLayer_Flag = 0x2
        };
    };

    typedef SkRefCnt INHERITED;
};

#endif