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 } 373