Home | History | Annotate | Download | only in effects
      1 
      2 /*
      3  * Copyright 2011 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 #ifndef SkGroupShape_DEFINED
      9 #define SkGroupShape_DEFINED
     10 
     11 #include "SkMatrix.h"
     12 #include "SkShape.h"
     13 #include "SkTDArray.h"
     14 #include "SkThread.h"
     15 
     16 template <typename T> class SkTRefCnt : public T {
     17 public:
     18     SkTRefCnt() : fRefCnt(1) {}
     19     ~SkTRefCnt() { SkASSERT(1 == fRefCnt); }
     20 
     21     int32_t getRefCnt() const { return fRefCnt; }
     22 
     23     /** Increment the reference count. Must be balanced by a call to unref().
     24      */
     25     void ref() const {
     26         SkASSERT(fRefCnt > 0);
     27         sk_atomic_inc(&fRefCnt);
     28     }
     29 
     30     /** Decrement the reference count. If the reference count is 1 before the
     31         decrement, then call delete on the object. Note that if this is the
     32         case, then the object needs to have been allocated via new, and not on
     33         the stack.
     34      */
     35     void unref() const {
     36         SkASSERT(fRefCnt > 0);
     37         if (sk_atomic_dec(&fRefCnt) == 1) {
     38             fRefCnt = 1;    // so our destructor won't complain
     39             SkDELETE(this);
     40         }
     41     }
     42 
     43     static void SafeRef(const SkTRefCnt* obj) {
     44         if (obj) {
     45             obj->ref();
     46         }
     47     }
     48 
     49     static void SafeUnref(const SkTRefCnt* obj) {
     50         if (obj) {
     51             obj->unref();
     52         }
     53     }
     54 
     55 private:
     56     mutable int32_t fRefCnt;
     57 };
     58 
     59 class SkMatrixRef : public SkTRefCnt<SkMatrix> {
     60 public:
     61     SkMatrixRef() { this->reset(); }
     62     explicit SkMatrixRef(const SkMatrix& matrix) {
     63         SkMatrix& m = *this;
     64         m = matrix;
     65     }
     66 
     67     SkMatrix& operator=(const SkMatrix& matrix) {
     68         SkMatrix& m = *this;
     69         m = matrix;
     70         return m;
     71     }
     72 };
     73 
     74 class SkGroupShape : public SkShape {
     75 public:
     76             SkGroupShape();
     77     virtual ~SkGroupShape();
     78 
     79     /** Return the number of child shapes in this group
     80      */
     81     int countShapes() const;
     82 
     83     /** Return the shape at the specified index. Note this does not affect the
     84         owner count of the index'd shape. If index is out of range, returns NULL
     85      */
     86     SkShape* getShape(int index, SkMatrixRef** = NULL) const;
     87 
     88     /** Helper function to return the matrixref of the specified shape.
     89      */
     90     SkMatrixRef* getShapeMatrixRef(int index) const {
     91         SkMatrixRef* mr = NULL;
     92         (void)this->getShape(index, &mr);
     93         return mr;
     94     }
     95 
     96     /** Ref the specified shape, and insert it into the child list at the
     97         specified index. If index == countShapes(), then the shape will be
     98         appended to the child list, otherwise if index is out of range, the
     99         shape is not added. Either way, the shape parameter is returned.
    100 
    101         Child shapes are drawn in order, after the parent, so the shape at index
    102         0 will be drawn first, and the shape at index countShapes() - 1 will be
    103         drawn last.
    104      */
    105     void addShape(int index, SkShape*, SkMatrixRef* = NULL);
    106 
    107     void addShape(int index, SkShape* shape, const SkMatrix& matrix) {
    108         SkMatrixRef* mr = SkNEW_ARGS(SkMatrixRef, (matrix));
    109         this->addShape(index, shape, mr);
    110         mr->unref();
    111     }
    112 
    113     /** Helper method to append a shape, passing countShapes() for the index
    114      */
    115     SkShape* appendShape(SkShape* shape, SkMatrixRef* mr = NULL) {
    116         this->addShape(this->countShapes(), shape, mr);
    117         return shape;
    118     }
    119 
    120     SkShape* appendShape(SkShape* shape, const SkMatrix& matrix) {
    121         this->addShape(this->countShapes(), shape, matrix);
    122         return shape;
    123     }
    124 
    125     /** Unref the specified index, and remove it from the child list. If index
    126         is out of range, does nothing.
    127      */
    128     void removeShape(int index);
    129 
    130     /** Unrefs and removes all of the child shapes
    131      */
    132     void removeAllShapes();
    133 
    134     // overrides
    135     virtual Factory getFactory();
    136     virtual void flatten(SkFlattenableWriteBuffer&);
    137 
    138     // public for Registrar
    139     static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);
    140 
    141     SK_DECLARE_FLATTENABLE_REGISTRAR()
    142 
    143 protected:
    144     // overrides
    145     virtual void onDraw(SkCanvas*);
    146 
    147     SkGroupShape(SkFlattenableReadBuffer&);
    148 
    149 private:
    150     struct Rec {
    151         SkShape*     fShape;
    152         SkMatrixRef* fMatrixRef;
    153     };
    154     SkTDArray<Rec> fList;
    155 
    156     typedef SkShape INHERITED;
    157 };
    158 
    159 #endif
    160