From 8381e007dc655b7db4ddf5cafdc057f2dbc1dc6a Mon Sep 17 00:00:00 2001 From: "reed@android.com" Date: Tue, 23 Mar 2010 20:10:46 +0000 Subject: [PATCH] add inherit-from-root-transform flag (for fixed-positioning) git-svn-id: http://skia.googlecode.com/svn/trunk@532 2bbb7eff-a529-9590-31e7-b0007b416f81 --- include/utils/SkLayer.h | 13 +++++++-- src/utils/SkLayer.cpp | 63 ++++++++++++++++++++++++++++------------- 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/include/utils/SkLayer.h b/include/utils/SkLayer.h index c8dea484dd..c42261f808 100644 --- a/include/utils/SkLayer.h +++ b/include/utils/SkLayer.h @@ -34,6 +34,7 @@ public: SkLayer(const SkLayer&); virtual ~SkLayer(); + bool isInheritFromRootTransform() const; SkScalar getOpacity() const { return m_opacity; } const SkSize& getSize() const { return m_size; } const SkPoint& getPosition() const { return m_position; } @@ -44,6 +45,7 @@ public: SkScalar getWidth() const { return m_size.width(); } SkScalar getHeight() const { return m_size.height(); } + void setInheritFromRootTransform(bool); void setOpacity(SkScalar opacity) { m_opacity = opacity; } void setSize(SkScalar w, SkScalar h) { m_size.set(w, h); } void setPosition(SkScalar x, SkScalar y) { m_position.set(x, y); } @@ -68,10 +70,10 @@ public: */ SkLayer* addChild(SkLayer* child); - /** Remove this layer from our child list, and unref() it and return true. - If it is not in our child list, do nothing and return false. + /** Remove this layer from its parent's list (or do nothing if it has no + 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. */ @@ -112,6 +114,10 @@ protected: virtual void onDraw(SkCanvas*, SkScalar opacity); private: + enum Flags { + kInheritFromRootTransform_Flag = 0x01 + }; + SkLayer* fParent; SkScalar m_opacity; SkSize m_size; @@ -119,6 +125,7 @@ private: SkPoint m_anchorPoint; SkMatrix fMatrix; SkMatrix fChildrenMatrix; + uint32_t fFlags; SkTDArray m_children; }; diff --git a/src/utils/SkLayer.cpp b/src/utils/SkLayer.cpp index 888afec99e..5c68261bc8 100644 --- a/src/utils/SkLayer.cpp +++ b/src/utils/SkLayer.cpp @@ -19,6 +19,7 @@ SkLayer::SkLayer() { fMatrix.reset(); fChildrenMatrix.reset(); + fFlags = 0; #ifdef DEBUG_TRACK_NEW_DELETE gLayerAllocCount += 1; @@ -35,6 +36,7 @@ SkLayer::SkLayer(const SkLayer& src) { fMatrix = src.fMatrix; fChildrenMatrix = src.fChildrenMatrix; + fFlags = src.fFlags; #ifdef DEBUG_TRACK_NEW_DELETE 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) { fMatrix = matrix; } @@ -69,16 +83,16 @@ int SkLayer::countChildren() const { SkLayer* SkLayer::getChild(int index) const { if ((unsigned)index < (unsigned)m_children.count()) { + SkASSERT(m_children[index]->fParent == this); return m_children[index]; } return NULL; } SkLayer* SkLayer::addChild(SkLayer* child) { + SkASSERT(this != child); child->ref(); - if (child->fParent) { - child->fParent->removeChild(child); - } + child->detachFromParent(); SkASSERT(child->fParent == NULL); child->fParent = this; @@ -86,20 +100,24 @@ SkLayer* SkLayer::addChild(SkLayer* child) { return child; } -bool SkLayer::removeChild(SkLayer* child) { - int index = m_children.find(child); - if (index >= 0) { - SkASSERT(child->fParent == this); - child->fParent = NULL; - child->unref(); - m_children.remove(index); - return true; +void SkLayer::detachFromParent() { + if (fParent) { + int index = fParent->m_children.find(this); + SkASSERT(index >= 0); + fParent->m_children.remove(index); + fParent = NULL; + this->unref(); // this call might delete us } - return false; } 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(); } @@ -126,6 +144,11 @@ void SkLayer::getLocalTransform(SkMatrix* matrix) const { void SkLayer::localToGlobal(SkMatrix* matrix) const { this->getLocalTransform(matrix); + if (this->isInheritFromRootTransform()) { + matrix->postConcat(this->getRootLayer()->getMatrix()); + return; + } + const SkLayer* layer = this; while (layer->fParent != NULL) { layer = layer->fParent; @@ -165,13 +188,13 @@ void SkLayer::draw(SkCanvas* canvas, SkScalar opacity) { // apply our local transform { - canvas->translate(m_position.fX, m_position.fY); - - SkScalar tx = SkScalarMul(m_anchorPoint.fX, m_size.width()); - SkScalar ty = SkScalarMul(m_anchorPoint.fY, m_size.height()); - canvas->translate(tx, ty); - canvas->concat(this->getMatrix()); - canvas->translate(-tx, -ty); + SkMatrix tmp; + this->getLocalTransform(&tmp); + if (this->isInheritFromRootTransform()) { + // should we also apply the root's childrenMatrix? + canvas->setMatrix(getRootLayer()->getMatrix()); + } + canvas->concat(tmp); } this->onDraw(canvas, opacity);