diff options
Diffstat (limited to 'skia/animator/SkAnimateMaker.cpp')
-rw-r--r-- | skia/animator/SkAnimateMaker.cpp | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/skia/animator/SkAnimateMaker.cpp b/skia/animator/SkAnimateMaker.cpp new file mode 100644 index 0000000..82c3f9a --- /dev/null +++ b/skia/animator/SkAnimateMaker.cpp @@ -0,0 +1,376 @@ +/* libs/graphics/animator/SkAnimateMaker.cpp +** +** Copyright 2006, Google Inc. +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#include "SkAnimateMaker.h" +#include "SkAnimator.h" +#include "SkAnimatorScript.h" +#include "SkDisplayable.h" +#include "SkDisplayApply.h" +#include "SkDisplayList.h" +#include "SkDisplayMovie.h" +#include "SkDisplayType.h" +#include "SkExtras.h" +#include "SkMemberInfo.h" +#include "SkStream.h" +#include "SkSystemEventTypes.h" +#include "SkTime.h" + +class DefaultTimeline : public SkAnimator::Timeline { + virtual SkMSec getMSecs() const { + return SkTime::GetMSecs(); + } +} gDefaultTimeline; + +SkAnimateMaker::SkAnimateMaker(SkAnimator* animator, SkCanvas* canvas, SkPaint* paint) + : fActiveEvent(NULL), fAdjustedStart(0), fCanvas(canvas), fEnableTime(0), + fHostEventSinkID(0), fMinimumInterval((SkMSec) -1), fPaint(paint), fParentMaker(NULL), + fTimeline(&gDefaultTimeline), fInInclude(false), fInMovie(false), + fFirstScriptError(false), fLoaded(false), fIDs(256), fAnimator(animator) +{ + fScreenplay.time = 0; +#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING + fDebugTimeBase = (SkMSec) -1; +#endif +#ifdef SK_DUMP_ENABLED + fDumpEvents = fDumpGConditions = fDumpPosts = false; +#endif +} + +SkAnimateMaker::~SkAnimateMaker() { + deleteMembers(); +} + +#if 0 +SkMSec SkAnimateMaker::adjustDelay(SkMSec expectedBase, SkMSec delay) { + SkMSec appTime = (*fTimeCallBack)(); + if (appTime) + delay -= appTime - expectedBase; + if (delay < 0) + delay = 0; + return delay; +} +#endif + +void SkAnimateMaker::appendActive(SkActive* active) { + fDisplayList.append(active); +} + +void SkAnimateMaker::clearExtraPropertyCallBack(SkDisplayTypes type) { + SkExtras** end = fExtras.end(); + for (SkExtras** extraPtr = fExtras.begin(); extraPtr < end; extraPtr++) { + SkExtras* extra = *extraPtr; + if (extra->definesType(type)) { + extra->fExtraCallBack = NULL; + extra->fExtraStorage = NULL; + break; + } + } +} + +bool SkAnimateMaker::computeID(SkDisplayable* displayable, SkDisplayable* parent, SkString* newID) { + const char* script; + if (findKey(displayable, &script) == false) + return true; + return SkAnimatorScript::EvaluateString(*this, displayable, parent, script, newID); +} + +SkDisplayable* SkAnimateMaker::createInstance(const char name[], size_t len) { + SkDisplayTypes type = SkDisplayType::GetType(this, name, len ); + if ((int)type >= 0) + return SkDisplayType::CreateInstance(this, type); + return NULL; +} + +// differs from SkAnimator::decodeStream in that it does not reset error state +bool SkAnimateMaker::decodeStream(SkStream* stream) +{ + SkDisplayXMLParser parser(*this); + return parser.parse(*stream); +} + +// differs from SkAnimator::decodeURI in that it does not set URI base +bool SkAnimateMaker::decodeURI(const char uri[]) { +// SkDebugf("animator decode %s\n", uri); + +// SkStream* stream = SkStream::GetURIStream(fPrefix.c_str(), uri); + SkStream* stream = new SkFILEStream(uri); + + SkAutoTDelete<SkStream> autoDel(stream); + bool success = decodeStream(stream); + if (hasError() && fError.hasNoun() == false) + fError.setNoun(uri); + return success; +} + +#if defined SK_DEBUG && 0 +//used for the if'd out section of deleteMembers +#include "SkTSearch.h" + +extern "C" { + int compare_disp(const void* a, const void* b) { + return *(const SkDisplayable**)a - *(const SkDisplayable**)b; + } +} +#endif + +void SkAnimateMaker::delayEnable(SkApply* apply, SkMSec time) { + int index = fDelayed.find(apply); + if (index < 0) + *fDelayed.append() = apply; + (new SkEvent(SK_EventType_Delay))->postTime(fAnimator->getSinkID(), time); +} + +void SkAnimateMaker::deleteMembers() { + int index; +#if defined SK_DEBUG && 0 + //this code checks to see if helpers are among the children, but it is not complete - + //it should check the children of the children + int result; + SkTDArray<SkDisplayable*> children(fChildren.begin(), fChildren.count()); + SkQSort(children.begin(), children.count(), sizeof(SkDisplayable*),compare_disp); + for (index = 0; index < fHelpers.count(); index++) { + SkDisplayable* helper = fHelpers[index]; + result = SkTSearch(children.begin(), children.count(), helper, sizeof(SkDisplayable*)); + SkASSERT(result < 0); + } +#endif + for (index = 0; index < fChildren.count(); index++) { + SkDisplayable* child = fChildren[index]; + delete child; + } + for (index = 0; index < fHelpers.count(); index++) { + SkDisplayable* helper = fHelpers[index]; + delete helper; + } + for (index = 0; index < fExtras.count(); index++) { + SkExtras* extras = fExtras[index]; + delete extras; + } +} + +void SkAnimateMaker::doDelayedEvent() { + fEnableTime = getAppTime(); + for (int index = 0; index < fDelayed.count(); ) { + SkDisplayable* child = fDelayed[index]; + SkASSERT(child->isApply()); + SkApply* apply = (SkApply*) child; + apply->interpolate(*this, fEnableTime); + if (apply->hasDelayedAnimator()) + index++; + else + fDelayed.remove(index); + } +} + +bool SkAnimateMaker::doEvent(const SkEvent& event) { + return (!fInMovie || fLoaded) && fAnimator->doEvent(event); +} + +#ifdef SK_DUMP_ENABLED +void SkAnimateMaker::dump(const char* match) { + SkTDict<SkDisplayable*>::Iter iter(fIDs); + const char* name; + SkDisplayable* result; + while ((name = iter.next(&result)) != NULL) { + if (strcmp(match,name) == 0) + result->dump(this); + } +} +#endif + +int SkAnimateMaker::dynamicProperty(SkString& nameStr, SkDisplayable** displayablePtr ) { + const char* name = nameStr.c_str(); + const char* dot = strchr(name, '.'); + SkASSERT(dot); + SkDisplayable* displayable; + if (find(name, dot - name, &displayable) == false) { + SkASSERT(0); + return 0; + } + const char* fieldName = dot + 1; + const SkMemberInfo* memberInfo = displayable->getMember(fieldName); + *displayablePtr = displayable; + return (int) memberInfo->fOffset; +} + +SkMSec SkAnimateMaker::getAppTime() const { + return fTimeline->getMSecs(); +} + +#ifdef SK_DEBUG +SkAnimator* SkAnimateMaker::getRoot() +{ + SkAnimateMaker* maker = this; + while (maker->fParentMaker) + maker = maker->fParentMaker; + return maker == this ? NULL : maker->fAnimator; +} +#endif + +void SkAnimateMaker::helperAdd(SkDisplayable* trackMe) { + SkASSERT(fHelpers.find(trackMe) < 0); + *fHelpers.append() = trackMe; +} + +void SkAnimateMaker::helperRemove(SkDisplayable* alreadyTracked) { + int helperIndex = fHelpers.find(alreadyTracked); + if (helperIndex >= 0) + fHelpers.remove(helperIndex); +} + +#if 0 +void SkAnimateMaker::loadMovies() { + for (SkDisplayable** dispPtr = fMovies.begin(); dispPtr < fMovies.end(); dispPtr++) { + SkDisplayable* displayable = *dispPtr; + SkASSERT(displayable->getType() == SkType_Movie); + SkDisplayMovie* movie = (SkDisplayMovie*) displayable; + SkAnimateMaker* movieMaker = movie->fMovie.fMaker; + movieMaker->fEvents.doEvent(*movieMaker, SkDisplayEvent::kOnload, NULL); + movieMaker->fEvents.removeEvent(SkDisplayEvent::kOnload, NULL); + movieMaker->loadMovies(); + } +} +#endif + +void SkAnimateMaker::notifyInval() { + if (fHostEventSinkID) + fAnimator->onEventPost(new SkEvent(SK_EventType_Inval), fHostEventSinkID); +} + +void SkAnimateMaker::notifyInvalTime(SkMSec time) { + if (fHostEventSinkID) + fAnimator->onEventPostTime(new SkEvent(SK_EventType_Inval), fHostEventSinkID, time); +} + +void SkAnimateMaker::postOnEnd(SkAnimateBase* animate, SkMSec end) { + SkEvent evt; + evt.setS32("time", animate->getStart() + end); + evt.setPtr("anim", animate); + evt.setType(SK_EventType_OnEnd); + SkEventSinkID sinkID = fAnimator->getSinkID(); + fAnimator->onEventPost(new SkEvent(evt), sinkID); +} + +void SkAnimateMaker::reset() { + deleteMembers(); + fChildren.reset(); + fHelpers.reset(); + fIDs.reset(); + fEvents.reset(); + fDisplayList.hardReset(); +} + +void SkAnimateMaker::removeActive(SkActive* active) { + if (active == NULL) + return; + fDisplayList.remove(active); +} + +bool SkAnimateMaker::resolveID(SkDisplayable* displayable, SkDisplayable* original) { + SkString newID; + bool success = computeID(original, NULL, &newID); + if (success) + setID(displayable, newID); + return success; +} + +void SkAnimateMaker::setErrorString() { + fErrorString.reset(); + if (fError.hasError()) { + SkString err; + if (fFileName.size() > 0) + fErrorString.set(fFileName.c_str()); + else + fErrorString.set("screenplay error"); + int line = fError.getLineNumber(); + if (line >= 0) { + fErrorString.append(", "); + fErrorString.append("line "); + fErrorString.appendS32(line); + } + fErrorString.append(": "); + fError.getErrorString(&err); + fErrorString.append(err); +#if defined SK_DEBUG + SkDebugf("%s\n", fErrorString.c_str()); +#endif + } +} + +void SkAnimateMaker::setEnableTime(SkMSec appTime, SkMSec expectedTime) { +#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING + SkString debugOut; + SkMSec time = getAppTime(); + debugOut.appendS32(time - fDebugTimeBase); + debugOut.append(" set enable old enable="); + debugOut.appendS32(fEnableTime - fDebugTimeBase); + debugOut.append(" old adjust="); + debugOut.appendS32(fAdjustedStart); + debugOut.append(" new enable="); + debugOut.appendS32(expectedTime - fDebugTimeBase); + debugOut.append(" new adjust="); + debugOut.appendS32(appTime - expectedTime); + SkDebugf("%s\n", debugOut.c_str()); +#endif + fAdjustedStart = appTime - expectedTime; + fEnableTime = expectedTime; + SkDisplayable** firstMovie = fMovies.begin(); + SkDisplayable** endMovie = fMovies.end(); + for (SkDisplayable** ptr = firstMovie; ptr < endMovie; ptr++) { + SkDisplayMovie* movie = (SkDisplayMovie*) *ptr; + movie->fMovie.fMaker->setEnableTime(appTime, expectedTime); + } +} + +void SkAnimateMaker::setExtraPropertyCallBack(SkDisplayTypes type, + SkScriptEngine::_propertyCallBack callBack, void* userStorage) { + SkExtras** end = fExtras.end(); + for (SkExtras** extraPtr = fExtras.begin(); extraPtr < end; extraPtr++) { + SkExtras* extra = *extraPtr; + if (extra->definesType(type)) { + extra->fExtraCallBack = callBack; + extra->fExtraStorage = userStorage; + break; + } + } +} + +void SkAnimateMaker::setID(SkDisplayable* displayable, const SkString& newID) { + fIDs.set(newID.c_str(), displayable); +#ifdef SK_DEBUG + displayable->_id.set(newID); + displayable->id = displayable->_id.c_str(); +#endif +} + +void SkAnimateMaker::setScriptError(const SkScriptEngine& engine) { + SkString errorString; +#ifdef SK_DEBUG + engine.getErrorString(&errorString); +#endif + setErrorNoun(errorString); + setErrorCode(SkDisplayXMLParserError::kErrorInScript); +} + +bool SkAnimateMaker::GetStep(const char* token, size_t len, void* stepPtr, SkScriptValue* value) { + if (SK_LITERAL_STR_EQUAL("step", token, len)) { + value->fOperand.fS32 = *(int32_t*) stepPtr; + value->fType = SkType_Int; + return true; + } + return false; +} |