OLD | NEW |
| (Empty) |
1 /* libs/graphics/animator/SkAnimatorScript.cpp | |
2 ** | |
3 ** Copyright 2006, The Android Open Source Project | |
4 ** | |
5 ** Licensed under the Apache License, Version 2.0 (the "License"); | |
6 ** you may not use this file except in compliance with the License. | |
7 ** You may obtain a copy of the License at | |
8 ** | |
9 ** http://www.apache.org/licenses/LICENSE-2.0 | |
10 ** | |
11 ** Unless required by applicable law or agreed to in writing, software | |
12 ** distributed under the License is distributed on an "AS IS" BASIS, | |
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 ** See the License for the specific language governing permissions and | |
15 ** limitations under the License. | |
16 */ | |
17 | |
18 #include "SkAnimatorScript.h" | |
19 #include "SkAnimateBase.h" | |
20 #include "SkAnimateMaker.h" | |
21 #include "SkDisplayTypes.h" | |
22 #include "SkExtras.h" | |
23 #include "SkMemberInfo.h" | |
24 #include "SkParse.h" | |
25 | |
26 static const SkDisplayEnumMap gEnumMaps[] = { | |
27 { SkType_AddMode, "indirect|immediate" }, | |
28 { SkType_Align, "left|center|right" }, | |
29 { SkType_ApplyMode, "create|immediate|once" }, | |
30 { SkType_ApplyTransition, "normal|reverse" }, | |
31 { SkType_BitmapEncoding, "jpeg|png" }, | |
32 { SkType_BitmapFormat, "none|A1|A8|Index8|RGB16|RGB32" }, | |
33 { SkType_Boolean, "false|true" }, | |
34 { SkType_Cap, "butt|round|square" }, | |
35 { SkType_EventCode, "none|leftSoftKey|rightSoftKey|home|back|send|end|key0|k
ey1|key2|key3|key4|key5|key6|key7|key8|key9|star|hash|up|down|left|right|OK|volU
p|volDown|camera" }, | |
36 { SkType_EventKind, "none|keyChar|keyPress|keyPressUp|mouseDown|mouseDrag|mo
useMove|mouseUp|onEnd|onLoad|user" }, | |
37 { SkType_EventMode, "deferred|immediate" }, | |
38 { SkType_FillType, "winding|evenOdd" }, | |
39 { SkType_FilterType, "none|bilinear" }, | |
40 { SkType_FontStyle, "normal|bold|italic|boldItalic" }, | |
41 { SkType_FromPathMode, "normal|angle|position" }, | |
42 { SkType_Join, "miter|round|blunt" }, | |
43 { SkType_MaskFilterBlurStyle, "normal|solid|outer|inner" }, | |
44 { SkType_PathDirection, "cw|ccw" }, | |
45 { SkType_Style, "fill|stroke|strokeAndFill" }, | |
46 { SkType_TextBoxAlign, "start|center|end" }, | |
47 { SkType_TextBoxMode, "oneLine|lineBreak" }, | |
48 { SkType_TileMode, "clamp|repeat|mirror" }, | |
49 { SkType_Xfermode, "clear|src|dst|srcOver|dstOver|srcIn|dstIn|srcOut|dstOut|
" | |
50 "srcATop|dstATop|xor|darken|lighten" }, | |
51 }; | |
52 | |
53 static int gEnumMapCount = SK_ARRAY_COUNT(gEnumMaps); | |
54 | |
55 SkAnimatorScript::SkAnimatorScript(SkAnimateMaker& maker, SkDisplayable* working
, SkDisplayTypes type) | |
56 : SkScriptEngine(SkScriptEngine::ToOpType(type)), fMaker(maker), fParent(NUL
L), fWorking(working) | |
57 { | |
58 memberCallBack(EvalMember, (void*) this); | |
59 memberFunctionCallBack(EvalMemberFunction, (void*) this); | |
60 boxCallBack(Box, (void*) this); | |
61 unboxCallBack(Unbox, (void*) &maker); | |
62 propertyCallBack(EvalID, (void*) this); // must be first (entries are prepen
ded, will be last), since it never fails | |
63 propertyCallBack(Infinity, (void*) this); | |
64 propertyCallBack(NaN, (void*) this); | |
65 functionCallBack(Eval, (void*) this); | |
66 functionCallBack(IsFinite, (void*) this); | |
67 functionCallBack(IsNaN, (void*) this); | |
68 if (type == SkType_ARGB) { | |
69 functionCallBack(EvalRGB, (void*) this); | |
70 propertyCallBack(EvalNamedColor, (void*) &maker.fIDs); | |
71 } | |
72 if (SkDisplayType::IsEnum(&maker, type)) { | |
73 // !!! for SpiderMonkey, iterate through the enum values, and map them t
o globals | |
74 const SkDisplayEnumMap& map = GetEnumValues(type); | |
75 propertyCallBack(EvalEnum, (void*) map.fValues); | |
76 } | |
77 for (SkExtras** extraPtr = maker.fExtras.begin(); extraPtr < maker.fExtras.e
nd(); extraPtr++) { | |
78 SkExtras* extra = *extraPtr; | |
79 if (extra->fExtraCallBack) | |
80 propertyCallBack(extra->fExtraCallBack, extra->fExtraStorage); | |
81 } | |
82 } | |
83 | |
84 SkAnimatorScript::~SkAnimatorScript() { | |
85 for (SkDisplayable** dispPtr = fTrackDisplayable.begin(); dispPtr < fTrackDi
splayable.end(); dispPtr++) | |
86 delete *dispPtr; | |
87 } | |
88 | |
89 bool SkAnimatorScript::evaluate(const char* original, SkScriptValue* result, SkD
isplayTypes type) { | |
90 const char* script = original; | |
91 bool success = evaluateScript(&script, result); | |
92 if (success == false || result->fType != type) { | |
93 fMaker.setScriptError(*this); | |
94 return false; | |
95 } | |
96 return true; | |
97 } | |
98 | |
99 bool SkAnimatorScript::Box(void* user, SkScriptValue* scriptValue) { | |
100 SkAnimatorScript* engine = (SkAnimatorScript*) user; | |
101 SkDisplayTypes type = scriptValue->fType; | |
102 SkDisplayable* displayable; | |
103 switch (type) { | |
104 case SkType_Array: { | |
105 SkDisplayArray* boxedValue = new SkDisplayArray(*scriptValue->fOpera
nd.fArray); | |
106 displayable = boxedValue; | |
107 } break; | |
108 case SkType_Boolean: { | |
109 SkDisplayBoolean* boxedValue = new SkDisplayBoolean; | |
110 displayable = boxedValue; | |
111 boxedValue->value = !! scriptValue->fOperand.fS32; | |
112 } break; | |
113 case SkType_Int: { | |
114 SkDisplayInt* boxedValue = new SkDisplayInt; | |
115 displayable = boxedValue; | |
116 boxedValue->value = scriptValue->fOperand.fS32; | |
117 } break; | |
118 case SkType_Float: { | |
119 SkDisplayFloat* boxedValue = new SkDisplayFloat; | |
120 displayable = boxedValue; | |
121 boxedValue->value = scriptValue->fOperand.fScalar; | |
122 } break; | |
123 case SkType_String: { | |
124 SkDisplayString* boxedValue = new SkDisplayString(*scriptValue->fOpe
rand.fString); | |
125 displayable = boxedValue; | |
126 } break; | |
127 case SkType_Displayable: | |
128 scriptValue->fOperand.fObject = scriptValue->fOperand.fDisplayable; | |
129 scriptValue->fType = SkType_Displayable; | |
130 return true; | |
131 default: | |
132 SkASSERT(0); | |
133 return false; | |
134 } | |
135 engine->track(displayable); | |
136 scriptValue->fOperand.fObject = displayable; | |
137 scriptValue->fType = SkType_Displayable; | |
138 return true; | |
139 } | |
140 | |
141 bool SkAnimatorScript::Eval(const char* function, size_t len, SkTDArray<SkScript
Value>& params, | |
142 void* eng, SkScriptValue* value) { | |
143 if (SK_LITERAL_STR_EQUAL("eval", function, len) == false) | |
144 return false; | |
145 if (params.count() != 1) | |
146 return false; | |
147 SkAnimatorScript* host = (SkAnimatorScript*) eng; | |
148 SkAnimatorScript engine(host->fMaker, host->fWorking, SkScriptEngine::ToDisp
layType(host->fReturnType)); | |
149 SkScriptValue* scriptValue = params.begin(); | |
150 bool success = true; | |
151 if (scriptValue->fType == SkType_String) { | |
152 const char* script = scriptValue->fOperand.fString->c_str(); | |
153 success = engine.evaluateScript(&script, value); | |
154 } else | |
155 *value = *scriptValue; | |
156 return success; | |
157 } | |
158 | |
159 bool SkAnimatorScript::EvalEnum(const char* token, size_t len, void* callBack, S
kScriptValue* value) { | |
160 const char* tokens = (const char*) callBack; | |
161 value->fType = SkType_Int; | |
162 if (MapEnums(tokens, token, len, (int*)&value->fOperand.fS32)) | |
163 return true; | |
164 return false; | |
165 } | |
166 | |
167 bool SkAnimatorScript::EvalID(const char* token, size_t len, void* user, SkScrip
tValue* value) { | |
168 SkAnimatorScript* engine = (SkAnimatorScript*) user; | |
169 SkTDict<SkDisplayable*>* ids = &engine->fMaker.fIDs; | |
170 SkDisplayable* displayable; | |
171 bool success = ids->find(token, len, &displayable); | |
172 if (success == false) { | |
173 displayable = engine->fWorking; | |
174 if (SK_LITERAL_STR_EQUAL("parent", token, len)) { | |
175 SkDisplayable* parent = displayable->getParent(); | |
176 if (parent == false) | |
177 parent = engine->fParent; | |
178 if (parent) { | |
179 value->fOperand.fDisplayable = parent; | |
180 value->fType = SkType_Displayable; | |
181 return true; | |
182 } | |
183 } | |
184 if (displayable && EvalMember(token, len, displayable, engine, value)) | |
185 return true; | |
186 value->fOperand.fString = NULL; | |
187 value->fType = SkType_String; | |
188 } else { | |
189 SkDisplayable* working = engine->fWorking; | |
190 value->fOperand.fDisplayable = displayable; | |
191 value->fType = SkType_Displayable; | |
192 if (displayable->canContainDependents() && working && working->isAnimate
()) { | |
193 SkAnimateBase* animator = (SkAnimateBase*) working; | |
194 if (animator->isDynamic()) { | |
195 SkDisplayDepend* depend = (SkDisplayDepend* ) displayable; | |
196 depend->addDependent(working); | |
197 } | |
198 } | |
199 } | |
200 return true; | |
201 } | |
202 | |
203 bool SkAnimatorScript::EvalNamedColor(const char* token, size_t len, void* callb
ack, SkScriptValue* value) { | |
204 value->fType = SkType_Int; | |
205 if (SkParse::FindNamedColor(token, len, (SkColor*) &value->fOperand.fS32) !=
NULL) | |
206 return true; | |
207 return false; | |
208 } | |
209 | |
210 bool SkAnimatorScript::EvalRGB(const char* function, size_t len, SkTDArray<SkScr
iptValue>& params, | |
211 void* eng, SkScriptValue* value) { | |
212 if (SK_LITERAL_STR_EQUAL("rgb", function, len) == false) | |
213 return false; | |
214 if (params.count() != 3) | |
215 return false; | |
216 SkScriptEngine* engine = (SkScriptEngine*) eng; | |
217 unsigned result = 0xFF000000; | |
218 int shift = 16; | |
219 for (SkScriptValue* valuePtr = params.begin(); valuePtr < params.end(); valu
ePtr++) { | |
220 engine->convertTo(SkType_Int, valuePtr); | |
221 result |= SkClampMax(valuePtr->fOperand.fS32, 255) << shift; | |
222 shift -= 8; | |
223 } | |
224 value->fOperand.fS32 = result; | |
225 value->fType = SkType_Int; | |
226 return true; | |
227 } | |
228 | |
229 bool SkAnimatorScript::EvalMemberCommon(SkScriptEngine* engine, const SkMemberIn
fo* info, | |
230 SkDisplayable* displayable, SkScriptValue* value) { | |
231 SkDisplayTypes original; | |
232 SkDisplayTypes type = original = (SkDisplayTypes) info->getType(); | |
233 if (info->fType == SkType_Array) | |
234 type = SkType_Array; | |
235 switch (type) { | |
236 case SkType_ARGB: | |
237 type = SkType_Int; | |
238 case SkType_Boolean: | |
239 case SkType_Int: | |
240 case SkType_MSec: | |
241 case SkType_Float: | |
242 SkASSERT(info->getCount() == 1); | |
243 if (info->fType != SkType_MemberProperty && info->fType != SkType_Me
mberFunction) | |
244 value->fOperand.fS32 = *(int32_t*) info->memberData(displayable)
; // OK for SkScalar too | |
245 if (type == SkType_MSec) { | |
246 value->fOperand.fScalar = SkScalarDiv((SkScalar) value->fOperand
.fS32, 1000); // dividing two ints is the same as dividing two scalars | |
247 type = SkType_Float; | |
248 } | |
249 break; | |
250 case SkType_String: { | |
251 SkString* displayableString; | |
252 if (info->fType != SkType_MemberProperty && info->fType != SkType_Me
mberFunction) { | |
253 info->getString(displayable, &displayableString); | |
254 value->fOperand.fString = new SkString(*displayableString); | |
255 } | |
256 } break; | |
257 case SkType_Array: { | |
258 SkASSERT(info->fType != SkType_MemberProperty); // !!! incomplete | |
259 SkTDOperandArray* displayableArray = (SkTDOperandArray*) info->membe
rData(displayable); | |
260 if (displayable->getType() == SkType_Array) { | |
261 SkDisplayArray* typedArray = (SkDisplayArray*) displayable; | |
262 original = typedArray->values.getType(); | |
263 } | |
264 SkASSERT(original != SkType_Unknown); | |
265 SkTypedArray* array = value->fOperand.fArray = new SkTypedArray(orig
inal); | |
266 engine->track(array); | |
267 int count = displayableArray->count(); | |
268 if (count > 0) { | |
269 array->setCount(count); | |
270 memcpy(array->begin(), displayableArray->begin(), count * sizeof
(SkOperand)); | |
271 } | |
272 } break; | |
273 default: | |
274 SkASSERT(0); // unimplemented | |
275 } | |
276 value->fType = type; | |
277 return true; | |
278 } | |
279 | |
280 bool SkAnimatorScript::EvalMember(const char* member, size_t len, void* object,
void* eng, | |
281 SkScriptValue* value) { | |
282 SkScriptEngine* engine = (SkScriptEngine*) eng; | |
283 SkDisplayable* displayable = (SkDisplayable*) object; | |
284 SkString name(member, len); | |
285 SkDisplayable* named = displayable->contains(name); | |
286 if (named) { | |
287 value->fOperand.fDisplayable = named; | |
288 value->fType = SkType_Displayable; | |
289 return true; | |
290 } | |
291 const SkMemberInfo* info = displayable->getMember(name.c_str()); | |
292 if (info == NULL) | |
293 return false; | |
294 if (info->fType == SkType_MemberProperty) { | |
295 if (displayable->getProperty(info->propertyIndex(), value) == false) { | |
296 SkASSERT(0); | |
297 return false; | |
298 } | |
299 } | |
300 return EvalMemberCommon(engine, info, displayable, value); | |
301 } | |
302 | |
303 bool SkAnimatorScript::EvalMemberFunction(const char* member, size_t len, void*
object, | |
304 SkTDArray<SkScriptValue>& params, void* eng, SkScriptValue* value) { | |
305 SkScriptEngine* engine = (SkScriptEngine*) eng; | |
306 SkDisplayable* displayable = (SkDisplayable*) object; | |
307 SkString name(member, len); | |
308 const SkMemberInfo* info = displayable->getMember(name.c_str()); | |
309 SkASSERT(info != NULL); /* !!! error handling unimplemented */ | |
310 if (info->fType != SkType_MemberFunction) { | |
311 SkASSERT(0); | |
312 return false; | |
313 } | |
314 displayable->executeFunction(displayable, info->functionIndex(), params, inf
o->getType(), | |
315 value); | |
316 return EvalMemberCommon(engine, info, displayable, value); | |
317 } | |
318 | |
319 bool SkAnimatorScript::EvaluateDisplayable(SkAnimateMaker& maker, SkDisplayable*
displayable, const char* script, SkDisplayable** result) { | |
320 SkAnimatorScript engine(maker, displayable, SkType_Displayable); | |
321 SkScriptValue value; | |
322 bool success = engine.evaluate(script, &value, SkType_Displayable); | |
323 if (success) | |
324 *result = value.fOperand.fDisplayable; | |
325 return success; | |
326 } | |
327 | |
328 bool SkAnimatorScript::EvaluateInt(SkAnimateMaker& maker, SkDisplayable* display
able, const char* script, int32_t* result) { | |
329 SkAnimatorScript engine(maker, displayable, SkType_Int); | |
330 SkScriptValue value; | |
331 bool success = engine.evaluate(script, &value, SkType_Int); | |
332 if (success) | |
333 *result = value.fOperand.fS32; | |
334 return success; | |
335 } | |
336 | |
337 bool SkAnimatorScript::EvaluateFloat(SkAnimateMaker& maker, SkDisplayable* displ
ayable, const char* script, SkScalar* result) { | |
338 SkAnimatorScript engine(maker, displayable, SkType_Float); | |
339 SkScriptValue value; | |
340 bool success = engine.evaluate(script, &value, SkType_Float); | |
341 if (success) | |
342 *result = value.fOperand.fScalar; | |
343 return success; | |
344 } | |
345 | |
346 bool SkAnimatorScript::EvaluateString(SkAnimateMaker& maker, SkDisplayable* disp
layable, const char* script, SkString* result) { | |
347 SkAnimatorScript engine(maker, displayable, SkType_String); | |
348 SkScriptValue value; | |
349 bool success = engine.evaluate(script, &value, SkType_String); | |
350 if (success) | |
351 result->set(*(value.fOperand.fString)); | |
352 return success; | |
353 } | |
354 | |
355 bool SkAnimatorScript::EvaluateString(SkAnimateMaker& maker, SkDisplayable* disp
layable, SkDisplayable* parent, const char* script, SkString* result) { | |
356 SkAnimatorScript engine(maker, displayable, SkType_String); | |
357 engine.fParent = parent; | |
358 SkScriptValue value; | |
359 bool success = engine.evaluate(script, &value, SkType_String); | |
360 if (success) | |
361 result->set(*(value.fOperand.fString)); | |
362 return success; | |
363 } | |
364 | |
365 const SkDisplayEnumMap& SkAnimatorScript::GetEnumValues(SkDisplayTypes type) { | |
366 int index = SkTSearch<SkDisplayTypes>(&gEnumMaps[0].fType, gEnumMapCount, ty
pe, | |
367 sizeof(SkDisplayEnumMap)); | |
368 SkASSERT(index >= 0); | |
369 return gEnumMaps[index]; | |
370 } | |
371 | |
372 bool SkAnimatorScript::Infinity(const char* token, size_t len, void* user, SkScr
iptValue* value) { | |
373 if (SK_LITERAL_STR_EQUAL("Infinity", token, len) == false) | |
374 return false; | |
375 value->fType = SkType_Float; | |
376 value->fOperand.fScalar = SK_ScalarInfinity; | |
377 return true; | |
378 } | |
379 | |
380 bool SkAnimatorScript::IsFinite(const char* function, size_t len, SkTDArray<SkSc
riptValue>& params, | |
381 void* eng, SkScriptValue* value) { | |
382 if (SK_LITERAL_STR_EQUAL(function, "isFinite", len) == false) | |
383 return false; | |
384 if (params.count() != 1) | |
385 return false; | |
386 SkScriptValue* scriptValue = params.begin(); | |
387 SkDisplayTypes type = scriptValue->fType; | |
388 SkScalar scalar = scriptValue->fOperand.fScalar; | |
389 value->fType = SkType_Int; | |
390 value->fOperand.fS32 = type == SkType_Float ? SkScalarIsNaN(scalar) == false
&& | |
391 SkScalarAbs(scalar) != SK_ScalarInfinity : type == SkType_Int; | |
392 return true; | |
393 } | |
394 | |
395 bool SkAnimatorScript::IsNaN(const char* function, size_t len, SkTDArray<SkScrip
tValue>& params, | |
396 void* eng, SkScriptValue* value) { | |
397 if (SK_LITERAL_STR_EQUAL("isNaN", function, len) == false) | |
398 return false; | |
399 if (params.count() != 1) | |
400 return false; | |
401 SkScriptValue* scriptValue = params.begin(); | |
402 value->fType = SkType_Int; | |
403 value->fOperand.fS32 = scriptValue->fType == SkType_Float ? SkScalarIsNaN(sc
riptValue->fOperand.fScalar) : 0; | |
404 return true; | |
405 } | |
406 | |
407 bool SkAnimatorScript::MapEnums(const char* ptr, const char* match, size_t len,
int* value) { | |
408 int index = 0; | |
409 bool more = true; | |
410 do { | |
411 const char* last = strchr(ptr, '|'); | |
412 if (last == NULL) { | |
413 last = &ptr[strlen(ptr)]; | |
414 more = false; | |
415 } | |
416 size_t length = last - ptr; | |
417 if (len == length && strncmp(ptr, match, length) == 0) { | |
418 *value = index; | |
419 return true; | |
420 } | |
421 index++; | |
422 ptr = last + 1; | |
423 } while (more); | |
424 return false; | |
425 } | |
426 | |
427 bool SkAnimatorScript::NaN(const char* token, size_t len, void* user, SkScriptVa
lue* value) { | |
428 if (SK_LITERAL_STR_EQUAL("NaN", token, len) == false) | |
429 return false; | |
430 value->fType = SkType_Float; | |
431 value->fOperand.fScalar = SK_ScalarNaN; | |
432 return true; | |
433 } | |
434 | |
435 #if 0 | |
436 bool SkAnimatorScript::ObjectToString(void* object, void* user, SkScriptValue* v
alue) { | |
437 SkTDict<SkDisplayable*>* ids = (SkTDict<SkDisplayable*>*) user; | |
438 SkDisplayable* displayable = (SkDisplayable*) object; | |
439 const char* key; | |
440 bool success = ids->findKey(displayable, &key); | |
441 if (success == false) | |
442 return false; | |
443 value->fOperand.fString = new SkString(key); | |
444 value->fType = SkType_String; | |
445 return true; | |
446 } | |
447 #endif | |
448 | |
449 bool SkAnimatorScript::Unbox(void* m, SkScriptValue* scriptValue) { | |
450 SkAnimateMaker* maker = (SkAnimateMaker*) m; | |
451 SkASSERT((unsigned) scriptValue->fType == (unsigned) SkType_Displayable); | |
452 SkDisplayable* displayable = (SkDisplayable*) scriptValue->fOperand.fObject; | |
453 SkDisplayTypes type = displayable->getType(); | |
454 switch (displayable->getType()) { | |
455 case SkType_Array: { | |
456 SkDisplayArray* boxedValue = (SkDisplayArray*) displayable; | |
457 scriptValue->fOperand.fArray = &boxedValue->values; | |
458 } break; | |
459 case SkType_Boolean: { | |
460 SkDisplayBoolean* boxedValue = (SkDisplayBoolean*) displayable; | |
461 scriptValue->fOperand.fS32 = boxedValue->value; | |
462 } break; | |
463 case SkType_Int: { | |
464 SkDisplayInt* boxedValue = (SkDisplayInt*) displayable; | |
465 scriptValue->fOperand.fS32 = boxedValue->value; | |
466 } break; | |
467 case SkType_Float: { | |
468 SkDisplayFloat* boxedValue = (SkDisplayFloat*) displayable; | |
469 scriptValue->fOperand.fScalar = boxedValue->value; | |
470 } break; | |
471 case SkType_String: { | |
472 SkDisplayString* boxedValue = (SkDisplayString*) displayable; | |
473 scriptValue->fOperand.fString = SkNEW_ARGS(SkString, (boxedValue->va
lue)); | |
474 } break; | |
475 default: { | |
476 const char* id; | |
477 bool success = maker->findKey(displayable, &id); | |
478 SkASSERT(success); | |
479 scriptValue->fOperand.fString = SkNEW_ARGS(SkString, (id)); | |
480 type = SkType_String; | |
481 } | |
482 } | |
483 scriptValue->fType = type; | |
484 return true; | |
485 } | |
486 | |
487 #if defined SK_SUPPORT_UNITTEST | |
488 | |
489 #include "SkAnimator.h" | |
490 | |
491 static const char scriptTestSetup[] = | |
492 "<screenplay>\n" | |
493 "<text id='label' text='defg'/>\n" | |
494 "<add id='addLabel' use='label'/>\n" | |
495 "<text id='text1' text='test'/>\n" | |
496 "<apply scope='addLabel'>\n" | |
497 "<set target='label' field='text' to='#script:text1.text'/>\n" | |
498 "</apply>\n" | |
499 "<apply>\n" | |
500 "<paint id='labelPaint'>\n" | |
501 "<emboss id='emboss' direction='[1,1,1]' />\n" | |
502 "</paint>\n" | |
503 "<animate id='animation' field='direction' target='emboss' from='[1,1,1]
' to='[-1,1,1]' dur='1'/>\n" | |
504 "<set lval='direction[0]' target='emboss' to='-1' />\n" | |
505 "</apply>\n" | |
506 "<color id='testColor' color='0 ? rgb(0,0,0) : rgb(255,255,255)' />\n" | |
507 "<color id='xColor' color='rgb(12,34,56)' />\n" | |
508 "<array id='emptyArray' />\n" | |
509 "<array id='intArray' values='[1, 4, 6]' />\n" | |
510 "<int id='idx' value='2' />\n" | |
511 "<int id='idy' value='2' />\n" | |
512 "<string id='alpha' value='abc' />\n" | |
513 "<rect id='testRect' left='Math.cos(0)' top='2' right='12' bottom='5' />\n" | |
514 "<event id='evt'>\n" | |
515 "<input name='x' />\n" | |
516 "<apply scope='idy'>\n" | |
517 "<set field='value' to='evt.x.int' />\n" | |
518 "</apply>\n" | |
519 "</event>\n" | |
520 "</screenplay>"; | |
521 | |
522 #if !defined(SK_BUILD_FOR_BREW) | |
523 | |
524 #define DEFAULT_ANSWER , 0 | |
525 | |
526 static const SkScriptNAnswer scriptTests[] = { | |
527 { "label.text.length == 4", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, | |
528 // { "labelPaint.measureText(label.text) > 0 ? labelPaint.measureText(label.tex
t)+10 : 40", SkType_Float, 0, SkIntToScalar(0x23) }, | |
529 { "Number.POSITIVE_INFINITY >= Number.MAX_VALUE ? 1 : 0", SkType_Int, 1 DE
FAULT_ANSWER DEFAULT_ANSWER }, | |
530 { "Infinity >= Number.MAX_VALUE ? 1 : 0", SkType_Int, 1 DEFAULT_ANSWER DEF
AULT_ANSWER }, | |
531 { "Number.NEGATIVE_INFINITY <= -Number.MAX_VALUE ? 1 : 0", SkType_Int, 1 D
EFAULT_ANSWER DEFAULT_ANSWER }, | |
532 { "Number.MIN_VALUE > 0 ? 1 : 0", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANS
WER }, | |
533 { "isNaN(Number.NaN)", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, | |
534 { "isNaN(NaN)", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, | |
535 { "Math.sin(0)", SkType_Float, 0, SkIntToScalar(0) DEFAULT_ANSWER }, | |
536 { "alpha+alpha", SkType_String, 0, 0, "abcabc" }, | |
537 { "intArray[4]", SkType_Unknown DEFAULT_ANSWER DEFAULT_ANSWER DEFAULT_ANSW
ER }, | |
538 { "emptyArray[4]", SkType_Unknown DEFAULT_ANSWER DEFAULT_ANSWER DEFAULT_AN
SWER }, | |
539 { "idx", SkType_Int, 2 DEFAULT_ANSWER DEFAULT_ANSWER }, | |
540 { "intArray.length", SkType_Int, 3 DEFAULT_ANSWER DEFAULT_ANSWER }, | |
541 { "intArray.values[0]", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, | |
542 { "intArray[0]", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, | |
543 { "idx.value", SkType_Int, 2 DEFAULT_ANSWER DEFAULT_ANSWER }, | |
544 { "alpha.value", SkType_String, 0, 0, "abc" }, | |
545 { "alpha", SkType_String, 0, 0, "abc" }, | |
546 { "alpha.value+alpha.value", SkType_String, 0, 0, "abcabc" }, | |
547 { "alpha+idx", SkType_String, 0, 0, "abc2" }, | |
548 { "idx+alpha", SkType_String, 0, 0, "2abc" }, | |
549 { "intArray[idx]", SkType_Int, 6 DEFAULT_ANSWER DEFAULT_ANSWER }, | |
550 { "alpha.slice(1,2)", SkType_String, 0, 0, "b" }, | |
551 { "alpha.value.slice(1,2)", SkType_String, 0, 0, "b" }, | |
552 { "testRect.left+2", SkType_Float, 0, SkIntToScalar(3) DEFAULT_ANSWER }, | |
553 { "0 ? Math.sin(0) : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, | |
554 { "0 ? intArray[0] : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, | |
555 { "0 ? intArray.values[0] : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWE
R }, | |
556 { "0 ? idx : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, | |
557 { "0 ? idx.value : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, | |
558 { "0 ? alpha.slice(1,2) : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER
}, | |
559 { "0 ? alpha.value.slice(1,2) : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_A
NSWER }, | |
560 { "idy", SkType_Int, 3 DEFAULT_ANSWER DEFAULT_ANSWER } | |
561 }; | |
562 #endif | |
563 | |
564 #define SkScriptNAnswer_testCount SK_ARRAY_COUNT(scriptTests) | |
565 | |
566 void SkAnimatorScript::UnitTest() { | |
567 #if !defined(SK_BUILD_FOR_BREW) && defined(SK_SUPPORT_UNITTEST) | |
568 SkAnimator animator; | |
569 SkASSERT(animator.decodeMemory(scriptTestSetup, sizeof(scriptTestSetup)-1)); | |
570 SkEvent evt; | |
571 evt.setString("id", "evt"); | |
572 evt.setS32("x", 3); | |
573 animator.doUserEvent(evt); | |
574 // set up animator with memory script above, then run value tests | |
575 for (unsigned index = 0; index < SkScriptNAnswer_testCount; index++) { | |
576 SkAnimatorScript engine(*animator.fMaker, NULL, scriptTests[index].fType
); | |
577 SkScriptValue value; | |
578 const char* script = scriptTests[index].fScript; | |
579 bool success = engine.evaluateScript(&script, &value); | |
580 if (success == false) { | |
581 SkDebugf("script failed: %s\n", scriptTests[index].fScript); | |
582 SkASSERT(scriptTests[index].fType == SkType_Unknown); | |
583 continue; | |
584 } | |
585 SkASSERT(value.fType == scriptTests[index].fType); | |
586 SkScalar error; | |
587 switch (value.fType) { | |
588 case SkType_Int: | |
589 SkASSERT(value.fOperand.fS32 == scriptTests[index].fIntAnswer); | |
590 break; | |
591 case SkType_Float: | |
592 error = SkScalarAbs(value.fOperand.fScalar - scriptTests[index].
fScalarAnswer); | |
593 SkASSERT(error < SK_Scalar1 / 10000); | |
594 break; | |
595 case SkType_String: | |
596 SkASSERT(strcmp(value.fOperand.fString->c_str(), scriptTests[ind
ex].fStringAnswer) == 0); | |
597 break; | |
598 default: | |
599 SkASSERT(0); | |
600 } | |
601 } | |
602 #endif | |
603 } | |
604 | |
605 #endif | |
606 | |
607 | |
OLD | NEW |