aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkShape.h13
-rw-r--r--samplecode/SampleShapes.cpp33
-rw-r--r--src/core/SkShape.cpp59
-rw-r--r--src/shapes/SkGroupShape.cpp62
-rw-r--r--src/shapes/SkGroupShape.h82
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&);