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