1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/animator/SkAnimatorScript.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,594 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2006 The Android Open Source Project 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#include "SkAnimatorScript.h" 1.14 +#include "SkAnimateBase.h" 1.15 +#include "SkAnimateMaker.h" 1.16 +#include "SkDisplayTypes.h" 1.17 +#include "SkExtras.h" 1.18 +#include "SkMemberInfo.h" 1.19 +#include "SkParse.h" 1.20 + 1.21 +static const SkDisplayEnumMap gEnumMaps[] = { 1.22 + { SkType_AddMode, "indirect|immediate" }, 1.23 + { SkType_Align, "left|center|right" }, 1.24 + { SkType_ApplyMode, "create|immediate|once" }, 1.25 + { SkType_ApplyTransition, "normal|reverse" }, 1.26 + { SkType_BitmapEncoding, "jpeg|png" }, 1.27 + { SkType_BitmapFormat, "none|A1|A8|Index8|RGB16|RGB32" }, 1.28 + { SkType_Boolean, "false|true" }, 1.29 + { SkType_Cap, "butt|round|square" }, 1.30 + { SkType_EventCode, "none|leftSoftKey|rightSoftKey|home|back|send|end|key0|key1|key2|key3|key4|key5|key6|key7|key8|key9|star|hash|up|down|left|right|OK|volUp|volDown|camera" }, 1.31 + { SkType_EventKind, "none|keyChar|keyPress|keyPressUp|mouseDown|mouseDrag|mouseMove|mouseUp|onEnd|onLoad|user" }, 1.32 + { SkType_EventMode, "deferred|immediate" }, 1.33 + { SkType_FillType, "winding|evenOdd" }, 1.34 + { SkType_FilterType, "none|bilinear" }, 1.35 + { SkType_FontStyle, "normal|bold|italic|boldItalic" }, 1.36 + { SkType_FromPathMode, "normal|angle|position" }, 1.37 + { SkType_Join, "miter|round|blunt" }, 1.38 + { SkType_MaskFilterBlurStyle, "normal|solid|outer|inner" }, 1.39 + { SkType_PathDirection, "cw|ccw" }, 1.40 + { SkType_Style, "fill|stroke|strokeAndFill" }, 1.41 + { SkType_TextBoxAlign, "start|center|end" }, 1.42 + { SkType_TextBoxMode, "oneLine|lineBreak" }, 1.43 + { SkType_TileMode, "clamp|repeat|mirror" }, 1.44 + { SkType_Xfermode, "clear|src|dst|srcOver|dstOver|srcIn|dstIn|srcOut|dstOut|" 1.45 + "srcATop|dstATop|xor|darken|lighten" }, 1.46 +}; 1.47 + 1.48 +static int gEnumMapCount = SK_ARRAY_COUNT(gEnumMaps); 1.49 + 1.50 +SkAnimatorScript::SkAnimatorScript(SkAnimateMaker& maker, SkDisplayable* working, SkDisplayTypes type) 1.51 + : SkScriptEngine(SkScriptEngine::ToOpType(type)), fMaker(maker), fParent(NULL), fWorking(working) 1.52 +{ 1.53 + memberCallBack(EvalMember, (void*) this); 1.54 + memberFunctionCallBack(EvalMemberFunction, (void*) this); 1.55 + boxCallBack(Box, (void*) this); 1.56 + unboxCallBack(Unbox, (void*) &maker); 1.57 + propertyCallBack(EvalID, (void*) this); // must be first (entries are prepended, will be last), since it never fails 1.58 + propertyCallBack(Infinity, (void*) this); 1.59 + propertyCallBack(NaN, (void*) this); 1.60 + functionCallBack(Eval, (void*) this); 1.61 + functionCallBack(IsFinite, (void*) this); 1.62 + functionCallBack(IsNaN, (void*) this); 1.63 + if (type == SkType_ARGB) { 1.64 + functionCallBack(EvalRGB, (void*) this); 1.65 + propertyCallBack(EvalNamedColor, (void*) &maker.fIDs); 1.66 + } 1.67 + if (SkDisplayType::IsEnum(&maker, type)) { 1.68 + // !!! for SpiderMonkey, iterate through the enum values, and map them to globals 1.69 + const SkDisplayEnumMap& map = GetEnumValues(type); 1.70 + propertyCallBack(EvalEnum, (void*) map.fValues); 1.71 + } 1.72 + for (SkExtras** extraPtr = maker.fExtras.begin(); extraPtr < maker.fExtras.end(); extraPtr++) { 1.73 + SkExtras* extra = *extraPtr; 1.74 + if (extra->fExtraCallBack) 1.75 + propertyCallBack(extra->fExtraCallBack, extra->fExtraStorage); 1.76 + } 1.77 +} 1.78 + 1.79 +SkAnimatorScript::~SkAnimatorScript() { 1.80 + for (SkDisplayable** dispPtr = fTrackDisplayable.begin(); dispPtr < fTrackDisplayable.end(); dispPtr++) 1.81 + delete *dispPtr; 1.82 +} 1.83 + 1.84 +bool SkAnimatorScript::evaluate(const char* original, SkScriptValue* result, SkDisplayTypes type) { 1.85 + const char* script = original; 1.86 + bool success = evaluateScript(&script, result); 1.87 + if (success == false || result->fType != type) { 1.88 + fMaker.setScriptError(*this); 1.89 + return false; 1.90 + } 1.91 + return true; 1.92 +} 1.93 + 1.94 +bool SkAnimatorScript::Box(void* user, SkScriptValue* scriptValue) { 1.95 + SkAnimatorScript* engine = (SkAnimatorScript*) user; 1.96 + SkDisplayTypes type = scriptValue->fType; 1.97 + SkDisplayable* displayable; 1.98 + switch (type) { 1.99 + case SkType_Array: { 1.100 + SkDisplayArray* boxedValue = new SkDisplayArray(*scriptValue->fOperand.fArray); 1.101 + displayable = boxedValue; 1.102 + } break; 1.103 + case SkType_Boolean: { 1.104 + SkDisplayBoolean* boxedValue = new SkDisplayBoolean; 1.105 + displayable = boxedValue; 1.106 + boxedValue->value = !! scriptValue->fOperand.fS32; 1.107 + } break; 1.108 + case SkType_Int: { 1.109 + SkDisplayInt* boxedValue = new SkDisplayInt; 1.110 + displayable = boxedValue; 1.111 + boxedValue->value = scriptValue->fOperand.fS32; 1.112 + } break; 1.113 + case SkType_Float: { 1.114 + SkDisplayFloat* boxedValue = new SkDisplayFloat; 1.115 + displayable = boxedValue; 1.116 + boxedValue->value = scriptValue->fOperand.fScalar; 1.117 + } break; 1.118 + case SkType_String: { 1.119 + SkDisplayString* boxedValue = new SkDisplayString(*scriptValue->fOperand.fString); 1.120 + displayable = boxedValue; 1.121 + } break; 1.122 + case SkType_Displayable: 1.123 + scriptValue->fOperand.fObject = scriptValue->fOperand.fDisplayable; 1.124 + scriptValue->fType = SkType_Displayable; 1.125 + return true; 1.126 + default: 1.127 + SkASSERT(0); 1.128 + return false; 1.129 + } 1.130 + engine->track(displayable); 1.131 + scriptValue->fOperand.fObject = displayable; 1.132 + scriptValue->fType = SkType_Displayable; 1.133 + return true; 1.134 +} 1.135 + 1.136 +bool SkAnimatorScript::Eval(const char* function, size_t len, SkTDArray<SkScriptValue>& params, 1.137 + void* eng, SkScriptValue* value) { 1.138 + if (SK_LITERAL_STR_EQUAL("eval", function, len) == false) 1.139 + return false; 1.140 + if (params.count() != 1) 1.141 + return false; 1.142 + SkAnimatorScript* host = (SkAnimatorScript*) eng; 1.143 + SkAnimatorScript engine(host->fMaker, host->fWorking, SkScriptEngine::ToDisplayType(host->fReturnType)); 1.144 + SkScriptValue* scriptValue = params.begin(); 1.145 + bool success = true; 1.146 + if (scriptValue->fType == SkType_String) { 1.147 + const char* script = scriptValue->fOperand.fString->c_str(); 1.148 + success = engine.evaluateScript(&script, value); 1.149 + } else 1.150 + *value = *scriptValue; 1.151 + return success; 1.152 +} 1.153 + 1.154 +bool SkAnimatorScript::EvalEnum(const char* token, size_t len, void* callBack, SkScriptValue* value) { 1.155 + const char* tokens = (const char*) callBack; 1.156 + value->fType = SkType_Int; 1.157 + if (MapEnums(tokens, token, len, (int*)&value->fOperand.fS32)) 1.158 + return true; 1.159 + return false; 1.160 +} 1.161 + 1.162 +bool SkAnimatorScript::EvalID(const char* token, size_t len, void* user, SkScriptValue* value) { 1.163 + SkAnimatorScript* engine = (SkAnimatorScript*) user; 1.164 + SkTDict<SkDisplayable*>* ids = &engine->fMaker.fIDs; 1.165 + SkDisplayable* displayable; 1.166 + bool success = ids->find(token, len, &displayable); 1.167 + if (success == false) { 1.168 + displayable = engine->fWorking; 1.169 + if (SK_LITERAL_STR_EQUAL("parent", token, len)) { 1.170 + SkDisplayable* parent = displayable->getParent(); 1.171 + if (parent == NULL) 1.172 + parent = engine->fParent; 1.173 + if (parent) { 1.174 + value->fOperand.fDisplayable = parent; 1.175 + value->fType = SkType_Displayable; 1.176 + return true; 1.177 + } 1.178 + } 1.179 + if (displayable && EvalMember(token, len, displayable, engine, value)) 1.180 + return true; 1.181 + value->fOperand.fString = NULL; 1.182 + value->fType = SkType_String; 1.183 + } else { 1.184 + SkDisplayable* working = engine->fWorking; 1.185 + value->fOperand.fDisplayable = displayable; 1.186 + value->fType = SkType_Displayable; 1.187 + if (displayable->canContainDependents() && working && working->isAnimate()) { 1.188 + SkAnimateBase* animator = (SkAnimateBase*) working; 1.189 + if (animator->isDynamic()) { 1.190 + SkDisplayDepend* depend = (SkDisplayDepend* ) displayable; 1.191 + depend->addDependent(working); 1.192 + } 1.193 + } 1.194 + } 1.195 + return true; 1.196 +} 1.197 + 1.198 +bool SkAnimatorScript::EvalNamedColor(const char* token, size_t len, void* callback, SkScriptValue* value) { 1.199 + value->fType = SkType_Int; 1.200 + if (SkParse::FindNamedColor(token, len, (SkColor*) &value->fOperand.fS32) != NULL) 1.201 + return true; 1.202 + return false; 1.203 +} 1.204 + 1.205 +bool SkAnimatorScript::EvalRGB(const char* function, size_t len, SkTDArray<SkScriptValue>& params, 1.206 + void* eng, SkScriptValue* value) { 1.207 + if (SK_LITERAL_STR_EQUAL("rgb", function, len) == false) 1.208 + return false; 1.209 + if (params.count() != 3) 1.210 + return false; 1.211 + SkScriptEngine* engine = (SkScriptEngine*) eng; 1.212 + unsigned result = 0xFF000000; 1.213 + int shift = 16; 1.214 + for (SkScriptValue* valuePtr = params.begin(); valuePtr < params.end(); valuePtr++) { 1.215 + engine->convertTo(SkType_Int, valuePtr); 1.216 + result |= SkClampMax(valuePtr->fOperand.fS32, 255) << shift; 1.217 + shift -= 8; 1.218 + } 1.219 + value->fOperand.fS32 = result; 1.220 + value->fType = SkType_Int; 1.221 + return true; 1.222 +} 1.223 + 1.224 +bool SkAnimatorScript::EvalMemberCommon(SkScriptEngine* engine, const SkMemberInfo* info, 1.225 + SkDisplayable* displayable, SkScriptValue* value) { 1.226 + SkDisplayTypes original; 1.227 + SkDisplayTypes type = original = (SkDisplayTypes) info->getType(); 1.228 + if (info->fType == SkType_Array) 1.229 + type = SkType_Array; 1.230 + switch (type) { 1.231 + case SkType_ARGB: 1.232 + type = SkType_Int; 1.233 + case SkType_Boolean: 1.234 + case SkType_Int: 1.235 + case SkType_MSec: 1.236 + case SkType_Float: 1.237 + SkASSERT(info->getCount() == 1); 1.238 + if (info->fType != SkType_MemberProperty && info->fType != SkType_MemberFunction) 1.239 + value->fOperand.fS32 = *(int32_t*) info->memberData(displayable); // OK for SkScalar too 1.240 + if (type == SkType_MSec) { 1.241 + value->fOperand.fScalar = SkScalarDiv((SkScalar) value->fOperand.fS32, 1000); // dividing two ints is the same as dividing two scalars 1.242 + type = SkType_Float; 1.243 + } 1.244 + break; 1.245 + case SkType_String: { 1.246 + SkString* displayableString; 1.247 + if (info->fType != SkType_MemberProperty && info->fType != SkType_MemberFunction) { 1.248 + info->getString(displayable, &displayableString); 1.249 + value->fOperand.fString = new SkString(*displayableString); 1.250 + } 1.251 + } break; 1.252 + case SkType_Array: { 1.253 + SkASSERT(info->fType != SkType_MemberProperty); // !!! incomplete 1.254 + SkTDOperandArray* displayableArray = (SkTDOperandArray*) info->memberData(displayable); 1.255 + if (displayable->getType() == SkType_Array) { 1.256 + SkDisplayArray* typedArray = (SkDisplayArray*) displayable; 1.257 + original = typedArray->values.getType(); 1.258 + } 1.259 + SkASSERT(original != SkType_Unknown); 1.260 + SkTypedArray* array = value->fOperand.fArray = new SkTypedArray(original); 1.261 + engine->track(array); 1.262 + int count = displayableArray->count(); 1.263 + if (count > 0) { 1.264 + array->setCount(count); 1.265 + memcpy(array->begin(), displayableArray->begin(), count * sizeof(SkOperand)); 1.266 + } 1.267 + } break; 1.268 + default: 1.269 + SkASSERT(0); // unimplemented 1.270 + } 1.271 + value->fType = type; 1.272 + return true; 1.273 +} 1.274 + 1.275 +bool SkAnimatorScript::EvalMember(const char* member, size_t len, void* object, void* eng, 1.276 + SkScriptValue* value) { 1.277 + SkScriptEngine* engine = (SkScriptEngine*) eng; 1.278 + SkDisplayable* displayable = (SkDisplayable*) object; 1.279 + SkString name(member, len); 1.280 + SkDisplayable* named = displayable->contains(name); 1.281 + if (named) { 1.282 + value->fOperand.fDisplayable = named; 1.283 + value->fType = SkType_Displayable; 1.284 + return true; 1.285 + } 1.286 + const SkMemberInfo* info = displayable->getMember(name.c_str()); 1.287 + if (info == NULL) 1.288 + return false; 1.289 + if (info->fType == SkType_MemberProperty) { 1.290 + if (displayable->getProperty(info->propertyIndex(), value) == false) { 1.291 + SkASSERT(0); 1.292 + return false; 1.293 + } 1.294 + } 1.295 + return EvalMemberCommon(engine, info, displayable, value); 1.296 +} 1.297 + 1.298 +bool SkAnimatorScript::EvalMemberFunction(const char* member, size_t len, void* object, 1.299 + SkTDArray<SkScriptValue>& params, void* eng, SkScriptValue* value) { 1.300 + SkScriptEngine* engine = (SkScriptEngine*) eng; 1.301 + SkDisplayable* displayable = (SkDisplayable*) object; 1.302 + SkString name(member, len); 1.303 + const SkMemberInfo* info = displayable->getMember(name.c_str()); 1.304 + SkASSERT(info != NULL); /* !!! error handling unimplemented */ 1.305 + if (info->fType != SkType_MemberFunction) { 1.306 + SkASSERT(0); 1.307 + return false; 1.308 + } 1.309 + displayable->executeFunction(displayable, info->functionIndex(), params, info->getType(), 1.310 + value); 1.311 + return EvalMemberCommon(engine, info, displayable, value); 1.312 +} 1.313 + 1.314 +bool SkAnimatorScript::EvaluateDisplayable(SkAnimateMaker& maker, SkDisplayable* displayable, const char* script, SkDisplayable** result) { 1.315 + SkAnimatorScript engine(maker, displayable, SkType_Displayable); 1.316 + SkScriptValue value; 1.317 + bool success = engine.evaluate(script, &value, SkType_Displayable); 1.318 + if (success) 1.319 + *result = value.fOperand.fDisplayable; 1.320 + return success; 1.321 +} 1.322 + 1.323 +bool SkAnimatorScript::EvaluateInt(SkAnimateMaker& maker, SkDisplayable* displayable, const char* script, int32_t* result) { 1.324 + SkAnimatorScript engine(maker, displayable, SkType_Int); 1.325 + SkScriptValue value; 1.326 + bool success = engine.evaluate(script, &value, SkType_Int); 1.327 + if (success) 1.328 + *result = value.fOperand.fS32; 1.329 + return success; 1.330 +} 1.331 + 1.332 +bool SkAnimatorScript::EvaluateFloat(SkAnimateMaker& maker, SkDisplayable* displayable, const char* script, SkScalar* result) { 1.333 + SkAnimatorScript engine(maker, displayable, SkType_Float); 1.334 + SkScriptValue value; 1.335 + bool success = engine.evaluate(script, &value, SkType_Float); 1.336 + if (success) 1.337 + *result = value.fOperand.fScalar; 1.338 + return success; 1.339 +} 1.340 + 1.341 +bool SkAnimatorScript::EvaluateString(SkAnimateMaker& maker, SkDisplayable* displayable, const char* script, SkString* result) { 1.342 + SkAnimatorScript engine(maker, displayable, SkType_String); 1.343 + SkScriptValue value; 1.344 + bool success = engine.evaluate(script, &value, SkType_String); 1.345 + if (success) 1.346 + result->set(*(value.fOperand.fString)); 1.347 + return success; 1.348 +} 1.349 + 1.350 +bool SkAnimatorScript::EvaluateString(SkAnimateMaker& maker, SkDisplayable* displayable, SkDisplayable* parent, const char* script, SkString* result) { 1.351 + SkAnimatorScript engine(maker, displayable, SkType_String); 1.352 + engine.fParent = parent; 1.353 + SkScriptValue value; 1.354 + bool success = engine.evaluate(script, &value, SkType_String); 1.355 + if (success) 1.356 + result->set(*(value.fOperand.fString)); 1.357 + return success; 1.358 +} 1.359 + 1.360 +const SkDisplayEnumMap& SkAnimatorScript::GetEnumValues(SkDisplayTypes type) { 1.361 + int index = SkTSearch<SkDisplayTypes>(&gEnumMaps[0].fType, gEnumMapCount, type, 1.362 + sizeof(SkDisplayEnumMap)); 1.363 + SkASSERT(index >= 0); 1.364 + return gEnumMaps[index]; 1.365 +} 1.366 + 1.367 +bool SkAnimatorScript::Infinity(const char* token, size_t len, void* user, SkScriptValue* value) { 1.368 + if (SK_LITERAL_STR_EQUAL("Infinity", token, len) == false) 1.369 + return false; 1.370 + value->fType = SkType_Float; 1.371 + value->fOperand.fScalar = SK_ScalarInfinity; 1.372 + return true; 1.373 +} 1.374 + 1.375 +bool SkAnimatorScript::IsFinite(const char* function, size_t len, SkTDArray<SkScriptValue>& params, 1.376 + void* eng, SkScriptValue* value) { 1.377 + if (SK_LITERAL_STR_EQUAL(function, "isFinite", len) == false) 1.378 + return false; 1.379 + if (params.count() != 1) 1.380 + return false; 1.381 + SkScriptValue* scriptValue = params.begin(); 1.382 + SkDisplayTypes type = scriptValue->fType; 1.383 + SkScalar scalar = scriptValue->fOperand.fScalar; 1.384 + value->fType = SkType_Int; 1.385 + value->fOperand.fS32 = type == SkType_Float ? SkScalarIsNaN(scalar) == false && 1.386 + SkScalarAbs(scalar) != SK_ScalarInfinity : type == SkType_Int; 1.387 + return true; 1.388 +} 1.389 + 1.390 +bool SkAnimatorScript::IsNaN(const char* function, size_t len, SkTDArray<SkScriptValue>& params, 1.391 + void* eng, SkScriptValue* value) { 1.392 + if (SK_LITERAL_STR_EQUAL("isNaN", function, len) == false) 1.393 + return false; 1.394 + if (params.count() != 1) 1.395 + return false; 1.396 + SkScriptValue* scriptValue = params.begin(); 1.397 + value->fType = SkType_Int; 1.398 + value->fOperand.fS32 = scriptValue->fType == SkType_Float ? SkScalarIsNaN(scriptValue->fOperand.fScalar) : 0; 1.399 + return true; 1.400 +} 1.401 + 1.402 +bool SkAnimatorScript::MapEnums(const char* ptr, const char* match, size_t len, int* value) { 1.403 + int index = 0; 1.404 + bool more = true; 1.405 + do { 1.406 + const char* last = strchr(ptr, '|'); 1.407 + if (last == NULL) { 1.408 + last = &ptr[strlen(ptr)]; 1.409 + more = false; 1.410 + } 1.411 + size_t length = last - ptr; 1.412 + if (len == length && strncmp(ptr, match, length) == 0) { 1.413 + *value = index; 1.414 + return true; 1.415 + } 1.416 + index++; 1.417 + ptr = last + 1; 1.418 + } while (more); 1.419 + return false; 1.420 +} 1.421 + 1.422 +bool SkAnimatorScript::NaN(const char* token, size_t len, void* user, SkScriptValue* value) { 1.423 + if (SK_LITERAL_STR_EQUAL("NaN", token, len) == false) 1.424 + return false; 1.425 + value->fType = SkType_Float; 1.426 + value->fOperand.fScalar = SK_ScalarNaN; 1.427 + return true; 1.428 +} 1.429 + 1.430 +#if 0 1.431 +bool SkAnimatorScript::ObjectToString(void* object, void* user, SkScriptValue* value) { 1.432 + SkTDict<SkDisplayable*>* ids = (SkTDict<SkDisplayable*>*) user; 1.433 + SkDisplayable* displayable = (SkDisplayable*) object; 1.434 + const char* key; 1.435 + bool success = ids->findKey(displayable, &key); 1.436 + if (success == false) 1.437 + return false; 1.438 + value->fOperand.fString = new SkString(key); 1.439 + value->fType = SkType_String; 1.440 + return true; 1.441 +} 1.442 +#endif 1.443 + 1.444 +bool SkAnimatorScript::Unbox(void* m, SkScriptValue* scriptValue) { 1.445 + SkAnimateMaker* maker = (SkAnimateMaker*) m; 1.446 + SkASSERT((unsigned) scriptValue->fType == (unsigned) SkType_Displayable); 1.447 + SkDisplayable* displayable = (SkDisplayable*) scriptValue->fOperand.fObject; 1.448 + SkDisplayTypes type = displayable->getType(); 1.449 + switch (displayable->getType()) { 1.450 + case SkType_Array: { 1.451 + SkDisplayArray* boxedValue = (SkDisplayArray*) displayable; 1.452 + scriptValue->fOperand.fArray = &boxedValue->values; 1.453 + } break; 1.454 + case SkType_Boolean: { 1.455 + SkDisplayBoolean* boxedValue = (SkDisplayBoolean*) displayable; 1.456 + scriptValue->fOperand.fS32 = boxedValue->value; 1.457 + } break; 1.458 + case SkType_Int: { 1.459 + SkDisplayInt* boxedValue = (SkDisplayInt*) displayable; 1.460 + scriptValue->fOperand.fS32 = boxedValue->value; 1.461 + } break; 1.462 + case SkType_Float: { 1.463 + SkDisplayFloat* boxedValue = (SkDisplayFloat*) displayable; 1.464 + scriptValue->fOperand.fScalar = boxedValue->value; 1.465 + } break; 1.466 + case SkType_String: { 1.467 + SkDisplayString* boxedValue = (SkDisplayString*) displayable; 1.468 + scriptValue->fOperand.fString = SkNEW_ARGS(SkString, (boxedValue->value)); 1.469 + } break; 1.470 + default: { 1.471 + const char* id = NULL; 1.472 + SkDEBUGCODE(bool success = ) maker->findKey(displayable, &id); 1.473 + SkASSERT(success); 1.474 + scriptValue->fOperand.fString = SkNEW_ARGS(SkString, (id)); 1.475 + type = SkType_String; 1.476 + } 1.477 + } 1.478 + scriptValue->fType = type; 1.479 + return true; 1.480 +} 1.481 + 1.482 +#if defined SK_SUPPORT_UNITTEST 1.483 + 1.484 +#include "SkAnimator.h" 1.485 + 1.486 +static const char scriptTestSetup[] = 1.487 +"<screenplay>\n" 1.488 + "<text id='label' text='defg'/>\n" 1.489 + "<add id='addLabel' use='label'/>\n" 1.490 + "<text id='text1' text='test'/>\n" 1.491 + "<apply scope='addLabel'>\n" 1.492 + "<set target='label' field='text' to='#script:text1.text'/>\n" 1.493 + "</apply>\n" 1.494 + "<apply>\n" 1.495 + "<paint id='labelPaint'>\n" 1.496 + "<emboss id='emboss' direction='[1,1,1]' />\n" 1.497 + "</paint>\n" 1.498 + "<animate id='animation' field='direction' target='emboss' from='[1,1,1]' to='[-1,1,1]' dur='1'/>\n" 1.499 + "<set lval='direction[0]' target='emboss' to='-1' />\n" 1.500 + "</apply>\n" 1.501 + "<color id='testColor' color='0 ? rgb(0,0,0) : rgb(255,255,255)' />\n" 1.502 + "<color id='xColor' color='rgb(12,34,56)' />\n" 1.503 + "<array id='emptyArray' />\n" 1.504 + "<array id='intArray' values='[1, 4, 6]' />\n" 1.505 + "<int id='idx' value='2' />\n" 1.506 + "<int id='idy' value='2' />\n" 1.507 + "<string id='alpha' value='abc' />\n" 1.508 + "<rect id='testRect' left='Math.cos(0)' top='2' right='12' bottom='5' />\n" 1.509 + "<event id='evt'>\n" 1.510 + "<input name='x' />\n" 1.511 + "<apply scope='idy'>\n" 1.512 + "<set field='value' to='evt.x.int' />\n" 1.513 + "</apply>\n" 1.514 + "</event>\n" 1.515 +"</screenplay>"; 1.516 + 1.517 +#define DEFAULT_ANSWER , 0 1.518 + 1.519 +static const SkScriptNAnswer scriptTests[] = { 1.520 + { "label.text.length == 4", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.521 +// { "labelPaint.measureText(label.text) > 0 ? labelPaint.measureText(label.text)+10 : 40", SkType_Float, 0, SkIntToScalar(0x23) }, 1.522 + { "Number.POSITIVE_INFINITY >= Number.MAX_VALUE ? 1 : 0", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.523 + { "Infinity >= Number.MAX_VALUE ? 1 : 0", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.524 + { "Number.NEGATIVE_INFINITY <= -Number.MAX_VALUE ? 1 : 0", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.525 + { "Number.MIN_VALUE > 0 ? 1 : 0", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.526 + { "isNaN(Number.NaN)", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.527 + { "isNaN(NaN)", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.528 + { "Math.sin(0)", SkType_Float, 0, SkIntToScalar(0) DEFAULT_ANSWER }, 1.529 + { "alpha+alpha", SkType_String, 0, 0, "abcabc" }, 1.530 + { "intArray[4]", SkType_Unknown DEFAULT_ANSWER DEFAULT_ANSWER DEFAULT_ANSWER }, 1.531 + { "emptyArray[4]", SkType_Unknown DEFAULT_ANSWER DEFAULT_ANSWER DEFAULT_ANSWER }, 1.532 + { "idx", SkType_Int, 2 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.533 + { "intArray.length", SkType_Int, 3 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.534 + { "intArray.values[0]", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.535 + { "intArray[0]", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.536 + { "idx.value", SkType_Int, 2 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.537 + { "alpha.value", SkType_String, 0, 0, "abc" }, 1.538 + { "alpha", SkType_String, 0, 0, "abc" }, 1.539 + { "alpha.value+alpha.value", SkType_String, 0, 0, "abcabc" }, 1.540 + { "alpha+idx", SkType_String, 0, 0, "abc2" }, 1.541 + { "idx+alpha", SkType_String, 0, 0, "2abc" }, 1.542 + { "intArray[idx]", SkType_Int, 6 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.543 + { "alpha.slice(1,2)", SkType_String, 0, 0, "b" }, 1.544 + { "alpha.value.slice(1,2)", SkType_String, 0, 0, "b" }, 1.545 + { "testRect.left+2", SkType_Float, 0, SkIntToScalar(3) DEFAULT_ANSWER }, 1.546 + { "0 ? Math.sin(0) : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.547 + { "0 ? intArray[0] : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.548 + { "0 ? intArray.values[0] : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.549 + { "0 ? idx : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.550 + { "0 ? idx.value : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.551 + { "0 ? alpha.slice(1,2) : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.552 + { "0 ? alpha.value.slice(1,2) : 1", SkType_Int, 1 DEFAULT_ANSWER DEFAULT_ANSWER }, 1.553 + { "idy", SkType_Int, 3 DEFAULT_ANSWER DEFAULT_ANSWER } 1.554 +}; 1.555 + 1.556 +#define SkScriptNAnswer_testCount SK_ARRAY_COUNT(scriptTests) 1.557 + 1.558 +void SkAnimatorScript::UnitTest() { 1.559 +#if defined(SK_SUPPORT_UNITTEST) 1.560 + SkAnimator animator; 1.561 + SkASSERT(animator.decodeMemory(scriptTestSetup, sizeof(scriptTestSetup)-1)); 1.562 + SkEvent evt; 1.563 + evt.setString("id", "evt"); 1.564 + evt.setS32("x", 3); 1.565 + animator.doUserEvent(evt); 1.566 + // set up animator with memory script above, then run value tests 1.567 + for (unsigned index = 0; index < SkScriptNAnswer_testCount; index++) { 1.568 + SkAnimatorScript engine(*animator.fMaker, NULL, scriptTests[index].fType); 1.569 + SkScriptValue value; 1.570 + const char* script = scriptTests[index].fScript; 1.571 + bool success = engine.evaluateScript(&script, &value); 1.572 + if (success == false) { 1.573 + SkDebugf("script failed: %s\n", scriptTests[index].fScript); 1.574 + SkASSERT(scriptTests[index].fType == SkType_Unknown); 1.575 + continue; 1.576 + } 1.577 + SkASSERT(value.fType == scriptTests[index].fType); 1.578 + SkScalar error; 1.579 + switch (value.fType) { 1.580 + case SkType_Int: 1.581 + SkASSERT(value.fOperand.fS32 == scriptTests[index].fIntAnswer); 1.582 + break; 1.583 + case SkType_Float: 1.584 + error = SkScalarAbs(value.fOperand.fScalar - scriptTests[index].fScalarAnswer); 1.585 + SkASSERT(error < SK_Scalar1 / 10000); 1.586 + break; 1.587 + case SkType_String: 1.588 + SkASSERT(strcmp(value.fOperand.fString->c_str(), scriptTests[index].fStringAnswer) == 0); 1.589 + break; 1.590 + default: 1.591 + SkASSERT(0); 1.592 + } 1.593 + } 1.594 +#endif 1.595 +} 1.596 + 1.597 +#endif