shapes checkpoint: move matrix into groupshape and out of shape

git-svn-id: http://skia.googlecode.com/svn/trunk@178 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@android.com 2009-05-18 04:20:55 +00:00
parent 3b89515707
commit f48f281766
5 changed files with 140 additions and 109 deletions

View File

@ -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;

View File

@ -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:

View File

@ -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) {}

View File

@ -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
}
}

View File

@ -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&);