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