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      * 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 
    113 private:
    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