blob: fe61c02338540d1b30ed9c6e14e5da2a366d42f0 [file] [log] [blame]
reed@android.com86d40082010-02-12 17:17:10 +00001#include "SkLayer.h"
reed@android.com81dc3312010-02-18 19:32:03 +00002#include "SkCanvas.h"
reed@android.com86d40082010-02-12 17:17:10 +00003
reed@android.com745bfbd2010-02-24 17:16:35 +00004//#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///////////////////////////////////////////////////////////////////////////////
reed@android.com2bd703b2010-02-24 02:01:23 +000012
reed@android.com86d40082010-02-12 17:17:10 +000013SkLayer::SkLayer() {
reed@android.com745bfbd2010-02-24 17:16:35 +000014 fParent = NULL;
reed@android.com2bd703b2010-02-24 02:01:23 +000015 m_opacity = SK_Scalar1;
reed@android.com86d40082010-02-12 17:17:10 +000016 m_size.set(0, 0);
17 m_position.set(0, 0);
reed@android.com2bd703b2010-02-24 02:01:23 +000018 m_anchorPoint.set(SK_ScalarHalf, SK_ScalarHalf);
reed@android.com81dc3312010-02-18 19:32:03 +000019
20 fMatrix.reset();
21 fChildrenMatrix.reset();
reed@android.com745bfbd2010-02-24 17:16:35 +000022
23#ifdef DEBUG_TRACK_NEW_DELETE
24 gLayerAllocCount += 1;
25 SkDebugf("SkLayer new: %d\n", gLayerAllocCount);
26#endif
reed@android.com86d40082010-02-12 17:17:10 +000027}
28
29SkLayer::SkLayer(const SkLayer& src) {
reed@android.com745bfbd2010-02-24 17:16:35 +000030 fParent = NULL;
reed@android.com86d40082010-02-12 17:17:10 +000031 m_opacity = src.m_opacity;
32 m_size = src.m_size;
33 m_position = src.m_position;
reed@android.com86d40082010-02-12 17:17:10 +000034 m_anchorPoint = src.m_anchorPoint;
reed@android.com81dc3312010-02-18 19:32:03 +000035
36 fMatrix = src.fMatrix;
37 fChildrenMatrix = src.fChildrenMatrix;
reed@android.com745bfbd2010-02-24 17:16:35 +000038
39#ifdef DEBUG_TRACK_NEW_DELETE
40 gLayerAllocCount += 1;
41 SkDebugf("SkLayer copy: %d\n", gLayerAllocCount);
42#endif
reed@android.com86d40082010-02-12 17:17:10 +000043}
44
45SkLayer::~SkLayer() {
46 this->removeChildren();
reed@android.com745bfbd2010-02-24 17:16:35 +000047
48#ifdef DEBUG_TRACK_NEW_DELETE
49 gLayerAllocCount -= 1;
50 SkDebugf("SkLayer delete: %d\n", gLayerAllocCount);
51#endif
reed@android.com86d40082010-02-12 17:17:10 +000052}
53
reed@android.com745bfbd2010-02-24 17:16:35 +000054///////////////////////////////////////////////////////////////////////////////
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
reed@android.com86d40082010-02-12 17:17:10 +000066int 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();
reed@android.com745bfbd2010-02-24 17:16:35 +000079 if (child->fParent) {
80 child->fParent->removeChild(child);
81 }
82 SkASSERT(child->fParent == NULL);
83 child->fParent = this;
84
reed@android.com86d40082010-02-12 17:17:10 +000085 *m_children.append() = child;
86 return child;
87}
88
reed@android.com745bfbd2010-02-24 17:16:35 +000089bool 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
reed@android.com86d40082010-02-12 17:17:10 +0000101void SkLayer::removeChildren() {
102 m_children.unrefAll();
103 m_children.reset();
104}
105
reed@android.com745bfbd2010-02-24 17:16:35 +0000106SkLayer* SkLayer::getRootLayer() const {
107 const SkLayer* root = this;
108 while (root->fParent != NULL) {
109 root = root->fParent;
110 }
111 return const_cast<SkLayer*>(root);
reed@android.com81dc3312010-02-18 19:32:03 +0000112}
113
reed@android.com745bfbd2010-02-24 17:16:35 +0000114///////////////////////////////////////////////////////////////////////////////
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 }
reed@android.com81dc3312010-02-18 19:32:03 +0000138}
139
140///////////////////////////////////////////////////////////////////////////////
141
reed@android.comda6fb322010-02-19 21:41:30 +0000142void SkLayer::onDraw(SkCanvas*, SkScalar opacity) {
143// SkDebugf("----- no onDraw for %p\n", this);
reed@android.com81dc3312010-02-18 19:32:03 +0000144}
145
reed@android.comda6fb322010-02-19 21:41:30 +0000146#include "SkString.h"
reed@android.com81dc3312010-02-18 19:32:03 +0000147
reed@android.comda6fb322010-02-19 21:41:30 +0000148void SkLayer::draw(SkCanvas* canvas, SkScalar opacity) {
reed@android.com81dc3312010-02-18 19:32:03 +0000149#if 0
reed@android.comda6fb322010-02-19 21:41:30 +0000150 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());
reed@android.com81dc3312010-02-18 19:32:03 +0000156#endif
157
158 opacity = SkScalarMul(opacity, this->getOpacity());
159 if (opacity <= 0 || this->getSize().isEmpty()) {
reed@android.comda6fb322010-02-19 21:41:30 +0000160#if 0
161 SkDebugf("---- abort drawing %p opacity %g size [%g %g]\n",
162 this, opacity, m_size.width(), m_size.height());
163#endif
reed@android.com81dc3312010-02-18 19:32:03 +0000164 return;
165 }
166
reed@android.comda6fb322010-02-19 21:41:30 +0000167 SkAutoCanvasRestore acr(canvas, true);
reed@android.com81dc3312010-02-18 19:32:03 +0000168
reed@android.com745bfbd2010-02-24 17:16:35 +0000169 // apply our local transform
reed@android.comda6fb322010-02-19 21:41:30 +0000170 {
reed@android.com745bfbd2010-02-24 17:16:35 +0000171 canvas->translate(m_position.fX, m_position.fY);
reed@android.comda6fb322010-02-19 21:41:30 +0000172
reed@android.com745bfbd2010-02-24 17:16:35 +0000173 SkScalar tx = SkScalarMul(m_anchorPoint.fX, m_size.width());
174 SkScalar ty = SkScalarMul(m_anchorPoint.fY, m_size.height());
reed@android.comda6fb322010-02-19 21:41:30 +0000175 canvas->translate(tx, ty);
176 canvas->concat(this->getMatrix());
177 canvas->translate(-tx, -ty);
178 }
179
180 this->onDraw(canvas, opacity);
reed@android.com81dc3312010-02-18 19:32:03 +0000181
reed@android.com745bfbd2010-02-24 17:16:35 +0000182#ifdef DEBUG_DRAW_LAYER_BOUNDS
reed@android.com2bd703b2010-02-24 02:01:23 +0000183 {
184 SkRect r = SkRect::MakeSize(this->getSize());
185 SkPaint p;
186 p.setAntiAlias(true);
187 p.setStyle(SkPaint::kStroke_Style);
188 p.setStrokeWidth(SkIntToScalar(2));
189 p.setColor(0xFFFF44DD);
190 canvas->drawRect(r, p);
191 canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, p);
192 canvas->drawLine(r.fLeft, r.fBottom, r.fRight, r.fTop, p);
193 }
194#endif
195
reed@android.com81dc3312010-02-18 19:32:03 +0000196 int count = this->countChildren();
197 if (count > 0) {
198 canvas->concat(this->getChildrenMatrix());
199 for (int i = 0; i < count; i++) {
reed@android.comda6fb322010-02-19 21:41:30 +0000200 this->getChild(i)->draw(canvas, opacity);
reed@android.com81dc3312010-02-18 19:32:03 +0000201 }
202 }
203}
reed@android.com86d40082010-02-12 17:17:10 +0000204