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