1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "SkAnimateBase.h"
11#include "SkAnimateMaker.h"
12#include "SkAnimateProperties.h"
13#include "SkAnimatorScript.h"
14#include "SkDisplayApply.h"
15#include "SkDrawable.h"
16
17#if SK_USE_CONDENSED_INFO == 0
18
19const SkMemberInfo SkAnimateBase::fInfo[] = {
20    SK_MEMBER(begin, MSec),
21    SK_MEMBER_ARRAY(blend, Float),
22    SK_MEMBER(dur, MSec),
23    SK_MEMBER_PROPERTY(dynamic, Boolean),
24    SK_MEMBER(field, String),   // name of member info in target
25    SK_MEMBER(formula, DynamicString),
26    SK_MEMBER(from, DynamicString),
27    SK_MEMBER(lval, DynamicString),
28    SK_MEMBER_PROPERTY(mirror, Boolean),
29    SK_MEMBER(repeat, Float),
30    SK_MEMBER_PROPERTY(reset, Boolean),
31    SK_MEMBER_PROPERTY(step, Int),
32    SK_MEMBER(target, DynamicString),
33    SK_MEMBER(to, DynamicString),
34    SK_MEMBER_PROPERTY(values, DynamicString)
35};
36
37#endif
38
39DEFINE_GET_MEMBER(SkAnimateBase);
40
41SkAnimateBase::SkAnimateBase() : begin(0), dur(1), repeat(SK_Scalar1),
42        fApply(NULL), fFieldInfo(NULL), fFieldOffset(0), fStart((SkMSec) -1), fTarget(NULL),
43        fChanged(0), fDelayed(0), fDynamic(0), fHasEndEvent(0), fHasValues(0),
44        fMirror(0), fReset(0), fResetPending(0), fTargetIsScope(0) {
45    blend.setCount(1);
46    blend[0] = SK_Scalar1;
47}
48
49SkAnimateBase::~SkAnimateBase() {
50    SkDisplayTypes type = fValues.getType();
51    if (type == SkType_String || type == SkType_DynamicString) {
52        SkASSERT(fValues.count() == 1);
53        delete fValues[0].fString;
54    }
55}
56
57int SkAnimateBase::components() {
58    return 1;
59}
60
61SkDisplayable* SkAnimateBase::deepCopy(SkAnimateMaker* maker) {
62    SkAnimateBase* result = (SkAnimateBase*) INHERITED::deepCopy(maker);
63    result->fApply = fApply;
64    result->fFieldInfo =fFieldInfo;
65    result->fHasValues = false;
66    return result;
67}
68
69void SkAnimateBase::dirty() {
70    fChanged = true;
71}
72
73#ifdef SK_DUMP_ENABLED
74void SkAnimateBase::dump(SkAnimateMaker* maker) {
75    dumpBase(maker);
76    if (target.size() > 0)
77        SkDebugf("target=\"%s\" ", target.c_str());
78    else if (fTarget && strcmp(fTarget->id, ""))
79        SkDebugf("target=\"%s\" ", fTarget->id);
80    if (lval.size() > 0)
81        SkDebugf("lval=\"%s\" ", lval.c_str());
82    if (field.size() > 0)
83        SkDebugf("field=\"%s\" ", field.c_str());
84    else if (fFieldInfo)
85        SkDebugf("field=\"%s\" ", fFieldInfo->fName);
86    if (formula.size() > 0)
87        SkDebugf("formula=\"%s\" ", formula.c_str());
88    else {
89        if (from.size() > 0)
90            SkDebugf("from=\"%s\" ", from.c_str());
91        SkDebugf("to=\"%s\" ", to.c_str());
92    }
93    if (begin != 0) {
94        SkDebugf("begin=\"%g\" ", SkScalarToFloat(SkScalarDiv(begin,1000)));
95    }
96}
97#endif
98
99SkDisplayable* SkAnimateBase::getParent() const {
100    return (SkDisplayable*) fApply;
101}
102
103bool SkAnimateBase::getProperty(int index, SkScriptValue* value) const {
104    int boolResult;
105    switch (index) {
106        case SK_PROPERTY(dynamic):
107            boolResult = fDynamic;
108            goto returnBool;
109        case SK_PROPERTY(mirror):
110            boolResult = fMirror;
111            goto returnBool;
112        case SK_PROPERTY(reset):
113            boolResult = fReset;
114returnBool:
115            value->fOperand.fS32 = SkToBool(boolResult);
116            value->fType = SkType_Boolean;
117            break;
118        case SK_PROPERTY(step):
119            if (fApply == NULL)
120                return false;    // !!! notify there's an error?
121            fApply->getStep(value);
122            break;
123        case SK_PROPERTY(values):
124            value->fOperand.fString = (SkString*) &to;
125            value->fType = SkType_String;
126            break;
127        default:
128            SkASSERT(0);
129            return false;
130    }
131    return true;
132}
133
134bool SkAnimateBase::hasExecute() const
135{
136    return false;
137}
138
139void SkAnimateBase::onEndElement(SkAnimateMaker& maker) {
140    fChanged = false;
141    setTarget(maker);
142    if (field.size()) {
143        SkASSERT(fTarget);
144        fFieldInfo = fTarget->getMember(field.c_str());
145        field.reset();
146    }
147    if (lval.size()) {
148        // lval must be of the form x[y]
149        const char* lvalStr = lval.c_str();
150        const char* arrayEnd = strchr(lvalStr, '[');
151        if (arrayEnd == NULL)
152            return; //should this return an error?
153        size_t arrayNameLen = arrayEnd - lvalStr;
154        SkString arrayStr(lvalStr, arrayNameLen);
155        SkASSERT(fTarget);  //this return an error?
156        fFieldInfo = fTarget->getMember(arrayStr.c_str());
157        SkString scriptStr(arrayEnd + 1, lval.size() - arrayNameLen - 2);
158        SkAnimatorScript::EvaluateInt(maker, this, scriptStr.c_str(), &fFieldOffset);
159    }
160}
161
162void SkAnimateBase::packARGB(SkScalar array[], int count, SkTDOperandArray* converted)
163{
164    SkASSERT(count == 4);
165    converted->setCount(1);
166    SkColor color = SkColorSetARGB(SkScalarRoundToInt(array[0]),
167                                   SkScalarRoundToInt(array[1]),
168                                   SkScalarRoundToInt(array[2]),
169                                   SkScalarRoundToInt(array[3]));
170    (*converted)[0].fS32 = color;
171}
172
173
174
175void SkAnimateBase::refresh(SkAnimateMaker& ) {
176}
177
178bool SkAnimateBase::setParent(SkDisplayable* apply) {
179    SkASSERT(apply->isApply());
180    fApply = (SkApply*) apply;
181    return false;
182}
183
184bool SkAnimateBase::setProperty(int index, SkScriptValue& value) {
185    bool boolValue = SkToBool(value.fOperand.fS32);
186    switch (index) {
187        case SK_PROPERTY(dynamic):
188            fDynamic = boolValue;
189            goto checkForBool;
190        case SK_PROPERTY(values):
191            fHasValues = true;
192            SkASSERT(value.fType == SkType_String);
193            to = *value.fOperand.fString;
194            break;
195        case SK_PROPERTY(mirror):
196            fMirror = boolValue;
197            goto checkForBool;
198        case SK_PROPERTY(reset):
199            fReset = boolValue;
200checkForBool:
201            SkASSERT(value.fType == SkType_Boolean);
202            break;
203        default:
204            return false;
205    }
206    return true;
207}
208
209void SkAnimateBase::setTarget(SkAnimateMaker& maker) {
210    if (target.size()) {
211        SkAnimatorScript engine(maker, this, SkType_Displayable);
212        const char* script = target.c_str();
213        SkScriptValue scriptValue;
214        bool success = engine.evaluateScript(&script, &scriptValue);
215        if (success && scriptValue.fType == SkType_Displayable)
216            fTarget = scriptValue.fOperand.fDrawable;
217        else if (maker.find(target.c_str(), (SkDisplayable**) &fTarget) == false) {
218            if (fApply->getMode() == SkApply::kMode_create)
219                return; // may not be an error
220            if (engine.getError() != SkScriptEngine::kNoError)
221                maker.setScriptError(engine);
222            else {
223                maker.setErrorNoun(target);
224                maker.setErrorCode(SkDisplayXMLParserError::kTargetIDNotFound);
225            }
226            return;
227        }
228        if (fApply && fApply->getMode() != SkApply::kMode_create)
229            target.reset();
230    }
231}
232
233bool SkAnimateBase::targetNeedsInitialization() const {
234    return false;
235}
236