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: SkTRefCnt()18 SkTRefCnt() : fRefCnt(1) {} ~SkTRefCnt()19 ~SkTRefCnt() { SkASSERT(1 == fRefCnt); } 20 getRefCnt()21 int32_t getRefCnt() const { return fRefCnt; } 22 23 /** Increment the reference count. Must be balanced by a call to unref(). 24 */ ref()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 */ unref()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 SafeRef(const SkTRefCnt * obj)43 static void SafeRef(const SkTRefCnt* obj) { 44 if (obj) { 45 obj->ref(); 46 } 47 } 48 SafeUnref(const SkTRefCnt * obj)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: SkMatrixRef()61 SkMatrixRef() { this->reset(); } SkMatrixRef(const SkMatrix & matrix)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 */ getShapeMatrixRef(int index)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 addShape(int index,SkShape * shape,const SkMatrix & matrix)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 appendShape(SkShape * shape,const SkMatrix & matrix)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