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