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 {
getMSecs() const25 virtual SkMSec getMSecs() const {
26 return SkEvent::GetMSecsSinceStartup();
27 }
28 } gDefaultTimeline;
29
SkAnimateMaker(SkAnimator * animator,SkCanvas * canvas,SkPaint * paint)30 SkAnimateMaker::SkAnimateMaker(SkAnimator* animator, SkCanvas* canvas, SkPaint* paint)
31 : fActiveEvent(nullptr), fAdjustedStart(0), fCanvas(canvas), fEnableTime(0),
32 fHostEventSinkID(0), fMinimumInterval((SkMSec) -1), fPaint(paint), fParentMaker(nullptr),
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
~SkAnimateMaker()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
appendActive(SkActive * active)60 void SkAnimateMaker::appendActive(SkActive* active) {
61 fDisplayList.append(active);
62 }
63
clearExtraPropertyCallBack(SkDisplayTypes type)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 = nullptr;
70 extra->fExtraStorage = nullptr;
71 break;
72 }
73 }
74 }
75
computeID(SkDisplayable * displayable,SkDisplayable * parent,SkString * newID)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
createInstance(const char name[],size_t len)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 nullptr;
88 }
89
90 // differs from SkAnimator::decodeStream in that it does not reset error state
decodeStream(SkStream * stream)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
decodeURI(const char uri[])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 std::unique_ptr<SkStream> stream = SkStream::MakeFromFile(uri);
103 if (stream) {
104 bool success = decodeStream(stream.get());
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" {
compare_disp(const void * a,const void * b)118 int compare_disp(const void* a, const void* b) {
119 return *(const SkDisplayable**)a - *(const SkDisplayable**)b;
120 }
121 }
122 #endif
123
delayEnable(SkApply * apply,SkMSec time)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
deleteMembers()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
doDelayedEvent()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
doEvent(const SkEvent & event)175 bool SkAnimateMaker::doEvent(const SkEvent& event) {
176 return (!fInMovie || fLoaded) && fAnimator->doEvent(event);
177 }
178
179 #ifdef SK_DUMP_ENABLED
dump(const char * match)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)) != nullptr) {
185 if (strcmp(match,name) == 0)
186 result->dump(this);
187 }
188 }
189 #endif
190
dynamicProperty(SkString & nameStr,SkDisplayable ** displayablePtr)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
getAppTime() const206 SkMSec SkAnimateMaker::getAppTime() const {
207 return fTimeline->getMSecs();
208 }
209
210 #ifdef SK_DEBUG
getRoot()211 SkAnimator* SkAnimateMaker::getRoot()
212 {
213 SkAnimateMaker* maker = this;
214 while (maker->fParentMaker)
215 maker = maker->fParentMaker;
216 return maker == this ? nullptr : maker->fAnimator;
217 }
218 #endif
219
helperAdd(SkDisplayable * trackMe)220 void SkAnimateMaker::helperAdd(SkDisplayable* trackMe) {
221 SkASSERT(fHelpers.find(trackMe) < 0);
222 *fHelpers.append() = trackMe;
223 }
224
helperRemove(SkDisplayable * alreadyTracked)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, nullptr);
239 movieMaker->fEvents.removeEvent(SkDisplayEvent::kOnload, nullptr);
240 movieMaker->loadMovies();
241 }
242 }
243 #endif
244
notifyInval()245 void SkAnimateMaker::notifyInval() {
246 if (fHostEventSinkID)
247 fAnimator->onEventPost(new SkEvent(SK_EventType_Inval), fHostEventSinkID);
248 }
249
notifyInvalTime(SkMSec time)250 void SkAnimateMaker::notifyInvalTime(SkMSec time) {
251 if (fHostEventSinkID)
252 fAnimator->onEventPostTime(new SkEvent(SK_EventType_Inval), fHostEventSinkID, time);
253 }
254
postOnEnd(SkAnimateBase * animate,SkMSec end)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
reset()264 void SkAnimateMaker::reset() {
265 deleteMembers();
266 fChildren.reset();
267 fHelpers.reset();
268 fIDs.reset();
269 fEvents.reset();
270 fDisplayList.hardReset();
271 }
272
removeActive(SkActive * active)273 void SkAnimateMaker::removeActive(SkActive* active) {
274 if (active == nullptr)
275 return;
276 fDisplayList.remove(active);
277 }
278
resolveID(SkDisplayable * displayable,SkDisplayable * original)279 bool SkAnimateMaker::resolveID(SkDisplayable* displayable, SkDisplayable* original) {
280 SkString newID;
281 bool success = computeID(original, nullptr, &newID);
282 if (success)
283 setID(displayable, newID);
284 return success;
285 }
286
setErrorString()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
setEnableTime(SkMSec appTime,SkMSec expectedTime)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
setExtraPropertyCallBack(SkDisplayTypes type,SkScriptEngine::_propertyCallBack callBack,void * userStorage)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
setID(SkDisplayable * displayable,const SkString & newID)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
setScriptError(const SkScriptEngine & engine)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
GetStep(const char * token,size_t len,void * stepPtr,SkScriptValue * value)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 }
373