Home | History | Annotate | Download | only in animator
      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 
     25 enum 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
     36 const 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 
     56 DEFINE_GET_MEMBER(SkApply);
     57 
     58 SkApply::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 
     64 SkApply::~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 
     73 void 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 
     94 void 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 
    107 void 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 
    155 bool 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 
    163 SkDisplayable* 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 
    177 void 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 
    186 bool 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
    211 void 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 
    263 bool 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) {
    353 append:
    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 
    393 void 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 
    425 void 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 
    455 void 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 
    485 bool 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 
    506 void SkApply::getStep(SkScriptValue* value) {
    507     getProperty(SK_PROPERTY(step), value);
    508 }
    509 
    510 SkDrawable* SkApply::getTarget(SkAnimateBase* animate) {
    511     if (animate->fTargetIsScope == false || mode != kMode_create)
    512         return animate->fTarget;
    513     return scope;
    514 }
    515 
    516 bool 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 
    526 bool SkApply::hasEnable() const {
    527     return true;
    528 }
    529 
    530 bool 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
    540 SkMSec lastTime = (SkMSec) -1;
    541 #endif
    542 
    543 bool 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 
    647 void SkApply::initialize() {
    648     if (scope == NULL)
    649         return;
    650     if (scope->isApply() || scope->isDrawable() == false)
    651         return;
    652     scope->initialize();
    653 }
    654 
    655 void 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 
    686 const 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 
    692 void 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 
    701 void SkApply::reset() {
    702     if (fActive)
    703         fActive->resetState();
    704 }
    705 
    706 bool 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 
    728 bool 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 
    736 void 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 
    778 bool 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 
    795 void SkApply::setSteps(int _steps) {
    796     steps = _steps;
    797 }
    798 
    799 #ifdef SK_DEBUG
    800 void SkApply::validate() {
    801     if (fActive)
    802         fActive->validate();
    803 }
    804 #endif
    805