blob: 5c68261bc8ce2c34d05cf6e41a40b76022b3f974 [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.com8381e002010-03-23 20:10:46 +000022 fFlags = 0;
reed@android.com745bfbd2010-02-24 17:16:35 +000023
24#ifdef DEBUG_TRACK_NEW_DELETE
25 gLayerAllocCount += 1;
26 SkDebugf("SkLayer new: %d\n", gLayerAllocCount);
27#endif
reed@android.com86d40082010-02-12 17:17:10 +000028}
29
30SkLayer::SkLayer(const SkLayer& src) {
reed@android.com745bfbd2010-02-24 17:16:35 +000031 fParent = NULL;
reed@android.com86d40082010-02-12 17:17:10 +000032 m_opacity = src.m_opacity;
33 m_size = src.m_size;
34 m_position = src.m_position;
reed@android.com86d40082010-02-12 17:17:10 +000035 m_anchorPoint = src.m_anchorPoint;
reed@android.com81dc3312010-02-18 19:32:03 +000036
37 fMatrix = src.fMatrix;
38 fChildrenMatrix = src.fChildrenMatrix;
reed@android.com8381e002010-03-23 20:10:46 +000039 fFlags = src.fFlags;
reed@android.com745bfbd2010-02-24 17:16:35 +000040
41#ifdef DEBUG_TRACK_NEW_DELETE
42 gLayerAllocCount += 1;
43 SkDebugf("SkLayer copy: %d\n", gLayerAllocCount);
44#endif
reed@android.com86d40082010-02-12 17:17:10 +000045}
46
47SkLayer::~SkLayer() {
48 this->removeChildren();
reed@android.com745bfbd2010-02-24 17:16:35 +000049
50#ifdef DEBUG_TRACK_NEW_DELETE
51 gLayerAllocCount -= 1;
52 SkDebugf("SkLayer delete: %d\n", gLayerAllocCount);
53#endif
reed@android.com86d40082010-02-12 17:17:10 +000054}
55
reed@android.com745bfbd2010-02-24 17:16:35 +000056///////////////////////////////////////////////////////////////////////////////
57
reed@android.com8381e002010-03-23 20:10:46 +000058bool 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
reed@android.com745bfbd2010-02-24 17:16:35 +000070void SkLayer::setMatrix(const SkMatrix& matrix) {
71 fMatrix = matrix;
72}
73
74void SkLayer::setChildrenMatrix(const SkMatrix& matrix) {
75 fChildrenMatrix = matrix;
76}
77
78///////////////////////////////////////////////////////////////////////////////
79
reed@android.com86d40082010-02-12 17:17:10 +000080int SkLayer::countChildren() const {
81 return m_children.count();
82}
83
84SkLayer* SkLayer::getChild(int index) const {
85 if ((unsigned)index < (unsigned)m_children.count()) {
reed@android.com8381e002010-03-23 20:10:46 +000086 SkASSERT(m_children[index]->fParent == this);
reed@android.com86d40082010-02-12 17:17:10 +000087 return m_children[index];
88 }
89 return NULL;
90}
91
92SkLayer* SkLayer::addChild(SkLayer* child) {
reed@android.com8381e002010-03-23 20:10:46 +000093 SkASSERT(this != child);
reed@android.com86d40082010-02-12 17:17:10 +000094 child->ref();
reed@android.com8381e002010-03-23 20:10:46 +000095 child->detachFromParent();
reed@android.com745bfbd2010-02-24 17:16:35 +000096 SkASSERT(child->fParent == NULL);
97 child->fParent = this;
98
reed@android.com86d40082010-02-12 17:17:10 +000099 *m_children.append() = child;
100 return child;
101}
102
reed@android.com8381e002010-03-23 20:10:46 +0000103void 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
reed@android.com745bfbd2010-02-24 17:16:35 +0000110 }
reed@android.com745bfbd2010-02-24 17:16:35 +0000111}
112
reed@android.com86d40082010-02-12 17:17:10 +0000113void SkLayer::removeChildren() {
reed@android.com8381e002010-03-23 20:10:46 +0000114 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 }
reed@android.com86d40082010-02-12 17:17:10 +0000121 m_children.reset();
122}
123
reed@android.com745bfbd2010-02-24 17:16:35 +0000124SkLayer* SkLayer::getRootLayer() const {
125 const SkLayer* root = this;
126 while (root->fParent != NULL) {
127 root = root->fParent;
128 }
129 return const_cast<SkLayer*>(root);
reed@android.com81dc3312010-02-18 19:32:03 +0000130}
131
reed@android.com745bfbd2010-02-24 17:16:35 +0000132///////////////////////////////////////////////////////////////////////////////
133
134void SkLayer::getLocalTransform(SkMatrix* matrix) const {
135 matrix->setTranslate(m_position.fX, m_position.fY);
reed@android.com940584d2010-02-26 22:04:15 +0000136
reed@android.com745bfbd2010-02-24 17:16:35 +0000137 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
reed@android.com8381e002010-03-23 20:10:46 +0000147 if (this->isInheritFromRootTransform()) {
148 matrix->postConcat(this->getRootLayer()->getMatrix());
149 return;
150 }
151
reed@android.com745bfbd2010-02-24 17:16:35 +0000152 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 }
reed@android.com81dc3312010-02-18 19:32:03 +0000161}
162
163///////////////////////////////////////////////////////////////////////////////
164
reed@android.comda6fb322010-02-19 21:41:30 +0000165void SkLayer::onDraw(SkCanvas*, SkScalar opacity) {
166// SkDebugf("----- no onDraw for %p\n", this);
reed@android.com81dc3312010-02-18 19:32:03 +0000167}
168
reed@android.comda6fb322010-02-19 21:41:30 +0000169#include "SkString.h"
reed@android.com81dc3312010-02-18 19:32:03 +0000170
reed@android.comda6fb322010-02-19 21:41:30 +0000171void SkLayer::draw(SkCanvas* canvas, SkScalar opacity) {
reed@android.com81dc3312010-02-18 19:32:03 +0000172#if 0
reed@android.comda6fb322010-02-19 21:41:30 +0000173 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());
reed@android.com81dc3312010-02-18 19:32:03 +0000179#endif
180
181 opacity = SkScalarMul(opacity, this->getOpacity());
reed@android.com940584d2010-02-26 22:04:15 +0000182 if (opacity <= 0) {
183// SkDebugf("---- abort drawing %p opacity %g\n", this, opacity);
reed@android.com81dc3312010-02-18 19:32:03 +0000184 return;
185 }
186
reed@android.comda6fb322010-02-19 21:41:30 +0000187 SkAutoCanvasRestore acr(canvas, true);
reed@android.com81dc3312010-02-18 19:32:03 +0000188
reed@android.com745bfbd2010-02-24 17:16:35 +0000189 // apply our local transform
reed@android.comda6fb322010-02-19 21:41:30 +0000190 {
reed@android.com8381e002010-03-23 20:10:46 +0000191 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);
reed@android.comda6fb322010-02-19 21:41:30 +0000198 }
199
200 this->onDraw(canvas, opacity);
reed@android.com81dc3312010-02-18 19:32:03 +0000201
reed@android.com745bfbd2010-02-24 17:16:35 +0000202#ifdef DEBUG_DRAW_LAYER_BOUNDS
reed@android.com2bd703b2010-02-24 02:01:23 +0000203 {
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
reed@android.com81dc3312010-02-18 19:32:03 +0000216 int count = this->countChildren();
217 if (count > 0) {
218 canvas->concat(this->getChildrenMatrix());
219 for (int i = 0; i < count; i++) {
reed@android.comda6fb322010-02-19 21:41:30 +0000220 this->getChild(i)->draw(canvas, opacity);
reed@android.com81dc3312010-02-18 19:32:03 +0000221 }
222 }
223}
reed@android.com86d40082010-02-12 17:17:10 +0000224