Home | History | Annotate | Download | only in core
      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 
     18 class 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  */
     25 class SkPictureStateTree : public SkRefCnt {
     26 private:
     27     struct Node;
     28 public:
     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 
    106 private:
    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