• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SkApply()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 
~SkApply()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 
activate(SkAnimateMaker & maker)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 
append(SkApply * apply)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 
applyValues(int animatorIndex,SkOperand * values,int count,SkDisplayTypes valuesType,SkMSec time)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 
contains(SkDisplayable * child)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 
deepCopy(SkAnimateMaker * maker)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 
disable()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 
draw(SkAnimateMaker & maker)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
dump(SkAnimateMaker * maker)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 
enable(SkAnimateMaker & maker)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 == true) {
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 
enableCreate(SkAnimateMaker & maker)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 
enableDynamic(SkAnimateMaker & maker)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 
endSave(int index)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 
getProperty(int index,SkScriptValue * value) const492 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 
getStep(SkScriptValue * value)513 void SkApply::getStep(SkScriptValue* value) {
514     getProperty(SK_PROPERTY(step), value);
515 }
516 
getTarget(SkAnimateBase * animate)517 SkDrawable* SkApply::getTarget(SkAnimateBase* animate) {
518     if (animate->fTargetIsScope == false || mode != kMode_create)
519         return animate->fTarget;
520     return scope;
521 }
522 
hasDelayedAnimator() const523 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 
hasEnable() const533 bool SkApply::hasEnable() const {
534     return true;
535 }
536 
inactivate(SkAnimateMaker & maker)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 
interpolate(SkAnimateMaker & maker,SkMSec rawTime)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 
initialize()654 void SkApply::initialize() {
655     if (scope == NULL)
656         return;
657     if (scope->isApply() || scope->isDrawable() == false)
658         return;
659     scope->initialize();
660 }
661 
onEndElement(SkAnimateMaker & maker)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 
preferredChild(SkDisplayTypes type)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 
refresh(SkAnimateMaker & maker)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 
reset()708 void SkApply::reset() {
709     if (fActive)
710         fActive->resetState();
711 }
712 
resolveIDs(SkAnimateMaker & maker,SkDisplayable * original,SkApply * apply)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 
resolveField(SkAnimateMaker & maker,SkDisplayable * parent,SkString * str)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 
save(int index)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 
setProperty(int index,SkScriptValue & scriptValue)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 
setSteps(int _steps)802 void SkApply::setSteps(int _steps) {
803     steps = _steps;
804 }
805 
806 #ifdef SK_DEBUG
validate()807 void SkApply::validate() {
808     if (fActive)
809         fActive->validate();
810 }
811 #endif
812 
813 
814 
815