1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/animator/SkScriptRuntime.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,351 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2011 Google Inc. 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 +#include "SkScriptRuntime.h" 1.12 +#include "SkScript2.h" 1.13 +#include "SkMath.h" 1.14 +#include "SkParse.h" 1.15 +#include "SkScriptCallBack.h" 1.16 +#include "SkString.h" 1.17 +#include "SkOpArray.h" 1.18 + 1.19 +// script tokenizer 1.20 + 1.21 +// turn text into token string 1.22 +// turn number literals into inline UTF8-style values 1.23 +// process operators to turn standard notation into stack notation 1.24 + 1.25 +// defer processing until the tokens can all be resolved 1.26 +// then, turn token strings into indices into the appropriate tables / dictionaries 1.27 + 1.28 +// consider: const evaluation? 1.29 + 1.30 +// replace script string with script tokens preceeded by special value 1.31 + 1.32 +// need second version of script plugins that return private index of found value? 1.33 + // then would need in script index of plugin, private index 1.34 + 1.35 +// encode brace stack push/pop as opcodes 1.36 + 1.37 +// should token script enocde type where possible? 1.38 + 1.39 +// current flow: 1.40 + // strip whitespace 1.41 + // if in array brace [ recurse, continue 1.42 + // if token, handle function, or array, or property (continue) 1.43 + // parse number, continue 1.44 + // parse token, continue 1.45 + // parse string literal, continue 1.46 + // if dot operator, handle dot, continue 1.47 + // if [ , handle array literal or accessor, continue 1.48 + // if ), pop (if function, break) 1.49 + // if ], pop ; if ',' break 1.50 + // handle logical ops 1.51 + // or, handle arithmetic ops 1.52 + // loop 1.53 + 1.54 +// !!! things to do 1.55 + // add separate processing loop to advance while suppressed 1.56 + // or, include jump offset to skip suppressed code? 1.57 + 1.58 +SkScriptRuntime::~SkScriptRuntime() { 1.59 + for (SkString** stringPtr = fTrackString.begin(); stringPtr < fTrackString.end(); stringPtr++) 1.60 + delete *stringPtr; 1.61 + for (SkOpArray** arrayPtr = fTrackArray.begin(); arrayPtr < fTrackArray.end(); arrayPtr++) 1.62 + delete *arrayPtr; 1.63 +} 1.64 + 1.65 +bool SkScriptRuntime::executeTokens(unsigned char* opCode) { 1.66 + SkOperand2 operand[2]; // 1=accumulator and 2=operand 1.67 + SkScriptEngine2::TypeOp op; 1.68 + size_t ref; 1.69 + int index, size; 1.70 + int registerLoad; 1.71 + SkScriptCallBack* callBack SK_INIT_TO_AVOID_WARNING; 1.72 + do { 1.73 + switch ((op = (SkScriptEngine2::TypeOp) *opCode++)) { 1.74 + case SkScriptEngine2::kArrayToken: // create an array 1.75 + operand[0].fArray = new SkOpArray(SkOperand2::kNoType /*fReturnType*/); 1.76 + break; 1.77 + case SkScriptEngine2::kArrayIndex: // array accessor 1.78 + index = operand[1].fS32; 1.79 + if (index >= operand[0].fArray->count()) { 1.80 + fError = kArrayIndexOutOfBounds; 1.81 + return false; 1.82 + } 1.83 + operand[0] = operand[0].fArray->begin()[index]; 1.84 + break; 1.85 + case SkScriptEngine2::kArrayParam: // array initializer, or function param 1.86 + *operand[0].fArray->append() = operand[1]; 1.87 + break; 1.88 + case SkScriptEngine2::kCallback: 1.89 + memcpy(&index, opCode, sizeof(index)); 1.90 + opCode += sizeof(index); 1.91 + callBack = fCallBackArray[index]; 1.92 + break; 1.93 + case SkScriptEngine2::kFunctionCall: { 1.94 + memcpy(&ref, opCode, sizeof(ref)); 1.95 + opCode += sizeof(ref); 1.96 + SkScriptCallBackFunction* callBackFunction = (SkScriptCallBackFunction*) callBack; 1.97 + if (callBackFunction->invoke(ref, operand[0].fArray, /* params */ 1.98 + &operand[0] /* result */) == false) { 1.99 + fError = kFunctionCallFailed; 1.100 + return false; 1.101 + } 1.102 + } break; 1.103 + case SkScriptEngine2::kMemberOp: { 1.104 + memcpy(&ref, opCode, sizeof(ref)); 1.105 + opCode += sizeof(ref); 1.106 + SkScriptCallBackMember* callBackMember = (SkScriptCallBackMember*) callBack; 1.107 + if (callBackMember->invoke(ref, operand[0].fObject, &operand[0]) == false) { 1.108 + fError = kMemberOpFailed; 1.109 + return false; 1.110 + } 1.111 + } break; 1.112 + case SkScriptEngine2::kPropertyOp: { 1.113 + memcpy(&ref, opCode, sizeof(ref)); 1.114 + opCode += sizeof(ref); 1.115 + SkScriptCallBackProperty* callBackProperty = (SkScriptCallBackProperty*) callBack; 1.116 + if (callBackProperty->getResult(ref, &operand[0])== false) { 1.117 + fError = kPropertyOpFailed; 1.118 + return false; 1.119 + } 1.120 + } break; 1.121 + case SkScriptEngine2::kAccumulatorPop: 1.122 + fRunStack.pop(&operand[0]); 1.123 + break; 1.124 + case SkScriptEngine2::kAccumulatorPush: 1.125 + *fRunStack.push() = operand[0]; 1.126 + break; 1.127 + case SkScriptEngine2::kIntegerAccumulator: 1.128 + case SkScriptEngine2::kIntegerOperand: 1.129 + registerLoad = op - SkScriptEngine2::kIntegerAccumulator; 1.130 + memcpy(&operand[registerLoad].fS32, opCode, sizeof(int32_t)); 1.131 + opCode += sizeof(int32_t); 1.132 + break; 1.133 + case SkScriptEngine2::kScalarAccumulator: 1.134 + case SkScriptEngine2::kScalarOperand: 1.135 + registerLoad = op - SkScriptEngine2::kScalarAccumulator; 1.136 + memcpy(&operand[registerLoad].fScalar, opCode, sizeof(SkScalar)); 1.137 + opCode += sizeof(SkScalar); 1.138 + break; 1.139 + case SkScriptEngine2::kStringAccumulator: 1.140 + case SkScriptEngine2::kStringOperand: { 1.141 + SkString* strPtr = new SkString(); 1.142 + track(strPtr); 1.143 + registerLoad = op - SkScriptEngine2::kStringAccumulator; 1.144 + memcpy(&size, opCode, sizeof(size)); 1.145 + opCode += sizeof(size); 1.146 + strPtr->set((char*) opCode, size); 1.147 + opCode += size; 1.148 + operand[registerLoad].fString = strPtr; 1.149 + } break; 1.150 + case SkScriptEngine2::kStringTrack: // call after kObjectToValue 1.151 + track(operand[0].fString); 1.152 + break; 1.153 + case SkScriptEngine2::kBoxToken: { 1.154 + SkOperand2::OpType type; 1.155 + memcpy(&type, opCode, sizeof(type)); 1.156 + opCode += sizeof(type); 1.157 + SkScriptCallBackConvert* callBackBox = (SkScriptCallBackConvert*) callBack; 1.158 + if (callBackBox->convert(type, &operand[0]) == false) 1.159 + return false; 1.160 + } break; 1.161 + case SkScriptEngine2::kUnboxToken: 1.162 + case SkScriptEngine2::kUnboxToken2: { 1.163 + SkScriptCallBackConvert* callBackUnbox = (SkScriptCallBackConvert*) callBack; 1.164 + if (callBackUnbox->convert(SkOperand2::kObject, &operand[0]) == false) 1.165 + return false; 1.166 + } break; 1.167 + case SkScriptEngine2::kIfOp: 1.168 + case SkScriptEngine2::kLogicalAndInt: 1.169 + memcpy(&size, opCode, sizeof(size)); 1.170 + opCode += sizeof(size); 1.171 + if (operand[0].fS32 == 0) 1.172 + opCode += size; // skip to else (or end of if predicate) 1.173 + break; 1.174 + case SkScriptEngine2::kElseOp: 1.175 + memcpy(&size, opCode, sizeof(size)); 1.176 + opCode += sizeof(size); 1.177 + opCode += size; // if true: after predicate, always skip to end of else 1.178 + break; 1.179 + case SkScriptEngine2::kLogicalOrInt: 1.180 + memcpy(&size, opCode, sizeof(size)); 1.181 + opCode += sizeof(size); 1.182 + if (operand[0].fS32 != 0) 1.183 + opCode += size; // skip to kToBool opcode after || predicate 1.184 + break; 1.185 + // arithmetic conversion ops 1.186 + case SkScriptEngine2::kFlipOpsOp: 1.187 + SkTSwap(operand[0], operand[1]); 1.188 + break; 1.189 + case SkScriptEngine2::kIntToString: 1.190 + case SkScriptEngine2::kIntToString2: 1.191 + case SkScriptEngine2::kScalarToString: 1.192 + case SkScriptEngine2::kScalarToString2:{ 1.193 + SkString* strPtr = new SkString(); 1.194 + track(strPtr); 1.195 + if (op == SkScriptEngine2::kIntToString || op == SkScriptEngine2::kIntToString2) 1.196 + strPtr->appendS32(operand[op - SkScriptEngine2::kIntToString].fS32); 1.197 + else 1.198 + strPtr->appendScalar(operand[op - SkScriptEngine2::kScalarToString].fScalar); 1.199 + operand[0].fString = strPtr; 1.200 + } break; 1.201 + case SkScriptEngine2::kIntToScalar: 1.202 + case SkScriptEngine2::kIntToScalar2: 1.203 + operand[0].fScalar = SkScriptEngine2::IntToScalar(operand[op - SkScriptEngine2::kIntToScalar].fS32); 1.204 + break; 1.205 + case SkScriptEngine2::kStringToInt: 1.206 + if (SkParse::FindS32(operand[0].fString->c_str(), &operand[0].fS32) == NULL) 1.207 + return false; 1.208 + break; 1.209 + case SkScriptEngine2::kStringToScalar: 1.210 + case SkScriptEngine2::kStringToScalar2: 1.211 + if (SkParse::FindScalar(operand[0].fString->c_str(), 1.212 + &operand[op - SkScriptEngine2::kStringToScalar].fScalar) == NULL) 1.213 + return false; 1.214 + break; 1.215 + case SkScriptEngine2::kScalarToInt: 1.216 + operand[0].fS32 = SkScalarFloorToInt(operand[0].fScalar); 1.217 + break; 1.218 + // arithmetic ops 1.219 + case SkScriptEngine2::kAddInt: 1.220 + operand[0].fS32 += operand[1].fS32; 1.221 + break; 1.222 + case SkScriptEngine2::kAddScalar: 1.223 + operand[0].fScalar += operand[1].fScalar; 1.224 + break; 1.225 + case SkScriptEngine2::kAddString: 1.226 +// if (fTrackString.find(operand[1].fString) < 0) { 1.227 +// operand[1].fString = SkNEW_ARGS(SkString, (*operand[1].fString)); 1.228 +// track(operand[1].fString); 1.229 +// } 1.230 + operand[0].fString->append(*operand[1].fString); 1.231 + break; 1.232 + case SkScriptEngine2::kBitAndInt: 1.233 + operand[0].fS32 &= operand[1].fS32; 1.234 + break; 1.235 + case SkScriptEngine2::kBitNotInt: 1.236 + operand[0].fS32 = ~operand[0].fS32; 1.237 + break; 1.238 + case SkScriptEngine2::kBitOrInt: 1.239 + operand[0].fS32 |= operand[1].fS32; 1.240 + break; 1.241 + case SkScriptEngine2::kDivideInt: 1.242 + SkASSERT(operand[1].fS32 != 0); 1.243 + if (operand[1].fS32 == 0) 1.244 + operand[0].fS32 = operand[0].fS32 == 0 ? SK_NaN32 : 1.245 + operand[0].fS32 > 0 ? SK_MaxS32 : -SK_MaxS32; 1.246 + else 1.247 + if (operand[1].fS32 != 0) // throw error on divide by zero? 1.248 + operand[0].fS32 /= operand[1].fS32; 1.249 + break; 1.250 + case SkScriptEngine2::kDivideScalar: 1.251 + if (operand[1].fScalar == 0) 1.252 + operand[0].fScalar = operand[0].fScalar == 0 ? SK_ScalarNaN : 1.253 + operand[0].fScalar > 0 ? SK_ScalarMax : -SK_ScalarMax; 1.254 + else 1.255 + operand[0].fScalar = SkScalarDiv(operand[0].fScalar, operand[1].fScalar); 1.256 + break; 1.257 + case SkScriptEngine2::kEqualInt: 1.258 + operand[0].fS32 = operand[0].fS32 == operand[1].fS32; 1.259 + break; 1.260 + case SkScriptEngine2::kEqualScalar: 1.261 + operand[0].fS32 = operand[0].fScalar == operand[1].fScalar; 1.262 + break; 1.263 + case SkScriptEngine2::kEqualString: 1.264 + operand[0].fS32 = *operand[0].fString == *operand[1].fString; 1.265 + break; 1.266 + case SkScriptEngine2::kGreaterEqualInt: 1.267 + operand[0].fS32 = operand[0].fS32 >= operand[1].fS32; 1.268 + break; 1.269 + case SkScriptEngine2::kGreaterEqualScalar: 1.270 + operand[0].fS32 = operand[0].fScalar >= operand[1].fScalar; 1.271 + break; 1.272 + case SkScriptEngine2::kGreaterEqualString: 1.273 + operand[0].fS32 = strcmp(operand[0].fString->c_str(), operand[1].fString->c_str()) >= 0; 1.274 + break; 1.275 + case SkScriptEngine2::kToBool: 1.276 + operand[0].fS32 = !! operand[0].fS32; 1.277 + break; 1.278 + case SkScriptEngine2::kLogicalNotInt: 1.279 + operand[0].fS32 = ! operand[0].fS32; 1.280 + break; 1.281 + case SkScriptEngine2::kMinusInt: 1.282 + operand[0].fS32 = -operand[0].fS32; 1.283 + break; 1.284 + case SkScriptEngine2::kMinusScalar: 1.285 + operand[0].fScalar = -operand[0].fScalar; 1.286 + break; 1.287 + case SkScriptEngine2::kModuloInt: 1.288 + operand[0].fS32 %= operand[1].fS32; 1.289 + break; 1.290 + case SkScriptEngine2::kModuloScalar: 1.291 + operand[0].fScalar = SkScalarMod(operand[0].fScalar, operand[1].fScalar); 1.292 + break; 1.293 + case SkScriptEngine2::kMultiplyInt: 1.294 + operand[0].fS32 *= operand[1].fS32; 1.295 + break; 1.296 + case SkScriptEngine2::kMultiplyScalar: 1.297 + operand[0].fScalar = SkScalarMul(operand[0].fScalar, operand[1].fScalar); 1.298 + break; 1.299 + case SkScriptEngine2::kShiftLeftInt: 1.300 + operand[0].fS32 <<= operand[1].fS32; 1.301 + break; 1.302 + case SkScriptEngine2::kShiftRightInt: 1.303 + operand[0].fS32 >>= operand[1].fS32; 1.304 + break; 1.305 + case SkScriptEngine2::kSubtractInt: 1.306 + operand[0].fS32 -= operand[1].fS32; 1.307 + break; 1.308 + case SkScriptEngine2::kSubtractScalar: 1.309 + operand[0].fScalar -= operand[1].fScalar; 1.310 + break; 1.311 + case SkScriptEngine2::kXorInt: 1.312 + operand[0].fS32 ^= operand[1].fS32; 1.313 + break; 1.314 + case SkScriptEngine2::kEnd: 1.315 + goto done; 1.316 + case SkScriptEngine2::kNop: 1.317 + SkASSERT(0); 1.318 + default: 1.319 + break; 1.320 + } 1.321 + } while (true); 1.322 +done: 1.323 + fRunStack.push(operand[0]); 1.324 + return true; 1.325 +} 1.326 + 1.327 +bool SkScriptRuntime::getResult(SkOperand2* result) { 1.328 + if (fRunStack.count() == 0) 1.329 + return false; 1.330 + fRunStack.pop(result); 1.331 + return true; 1.332 +} 1.333 + 1.334 +void SkScriptRuntime::track(SkOpArray* array) { 1.335 + SkASSERT(fTrackArray.find(array) < 0); 1.336 + *fTrackArray.append() = array; 1.337 +} 1.338 + 1.339 +void SkScriptRuntime::track(SkString* string) { 1.340 + SkASSERT(fTrackString.find(string) < 0); 1.341 + *fTrackString.append() = string; 1.342 +} 1.343 + 1.344 +void SkScriptRuntime::untrack(SkOpArray* array) { 1.345 + int index = fTrackArray.find(array); 1.346 + SkASSERT(index >= 0); 1.347 + fTrackArray.begin()[index] = NULL; 1.348 +} 1.349 + 1.350 +void SkScriptRuntime::untrack(SkString* string) { 1.351 + int index = fTrackString.find(string); 1.352 + SkASSERT(index >= 0); 1.353 + fTrackString.begin()[index] = NULL; 1.354 +}