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