diff options
-rw-r--r-- | include/core/SkShape.h | 13 | ||||
-rw-r--r-- | samplecode/SampleShapes.cpp | 33 | ||||
-rw-r--r-- | src/core/SkShape.cpp | 59 | ||||
-rw-r--r-- | src/shapes/SkGroupShape.cpp | 62 | ||||
-rw-r--r-- | src/shapes/SkGroupShape.h | 82 |
5 files changed, 140 insertions, 109 deletions
diff --git a/include/core/SkShape.h b/include/core/SkShape.h index 78a140e187..8978afa08d 100644 --- a/include/core/SkShape.h +++ b/include/core/SkShape.h @@ -2,19 +2,14 @@ #define SkShape_DEFINED #include "SkFlattenable.h" -#include "SkMatrix.h" class SkCanvas; +class SkMatrix; class SkWStream; class SkShape : public SkFlattenable { public: - SkShape() : fMatrix(NULL) {} - virtual ~SkShape(); - - void getMatrix(SkMatrix*) const; - void setMatrix(const SkMatrix&); - void resetMatrix(); + SkShape() {} void draw(SkCanvas*); @@ -34,11 +29,9 @@ public: protected: virtual void onDraw(SkCanvas*) = 0; - SkShape(SkFlattenableReadBuffer&); + SkShape(SkFlattenableReadBuffer&) {} private: - SkMatrix* fMatrix; - static SkFlattenable* CreateProc(SkFlattenableReadBuffer&); typedef SkFlattenable INHERITED; diff --git a/samplecode/SampleShapes.cpp b/samplecode/SampleShapes.cpp index 131ba9e73d..77283fe72d 100644 --- a/samplecode/SampleShapes.cpp +++ b/samplecode/SampleShapes.cpp @@ -14,33 +14,26 @@ static SkRect make_rect(int l, int t, int r, int b) { return rect; } -static SkShape* make_shape0(const SkMatrix* matrix = NULL) { +static SkShape* make_shape0(bool red) { SkRectShape* s = new SkRectShape; s->setRect(make_rect(10, 10, 90, 90)); - if (matrix) { - s->setMatrix(*matrix); + if (red) { s->paint().setColor(SK_ColorRED); } return s; } -static SkShape* make_shape1(const SkMatrix* matrix = NULL) { +static SkShape* make_shape1() { SkRectShape* s = new SkRectShape; s->setOval(make_rect(10, 10, 90, 90)); - if (matrix) { - s->setMatrix(*matrix); - } s->paint().setColor(SK_ColorBLUE); return s; } -static SkShape* make_shape2(const SkMatrix* matrix = NULL) { +static SkShape* make_shape2() { SkRectShape* s = new SkRectShape; s->setRRect(make_rect(10, 10, 90, 90), SkIntToScalar(20), SkIntToScalar(20)); - if (matrix) { - s->setMatrix(*matrix); - } s->paint().setColor(SK_ColorGREEN); return s; } @@ -52,15 +45,15 @@ class ShapesView : public SkView { public: ShapesView() { SkMatrix m; - fGroup.appendShape(make_shape0())->unref(); + fGroup.appendShape(make_shape0(false))->unref(); m.setRotate(SkIntToScalar(30), SkIntToScalar(50), SkIntToScalar(50)); m.postTranslate(0, SkIntToScalar(120)); - fGroup.appendShape(make_shape0(&m))->unref(); + fGroup.appendShape(make_shape0(true), m)->unref(); m.setTranslate(SkIntToScalar(120), 0); - fGroup.appendShape(make_shape1(&m))->unref(); + fGroup.appendShape(make_shape1(), m)->unref(); m.postTranslate(0, SkIntToScalar(120)); - fGroup.appendShape(make_shape2(&m))->unref(); + fGroup.appendShape(make_shape2(), m)->unref(); } protected: @@ -81,12 +74,20 @@ protected: this->drawBG(canvas); SkMatrix matrix; +#if 1 + SkGroupShape gs; + gs.appendShape(&fGroup); + matrix.setTranslate(0, SkIntToScalar(240)); + gs.appendShape(&fGroup, matrix); matrix.setTranslate(SkIntToScalar(240), 0); matrix.preScale(SK_Scalar1*2, SK_Scalar1*2); - + gs.appendShape(&fGroup, matrix); + canvas->drawShape(&gs); +#else fGroup.draw(canvas); fGroup.drawXY(canvas, 0, SkIntToScalar(240)); fGroup.drawMatrix(canvas, matrix); +#endif } private: diff --git a/src/core/SkShape.cpp b/src/core/SkShape.cpp index a6d19af96b..e5fa8ff487 100644 --- a/src/core/SkShape.cpp +++ b/src/core/SkShape.cpp @@ -2,46 +2,8 @@ #include "SkShape.h" #include "SkMatrix.h" -SkShape::~SkShape() { - if (fMatrix) { - SkDELETE(fMatrix); - } -} - -void SkShape::getMatrix(SkMatrix* matrix) const { - if (matrix) { - if (fMatrix) { - *matrix = *fMatrix; - } else { - matrix->reset(); - } - } -} - -void SkShape::setMatrix(const SkMatrix& matrix) { - if (matrix.isIdentity()) { - this->resetMatrix(); - } else { - if (NULL == fMatrix) { - fMatrix = SkNEW(SkMatrix); - } - *fMatrix = matrix; - } -} - -void SkShape::resetMatrix() { - if (fMatrix) { - SkDELETE(fMatrix); - fMatrix = NULL; - } -} - void SkShape::draw(SkCanvas* canvas) { int saveCount = canvas->getSaveCount(); - if (fMatrix) { - canvas->save(SkCanvas::kMatrix_SaveFlag); - canvas->concat(*fMatrix); - } this->onDraw(canvas); canvas->restoreToCount(saveCount); } @@ -49,9 +11,6 @@ void SkShape::draw(SkCanvas* canvas) { void SkShape::drawXY(SkCanvas* canvas, SkScalar dx, SkScalar dy) { int saveCount = canvas->save(SkCanvas::kMatrix_SaveFlag); canvas->translate(dx, dy); - if (fMatrix) { - canvas->concat(*fMatrix); - } this->onDraw(canvas); canvas->restoreToCount(saveCount); } @@ -59,27 +18,11 @@ void SkShape::drawXY(SkCanvas* canvas, SkScalar dx, SkScalar dy) { void SkShape::drawMatrix(SkCanvas* canvas, const SkMatrix& matrix) { int saveCount = canvas->save(SkCanvas::kMatrix_SaveFlag); canvas->concat(matrix); - if (fMatrix) { - canvas->concat(*fMatrix); - } this->onDraw(canvas); canvas->restoreToCount(saveCount); } /////////////////////////////////////////////////////////////////////////////// -void SkShape::flatten(SkFlattenableWriteBuffer& buffer) { - buffer.writeBool(fMatrix != NULL); - if (fMatrix) { - *(SkMatrix*)buffer.reserve(sizeof(SkMatrix)) = *fMatrix; - } -} - -SkShape::SkShape(SkFlattenableReadBuffer& buffer) { - fMatrix = NULL; - if (buffer.readBool()) { - fMatrix = SkNEW(SkMatrix); - buffer.read(fMatrix, sizeof(*fMatrix)); - } -} +void SkShape::flatten(SkFlattenableWriteBuffer& buffer) {} diff --git a/src/shapes/SkGroupShape.cpp b/src/shapes/SkGroupShape.cpp index 1322fe49b3..3baa3152ed 100644 --- a/src/shapes/SkGroupShape.cpp +++ b/src/shapes/SkGroupShape.cpp @@ -10,50 +10,69 @@ int SkGroupShape::countShapes() const { return fList.count(); } -SkShape* SkGroupShape::getShape(int index) const { +SkShape* SkGroupShape::getShape(int index, SkMatrixRef** mr) const { if ((unsigned)index < (unsigned)fList.count()) { - return fList[index]; + const Rec& rec = fList[index]; + if (mr) { + *mr = rec.fMatrixRef; + } + return rec.fShape; } return NULL; } -SkShape* SkGroupShape::addShape(int index, SkShape* shape) { +void SkGroupShape::addShape(int index, SkShape* shape, SkMatrixRef* mr) { int count = fList.count(); if (NULL == shape || index < 0 || index > count) { - return shape; + return; } shape->ref(); - SkShape** spot; + SkMatrixRef::SafeRef(mr); + + Rec* rec; if (index == count) { - spot = fList.append(); + rec = fList.append(); } else { - spot = fList.insert(index); + rec = fList.insert(index); } - *spot = shape; - return shape; + rec->fShape = shape; + rec->fMatrixRef = mr; } void SkGroupShape::removeShape(int index) { if ((unsigned)index < (unsigned)fList.count()) { - fList[index]->unref(); + Rec& rec = fList[index]; + rec.fShape->unref(); + SkMatrixRef::SafeUnref(rec.fMatrixRef); fList.remove(index); } } void SkGroupShape::removeAllShapes() { - fList.unrefAll(); + Rec* rec = fList.begin(); + Rec* stop = fList.end(); + while (rec < stop) { + rec->fShape->unref(); + SkMatrixRef::SafeUnref(rec->fMatrixRef); + rec++; + } fList.reset(); } /////////////////////////////////////////////////////////////////////////////// void SkGroupShape::onDraw(SkCanvas* canvas) { - SkShape** iter = fList.begin(); - SkShape** stop = fList.end(); - while (iter < stop) { - (*iter)->draw(canvas); - iter++; + const Rec* rec = fList.begin(); + const Rec* stop = fList.end(); + while (rec < stop) { + SkShape* shape = rec->fShape; + if (rec->fMatrixRef) { + shape->drawMatrix(canvas, *rec->fMatrixRef); + } else { + shape->draw(canvas); + } + rec++; } } @@ -66,9 +85,13 @@ void SkGroupShape::flatten(SkFlattenableWriteBuffer& buffer) { int count = fList.count(); buffer.write32(count); - for (int i = 0; i < count; i++) { - buffer.writeFunctionPtr((void*)fList[i]->getFactory()); - fList[i]->flatten(buffer); + const Rec* rec = fList.begin(); + const Rec* stop = fList.end(); + while (rec < stop) { + SkShape* shape = rec->fShape; + buffer.writeFunctionPtr((void*)shape->getFactory()); + shape->flatten(buffer); + // todo: flatten the matrixref if present } } @@ -78,6 +101,7 @@ SkGroupShape::SkGroupShape(SkFlattenableReadBuffer& buffer) : INHERITED(buffer){ SkFlattenable::Factory fact = (SkFlattenable::Factory)buffer.readFunctionPtr(); this->appendShape((SkShape*)fact(buffer))->unref(); + // todo: unflatten the matrixref if present } } diff --git a/src/shapes/SkGroupShape.h b/src/shapes/SkGroupShape.h index de7574b9eb..708f306abb 100644 --- a/src/shapes/SkGroupShape.h +++ b/src/shapes/SkGroupShape.h @@ -1,8 +1,62 @@ #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; + } +}; class SkGroupShape : public SkShape { public: @@ -16,7 +70,7 @@ public: /** 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) const; + SkShape* getShape(int index, SkMatrixRef** = NULL) const; /** Ref the specified shape, and insert it into the child list at the specified index. If index == countShapes(), then the shape will be @@ -27,14 +81,26 @@ public: 0 will be drawn first, and the shape at index countShapes() - 1 will be drawn last. */ - SkShape* addShape(int index, SkShape*); + 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) { - return this->addShape(this->countShapes(), shape); + 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. */ @@ -55,7 +121,11 @@ protected: SkGroupShape(SkFlattenableReadBuffer&); private: - SkTDArray<SkShape*> fList; + struct Rec { + SkShape* fShape; + SkMatrixRef* fMatrixRef; + }; + SkTDArray<Rec> fList; static SkFlattenable* CreateProc(SkFlattenableReadBuffer&); |