SkLayer.cpp revision 5770f2c5ca580514442e30a9f4965e8bb15342f3
1#include "SkLayer.h"
2#include "SkCanvas.h"
3
4//#define DEBUG_DRAW_LAYER_BOUNDS
5//#define DEBUG_TRACK_NEW_DELETE
6
7#ifdef DEBUG_TRACK_NEW_DELETE
8    static int gLayerAllocCount;
9#endif
10
11///////////////////////////////////////////////////////////////////////////////
12
13SkLayer::SkLayer() {
14    fParent = NULL;
15    m_opacity = SK_Scalar1;
16    m_size.set(0, 0);
17    m_position.set(0, 0);
18    m_anchorPoint.set(SK_ScalarHalf, SK_ScalarHalf);
19
20    fMatrix.reset();
21    fChildrenMatrix.reset();
22
23#ifdef DEBUG_TRACK_NEW_DELETE
24    gLayerAllocCount += 1;
25    SkDebugf("SkLayer new:    %d\n", gLayerAllocCount);
26#endif
27}
28
29SkLayer::SkLayer(const SkLayer& src) {
30    fParent = NULL;
31    m_opacity = src.m_opacity;
32    m_size = src.m_size;
33    m_position = src.m_position;
34    m_anchorPoint = src.m_anchorPoint;
35
36    fMatrix = src.fMatrix;
37    fChildrenMatrix = src.fChildrenMatrix;
38
39#ifdef DEBUG_TRACK_NEW_DELETE
40    gLayerAllocCount += 1;
41    SkDebugf("SkLayer copy:   %d\n", gLayerAllocCount);
42#endif
43}
44
45SkLayer::~SkLayer() {
46    this->removeChildren();
47
48#ifdef DEBUG_TRACK_NEW_DELETE
49    gLayerAllocCount -= 1;
50    SkDebugf("SkLayer delete: %d\n", gLayerAllocCount);
51#endif
52}
53
54///////////////////////////////////////////////////////////////////////////////
55
56void SkLayer::setMatrix(const SkMatrix& matrix) {
57    fMatrix = matrix;
58}
59
60void SkLayer::setChildrenMatrix(const SkMatrix& matrix) {
61    fChildrenMatrix = matrix;
62}
63
64///////////////////////////////////////////////////////////////////////////////
65
66int SkLayer::countChildren() const {
67    return m_children.count();
68}
69
70SkLayer* SkLayer::getChild(int index) const {
71    if ((unsigned)index < (unsigned)m_children.count()) {
72        return m_children[index];
73    }
74    return NULL;
75}
76
77SkLayer* SkLayer::addChild(SkLayer* child) {
78    child->ref();
79    if (child->fParent) {
80        child->fParent->removeChild(child);
81    }
82    SkASSERT(child->fParent == NULL);
83    child->fParent = this;
84
85    *m_children.append() = child;
86    return child;
87}
88
89bool SkLayer::removeChild(SkLayer* child) {
90    int index = m_children.find(child);
91    if (index >= 0) {
92        SkASSERT(child->fParent == this);
93        child->fParent = NULL;
94        child->unref();
95        m_children.remove(index);
96        return true;
97    }
98    return false;
99}
100
101void SkLayer::removeChildren() {
102    m_children.unrefAll();
103    m_children.reset();
104}
105
106SkLayer* SkLayer::getRootLayer() const {
107    const SkLayer* root = this;
108    while (root->fParent != NULL) {
109        root = root->fParent;
110    }
111    return const_cast<SkLayer*>(root);
112}
113
114///////////////////////////////////////////////////////////////////////////////
115
116void SkLayer::getLocalTransform(SkMatrix* matrix) const {
117    matrix->setTranslate(m_position.fX, m_position.fY);
118
119    SkScalar tx = SkScalarMul(m_anchorPoint.fX, m_size.width());
120    SkScalar ty = SkScalarMul(m_anchorPoint.fY, m_size.height());
121    matrix->preTranslate(tx, ty);
122    matrix->preConcat(this->getMatrix());
123    matrix->preTranslate(-tx, -ty);
124}
125
126void SkLayer::localToGlobal(SkMatrix* matrix) const {
127    this->getLocalTransform(matrix);
128
129    const SkLayer* layer = this;
130    while (layer->fParent != NULL) {
131        layer = layer->fParent;
132
133        SkMatrix tmp;
134        layer->getLocalTransform(&tmp);
135        tmp.preConcat(layer->getChildrenMatrix());
136        matrix->postConcat(tmp);
137    }
138}
139
140///////////////////////////////////////////////////////////////////////////////
141
142void SkLayer::onDraw(SkCanvas*, SkScalar opacity) {
143//    SkDebugf("----- no onDraw for %p\n", this);
144}
145
146#include "SkString.h"
147
148void SkLayer::draw(SkCanvas* canvas, SkScalar opacity) {
149#if 0
150    SkString str1, str2;
151 //   this->getMatrix().toDumpString(&str1);
152 //   this->getChildrenMatrix().toDumpString(&str2);
153    SkDebugf("--- drawlayer %p opacity %g size [%g %g] pos [%g %g] matrix %s children %s\n",
154             this, opacity * this->getOpacity(), m_size.width(), m_size.height(),
155             m_position.fX, m_position.fY, str1.c_str(), str2.c_str());
156#endif
157
158    opacity = SkScalarMul(opacity, this->getOpacity());
159    if (opacity <= 0) {
160//        SkDebugf("---- abort drawing %p opacity %g\n", this, opacity);
161        return;
162    }
163
164    SkAutoCanvasRestore acr(canvas, true);
165
166    // apply our local transform
167    {
168        canvas->translate(m_position.fX, m_position.fY);
169
170        SkScalar tx = SkScalarMul(m_anchorPoint.fX, m_size.width());
171        SkScalar ty = SkScalarMul(m_anchorPoint.fY, m_size.height());
172        canvas->translate(tx, ty);
173        canvas->concat(this->getMatrix());
174        canvas->translate(-tx, -ty);
175    }
176
177    this->onDraw(canvas, opacity);
178
179#ifdef DEBUG_DRAW_LAYER_BOUNDS
180    {
181        SkRect r = SkRect::MakeSize(this->getSize());
182        SkPaint p;
183        p.setAntiAlias(true);
184        p.setStyle(SkPaint::kStroke_Style);
185        p.setStrokeWidth(SkIntToScalar(2));
186        p.setColor(0xFFFF44DD);
187        canvas->drawRect(r, p);
188        canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, p);
189        canvas->drawLine(r.fLeft, r.fBottom, r.fRight, r.fTop, p);
190    }
191#endif
192
193    int count = this->countChildren();
194    if (count > 0) {
195        canvas->concat(this->getChildrenMatrix());
196        for (int i = 0; i < count; i++) {
197            this->getChild(i)->draw(canvas, opacity);
198        }
199    }
200}
201
202