add inherit-from-root-transform flag (for fixed-positioning)

git-svn-id: http://skia.googlecode.com/svn/trunk@532 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@android.com 2010-03-23 20:10:46 +00:00
parent e88f551b38
commit 8381e007dc
2 changed files with 53 additions and 23 deletions

View File

@ -34,6 +34,7 @@ public:
SkLayer(const SkLayer&); SkLayer(const SkLayer&);
virtual ~SkLayer(); virtual ~SkLayer();
bool isInheritFromRootTransform() const;
SkScalar getOpacity() const { return m_opacity; } SkScalar getOpacity() const { return m_opacity; }
const SkSize& getSize() const { return m_size; } const SkSize& getSize() const { return m_size; }
const SkPoint& getPosition() const { return m_position; } const SkPoint& getPosition() const { return m_position; }
@ -44,6 +45,7 @@ public:
SkScalar getWidth() const { return m_size.width(); } SkScalar getWidth() const { return m_size.width(); }
SkScalar getHeight() const { return m_size.height(); } SkScalar getHeight() const { return m_size.height(); }
void setInheritFromRootTransform(bool);
void setOpacity(SkScalar opacity) { m_opacity = opacity; } void setOpacity(SkScalar opacity) { m_opacity = opacity; }
void setSize(SkScalar w, SkScalar h) { m_size.set(w, h); } void setSize(SkScalar w, SkScalar h) { m_size.set(w, h); }
void setPosition(SkScalar x, SkScalar y) { m_position.set(x, y); } void setPosition(SkScalar x, SkScalar y) { m_position.set(x, y); }
@ -68,10 +70,10 @@ public:
*/ */
SkLayer* addChild(SkLayer* child); SkLayer* addChild(SkLayer* child);
/** Remove this layer from our child list, and unref() it and return true. /** Remove this layer from its parent's list (or do nothing if it has no
If it is not in our child list, do nothing and return false. parent.) If it had a parent, then unref() is called.
*/ */
bool removeChild(SkLayer* child); void detachFromParent();
/** Remove, and unref(), all of the layers in our child list. /** Remove, and unref(), all of the layers in our child list.
*/ */
@ -112,6 +114,10 @@ protected:
virtual void onDraw(SkCanvas*, SkScalar opacity); virtual void onDraw(SkCanvas*, SkScalar opacity);
private: private:
enum Flags {
kInheritFromRootTransform_Flag = 0x01
};
SkLayer* fParent; SkLayer* fParent;
SkScalar m_opacity; SkScalar m_opacity;
SkSize m_size; SkSize m_size;
@ -119,6 +125,7 @@ private:
SkPoint m_anchorPoint; SkPoint m_anchorPoint;
SkMatrix fMatrix; SkMatrix fMatrix;
SkMatrix fChildrenMatrix; SkMatrix fChildrenMatrix;
uint32_t fFlags;
SkTDArray<SkLayer*> m_children; SkTDArray<SkLayer*> m_children;
}; };

View File

