|
1 |
|
2 /* |
|
3 * Copyright 2006 The Android Open Source Project |
|
4 * |
|
5 * Use of this source code is governed by a BSD-style license that can be |
|
6 * found in the LICENSE file. |
|
7 */ |
|
8 |
|
9 |
|
10 #include "SkAnimateMaker.h" |
|
11 #include "SkAnimator.h" |
|
12 #include "SkAnimatorScript.h" |
|
13 #include "SkDisplayable.h" |
|
14 #include "SkDisplayApply.h" |
|
15 #include "SkDisplayList.h" |
|
16 #include "SkDisplayMovie.h" |
|
17 #include "SkDisplayType.h" |
|
18 #include "SkExtras.h" |
|
19 #include "SkMemberInfo.h" |
|
20 #include "SkStream.h" |
|
21 #include "SkSystemEventTypes.h" |
|
22 #include "SkTime.h" |
|
23 |
|
24 class DefaultTimeline : public SkAnimator::Timeline { |
|
25 virtual SkMSec getMSecs() const { |
|
26 return SkTime::GetMSecs(); |
|
27 } |
|
28 } gDefaultTimeline; |
|
29 |
|
30 SkAnimateMaker::SkAnimateMaker(SkAnimator* animator, SkCanvas* canvas, SkPaint* paint) |
|
31 : fActiveEvent(NULL), fAdjustedStart(0), fCanvas(canvas), fEnableTime(0), |
|
32 fHostEventSinkID(0), fMinimumInterval((SkMSec) -1), fPaint(paint), fParentMaker(NULL), |
|
33 fTimeline(&gDefaultTimeline), fInInclude(false), fInMovie(false), |
|
34 fFirstScriptError(false), fLoaded(false), fIDs(256), fAnimator(animator) |
|
35 { |
|
36 fScreenplay.time = 0; |
|
37 #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING |
|
38 fDebugTimeBase = (SkMSec) -1; |
|
39 #endif |
|
40 #ifdef SK_DUMP_ENABLED |
|
41 fDumpEvents = fDumpGConditions = fDumpPosts = false; |
|
42 #endif |
|
43 } |
|
44 |
|
45 SkAnimateMaker::~SkAnimateMaker() { |
|
46 deleteMembers(); |
|
47 } |
|
48 |
|
49 #if 0 |
|
50 SkMSec SkAnimateMaker::adjustDelay(SkMSec expectedBase, SkMSec delay) { |
|
51 SkMSec appTime = (*fTimeCallBack)(); |
|
52 if (appTime) |
|
53 delay -= appTime - expectedBase; |
|
54 if (delay < 0) |
|
55 delay = 0; |
|
56 return delay; |
|
57 } |
|
58 #endif |
|
59 |
|
60 void SkAnimateMaker::appendActive(SkActive* active) { |
|
61 fDisplayList.append(active); |
|
62 } |
|
63 |
|
64 void SkAnimateMaker::clearExtraPropertyCallBack(SkDisplayTypes type) { |
|
65 SkExtras** end = fExtras.end(); |
|
66 for (SkExtras** extraPtr = fExtras.begin(); extraPtr < end; extraPtr++) { |
|
67 SkExtras* extra = *extraPtr; |
|
68 if (extra->definesType(type)) { |
|
69 extra->fExtraCallBack = NULL; |
|
70 extra->fExtraStorage = NULL; |
|
71 break; |
|
72 } |
|
73 } |
|
74 } |
|
75 |
|
76 bool SkAnimateMaker::computeID(SkDisplayable* displayable, SkDisplayable* parent, SkString* newID) { |
|
77 const char* script; |
|
78 if (findKey(displayable, &script) == false) |
|
79 return true; |
|
80 return SkAnimatorScript::EvaluateString(*this, displayable, parent, script, newID); |
|
81 } |
|
82 |
|
83 SkDisplayable* SkAnimateMaker::createInstance(const char name[], size_t len) { |
|
84 SkDisplayTypes type = SkDisplayType::GetType(this, name, len ); |
|
85 if ((int)type >= 0) |
|
86 return SkDisplayType::CreateInstance(this, type); |
|
87 return NULL; |
|
88 } |
|
89 |
|
90 // differs from SkAnimator::decodeStream in that it does not reset error state |
|
91 bool SkAnimateMaker::decodeStream(SkStream* stream) |
|
92 { |
|
93 SkDisplayXMLParser parser(*this); |
|
94 return parser.parse(*stream); |
|
95 } |
|
96 |
|
97 // differs from SkAnimator::decodeURI in that it does not set URI base |
|
98 bool SkAnimateMaker::decodeURI(const char uri[]) { |
|
99 // SkDebugf("animator decode %s\n", uri); |
|
100 |
|
101 // SkStream* stream = SkStream::GetURIStream(fPrefix.c_str(), uri); |
|
102 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(uri)); |
|
103 if (stream.get()) { |
|
104 bool success = decodeStream(stream); |
|
105 if (hasError() && fError.hasNoun() == false) |
|
106 fError.setNoun(uri); |
|
107 return success; |
|
108 } else { |
|
109 return false; |
|
110 } |
|
111 } |
|
112 |
|
113 #if defined SK_DEBUG && 0 |
|
114 //used for the if'd out section of deleteMembers |
|
115 #include "SkTSearch.h" |
|
116 |
|
117 extern "C" { |
|
118 int compare_disp(const void* a, const void* b) { |
|
119 return *(const SkDisplayable**)a - *(const SkDisplayable**)b; |
|
120 } |
|
121 } |
|
122 #endif |
|
123 |
|
124 void SkAnimateMaker::delayEnable(SkApply* apply, SkMSec time) { |
|
125 int index = fDelayed.find(apply); |
|
126 if (index < 0) { |
|
127 *fDelayed.append() = apply; |
|
128 } |
|
129 |
|
130 (new SkEvent(SK_EventType_Delay, fAnimator->getSinkID()))->postTime(time); |
|
131 } |
|
132 |
|
133 void SkAnimateMaker::deleteMembers() { |
|
134 int index; |
|
135 #if defined SK_DEBUG && 0 |
|
136 //this code checks to see if helpers are among the children, but it is not complete - |
|
137 //it should check the children of the children |
|
138 int result; |
|
139 SkTDArray<SkDisplayable*> children(fChildren.begin(), fChildren.count()); |
|
140 SkQSort(children.begin(), children.count(), sizeof(SkDisplayable*),compare_disp); |
|
141 for (index = 0; index < fHelpers.count(); index++) { |
|
142 SkDisplayable* helper = fHelpers[index]; |
|
143 result = SkTSearch(children.begin(), children.count(), helper, sizeof(SkDisplayable*)); |
|
144 SkASSERT(result < 0); |
|
145 } |
|
146 #endif |
|
147 for (index = 0; index < fChildren.count(); index++) { |
|
148 SkDisplayable* child = fChildren[index]; |
|
149 delete child; |
|
150 } |
|
151 for (index = 0; index < fHelpers.count(); index++) { |
|
152 SkDisplayable* helper = fHelpers[index]; |
|
153 delete helper; |
|
154 } |
|
155 for (index = 0; index < fExtras.count(); index++) { |
|
156 SkExtras* extras = fExtras[index]; |
|
157 delete extras; |
|
158 } |
|
159 } |
|
160 |
|
161 void SkAnimateMaker::doDelayedEvent() { |
|
162 fEnableTime = getAppTime(); |
|
163 for (int index = 0; index < fDelayed.count(); ) { |
|
164 SkDisplayable* child = fDelayed[index]; |
|
165 SkASSERT(child->isApply()); |
|
166 SkApply* apply = (SkApply*) child; |
|
167 apply->interpolate(*this, fEnableTime); |
|
168 if (apply->hasDelayedAnimator()) |
|
169 index++; |
|
170 else |
|
171 fDelayed.remove(index); |
|
172 } |
|
173 } |
|
174 |
|
175 bool SkAnimateMaker::doEvent(const SkEvent& event) { |
|
176 return (!fInMovie || fLoaded) && fAnimator->doEvent(event); |
|
177 } |
|
178 |
|
179 #ifdef SK_DUMP_ENABLED |
|
180 void SkAnimateMaker::dump(const char* match) { |
|
181 SkTDict<SkDisplayable*>::Iter iter(fIDs); |
|
182 const char* name; |
|
183 SkDisplayable* result; |
|
184 while ((name = iter.next(&result)) != NULL) { |
|
185 if (strcmp(match,name) == 0) |
|
186 result->dump(this); |
|
187 } |
|
188 } |
|
189 #endif |
|
190 |
|
191 int SkAnimateMaker::dynamicProperty(SkString& nameStr, SkDisplayable** displayablePtr ) { |
|
192 const char* name = nameStr.c_str(); |
|
193 const char* dot = strchr(name, '.'); |
|
194 SkASSERT(dot); |
|
195 SkDisplayable* displayable; |
|
196 if (find(name, dot - name, &displayable) == false) { |
|
197 SkASSERT(0); |
|
198 return 0; |
|
199 } |
|
200 const char* fieldName = dot + 1; |
|
201 const SkMemberInfo* memberInfo = displayable->getMember(fieldName); |
|
202 *displayablePtr = displayable; |
|
203 return (int) memberInfo->fOffset; |
|
204 } |
|
205 |
|
206 SkMSec SkAnimateMaker::getAppTime() const { |
|
207 return fTimeline->getMSecs(); |
|
208 } |
|
209 |
|
210 #ifdef SK_DEBUG |
|
211 SkAnimator* SkAnimateMaker::getRoot() |
|
212 { |
|
213 SkAnimateMaker* maker = this; |
|
214 while (maker->fParentMaker) |
|
215 maker = maker->fParentMaker; |
|
216 return maker == this ? NULL : maker->fAnimator; |
|
217 } |
|
218 #endif |
|
219 |
|
220 void SkAnimateMaker::helperAdd(SkDisplayable* trackMe) { |
|
221 SkASSERT(fHelpers.find(trackMe) < 0); |
|
222 *fHelpers.append() = trackMe; |
|
223 } |
|
224 |
|
225 void SkAnimateMaker::helperRemove(SkDisplayable* alreadyTracked) { |
|
226 int helperIndex = fHelpers.find(alreadyTracked); |
|
227 if (helperIndex >= 0) |
|
228 fHelpers.remove(helperIndex); |
|
229 } |
|
230 |
|
231 #if 0 |
|
232 void SkAnimateMaker::loadMovies() { |
|
233 for (SkDisplayable** dispPtr = fMovies.begin(); dispPtr < fMovies.end(); dispPtr++) { |
|
234 SkDisplayable* displayable = *dispPtr; |
|
235 SkASSERT(displayable->getType() == SkType_Movie); |
|
236 SkDisplayMovie* movie = (SkDisplayMovie*) displayable; |
|
237 SkAnimateMaker* movieMaker = movie->fMovie.fMaker; |
|
238 movieMaker->fEvents.doEvent(*movieMaker, SkDisplayEvent::kOnload, NULL); |
|
239 movieMaker->fEvents.removeEvent(SkDisplayEvent::kOnload, NULL); |
|
240 movieMaker->loadMovies(); |
|
241 } |
|
242 } |
|
243 #endif |
|
244 |
|
245 void SkAnimateMaker::notifyInval() { |
|
246 if (fHostEventSinkID) |
|
247 fAnimator->onEventPost(new SkEvent(SK_EventType_Inval), fHostEventSinkID); |
|
248 } |
|
249 |
|
250 void SkAnimateMaker::notifyInvalTime(SkMSec time) { |
|
251 if (fHostEventSinkID) |
|
252 fAnimator->onEventPostTime(new SkEvent(SK_EventType_Inval), fHostEventSinkID, time); |
|
253 } |
|
254 |
|
255 void SkAnimateMaker::postOnEnd(SkAnimateBase* animate, SkMSec end) { |
|
256 SkEvent evt; |
|
257 evt.setS32("time", animate->getStart() + end); |
|
258 evt.setPtr("anim", animate); |
|
259 evt.setType(SK_EventType_OnEnd); |
|
260 SkEventSinkID sinkID = fAnimator->getSinkID(); |
|
261 fAnimator->onEventPost(new SkEvent(evt), sinkID); |
|
262 } |
|
263 |
|
264 void SkAnimateMaker::reset() { |
|
265 deleteMembers(); |
|
266 fChildren.reset(); |
|
267 fHelpers.reset(); |
|
268 fIDs.reset(); |
|
269 fEvents.reset(); |
|
270 fDisplayList.hardReset(); |
|
271 } |
|
272 |
|
273 void SkAnimateMaker::removeActive(SkActive* active) { |
|
274 if (active == NULL) |
|
275 return; |
|
276 fDisplayList.remove(active); |
|
277 } |
|
278 |
|
279 bool SkAnimateMaker::resolveID(SkDisplayable* displayable, SkDisplayable* original) { |
|
280 SkString newID; |
|
281 bool success = computeID(original, NULL, &newID); |
|
282 if (success) |
|
283 setID(displayable, newID); |
|
284 return success; |
|
285 } |
|
286 |
|
287 void SkAnimateMaker::setErrorString() { |
|
288 fErrorString.reset(); |
|
289 if (fError.hasError()) { |
|
290 SkString err; |
|
291 if (fFileName.size() > 0) |
|
292 fErrorString.set(fFileName.c_str()); |
|
293 else |
|
294 fErrorString.set("screenplay error"); |
|
295 int line = fError.getLineNumber(); |
|
296 if (line >= 0) { |
|
297 fErrorString.append(", "); |
|
298 fErrorString.append("line "); |
|
299 fErrorString.appendS32(line); |
|
300 } |
|
301 fErrorString.append(": "); |
|
302 fError.getErrorString(&err); |
|
303 fErrorString.append(err); |
|
304 #if defined SK_DEBUG |
|
305 SkDebugf("%s\n", fErrorString.c_str()); |
|
306 #endif |
|
307 } |
|
308 } |
|
309 |
|
310 void SkAnimateMaker::setEnableTime(SkMSec appTime, SkMSec expectedTime) { |
|
311 #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING |
|
312 SkString debugOut; |
|
313 SkMSec time = getAppTime(); |
|
314 debugOut.appendS32(time - fDebugTimeBase); |
|
315 debugOut.append(" set enable old enable="); |
|
316 debugOut.appendS32(fEnableTime - fDebugTimeBase); |
|
317 debugOut.append(" old adjust="); |
|
318 debugOut.appendS32(fAdjustedStart); |
|
319 debugOut.append(" new enable="); |
|
320 debugOut.appendS32(expectedTime - fDebugTimeBase); |
|
321 debugOut.append(" new adjust="); |
|
322 debugOut.appendS32(appTime - expectedTime); |
|
323 SkDebugf("%s\n", debugOut.c_str()); |
|
324 #endif |
|
325 fAdjustedStart = appTime - expectedTime; |
|
326 fEnableTime = expectedTime; |
|
327 SkDisplayable** firstMovie = fMovies.begin(); |
|
328 SkDisplayable** endMovie = fMovies.end(); |
|
329 for (SkDisplayable** ptr = firstMovie; ptr < endMovie; ptr++) { |
|
330 SkDisplayMovie* movie = (SkDisplayMovie*) *ptr; |
|
331 movie->fMovie.fMaker->setEnableTime(appTime, expectedTime); |
|
332 } |
|
333 } |
|
334 |
|
335 void SkAnimateMaker::setExtraPropertyCallBack(SkDisplayTypes type, |
|
336 SkScriptEngine::_propertyCallBack callBack, void* userStorage) { |
|
337 SkExtras** end = fExtras.end(); |
|
338 for (SkExtras** extraPtr = fExtras.begin(); extraPtr < end; extraPtr++) { |
|
339 SkExtras* extra = *extraPtr; |
|
340 if (extra->definesType(type)) { |
|
341 extra->fExtraCallBack = callBack; |
|
342 extra->fExtraStorage = userStorage; |
|
343 break; |
|
344 } |
|
345 } |
|
346 } |
|
347 |
|
348 void SkAnimateMaker::setID(SkDisplayable* displayable, const SkString& newID) { |
|
349 fIDs.set(newID.c_str(), displayable); |
|
350 #ifdef SK_DEBUG |
|
351 displayable->_id.set(newID); |
|
352 displayable->id = displayable->_id.c_str(); |
|
353 #endif |
|
354 } |
|
355 |
|
356 void SkAnimateMaker::setScriptError(const SkScriptEngine& engine) { |
|
357 SkString errorString; |
|
358 #ifdef SK_DEBUG |
|
359 engine.getErrorString(&errorString); |
|
360 #endif |
|
361 setErrorNoun(errorString); |
|
362 setErrorCode(SkDisplayXMLParserError::kErrorInScript); |
|
363 } |
|
364 |
|
365 bool SkAnimateMaker::GetStep(const char* token, size_t len, void* stepPtr, SkScriptValue* value) { |
|
366 if (SK_LITERAL_STR_EQUAL("step", token, len)) { |
|
367 value->fOperand.fS32 = *(int32_t*) stepPtr; |
|
368 value->fType = SkType_Int; |
|
369 return true; |
|
370 } |
|
371 return false; |
|
372 } |