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
SkLayer()13 SkLayer::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
SkLayer(const SkLayer & src)30 SkLayer::SkLayer(const SkLayer& src) : INHERITED() {
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
~SkLayer()47 SkLayer::~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
isInheritFromRootTransform() const58 bool SkLayer::isInheritFromRootTransform() const {
59 return (fFlags & kInheritFromRootTransform_Flag) != 0;
60 }
61
setInheritFromRootTransform(bool doInherit)62 void SkLayer::setInheritFromRootTransform(bool doInherit) {
63 if (doInherit) {
64 fFlags |= kInheritFromRootTransform_Flag;
65 } else {
66 fFlags &= ~kInheritFromRootTransform_Flag;
67 }
68 }
69
setMatrix(const SkMatrix & matrix)70 void SkLayer::setMatrix(const SkMatrix& matrix) {
71 fMatrix = matrix;
72 }
73
setChildrenMatrix(const SkMatrix & matrix)74 void SkLayer::setChildrenMatrix(const SkMatrix& matrix) {
75 fChildrenMatrix = matrix;
76 }
77
78 ///////////////////////////////////////////////////////////////////////////////
79
countChildren() const80 int SkLayer::countChildren() const {
81 return m_children.count();
82 }
83
getChild(int index) const84 SkLayer* 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
addChild(SkLayer * child)92 SkLayer* 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
detachFromParent()103 void 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
removeChildren()113 void 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
getRootLayer() const124 SkLayer* 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
getLocalTransform(SkMatrix * matrix) const134 void 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
localToGlobal(SkMatrix * matrix) const144 void 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
onDraw(SkCanvas *,SkScalar opacity)165 void SkLayer::onDraw(SkCanvas*, SkScalar opacity) {
166 // SkDebugf("----- no onDraw for %p\n", this);
167 }
168
169 #include "SkString.h"
170
draw(SkCanvas * canvas,SkScalar opacity)171 void 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