michael@0: michael@0: /* michael@0: * Copyright 2006 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: michael@0: #include "SkAnimateBase.h" michael@0: #include "SkAnimateMaker.h" michael@0: #include "SkAnimateProperties.h" michael@0: #include "SkAnimatorScript.h" michael@0: #include "SkDisplayApply.h" michael@0: #include "SkDrawable.h" michael@0: michael@0: #if SK_USE_CONDENSED_INFO == 0 michael@0: michael@0: const SkMemberInfo SkAnimateBase::fInfo[] = { michael@0: SK_MEMBER(begin, MSec), michael@0: SK_MEMBER_ARRAY(blend, Float), michael@0: SK_MEMBER(dur, MSec), michael@0: SK_MEMBER_PROPERTY(dynamic, Boolean), michael@0: SK_MEMBER(field, String), // name of member info in target michael@0: SK_MEMBER(formula, DynamicString), michael@0: SK_MEMBER(from, DynamicString), michael@0: SK_MEMBER(lval, DynamicString), michael@0: SK_MEMBER_PROPERTY(mirror, Boolean), michael@0: SK_MEMBER(repeat, Float), michael@0: SK_MEMBER_PROPERTY(reset, Boolean), michael@0: SK_MEMBER_PROPERTY(step, Int), michael@0: SK_MEMBER(target, DynamicString), michael@0: SK_MEMBER(to, DynamicString), michael@0: SK_MEMBER_PROPERTY(values, DynamicString) michael@0: }; michael@0: michael@0: #endif michael@0: michael@0: DEFINE_GET_MEMBER(SkAnimateBase); michael@0: michael@0: SkAnimateBase::SkAnimateBase() : begin(0), dur(1), repeat(SK_Scalar1), michael@0: fApply(NULL), fFieldInfo(NULL), fFieldOffset(0), fStart((SkMSec) -1), fTarget(NULL), michael@0: fChanged(0), fDelayed(0), fDynamic(0), fHasEndEvent(0), fHasValues(0), michael@0: fMirror(0), fReset(0), fResetPending(0), fTargetIsScope(0) { michael@0: blend.setCount(1); michael@0: blend[0] = SK_Scalar1; michael@0: } michael@0: michael@0: SkAnimateBase::~SkAnimateBase() { michael@0: SkDisplayTypes type = fValues.getType(); michael@0: if (type == SkType_String || type == SkType_DynamicString) { michael@0: SkASSERT(fValues.count() == 1); michael@0: delete fValues[0].fString; michael@0: } michael@0: } michael@0: michael@0: int SkAnimateBase::components() { michael@0: return 1; michael@0: } michael@0: michael@0: SkDisplayable* SkAnimateBase::deepCopy(SkAnimateMaker* maker) { michael@0: SkAnimateBase* result = (SkAnimateBase*) INHERITED::deepCopy(maker); michael@0: result->fApply = fApply; michael@0: result->fFieldInfo =fFieldInfo; michael@0: result->fHasValues = false; michael@0: return result; michael@0: } michael@0: michael@0: void SkAnimateBase::dirty() { michael@0: fChanged = true; michael@0: } michael@0: michael@0: #ifdef SK_DUMP_ENABLED michael@0: void SkAnimateBase::dump(SkAnimateMaker* maker) { michael@0: dumpBase(maker); michael@0: if (target.size() > 0) michael@0: SkDebugf("target=\"%s\" ", target.c_str()); michael@0: else if (fTarget && strcmp(fTarget->id, "")) michael@0: SkDebugf("target=\"%s\" ", fTarget->id); michael@0: if (lval.size() > 0) michael@0: SkDebugf("lval=\"%s\" ", lval.c_str()); michael@0: if (field.size() > 0) michael@0: SkDebugf("field=\"%s\" ", field.c_str()); michael@0: else if (fFieldInfo) michael@0: SkDebugf("field=\"%s\" ", fFieldInfo->fName); michael@0: if (formula.size() > 0) michael@0: SkDebugf("formula=\"%s\" ", formula.c_str()); michael@0: else { michael@0: if (from.size() > 0) michael@0: SkDebugf("from=\"%s\" ", from.c_str()); michael@0: SkDebugf("to=\"%s\" ", to.c_str()); michael@0: } michael@0: if (begin != 0) { michael@0: SkDebugf("begin=\"%g\" ", SkScalarToFloat(SkScalarDiv(begin,1000))); michael@0: } michael@0: } michael@0: #endif michael@0: michael@0: SkDisplayable* SkAnimateBase::getParent() const { michael@0: return (SkDisplayable*) fApply; michael@0: } michael@0: michael@0: bool SkAnimateBase::getProperty(int index, SkScriptValue* value) const { michael@0: int boolResult; michael@0: switch (index) { michael@0: case SK_PROPERTY(dynamic): michael@0: boolResult = fDynamic; michael@0: goto returnBool; michael@0: case SK_PROPERTY(mirror): michael@0: boolResult = fMirror; michael@0: goto returnBool; michael@0: case SK_PROPERTY(reset): michael@0: boolResult = fReset; michael@0: returnBool: michael@0: value->fOperand.fS32 = SkToBool(boolResult); michael@0: value->fType = SkType_Boolean; michael@0: break; michael@0: case SK_PROPERTY(step): michael@0: if (fApply == NULL) michael@0: return false; // !!! notify there's an error? michael@0: fApply->getStep(value); michael@0: break; michael@0: case SK_PROPERTY(values): michael@0: value->fOperand.fString = (SkString*) &to; michael@0: value->fType = SkType_String; michael@0: break; michael@0: default: michael@0: SkASSERT(0); michael@0: return false; michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: bool SkAnimateBase::hasExecute() const michael@0: { michael@0: return false; michael@0: } michael@0: michael@0: void SkAnimateBase::onEndElement(SkAnimateMaker& maker) { michael@0: fChanged = false; michael@0: setTarget(maker); michael@0: if (field.size()) { michael@0: SkASSERT(fTarget); michael@0: fFieldInfo = fTarget->getMember(field.c_str()); michael@0: field.reset(); michael@0: } michael@0: if (lval.size()) { michael@0: // lval must be of the form x[y] michael@0: const char* lvalStr = lval.c_str(); michael@0: const char* arrayEnd = strchr(lvalStr, '['); michael@0: if (arrayEnd == NULL) michael@0: return; //should this return an error? michael@0: size_t arrayNameLen = arrayEnd - lvalStr; michael@0: SkString arrayStr(lvalStr, arrayNameLen); michael@0: SkASSERT(fTarget); //this return an error? michael@0: fFieldInfo = fTarget->getMember(arrayStr.c_str()); michael@0: SkString scriptStr(arrayEnd + 1, lval.size() - arrayNameLen - 2); michael@0: SkAnimatorScript::EvaluateInt(maker, this, scriptStr.c_str(), &fFieldOffset); michael@0: } michael@0: } michael@0: michael@0: void SkAnimateBase::packARGB(SkScalar array[], int count, SkTDOperandArray* converted) michael@0: { michael@0: SkASSERT(count == 4); michael@0: converted->setCount(1); michael@0: SkColor color = SkColorSetARGB(SkScalarRoundToInt(array[0]), michael@0: SkScalarRoundToInt(array[1]), michael@0: SkScalarRoundToInt(array[2]), michael@0: SkScalarRoundToInt(array[3])); michael@0: (*converted)[0].fS32 = color; michael@0: } michael@0: michael@0: michael@0: michael@0: void SkAnimateBase::refresh(SkAnimateMaker& ) { michael@0: } michael@0: michael@0: bool SkAnimateBase::setParent(SkDisplayable* apply) { michael@0: SkASSERT(apply->isApply()); michael@0: fApply = (SkApply*) apply; michael@0: return false; michael@0: } michael@0: michael@0: bool SkAnimateBase::setProperty(int index, SkScriptValue& value) { michael@0: bool boolValue = SkToBool(value.fOperand.fS32); michael@0: switch (index) { michael@0: case SK_PROPERTY(dynamic): michael@0: fDynamic = boolValue; michael@0: goto checkForBool; michael@0: case SK_PROPERTY(values): michael@0: fHasValues = true; michael@0: SkASSERT(value.fType == SkType_String); michael@0: to = *value.fOperand.fString; michael@0: break; michael@0: case SK_PROPERTY(mirror): michael@0: fMirror = boolValue; michael@0: goto checkForBool; michael@0: case SK_PROPERTY(reset): michael@0: fReset = boolValue; michael@0: checkForBool: michael@0: SkASSERT(value.fType == SkType_Boolean); michael@0: break; michael@0: default: michael@0: return false; michael@0: } michael@0: return true; michael@0: } michael@0: michael@0: void SkAnimateBase::setTarget(SkAnimateMaker& maker) { michael@0: if (target.size()) { michael@0: SkAnimatorScript engine(maker, this, SkType_Displayable); michael@0: const char* script = target.c_str(); michael@0: SkScriptValue scriptValue; michael@0: bool success = engine.evaluateScript(&script, &scriptValue); michael@0: if (success && scriptValue.fType == SkType_Displayable) michael@0: fTarget = scriptValue.fOperand.fDrawable; michael@0: else if (maker.find(target.c_str(), (SkDisplayable**) &fTarget) == false) { michael@0: if (fApply->getMode() == SkApply::kMode_create) michael@0: return; // may not be an error michael@0: if (engine.getError() != SkScriptEngine::kNoError) michael@0: maker.setScriptError(engine); michael@0: else { michael@0: maker.setErrorNoun(target); michael@0: maker.setErrorCode(SkDisplayXMLParserError::kTargetIDNotFound); michael@0: } michael@0: return; michael@0: } michael@0: if (fApply && fApply->getMode() != SkApply::kMode_create) michael@0: target.reset(); michael@0: } michael@0: } michael@0: michael@0: bool SkAnimateBase::targetNeedsInitialization() const { michael@0: return false; michael@0: }