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