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:
parent
3b89515707
commit
f48f281766
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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) {}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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&);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user