1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc. 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScript2.h" 98a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com#include "SkData.h" 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkFloatingPoint.h" 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMath.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkParse.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScriptCallBack.h" 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScriptRuntime.h" 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkString.h" 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkOpArray.h" 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkScriptEngine2::OperatorAttributes SkScriptEngine2::gOpAttributes[] = { 1964cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org{ SkOperand2::kNoType, SkOperand2::kNoType, kNoBias, kResultIsNotBoolean }, 20d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com{ SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar | SkOperand2::kString), 2164cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar | SkOperand2::kString), kTowardsString, kResultIsNotBoolean }, // kAdd 2264cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org{ SkOperand2::kS32, SkOperand2::kS32, kNoBias, kResultIsNotBoolean }, // kBitAnd 2364cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org{ SkOperand2::kNoType, SkOperand2::kS32, kNoBias, kResultIsNotBoolean }, // kBitNot 2464cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org{ SkOperand2::kS32, SkOperand2::kS32, kNoBias, kResultIsNotBoolean }, // kBitOr 25d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com{ SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar), 2664cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar), kNoBias, kResultIsNotBoolean }, // kDivide 27d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com{ SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar | SkOperand2::kString), 28d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar |SkOperand2:: kString), kTowardsNumber, 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kResultIsBoolean }, // kEqual 3064cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org{ SkOperand2::kS32, SkOperand2::kNoType, kNoBias, kResultIsNotBoolean }, // kFlipOps 31d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com{ SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar | SkOperand2::kString), 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar | SkOperand2::kString), kTowardsNumber, 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kResultIsBoolean }, // kGreaterEqual 3464cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org{ SkOperand2::kNoType, SkOperand2::kS32, kNoBias, kResultIsNotBoolean }, // kLogicalAnd (really, ToBool) 3564cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org{ SkOperand2::kNoType, SkOperand2::kS32, kNoBias, kResultIsNotBoolean }, // kLogicalNot 3664cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org{ SkOperand2::kS32, SkOperand2::kS32, kNoBias, kResultIsNotBoolean }, // kLogicalOr 3764cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org{ SkOperand2::kNoType, SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar), kNoBias, kResultIsNotBoolean }, // kMinus 38d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com{ SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar), 3964cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org SkOperand2::OpType(SkOperand2::kS32 |SkOperand2:: kScalar), kNoBias, kResultIsNotBoolean }, // kModulo 40d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com{ SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar), 4164cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar), kNoBias, kResultIsNotBoolean }, // kMultiply 4264cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org{ SkOperand2::kS32, SkOperand2::kS32, kNoBias, kResultIsNotBoolean }, // kShiftLeft 4364cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org{ SkOperand2::kS32, SkOperand2::kS32, kNoBias, kResultIsNotBoolean }, // kShiftRight 44d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com{ SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar), 4564cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar), kNoBias, kResultIsNotBoolean }, // kSubtract 4664cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org{ SkOperand2::kS32, SkOperand2::kS32, kNoBias, kResultIsNotBoolean } // kXor 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define kBracketPrecedence 16 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define kIfElsePrecedence 15 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst signed char SkScriptEngine2::gPrecedence[] = { 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17, // kUnassigned, 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6, // kAdd, 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10, // kBitAnd, 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4, // kBitNot, 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12, // kBitOr, 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5, // kDivide, 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9, // kEqual, 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com -1, // kFlipOps, 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8, // kGreaterEqual, 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13, // kLogicalAnd, 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4, // kLogicalNot, 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14, // kLogicalOr, 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4, // kMinus, 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5, // kModulo, 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5, // kMultiply, 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7, // kShiftLeft, 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7, // kShiftRight, // signed 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6, // kSubtract, 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11, // kXor 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kBracketPrecedence, // kArrayOp 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kIfElsePrecedence, // kElse 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kIfElsePrecedence, // kIf 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kBracketPrecedence, // kParen 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkScriptEngine2::TypeOp SkScriptEngine2::gTokens[] = { 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kNop, // unassigned 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kAddInt, // kAdd, 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kBitAndInt, // kBitAnd, 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kBitNotInt, // kBitNot, 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kBitOrInt, // kBitOr, 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kDivideInt, // kDivide, 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kEqualInt, // kEqual, 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kFlipOpsOp, // kFlipOps, 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kGreaterEqualInt, // kGreaterEqual, 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kLogicalAndInt, // kLogicalAnd, 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kLogicalNotInt, // kLogicalNot, 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kLogicalOrInt, // kLogicalOr, 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kMinusInt, // kMinus, 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kModuloInt, // kModulo, 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kMultiplyInt, // kMultiply, 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kShiftLeftInt, // kShiftLeft, 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kShiftRightInt, // kShiftRight, // signed 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kSubtractInt, // kSubtract, 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kXorInt // kXor 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline bool is_between(int c, int min, int max) 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (unsigned)(c - min) <= (unsigned)(max - min); 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline bool is_ws(int c) 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return is_between(c, 1, 32); 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int token_length(const char* start) { 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com char ch = start[0]; 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (! is_between(ch, 'a' , 'z') && ! is_between(ch, 'A', 'Z') && ch != '_' && ch != '$') 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return -1; 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int length = 0; 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ch = start[++length]; 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (is_between(ch, 'a' , 'z') || is_between(ch, 'A', 'Z') || is_between(ch, '0', '9') || 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ch == '_' || ch == '$'); 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return length; 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkScriptEngine2::SkScriptEngine2(SkOperand2::OpType returnType) : fActiveStream(&fStream), 123d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comfTokenLength(0), fReturnType(returnType), fError(kNoError), 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comfAccumulatorType(SkOperand2::kNoType), 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comfBranchPopAllowed(true), fConstExpression(true), fOperandInUse(false) 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Branch branch(kUnassigned, 0, 0); 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBranchStack.push(branch); 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fOpStack.push() = (Op) kParen; 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkScriptEngine2::~SkScriptEngine2() { 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (SkString** stringPtr = fTrackString.begin(); stringPtr < fTrackString.end(); stringPtr++) 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com delete *stringPtr; 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (SkOpArray** arrayPtr = fTrackArray.begin(); arrayPtr < fTrackArray.end(); arrayPtr++) 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com delete *arrayPtr; 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkScriptEngine2::addToken(SkScriptEngine2::TypeOp op) { 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int limit = fBranchStack.count() - 1; 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int index = 0; index < limit; index++) { 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Branch& branch = fBranchStack.index(index); 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (branch.fPrimed == Branch::kIsPrimed) 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com resolveBranch(branch); 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBranchPopAllowed) { 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (fBranchStack.top().fDone == Branch::kIsDone) 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBranchStack.pop(); 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned char charOp = (unsigned char) op; 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fActiveStream->write(&charOp, sizeof(charOp)); 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 154d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comvoid SkScriptEngine2::addTokenConst(SkScriptValue2* value, AddTokenRegister reg, 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkOperand2::OpType toType, SkScriptEngine2::TypeOp op) { 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value->fIsConstant == SkScriptValue2::kConstant && convertTo(toType, value)) 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenValue(*value, reg); 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(op); 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value->fIsWritten = SkScriptValue2::kWritten; 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value->fType = toType; 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkScriptEngine2::addTokenInt(int integer) { 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fActiveStream->write(&integer, sizeof(integer)); 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkScriptEngine2::addTokenScalar(SkScalar scalar) { 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fActiveStream->write(&scalar, sizeof(scalar)); 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkScriptEngine2::addTokenString(const SkString& string) { 17392f93264e760b74cc706d01b2d0fcfaa3d857f51commit-bot@chromium.org int size = SkToInt(string.size()); 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenInt(size); 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fActiveStream->write(string.c_str(), size); 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkScriptEngine2::addTokenValue(const SkScriptValue2& value, AddTokenRegister reg) { 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value.isConstant() == false) { 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (reg == kAccumulator) { 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fAccumulatorType == SkOperand2::kNoType) 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(kAccumulatorPop); 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ; // !!! incomplete? 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (reg == kAccumulator && fAccumulatorType != SkOperand2::kNoType) 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(kAccumulatorPush); 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (value.fType) { 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkOperand2::kS32: 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(reg == kAccumulator ? kIntegerAccumulator : kIntegerOperand); 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenInt(value.fOperand.fS32); 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (reg == kAccumulator) 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAccumulatorType = SkOperand2::kS32; 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOperandInUse = true; 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkOperand2::kScalar: 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(reg == kAccumulator ? kScalarAccumulator : kScalarOperand); 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenScalar(value.fOperand.fScalar); 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (reg == kAccumulator) 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAccumulatorType = SkOperand2::kScalar; 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOperandInUse = true; 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkOperand2::kString: 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(reg == kAccumulator ? kStringAccumulator : kStringOperand); 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenString(*value.fOperand.fString); 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (reg == kAccumulator) 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAccumulatorType = SkOperand2::kString; 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOperandInUse = true; 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); //!!! not implemented yet 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkScriptEngine2::arithmeticOp(char ch, char nextChar, bool lastPush) { 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Op op = kUnassigned; 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool reverseOperands = false; 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool negateResult = false; 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int advance = 1; 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (ch) { 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '+': 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // !!! ignoring unary plus as implemented here has the side effect of 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // suppressing errors like +"hi" 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (lastPush == false) // unary plus, don't push an operator 230800046eba45c9e982ecfe8964b2107f7713ed639reed@android.com return advance; 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kAdd; 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '-': 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = lastPush ? kSubtract : kMinus; 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '*': 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kMultiply; 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '/': 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kDivide; 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '>': 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (nextChar == '>') { 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kShiftRight; 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto twoChar; 246d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kGreaterEqual; 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (nextChar == '=') 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto twoChar; 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com reverseOperands = negateResult = true; 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '<': 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (nextChar == '<') { 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kShiftLeft; 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto twoChar; 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kGreaterEqual; 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com reverseOperands = nextChar == '='; 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com negateResult = ! reverseOperands; 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com advance += reverseOperands; 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '=': 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (nextChar == '=') { 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kEqual; 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto twoChar; 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '!': 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (nextChar == '=') { 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kEqual; 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com negateResult = true; 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtwoChar: 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com advance++; 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 275d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kLogicalNot; 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '?': 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op =(Op) kIf; 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case ':': 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = (Op) kElse; 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '^': 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kXor; 2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '(': 2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fOpStack.push() = (Op) kParen; 289800046eba45c9e982ecfe8964b2107f7713ed639reed@android.com return advance; 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '&': 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(nextChar != '&'); 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kBitAnd; 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '|': 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(nextChar != '|'); 2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kBitOr; 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '%': 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kModulo; 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '~': 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kBitNot; 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (op == kUnassigned) 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com signed char precedence = gPrecedence[op]; 3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int idx = 0; 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Op compare; 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com compare = fOpStack.index(idx); 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((compare & kArtificialOp) == 0) 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com idx++; 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (true); 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com signed char topPrecedence = gPrecedence[compare]; 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(topPrecedence != -1); 319d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if (topPrecedence > precedence || (topPrecedence == precedence && 32064cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org gOpAttributes[op].fLeftType == SkOperand2::kNoType)) { 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com processOp(); 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (true); 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (negateResult) 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fOpStack.push() = (Op) (kLogicalNot | kArtificialOp); 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOpStack.push(op); 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (reverseOperands) 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fOpStack.push() = (Op) (kFlipOps | kArtificialOp); 330800046eba45c9e982ecfe8964b2107f7713ed639reed@android.com 331800046eba45c9e982ecfe8964b2107f7713ed639reed@android.com return advance; 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 334d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.combool SkScriptEngine2::convertParams(SkTDArray<SkScriptValue2>* params, 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkOperand2::OpType* paramTypes, int paramCount) { 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = params->count(); 3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count > paramCount) { 3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; // too many parameters passed 3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 341d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com for (int index = 0; index < count; index++) 3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com convertTo(paramTypes[index], &(*params)[index]); 3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkScriptEngine2::convertTo(SkOperand2::OpType toType, SkScriptValue2* value ) { 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkOperand2::OpType type = value->fType; 3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (type == toType) 3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (type == SkOperand2::kObject) { 3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (handleUnbox(value) == false) 3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return convertTo(toType, value); 3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return ConvertTo(this, toType, value); 3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 358d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.combool SkScriptEngine2::evaluateDot(const char*& script) { 3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t fieldLength = token_length(++script); // skip dot 3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fieldLength > 0); // !!! add error handling 3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* field = script; 3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com script += fieldLength; 3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool success = handleProperty(); 3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (success == false) { 3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fError = kCouldNotFindReferencedID; 3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto error; 3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return evaluateDotParam(script, field, fieldLength); 3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comerror: 3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 373d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.combool SkScriptEngine2::evaluateDotParam(const char*& script, const char* field, size_t fieldLength) { 3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2& top = fValueStack.top(); 3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (top.fType != SkOperand2::kObject) 3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void* object = top.fOperand.fObject; 3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.pop(); 3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com char ch; // see if it is a simple member or a function 380d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com while (is_ws(ch = script[0])) 3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com script++; 3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool success = true; 3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ch != '(') 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = handleMember(field, fieldLength, object); 3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else { 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTDArray<SkScriptValue2> params; 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fBraceStack.push() = kFunctionBrace; 3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = functionParams(&script, ¶ms); 3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (success) 3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = handleMemberFunction(field, fieldLength, object, ¶ms); 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 392d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com return success; 3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkScriptEngine2::evaluateScript(const char** scriptPtr, SkScriptValue2* value) { 3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // fArrayOffset = 0; // no support for structures for now 3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool success; 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* inner; 3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (strncmp(*scriptPtr, "#script:", sizeof("#script:") - 1) == 0) { 4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *scriptPtr += sizeof("#script:") - 1; 4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fReturnType == SkOperand2::kNoType || fReturnType == SkOperand2::kString) { 4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = innerScript(scriptPtr, value); 4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(success); 4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inner = value->fOperand.fString->c_str(); 4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scriptPtr = &inner; 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = innerScript(scriptPtr, value); 4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* script = *scriptPtr; 4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com char ch; 4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (is_ws(ch = script[0])) 4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com script++; 4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ch != '\0') { 4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // error may trigger on scripts like "50,0" that were intended to be written as "[50, 0]" 4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return success; 4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkScriptEngine2::forget(SkOpArray* array) { 4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (array->getType() == SkOperand2::kString) { 4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int index = 0; index < array->count(); index++) { 4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkString* string = (*array)[index].fString; 4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int found = fTrackString.find(string); 4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (found >= 0) 4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTrackString.remove(found); 4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (array->getType() == SkOperand2::kArray) { 4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int index = 0; index < array->count(); index++) { 4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkOpArray* child = (*array)[index].fArray; 4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com forget(child); // forgets children of child 4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int found = fTrackArray.find(child); 4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (found >= 0) 4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTrackArray.remove(found); 4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkScriptEngine2::functionParams(const char** scriptPtr, SkTDArray<SkScriptValue2>* params) { 4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (*scriptPtr)++; // skip open paren 4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fOpStack.push() = (Op) kParen; 4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fBraceStack.push() = kFunctionBrace; 4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2 value; 4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool success = innerScript(scriptPtr, &value); 4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(success); 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (success == false) 4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *params->append() = value; 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while ((*scriptPtr)[-1] == ','); 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBraceStack.pop(); 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOpStack.pop(); // pop paren 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (*scriptPtr)++; // advance beyond close paren 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comsize_t SkScriptEngine2::getTokenOffset() { 4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fActiveStream->getOffset(); 4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkOperand2::OpType SkScriptEngine2::getUnboxType(SkOperand2 scriptValue) { 4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (SkScriptCallBack** callBack = fCallBackArray.begin(); callBack < fCallBackArray.end(); callBack++) { 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((*callBack)->getType() != SkScriptCallBack::kUnbox) 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (*callBack)->getReturnType(0, &scriptValue); 4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkOperand2::kObject; 4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkScriptEngine2::innerScript(const char** scriptPtr, SkScriptValue2* value) { 4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* script = *scriptPtr; 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com char ch; 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool lastPush = false; 4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool success = true; 4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int opBalance = fOpStack.count(); 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int baseBrace = fBraceStack.count(); 4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int branchBalance = fBranchStack.count(); 4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while ((ch = script[0]) != '\0') { 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (is_ws(ch)) { 4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com script++; 4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2 operand; 4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* dotCheck; 4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBraceStack.count() > baseBrace) { 4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBraceStack.top() == kArrayBrace) { 4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2 tokenValue; 4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = innerScript(&script, &tokenValue); // terminate and return on comma, close brace 4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(success); 4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkOperand2::OpType type = fReturnType; 4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fReturnType == SkOperand2::kNoType) { 495d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com // !!! short sighted; in the future, allow each returned array component to carry 4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // its own type, and let caller do any needed conversions 4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value->fOperand.fArray->count() == 0) 4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value->fOperand.fArray->setType(type = tokenValue.fType); 4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else 5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com type = value->fOperand.fArray->getType(); 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (tokenValue.fType != type) 5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com convertTo(type, &tokenValue); 5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *value->fOperand.fArray->append() = tokenValue.fOperand; 5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastPush = false; 5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 508a7ed3cc6371e50a5beb3750c475fe23665dafa7dtomhudson@google.com } else { 5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(token_length(script) > 0); 510a7ed3cc6371e50a5beb3750c475fe23665dafa7dtomhudson@google.com } 5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (lastPush != false && fTokenLength > 0) { 5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ch == '(') { 5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fBraceStack.push() = kFunctionBrace; 5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkString functionName(fToken, fTokenLength); 516d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (handleFunction(&script) == false) 5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastPush = true; 5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (ch == '[') { 5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (handleProperty() == false) { 5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (handleArrayIndexer(&script) == false) 5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastPush = true; 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (ch != '.') { 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (handleProperty() == false) { 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastPush = true; 5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ch == '0' && (script[1] & ~0x20) == 'X') { 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(lastPush == false); 5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com script += 2; 5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com script = SkParse::FindHex(script, (uint32_t*) &operand.fOperand.fS32); 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(script); 5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto intCommon; 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (lastPush == false && ch == '.') 5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto scalarCommon; 5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ch >= '0' && ch <= '9') { 5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(lastPush == false); 5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dotCheck = SkParse::FindS32(script, &operand.fOperand.fS32); 5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (dotCheck[0] != '.') { 5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com script = dotCheck; 5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comintCommon: 5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fType = SkOperand2::kS32; 5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comscalarCommon: 5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com script = SkParse::FindScalar(script, &operand.fOperand.fScalar); 5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fType = SkOperand2::kScalar; 5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fIsConstant = SkScriptValue2::kConstant; 5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.push(operand); 5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastPush = true; 5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int length = token_length(script); 5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (length > 0) { 5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(lastPush == false); 5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fToken = script; 5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTokenLength = length; 5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com script += length; 5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastPush = true; 5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com char startQuote = ch; 5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (startQuote == '\'' || startQuote == '\"') { 5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(lastPush == false); 5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fOperand.fString = new SkString(); 5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ++script; 5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* stringStart = script; 5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { // measure string 5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (script[0] == '\\') 5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ++script; 5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ++script; 5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(script[0]); // !!! throw an error 5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (script[0] != startQuote); 5868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fOperand.fString->set(stringStart, script - stringStart); 5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com script = stringStart; 5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com char* stringWrite = operand.fOperand.fString->writable_str(); 5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { // copy string 5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (script[0] == '\\') 5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ++script; 5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *stringWrite++ = script[0]; 5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ++script; 5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(script[0]); // !!! throw an error 5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (script[0] != startQuote); 5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ++script; 5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com track(operand.fOperand.fString); 5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fType = SkOperand2::kString; 5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fIsConstant = SkScriptValue2::kConstant; 6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.push(operand); 6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastPush = true; 6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ch == '.') { 6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fTokenLength == 0) { 6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int tokenLength = token_length(++script); 6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* token = script; 6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com script += tokenLength; 6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fValueStack.count() > 0); // !!! add error handling 6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2 top; 6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.pop(&top); 612d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenInt(top.fType); 6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(kBoxToken); 6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com top.fType = SkOperand2::kObject; 6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com top.fIsConstant = SkScriptValue2::kVariable; 6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fConstExpression = false; 6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.push(top); 6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = evaluateDotParam(script, token, tokenLength); 6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(success); 6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastPush = true; 622d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com continue; 6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // get next token, and evaluate immediately 6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = evaluateDot(script); 6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (success == false) { 6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // SkASSERT(0); 6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastPush = true; 6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ch == '[') { 6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (lastPush == false) { 6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com script++; 6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fBraceStack.push() = kArrayBrace; 6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fOperand.fArray = value->fOperand.fArray = new SkOpArray(fReturnType); 6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com track(value->fOperand.fArray); 639d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fType = SkOperand2::kArray; 6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fIsConstant = SkScriptValue2::kVariable; 6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.push(operand); 6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (handleArrayIndexer(&script) == false) 6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastPush = true; 6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0 // structs not supported for now 6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ch == '{') { 6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (lastPush == false) { 6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com script++; 6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fBraceStack.push() = kStructBrace; 6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fS32 = 0; 6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fTypeStack.push() = (SkOpType) kStruct; 6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOperandStack.push(operand); 6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); // braces in other contexts aren't supported yet 6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ch == ')' && fBraceStack.count() > 0) { 664d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com BraceStyle braceStyle = fBraceStack.top(); 6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (braceStyle == kFunctionBrace) { 6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBraceStack.pop(); 6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ch == ',' || ch == ']') { 6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ch != ',') { 6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com BraceStyle match; 6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBraceStack.pop(&match); 6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(match == kArrayBrace); 6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com script++; 6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // !!! see if brace or bracket is correct closer 6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com char nextChar = script[1]; 6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int advance = logicalOp(ch, nextChar); 682d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if (advance == 0) 6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com advance = arithmeticOp(ch, nextChar, lastPush); 6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (advance == 0) // unknown token 6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (advance > 0) 6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com script += advance; 6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com lastPush = ch == ']' || ch == ')'; 6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fTokenLength > 0) { 6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = handleProperty(); 6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(success); 6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int branchIndex = 0; 6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com branchBalance = fBranchStack.count() - branchBalance; 6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBranchPopAllowed = false; 6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (branchIndex < branchBalance) { 6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Branch& branch = fBranchStack.index(branchIndex++); 6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (branch.fPrimed == Branch::kIsPrimed) 7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Op branchOp = branch.fOperator; 7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkOperand2::OpType lastType = fValueStack.top().fType; 7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenValue(fValueStack.top(), kAccumulator); 7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.pop(); 7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (branchOp == kLogicalAnd || branchOp == kLogicalOr) { 7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (branch.fOperator == kLogicalAnd) 7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com branch.prime(); 7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(kToBool); 7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com resolveBranch(branch); 7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2 operand; 7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fType = lastType; 7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // !!! note that many branching expressions could be constant 7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // today, we always evaluate branches as returning variables 7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fIsConstant = SkScriptValue2::kVariable; 7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.push(operand); 7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (branch.fDone == Branch::kIsNotDone) 7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com branch.prime(); 7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBranchPopAllowed = true; 7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (fBranchStack.top().fDone == Branch::kIsDone) 7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBranchStack.pop(); 7248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (fOpStack.count() > opBalance) { // leave open paren 7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (processOp() == false) 7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkOperand2::OpType topType = fValueStack.count() > 0 ? fValueStack.top().fType : SkOperand2::kNoType; 7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (topType != fReturnType && 7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com topType == SkOperand2::kString && fReturnType != SkOperand2::kNoType) { // if result is a string, give handle property a chance to convert it to the property value 7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkString* string = fValueStack.top().fOperand.fString; 7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fToken = string->c_str(); 7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTokenLength = string->size(); 7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.pop(); 7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = handleProperty(); 7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (success == false) { // if it couldn't convert, return string (error?) 7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2 operand; 7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fType = SkOperand2::kString; 7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fOperand.fString = string; 7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fIsConstant = SkScriptValue2::kVariable; // !!! ? 7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.push(operand); 7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fStream.getOffset() > 0) { 7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(kEnd); 7468a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com SkAutoDataUnref data(fStream.copyToData()); 7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 74841f9e6e45d54c73cc0cc4f84b46b48f9480ff396robertphillips@google.com decompile(data->bytes(), data->size()); 7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptRuntime runtime(fCallBackArray); 75159f46b81f8bdd1b524f5cc43bc27603f9604c71arobertphillips@google.com runtime.executeTokens((unsigned char*) data->bytes()); 7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2 value1; 7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runtime.getResult(&value1.fOperand); 7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value1.fType = fReturnType; 7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.push(value1); 7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value) { 7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fValueStack.count() == 0) 7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.pop(value); 761d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if (value->fType != fReturnType && value->fType == SkOperand2::kObject && 7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fReturnType != SkOperand2::kNoType) 7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com convertTo(fReturnType, value); 7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if (fBranchStack.top().fOpStackDepth > fOpStack.count()) 7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // resolveBranch(); 7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *scriptPtr = script; 7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; // no error 7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkScriptEngine2::handleArrayIndexer(const char** scriptPtr) { 7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2 scriptValue; 7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (*scriptPtr)++; 7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fOpStack.push() = (Op) kParen; 7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fBraceStack.push() = kArrayBrace; 7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkOperand2::OpType saveType = fReturnType; 7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fReturnType = SkOperand2::kS32; 7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool success = innerScript(scriptPtr, &scriptValue); 7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fReturnType = saveType; 7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(success); 7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = convertTo(SkOperand2::kS32, &scriptValue); 7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(success); 7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = scriptValue.fOperand.fS32; 7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.pop(&scriptValue); 7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scriptValue.fType == SkOperand2::kObject) { 7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = handleUnbox(&scriptValue); 7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(success); 7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(scriptValue.fType == SkOperand2::kArray); 7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scriptValue.fType = scriptValue.fOperand.fArray->getType(); 7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // SkASSERT(index >= 0); 7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((unsigned) index >= (unsigned) scriptValue.fOperand.fArray->count()) { 7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fError = kArrayIndexOutOfBounds; 7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scriptValue.fOperand = scriptValue.fOperand.fArray->begin()[index]; 7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scriptValue.fIsConstant = SkScriptValue2::kVariable; 7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.push(scriptValue); 7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOpStack.pop(); // pop paren 8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return success; 8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkScriptEngine2::handleFunction(const char** scriptPtr) { 8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* functionName = fToken; 8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t functionNameLen = fTokenLength; 8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTokenLength = 0; 8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTDArray<SkScriptValue2> params; 8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool success = functionParams(scriptPtr, ¶ms); 8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (success == false) 8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto done; 8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (SkScriptCallBack** callBack = fCallBackArray.begin(); callBack < fCallBackArray.end(); callBack++) { 8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((*callBack)->getType() != SkScriptCallBack::kFunction) 8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2 callbackResult; 8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = (*callBack)->getReference(functionName, functionNameLen, &callbackResult); 8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (success) { 8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com callbackResult.fType = (*callBack)->getReturnType(callbackResult.fOperand.fReference, NULL); 8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com callbackResult.fIsConstant = SkScriptValue2::kVariable; 8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.push(callbackResult); 8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto done; 8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comdone: 8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOpStack.pop(); 8288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return success; 8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkScriptEngine2::handleMember(const char* field, size_t len, void* object) { 8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool success = true; 8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (SkScriptCallBack** callBack = fCallBackArray.begin(); callBack < fCallBackArray.end(); callBack++) { 8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((*callBack)->getType() != SkScriptCallBack::kMember) 8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 8368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2 callbackResult; 8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = (*callBack)->getReference(field, len, &callbackResult); 8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (success) { 8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (callbackResult.fType == SkOperand2::kString) 8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com track(callbackResult.fOperand.fString); 8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com callbackResult.fIsConstant = SkScriptValue2::kVariable; 8428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.push(callbackResult); 8438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto done; 8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comdone: 8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return success; 8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 851d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.combool SkScriptEngine2::handleMemberFunction(const char* field, size_t len, void* object, 8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTDArray<SkScriptValue2>* params) { 8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool success = true; 8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (SkScriptCallBack** callBack = fCallBackArray.begin(); callBack < fCallBackArray.end(); callBack++) { 8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((*callBack)->getType() != SkScriptCallBack::kMemberFunction) 8568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 8578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2 callbackResult; 8588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = (*callBack)->getReference(field, len, &callbackResult); 8598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (success) { 8608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (callbackResult.fType == SkOperand2::kString) 8618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com track(callbackResult.fOperand.fString); 8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com callbackResult.fIsConstant = SkScriptValue2::kVariable; 8638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.push(callbackResult); 8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto done; 8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comdone: 8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return success; 8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkScriptEngine2::handleProperty() { 8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool success = true; 8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (SkScriptCallBack** callBack = fCallBackArray.begin(); callBack < fCallBackArray.end(); callBack++) { 8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((*callBack)->getType() != SkScriptCallBack::kProperty) 8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2 callbackResult; 8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = (*callBack)->getReference(fToken, fTokenLength, &callbackResult); 8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (success) { 8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (callbackResult.fType == SkOperand2::kString && callbackResult.fOperand.fString == NULL) { 8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com callbackResult.fOperand.fString = new SkString(fToken, fTokenLength); 8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com track(callbackResult.fOperand.fString); 8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com callbackResult.fIsConstant = SkScriptValue2::kVariable; 8858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.push(callbackResult); 8868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto done; 8878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comdone: 8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTokenLength = 0; 8918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return success; 8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkScriptEngine2::handleUnbox(SkScriptValue2* scriptValue) { 8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool success = true; 8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (SkScriptCallBack** callBack = fCallBackArray.begin(); callBack < fCallBackArray.end(); callBack++) { 8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((*callBack)->getType() != SkScriptCallBack::kUnbox) 8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptCallBackConvert* callBackConvert = (SkScriptCallBackConvert*) *callBack; 9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = callBackConvert->convert(scriptValue->fType, &scriptValue->fOperand); 9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (success) { 9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scriptValue->fType == SkOperand2::kString) 9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com track(scriptValue->fOperand.fString); 9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto done; 9058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comdone: 9098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return success; 9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// note that entire expression is treated as if it were enclosed in parens 9138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// an open paren is always the first thing in the op stack 9148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comint SkScriptEngine2::logicalOp(char ch, char nextChar) { 9168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int advance = 1; 9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Op op; 9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com signed char precedence; 9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (ch) { 9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case ')': 9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = (Op) kParen; 9228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 9238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case ']': 9248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = (Op) kArrayOp; 9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '?': 9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = (Op) kIf; 9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case ':': 9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = (Op) kElse; 9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '&': 9338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (nextChar != '&') 9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto noMatch; 9358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kLogicalAnd; 9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com advance = 2; 9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case '|': 9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (nextChar != '|') 9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto noMatch; 9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = kLogicalOr; 9428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com advance = 2; 9438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 9458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com noMatch: 9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return 0; 9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com precedence = gPrecedence[op]; 9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int branchIndex = 0; 9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBranchPopAllowed = false; 9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (gPrecedence[fOpStack.top() & ~kArtificialOp] < precedence) 9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com processOp(); 9548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Branch& branch = fBranchStack.index(branchIndex++); 9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Op branchOp = branch.fOperator; 9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (gPrecedence[branchOp] >= precedence) 9578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 9588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenValue(fValueStack.top(), kAccumulator); 9598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.pop(); 9608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (branchOp == kLogicalAnd || branchOp == kLogicalOr) { 9618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (branch.fOperator == kLogicalAnd) 9628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com branch.prime(); 9638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(kToBool); 9648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else 9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com resolveBranch(branch); 9668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (branch.fDone == Branch::kIsNotDone) 9678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com branch.prime(); 9688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (true); 9698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBranchPopAllowed = true; 9708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (fBranchStack.top().fDone == Branch::kIsDone) 9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBranchStack.pop(); 9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com processLogicalOp(op); 9738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return advance; 9748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkScriptEngine2::processLogicalOp(Op op) { 9778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (op) { 9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case kParen: 9798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case kArrayOp: 9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fOpStack.count() > 1 && fOpStack.top() == op); // !!! add error handling 981d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if (op == kParen) 9828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOpStack.pop(); 9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else { 9848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2 value; 9858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.pop(&value); 9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(value.fType == SkOperand2::kS32 || value.fType == SkOperand2::kScalar); // !!! add error handling (although, could permit strings eventually) 987e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int index = value.fType == SkOperand2::kScalar ? SkScalarFloorToInt(value.fOperand.fScalar) : 9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value.fOperand.fS32; 9898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2 arrayValue; 9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.pop(&arrayValue); 9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(arrayValue.fType == SkOperand2::kArray); // !!! add error handling 9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkOpArray* array = arrayValue.fOperand.fArray; 9938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkOperand2 operand; 9940e51577a14f903ffeafa117a75954baeb173ffb9humper@google.com SkDEBUGCODE(bool success = ) array->getIndex(index, &operand); 9958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(success); // !!! add error handling 9968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2 resultValue; 9978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com resultValue.fType = array->getType(); 9988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com resultValue.fOperand = operand; 9998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com resultValue.fIsConstant = SkScriptValue2::kVariable; 10008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.push(resultValue); 10018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 10038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case kIf: { 10048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fAccumulatorType == SkOperand2::kNoType) { 10058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenValue(fValueStack.top(), kAccumulator); 10068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.pop(); 10078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fAccumulatorType != SkOperand2::kString); // !!! add error handling 10098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(kIfOp); 10108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Branch branch(op, fOpStack.count(), getTokenOffset()); 10118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fBranchStack.push() = branch; 10128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenInt(0); // placeholder for future branch 10138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAccumulatorType = SkOperand2::kNoType; 10148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } break; 10158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case kElse: { 10168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenValue(fValueStack.top(), kAccumulator); 10178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.pop(); 10188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(kElseOp); 10198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t newOffset = getTokenOffset(); 10208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenInt(0); // placeholder for future branch 10218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Branch& branch = fBranchStack.top(); 10228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com resolveBranch(branch); 10238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com branch.fOperator = op; 10248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com branch.fDone = Branch::kIsNotDone; 10258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(branch.fOpStackDepth == fOpStack.count()); 102692f93264e760b74cc706d01b2d0fcfaa3d857f51commit-bot@chromium.org branch.fOffset = SkToU16(newOffset); 10278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAccumulatorType = SkOperand2::kNoType; 10288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } break; 10298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case kLogicalAnd: 10308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case kLogicalOr: { 10318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Branch& oldTop = fBranchStack.top(); 10328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Branch::Primed wasPrime = oldTop.fPrimed; 10338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Branch::Done wasDone = oldTop.fDone; 10348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com oldTop.fPrimed = Branch::kIsNotPrimed; 10358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com oldTop.fDone = Branch::kIsNotDone; 10368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fAccumulatorType == SkOperand2::kNoType) { 10378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fValueStack.top().fType == SkOperand2::kS32); // !!! add error handling, and conversion to int? 10388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenValue(fValueStack.top(), kAccumulator); 10398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.pop(); 1040a7ed3cc6371e50a5beb3750c475fe23665dafa7dtomhudson@google.com } else { 10418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fAccumulatorType == SkOperand2::kS32); 1042a7ed3cc6371e50a5beb3750c475fe23665dafa7dtomhudson@google.com } 10438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if 'and', write beq goto opcode after end of predicate (after to bool) 10448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if 'or', write bne goto to bool 10458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(op == kLogicalAnd ? kLogicalAndInt : kLogicalOrInt); 10468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Branch branch(op, fOpStack.count(), getTokenOffset()); 1047d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com addTokenInt(0); // placeholder for future branch 10488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com oldTop.fPrimed = wasPrime; 10498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com oldTop.fDone = wasDone; 10508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *fBranchStack.push() = branch; 10518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAccumulatorType = SkOperand2::kNoType; 10528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } break; 10538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 10548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 10558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkScriptEngine2::processOp() { 10598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Op op; 10608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOpStack.pop(&op); 10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = (Op) (op & ~kArtificialOp); 10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const OperatorAttributes* attributes = &gOpAttributes[op]; 106364cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org SkScriptValue2 value1; 106464cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org memset(&value1, 0, sizeof(SkScriptValue2)); 10658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2 value2; 10668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.pop(&value2); 10678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value2.fIsWritten = SkScriptValue2::kUnwritten; 10688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // SkScriptEngine2::SkTypeOp convert1[3]; 10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // SkScriptEngine2::SkTypeOp convert2[3]; 10708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // SkScriptEngine2::SkTypeOp* convert2Ptr = convert2; 10718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool constantOperands = value2.fIsConstant == SkScriptValue2::kConstant; 10728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (attributes->fLeftType != SkOperand2::kNoType) { 10738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.pop(&value1); 1074d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com constantOperands &= value1.fIsConstant == SkScriptValue2::kConstant; 10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value1.fIsWritten = SkScriptValue2::kUnwritten; 10768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (op == kFlipOps) { 10778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTSwap(value1, value2); 10788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOpStack.pop(&op); 10798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com op = (Op) (op & ~kArtificialOp); 10808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com attributes = &gOpAttributes[op]; 10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (constantOperands == false) 10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(kFlipOpsOp); 10838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value1.fType == SkOperand2::kObject && (value1.fType & attributes->fLeftType) == 0) { 10858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value1.fType = getUnboxType(value1.fOperand); 10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(kUnboxToken); 10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value2.fType == SkOperand2::kObject && (value2.fType & attributes->fLeftType) == 0) { 10908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value1.fType = getUnboxType(value2.fOperand); 10918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(kUnboxToken2); 10928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (attributes->fLeftType != SkOperand2::kNoType) { 10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value1.fType != value2.fType) { 1095d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if ((attributes->fLeftType & SkOperand2::kString) && attributes->fBias & kTowardsString && 10968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ((value1.fType | value2.fType) & SkOperand2::kString)) { 10978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value1.fType == SkOperand2::kS32 || value1.fType == SkOperand2::kScalar) { 1098d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com addTokenConst(&value1, kAccumulator, SkOperand2::kString, 10998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value1.fType == SkOperand2::kS32 ? kIntToString : kScalarToString); 11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value2.fType == SkOperand2::kS32 || value2.fType == SkOperand2::kScalar) { 1102d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com addTokenConst(&value2, kOperand, SkOperand2::kString, 11038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value2.fType == SkOperand2::kS32 ? kIntToString2 : kScalarToString2); 11048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1105d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } else if (attributes->fLeftType & SkOperand2::kScalar && ((value1.fType | value2.fType) & 11068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkOperand2::kScalar)) { 11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value1.fType == SkOperand2::kS32) 11088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenConst(&value1, kAccumulator, SkOperand2::kScalar, kIntToScalar); 11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value2.fType == SkOperand2::kS32) 11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenConst(&value2, kOperand, SkOperand2::kScalar, kIntToScalar2); 11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((value1.fType & attributes->fLeftType) == 0 || value1.fType != value2.fType) { 11148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value1.fType == SkOperand2::kString) 11158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenConst(&value1, kAccumulator, SkOperand2::kScalar, kStringToScalar); 1116d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if (value1.fType == SkOperand2::kScalar && (attributes->fLeftType == SkOperand2::kS32 || 11178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value2.fType == SkOperand2::kS32)) 11188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenConst(&value1, kAccumulator, SkOperand2::kS32, kScalarToInt); 11198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AddTokenRegister rhRegister = attributes->fLeftType != SkOperand2::kNoType ? 11228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kOperand : kAccumulator; 11238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((value2.fType & attributes->fRightType) == 0 || value1.fType != value2.fType) { 11248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value2.fType == SkOperand2::kString) 11258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenConst(&value2, rhRegister, SkOperand2::kScalar, kStringToScalar2); 1126d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if (value2.fType == SkOperand2::kScalar && (attributes->fRightType == SkOperand2::kS32 || 11278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value1.fType == SkOperand2::kS32)) 11288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenConst(&value2, rhRegister, SkOperand2::kS32, kScalarToInt2); 11298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com TypeOp typeOp = gTokens[op]; 11318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value2.fType == SkOperand2::kScalar) 11328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typeOp = (TypeOp) (typeOp + 1); 11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else if (value2.fType == SkOperand2::kString) 11348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typeOp = (TypeOp) (typeOp + 2); 11358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDynamicMemoryWStream stream; 1136a7ed3cc6371e50a5beb3750c475fe23665dafa7dtomhudson@google.com SkOperand2::OpType saveType = SkOperand2::kNoType; 1137a7ed3cc6371e50a5beb3750c475fe23665dafa7dtomhudson@google.com SkBool saveOperand = false; 11388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (constantOperands) { 11398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fActiveStream = &stream; 11408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com saveType = fAccumulatorType; 11418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com saveOperand = fOperandInUse; 11428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAccumulatorType = SkOperand2::kNoType; 11438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOperandInUse = false; 11448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (attributes->fLeftType != SkOperand2::kNoType) { // two operands 11468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value1.fIsWritten == SkScriptValue2::kUnwritten) 11478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenValue(value1, kAccumulator); 11488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value2.fIsWritten == SkScriptValue2::kUnwritten) 11508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addTokenValue(value2, rhRegister); 11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(typeOp); 11528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (constantOperands) { 11538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com addToken(kEnd); 11548a85d0c4938173476d037d7af0ee3b9436a1234ereed@google.com SkAutoDataUnref data(fStream.copyToData()); 1155d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com#ifdef SK_DEBUG 115641f9e6e45d54c73cc0cc4f84b46b48f9480ff396robertphillips@google.com decompile(data->bytes(), data->size()); 11578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 11588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptRuntime runtime(fCallBackArray); 115959f46b81f8bdd1b524f5cc43bc27603f9604c71arobertphillips@google.com runtime.executeTokens((unsigned char*)data->bytes()); 11608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runtime.getResult(&value1.fOperand); 11618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (attributes->fResultIsBoolean == kResultIsBoolean) 11628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value1.fType = SkOperand2::kS32; 11638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else if (attributes->fLeftType == SkOperand2::kNoType) // unary operand 11648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value1.fType = value2.fType; 11658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.push(value1); 11668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value1.fType == SkOperand2::kString) 11678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runtime.untrack(value1.fOperand.fString); 11688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else if (value1.fType == SkOperand2::kArray) 11698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runtime.untrack(value1.fOperand.fArray); 11708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fActiveStream = &fStream; 11718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAccumulatorType = saveType; 11728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOperandInUse = saveOperand; 11738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 11748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value2.fIsConstant = SkScriptValue2::kVariable; 11768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fValueStack.push(value2); 11778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 11788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkScriptEngine2::Branch::resolve(SkDynamicMemoryWStream* stream, size_t off) { 11818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fDone == kIsNotDone); 11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPrimed = kIsNotPrimed; 11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDone = kIsDone; 11848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(off > fOffset + sizeof(size_t)); 11858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t offset = off - fOffset - sizeof(offset); 11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stream->write(&offset, fOffset, sizeof(offset)); 11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkScriptEngine2::resolveBranch(SkScriptEngine2::Branch& branch) { 11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com branch.resolve(fActiveStream, getTokenOffset()); 11918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkScriptEngine2::ConvertTo(SkScriptEngine2* engine, SkOperand2::OpType toType, SkScriptValue2* value ) { 11948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(value); 11958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkOperand2::OpType type = value->fType; 1196d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if (type == toType) 11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkOperand2& operand = value->fOperand; 11998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool success = true; 12008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (toType) { 12018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkOperand2::kS32: 12028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (type == SkOperand2::kScalar) 1203e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com operand.fS32 = SkScalarFloorToInt(operand.fScalar); 12048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else { 12058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(type == SkOperand2::kString); 12068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = SkParse::FindS32(operand.fString->c_str(), &operand.fS32) != NULL; 12078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 12098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkOperand2::kScalar: 12108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (type == SkOperand2::kS32) 12118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fScalar = IntToScalar(operand.fS32); 12128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else { 12138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(type == SkOperand2::kString); 12148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com success = SkParse::FindScalar(operand.fString->c_str(), &operand.fScalar) != NULL; 12158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 12178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkOperand2::kString: { 12188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkString* strPtr = new SkString(); 12198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(engine); 12208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com engine->track(strPtr); 12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (type == SkOperand2::kS32) 12228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com strPtr->appendS32(operand.fS32); 12238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else { 12248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(type == SkOperand2::kScalar); 12258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com strPtr->appendScalar(operand.fScalar); 12268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fString = strPtr; 12288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } break; 12298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkOperand2::kArray: { 12308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkOpArray* array = new SkOpArray(type); 12318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *array->append() = operand; 12328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com engine->track(array); 12338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com operand.fArray = array; 12348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } break; 12358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 12368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com value->fType = toType; 12398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return success; 12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkScalar SkScriptEngine2::IntToScalar(int32_t s32) { 12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar scalar; 124464cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org if (s32 == (int32_t) SK_NaN32) 12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scalar = SK_ScalarNaN; 12468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else if (SkAbs32(s32) == SK_MaxS32) 12478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scalar = SkSign32(s32) * SK_ScalarMax; 12488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com else 12498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scalar = SkIntToScalar(s32); 12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return scalar; 12518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkScriptEngine2::ValueToString(const SkScriptValue2& value, SkString* string) { 12548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (value.fType) { 12558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkOperand2::kS32: 12568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com string->reset(); 12578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com string->appendS32(value.fOperand.fS32); 12588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 12598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkOperand2::kScalar: 12608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com string->reset(); 12618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com string->appendScalar(value.fOperand.fScalar); 12628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 12638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkOperand2::kString: 12648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com string->set(*value.fOperand.fString); 12658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 12668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 12678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 12688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 12698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; // no error 12718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 12749c55f801a35b0d6c39f007fae432bd13094f3c52sugoi@google.com#if defined(SK_SUPPORT_UNITTEST) 12758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 127664cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org#define testInt(expression) { #expression, SkOperand2::kS32, expression, 0, NULL } 1277100abf49e10544bc4f436bf1f38e6929779621f4bsalomon@google.com#define testScalar(expression) { #expression, SkOperand2::kScalar, 0, (float) (expression), NULL } 1278100abf49e10544bc4f436bf1f38e6929779621f4bsalomon@google.com#define testRemainder(exp1, exp2) { #exp1 "%" #exp2, SkOperand2::kScalar, 0, fmodf((float) exp1, (float) exp2), NULL } 127964cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org#define testTrue(expression) { #expression, SkOperand2::kS32, 1, 0, NULL } 128064cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org#define testFalse(expression) { #expression, SkOperand2::kS32, 0, 0, NULL } 12818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic const SkScriptNAnswer2 scriptTests[] = { 128364cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org testInt(1||(0&&3)), 12848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testScalar(- -5.5- -1.5), 1285d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com testScalar(1.0+5), 12868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt((6+7)*8), 12878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(3*(4+5)), 12888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testScalar(1.0+2.0), 1289d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com testScalar(3.0-1.0), 1290d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com testScalar(6-1.0), 1291d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com testScalar(2.5*6.), 1292d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com testScalar(0.5*4), 1293d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com testScalar(4.5/.5), 1294d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com testScalar(9.5/19), 1295d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com testRemainder(9.5, 0.5), 1296d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com testRemainder(9.,2), 12978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testRemainder(9,2.5), 12988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testRemainder(-9,2.5), 12998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue(-9==-9.0), 13008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue(-9.==-4.0-5), 13018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue(-9.*1==-4-5), 13028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse(-9!=-9.0), 13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse(-9.!=-4.0-5), 13048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse(-9.*1!=-4-5), 13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(0x123), 13068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(0XABC), 13078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(0xdeadBEEF), 13088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { "'123'+\"456\"", SkOperand2::kString, 0, 0, "123456" }, 13098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { "123+\"456\"", SkOperand2::kString, 0, 0, "123456" }, 13108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { "'123'+456", SkOperand2::kString, 0, 0, "123456" }, 131164cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org { "'123'|\"456\"", SkOperand2::kS32, 123|456, 0, NULL }, 131264cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org { "123|\"456\"", SkOperand2::kS32, 123|456, 0, NULL }, 131364cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org { "'123'|456", SkOperand2::kS32, 123|456, 0, NULL }, 131464cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org { "'2'<11", SkOperand2::kS32, 1, 0, NULL }, 131564cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org { "2<'11'", SkOperand2::kS32, 1, 0, NULL }, 131664cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org { "'2'<'11'", SkOperand2::kS32, 0, 0, NULL }, 13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(123), 13188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(-345), 13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(+678), 13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(1+2+3), 13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(3*4+5), 13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(6+7*8), 13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(-1-2-8/4), 13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(-9%4), 13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(9%-4), 13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(-9%-4), 13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(123|978), 13288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(123&978), 13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(123^978), 13308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2<<4), 13318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(99>>3), 13328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(~55), 13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(~~55), 13348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(!55), 13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(!!55), 13368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // both int 13378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2<2), 13388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2<11), 13398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20<11), 13408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2<=2), 13418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2<=11), 13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20<=11), 13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2>2), 13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2>11), 13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20>11), 13468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2>=2), 13478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2>=11), 13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20>=11), 13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2==2), 13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2==11), 13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20==11), 13528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2!=2), 13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2!=11), 13548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20!=11), 13558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // left int, right scalar 13568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2<2.), 13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2<11.), 13588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20<11.), 13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2<=2.), 13608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2<=11.), 13618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20<=11.), 13628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2>2.), 13638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2>11.), 13648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20>11.), 13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2>=2.), 13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2>=11.), 13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20>=11.), 13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2==2.), 13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2==11.), 13708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20==11.), 13718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2!=2.), 13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2!=11.), 13738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20!=11.), 13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // left scalar, right int 13758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.<2), 13768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.<11), 13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20.<11), 13788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.<=2), 13798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.<=11), 13808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20.<=11), 13818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.>2), 13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.>11), 13838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20.>11), 13848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.>=2), 13858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.>=11), 13868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20.>=11), 13878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.==2), 13888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.==11), 13898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20.==11), 13908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.!=2), 13918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.!=11), 13928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20.!=11), 13938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // both scalar 13948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.<11.), 13958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20.<11.), 13968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.<=2.), 13978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.<=11.), 13988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20.<=11.), 13998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.>2.), 14008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.>11.), 14018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20.>11.), 14028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.>=2.), 14038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.>=11.), 14048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20.>=11.), 14058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.==2.), 14068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.==11.), 14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20.==11.), 14088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.!=2.), 14098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(2.!=11.), 14108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(20.!=11.), 14118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // int, string (string is int) 14128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse(2<'2'), 14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue(2<'11'), 14148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse(20<'11'), 14158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue(2<='2'), 14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue(2<='11'), 14178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse(20<='11'), 14188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse(2>'2'), 14198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse(2>'11'), 14208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue(20>'11'), 14218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue(2>='2'), 14228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse(2>='11'), 14238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue(20>='11'), 14248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue(2=='2'), 14258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse(2=='11'), 14268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse(2!='2'), 14278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue(2!='11'), 14288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // int, string (string is scalar) 14298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse(2<'2.'), 14308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue(2<'11.'), 14318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse(20<'11.'), 14328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue(2=='2.'), 14338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse(2=='11.'), 14348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // scalar, string 14358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse(2.<'2.'), 14368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue(2.<'11.'), 14378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse(20.<'11.'), 14388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue(2.=='2.'), 14398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse(2.=='11.'), 14408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // string, int 14418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse('2'<2), 14428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue('2'<11), 14438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse('20'<11), 14448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue('2'==2), 14458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse('2'==11), 14468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // string, scalar 14478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse('2'<2.), 14488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue('2'<11.), 14498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse('20'<11.), 14508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue('2'==2.), 14518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse('2'==11.), 14528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // string, string 14538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse('2'<'2'), 14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse('2'<'11'), 14558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse('20'<'11'), 14568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testTrue('2'=='2'), 14578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testFalse('2'=='11'), 14588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // logic 14598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(1?2:3), 14608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(0?2:3), 146164cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org testInt((1&&2)||3), 146264cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org testInt((1&&0)||3), 146364cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org testInt((1&&0)||0), 146464cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org testInt(1||(0&&3)), 146564cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org testInt(0||(0&&3)), 146664cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org testInt(0||(1&&3)), 14678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com testInt(0&&1?2:3) 146864cc579efa7e416c7298ed159d76b074b283c0f9senorblanco@chromium.org , { "123.5", SkOperand2::kScalar, 0, SkIntToScalar(123) + SK_Scalar1/2, NULL } 14698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 14708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkScriptNAnswer_testCount SK_ARRAY_COUNT(scriptTests) 14729c55f801a35b0d6c39f007fae432bd13094f3c52sugoi@google.com#endif // SK_SUPPORT_UNITTEST 14738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkScriptEngine2::UnitTest() { 1475ec10d21eb9a17639688188b0defce6d757331eb4reed@android.com#if defined(SK_SUPPORT_UNITTEST) 14768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ValidateDecompileTable(); 14772dc8b96230c99cd460c02fdb69b036905d072216commit-bot@chromium.org for (size_t index = 0; index < SkScriptNAnswer_testCount; index++) { 14788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptEngine2 engine(scriptTests[index].fType); 14798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScriptValue2 value; 14808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* script = scriptTests[index].fScript; 14818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* scriptPtr = script; 14828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(engine.evaluateScript(&scriptPtr, &value) == true); 14838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(value.fType == scriptTests[index].fType); 14848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar error; 14858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (value.fType) { 14868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkOperand2::kS32: 14878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (value.fOperand.fS32 != scriptTests[index].fIntAnswer) 14888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGF(("script '%s' == value %d != expected answer %d\n", script, value.fOperand.fS32, scriptTests[index].fIntAnswer)); 14898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(value.fOperand.fS32 == scriptTests[index].fIntAnswer); 14908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 14918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkOperand2::kScalar: 14928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com error = SkScalarAbs(value.fOperand.fScalar - scriptTests[index].fScalarAnswer); 14938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (error >= SK_Scalar1 / 10000) 14948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGF(("script '%s' == value %g != expected answer %g\n", script, value.fOperand.fScalar / (1.0f * SK_Scalar1), scriptTests[index].fScalarAnswer / (1.0f * SK_Scalar1))); 14958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(error < SK_Scalar1 / 10000); 14968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 14978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkOperand2::kString: 14988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(value.fOperand.fString->equals(scriptTests[index].fStringAnswer)); 14998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 15008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 15018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0); 15028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15049c55f801a35b0d6c39f007fae432bd13094f3c52sugoi@google.com#endif // SK_SUPPORT_UNITTEST 15058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15069c55f801a35b0d6c39f007fae432bd13094f3c52sugoi@google.com#endif // SK_DEBUG 1507