2009-05-13 14:00:33 +00:00
|
|
|
#ifndef SkGroupShape_DEFINED
|
|
|
|
#define SkGroupShape_DEFINED
|
|
|
|
|
2009-05-18 04:20:55 +00:00
|
|
|
#include "SkMatrix.h"
|
2009-05-13 14:00:33 +00:00
|
|
|
#include "SkShape.h"
|
|
|
|
#include "SkTDArray.h"
|
2009-05-18 04:20:55 +00:00
|
|
|
#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;
|
|
|
|
}
|
2009-05-27 01:44:24 +00:00
|
|
|
|
|
|
|
SkMatrix& operator=(const SkMatrix& matrix) {
|
|
|
|
SkMatrix& m = *this;
|
|
|
|
m = matrix;
|
|
|
|
return m;
|
|
|
|
}
|
2009-05-18 04:20:55 +00:00
|
|
|
};
|
2009-05-13 14:00:33 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
*/
|
2009-05-18 04:20:55 +00:00
|
|
|
SkShape* getShape(int index, SkMatrixRef** = NULL) const;
|
2009-05-27 01:44:24 +00:00
|
|
|
|
|
|
|
/** 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;
|
|
|
|
}
|
2009-05-13 14:00:33 +00:00
|
|
|
|
|
|
|
/** 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.
|
|
|
|
*/
|
2009-05-18 04:20:55 +00:00
|
|
|
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();
|
|
|
|
}
|
2009-05-13 14:00:33 +00:00
|
|
|
|
|
|
|
/** Helper method to append a shape, passing countShapes() for the index
|
|
|
|
*/
|
2009-05-18 04:20:55 +00:00
|
|
|
SkShape* appendShape(SkShape* shape, SkMatrixRef* mr = NULL) {
|
|
|
|
this->addShape(this->countShapes(), shape, mr);
|
|
|
|
return shape;
|
2009-05-13 14:00:33 +00:00
|
|
|
}
|
2009-05-18 04:20:55 +00:00
|
|
|
|
|
|
|
SkShape* appendShape(SkShape* shape, const SkMatrix& matrix) {
|
|
|
|
this->addShape(this->countShapes(), shape, matrix);
|
|
|
|
return shape;
|
|
|
|
}
|
|
|
|
|
2009-05-13 14:00:33 +00:00
|
|
|
/** 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&);
|
|
|
|
|
2009-06-29 16:02:20 +00:00
|
|
|
// public for Registrar
|
|
|
|
static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);
|
|
|
|
|
2009-05-13 14:00:33 +00:00
|
|
|
protected:
|
|
|
|
// overrides
|
|
|
|
virtual void onDraw(SkCanvas*);
|
|
|
|
|
|
|
|
SkGroupShape(SkFlattenableReadBuffer&);
|
|
|
|
|
|
|
|
private:
|
2009-05-18 04:20:55 +00:00
|
|
|
struct Rec {
|
|
|
|
SkShape* fShape;
|
|
|
|
SkMatrixRef* fMatrixRef;
|
|
|
|
};
|
|
|
|
SkTDArray<Rec> fList;
|
2009-05-13 14:00:33 +00:00
|
|
|
|
|
|
|
typedef SkShape INHERITED;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|