blob: aa53564e04fa5aafaeb312ca306bc22d84345cfa [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* libs/graphics/animator/SkDrawGroup.cpp
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include "SkDrawGroup.h"
19#include "SkAnimateMaker.h"
20#include "SkAnimatorScript.h"
21#include "SkCanvas.h"
22#include "SkDisplayApply.h"
23#include "SkPaint.h"
24#ifdef SK_DEBUG
25#include "SkDisplayList.h"
26#endif
27
28#if SK_USE_CONDENSED_INFO == 0
29
30const SkMemberInfo SkGroup::fInfo[] = {
31 SK_MEMBER(condition, String),
32 SK_MEMBER(enableCondition, String)
33};
34
35#endif
36
37DEFINE_GET_MEMBER(SkGroup);
38
39SkGroup::SkGroup() : fParentList(NULL), fOriginal(NULL) {
40}
41
42SkGroup::~SkGroup() {
43 if (fOriginal) // has been copied
44 return;
45 int index = 0;
46 int max = fCopies.count() << 5;
47 for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
48 if (index >= max || markedForDelete(index))
49 delete *ptr;
50// else {
51// SkApply* apply = (SkApply*) *ptr;
52// SkASSERT(apply->isApply());
53// SkASSERT(apply->getScope());
54// delete apply->getScope();
55// }
56 index++;
57 }
58}
59
60bool SkGroup::add(SkAnimateMaker& , SkDisplayable* child) {
61 SkASSERT(child);
62// SkASSERT(child->isDrawable());
63 *fChildren.append() = (SkDrawable*) child;
64 if (child->isGroup()) {
65 SkGroup* groupie = (SkGroup*) child;
66 SkASSERT(groupie->fParentList == NULL);
67 groupie->fParentList = &fChildren;
68 }
69 return true;
70}
71
72bool SkGroup::contains(SkDisplayable* match) {
73 for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
74 SkDrawable* drawable = *ptr;
75 if (drawable == match || drawable->contains(match))
76 return true;
77 }
78 return false;
79}
80
81SkGroup* SkGroup::copy() {
82 SkGroup* result = new SkGroup();
83 result->fOriginal = this;
84 result->fChildren = fChildren;
85 return result;
86}
87
88SkBool SkGroup::copySet(int index) {
89 return (fCopies[index >> 5] & 1 << (index & 0x1f)) != 0;
90}
91
92SkDisplayable* SkGroup::deepCopy(SkAnimateMaker* maker) {
93 SkDisplayable* copy = INHERITED::deepCopy(maker);
94 for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
95 SkDisplayable* displayable = (SkDisplayable*)*ptr;
96 SkDisplayable* deeperCopy = displayable->deepCopy(maker);
97 ((SkGroup*)copy)->add(*maker, deeperCopy);
98 }
99 return copy;
100}
101
102bool SkGroup::doEvent(SkDisplayEvent::Kind kind, SkEventState* state) {
103 bool handled = false;
104 for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
105 SkDrawable* drawable = *ptr;
106 if (drawable->isDrawable() == false)
107 continue;
108 handled |= drawable->doEvent(kind, state);
109 }
110 return handled;
111}
112
113bool SkGroup::draw(SkAnimateMaker& maker) {
114 bool conditionTrue = ifCondition(maker, this, condition);
115 bool result = false;
116 for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
117 SkDrawable* drawable = *ptr;
118 if (drawable->isDrawable() == false)
119 continue;
120 if (conditionTrue == false) {
121 if (drawable->isApply())
122 ((SkApply*) drawable)->disable();
123 continue;
124 }
125 maker.validate();
126 result |= drawable->draw(maker);
127 maker.validate();
128 }
129 return result;
130}
131
132#ifdef SK_DUMP_ENABLED
133void SkGroup::dump(SkAnimateMaker* maker) {
134 dumpBase(maker);
135 if (condition.size() > 0)
136 SkDebugf("condition=\"%s\" ", condition.c_str());
137 if (enableCondition.size() > 0)
138 SkDebugf("enableCondition=\"%s\" ", enableCondition.c_str());
139 dumpDrawables(maker);
140}
141
142void SkGroup::dumpDrawables(SkAnimateMaker* maker) {
143 SkDisplayList::fIndent += 4;
144 int save = SkDisplayList::fDumpIndex;
145 SkDisplayList::fDumpIndex = 0;
146 bool closedYet = false;
147 for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
148 if (closedYet == false) {
149 closedYet = true;
150 SkDebugf(">\n");
151 }
152 SkDrawable* drawable = *ptr;
153 drawable->dump(maker);
154 SkDisplayList::fDumpIndex++;
155 }
156 SkDisplayList::fIndent -= 4;
157 SkDisplayList::fDumpIndex = save;
158 if (closedYet) //we had children, now it's time to close the group
159 dumpEnd(maker);
160 else //no children
161 SkDebugf("/>\n");
162}
163
164void SkGroup::dumpEvents() {
165 for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
166 SkDrawable* drawable = *ptr;
167 drawable->dumpEvents();
168 }
169}
170#endif
171
172bool SkGroup::enable(SkAnimateMaker& maker ) {
173 reset();
174 for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
175 SkDrawable* drawable = *ptr;
176 if (ifCondition(maker, drawable, enableCondition) == false)
177 continue;
178 drawable->enable(maker);
179 }
180 return true; // skip add; already added so that scope is findable by children
181}
182
183int SkGroup::findGroup(SkDrawable* match, SkTDDrawableArray** list,
184 SkGroup** parent, SkGroup** found, SkTDDrawableArray** grandList) {
185 *list = &fChildren;
186 for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
187 SkDrawable* drawable = *ptr;
188 if (drawable->isGroup()) {
189 SkGroup* childGroup = (SkGroup*) drawable;
190 if (childGroup->fOriginal == match)
191 goto foundMatch;
192 }
193 if (drawable == match) {
194foundMatch:
195 *parent = this;
196 return (int) (ptr - fChildren.begin());
197 }
198 }
199 *grandList = &fChildren;
200 return SkDisplayList::SearchForMatch(match, list, parent, found, grandList);
201}
202
203bool SkGroup::hasEnable() const {
204 return true;
205}
206
207bool SkGroup::ifCondition(SkAnimateMaker& maker, SkDrawable* drawable,
208 SkString& conditionString) {
209 if (conditionString.size() == 0)
210 return true;
211 int32_t result;
212 bool success = SkAnimatorScript::EvaluateInt(maker, this, conditionString.c_str(), &result);
213#ifdef SK_DUMP_ENABLED
214 if (maker.fDumpGConditions) {
215 SkDebugf("group: ");
216 dumpBase(&maker);
217 SkDebugf("condition=%s ", conditionString.c_str());
218 if (success == false)
219 SkDebugf("(script failed)\n");
220 else
221 SkDebugf("success=%s\n", result != 0 ? "true" : "false");
222 }
223#endif
224 return success && result != 0;
225}
226
227void SkGroup::initialize() {
228 for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
229 SkDrawable* drawable = *ptr;
230 if (drawable->isDrawable() == false)
231 continue;
232 drawable->initialize();
233 }
234}
235
236void SkGroup::markCopyClear(int index) {
237 if (index < 0)
238 index = fChildren.count();
239 fCopies[index >> 5] &= ~(1 << (index & 0x1f));
240}
241
242void SkGroup::markCopySet(int index) {
243 if (index < 0)
244 index = fChildren.count();
245 fCopies[index >> 5] |= 1 << (index & 0x1f);
246}
247
248void SkGroup::markCopySize(int index) {
249 if (index < 0)
250 index = fChildren.count() + 1;
251 int oldLongs = fCopies.count();
252 int newLongs = (index >> 5) + 1;
253 if (oldLongs < newLongs) {
254 fCopies.setCount(newLongs);
255 memset(&fCopies[oldLongs], 0, (newLongs - oldLongs) << 2);
256 }
257}
258
259void SkGroup::reset() {
260 if (fOriginal) // has been copied
261 return;
262 int index = 0;
263 int max = fCopies.count() << 5;
264 for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
265 if (index >= max || copySet(index) == false)
266 continue;
267 SkApply* apply = (SkApply*) *ptr;
268 SkASSERT(apply->isApply());
269 SkASSERT(apply->getScope());
270 *ptr = apply->getScope();
271 markCopyClear(index);
272 index++;
273 }
274}
275
276bool SkGroup::resolveIDs(SkAnimateMaker& maker, SkDisplayable* orig, SkApply* apply) {
277 SkGroup* original = (SkGroup*) orig;
278 SkTDDrawableArray& originalChildren = original->fChildren;
279 SkDrawable** originalPtr = originalChildren.begin();
280 SkDrawable** ptr = fChildren.begin();
281 SkDrawable** end = fChildren.end();
282 SkDrawable** origChild = ((SkGroup*) orig)->fChildren.begin();
283 while (ptr < end) {
284 SkDrawable* drawable = *ptr++;
285 maker.resolveID(drawable, *origChild++);
286 if (drawable->resolveIDs(maker, *originalPtr++, apply) == true)
287 return true; // failed
288 }
289 return false;
290}
291
292void SkGroup::setSteps(int steps) {
293 for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
294 SkDrawable* drawable = *ptr;
295 if (drawable->isDrawable() == false)
296 continue;
297 drawable->setSteps(steps);
298 }
299}
300
301#ifdef SK_DEBUG
302void SkGroup::validate() {
303 for (SkDrawable** ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) {
304 SkDrawable* drawable = *ptr;
305 drawable->validate();
306 }
307}
308#endif
309
310#if SK_USE_CONDENSED_INFO == 0
311
312const SkMemberInfo SkSave::fInfo[] = {
313 SK_MEMBER_INHERITED
314};
315
316#endif
317
318DEFINE_GET_MEMBER(SkSave);
319
320bool SkSave::draw(SkAnimateMaker& maker) {
321 maker.fCanvas->save();
322 SkPaint* save = maker.fPaint;
323 SkPaint local = SkPaint(*maker.fPaint);
324 maker.fPaint = &local;
325 bool result = INHERITED::draw(maker);
326 maker.fPaint = save;
327 maker.fCanvas->restore();
328 return result;
329}
330
331