gfx/skia/trunk/src/animator/SkScriptRuntime.cpp

changeset 0
6474c204b198
     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 +}

mercurial