blob: 888afec99e9e9e56a7ce50bde6173eb807358406 [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);
reed@android.com940584d2010-02-26 22:04:15 +0000118
reed@android.com745bfbd2010-02-24 17:16:35 +0000119 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());
reed@android.com940584d2010-02-26 22:04:15 +0000159 if (opacity <= 0) {
160// SkDebugf("---- abort drawing %p opacity %g\n", this, opacity);
reed@android.com81dc3312010-02-18 19:32:03 +0000161 return;
162 }
163
reed@android.comda6fb322010-02-19 21:41:30 +0000164 SkAutoCanvasRestore acr(canvas, true);
reed@android.com81dc3312010-02-18 19:32:03 +0000165
reed@android.com745bfbd2010-02-24 17:16:35 +0000166 // apply our local transform
reed@android.comda6fb322010-02-19 21:41:30 +0000167 {
reed@android.com745bfbd2010-02-24 17:16:35 +0000168 canvas->translate(m_position.fX, m_position.fY);
reed@android.comda6fb322010-02-19 21:41:30 +0000169
reed@android.com745bfbd2010-02-24 17:16:35 +0000170 SkScalar tx = SkScalarMul(m_anchorPoint.fX, m_size.width());
171 SkScalar ty = SkScalarMul(m_anchorPoint.fY, m_size.height());
reed@android.comda6fb322010-02-19 21:41:30 +0000172 canvas->translate(tx, ty);
173 canvas->concat(this->getMatrix());
174 canvas->translate(-tx, -ty);
175 }
176
177 this->onDraw(canvas, opacity);
reed@android.com81dc3312010-02-18 19:32:03 +0000178
reed@android.com745bfbd2010-02-24 17:16:35 +0000179#ifdef DEBUG_DRAW_LAYER_BOUNDS
reed@android.com2bd703b2010-02-24 02:01:23 +0000180 {
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
reed@android.com81dc3312010-02-18 19:32:03 +0000193 int count = this->countChildren();
194 if (count > 0) {
195 canvas->concat(this->getChildrenMatrix());
196 for (int i = 0; i < count; i++) {
reed@android.comda6fb322010-02-19 21:41:30 +0000197 this->getChild(i)->draw(canvas, opacity);
reed@android.com81dc3312010-02-18 19:32:03 +0000198 }
199 }
200}
reed@android.com86d40082010-02-12 17:17:10 +0000201