blob: ce4ddfdec7102c032c2784e110afc43485edd990 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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
reed@android.com8a1c16f2008-12-17 15:59:43 +00009
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
24class DefaultTimeline : public SkAnimator::Timeline {
25 virtual SkMSec getMSecs() const {
26 return SkTime::GetMSecs();
27 }
28} gDefaultTimeline;
29
30SkAnimateMaker::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
45SkAnimateMaker::~SkAnimateMaker() {
46 deleteMembers();
47}
48
49#if 0
50SkMSec 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
60void SkAnimateMaker::appendActive(SkActive* active) {
61 fDisplayList.append(active);
62}
63
64void 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
76bool 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
83SkDisplayable* 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
91bool 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
98bool SkAnimateMaker::decodeURI(const char uri[]) {
99// SkDebugf("animator decode %s\n", uri);
100
101// SkStream* stream = SkStream::GetURIStream(fPrefix.c_str(), uri);
102 SkStream* stream = new SkFILEStream(uri);
103
104 SkAutoTDelete<SkStream> autoDel(stream);
105 bool success = decodeStream(stream);
106 if (hasError() && fError.hasNoun() == false)
107 fError.setNoun(uri);
108 return success;
109}
110
111#if defined SK_DEBUG && 0
112//used for the if'd out section of deleteMembers
113#include "SkTSearch.h"
114
115extern "C" {
116 int compare_disp(const void* a, const void* b) {
117 return *(const SkDisplayable**)a - *(const SkDisplayable**)b;
118 }
119}
120#endif
121
122void SkAnimateMaker::delayEnable(SkApply* apply, SkMSec time) {
123 int index = fDelayed.find(apply);
124 if (index < 0)
125 *fDelayed.append() = apply;
126 (new SkEvent(SK_EventType_Delay))->postTime(fAnimator->getSinkID(), time);
127}
128
129void SkAnimateMaker::deleteMembers() {
130 int index;
131#if defined SK_DEBUG && 0
132 //this code checks to see if helpers are among the children, but it is not complete -
133 //it should check the children of the children
134 int result;
135 SkTDArray<SkDisplayable*> children(fChildren.begin(), fChildren.count());
136 SkQSort(children.begin(), children.count(), sizeof(SkDisplayable*),compare_disp);
137 for (index = 0; index < fHelpers.count(); index++) {
138 SkDisplayable* helper = fHelpers[index];
139 result = SkTSearch(children.begin(), children.count(), helper, sizeof(SkDisplayable*));
140 SkASSERT(result < 0);
141 }
142#endif
143 for (index = 0; index < fChildren.count(); index++) {
144 SkDisplayable* child = fChildren[index];
145 delete child;
146 }
147 for (index = 0; index < fHelpers.count(); index++) {
148 SkDisplayable* helper = fHelpers[index];
149 delete helper;
150 }
151 for (index = 0; index < fExtras.count(); index++) {
152 SkExtras* extras = fExtras[index];
153 delete extras;
154 }
155}
156
157void SkAnimateMaker::doDelayedEvent() {
158 fEnableTime = getAppTime();
159 for (int index = 0; index < fDelayed.count(); ) {
160 SkDisplayable* child = fDelayed[index];
161 SkASSERT(child->isApply());
162 SkApply* apply = (SkApply*) child;
163 apply->interpolate(*this, fEnableTime);
164 if (apply->hasDelayedAnimator())
165 index++;
166 else
167 fDelayed.remove(index);
168 }
169}
170
171bool SkAnimateMaker::doEvent(const SkEvent& event) {
172 return (!fInMovie || fLoaded) && fAnimator->doEvent(event);
173}
174
175#ifdef SK_DUMP_ENABLED
176void SkAnimateMaker::dump(const char* match) {
177 SkTDict<SkDisplayable*>::Iter iter(fIDs);
178 const char* name;
179 SkDisplayable* result;
180 while ((name = iter.next(&result)) != NULL) {
181 if (strcmp(match,name) == 0)
182 result->dump(this);
183 }
184}
185#endif
186
187int SkAnimateMaker::dynamicProperty(SkString& nameStr, SkDisplayable** displayablePtr ) {
188 const char* name = nameStr.c_str();
189 const char* dot = strchr(name, '.');
190 SkASSERT(dot);
191 SkDisplayable* displayable;
192 if (find(name, dot - name, &displayable) == false) {
193 SkASSERT(0);
194 return 0;
195 }
196 const char* fieldName = dot + 1;
197 const SkMemberInfo* memberInfo = displayable->getMember(fieldName);
198 *displayablePtr = displayable;
199 return (int) memberInfo->fOffset;
200}
201
202SkMSec SkAnimateMaker::getAppTime() const {
203 return fTimeline->getMSecs();
204}
205
206#ifdef SK_DEBUG
207SkAnimator* SkAnimateMaker::getRoot()
208{
209 SkAnimateMaker* maker = this;
210 while (maker->fParentMaker)
211 maker = maker->fParentMaker;
212 return maker == this ? NULL : maker->fAnimator;
213}
214#endif
215
216void SkAnimateMaker::helperAdd(SkDisplayable* trackMe) {
217 SkASSERT(fHelpers.find(trackMe) < 0);
218 *fHelpers.append() = trackMe;
219}
220
221void SkAnimateMaker::helperRemove(SkDisplayable* alreadyTracked) {
222 int helperIndex = fHelpers.find(alreadyTracked);
223 if (helperIndex >= 0)
224 fHelpers.remove(helperIndex);
225}
226
227#if 0
228void SkAnimateMaker::loadMovies() {
229 for (SkDisplayable** dispPtr = fMovies.begin(); dispPtr < fMovies.end(); dispPtr++) {
230 SkDisplayable* displayable = *dispPtr;
231 SkASSERT(displayable->getType() == SkType_Movie);
232 SkDisplayMovie* movie = (SkDisplayMovie*) displayable;
233 SkAnimateMaker* movieMaker = movie->fMovie.fMaker;
234 movieMaker->fEvents.doEvent(*movieMaker, SkDisplayEvent::kOnload, NULL);
235 movieMaker->fEvents.removeEvent(SkDisplayEvent::kOnload, NULL);
236 movieMaker->loadMovies();
237 }
238}
239#endif
240
241void SkAnimateMaker::notifyInval() {
242 if (fHostEventSinkID)
243 fAnimator->onEventPost(new SkEvent(SK_EventType_Inval), fHostEventSinkID);
244}
245
246void SkAnimateMaker::notifyInvalTime(SkMSec time) {
247 if (fHostEventSinkID)
248 fAnimator->onEventPostTime(new SkEvent(SK_EventType_Inval), fHostEventSinkID, time);
249}
250
251void SkAnimateMaker::postOnEnd(SkAnimateBase* animate, SkMSec end) {
252 SkEvent evt;
253 evt.setS32("time", animate->getStart() + end);
254 evt.setPtr("anim", animate);
255 evt.setType(SK_EventType_OnEnd);
256 SkEventSinkID sinkID = fAnimator->getSinkID();
257 fAnimator->onEventPost(new SkEvent(evt), sinkID);
258}
259
260void SkAnimateMaker::reset() {
261 deleteMembers();
262 fChildren.reset();
263 fHelpers.reset();
264 fIDs.reset();
265 fEvents.reset();
266 fDisplayList.hardReset();
267}
268
269void SkAnimateMaker::removeActive(SkActive* active) {
270 if (active == NULL)
271 return;
272 fDisplayList.remove(active);
273}
274
275bool SkAnimateMaker::resolveID(SkDisplayable* displayable, SkDisplayable* original) {
276 SkString newID;
277 bool success = computeID(original, NULL, &newID);
278 if (success)
279 setID(displayable, newID);
280 return success;
281}
282
283void SkAnimateMaker::setErrorString() {
284 fErrorString.reset();
285 if (fError.hasError()) {
286 SkString err;
287 if (fFileName.size() > 0)
288 fErrorString.set(fFileName.c_str());
289 else
290 fErrorString.set("screenplay error");
291 int line = fError.getLineNumber();
292 if (line >= 0) {
293 fErrorString.append(", ");
294 fErrorString.append("line ");
295 fErrorString.appendS32(line);
296 }
297 fErrorString.append(": ");
298 fError.getErrorString(&err);
299 fErrorString.append(err);
300#if defined SK_DEBUG
301 SkDebugf("%s\n", fErrorString.c_str());
302#endif
303 }
304}
305
306void SkAnimateMaker::setEnableTime(SkMSec appTime, SkMSec expectedTime) {
307#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING
308 SkString debugOut;
309 SkMSec time = getAppTime();
310 debugOut.appendS32(time - fDebugTimeBase);
311 debugOut.append(" set enable old enable=");
312 debugOut.appendS32(fEnableTime - fDebugTimeBase);
313 debugOut.append(" old adjust=");
314 debugOut.appendS32(fAdjustedStart);
315 debugOut.append(" new enable=");
316 debugOut.appendS32(expectedTime - fDebugTimeBase);
317 debugOut.append(" new adjust=");
318 debugOut.appendS32(appTime - expectedTime);
319 SkDebugf("%s\n", debugOut.c_str());
320#endif
321 fAdjustedStart = appTime - expectedTime;
322 fEnableTime = expectedTime;
323 SkDisplayable** firstMovie = fMovies.begin();
324 SkDisplayable** endMovie = fMovies.end();
325 for (SkDisplayable** ptr = firstMovie; ptr < endMovie; ptr++) {
326 SkDisplayMovie* movie = (SkDisplayMovie*) *ptr;
327 movie->fMovie.fMaker->setEnableTime(appTime, expectedTime);
328 }
329}
330
331void SkAnimateMaker::setExtraPropertyCallBack(SkDisplayTypes type,
332 SkScriptEngine::_propertyCallBack callBack, void* userStorage) {
333 SkExtras** end = fExtras.end();
334 for (SkExtras** extraPtr = fExtras.begin(); extraPtr < end; extraPtr++) {
335 SkExtras* extra = *extraPtr;
336 if (extra->definesType(type)) {
337 extra->fExtraCallBack = callBack;
338 extra->fExtraStorage = userStorage;
339 break;
340 }
341 }
342}
343
344void SkAnimateMaker::setID(SkDisplayable* displayable, const SkString& newID) {
345 fIDs.set(newID.c_str(), displayable);
346#ifdef SK_DEBUG
347 displayable->_id.set(newID);
348 displayable->id = displayable->_id.c_str();
349#endif
350}
351
352void SkAnimateMaker::setScriptError(const SkScriptEngine& engine) {
353 SkString errorString;
354#ifdef SK_DEBUG
355 engine.getErrorString(&errorString);
356#endif
357 setErrorNoun(errorString);
358 setErrorCode(SkDisplayXMLParserError::kErrorInScript);
359}
360
361bool SkAnimateMaker::GetStep(const char* token, size_t len, void* stepPtr, SkScriptValue* value) {
362 if (SK_LITERAL_STR_EQUAL("step", token, len)) {
363 value->fOperand.fS32 = *(int32_t*) stepPtr;
364 value->fType = SkType_Int;
365 return true;
366 }
367 return false;
368}