blob: b9e65f741fb615e2009e9fcc07142cde4b3a52c2 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* 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
33enum 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
44const 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
64DEFINE_GET_MEMBER(SkApply);
65
66SkApply::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
72SkApply::~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
81void 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
102void 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
115void 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
162bool 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
170SkDisplayable* 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
184void 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
193bool 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
218void 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
270bool 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) {
360append:
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
400void 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
432void 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
462void 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
492bool 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
513void SkApply::getStep(SkScriptValue* value) {
514 getProperty(SK_PROPERTY(step), value);
515}
516
517SkDrawable* SkApply::getTarget(SkAnimateBase* animate) {
518 if (animate->fTargetIsScope == false || mode != kMode_create)
519 return animate->fTarget;
520 return scope;
521}
522
523bool 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
533bool SkApply::hasEnable() const {
534 return true;
535}
536
537bool 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
547SkMSec lastTime = (SkMSec) -1;
548#endif
549
550bool 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
654void SkApply::initialize() {
655 if (scope == NULL)
656 return;
657 if (scope->isApply() || scope->isDrawable() == false)
658 return;
659 scope->initialize();
660}
661
662void 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
693const 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
699void 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
708void SkApply::reset() {
709 if (fActive)
710 fActive->resetState();
711}
712
713bool 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
735bool 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
743void 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
785bool 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
802void SkApply::setSteps(int _steps) {
803 steps = _steps;
804}
805
806#ifdef SK_DEBUG
807void SkApply::validate() {
808 if (fActive)
809 fActive->validate();
810}
811#endif
812
813
814