From 745bfbd74d1bcd62b9c597b62907875bca5cf84e Mon Sep 17 00:00:00 2001 From: "reed@android.com" Date: Wed, 24 Feb 2010 17:16:35 +0000 Subject: [PATCH] add localToGlobal and parents git-svn-id: http://skia.googlecode.com/svn/trunk@511 2bbb7eff-a529-9590-31e7-b0007b416f81 --- include/utils/SkLayer.h | 44 +++++++++++++++ samplecode/SampleSkLayer.cpp | 49 ++++++++++++++--- src/utils/SkLayer.cpp | 101 ++++++++++++++++++++++++++++++----- 3 files changed, 174 insertions(+), 20 deletions(-) diff --git a/include/utils/SkLayer.h b/include/utils/SkLayer.h index c97bf72680..c8dea484dd 100644 --- a/include/utils/SkLayer.h +++ b/include/utils/SkLayer.h @@ -53,11 +53,54 @@ public: // children + /** Return the number of layers in our child list. + */ int countChildren() const; + + /** Return the child at the specified index (starting at 0). This does not + affect the reference count of the child. + */ SkLayer* getChild(int index) const; + + /** Add this layer to our child list at the end (top-most), and ref() it. + If it was already in another hierarchy, remove it from that list. + Return the new child. + */ 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. + */ + bool removeChild(SkLayer* child); + + /** Remove, and unref(), all of the layers in our child list. + */ void removeChildren(); + /** Return our parent layer, or NULL if we have none. + */ + SkLayer* getParent() const { return fParent; } + + /** Return the root layer in this hiearchy. If this layer is the root + (i.e. has no parent), then this returns itself. + */ + SkLayer* getRootLayer() const; + + // coordinate system transformations + + /** Return, in matrix, the matix transfomations that are applied locally + when this layer draws (i.e. its position and matrix/anchorPoint). + This does not include the childrenMatrix, since that is only applied + after this layer draws (but before its children draw). + */ + void getLocalTransform(SkMatrix* matrix) const; + + /** Return, in matrix, the concatenation of transforms that are applied + from this layer's root parent to the layer itself. + This is the matrix that is applied to the layer during drawing. + */ + void localToGlobal(SkMatrix* matrix) const; + // paint method void draw(SkCanvas*, SkScalar opacity); @@ -69,6 +112,7 @@ protected: virtual void onDraw(SkCanvas*, SkScalar opacity); private: + SkLayer* fParent; SkScalar m_opacity; SkSize m_size; SkPoint m_position; diff --git a/samplecode/SampleSkLayer.cpp b/samplecode/SampleSkLayer.cpp index 8b6897bf7c..c10bdfd778 100644 --- a/samplecode/SampleSkLayer.cpp +++ b/samplecode/SampleSkLayer.cpp @@ -54,6 +54,24 @@ static void test44() { /////////////////////////////////////////////////////////////////////////////// +static void dump_layers(const SkLayer* layer, int tab = 0) { + SkMatrix matrix; + SkString matrixStr; + + layer->getLocalTransform(&matrix); + matrix.toDumpString(&matrixStr); + + for (int j = 0; j < tab; j++) { + SkDebugf(" "); + } + SkDebugf("layer=%p parent=%p size=[%g %g] transform=%s\n", + layer, layer->getParent(), layer->getWidth(), layer->getHeight(), + matrixStr.c_str()); + for (int i = 0; i < layer->countChildren(); i++) { + dump_layers(layer->getChild(i), tab + 4); + } +} + class TestLayer : public SkLayer { public: TestLayer(SkColor c) : fColor(c) {} @@ -77,7 +95,7 @@ private: class SkLayerView : public SkView { private: SkLayer* fRootLayer; - + SkLayer* fLastChild; public: SkLayerView() { test44(); @@ -115,7 +133,16 @@ public: m.setRotate(SkIntToScalar(30)); child->setMatrix(m); } + fLastChild = child; fRootLayer->addChild(child)->unref(); + + if (false) { + SkMatrix matrix; + matrix.setScale(0.5, 0.5); + fRootLayer->setMatrix(matrix); + } + + dump_layers(fRootLayer); } virtual ~SkLayerView() { @@ -132,17 +159,25 @@ protected: return this->INHERITED::onQuery(evt); } - void drawBG(SkCanvas* canvas) { + virtual void onDraw(SkCanvas* canvas) { canvas->drawColor(SK_ColorWHITE); - + canvas->translate(20, 20); fRootLayer->draw(canvas); + + // visual test of getLocalTransform + if (true) { + SkMatrix matrix; + fLastChild->localToGlobal(&matrix); + SkPaint paint; + paint.setStyle(SkPaint::kStroke_Style); + paint.setStrokeWidth(5); + paint.setColor(0x88FF0000); + canvas->concat(matrix); + canvas->drawRect(SkRect::MakeSize(fLastChild->getSize()), paint); + } } - virtual void onDraw(SkCanvas* canvas) { - this->drawBG(canvas); -} - private: typedef SkView INHERITED; }; diff --git a/src/utils/SkLayer.cpp b/src/utils/SkLayer.cpp index 759f826d96..fe61c02338 100644 --- a/src/utils/SkLayer.cpp +++ b/src/utils/SkLayer.cpp @@ -1,9 +1,17 @@ #include "SkLayer.h" #include "SkCanvas.h" -//#define DEBUG_LAYER_BOUNDS +//#define DEBUG_DRAW_LAYER_BOUNDS +//#define DEBUG_TRACK_NEW_DELETE + +#ifdef DEBUG_TRACK_NEW_DELETE + static int gLayerAllocCount; +#endif + +/////////////////////////////////////////////////////////////////////////////// SkLayer::SkLayer() { + fParent = NULL; m_opacity = SK_Scalar1; m_size.set(0, 0); m_position.set(0, 0); @@ -11,9 +19,15 @@ SkLayer::SkLayer() { fMatrix.reset(); fChildrenMatrix.reset(); + +#ifdef DEBUG_TRACK_NEW_DELETE + gLayerAllocCount += 1; + SkDebugf("SkLayer new: %d\n", gLayerAllocCount); +#endif } SkLayer::SkLayer(const SkLayer& src) { + fParent = NULL; m_opacity = src.m_opacity; m_size = src.m_size; m_position = src.m_position; @@ -21,12 +35,34 @@ SkLayer::SkLayer(const SkLayer& src) { fMatrix = src.fMatrix; fChildrenMatrix = src.fChildrenMatrix; + +#ifdef DEBUG_TRACK_NEW_DELETE + gLayerAllocCount += 1; + SkDebugf("SkLayer copy: %d\n", gLayerAllocCount); +#endif } SkLayer::~SkLayer() { this->removeChildren(); + +#ifdef DEBUG_TRACK_NEW_DELETE + gLayerAllocCount -= 1; + SkDebugf("SkLayer delete: %d\n", gLayerAllocCount); +#endif +} + +/////////////////////////////////////////////////////////////////////////////// + +void SkLayer::setMatrix(const SkMatrix& matrix) { + fMatrix = matrix; +} + +void SkLayer::setChildrenMatrix(const SkMatrix& matrix) { + fChildrenMatrix = matrix; } +/////////////////////////////////////////////////////////////////////////////// + int SkLayer::countChildren() const { return m_children.count(); } @@ -40,23 +76,65 @@ SkLayer* SkLayer::getChild(int index) const { SkLayer* SkLayer::addChild(SkLayer* child) { child->ref(); + if (child->fParent) { + child->fParent->removeChild(child); + } + SkASSERT(child->fParent == NULL); + child->fParent = this; + *m_children.append() = 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; + } + return false; +} + void SkLayer::removeChildren() { m_children.unrefAll(); m_children.reset(); } +SkLayer* SkLayer::getRootLayer() const { + const SkLayer* root = this; + while (root->fParent != NULL) { + root = root->fParent; + } + return const_cast(root); +} + /////////////////////////////////////////////////////////////////////////////// -void SkLayer::setMatrix(const SkMatrix& matrix) { - fMatrix = matrix; +void SkLayer::getLocalTransform(SkMatrix* matrix) const { + matrix->setTranslate(m_position.fX, m_position.fY); + + SkScalar tx = SkScalarMul(m_anchorPoint.fX, m_size.width()); + SkScalar ty = SkScalarMul(m_anchorPoint.fY, m_size.height()); + matrix->preTranslate(tx, ty); + matrix->preConcat(this->getMatrix()); + matrix->preTranslate(-tx, -ty); } -void SkLayer::setChildrenMatrix(const SkMatrix& matrix) { - fChildrenMatrix = matrix; +void SkLayer::localToGlobal(SkMatrix* matrix) const { + this->getLocalTransform(matrix); + + const SkLayer* layer = this; + while (layer->fParent != NULL) { + layer = layer->fParent; + + SkMatrix tmp; + layer->getLocalTransform(&tmp); + tmp.preConcat(layer->getChildrenMatrix()); + matrix->postConcat(tmp); + } } /////////////////////////////////////////////////////////////////////////////// @@ -88,15 +166,12 @@ void SkLayer::draw(SkCanvas* canvas, SkScalar opacity) { SkAutoCanvasRestore acr(canvas, true); - // update the matrix + // apply our local transform { - SkScalar tx = m_position.fX; - SkScalar ty = m_position.fY; - canvas->translate(tx, ty); + canvas->translate(m_position.fX, m_position.fY); - // now apply our matrix about the anchorPoint - tx = SkScalarMul(m_anchorPoint.fX, m_size.width()); - ty = SkScalarMul(m_anchorPoint.fY, m_size.height()); + 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); @@ -104,7 +179,7 @@ void SkLayer::draw(SkCanvas* canvas, SkScalar opacity) { this->onDraw(canvas, opacity); -#ifdef DEBUG_LAYER_BOUNDS +#ifdef DEBUG_DRAW_LAYER_BOUNDS { SkRect r = SkRect::MakeSize(this->getSize()); SkPaint p; -- 2.34.1