@ -19,6 +19,7 @@ SkLayer::SkLayer() {
fMatrix.reset(); fMatrix.reset();
fChildrenMatrix.reset(); fChildrenMatrix.reset();
fFlags = 0;
#ifdef DEBUG_TRACK_NEW_DELETE #ifdef DEBUG_TRACK_NEW_DELETE
gLayerAllocCount += 1; gLayerAllocCount += 1;
@ -35,6 +36,7 @@ SkLayer::SkLayer(const SkLayer& src) {
fMatrix = src.fMatrix; fMatrix = src.fMatrix;
fChildrenMatrix = src.fChildrenMatrix; fChildrenMatrix = src.fChildrenMatrix;
fFlags = src.fFlags;
#ifdef DEBUG_TRACK_NEW_DELETE #ifdef DEBUG_TRACK_NEW_DELETE
gLayerAllocCount += 1; gLayerAllocCount += 1;
@ -53,6 +55,18 @@ SkLayer::~SkLayer() {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
bool SkLayer::isInheritFromRootTransform() const {
return (fFlags & kInheritFromRootTransform_Flag) != 0;
}
void SkLayer::setInheritFromRootTransform(bool doInherit) {
if (doInherit) {
fFlags |= kInheritFromRootTransform_Flag;
} else {
fFlags &= ~kInheritFromRootTransform_Flag;
}
}
void SkLayer::setMatrix(const SkMatrix& matrix) { void SkLayer::setMatrix(const SkMatrix& matrix) {
fMatrix = matrix; fMatrix = matrix;
} }
@ -69,16 +83,16 @@ int SkLayer::countChildren() const {
SkLayer* SkLayer::getChild(int index) const { SkLayer* SkLayer::getChild(int index) const {
if ((unsigned)index < (unsigned)m_children.count()) { if ((unsigned)index < (unsigned)m_children.count()) {
SkASSERT(m_children[index]->fParent == this);
return m_children[index]; return m_children[index];
} }
return NULL; return NULL;
} }
SkLayer* SkLayer::addChild(SkLayer* child) { SkLayer* SkLayer::addChild(SkLayer* child) {
SkASSERT(this != child);
child->ref(); child->ref();
if (child->fParent) { child->detachFromParent();
child->fParent->removeChild(child);
}
SkASSERT(child->fParent == NULL); SkASSERT(child->fParent == NULL);
child->fParent = this; child->fParent = this;
@ -86,20 +100,24 @@ SkLayer* SkLayer::addChild(SkLayer* child) {
return child; return child;
} }
bool SkLayer::removeChild(SkLayer* child) { void SkLayer::detachFromParent() {
int index = m_children.find(child); if (fParent) {
if (index >= 0) { int index = fParent->m_children.find(this);
SkASSERT(child->fParent == this); SkASSERT(index >= 0);
child->fParent = NULL; fParent->m_children.remove(index);
child->unref(); fParent = NULL;
m_children.remove(index); this->unref(); // this call might delete us
return true;
} }
return false;
} }
void SkLayer::removeChildren() { void SkLayer::removeChildren() {
m_children.unrefAll(); int count = m_children.count();
for (int i = 0; i < count; i++) {
SkLayer* child = m_children[i];
SkASSERT(child->fParent == this);
child->fParent = NULL; // in case it has more than one owner
child->unref();
}
m_children.reset(); m_children.reset();
} }
@ -126,6 +144,11 @@ void SkLayer::getLocalTransform(SkMatrix* matrix) const {
void SkLayer::localToGlobal(SkMatrix* matrix) const { void SkLayer::localToGlobal(SkMatrix* matrix) const {
this->getLocalTransform(matrix); this->getLocalTransform(matrix);
if (this->isInheritFromRootTransform()) {
matrix->postConcat(this->getRootLayer()->getMatrix());
return;
}
const SkLayer* layer = this; const SkLayer* layer = this;
while (layer->fParent != NULL) { while (layer->fParent != NULL) {
layer = layer->fParent; layer = layer->fParent;
@ -165,13 +188,13 @@ void SkLayer::draw(SkCanvas* canvas, SkScalar opacity) {
// apply our local transform // apply our local transform
{ {
canvas->translate(m_position.fX, m_position.fY); SkMatrix tmp;
this->getLocalTransform(&tmp);
SkScalar tx = SkScalarMul(m_anchorPoint.fX, m_size.width()); if (this->isInheritFromRootTransform()) {
SkScalar ty = SkScalarMul(m_anchorPoint.fY, m_size.height()); // should we also apply the root's childrenMatrix?
canvas->translate(tx, ty); canvas->setMatrix(getRootLayer()->getMatrix());
canvas->concat(this->getMatrix()); }
canvas->translate(-tx, -ty); canvas->concat(tmp);
} }
this->onDraw(canvas, opacity); this->onDraw(canvas, opacity);