1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
886d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com#include "SkLayer.h"
981dc331e65ba5a24d515c11890234dd205408c89reed@android.com#include "SkCanvas.h"
1086d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com
11745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com//#define DEBUG_DRAW_LAYER_BOUNDS
12745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com//#define DEBUG_TRACK_NEW_DELETE
13745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com
14745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com#ifdef DEBUG_TRACK_NEW_DELETE
15745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    static int gLayerAllocCount;
16745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com#endif
17745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com
18745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com///////////////////////////////////////////////////////////////////////////////
192bd703b3163fe1da3ea55f6459c5e162f32cce12reed@android.com
2086d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.comSkLayer::SkLayer() {
21745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    fParent = NULL;
222bd703b3163fe1da3ea55f6459c5e162f32cce12reed@android.com    m_opacity = SK_Scalar1;
2386d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com    m_size.set(0, 0);
2486d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com    m_position.set(0, 0);
252bd703b3163fe1da3ea55f6459c5e162f32cce12reed@android.com    m_anchorPoint.set(SK_ScalarHalf, SK_ScalarHalf);
2681dc331e65ba5a24d515c11890234dd205408c89reed@android.com
2781dc331e65ba5a24d515c11890234dd205408c89reed@android.com    fMatrix.reset();
2881dc331e65ba5a24d515c11890234dd205408c89reed@android.com    fChildrenMatrix.reset();
298381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com    fFlags = 0;
30745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com
31745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com#ifdef DEBUG_TRACK_NEW_DELETE
32745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    gLayerAllocCount += 1;
33745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    SkDebugf("SkLayer new:    %d\n", gLayerAllocCount);
34745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com#endif
3586d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com}
3686d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com
37faa5ae456d184202993a5dbe782a3a95acc25326commit-bot@chromium.orgSkLayer::SkLayer(const SkLayer& src) : INHERITED() {
38745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    fParent = NULL;
3986d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com    m_opacity = src.m_opacity;
4086d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com    m_size = src.m_size;
4186d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com    m_position = src.m_position;
4286d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com    m_anchorPoint = src.m_anchorPoint;
4381dc331e65ba5a24d515c11890234dd205408c89reed@android.com
4481dc331e65ba5a24d515c11890234dd205408c89reed@android.com    fMatrix = src.fMatrix;
4581dc331e65ba5a24d515c11890234dd205408c89reed@android.com    fChildrenMatrix = src.fChildrenMatrix;
468381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com    fFlags = src.fFlags;
47745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com
48745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com#ifdef DEBUG_TRACK_NEW_DELETE
49745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    gLayerAllocCount += 1;
50745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    SkDebugf("SkLayer copy:   %d\n", gLayerAllocCount);
51745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com#endif
5286d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com}
5386d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com
5486d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.comSkLayer::~SkLayer() {
5586d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com    this->removeChildren();
56745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com
57745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com#ifdef DEBUG_TRACK_NEW_DELETE
58745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    gLayerAllocCount -= 1;
59745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    SkDebugf("SkLayer delete: %d\n", gLayerAllocCount);
60745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com#endif
61745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com}
62745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com
63745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com///////////////////////////////////////////////////////////////////////////////
64745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com
658381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.combool SkLayer::isInheritFromRootTransform() const {
668381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com    return (fFlags & kInheritFromRootTransform_Flag) != 0;
678381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com}
688381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com
698381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.comvoid SkLayer::setInheritFromRootTransform(bool doInherit) {
708381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com    if (doInherit) {
718381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        fFlags |= kInheritFromRootTransform_Flag;
728381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com    } else {
738381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        fFlags &= ~kInheritFromRootTransform_Flag;
748381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com    }
758381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com}
768381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com
77745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.comvoid SkLayer::setMatrix(const SkMatrix& matrix) {
78745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    fMatrix = matrix;
79745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com}
80745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com
81745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.comvoid SkLayer::setChildrenMatrix(const SkMatrix& matrix) {
82745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    fChildrenMatrix = matrix;
8386d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com}
8486d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com
85745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com///////////////////////////////////////////////////////////////////////////////
86745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com
8786d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.comint SkLayer::countChildren() const {
8886d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com    return m_children.count();
8986d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com}
9086d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com
9186d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.comSkLayer* SkLayer::getChild(int index) const {
9286d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com    if ((unsigned)index < (unsigned)m_children.count()) {
938381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        SkASSERT(m_children[index]->fParent == this);
9486d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com        return m_children[index];
9586d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com    }
9686d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com    return NULL;
9786d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com}
9886d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com
9986d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.comSkLayer* SkLayer::addChild(SkLayer* child) {
1008381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com    SkASSERT(this != child);
10186d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com    child->ref();
1028381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com    child->detachFromParent();
103745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    SkASSERT(child->fParent == NULL);
104745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    child->fParent = this;
105745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com
10686d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com    *m_children.append() = child;
10786d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com    return child;
10886d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com}
10986d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com
1108381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.comvoid SkLayer::detachFromParent() {
1118381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com    if (fParent) {
1128381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        int index = fParent->m_children.find(this);
1138381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        SkASSERT(index >= 0);
1148381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        fParent->m_children.remove(index);
1158381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        fParent = NULL;
1168381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        this->unref();  // this call might delete us
117745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    }
118745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com}
119745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com
12086d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.comvoid SkLayer::removeChildren() {
1218381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com    int count = m_children.count();
1228381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com    for (int i = 0; i < count; i++) {
1238381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        SkLayer* child = m_children[i];
1248381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        SkASSERT(child->fParent == this);
1258381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        child->fParent = NULL;  // in case it has more than one owner
1268381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        child->unref();
1278381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com    }
12886d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com    m_children.reset();
12986d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com}
13086d4008e894f6ce0b1938ac6b45d4074af85d3b7reed@android.com
131745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.comSkLayer* SkLayer::getRootLayer() const {
132745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    const SkLayer* root = this;
133745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    while (root->fParent != NULL) {
134745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com        root = root->fParent;
135745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    }
136745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    return const_cast<SkLayer*>(root);
137745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com}
138745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com
13981dc331e65ba5a24d515c11890234dd205408c89reed@android.com///////////////////////////////////////////////////////////////////////////////
14081dc331e65ba5a24d515c11890234dd205408c89reed@android.com
141745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.comvoid SkLayer::getLocalTransform(SkMatrix* matrix) const {
142745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    matrix->setTranslate(m_position.fX, m_position.fY);
143940584d30085db25c502833cbb8d19e776811841reed@android.com
144745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    SkScalar tx = SkScalarMul(m_anchorPoint.fX, m_size.width());
145745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    SkScalar ty = SkScalarMul(m_anchorPoint.fY, m_size.height());
146745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    matrix->preTranslate(tx, ty);
147745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    matrix->preConcat(this->getMatrix());
148745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    matrix->preTranslate(-tx, -ty);
14981dc331e65ba5a24d515c11890234dd205408c89reed@android.com}
15081dc331e65ba5a24d515c11890234dd205408c89reed@android.com
151745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.comvoid SkLayer::localToGlobal(SkMatrix* matrix) const {
152745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    this->getLocalTransform(matrix);
153745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com
1548381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com    if (this->isInheritFromRootTransform()) {
1558381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        matrix->postConcat(this->getRootLayer()->getMatrix());
1568381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        return;
1578381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com    }
1588381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com
159745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    const SkLayer* layer = this;
160745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    while (layer->fParent != NULL) {
161745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com        layer = layer->fParent;
162745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com
163745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com        SkMatrix tmp;
164745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com        layer->getLocalTransform(&tmp);
165745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com        tmp.preConcat(layer->getChildrenMatrix());
166745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com        matrix->postConcat(tmp);
167745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    }
16881dc331e65ba5a24d515c11890234dd205408c89reed@android.com}
16981dc331e65ba5a24d515c11890234dd205408c89reed@android.com
17081dc331e65ba5a24d515c11890234dd205408c89reed@android.com///////////////////////////////////////////////////////////////////////////////
17181dc331e65ba5a24d515c11890234dd205408c89reed@android.com
172da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.comvoid SkLayer::onDraw(SkCanvas*, SkScalar opacity) {
173da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com//    SkDebugf("----- no onDraw for %p\n", this);
17481dc331e65ba5a24d515c11890234dd205408c89reed@android.com}
17581dc331e65ba5a24d515c11890234dd205408c89reed@android.com
176da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com#include "SkString.h"
17781dc331e65ba5a24d515c11890234dd205408c89reed@android.com
178da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.comvoid SkLayer::draw(SkCanvas* canvas, SkScalar opacity) {
17981dc331e65ba5a24d515c11890234dd205408c89reed@android.com#if 0
180da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    SkString str1, str2;
181da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com //   this->getMatrix().toDumpString(&str1);
182da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com //   this->getChildrenMatrix().toDumpString(&str2);
183da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    SkDebugf("--- drawlayer %p opacity %g size [%g %g] pos [%g %g] matrix %s children %s\n",
184da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com             this, opacity * this->getOpacity(), m_size.width(), m_size.height(),
185da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com             m_position.fX, m_position.fY, str1.c_str(), str2.c_str());
18681dc331e65ba5a24d515c11890234dd205408c89reed@android.com#endif
18781dc331e65ba5a24d515c11890234dd205408c89reed@android.com
18881dc331e65ba5a24d515c11890234dd205408c89reed@android.com    opacity = SkScalarMul(opacity, this->getOpacity());
189940584d30085db25c502833cbb8d19e776811841reed@android.com    if (opacity <= 0) {
190940584d30085db25c502833cbb8d19e776811841reed@android.com//        SkDebugf("---- abort drawing %p opacity %g\n", this, opacity);
19181dc331e65ba5a24d515c11890234dd205408c89reed@android.com        return;
19281dc331e65ba5a24d515c11890234dd205408c89reed@android.com    }
19381dc331e65ba5a24d515c11890234dd205408c89reed@android.com
194da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    SkAutoCanvasRestore acr(canvas, true);
195da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com
196745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com    // apply our local transform
197da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    {
1988381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        SkMatrix tmp;
1998381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        this->getLocalTransform(&tmp);
2008381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        if (this->isInheritFromRootTransform()) {
2018381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com            // should we also apply the root's childrenMatrix?
2028381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com            canvas->setMatrix(getRootLayer()->getMatrix());
2038381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        }
2048381e007dc655b7db4ddf5cafdc057f2dbc1dc6areed@android.com        canvas->concat(tmp);
205da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    }
20681dc331e65ba5a24d515c11890234dd205408c89reed@android.com
207da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com    this->onDraw(canvas, opacity);
20881dc331e65ba5a24d515c11890234dd205408c89reed@android.com
209745bfbd74d1bcd62b9c597b62907875bca5cf84ereed@android.com#ifdef DEBUG_DRAW_LAYER_BOUNDS
2102bd703b3163fe1da3ea55f6459c5e162f32cce12reed@android.com    {
2112bd703b3163fe1da3ea55f6459c5e162f32cce12reed@android.com        SkRect r = SkRect::MakeSize(this->getSize());
2122bd703b3163fe1da3ea55f6459c5e162f32cce12reed@android.com        SkPaint p;
2132bd703b3163fe1da3ea55f6459c5e162f32cce12reed@android.com        p.setAntiAlias(true);
2142bd703b3163fe1da3ea55f6459c5e162f32cce12reed@android.com        p.setStyle(SkPaint::kStroke_Style);
2152bd703b3163fe1da3ea55f6459c5e162f32cce12reed@android.com        p.setStrokeWidth(SkIntToScalar(2));
2162bd703b3163fe1da3ea55f6459c5e162f32cce12reed@android.com        p.setColor(0xFFFF44DD);
2172bd703b3163fe1da3ea55f6459c5e162f32cce12reed@android.com        canvas->drawRect(r, p);
2182bd703b3163fe1da3ea55f6459c5e162f32cce12reed@android.com        canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, p);
2192bd703b3163fe1da3ea55f6459c5e162f32cce12reed@android.com        canvas->drawLine(r.fLeft, r.fBottom, r.fRight, r.fTop, p);
2202bd703b3163fe1da3ea55f6459c5e162f32cce12reed@android.com    }
2212bd703b3163fe1da3ea55f6459c5e162f32cce12reed@android.com#endif
2222bd703b3163fe1da3ea55f6459c5e162f32cce12reed@android.com
22381dc331e65ba5a24d515c11890234dd205408c89reed@android.com    int count = this->countChildren();
22481dc331e65ba5a24d515c11890234dd205408c89reed@android.com    if (count > 0) {
22581dc331e65ba5a24d515c11890234dd205408c89reed@android.com        canvas->concat(this->getChildrenMatrix());
22681dc331e65ba5a24d515c11890234dd205408c89reed@android.com        for (int i = 0; i < count; i++) {
227da6fb3246a4f3e7e835f23b4834affb80bb613fareed@android.com            this->getChild(i)->draw(canvas, opacity);
22881dc331e65ba5a24d515c11890234dd205408c89reed@android.com        }
22981dc331e65ba5a24d515c11890234dd205408c89reed@android.com    }
23081dc331e65ba5a24d515c11890234dd205408c89reed@android.com}
231