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    fFlags = 0;
23
24#ifdef DEBUG_TRACK_NEW_DELETE
25    gLayerAllocCount += 1;
26    SkDebugf("SkLayer new:    %d\n", gLayerAllocCount);
27#endif
28}
29
30SkLayer::SkLayer(const SkLayer& src) {
31    fParent = NULL;
32    m_opacity = src.m_opacity;
33    m_size = src.m_size;
34    m_position = src.m_position;
35    m_anchorPoint = src.m_anchorPoint;
36
37    fMatrix = src.fMatrix;
38    fChildrenMatrix = src.fChildrenMatrix;
39    fFlags = src.fFlags;
40
41#ifdef DEBUG_TRACK_NEW_DELETE
42    gLayerAllocCount += 1;
43    SkDebugf("SkLayer copy:   %d\n", gLayerAllocCount);
44#endif
45}
46
47SkLayer::~SkLayer() {
48    this->removeChildren();
49
50#ifdef DEBUG_TRACK_NEW_DELETE
51    gLayerAllocCount -= 1;
52    SkDebugf("SkLayer delete: %d\n", gLayerAllocCount);
53#endif
54}
55
56///////////////////////////////////////////////////////////////////////////////
57
58bool SkLayer::isInheritFromRootTransform() const {
59    return (fFlags & kInheritFromRootTransform_Flag) != 0;
60}
61
62void SkLayer::setInheritFromRootTransform(bool doInherit) {
63    if (doInherit) {
64        fFlags |= kInheritFromRootTransform_Flag;
65    } else {
66        fFlags &= ~kInheritFromRootTransform_Flag;
67    }
68}
69
70void SkLayer::setMatrix(const SkMatrix& matrix) {
71    fMatrix = matrix;
72}
73
74void SkLayer::setChildrenMatrix(const SkMatrix& matrix) {
75    fChildrenMatrix = matrix;
76}
77
78///////////////////////////////////////////////////////////////////////////////
79
80int SkLayer::countChildren() const {
81    return m_children.count();
82}
83
84SkLayer* SkLayer::getChild(int index) const {
85    if ((unsigned)index < (unsigned)m_children.count()) {
86        SkASSERT(m_children[index]->fParent == this);
87        return m_children[index];
88    }
89    return NULL;
90}
91
92SkLayer* SkLayer::addChild(SkLayer* child) {
93    SkASSERT(this != child);
94    child->ref();
95    child->detachFromParent();
96    SkASSERT(child->fParent == NULL);
97    child->fParent = this;
98
99    *m_children.append() = child;
100    return child;
101}
102
103void SkLayer::detachFromParent() {
104    if (fParent) {
105        int index = fParent->m_children.find(this);
106        SkASSERT(index >= 0);
107        fParent->m_children.remove(index);
108        fParent = NULL;
109        this->unref();  // this call might delete us
110    }
111}
112
113void SkLayer::removeChildren() {
114    int count = m_children.count();
115    for (int i = 0; i < count; i++) {
116        SkLayer* child = m_children[i];
117        SkASSERT(child->fParent == this);
118        child->fParent = NULL;  // in case it has more than one owner
119        child->unref();
120    }
121    m_children.reset();
122}
123
124SkLayer* SkLayer::getRootLayer() const {
125    const SkLayer* root = this;
126    while (root->fParent != NULL) {
127        root = root->fParent;
128    }
129    return const_cast<SkLayer*>(root);
130}
131
132///////////////////////////////////////////////////////////////////////////////
133
134void SkLayer::getLocalTransform(SkMatrix* matrix) const {
135    matrix->setTranslate(m_position.fX, m_position.fY);
136
137    SkScalar tx = SkScalarMul(m_anchorPoint.fX, m_size.width());
138    SkScalar ty = SkScalarMul(m_anchorPoint.fY, m_size.height());
139    matrix->preTranslate(tx, ty);
140    matrix->preConcat(this->getMatrix());
141    matrix->preTranslate(-tx, -ty);
142}
143
144void SkLayer::localToGlobal(SkMatrix* matrix) const {
145    this->getLocalTransform(matrix);
146
147    if (this->isInheritFromRootTransform()) {
148        matrix->postConcat(this->getRootLayer()->getMatrix());
149        return;
150    }
151
152    const SkLayer* layer = this;
153    while (layer->fParent != NULL) {
154        layer = layer->fParent;
155
156        SkMatrix tmp;
157        layer->getLocalTransform(&tmp);
158        tmp.preConcat(layer->getChildrenMatrix());
159        matrix->postConcat(tmp);
160    }
161}
162
163///////////////////////////////////////////////////////////////////////////////
164
165void SkLayer::onDraw(SkCanvas*, SkScalar opacity) {
166//    SkDebugf("----- no onDraw for %p\n", this);
167}
168
169#include "SkString.h"
170
171void SkLayer::draw(SkCanvas* canvas, SkScalar opacity) {
172#if 0
173    SkString str1, str2;
174 //   this->getMatrix().toDumpString(&str1);
175 //   this->getChildrenMatrix().toDumpString(&str2);
176    SkDebugf("--- drawlayer %p opacity %g size [%g %g] pos [%g %g] matrix %s children %s\n",
177             this, opacity * this->getOpacity(), m_size.width(), m_size.height(),
178             m_position.fX, m_position.fY, str1.c_str(), str2.c_str());
179#endif
180
181    opacity = SkScalarMul(opacity, this->getOpacity());
182    if (opacity <= 0) {
183//        SkDebugf("---- abort drawing %p opacity %g\n", this, opacity);
184        return;
185    }
186
187    SkAutoCanvasRestore acr(canvas, true);
188
189    // apply our local transform
190    {
191        SkMatrix tmp;
192        this->getLocalTransform(&tmp);
193        if (this->isInheritFromRootTransform()) {
194            // should we also apply the root's childrenMatrix?
195            canvas->setMatrix(getRootLayer()->getMatrix());
196        }
197        canvas->concat(tmp);
198    }
199
200    this->onDraw(canvas, opacity);
201
202#ifdef DEBUG_DRAW_LAYER_BOUNDS
203    {
204        SkRect r = SkRect::MakeSize(this->getSize());
205        SkPaint p;
206        p.setAntiAlias(true);
207        p.setStyle(SkPaint::kStroke_Style);
208        p.setStrokeWidth(SkIntToScalar(2));
209        p.setColor(0xFFFF44DD);
210        canvas->drawRect(r, p);
211        canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, p);
212        canvas->drawLine(r.fLeft, r.fBottom, r.fRight, r.fTop, p);
213    }
214#endif
215
216    int count = this->countChildren();
217    if (count > 0) {
218        canvas->concat(this->getChildrenMatrix());
219        for (int i = 0; i < count; i++) {
220            this->getChild(i)->draw(canvas, opacity);
221        }
222    }
223}
224
225