OLD | NEW |
| (Empty) |
1 #include "SkAnimatorScript2.h" | |
2 #include "SkAnimateBase.h" | |
3 #include "SkAnimateMaker.h" | |
4 #include "SkDisplayTypes.h" | |
5 #include "SkExtras.h" | |
6 #include "SkMemberInfo.h" | |
7 #include "SkOpArray.h" | |
8 #include "SkParse.h" | |
9 #include "SkScript2.h" | |
10 #include "SkScriptCallBack.h" | |
11 | |
12 static const SkDisplayEnumMap gEnumMaps[] = { | |
13 { SkType_AddMode, "indirect|immediate" }, | |
14 { SkType_Align, "left|center|right" }, | |
15 { SkType_ApplyMode, "immediate|once" }, | |
16 { SkType_ApplyTransition, "reverse" }, | |
17 { SkType_BitmapEncoding, "jpeg|png" }, | |
18 { SkType_BitmapFormat, "none|A1|A8|Index8|RGB16|RGB32" }, | |
19 { SkType_Boolean, "false|true" }, | |
20 { SkType_Cap, "butt|round|square" }, | |
21 { SkType_EventCode, "none|up|down|left|right|back|end|OK|send|leftSoftKe
y|rightSoftKey|key0|key1|key2|key3|key4|key5|key6|key7|key8|key9|star|hash" }, | |
22 { SkType_EventKind, "none|keyChar|keyPress|mouseDown|mouseDrag|mouseMove
|mouseUp|onEnd|onLoad|user" }, | |
23 { SkType_EventMode, "deferred|immediate" }, | |
24 { SkType_FillType, "winding|evenOdd" }, | |
25 { SkType_FilterType, "none|bilinear" }, | |
26 { SkType_FromPathMode, "normal|angle|position" }, | |
27 { SkType_Join, "miter|round|blunt" }, | |
28 { SkType_MaskFilterBlurStyle, "normal|solid|outer|inner" }, | |
29 { SkType_PathDirection, "cw|ccw" }, | |
30 { SkType_Style, "fill|stroke|strokeAndFill" }, | |
31 { SkType_TextBoxAlign, "start|center|end" }, | |
32 { SkType_TextBoxMode, "oneLine|lineBreak" }, | |
33 { SkType_TileMode, "clamp|repeat|mirror" }, | |
34 { SkType_Xfermode, "clear|src|dst|srcOver|dstOver|srcIn|dstIn|srcOut|dst
Out|" | |
35 "srcATop|dstATop|xor|darken|lighten" }, | |
36 }; | |
37 | |
38 static int gEnumMapCount = SK_ARRAY_COUNT(gEnumMaps); | |
39 | |
40 | |
41 class SkAnimatorScript_Box : public SkScriptCallBackConvert { | |
42 public: | |
43 SkAnimatorScript_Box() {} | |
44 | |
45 ~SkAnimatorScript_Box() { | |
46 for (SkDisplayable** dispPtr = fTrackDisplayable.begin(); dispPt
r < fTrackDisplayable.end(); dispPtr++) | |
47 delete *dispPtr; | |
48 } | |
49 | |
50 virtual bool convert(SkOperand2::OpType type, SkOperand2* operand) { | |
51 SkDisplayable* displayable; | |
52 switch (type) { | |
53 case SkOperand2::kArray: { | |
54 SkDisplayArray* boxedValue = new SkDisplayArray(
*operand->fArray); | |
55 displayable = boxedValue; | |
56 } break; | |
57 case SkOperand2::kS32: { | |
58 SkDisplayInt* boxedValue = new SkDisplayInt; | |
59 displayable = boxedValue; | |
60 boxedValue->value = operand->fS32; | |
61 } break; | |
62 case SkOperand2::kScalar: { | |
63 SkDisplayFloat* boxedValue = new SkDisplayFloat; | |
64 displayable = boxedValue; | |
65 boxedValue->value = operand->fScalar; | |
66 } break; | |
67 case SkOperand2::kString: { | |
68 SkDisplayString* boxedValue = new SkDisplayStrin
g(*operand->fString); | |
69 displayable = boxedValue; | |
70 } break; | |
71 case SkOperand2::kObject: | |
72 return true; | |
73 default: | |
74 SkASSERT(0); | |
75 return false; | |
76 } | |
77 track(displayable); | |
78 operand->fObject = (void*) displayable; | |
79 return true; | |
80 } | |
81 | |
82 virtual SkOperand2::OpType getReturnType(int index) { | |
83 return SkOperand2::kObject; | |
84 } | |
85 | |
86 virtual Type getType() const { | |
87 return kBox; | |
88 } | |
89 | |
90 void track(SkDisplayable* displayable) { | |
91 SkASSERT(fTrackDisplayable.find(displayable) < 0); | |
92 *fTrackDisplayable.append() = displayable; | |
93 } | |
94 | |
95 SkTDDisplayableArray fTrackDisplayable; | |
96 }; | |
97 | |
98 | |
99 class SkAnimatorScript_Enum : public SkScriptCallBackProperty { | |
100 public: | |
101 SkAnimatorScript_Enum(const char* tokens) : fTokens(tokens) {} | |
102 | |
103 virtual bool getConstValue(const char* name, int len, SkOperand2* value)
{ | |
104 return SkAnimatorScript2::MapEnums(fTokens, name, len, &value->f
S32); | |
105 } | |
106 | |
107 private: | |
108 const char* fTokens; | |
109 }; | |
110 | |
111 // !!! if type is string, call invoke | |
112 // if any other type, return original value | |
113 // distinction is undone: could do this by returning index == 0
only if param is string | |
114 // still, caller of getParamTypes will attempt to convert param
to string (I guess) | |
115 class SkAnimatorScript_Eval : public SkScriptCallBackFunction { | |
116 public: | |
117 SkAnimatorScript_Eval(SkAnimatorScript2* engine) : fEngine(engine) {} | |
118 | |
119 virtual bool getIndex(const char* name, int len, size_t* result) { | |
120 if (SK_LITERAL_STR_EQUAL("eval", name, len) != 0) | |
121 return false; | |
122 *result = 0; | |
123 return true; | |
124 } | |
125 | |
126 virtual void getParamTypes(SkIntArray(SkOperand2::OpType)* types) { | |
127 types->setCount(1); | |
128 SkOperand2::OpType* type = types->begin(); | |
129 type[0] = SkOperand2::kString; | |
130 } | |
131 | |
132 virtual bool invoke(size_t index, SkOpArray* params, SkOperand2* answer)
{ | |
133 SkAnimatorScript2 engine(fEngine->getMaker(), fEngine->getWorkin
g(), | |
134 SkAnimatorScript2::ToDisplayType(fEngine->getReturnType(
))); | |
135 SkOperand2* op = params->begin(); | |
136 const char* script = op->fString->c_str(); | |
137 SkScriptValue2 value; | |
138 return engine.evaluateScript(&script, &value); | |
139 SkASSERT(value.fType == fEngine->getReturnType()); | |
140 *answer = value.fOperand; | |
141 // !!! incomplete ? | |
142 return true; | |
143 } | |
144 | |
145 private: | |
146 SkAnimatorScript2* fEngine; | |
147 }; | |
148 | |
149 class SkAnimatorScript_ID : public SkScriptCallBackProperty { | |
150 public: | |
151 SkAnimatorScript_ID(SkAnimatorScript2* engine) : fEngine(engine) {} | |
152 | |
153 virtual bool getIndex(const char* token, int len, size_t* result) { | |
154 SkDisplayable* displayable; | |
155 bool success = fEngine->getMaker().find(token, len, &displayable
); | |
156 if (success == false) { | |
157 *result = 0; | |
158 } else { | |
159 *result = (size_t) displayable; | |
160 SkDisplayable* working = fEngine->getWorking(); | |
161 if (displayable->canContainDependents() && working && wo
rking->isAnimate()) { | |
162 SkAnimateBase* animator = (SkAnimateBase*) worki
ng; | |
163 if (animator->isDynamic()) { | |
164 SkDisplayDepend* depend = (SkDisplayDepe
nd* ) displayable; | |
165 depend->addDependent(working); | |
166 } | |
167 } | |
168 } | |
169 return true; | |
170 } | |
171 | |
172 virtual bool getResult(size_t ref, SkOperand2* answer) { | |
173 answer->fObject = (void*) ref; | |
174 return true; | |
175 } | |
176 | |
177 virtual SkOperand2::OpType getReturnType(size_t index) { | |
178 return index == 0 ? SkOperand2::kString : SkOperand2::kObject; | |
179 } | |
180 | |
181 private: | |
182 SkAnimatorScript2* fEngine; | |
183 }; | |
184 | |
185 | |
186 class SkAnimatorScript_Member : public SkScriptCallBackMember { | |
187 public: | |
188 | |
189 SkAnimatorScript_Member(SkAnimatorScript2* engine) : fEngine(engine) {} | |
190 | |
191 bool getMemberReference(const char* member, size_t len, void* object, Sk
ScriptValue2* ref) { | |
192 SkDisplayable* displayable = (SkDisplayable*) object; | |
193 SkString name(member, len); | |
194 SkDisplayable* named = displayable->contains(name); | |
195 if (named) { | |
196 ref->fType = SkOperand2::kObject; | |
197 ref->fOperand.fObject = named; | |
198 return true; | |
199 } | |
200 const SkMemberInfo* info = displayable->getMember(name.c_str()); | |
201 if (info == NULL) | |
202 return false; // !!! add additional error info? | |
203 ref->fType = SkAnimatorScript2::ToOpType(info->getType()); | |
204 ref->fOperand.fObject = (void*) info; | |
205 return true; | |
206 } | |
207 | |
208 bool invoke(size_t ref, void* object, SkOperand2* value) { | |
209 const SkMemberInfo* info = (const SkMemberInfo* ) ref; | |
210 SkDisplayable* displayable = (SkDisplayable*) object; | |
211 if (info->fType == SkType_MemberProperty) { | |
212 if (displayable->getProperty2(info->propertyIndex(), val
ue) == false) { | |
213 return false; | |
214 } | |
215 } | |
216 return fEngine->evalMemberCommon(info, displayable, value); | |
217 } | |
218 | |
219 SkAnimatorScript2* fEngine; | |
220 }; | |
221 | |
222 | |
223 class SkAnimatorScript_MemberFunction : public SkScriptCallBackMemberFunction { | |
224 public: | |
225 SkAnimatorScript_MemberFunction(SkAnimatorScript2* engine) : fEngine(eng
ine) {} | |
226 | |
227 bool getMemberReference(const char* member, size_t len, void* object, Sk
ScriptValue2* ref) { | |
228 SkDisplayable* displayable = (SkDisplayable*) object; | |
229 SkString name(member, len); | |
230 const SkMemberInfo* info = displayable->getMember(name.c_str()); | |
231 if (info == NULL || info->fType != SkType_MemberFunction) | |
232 return false; // !!! add additional error info? | |
233 ref->fType = SkAnimatorScript2::ToOpType(info->getType()); | |
234 ref->fOperand.fObject = (void*) info; | |
235 return true; | |
236 } | |
237 | |
238 virtual void getParamTypes(SkIntArray(SkOperand2::OpType)* types) { | |
239 types->setCount(3); | |
240 SkOperand2::OpType* type = types->begin(); | |
241 type[0] = type[1] = type[2] = SkOperand2::kS32; | |
242 } | |
243 | |
244 bool invoke(size_t ref, void* object, SkOpArray* params, SkOperand2* val
ue) | |
245 { | |
246 const SkMemberInfo* info = (const SkMemberInfo* ) ref; | |
247 SkDisplayable* displayable = (SkDisplayable*) object; | |
248 displayable->executeFunction2(displayable, info->functionIndex()
, params, info->getType(), | |
249 value); | |
250 return fEngine->evalMemberCommon(info, displayable, value); | |
251 } | |
252 | |
253 SkAnimatorScript2* fEngine; | |
254 }; | |
255 | |
256 | |
257 class SkAnimatorScript_NamedColor : public SkScriptCallBackProperty { | |
258 public: | |
259 virtual bool getConstValue(const char* name, int len, SkOperand2* value)
{ | |
260 return SkParse::FindNamedColor(name, len, (SkColor*) &value->fS3
2) != NULL; | |
261 } | |
262 }; | |
263 | |
264 | |
265 class SkAnimatorScript_RGB : public SkScriptCallBackFunction { | |
266 public: | |
267 virtual bool getIndex(const char* name, int len, size_t* result) { | |
268 if (SK_LITERAL_STR_EQUAL("rgb", name, len) != 0) | |
269 return false; | |
270 *result = 0; | |
271 return true; | |
272 } | |
273 | |
274 virtual void getParamTypes(SkIntArray(SkOperand2::OpType)* types) { | |
275 types->setCount(3); | |
276 SkOperand2::OpType* type = types->begin(); | |
277 type[0] = type[1] = type[2] = SkOperand2::kS32; | |
278 } | |
279 | |
280 virtual bool invoke(size_t index, SkOpArray* params, SkOperand2* answer)
{ | |
281 SkASSERT(index == 0); | |
282 unsigned result = 0xFF000000; | |
283 int shift = 16; | |
284 for (int index = 0; index < 3; index++) { | |
285 result |= SkClampMax(params->begin()[index].fS32, 255) <
< shift; | |
286 shift -= 8; | |
287 } | |
288 answer->fS32 = result; | |
289 return true; | |
290 } | |
291 | |
292 }; | |
293 | |
294 | |
295 class SkAnimatorScript_Unbox : public SkScriptCallBackConvert { | |
296 public: | |
297 SkAnimatorScript_Unbox(SkAnimatorScript2* engine) : fEngine(engine) {} | |
298 | |
299 virtual bool convert(SkOperand2::OpType type, SkOperand2* operand) { | |
300 SkASSERT(type == SkOperand2::kObject); | |
301 SkDisplayable* displayable = (SkDisplayable*) operand->fObject; | |
302 switch (displayable->getType()) { | |
303 case SkType_Array: { | |
304 SkDisplayArray* boxedValue = (SkDisplayArray*) d
isplayable; | |
305 operand->fArray = new SkOpArray(SkAnimatorScript
2::ToOpType(boxedValue->values.getType())); | |
306 int count = boxedValue->values.count(); | |
307 operand->fArray->setCount(count); | |
308 memcpy(operand->fArray->begin(), boxedValue->val
ues.begin(), count * sizeof(SkOperand2)); | |
309 fEngine->track(operand->fArray); | |
310 } break; | |
311 case SkType_Boolean: { | |
312 SkDisplayBoolean* boxedValue = (SkDisplayBoolean
*) displayable; | |
313 operand->fS32 = boxedValue->value; | |
314 } break; | |
315 case SkType_Int: { | |
316 SkDisplayInt* boxedValue = (SkDisplayInt*) displ
ayable; | |
317 operand->fS32 = boxedValue->value; | |
318 } break; | |
319 case SkType_Float: { | |
320 SkDisplayFloat* boxedValue = (SkDisplayFloat*) d
isplayable; | |
321 operand->fScalar = boxedValue->value; | |
322 } break; | |
323 case SkType_String: { | |
324 SkDisplayString* boxedValue = (SkDisplayString*)
displayable; | |
325 operand->fString = SkNEW_ARGS(SkString, (boxedVa
lue->value)); | |
326 } break; | |
327 default: { | |
328 const char* id; | |
329 bool success = fEngine->getMaker().findKey(displ
ayable, &id); | |
330 SkASSERT(success); | |
331 operand->fString = SkNEW_ARGS(SkString, (id)); | |
332 } | |
333 } | |
334 return true; | |
335 } | |
336 | |
337 virtual SkOperand2::OpType getReturnType(int /*index*/, SkOperand2* oper
and) { | |
338 SkDisplayable* displayable = (SkDisplayable*) operand->fObject; | |
339 switch (displayable->getType()) { | |
340 case SkType_Array: | |
341 return SkOperand2::kArray; | |
342 case SkType_Int: | |
343 return SkOperand2::kS32; | |
344 case SkType_Float: | |
345 return SkOperand2::kScalar; | |
346 case SkType_String: | |
347 default: | |
348 return SkOperand2::kString; | |
349 } | |
350 } | |
351 | |
352 virtual Type getType() const { | |
353 return kUnbox; | |
354 } | |
355 | |
356 SkAnimatorScript2* fEngine; | |
357 }; | |
358 | |
359 SkAnimatorScript2::SkAnimatorScript2(SkAnimateMaker& maker, SkDisplayable* worki
ng, SkDisplayTypes type) : | |
360 SkScriptEngine2(ToOpType(type)), fMaker(maker), fWorking(working
) { | |
361 *fCallBackArray.append() = new SkAnimatorScript_Member(this); | |
362 *fCallBackArray.append() = new SkAnimatorScript_MemberFunction(this); | |
363 *fCallBackArray.append() = new SkAnimatorScript_Box(); | |
364 *fCallBackArray.append() = new SkAnimatorScript_Unbox(this); | |
365 *fCallBackArray.append() = new SkAnimatorScript_ID(this); | |
366 if (type == SkType_ARGB) { | |
367 *fCallBackArray.append() = new SkAnimatorScript_RGB(); | |
368 *fCallBackArray.append() = new SkAnimatorScript_NamedColor(); | |
369 } | |
370 if (SkDisplayType::IsEnum(&maker, type)) { | |
371 // !!! for SpiderMonkey, iterate through the enum values, and ma
p them to globals | |
372 const SkDisplayEnumMap& map = GetEnumValues(type); | |
373 *fCallBackArray.append() = new SkAnimatorScript_Enum(map.fValues
); | |
374 } | |
375 *fCallBackArray.append() = new SkAnimatorScript_Eval(this); | |
376 #if 0 // !!! no extra support for now | |
377 for (SkExtras** extraPtr = maker.fExtras.begin(); extraPtr < maker.fExtr
as.end(); extraPtr++) { | |
378 SkExtras* extra = *extraPtr; | |
379 if (extra->fExtraCallBack) | |
380 *fCallBackArray.append() = new propertyCallBack(extra->f
ExtraCallBack, extra->fExtraStorage); | |
381 } | |
382 #endif | |
383 } | |
384 | |
385 SkAnimatorScript2::~SkAnimatorScript2() { | |
386 SkScriptCallBack** end = fCallBackArray.end(); | |
387 for (SkScriptCallBack** ptr = fCallBackArray.begin(); ptr < end; ptr++) | |
388 delete *ptr; | |
389 } | |
390 | |
391 bool SkAnimatorScript2::evalMemberCommon(const SkMemberInfo* info, | |
392 SkDisplayable* displayable, SkOperand2* value) { | |
393 SkDisplayTypes original; | |
394 SkDisplayTypes type = original = (SkDisplayTypes) info->getType(); | |
395 if (info->fType == SkType_Array) | |
396 type = SkType_Array; | |
397 switch (type) { | |
398 case SkType_ARGB: | |
399 type = SkType_Int; | |
400 case SkType_Boolean: | |
401 case SkType_Int: | |
402 case SkType_MSec: | |
403 case SkType_Float: | |
404 SkASSERT(info->getCount() == 1); | |
405 if (info->fType != SkType_MemberProperty && info->fType
!= SkType_MemberFunction) | |
406 value->fS32 = *(int32_t*) info->memberData(displ
ayable); // OK for SkScalar too | |
407 if (type == SkType_MSec) { | |
408 value->fScalar = SkScalarDiv((SkScalar) value->f
S32, 1000); // dividing two ints is the same as dividing two scalars | |
409 type = SkType_Float; | |
410 } | |
411 break; | |
412 case SkType_String: { | |
413 SkString* displayableString; | |
414 if (info->fType != SkType_MemberProperty && info->fType
!= SkType_MemberFunction) { | |
415 info->getString(displayable, &displayableString)
; | |
416 value->fString = new SkString(*displayableString
); | |
417 } | |
418 } break; | |
419 case SkType_Array: { | |
420 SkASSERT(info->fType != SkType_MemberProperty); // !!! i
ncomplete | |
421 SkTDOperandArray* displayableArray = (SkTDOperandArray*)
info->memberData(displayable); | |
422 if (displayable->getType() == SkType_Array) { | |
423 SkDisplayArray* typedArray = (SkDisplayArray*) d
isplayable; | |
424 original = typedArray->values.getType(); | |
425 } | |
426 SkASSERT(original != SkType_Unknown); | |
427 SkOpArray* array = value->fArray = new SkOpArray(ToOpTyp
e(original)); | |
428 track(array); | |
429 int count = displayableArray->count(); | |
430 if (count > 0) { | |
431 array->setCount(count); | |
432 memcpy(array->begin(), displayableArray->begin()
, count * sizeof(SkOperand2)); | |
433 } | |
434 } break; | |
435 default: | |
436 SkASSERT(0); // unimplemented | |
437 } | |
438 return true; | |
439 } | |
440 | |
441 const SkDisplayEnumMap& SkAnimatorScript2::GetEnumValues(SkDisplayTypes type) { | |
442 int index = SkTSearch<SkDisplayTypes>(&gEnumMaps[0].fType, gEnumMapCount
, type, | |
443 sizeof(SkDisplayEnumMap)); | |
444 SkASSERT(index >= 0); | |
445 return gEnumMaps[index]; | |
446 } | |
447 | |
448 SkDisplayTypes SkAnimatorScript2::ToDisplayType(SkOperand2::OpType type) { | |
449 int val = type; | |
450 switch (val) { | |
451 case SkOperand2::kNoType: | |
452 return SkType_Unknown; | |
453 case SkOperand2::kS32: | |
454 return SkType_Int; | |
455 case SkOperand2::kScalar: | |
456 return SkType_Float; | |
457 case SkOperand2::kString: | |
458 return SkType_String; | |
459 case SkOperand2::kArray: | |
460 return SkType_Array; | |
461 case SkOperand2::kObject: | |
462 return SkType_Displayable; | |
463 default: | |
464 SkASSERT(0); | |
465 return SkType_Unknown; | |
466 } | |
467 } | |
468 | |
469 SkOperand2::OpType SkAnimatorScript2::ToOpType(SkDisplayTypes type) { | |
470 if (SkDisplayType::IsDisplayable(NULL /* fMaker */, type)) | |
471 return SkOperand2::kObject; | |
472 if (SkDisplayType::IsEnum(NULL /* fMaker */, type)) | |
473 return SkOperand2::kS32; | |
474 switch (type) { | |
475 case SkType_ARGB: | |
476 case SkType_MSec: | |
477 case SkType_Int: | |
478 return SkOperand2::kS32; | |
479 case SkType_Float: | |
480 case SkType_Point: | |
481 case SkType_3D_Point: | |
482 return SkOperand2::kScalar; | |
483 case SkType_Base64: | |
484 case SkType_DynamicString: | |
485 case SkType_String: | |
486 return SkOperand2::kString; | |
487 case SkType_Array: | |
488 return SkOperand2::kArray; | |
489 case SkType_Unknown: | |
490 return SkOperand2::kNoType; | |
491 default: | |
492 SkASSERT(0); | |
493 return SkOperand2::kNoType; | |
494 } | |
495 } | |
496 | |
497 bool SkAnimatorScript2::MapEnums(const char* ptr, const char* match, size_t len,
int* value) { | |
498 int index = 0; | |
499 bool more = true; | |
500 do { | |
501 const char* last = strchr(ptr, '|'); | |
502 if (last == NULL) { | |
503 last = &ptr[strlen(ptr)]; | |
504 more = false; | |
505 } | |
506 size_t length = last - ptr; | |
507 if (len == length && strncmp(ptr, match, length) == 0) { | |
508 *value = index; | |
509 return true; | |
510 } | |
511 index++; | |
512 ptr = last + 1; | |
513 } while (more); | |
514 return false; | |
515 } | |
516 | |
517 #if defined SK_DEBUG | |
518 | |
519 #include "SkAnimator.h" | |
520 | |
521 static const char scriptTestSetup[] = | |
522 "<screenplay>" | |
523 "<apply>" | |
524 "<paint>" | |
525 "<emboss id='emboss' direction='[1,1,1]' />" | |
526 "</paint>" | |
527 "<animateField id='animation' field='direction' target='emboss'
from='[1,1,1]' to='[-1,1,1]' dur='1'/>" | |
528 "<set lval='direction[0]' target='emboss' to='-1' />" | |
529 "</apply>" | |
530 "<color id='testColor' color='0 ? rgb(0,0,0) : rgb(255,255,255)' />" | |
531 "<color id='xColor' color='rgb(12,34,56)' />" | |
532 "<typedArray id='emptyArray' />" | |
533 "<typedArray id='intArray' values='[1, 4, 6]' />" | |
534 "<s32 id='idx' value='2' />" | |
535 "<s32 id='idy' value='2' />" | |
536 "<string id='alpha' value='abc' />" | |
537 "<rectangle id='testRect' left='Math.cos(0)' top='2' right='12' bottom='
5' />" | |
538 "<event id='evt'>" | |
539 "<input name='x' />" | |
540 "<apply scope='idy'>" | |
541 "<set field='value' to='evt.x.s32' />" | |
542 "</apply>" | |
543 "</event>" | |
544 "</screenplay>"; | |
545 | |
546 #if !defined(SK_BUILD_FOR_BREW) | |
547 static const SkScriptNAnswer scriptTests[] = { | |
548 { "alpha+alpha", SkType_String, 0, 0, "abcabc" }, | |
549 { "0 ? Math.sin(0) : 1", SkType_Int, 1 }, | |
550 { "intArray[4]", SkType_Unknown }, | |
551 { "emptyArray[4]", SkType_Unknown }, | |
552 { "idx", SkType_Int, 2 }, | |
553 { "intArray.length", SkType_Int, 3 }, | |
554 { "intArray.values[0]", SkType_Int, 1 }, | |
555 { "intArray[0]", SkType_Int, 1 }, | |
556 { "idx.value", SkType_Int, 2 }, | |
557 { "alpha.value", SkType_String, 0, 0, "abc" }, | |
558 { "alpha", SkType_String, 0, 0, "abc" }, | |
559 { "alpha.value+alpha.value", SkType_String, 0, 0, "abcabc" }, | |
560 { "alpha+idx", SkType_String, 0, 0, "abc2" }, | |
561 { "idx+alpha", SkType_String, 0, 0, "2abc" }, | |
562 { "intArray[idx]", SkType_Int, 6 }, | |
563 { "alpha.slice(1,2)", SkType_String, 0, 0, "b" }, | |
564 { "alpha.value.slice(1,2)", SkType_String, 0, 0, "b" }, | |
565 { "Math.sin(0)", SkType_Float, 0, SkIntToScalar(0) }, | |
566 { "testRect.left+2", SkType_Float, 0, SkIntToScalar(3) }, | |
567 { "0 ? intArray[0] : 1", SkType_Int, 1 }, | |
568 { "0 ? intArray.values[0] : 1", SkType_Int, 1 }, | |
569 { "0 ? idx : 1", SkType_Int, 1 }, | |
570 { "0 ? idx.value : 1", SkType_Int, 1 }, | |
571 { "0 ? alpha.slice(1,2) : 1", SkType_Int, 1 }, | |
572 { "0 ? alpha.value.slice(1,2) : 1", SkType_Int, 1 }, | |
573 { "idy", SkType_Int, 3 } | |
574 }; | |
575 #endif | |
576 | |
577 #define SkScriptNAnswer_testCount SK_ARRAY_COUNT(scriptTests) | |
578 | |
579 void SkAnimatorScript2::UnitTest() { | |
580 #if !defined(SK_BUILD_FOR_BREW) && defined(SK_SUPPORT_UNITTEST) | |
581 SkAnimator animator; | |
582 SkASSERT(animator.decodeMemory(scriptTestSetup, sizeof(scriptTestSetup)-
1)); | |
583 SkEvent evt; | |
584 evt.setString("id", "evt"); | |
585 evt.setS32("x", 3); | |
586 animator.doUserEvent(evt); | |
587 // set up animator with memory script above, then run value tests | |
588 for (int index = 0; index < SkScriptNAnswer_testCount; index++) { | |
589 SkAnimatorScript2 engine(*animator.fMaker, NULL, scriptTests[ind
ex].fType); | |
590 SkScriptValue2 value; | |
591 const char* script = scriptTests[index].fScript; | |
592 bool success = engine.evaluateScript(&script, &value); | |
593 if (success == false) { | |
594 SkASSERT(scriptTests[index].fType == SkType_Unknown); | |
595 continue; | |
596 } | |
597 SkASSERT(value.fType == ToOpType(scriptTests[index].fType)); | |
598 SkScalar error; | |
599 switch (value.fType) { | |
600 case SkOperand2::kS32: | |
601 SkASSERT(value.fOperand.fS32 == scriptTests[inde
x].fIntAnswer); | |
602 break; | |
603 case SkOperand2::kScalar: | |
604 error = SkScalarAbs(value.fOperand.fScalar - scr
iptTests[index].fScalarAnswer); | |
605 SkASSERT(error < SK_Scalar1 / 10000); | |
606 break; | |
607 case SkOperand2::kString: | |
608 SkASSERT(value.fOperand.fString->equals(scriptTe
sts[index].fStringAnswer)); | |
609 break; | |
610 default: | |
611 SkASSERT(0); | |
612 } | |
613 } | |
614 #endif | |
615 } | |
616 | |
617 #endif | |
618 | |
OLD | NEW |