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(size_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(size_t offset);
     61     void appendRestore();
     62     void appendTransform(const SkMatrix& trans);
     63     void appendClip(size_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 op offset needed to create the drawing state
     78             required by the queued up draw operation or the offset of the queued
     79             up draw operation itself. In the latter case, the next draw operation
     80             will move into the queued up slot.
     81             It retuns kDrawComplete when done.
     82             TODO: this might be better named nextOp
     83         */
     84         uint32_t nextDraw();
     85         static const uint32_t kDrawComplete = SK_MaxU32;
     86         Iterator() : fPlaybackMatrix(), fValid(false) { }
     87         bool isValid() const { return fValid; }
     88 
     89     private:
     90         Iterator(const SkTDArray<void*>& draws, SkCanvas* canvas, Node* root);
     91 
     92         void setCurrentMatrix(const SkMatrix*);
     93 
     94         // The draws this iterator is associated with
     95         const SkTDArray<void*>* fDraws;
     96 
     97         // canvas this is playing into (so we can insert saves/restores as necessary)
     98         SkCanvas* fCanvas;
     99 
    100         // current state node
    101         Node* fCurrentNode;
    102 
    103         // List of nodes whose state we need to apply to reach TargetNode
    104         SkTDArray<Node*> fNodes;
    105 
    106         // The matrix of the canvas we're playing back into
    107         const SkMatrix fPlaybackMatrix;
    108 
    109         // Cache of current matrix, so we can avoid redundantly setting it
    110         const SkMatrix* fCurrentMatrix;
    111 
    112         // current position in the array of draws
    113         int fPlaybackIndex;
    114         // Whether or not we need to do a save next iteration
    115         bool fSave;
    116 
    117         // Whether or not this is a valid iterator (the default public constructor sets this false)
    118         bool fValid;
    119 
    120         uint32_t finish();
    121 
    122         friend class SkPictureStateTree;
    123     };
    124 
    125 private:
    126 
    127     void appendNode(size_t offset);
    128 
    129     SkChunkAlloc fAlloc;
    130     // Needed by saveCollapsed() because nodes do not currently store
    131     // references to their children.  If they did, we could just retrieve the
    132     // last added child.
    133     Node* fLastRestoredNode;
    134 
    135     // The currently active state
    136     Draw fCurrentState;
    137     // A stack of states for tracking save/restores
    138     SkDeque fStateStack;
    139 
    140     // Represents a notable piece of state that requires an offset into the command buffer,
    141     // corresponding to a clip/saveLayer/etc call, to apply.
    142     struct Node {
    143         Node* fParent;
    144         uint32_t fOffset;
    145         uint16_t fLevel;
    146         uint16_t fFlags;
    147         SkMatrix* fMatrix;
    148         enum Flags {
    149             kSave_Flag      = 0x1,
    150             kSaveLayer_Flag = 0x2
    151         };
    152     };
    153 
    154     Node fRoot;
    155     SkMatrix fRootMatrix;
    156 
    157     typedef SkRefCnt INHERITED;
    158 };
    159 
    160 #endif
    161