| OLD | NEW |
| (Empty) |
| 1 #include "SkScriptRuntime.h" | |
| 2 #include "SkScript2.h" | |
| 3 #include "SkParse.h" | |
| 4 #include "SkScriptCallBack.h" | |
| 5 #include "SkString.h" | |
| 6 #include "SkOpArray.h" | |
| 7 | |
| 8 // script tokenizer | |
| 9 | |
| 10 // turn text into token string | |
| 11 // turn number literals into inline UTF8-style values | |
| 12 // process operators to turn standard notation into stack notation | |
| 13 | |
| 14 // defer processing until the tokens can all be resolved | |
| 15 // then, turn token strings into indices into the appropriate tables / dictionar
ies | |
| 16 | |
| 17 // consider: const evaluation? | |
| 18 | |
| 19 // replace script string with script tokens preceeded by special value | |
| 20 | |
| 21 // need second version of script plugins that return private index of found valu
e? | |
| 22 // then would need in script index of plugin, private index | |
| 23 | |
| 24 // encode brace stack push/pop as opcodes | |
| 25 | |
| 26 // should token script enocde type where possible? | |
| 27 | |
| 28 // current flow: | |
| 29 // strip whitespace | |
| 30 // if in array brace [ recurse, continue | |
| 31 // if token, handle function, or array, or property (continue) | |
| 32 // parse number, continue | |
| 33 // parse token, continue | |
| 34 // parse string literal, continue | |
| 35 // if dot operator, handle dot, continue | |
| 36 // if [ , handle array literal or accessor, continue | |
| 37 // if ), pop (if function, break) | |
| 38 // if ], pop ; if ',' break | |
| 39 // handle logical ops | |
| 40 // or, handle arithmetic ops | |
| 41 // loop | |
| 42 | |
| 43 // !!! things to do | |
| 44 // add separate processing loop to advance while suppressed | |
| 45 // or, include jump offset to skip suppressed code? | |
| 46 | |
| 47 SkScriptRuntime::~SkScriptRuntime() { | |
| 48 for (SkString** stringPtr = fTrackString.begin(); stringPtr < fTrackStri
ng.end(); stringPtr++) | |
| 49 delete *stringPtr; | |
| 50 for (SkOpArray** arrayPtr = fTrackArray.begin(); arrayPtr < fTrackArray.
end(); arrayPtr++) | |
| 51 delete *arrayPtr; | |
| 52 } | |
| 53 | |
| 54 bool SkScriptRuntime::executeTokens(unsigned char* opCode) { | |
| 55 SkOperand2 operand[2]; // 1=accumulator and 2=operand | |
| 56 SkScriptEngine2::TypeOp op; | |
| 57 size_t ref; | |
| 58 int index, size; | |
| 59 int registerLoad; | |
| 60 SkScriptCallBack* callBack SK_INIT_TO_AVOID_WARNING; | |
| 61 do { | |
| 62 switch ((op = (SkScriptEngine2::TypeOp) *opCode++)) { | |
| 63 case SkScriptEngine2::kArrayToken: // create an array | |
| 64 operand[0].fArray = new SkOpArray(SkOperand2::kNoType /*
fReturnType*/); | |
| 65 break; | |
| 66 case SkScriptEngine2::kArrayIndex: // array accessor | |
| 67 index = operand[1].fS32; | |
| 68 if (index >= operand[0].fArray->count()) { | |
| 69 fError = kArrayIndexOutOfBounds; | |
| 70 return false; | |
| 71 } | |
| 72 operand[0] = operand[0].fArray->begin()[index]; | |
| 73 break; | |
| 74 case SkScriptEngine2::kArrayParam: // array initializer, or
function param | |
| 75 *operand[0].fArray->append() = operand[1]; | |
| 76 break; | |
| 77 case SkScriptEngine2::kCallback: | |
| 78 memcpy(&index, opCode, sizeof(index)); | |
| 79 opCode += sizeof(index); | |
| 80 callBack = fCallBackArray[index]; | |
| 81 break; | |
| 82 case SkScriptEngine2::kFunctionCall: { | |
| 83 memcpy(&ref, opCode, sizeof(ref)); | |
| 84 opCode += sizeof(ref); | |
| 85 SkScriptCallBackFunction* callBackFunction = (SkScriptCa
llBackFunction*) callBack; | |
| 86 if (callBackFunction->invoke(ref, operand[0].fArray, /*
params */ | |
| 87 &operand[0] /* result */) == false) { | |
| 88 fError = kFunctionCallFailed; | |
| 89 return false; | |
| 90 } | |
| 91 } break; | |
| 92 case SkScriptEngine2::kMemberOp: { | |
| 93 memcpy(&ref, opCode, sizeof(ref)); | |
| 94 opCode += sizeof(ref); | |
| 95 SkScriptCallBackMember* callBackMember = (SkScriptCallBa
ckMember*) callBack; | |
| 96 if (callBackMember->invoke(ref, operand[0].fObject, &ope
rand[0]) == false) { | |
| 97 fError = kMemberOpFailed; | |
| 98 return false; | |
| 99 } | |
| 100 } break; | |
| 101 case SkScriptEngine2::kPropertyOp: { | |
| 102 memcpy(&ref, opCode, sizeof(ref)); | |
| 103 opCode += sizeof(ref); | |
| 104 SkScriptCallBackProperty* callBackProperty = (SkScriptCa
llBackProperty*) callBack; | |
| 105 if (callBackProperty->getResult(ref, &operand[0])== fals
e) { | |
| 106 fError = kPropertyOpFailed; | |
| 107 return false; | |
| 108 } | |
| 109 } break; | |
| 110 case SkScriptEngine2::kAccumulatorPop: | |
| 111 fRunStack.pop(&operand[0]); | |
| 112 break; | |
| 113 case SkScriptEngine2::kAccumulatorPush: | |
| 114 *fRunStack.push() = operand[0]; | |
| 115 break; | |
| 116 case SkScriptEngine2::kIntegerAccumulator: | |
| 117 case SkScriptEngine2::kIntegerOperand: | |
| 118 registerLoad = op - SkScriptEngine2::kIntegerAccumulator
; | |
| 119 memcpy(&operand[registerLoad].fS32, opCode, sizeof(int32
_t)); | |
| 120 opCode += sizeof(int32_t); | |
| 121 break; | |
| 122 case SkScriptEngine2::kScalarAccumulator: | |
| 123 case SkScriptEngine2::kScalarOperand: | |
| 124 registerLoad = op - SkScriptEngine2::kScalarAccumulator; | |
| 125 memcpy(&operand[registerLoad].fScalar, opCode, sizeof(Sk
Scalar)); | |
| 126 opCode += sizeof(SkScalar); | |
| 127 break; | |
| 128 case SkScriptEngine2::kStringAccumulator: | |
| 129 case SkScriptEngine2::kStringOperand: { | |
| 130 SkString* strPtr = new SkString(); | |
| 131 track(strPtr); | |
| 132 registerLoad = op - SkScriptEngine2::kStringAccumulator; | |
| 133 memcpy(&size, opCode, sizeof(size)); | |
| 134 opCode += sizeof(size); | |
| 135 strPtr->set((char*) opCode, size); | |
| 136 opCode += size; | |
| 137 operand[registerLoad].fString = strPtr; | |
| 138 } break; | |
| 139 case SkScriptEngine2::kStringTrack: // call after kObjectToValue | |
| 140 track(operand[0].fString); | |
| 141 break; | |
| 142 case SkScriptEngine2::kBoxToken: { | |
| 143 SkOperand2::OpType type; | |
| 144 memcpy(&type, opCode, sizeof(type)); | |
| 145 opCode += sizeof(type); | |
| 146 SkScriptCallBackConvert* callBackBox = (SkScriptCallBack
Convert*) callBack; | |
| 147 if (callBackBox->convert(type, &operand[0]) == false) | |
| 148 return false; | |
| 149 } break; | |
| 150 case SkScriptEngine2::kUnboxToken: | |
| 151 case SkScriptEngine2::kUnboxToken2: { | |
| 152 SkScriptCallBackConvert* callBackUnbox = (SkScriptCallBa
ckConvert*) callBack; | |
| 153 if (callBackUnbox->convert(SkOperand2::kObject, &operand
[0]) == false) | |
| 154 return false; | |
| 155 } break; | |
| 156 case SkScriptEngine2::kIfOp: | |
| 157 case SkScriptEngine2::kLogicalAndInt: | |
| 158 memcpy(&size, opCode, sizeof(size)); | |
| 159 opCode += sizeof(size); | |
| 160 if (operand[0].fS32 == 0) | |
| 161 opCode += size; // skip to else (or end of if pr
edicate) | |
| 162 break; | |
| 163 case SkScriptEngine2::kElseOp: | |
| 164 memcpy(&size, opCode, sizeof(size)); | |
| 165 opCode += sizeof(size); | |
| 166 opCode += size; // if true: after predicate, always skip
to end of else | |
| 167 break; | |
| 168 case SkScriptEngine2::kLogicalOrInt: | |
| 169 memcpy(&size, opCode, sizeof(size)); | |
| 170 opCode += sizeof(size); | |
| 171 if (operand[0].fS32 != 0) | |
| 172 opCode += size; // skip to kToBool opcode after
|| predicate | |
| 173 break; | |
| 174 // arithmetic conversion ops | |
| 175 case SkScriptEngine2::kFlipOpsOp: | |
| 176 SkTSwap(operand[0], operand[1]); | |
| 177 break; | |
| 178 case SkScriptEngine2::kIntToString: | |
| 179 case SkScriptEngine2::kIntToString2: | |
| 180 case SkScriptEngine2::kScalarToString: | |
| 181 case SkScriptEngine2::kScalarToString2:{ | |
| 182 SkString* strPtr = new SkString(); | |
| 183 track(strPtr); | |
| 184 if (op == SkScriptEngine2::kIntToString || op == SkScrip
tEngine2::kIntToString2) | |
| 185 strPtr->appendS32(operand[op - SkScriptEngine2::
kIntToString].fS32); | |
| 186 else | |
| 187 strPtr->appendScalar(operand[op - SkScriptEngine
2::kScalarToString].fScalar); | |
| 188 operand[0].fString = strPtr; | |
| 189 } break; | |
| 190 case SkScriptEngine2::kIntToScalar: | |
| 191 case SkScriptEngine2::kIntToScalar2: | |
| 192 operand[0].fScalar = SkScriptEngine2::IntToScalar(operan
d[op - SkScriptEngine2::kIntToScalar].fS32); | |
| 193 break; | |
| 194 case SkScriptEngine2::kStringToInt: | |
| 195 if (SkParse::FindS32(operand[0].fString->c_str(), &opera
nd[0].fS32) == false) | |
| 196 return false; | |
| 197 break; | |
| 198 case SkScriptEngine2::kStringToScalar: | |
| 199 case SkScriptEngine2::kStringToScalar2: | |
| 200 if (SkParse::FindScalar(operand[0].fString->c_str(), | |
| 201 &operand[op - SkScriptEngine2::kStringTo
Scalar].fScalar) == false) | |
| 202 return false; | |
| 203 break; | |
| 204 case SkScriptEngine2::kScalarToInt: | |
| 205 operand[0].fS32 = SkScalarFloor(operand[0].fScalar); | |
| 206 break; | |
| 207 // arithmetic ops | |
| 208 case SkScriptEngine2::kAddInt: | |
| 209 operand[0].fS32 += operand[1].fS32; | |
| 210 break; | |
| 211 case SkScriptEngine2::kAddScalar: | |
| 212 operand[0].fScalar += operand[1].fScalar; | |
| 213 break; | |
| 214 case SkScriptEngine2::kAddString: | |
| 215 // if (fTrackString.find(operand[1].fString) < 0) { | |
| 216 // operand[1].fString = SkNEW_ARGS(SkString, (*oper
and[1].fString)); | |
| 217 // track(operand[1].fString); | |
| 218 // } | |
| 219 operand[0].fString->append(*operand[1].fString); | |
| 220 break; | |
| 221 case SkScriptEngine2::kBitAndInt: | |
| 222 operand[0].fS32 &= operand[1].fS32; | |
| 223 break; | |
| 224 case SkScriptEngine2::kBitNotInt: | |
| 225 operand[0].fS32 = ~operand[0].fS32; | |
| 226 break; | |
| 227 case SkScriptEngine2::kBitOrInt: | |
| 228 operand[0].fS32 |= operand[1].fS32; | |
| 229 break; | |
| 230 case SkScriptEngine2::kDivideInt: | |
| 231 SkASSERT(operand[1].fS32 != 0); | |
| 232 if (operand[1].fS32 == 0) | |
| 233 operand[0].fS32 = operand[0].fS32 == 0 ? SK_NaN3
2 : | |
| 234 operand[0].fS32 > 0 ? SK_MaxS32 : -SK_Ma
xS32; | |
| 235 else | |
| 236 if (operand[1].fS32 != 0) // throw error on divide by ze
ro? | |
| 237 operand[0].fS32 /= operand[1].fS32; | |
| 238 break; | |
| 239 case SkScriptEngine2::kDivideScalar: | |
| 240 if (operand[1].fScalar == 0) | |
| 241 operand[0].fScalar = operand[0].fScalar == 0 ? S
K_ScalarNaN : | |
| 242 operand[0].fScalar > 0 ? SK_ScalarMax :
-SK_ScalarMax; | |
| 243 else | |
| 244 operand[0].fScalar = SkScalarDiv(operand[0].fSca
lar, operand[1].fScalar); | |
| 245 break; | |
| 246 case SkScriptEngine2::kEqualInt: | |
| 247 operand[0].fS32 = operand[0].fS32 == operand[1].fS32; | |
| 248 break; | |
| 249 case SkScriptEngine2::kEqualScalar: | |
| 250 operand[0].fS32 = operand[0].fScalar == operand[1].fScal
ar; | |
| 251 break; | |
| 252 case SkScriptEngine2::kEqualString: | |
| 253 operand[0].fS32 = *operand[0].fString == *operand[1].fSt
ring; | |
| 254 break; | |
| 255 case SkScriptEngine2::kGreaterEqualInt: | |
| 256 operand[0].fS32 = operand[0].fS32 >= operand[1].fS32; | |
| 257 break; | |
| 258 case SkScriptEngine2::kGreaterEqualScalar: | |
| 259 operand[0].fS32 = operand[0].fScalar >= operand[1].fScal
ar; | |
| 260 break; | |
| 261 case SkScriptEngine2::kGreaterEqualString: | |
| 262 operand[0].fS32 = strcmp(operand[0].fString->c_str(), op
erand[1].fString->c_str()) >= 0; | |
| 263 break; | |
| 264 case SkScriptEngine2::kToBool: | |
| 265 operand[0].fS32 = !! operand[0].fS32; | |
| 266 break; | |
| 267 case SkScriptEngine2::kLogicalNotInt: | |
| 268 operand[0].fS32 = ! operand[0].fS32; | |
| 269 break; | |
| 270 case SkScriptEngine2::kMinusInt: | |
| 271 operand[0].fS32 = -operand[0].fS32; | |
| 272 break; | |
| 273 case SkScriptEngine2::kMinusScalar: | |
| 274 operand[0].fScalar = -operand[0].fScalar; | |
| 275 break; | |
| 276 case SkScriptEngine2::kModuloInt: | |
| 277 operand[0].fS32 %= operand[1].fS32; | |
| 278 break; | |
| 279 case SkScriptEngine2::kModuloScalar: | |
| 280 operand[0].fScalar = SkScalarMod(operand[0].fScalar, ope
rand[1].fScalar); | |
| 281 break; | |
| 282 case SkScriptEngine2::kMultiplyInt: | |
| 283 operand[0].fS32 *= operand[1].fS32; | |
| 284 break; | |
| 285 case SkScriptEngine2::kMultiplyScalar: | |
| 286 operand[0].fScalar = SkScalarMul(operand[0].fScalar, ope
rand[1].fScalar); | |
| 287 break; | |
| 288 case SkScriptEngine2::kShiftLeftInt: | |
| 289 operand[0].fS32 <<= operand[1].fS32; | |
| 290 break; | |
| 291 case SkScriptEngine2::kShiftRightInt: | |
| 292 operand[0].fS32 >>= operand[1].fS32; | |
| 293 break; | |
| 294 case SkScriptEngine2::kSubtractInt: | |
| 295 operand[0].fS32 -= operand[1].fS32; | |
| 296 break; | |
| 297 case SkScriptEngine2::kSubtractScalar: | |
| 298 operand[0].fScalar -= operand[1].fScalar; | |
| 299 break; | |
| 300 case SkScriptEngine2::kXorInt: | |
| 301 operand[0].fS32 ^= operand[1].fS32; | |
| 302 break; | |
| 303 case SkScriptEngine2::kEnd: | |
| 304 goto done; | |
| 305 case SkScriptEngine2::kNop: | |
| 306 SkASSERT(0); | |
| 307 } | |
| 308 } while (true); | |
| 309 done: | |
| 310 fRunStack.push(operand[0]); | |
| 311 return true; | |
| 312 } | |
| 313 | |
| 314 bool SkScriptRuntime::getResult(SkOperand2* result) { | |
| 315 if (fRunStack.count() == 0) | |
| 316 return false; | |
| 317 fRunStack.pop(result); | |
| 318 return true; | |
| 319 } | |
| 320 | |
| 321 void SkScriptRuntime::track(SkOpArray* array) { | |
| 322 SkASSERT(fTrackArray.find(array) < 0); | |
| 323 *fTrackArray.append() = array; | |
| 324 } | |
| 325 | |
| 326 void SkScriptRuntime::track(SkString* string) { | |
| 327 SkASSERT(fTrackString.find(string) < 0); | |
| 328 *fTrackString.append() = string; | |
| 329 } | |
| 330 | |
| 331 void SkScriptRuntime::untrack(SkOpArray* array) { | |
| 332 int index = fTrackArray.find(array); | |
| 333 SkASSERT(index >= 0); | |
| 334 fTrackArray.begin()[index] = NULL; | |
| 335 } | |
| 336 | |
| 337 void SkScriptRuntime::untrack(SkString* string) { | |
| 338 int index = fTrackString.find(string); | |
| 339 SkASSERT(index >= 0); | |
| 340 fTrackString.begin()[index] = NULL; | |
| 341 } | |
| 342 | |
| OLD | NEW |