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 "SkDisplayApply.h" 11#include "SkAnimateActive.h" 12#include "SkAnimateMaker.h" 13#include "SkAnimateSet.h" 14#include "SkAnimatorScript.h" 15#include "SkDisplayType.h" 16#include "SkDrawGroup.h" 17#include "SkParse.h" 18#include "SkScript.h" 19#include "SkSystemEventTypes.h" 20#ifdef SK_DEBUG 21#include "SkTime.h" 22#endif 23#include <ctype.h> 24 25enum SkApply_Properties { 26 SK_PROPERTY(animator), 27 SK_PROPERTY(step), 28 SK_PROPERTY(steps), 29 SK_PROPERTY(time) 30}; 31 32#if SK_USE_CONDENSED_INFO == 0 33 34// if no attibutes, enclosed displayable is both scope & target 35// only if both scope & target are specified, or if target and enclosed displayable, are scope and target different 36const SkMemberInfo SkApply::fInfo[] = { 37 SK_MEMBER_PROPERTY(animator, Animate), 38 SK_MEMBER(begin, MSec), 39 SK_MEMBER(dontDraw, Boolean), 40 SK_MEMBER(dynamicScope, String), 41 SK_MEMBER(interval, MSec), // recommended redraw interval 42 SK_MEMBER(mode, ApplyMode), 43#if 0 44 SK_MEMBER(pickup, Boolean), 45#endif 46 SK_MEMBER(restore, Boolean), 47 SK_MEMBER(scope, Drawable), // thing that scopes animation (unnamed enclosed displayable goes here) 48 SK_MEMBER_PROPERTY(step, Int), 49 SK_MEMBER_PROPERTY(steps, Int), 50 SK_MEMBER_PROPERTY(time, MSec), 51 SK_MEMBER(transition, ApplyTransition) 52}; 53 54#endif 55 56DEFINE_GET_MEMBER(SkApply); 57 58SkApply::SkApply() : begin(0), dontDraw(false), interval((SkMSec) -1), mode((Mode) -1), /*pickup(false), */ 59 restore(false), scope(NULL), steps(-1), transition((Transition) -1), fActive(NULL), /*fCurrentScope(NULL),*/ 60 fLastTime(0), fAppended(false), fContainsScope(false), fDeleteScope(false), fEmbedded(false), 61 fEnabled(false), fEnabling(false) { 62} 63 64SkApply::~SkApply() { 65 for (SkDrawable** curPtr = fScopes.begin(); curPtr < fScopes.end(); curPtr++) 66 delete *curPtr; 67 if (fDeleteScope) 68 delete scope; 69 // !!! caller must call maker.removeActive(fActive) 70 delete fActive; 71} 72 73void SkApply::activate(SkAnimateMaker& maker) { 74 if (fActive != NULL) { 75 if (fActive->fDrawIndex == 0 && fActive->fDrawMax == 0) 76 return; // if only one use, nothing more to do 77 if (restore == false) 78 return; // all share same state, regardless of instance number 79 bool save = fActive->initializeSave(); 80 fActive->fixInterpolator(save); 81 } else { 82 fActive = new SkActive(*this, maker); 83 fActive->init(); 84 maker.appendActive(fActive); 85 if (restore) { 86 fActive->initializeSave(); 87 int animators = fAnimators.count(); 88 for (int index = 0; index < animators; index++) 89 fActive->saveInterpolatorValues(index); 90 } 91 } 92} 93 94void SkApply::append(SkApply* apply) { 95 if (fActive == NULL) 96 return; 97 int oldCount = fActive->fAnimators.count(); 98 fActive->append(apply); 99 if (restore) { 100 fActive->appendSave(oldCount); 101 int newCount = fActive->fAnimators.count(); 102 for (int index = oldCount; index < newCount; index++) 103 fActive->saveInterpolatorValues(index); 104 } 105} 106 107void SkApply::applyValues(int animatorIndex, SkOperand* values, int count, 108 SkDisplayTypes valuesType, SkMSec time) 109{ 110 SkAnimateBase* animator = fActive->fAnimators[animatorIndex]; 111 const SkMemberInfo * info = animator->fFieldInfo; 112 SkASSERT(animator); 113 SkASSERT(info != NULL); 114 SkDisplayTypes type = (SkDisplayTypes) info->fType; 115 SkDisplayable* target = getTarget(animator); 116 if (animator->hasExecute() || type == SkType_MemberFunction || type == SkType_MemberProperty) { 117 SkDisplayable* executor = animator->hasExecute() ? animator : target; 118 if (type != SkType_MemberProperty) { 119 SkTDArray<SkScriptValue> typedValues; 120 for (int index = 0; index < count; index++) { 121 SkScriptValue temp; 122 temp.fType = valuesType; 123 temp.fOperand = values[index]; 124 *typedValues.append() = temp; 125 } 126 executor->executeFunction(target, info->functionIndex(), typedValues, info->getType(), NULL); 127 } else { 128 SkScriptValue scriptValue; 129 scriptValue.fOperand = values[0]; 130 scriptValue.fType = info->getType(); 131 target->setProperty(info->propertyIndex(), scriptValue); 132 } 133 } else { 134 SkTypedArray converted; 135 if (type == SkType_ARGB) { 136 if (count == 4) { 137 // !!! assert that it is SkType_Float ? 138 animator->packARGB(&values->fScalar, count, &converted); 139 values = converted.begin(); 140 count = converted.count(); 141 } else { 142 SkASSERT(count == 1); 143 } 144 } 145// SkASSERT(type == SkType_ARGB || type == SkType_String ||info->isSettable()); 146 if (type == SkType_String || type == SkType_DynamicString) 147 info->setString(target, values->fString); 148 else if (type == SkType_Drawable || type == SkType_Displayable) 149 target->setReference(info, values->fDisplayable); 150 else 151 info->setValue(target, values, count); 152 } 153} 154 155bool SkApply::contains(SkDisplayable* child) { 156 for (SkDrawable** curPtr = fScopes.begin(); curPtr < fScopes.end(); curPtr++) { 157 if (*curPtr == child || (*curPtr)->contains(child)) 158 return true; 159 } 160 return fDeleteScope && scope == child; 161} 162 163SkDisplayable* SkApply::deepCopy(SkAnimateMaker* maker) { 164 SkDrawable* saveScope = scope; 165 scope = NULL; 166 SkApply* result = (SkApply*) INHERITED::deepCopy(maker); 167 result->scope = scope = saveScope; 168 SkAnimateBase** end = fAnimators.end(); 169 for (SkAnimateBase** animPtr = fAnimators.begin(); animPtr < end; animPtr++) { 170 SkAnimateBase* anim = (SkAnimateBase*) (*animPtr)->deepCopy(maker); 171 *result->fAnimators.append() = anim; 172 maker->helperAdd(anim); 173 } 174 return result; 175} 176 177void SkApply::disable() { 178 //!!! this is the right thing to do, but has bad side effects because of other problems 179 // currently, if an apply is in a g and scopes a statement in another g, it ends up as members 180 // of both containers. The disabling here incorrectly disables both instances 181 // maybe the fEnabled flag needs to be moved to the fActive data so that both 182 // instances are not affected. 183// fEnabled = false; 184} 185 186bool SkApply::draw(SkAnimateMaker& maker) { 187 if (scope ==NULL) 188 return false; 189 if (scope->isApply() || scope->isDrawable() == false) 190 return false; 191 if (fEnabled == false) 192 enable(maker); 193 SkASSERT(scope); 194 activate(maker); 195 if (mode == kMode_immediate) 196 return fActive->draw(); 197 bool result = interpolate(maker, maker.getInTime()); 198 if (dontDraw == false) { 199// if (scope->isDrawable()) 200 result |= scope->draw(maker); 201 } 202 if (restore) { 203 for (int index = 0; index < fActive->fAnimators.count(); index++) 204 endSave(index); 205 fActive->advance(); 206 } 207 return result; 208} 209 210#ifdef SK_DUMP_ENABLED 211void SkApply::dump(SkAnimateMaker* maker) { 212 dumpBase(maker); 213 if (dynamicScope.isEmpty() == false) 214 SkDebugf("dynamicScope=\"%s\" ", dynamicScope.c_str()); 215 if (dontDraw) 216 SkDebugf("dontDraw=\"true\" "); 217 if (begin != 0) //perhaps we want this no matter what? 218 SkDebugf("begin=\"%g\" ", (float) begin/1000.0f); //is this correct? 219 if (interval != (SkMSec) -1) 220 SkDebugf("interval=\"%g\" ", (float) interval/1000.0f); 221 if (steps != -1) 222 SkDebugf("steps=\"%d\" ", steps); 223 if (restore) 224 SkDebugf("restore=\"true\" "); 225 if (transition == kTransition_reverse) 226 SkDebugf("transition=\"reverse\" "); 227 if (mode == kMode_immediate) { 228 SkDebugf("mode=\"immediate\" "); 229 } 230 else if (mode == kMode_create) { 231 SkDebugf("mode=\"create\" "); 232 } 233 bool closedYet = false; 234 SkDisplayList::fIndent += 4; 235 int save = SkDisplayList::fDumpIndex; 236 if (scope) { 237 if (closedYet == false) { 238 SkDebugf(">\n"); 239 closedYet = true; 240 } 241 scope->dump(maker); 242 } 243 int index; 244// if (fActive) { 245 for (index = 0; index < fAnimators.count(); index++) { 246 if (closedYet == false) { 247 SkDebugf(">\n"); 248 closedYet = true; 249 } 250 SkAnimateBase* animator = fAnimators[index]; 251 animator->dump(maker); 252// } 253 } 254 SkDisplayList::fIndent -= 4; 255 SkDisplayList::fDumpIndex = save; 256 if (closedYet) 257 dumpEnd(maker); 258 else 259 SkDebugf("/>\n"); 260} 261#endif 262 263bool SkApply::enable(SkAnimateMaker& maker) { 264 fEnabled = true; 265 bool initialized = fActive != NULL; 266 if (dynamicScope.size() > 0) 267 enableDynamic(maker); 268 if (maker.fError.hasError()) 269 return false; 270 int animators = fAnimators.count(); 271 int index; 272 for (index = 0; index < animators; index++) { 273 SkAnimateBase* animator = fAnimators[index]; 274 animator->fStart = maker.fEnableTime; 275 animator->fResetPending = animator->fReset; 276 } 277 if (scope && scope->isApply()) 278 ((SkApply*) scope)->setEmbedded(); 279/* if (mode == kMode_once) { 280 if (scope) { 281 activate(maker); 282 interpolate(maker, maker.fEnableTime); 283 inactivate(maker); 284 } 285 return true; 286 }*/ 287 if ((mode == kMode_immediate || mode == kMode_create) && scope == NULL) 288 return false; // !!! error? 289 bool enableMe = scope && (scope->hasEnable() || scope->isApply() || scope->isDrawable() == false); 290 if ((mode == kMode_immediate && enableMe) || mode == kMode_create) 291 activate(maker); // for non-drawables like post, prime them here 292 if (mode == kMode_immediate && enableMe) 293 fActive->enable(); 294 if (mode == kMode_create && scope != NULL) { 295 enableCreate(maker); 296 return true; 297 } 298 if (mode == kMode_immediate) { 299 return scope->isApply() || scope->isDrawable() == false; 300 } 301 refresh(maker); 302 SkDisplayList& displayList = maker.fDisplayList; 303 SkDrawable* drawable; 304#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING 305 SkString debugOut; 306 SkMSec time = maker.getAppTime(); 307 debugOut.appendS32(time - maker.fDebugTimeBase); 308 debugOut.append(" apply enable id="); 309 debugOut.append(_id); 310 debugOut.append("; start="); 311 debugOut.appendS32(maker.fEnableTime - maker.fDebugTimeBase); 312 SkDebugf("%s\n", debugOut.c_str()); 313#endif 314 if (scope == NULL || scope->isApply() || scope->getType() == SkType_Movie || scope->isDrawable() == false) { 315 activate(maker); // for non-drawables like post, prime them here 316 if (initialized) { 317 append(this); 318 } 319 fEnabling = true; 320 interpolate(maker, maker.fEnableTime); 321 fEnabling = false; 322 if (scope != NULL && dontDraw == false) 323 scope->enable(maker); 324 return true; 325 } else if (initialized && restore == false) 326 append(this); 327#if 0 328 bool wasActive = inactivate(maker); // start fresh 329 if (wasActive) { 330 activate(maker); 331 interpolate(maker, maker.fEnableTime); 332 return true; 333 } 334#endif 335// start here; 336 // now that one apply might embed another, only the parent apply should replace the scope 337 // or get appended to the display list 338 // similarly, an apply added by an add immediate has already been located in the display list 339 // and should not get moved or added again here 340 if (fEmbedded) { 341 return false; // already added to display list by embedder 342 } 343 drawable = (SkDrawable*) scope; 344 SkTDDrawableArray* parentList; 345 SkTDDrawableArray* grandList; 346 SkGroup* parentGroup; 347 SkGroup* thisGroup; 348 int old = displayList.findGroup(drawable, &parentList, &parentGroup, &thisGroup, &grandList); 349 if (old < 0) 350 goto append; 351 else if (fContainsScope) { 352 if ((*parentList)[old] != this || restore) { 353append: 354 if (parentGroup) 355 parentGroup->markCopySize(old); 356 if (parentList->count() < 10000) { 357 fAppended = true; 358 *parentList->append() = this; 359 } else 360 maker.setErrorCode(SkDisplayXMLParserError::kDisplayTreeTooDeep); 361 old = -1; 362 } else 363 reset(); 364 } else { 365 SkASSERT(old < parentList->count()); 366 if ((*parentList)[old]->isApply()) { 367 SkApply* apply = (SkApply*) (*parentList)[old]; 368 if (apply != this && apply->fActive == NULL) 369 apply->activate(maker); 370 apply->append(this); 371 parentGroup = NULL; 372 } else { 373 if (parentGroup) 374 parentGroup->markCopySize(old); 375 SkDrawable** newApplyLocation = &(*parentList)[old]; 376 SkGroup* pGroup; 377 int oldApply = displayList.findGroup(this, &parentList, &pGroup, &thisGroup, &grandList); 378 if (oldApply >= 0) { 379 (*parentList)[oldApply] = (SkDrawable*) SkDisplayType::CreateInstance(&maker, SkType_Apply); 380 parentGroup = NULL; 381 fDeleteScope = true; 382 } 383 *newApplyLocation = this; 384 } 385 } 386 if (parentGroup) { 387 parentGroup->markCopySet(old); 388 fDeleteScope = dynamicScope.size() == 0; 389 } 390 return true; 391} 392 393void SkApply::enableCreate(SkAnimateMaker& maker) { 394 SkString newID; 395 for (int step = 0; step <= steps; step++) { 396 fLastTime = step * SK_MSec1; 397 bool success = maker.computeID(scope, this, &newID); 398 if (success == false) 399 return; 400 if (maker.find(newID.c_str(), NULL)) 401 continue; 402 SkApply* copy = (SkApply*) deepCopy(&maker); // work on copy of animator state 403 if (mode == kMode_create) 404 copy->mode = (Mode) -1; 405 SkDrawable* copyScope = copy->scope = (SkDrawable*) scope->deepCopy(&maker); 406 *fScopes.append() = copyScope; 407 if (copyScope->resolveIDs(maker, scope, this)) { 408 step = steps; // quit 409 goto next; // resolveIDs failed 410 } 411 if (newID.size() > 0) 412 maker.setID(copyScope, newID); 413 if (copy->resolveIDs(maker, this, this)) { // fix up all fields, including target 414 step = steps; // quit 415 goto next; // resolveIDs failed 416 } 417 copy->activate(maker); 418 copy->interpolate(maker, step * SK_MSec1); 419 maker.removeActive(copy->fActive); 420 next: 421 delete copy; 422 } 423} 424 425void SkApply::enableDynamic(SkAnimateMaker& maker) { 426 SkASSERT(mode != kMode_create); // create + dynamic are not currently compatible 427 SkDisplayable* newScope; 428 bool success = SkAnimatorScript::EvaluateDisplayable(maker, this, dynamicScope.c_str(), 429 &newScope); 430 if (success && scope != newScope) { 431 SkTDDrawableArray* pList, * gList; 432 SkGroup* pGroup = NULL, * found = NULL; 433 int old = maker.fDisplayList.findGroup(scope, &pList, &pGroup, &found, &gList); 434 if (pList && old >= 0 && (*pList)[old]->isApply() && (*pList)[old] != this) { 435 if (fAppended == false) { 436 if (found != NULL) { 437 SkDisplayable* oldChild = (*pList)[old]; 438 if (oldChild->isApply() && found->copySet(old)) { 439 found->markCopyClear(old); 440 // delete oldChild; 441 } 442 } 443 (*pList)[old] = scope; 444 } else 445 pList->remove(old); 446 } 447 scope = (SkDrawable*) newScope; 448 onEndElement(maker); 449 } 450 maker.removeActive(fActive); 451 delete fActive; 452 fActive = NULL; 453} 454 455void SkApply::endSave(int index) { 456 SkAnimateBase* animate = fActive->fAnimators[index]; 457 const SkMemberInfo* info = animate->fFieldInfo; 458 SkDisplayTypes type = (SkDisplayTypes) info->fType; 459 if (type == SkType_MemberFunction) 460 return; 461 SkDisplayable* target = getTarget(animate); 462 size_t size = info->getSize(target); 463 int count = (int) (size / sizeof(SkScalar)); 464 int activeIndex = fActive->fDrawIndex + index; 465 SkOperand* last = new SkOperand[count]; 466 SkAutoTDelete<SkOperand> autoLast(last); 467 if (type != SkType_MemberProperty) { 468 info->getValue(target, last, count); 469 SkOperand* saveOperand = fActive->fSaveRestore[activeIndex]; 470 if (saveOperand) 471 info->setValue(target, fActive->fSaveRestore[activeIndex], count); 472 } else { 473 SkScriptValue scriptValue; 474 SkDEBUGCODE(bool success = ) target->getProperty(info->propertyIndex(), &scriptValue); 475 SkASSERT(success == true); 476 last[0] = scriptValue.fOperand; 477 scriptValue.fOperand = fActive->fSaveRestore[activeIndex][0]; 478 target->setProperty(info->propertyIndex(), scriptValue); 479 } 480 SkOperand* save = fActive->fSaveRestore[activeIndex]; 481 if (save) 482 memcpy(save, last, count * sizeof(SkOperand)); 483} 484 485bool SkApply::getProperty(int index, SkScriptValue* value) const { 486 switch (index) { 487 case SK_PROPERTY(step): 488 value->fType = SkType_Int; 489 value->fOperand.fS32 = fLastTime / SK_MSec1; 490 break; 491 case SK_PROPERTY(steps): 492 value->fType = SkType_Int; 493 value->fOperand.fS32 = steps; 494 break; 495 case SK_PROPERTY(time): 496 value->fType = SkType_MSec; 497 value->fOperand.fS32 = fLastTime; 498 break; 499 default: 500 // SkASSERT(0); 501 return false; 502 } 503 return true; 504} 505 506void SkApply::getStep(SkScriptValue* value) { 507 getProperty(SK_PROPERTY(step), value); 508} 509 510SkDrawable* SkApply::getTarget(SkAnimateBase* animate) { 511 if (animate->fTargetIsScope == false || mode != kMode_create) 512 return animate->fTarget; 513 return scope; 514} 515 516bool SkApply::hasDelayedAnimator() const { 517 SkAnimateBase* const* animEnd = fAnimators.end(); 518 for (SkAnimateBase* const* animPtr = fAnimators.begin(); animPtr < animEnd; animPtr++) { 519 SkAnimateBase* const animator = *animPtr; 520 if (animator->fDelayed) 521 return true; 522 } 523 return false; 524} 525 526bool SkApply::hasEnable() const { 527 return true; 528} 529 530bool SkApply::inactivate(SkAnimateMaker& maker) { 531 if (fActive == NULL) 532 return false; 533 maker.removeActive(fActive); 534 delete fActive; 535 fActive = NULL; 536 return true; 537} 538 539#ifdef SK_DEBUG 540SkMSec lastTime = (SkMSec) -1; 541#endif 542 543bool SkApply::interpolate(SkAnimateMaker& maker, SkMSec rawTime) { 544 if (fActive == NULL) 545 return false; 546 bool result = false; 547#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING 548 SkMSec time = maker.getAppTime(); 549 if (lastTime == (SkMSec) -1) 550 lastTime = rawTime - 1; 551 if (fActive != NULL && 552 strcmp(id, "a3") == 0 && rawTime > lastTime) { 553 lastTime += 1000; 554 SkString debugOut; 555 debugOut.appendS32(time - maker.fDebugTimeBase); 556 debugOut.append(" apply id="); 557 debugOut.append(_id); 558 debugOut.append("; "); 559 debugOut.append(fActive->fAnimators[0]->_id); 560 debugOut.append("="); 561 debugOut.appendS32(rawTime - fActive->fState[0].fStartTime); 562 debugOut.append(")"); 563 SkDebugf("%s\n", debugOut.c_str()); 564 } 565#endif 566 fActive->start(); 567 if (restore) 568 fActive->initializeSave(); 569 int animators = fActive->fAnimators.count(); 570 for (int inner = 0; inner < animators; inner++) { 571 SkAnimateBase* animate = fActive->fAnimators[inner]; 572 if (animate->fChanged) { 573 animate->fChanged = false; 574 animate->fStart = rawTime; 575 // SkTypedArray values; 576 // int count = animate->fValues.count(); 577 // values.setCount(count); 578 // memcpy(values.begin(), animate->fValues.begin(), sizeof(SkOperand) * count); 579 animate->onEndElement(maker); 580 // if (memcmp(values.begin(), animate->fValues.begin(), sizeof(SkOperand) * count) != 0) { 581 fActive->append(this); 582 fActive->start(); 583 // } 584 } 585 SkMSec time = fActive->getTime(rawTime, inner); 586 SkActive::SkState& state = fActive->fState[inner]; 587 if (SkMSec_LT(rawTime, state.fStartTime)) { 588 if (fEnabling) { 589 animate->fDelayed = true; 590 maker.delayEnable(this, state.fStartTime); 591 } 592 continue; 593 } else 594 animate->fDelayed = false; 595 SkMSec innerTime = fLastTime = state.getRelativeTime(time); 596 if (restore) 597 fActive->restoreInterpolatorValues(inner); 598 if (animate->fReset) { 599 if (transition != SkApply::kTransition_reverse) { 600 if (SkMSec_LT(state.fBegin + state.fDuration, innerTime)) { 601 if (animate->fResetPending) { 602 innerTime = 0; 603 animate->fResetPending = false; 604 } else 605 continue; 606 } 607 } else if (innerTime == 0) { 608 if (animate->fResetPending) { 609 innerTime = state.fBegin + state.fDuration; 610 animate->fResetPending = false; 611 } else 612 continue; 613 } 614 } 615 int count = animate->components(); 616 SkAutoSTMalloc<16, SkOperand> values(count); 617 SkInterpolatorBase::Result interpResult = fActive->fInterpolators[inner]->timeToValues( 618 innerTime, values.get()); 619 result |= (interpResult != SkInterpolatorBase::kFreezeEnd_Result); 620 if (((transition != SkApply::kTransition_reverse && interpResult == SkInterpolatorBase::kFreezeEnd_Result) || 621 (transition == SkApply::kTransition_reverse && fLastTime == 0)) && state.fUnpostedEndEvent) { 622// SkDEBUGF(("interpolate: post on end\n")); 623 state.fUnpostedEndEvent = false; 624 maker.postOnEnd(animate, state.fBegin + state.fDuration); 625 maker.fAdjustedStart = 0; // !!! left over from synchronizing animation days, undoubtably out of date (and broken) 626 } 627 if (animate->formula.size() > 0) { 628 if (fLastTime > animate->dur) 629 fLastTime = animate->dur; 630 SkTypedArray formulaValues; 631 formulaValues.setCount(count); 632 SkDEBUGCODE(bool success = ) animate->fFieldInfo->setValue(maker, &formulaValues, 0, 0, NULL, 633 animate->getValuesType(), animate->formula); 634 SkASSERT(success); 635 if (restore) 636 save(inner); // save existing value 637 applyValues(inner, formulaValues.begin(), count, animate->getValuesType(), innerTime); 638 } else { 639 if (restore) 640 save(inner); // save existing value 641 applyValues(inner, values.get(), count, animate->getValuesType(), innerTime); 642 } 643 } 644 return result; 645} 646 647void SkApply::initialize() { 648 if (scope == NULL) 649 return; 650 if (scope->isApply() || scope->isDrawable() == false) 651 return; 652 scope->initialize(); 653} 654 655void SkApply::onEndElement(SkAnimateMaker& maker) 656{ 657 SkDrawable* scopePtr = scope; 658 while (scopePtr && scopePtr->isApply()) { 659 SkApply* scopedApply = (SkApply*) scopePtr; 660 if (scopedApply->scope == this) { 661 maker.setErrorCode(SkDisplayXMLParserError::kApplyScopesItself); 662 return; 663 } 664 scopePtr = scopedApply->scope; 665 } 666 if (mode == kMode_create) 667 return; 668 if (scope != NULL && steps >= 0 && scope->isApply() == false && scope->isDrawable()) 669 scope->setSteps(steps); 670 for (SkAnimateBase** animPtr = fAnimators.begin(); animPtr < fAnimators.end(); animPtr++) { 671 SkAnimateBase* anim = *animPtr; 672 //for reusing apply statements with dynamic scope 673 if (anim->fTarget == NULL || anim->fTargetIsScope) { 674 anim->fTargetIsScope = true; 675 if (scope) 676 anim->fTarget = scope; 677 else 678 anim->setTarget(maker); 679 anim->onEndElement(maker); // allows animate->fFieldInfo to be set 680 } 681 if (scope != NULL && steps >= 0 && anim->fTarget != scope && anim->fTarget->isDrawable()) 682 anim->fTarget->setSteps(steps); 683 } 684} 685 686const SkMemberInfo* SkApply::preferredChild(SkDisplayTypes type) { 687 SkASSERT(SkDisplayType::IsAnimate(type) == false); 688 fContainsScope = true; 689 return getMember("scope"); // !!! cwap! need to refer to member through enum like kScope instead 690} 691 692void SkApply::refresh(SkAnimateMaker& maker) { 693 for (SkAnimateBase** animPtr = fAnimators.begin(); animPtr < fAnimators.end(); animPtr++) { 694 SkAnimateBase* animate = *animPtr; 695 animate->onEndElement(maker); 696 } 697 if (fActive) 698 fActive->resetInterpolators(); 699} 700 701void SkApply::reset() { 702 if (fActive) 703 fActive->resetState(); 704} 705 706bool SkApply::resolveIDs(SkAnimateMaker& maker, SkDisplayable* original, SkApply* apply) { // replace to/formula strings in animators of the form xxx.step with the step value, if xxx.step is in scope 707 if (resolveField(maker, apply, &dynamicScope) == false) 708 return true; // failed 709 SkAnimateBase** endPtr = fAnimators.end(); 710 SkAnimateBase** origPtr = ((SkApply*) original)->fAnimators.begin(); 711 for (SkAnimateBase** animPtr = fAnimators.begin(); animPtr < endPtr; ) { 712 SkAnimateBase* animator = *animPtr++; 713 maker.resolveID(animator, *origPtr++); 714 if (resolveField(maker, this, &animator->target) == false) 715 return true; 716 if (resolveField(maker, this, &animator->from) == false) 717 return true; 718 if (resolveField(maker, this, &animator->to) == false) 719 return true; 720 if (resolveField(maker, this, &animator->formula) == false) 721 return true; 722 } 723// setEmbedded(); 724 onEndElement(maker); 725 return false; // succeeded 726} 727 728bool SkApply::resolveField(SkAnimateMaker& maker, SkDisplayable* parent, SkString* str) { 729 const char* script = str->c_str(); 730 if (str->startsWith("#string:") == false) 731 return true; 732 script += sizeof("#string:") - 1; 733 return SkAnimatorScript::EvaluateString(maker, this, parent, script, str); 734} 735 736void SkApply::save(int index) { 737 SkAnimateBase* animate = fActive->fAnimators[index]; 738 const SkMemberInfo * info = animate->fFieldInfo; 739 SkDisplayable* target = getTarget(animate); 740// if (animate->hasExecute()) 741// info = animate->getResolvedInfo(); 742 SkDisplayTypes type = (SkDisplayTypes) info->fType; 743 if (type == SkType_MemberFunction) 744 return; // nothing to save 745 size_t size = info->getSize(target); 746 int count = (int) (size / sizeof(SkScalar)); 747 bool useLast = true; 748// !!! this all may be unneeded, at least in the dynamic case ?? 749 int activeIndex = fActive->fDrawIndex + index; 750 SkTDOperandArray last; 751 if (fActive->fSaveRestore[activeIndex] == NULL) { 752 fActive->fSaveRestore[activeIndex] = new SkOperand[count]; 753 useLast = false; 754 } else { 755 last.setCount(count); 756 memcpy(last.begin(), fActive->fSaveRestore[activeIndex], count * sizeof(SkOperand)); 757 } 758 if (type != SkType_MemberProperty) { 759 info->getValue(target, fActive->fSaveRestore[activeIndex], count); 760 if (useLast) 761 info->setValue(target, last.begin(), count); 762 } else { 763 SkScriptValue scriptValue; 764 SkDEBUGCODE(bool success = ) target->getProperty(info->propertyIndex(), &scriptValue); 765 SkASSERT(success == true); 766 SkASSERT(scriptValue.fType == SkType_Float); 767 fActive->fSaveRestore[activeIndex][0] = scriptValue.fOperand; 768 if (useLast) { 769 SkScriptValue scriptValue; 770 scriptValue.fType = type; 771 scriptValue.fOperand = last[0]; 772 target->setProperty(info->propertyIndex(), scriptValue); 773 } 774 } 775// !!! end of unneeded 776} 777 778bool SkApply::setProperty(int index, SkScriptValue& scriptValue) { 779 switch (index) { 780 case SK_PROPERTY(animator): { 781 SkAnimateBase* animate = (SkAnimateBase*) scriptValue.fOperand.fDisplayable; 782 SkASSERT(animate->isAnimate()); 783 *fAnimators.append() = animate; 784 return true; 785 } 786 case SK_PROPERTY(steps): 787 steps = scriptValue.fOperand.fS32; 788 if (fActive) 789 fActive->setSteps(steps); 790 return true; 791 } 792 return false; 793} 794 795void SkApply::setSteps(int _steps) { 796 steps = _steps; 797} 798 799#ifdef SK_DEBUG 800void SkApply::validate() { 801 if (fActive) 802 fActive->validate(); 803} 804#endif 805