aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/animator/SkAnimateMaker.cpp
diff options
context:
space:
mode:
authorGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2008-12-17 15:59:43 +0000
committerGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2008-12-17 15:59:43 +0000
commit8a1c16ff38322f0210116fa7293eb8817c7e477e (patch)
treefe40e07f6c8983318a2f79032b9a706ede1090c1 /src/animator/SkAnimateMaker.cpp
parent2559c629078f738ac37095d896d580b681ac6a30 (diff)
grab from latest android
git-svn-id: http://skia.googlecode.com/svn/trunk@27 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/animator/SkAnimateMaker.cpp')
-rw-r--r--src/animator/SkAnimateMaker.cpp376
1 files changed, 376 insertions, 0 deletions
diff --git a/src/animator/SkAnimateMaker.cpp b/src/animator/SkAnimateMaker.cpp
new file mode 100644
index 0000000000..8a78678247
--- /dev/null
+++ b/src/animator/SkAnimateMaker.cpp
@@ -0,0 +1,376 @@
+/* libs/graphics/animator/SkAnimateMaker.cpp
+**
+** Copyright 2006, The Android Open Source Project
+**
+** 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;
+}