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