blob: f54afcc1f4090dfea362353fafb4b5706a24df42 [file] [log] [blame]
#include "SkDrawing.h"
#include "SkCanvas.h"
SkDrawing::SkDrawing() {
fMatrix.reset();
fParent = fFirstChild = fNextSibling = fPrevSibling = NULL;
}
SkDrawing::~SkDrawing() {
this->detachAllChildren();
}
///////////////////////////////////////////////////////////////////////////////
void SkDrawing::resetMatrix() {
fMatrix.reset();
}
void SkDrawing::getMatrix(SkMatrix* matrix) const {
if (matrix) {
*matrix = fMatrix;
}
}
void SkDrawing::setMatrix(const SkMatrix& matrix) {
if (fMatrix != matrix) {
this->inval();
fMatrix = matrix;
this->inval();
}
}
void SkDrawing::draw(SkCanvas* canvas) {
SkAutoCanvasRestore ar(canvas, false);
canvas->save(SkCanvas::kMatrix_SaveFlag);
canvas->concat(fMatrix);
this->onDraw(canvas);
B2FIter iter(this);
SkDrawing* child;
while ((child = iter.next()) != NULL) {
child->draw(canvas);
}
}
///////////////////////////////////////////////////////////////////////////////
void SkDrawing::detachFromParent() {
SkDrawing* parent = fParent;
if (NULL == parent) {
return;
}
this->inval();
SkDrawing* next = NULL;
if (fNextSibling != this) { // do we have any siblings
fNextSibling->fPrevSibling = fPrevSibling;
fPrevSibling->fNextSibling = fNextSibling;
next = fNextSibling;
}
if (fParent->fFirstChild == this) {
fParent->fFirstChild = next;
}
fParent = fNextSibling = fPrevSibling = NULL;
this->unref();
}
SkDrawing* SkDrawing::attachChildToBack(SkDrawing* child) {
SkASSERT(child != this);
if (child == NULL || fFirstChild == child) {
return child;
}
child->ref();
child->detachFromParent();
if (fFirstChild == NULL) {
child->fNextSibling = child;
child->fPrevSibling = child;
} else {
child->fNextSibling = fFirstChild;
child->fPrevSibling = fFirstChild->fPrevSibling;
fFirstChild->fPrevSibling->fNextSibling = child;
fFirstChild->fPrevSibling = child;
}
fFirstChild = child;
child->fParent = this;
child->inval();
return child;
}
SkDrawing* SkDrawing::attachChildToFront(SkDrawing* child) {
SkASSERT(child != this);
if (child == NULL || fFirstChild && fFirstChild->fPrevSibling == child) {
return child;
}
child->ref();
child->detachFromParent();
if (fFirstChild == NULL) {
fFirstChild = child;
child->fNextSibling = child;
child->fPrevSibling = child;
} else {
child->fNextSibling = fFirstChild;
child->fPrevSibling = fFirstChild->fPrevSibling;
fFirstChild->fPrevSibling->fNextSibling = child;
fFirstChild->fPrevSibling = child;
}
child->fParent = this;
child->inval();
return child;
}
void SkDrawing::detachAllChildren() {
while (fFirstChild) {
fFirstChild->detachFromParent();
}
}
///////////////////////////////////////////////////////////////////////////////
SkDrawing::B2FIter::B2FIter(const SkDrawing* parent) {
fFirstChild = parent ? parent->fFirstChild : NULL;
fChild = fFirstChild;
}
SkDrawing* SkDrawing::B2FIter::next() {
SkDrawing* curr = fChild;
if (fChild) {
SkDrawing* next = fChild->fNextSibling;
if (next == fFirstChild) {
next = NULL;
}
fChild = next;
}
return curr;
}