| |
| /* |
| * Copyright 2011 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| #ifndef SkGroupShape_DEFINED |
| #define SkGroupShape_DEFINED |
| |
| #include "SkMatrix.h" |
| #include "SkShape.h" |
| #include "SkTDArray.h" |
| #include "SkThread.h" |
| |
| template <typename T> class SkTRefCnt : public T { |
| public: |
| SkTRefCnt() : fRefCnt(1) {} |
| ~SkTRefCnt() { SkASSERT(1 == fRefCnt); } |
| |
| int32_t getRefCnt() const { return fRefCnt; } |
| |
| /** Increment the reference count. Must be balanced by a call to unref(). |
| */ |
| void ref() const { |
| SkASSERT(fRefCnt > 0); |
| sk_atomic_inc(&fRefCnt); |
| } |
| |
| /** Decrement the reference count. If the reference count is 1 before the |
| decrement, then call delete on the object. Note that if this is the |
| case, then the object needs to have been allocated via new, and not on |
| the stack. |
| */ |
| void unref() const { |
| SkASSERT(fRefCnt > 0); |
| if (sk_atomic_dec(&fRefCnt) == 1) { |
| fRefCnt = 1; // so our destructor won't complain |
| SkDELETE(this); |
| } |
| } |
| |
| static void SafeRef(const SkTRefCnt* obj) { |
| if (obj) { |
| obj->ref(); |
| } |
| } |
| |
| static void SafeUnref(const SkTRefCnt* obj) { |
| if (obj) { |
| obj->unref(); |
| } |
| } |
| |
| private: |
| mutable int32_t fRefCnt; |
| }; |
| |
| class SkMatrixRef : public SkTRefCnt<SkMatrix> { |
| public: |
| SkMatrixRef() { this->reset(); } |
| explicit SkMatrixRef(const SkMatrix& matrix) { |
| SkMatrix& m = *this; |
| m = matrix; |
| } |
| |
| SkMatrix& operator=(const SkMatrix& matrix) { |
| SkMatrix& m = *this; |
| m = matrix; |
| return m; |
| } |
| }; |
| |
| class SkGroupShape : public SkShape { |
| public: |
| SkGroupShape(); |
| virtual ~SkGroupShape(); |
| |
| /** Return the number of child shapes in this group |
| */ |
| int countShapes() const; |
| |
| /** Return the shape at the specified index. Note this does not affect the |
| owner count of the index'd shape. If index is out of range, returns NULL |
| */ |
| SkShape* getShape(int index, SkMatrixRef** = NULL) const; |
| |
| /** Helper function to return the matrixref of the specified shape. |
| */ |
| SkMatrixRef* getShapeMatrixRef(int index) const { |
| SkMatrixRef* mr = NULL; |
| (void)this->getShape(index, &mr); |
| return mr; |
| } |
| |
| /** Ref the specified shape, and insert it into the child list at the |
| specified index. If index == countShapes(), then the shape will be |
| appended to the child list, otherwise if index is out of range, the |
| shape is not added. Either way, the shape parameter is returned. |
| |
| Child shapes are drawn in order, after the parent, so the shape at index |
| 0 will be drawn first, and the shape at index countShapes() - 1 will be |
| drawn last. |
| */ |
| void addShape(int index, SkShape*, SkMatrixRef* = NULL); |
| |
| void addShape(int index, SkShape* shape, const SkMatrix& matrix) { |
| SkMatrixRef* mr = SkNEW_ARGS(SkMatrixRef, (matrix)); |
| this->addShape(index, shape, mr); |
| mr->unref(); |
| } |
| |
| /** Helper method to append a shape, passing countShapes() for the index |
| */ |
| SkShape* appendShape(SkShape* shape, SkMatrixRef* mr = NULL) { |
| this->addShape(this->countShapes(), shape, mr); |
| return shape; |
| } |
| |
| SkShape* appendShape(SkShape* shape, const SkMatrix& matrix) { |
| this->addShape(this->countShapes(), shape, matrix); |
| return shape; |
| } |
| |
| /** Unref the specified index, and remove it from the child list. If index |
| is out of range, does nothing. |
| */ |
| void removeShape(int index); |
| |
| /** Unrefs and removes all of the child shapes |
| */ |
| void removeAllShapes(); |
| |
| // overrides |
| virtual Factory getFactory(); |
| virtual void flatten(SkFlattenableWriteBuffer&); |
| |
| // public for Registrar |
| static SkFlattenable* CreateProc(SkFlattenableReadBuffer&); |
| |
| SK_DECLARE_FLATTENABLE_REGISTRAR() |
| |
| protected: |
| // overrides |
| virtual void onDraw(SkCanvas*); |
| |
| SkGroupShape(SkFlattenableReadBuffer&); |
| |
| private: |
| struct Rec { |
| SkShape* fShape; |
| SkMatrixRef* fMatrixRef; |
| }; |
| SkTDArray<Rec> fList; |
| |
| typedef SkShape INHERITED; |
| }; |
| |
| #endif |