blob: 87529586d3333fbddb76782070e05dd0535ffeca [file] [log] [blame]
/*
* 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) const { 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);
/**
* Call this immediately after an appendRestore call that is associated
* a save or saveLayer that was removed from the command stream
* due to a command pattern optimization in SkPicture.
*/
void saveCollapsed();
/**
* 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;
// Needed by saveCollapsed() because nodes do not currently store
// references to their children. If they did, we could just retrieve the
// last added child.
Node* fLastRestoredNode;
// 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
};
};
Node fRoot;
SkMatrix fRootMatrix;
typedef SkRefCnt INHERITED;
};
#endif