| |
| /* |
| * 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 "SkADrawable.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(nullptr), fFieldInfo(nullptr), fFieldOffset(0), fStart((SkMSec) -1), fTarget(nullptr), |
| 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) { |
| SkDebugf("begin=\"%g\" ", begin * 0.001); |
| } |
| } |
| #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 == nullptr) |
| 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 == nullptr) |
| 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(SkScalarRoundToInt(array[0]), |
| SkScalarRoundToInt(array[1]), |
| SkScalarRoundToInt(array[2]), |
| SkScalarRoundToInt(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; |
| } |