11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc.
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkScript2.h"
91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkData.h"
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkFloatingPoint.h"
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkMath.h"
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkParse.h"
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkScriptCallBack.h"
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkScriptRuntime.h"
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkString.h"
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkOpArray.h"
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectconst SkScriptEngine2::OperatorAttributes SkScriptEngine2::gOpAttributes[] = {
190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger{ SkOperand2::kNoType, SkOperand2::kNoType, kNoBias, kResultIsNotBoolean },
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar | SkOperand2::kString),
210b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar | SkOperand2::kString), kTowardsString, kResultIsNotBoolean },    // kAdd
220b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger{ SkOperand2::kS32, SkOperand2::kS32, kNoBias, kResultIsNotBoolean }, // kBitAnd
230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger{ SkOperand2::kNoType, SkOperand2::kS32, kNoBias, kResultIsNotBoolean }, // kBitNot
240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger{ SkOperand2::kS32, SkOperand2::kS32, kNoBias, kResultIsNotBoolean }, // kBitOr
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar),
260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar), kNoBias, kResultIsNotBoolean }, // kDivide
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar | SkOperand2::kString),
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar |SkOperand2:: kString), kTowardsNumber,
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kResultIsBoolean }, // kEqual
300b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger{ SkOperand2::kS32, SkOperand2::kNoType, kNoBias, kResultIsNotBoolean },     // kFlipOps
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar | SkOperand2::kString),
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar | SkOperand2::kString), kTowardsNumber,
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kResultIsBoolean }, // kGreaterEqual
340b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger{ SkOperand2::kNoType, SkOperand2::kS32, kNoBias, kResultIsNotBoolean }, // kLogicalAnd    (really, ToBool)
350b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger{ SkOperand2::kNoType, SkOperand2::kS32, kNoBias, kResultIsNotBoolean }, // kLogicalNot
360b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger{ SkOperand2::kS32, SkOperand2::kS32, kNoBias, kResultIsNotBoolean }, // kLogicalOr
370b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger{ SkOperand2::kNoType, SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar), kNoBias, kResultIsNotBoolean }, // kMinus
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar),
390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkOperand2::OpType(SkOperand2::kS32 |SkOperand2:: kScalar), kNoBias, kResultIsNotBoolean }, // kModulo
400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar),
410b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar), kNoBias, kResultIsNotBoolean }, // kMultiply
420b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger{ SkOperand2::kS32, SkOperand2::kS32, kNoBias, kResultIsNotBoolean }, // kShiftLeft
430b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger{ SkOperand2::kS32, SkOperand2::kS32, kNoBias, kResultIsNotBoolean }, // kShiftRight
440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{ SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar),
450b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkOperand2::OpType(SkOperand2::kS32 | SkOperand2::kScalar), kNoBias, kResultIsNotBoolean }, // kSubtract
460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger{ SkOperand2::kS32, SkOperand2::kS32, kNoBias, kResultIsNotBoolean } // kXor
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define kBracketPrecedence 16
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define kIfElsePrecedence 15
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectconst signed char SkScriptEngine2::gPrecedence[] = {
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    17, // kUnassigned,
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    6, // kAdd,
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    10, // kBitAnd,
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    4, // kBitNot,
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    12, // kBitOr,
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    5, // kDivide,
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    9, // kEqual,
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    -1, // kFlipOps,
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    8, // kGreaterEqual,
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    13, // kLogicalAnd,
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    4, // kLogicalNot,
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    14, // kLogicalOr,
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    4, // kMinus,
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    5, // kModulo,
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    5, // kMultiply,
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    7, // kShiftLeft,
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    7, // kShiftRight,    // signed
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    6, // kSubtract,
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    11, // kXor
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kBracketPrecedence, // kArrayOp
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kIfElsePrecedence, // kElse
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kIfElsePrecedence, // kIf
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kBracketPrecedence, // kParen
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectconst SkScriptEngine2::TypeOp SkScriptEngine2::gTokens[] = {
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kNop, // unassigned
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kAddInt, // kAdd,
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kBitAndInt, // kBitAnd,
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kBitNotInt, // kBitNot,
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kBitOrInt, // kBitOr,
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kDivideInt, // kDivide,
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kEqualInt, // kEqual,
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kFlipOpsOp, // kFlipOps,
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kGreaterEqualInt, // kGreaterEqual,
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kLogicalAndInt, // kLogicalAnd,
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kLogicalNotInt, // kLogicalNot,
900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kLogicalOrInt, // kLogicalOr,
910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kMinusInt, // kMinus,
920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kModuloInt, // kModulo,
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kMultiplyInt, // kMultiply,
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kShiftLeftInt, // kShiftLeft,
950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kShiftRightInt, // kShiftRight,    // signed
960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kSubtractInt, // kSubtract,
970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    kXorInt // kXor
980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline bool is_between(int c, int min, int max)
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return (unsigned)(c - min) <= (unsigned)(max - min);
1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline bool is_ws(int c)
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return is_between(c, 1, 32);
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic int token_length(const char* start) {
1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    char ch = start[0];
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (! is_between(ch, 'a' , 'z') &&  ! is_between(ch, 'A', 'Z') && ch != '_' && ch != '$')
1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return -1;
1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int length = 0;
1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    do
1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        ch = start[++length];
1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while (is_between(ch, 'a' , 'z') || is_between(ch, 'A', 'Z') || is_between(ch, '0', '9') ||
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project           ch == '_' || ch == '$');
1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return length;
1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScriptEngine2::SkScriptEngine2(SkOperand2::OpType returnType) : fActiveStream(&fStream),
1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectfTokenLength(0), fReturnType(returnType), fError(kNoError),
1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectfAccumulatorType(SkOperand2::kNoType),
1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectfBranchPopAllowed(true), fConstExpression(true), fOperandInUse(false)
1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    Branch branch(kUnassigned, 0, 0);
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fBranchStack.push(branch);
1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *fOpStack.push() = (Op) kParen;
1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScriptEngine2::~SkScriptEngine2() {
1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    for (SkString** stringPtr = fTrackString.begin(); stringPtr < fTrackString.end(); stringPtr++)
1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        delete *stringPtr;
1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    for (SkOpArray** arrayPtr = fTrackArray.begin(); arrayPtr < fTrackArray.end(); arrayPtr++)
1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        delete *arrayPtr;
1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScriptEngine2::addToken(SkScriptEngine2::TypeOp op) {
1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int limit = fBranchStack.count() - 1;
1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    for (int index = 0; index < limit; index++) {
1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Branch& branch = fBranchStack.index(index);
1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (branch.fPrimed == Branch::kIsPrimed)
1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            resolveBranch(branch);
1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fBranchPopAllowed) {
1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        while (fBranchStack.top().fDone == Branch::kIsDone)
1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fBranchStack.pop();
1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    unsigned char charOp = (unsigned char) op;
1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fActiveStream->write(&charOp, sizeof(charOp));
1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScriptEngine2::addTokenConst(SkScriptValue2* value, AddTokenRegister reg,
1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                    SkOperand2::OpType toType, SkScriptEngine2::TypeOp op) {
1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (value->fIsConstant == SkScriptValue2::kConstant && convertTo(toType, value))
1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return;
1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    addTokenValue(*value, reg);
1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    addToken(op);
1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    value->fIsWritten = SkScriptValue2::kWritten;
1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    value->fType = toType;
1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScriptEngine2::addTokenInt(int integer) {
1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fActiveStream->write(&integer, sizeof(integer));
1660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScriptEngine2::addTokenScalar(SkScalar scalar) {
1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fActiveStream->write(&scalar, sizeof(scalar));
1700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScriptEngine2::addTokenString(const SkString& string) {
1730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int size = string.size();
1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    addTokenInt(size);
1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fActiveStream->write(string.c_str(), size);
1760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScriptEngine2::addTokenValue(const SkScriptValue2& value, AddTokenRegister reg) {
1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (value.isConstant() == false) {
1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (reg == kAccumulator) {
1810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (fAccumulatorType == SkOperand2::kNoType)
1820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                addToken(kAccumulatorPop);
1830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else {
1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            ; // !!! incomplete?
1850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
1860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return;
1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (reg == kAccumulator && fAccumulatorType != SkOperand2::kNoType)
1890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        addToken(kAccumulatorPush);
1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    switch (value.fType) {
1910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkOperand2::kS32:
1920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addToken(reg == kAccumulator ? kIntegerAccumulator : kIntegerOperand);
1930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addTokenInt(value.fOperand.fS32);
1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (reg == kAccumulator)
1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fAccumulatorType = SkOperand2::kS32;
1960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            else
1970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fOperandInUse = true;
1980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
1990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkOperand2::kScalar:
2000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addToken(reg == kAccumulator ? kScalarAccumulator : kScalarOperand);
2010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addTokenScalar(value.fOperand.fScalar);
2020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (reg == kAccumulator)
2030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fAccumulatorType = SkOperand2::kScalar;
2040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            else
2050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fOperandInUse = true;
2060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkOperand2::kString:
2080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addToken(reg == kAccumulator ? kStringAccumulator : kStringOperand);
2090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addTokenString(*value.fOperand.fString);
2100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (reg == kAccumulator)
2110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fAccumulatorType = SkOperand2::kString;
2120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            else
2130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fOperandInUse = true;
2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        default:
2160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(0); //!!! not implemented yet
2170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectint SkScriptEngine2::arithmeticOp(char ch, char nextChar, bool lastPush) {
2210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    Op op = kUnassigned;
2220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool reverseOperands = false;
2230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool negateResult = false;
2240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int advance = 1;
2250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    switch (ch) {
2260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '+':
2270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            // !!! ignoring unary plus as implemented here has the side effect of
2280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            // suppressing errors like +"hi"
2290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (lastPush == false)    // unary plus, don't push an operator
2304c1d4eb4c9602adf6207d1dffcbfc793cffc43e8Mike Reed                return advance;
2310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = kAdd;
2320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '-':
2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = lastPush ? kSubtract : kMinus;
2350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '*':
2370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = kMultiply;
2380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '/':
2400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = kDivide;
2410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '>':
2430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (nextChar == '>') {
2440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                op = kShiftRight;
2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                goto twoChar;
2460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
2470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = kGreaterEqual;
2480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (nextChar == '=')
2490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                goto twoChar;
2500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                reverseOperands = negateResult = true;
2510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '<':
2530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (nextChar == '<') {
2540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                op = kShiftLeft;
2550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                goto twoChar;
2560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
2570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = kGreaterEqual;
2580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            reverseOperands = nextChar == '=';
2590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            negateResult = ! reverseOperands;
2600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            advance += reverseOperands;
2610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '=':
2630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (nextChar == '=') {
2640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                op = kEqual;
2650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                goto twoChar;
2660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
2670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '!':
2690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (nextChar == '=') {
2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                op = kEqual;
2710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                negateResult = true;
2720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjecttwoChar:
2730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    advance++;
2740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
2750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
2760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = kLogicalNot;
2770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '?':
2790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op =(Op)  kIf;
2800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case ':':
2820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = (Op) kElse;
2830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '^':
2850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = kXor;
2860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '(':
2880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            *fOpStack.push() = (Op) kParen;
2894c1d4eb4c9602adf6207d1dffcbfc793cffc43e8Mike Reed            return advance;
2900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '&':
2910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(nextChar != '&');
2920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = kBitAnd;
2930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '|':
2950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(nextChar != '|');
2960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = kBitOr;
2970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
2980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '%':
2990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = kModulo;
3000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
3010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '~':
3020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = kBitNot;
3030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
3040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (op == kUnassigned)
3060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return 0;
3070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    signed char precedence = gPrecedence[op];
3080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    do {
3090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int idx = 0;
3100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Op compare;
3110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        do {
3120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            compare = fOpStack.index(idx);
3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if ((compare & kArtificialOp) == 0)
3140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
3150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            idx++;
3160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } while (true);
3170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        signed char topPrecedence = gPrecedence[compare];
3180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(topPrecedence != -1);
3190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        if (topPrecedence > precedence || (topPrecedence == precedence &&
3200b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            gOpAttributes[op].fLeftType == SkOperand2::kNoType)) {
3210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
3230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        processOp();
3240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } while (true);
3250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (negateResult)
3260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *fOpStack.push() = (Op) (kLogicalNot | kArtificialOp);
3270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fOpStack.push(op);
3280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (reverseOperands)
3290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *fOpStack.push() = (Op) (kFlipOps | kArtificialOp);
3304c1d4eb4c9602adf6207d1dffcbfc793cffc43e8Mike Reed
3314c1d4eb4c9602adf6207d1dffcbfc793cffc43e8Mike Reed    return advance;
3320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkScriptEngine2::convertParams(SkTDArray<SkScriptValue2>* params,
3350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                    const SkOperand2::OpType* paramTypes, int paramCount) {
3360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int count = params->count();
3370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (count > paramCount) {
3380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(0);
3390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;    // too many parameters passed
3400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    for (int index = 0; index < count; index++)
3420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        convertTo(paramTypes[index], &(*params)[index]);
3430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return true;
3440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkScriptEngine2::convertTo(SkOperand2::OpType toType, SkScriptValue2* value ) {
3470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkOperand2::OpType type = value->fType;
3480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (type == toType)
3490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;
3500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (type == SkOperand2::kObject) {
3510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (handleUnbox(value) == false)
3520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return false;
3530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return convertTo(toType, value);
3540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return ConvertTo(this, toType, value);
3560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkScriptEngine2::evaluateDot(const char*& script) {
3590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    size_t fieldLength = token_length(++script);        // skip dot
3600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(fieldLength > 0); // !!! add error handling
3610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* field = script;
3620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    script += fieldLength;
3630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool success = handleProperty();
3640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (success == false) {
3650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fError = kCouldNotFindReferencedID;
3660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        goto error;
3670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return evaluateDotParam(script, field, fieldLength);
3690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projecterror:
3700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
3710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkScriptEngine2::evaluateDotParam(const char*& script, const char* field, size_t fieldLength) {
3740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScriptValue2& top = fValueStack.top();
3750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (top.fType != SkOperand2::kObject)
3760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
3770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    void* object = top.fOperand.fObject;
3780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fValueStack.pop();
3790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    char ch; // see if it is a simple member or a function
3800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while (is_ws(ch = script[0]))
3810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        script++;
3820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool success = true;
3830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (ch != '(')
3840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        success = handleMember(field, fieldLength, object);
3850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else {
3860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkTDArray<SkScriptValue2> params;
3870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *fBraceStack.push() = kFunctionBrace;
3880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        success = functionParams(&script, &params);
3890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (success)
3900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            success = handleMemberFunction(field, fieldLength, object, &params);
3910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
3920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return success;
3930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
3940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkScriptEngine2::evaluateScript(const char** scriptPtr, SkScriptValue2* value) {
3960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    //    fArrayOffset = 0;        // no support for structures for now
3970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool success;
3980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* inner;
3990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (strncmp(*scriptPtr, "#script:", sizeof("#script:") - 1) == 0) {
4000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *scriptPtr += sizeof("#script:") - 1;
4010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fReturnType == SkOperand2::kNoType || fReturnType == SkOperand2::kString) {
4020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            success = innerScript(scriptPtr, value);
4030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(success);
4040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            inner = value->fOperand.fString->c_str();
4050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            scriptPtr = &inner;
4060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
4070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    success = innerScript(scriptPtr, value);
4090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* script = *scriptPtr;
4100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    char ch;
4110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while (is_ws(ch = script[0]))
4120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        script++;
4130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (ch != '\0') {
4140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        // error may trigger on scripts like "50,0" that were intended to be written as "[50, 0]"
4150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
4160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return success;
4180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScriptEngine2::forget(SkOpArray* array) {
4210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (array->getType() == SkOperand2::kString) {
4220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        for (int index = 0; index < array->count(); index++) {
4230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkString* string = (*array)[index].fString;
4240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int found = fTrackString.find(string);
4250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (found >= 0)
4260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fTrackString.remove(found);
4270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
4280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return;
4290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (array->getType() == SkOperand2::kArray) {
4310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        for (int index = 0; index < array->count(); index++) {
4320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkOpArray* child = (*array)[index].fArray;
4330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            forget(child);    // forgets children of child
4340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            int found = fTrackArray.find(child);
4350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (found >= 0)
4360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fTrackArray.remove(found);
4370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
4380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkScriptEngine2::functionParams(const char** scriptPtr, SkTDArray<SkScriptValue2>* params) {
4420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    (*scriptPtr)++; // skip open paren
4430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *fOpStack.push() = (Op) kParen;
4440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *fBraceStack.push() = kFunctionBrace;
4450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    do {
4460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScriptValue2 value;
4470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        bool success = innerScript(scriptPtr, &value);
4480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(success);
4490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (success == false)
4500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return false;
4510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *params->append() = value;
4520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } while ((*scriptPtr)[-1] == ',');
4530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fBraceStack.pop();
4540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fOpStack.pop(); // pop paren
4550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    (*scriptPtr)++; // advance beyond close paren
4560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return true;
4570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectsize_t SkScriptEngine2::getTokenOffset() {
4600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return fActiveStream->getOffset();
4610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkOperand2::OpType SkScriptEngine2::getUnboxType(SkOperand2 scriptValue) {
4640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    for (SkScriptCallBack** callBack = fCallBackArray.begin(); callBack < fCallBackArray.end(); callBack++) {
4650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if ((*callBack)->getType() != SkScriptCallBack::kUnbox)
4660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            continue;
4670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return (*callBack)->getReturnType(0, &scriptValue);
4680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
4690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return SkOperand2::kObject;
4700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
4710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
4720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkScriptEngine2::innerScript(const char** scriptPtr, SkScriptValue2* value) {
4730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* script = *scriptPtr;
4740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    char ch;
4750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool lastPush = false;
4760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool success = true;
4770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int opBalance = fOpStack.count();
4780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int baseBrace = fBraceStack.count();
4790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int branchBalance = fBranchStack.count();
4800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while ((ch = script[0]) != '\0') {
4810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (is_ws(ch)) {
4820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            script++;
4830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            continue;
4840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
4850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScriptValue2 operand;
4860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const char* dotCheck;
4870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fBraceStack.count() > baseBrace) {
4880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (fBraceStack.top() == kArrayBrace) {
4890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkScriptValue2 tokenValue;
4900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                success = innerScript(&script, &tokenValue);    // terminate and return on comma, close brace
4910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(success);
4920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                {
4930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkOperand2::OpType type = fReturnType;
4940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    if (fReturnType == SkOperand2::kNoType) {
4950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        // !!! short sighted; in the future, allow each returned array component to carry
4960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        // its own type, and let caller do any needed conversions
4970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        if (value->fOperand.fArray->count() == 0)
4980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                            value->fOperand.fArray->setType(type = tokenValue.fType);
4990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        else
5000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                            type = value->fOperand.fArray->getType();
5010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    }
5020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    if (tokenValue.fType != type)
5030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                        convertTo(type, &tokenValue);
5040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    *value->fOperand.fArray->append() = tokenValue.fOperand;
5050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
5060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                lastPush = false;
5070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                continue;
5081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            } else {
5090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(token_length(script) > 0);
5101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
5110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
5120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (lastPush != false && fTokenLength > 0) {
5130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (ch == '(') {
5140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *fBraceStack.push() = kFunctionBrace;
5150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkString functionName(fToken, fTokenLength);
5160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
5170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (handleFunction(&script) == false)
5180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    return false;
5190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                lastPush = true;
5200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                continue;
5210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } else if (ch == '[') {
5220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (handleProperty() == false) {
5230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkASSERT(0);
5240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    return false;
5250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
5260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (handleArrayIndexer(&script) == false)
5270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    return false;
5280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                lastPush = true;
5290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                continue;
5300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } else if (ch != '.') {
5310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (handleProperty() == false) {
5320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkASSERT(0);
5330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    return false;
5340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
5350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                lastPush = true;
5360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                continue;
5370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
5380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
5390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (ch == '0' && (script[1] & ~0x20) == 'X') {
5400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(lastPush == false);
5410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            script += 2;
5420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            script = SkParse::FindHex(script, (uint32_t*) &operand.fOperand.fS32);
5430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(script);
5440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            goto intCommon;
5450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
5460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (lastPush == false && ch == '.')
5470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            goto scalarCommon;
5480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (ch >= '0' && ch <= '9') {
5490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(lastPush == false);
5500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            dotCheck = SkParse::FindS32(script, &operand.fOperand.fS32);
5510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (dotCheck[0] != '.') {
5520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                script = dotCheck;
5530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectintCommon:
5540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                operand.fType = SkOperand2::kS32;
5550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } else {
5560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectscalarCommon:
5570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                script = SkParse::FindScalar(script, &operand.fOperand.fScalar);
5580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                operand.fType = SkOperand2::kScalar;
5590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
5600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            operand.fIsConstant = SkScriptValue2::kConstant;
5610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fValueStack.push(operand);
5620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            lastPush = true;
5630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            continue;
5640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
5650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int length = token_length(script);
5660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (length > 0) {
5670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(lastPush == false);
5680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fToken = script;
5690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fTokenLength = length;
5700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            script += length;
5710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            lastPush = true;
5720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            continue;
5730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
5740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        char startQuote = ch;
5750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (startQuote == '\'' || startQuote == '\"') {
5760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(lastPush == false);
5770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            operand.fOperand.fString = new SkString();
5780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            ++script;
5790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            const char* stringStart = script;
5800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            do {    // measure string
5810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (script[0] == '\\')
5820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    ++script;
5830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                ++script;
5840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(script[0]); // !!! throw an error
5850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } while (script[0] != startQuote);
5860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            operand.fOperand.fString->set(stringStart, script - stringStart);
5870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            script = stringStart;
5880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            char* stringWrite = operand.fOperand.fString->writable_str();
5890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            do {    // copy string
5900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (script[0] == '\\')
5910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    ++script;
5920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *stringWrite++ = script[0];
5930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                ++script;
5940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(script[0]); // !!! throw an error
5950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } while (script[0] != startQuote);
5960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            ++script;
5970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            track(operand.fOperand.fString);
5980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            operand.fType = SkOperand2::kString;
5990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            operand.fIsConstant = SkScriptValue2::kConstant;
6000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fValueStack.push(operand);
6010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            lastPush = true;
6020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            continue;
6030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
6040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (ch ==  '.') {
6050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (fTokenLength == 0) {
6061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                SkDEBUGCODE(SkScriptValue2 scriptValue;)
6070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkDEBUGCODE(scriptValue.fOperand.fObject = NULL);
6080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                int tokenLength = token_length(++script);
6090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                const char* token = script;
6100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                script += tokenLength;
6110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(fValueStack.count() > 0); // !!! add error handling
6120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkScriptValue2 top;
6130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fValueStack.pop(&top);
6140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                addTokenInt(top.fType);
6160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                addToken(kBoxToken);
6170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                top.fType = SkOperand2::kObject;
6180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                top.fIsConstant = SkScriptValue2::kVariable;
6190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fConstExpression = false;
6200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fValueStack.push(top);
6210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                success = evaluateDotParam(script, token, tokenLength);
6220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(success);
6230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                lastPush = true;
6240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                continue;
6250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
6260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            // get next token, and evaluate immediately
6270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            success = evaluateDot(script);
6280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (success == false) {
6290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                //                SkASSERT(0);
6300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                return false;
6310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
6320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            lastPush = true;
6330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            continue;
6340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
6350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (ch == '[') {
6360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (lastPush == false) {
6370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                script++;
6380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *fBraceStack.push() = kArrayBrace;
6390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                operand.fOperand.fArray = value->fOperand.fArray = new SkOpArray(fReturnType);
6400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                track(value->fOperand.fArray);
6410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
6420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                operand.fType = SkOperand2::kArray;
6430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                operand.fIsConstant = SkScriptValue2::kVariable;
6440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fValueStack.push(operand);
6450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                continue;
6460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
6470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (handleArrayIndexer(&script) == false)
6480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                return false;
6490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            lastPush = true;
6500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            continue;
6510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
6520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if 0 // structs not supported for now
6530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (ch == '{') {
6540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (lastPush == false) {
6550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                script++;
6560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *fBraceStack.push() = kStructBrace;
6570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                operand.fS32 = 0;
6580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                *fTypeStack.push() = (SkOpType) kStruct;
6590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fOperandStack.push(operand);
6600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                continue;
6610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
6620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(0); // braces in other contexts aren't supported yet
6630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
6640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
6650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (ch == ')' && fBraceStack.count() > 0) {
6660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            BraceStyle braceStyle = fBraceStack.top();
6670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (braceStyle == kFunctionBrace) {
6680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fBraceStack.pop();
6690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
6700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
6710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
6720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (ch == ',' || ch == ']') {
6730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (ch != ',') {
6740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                BraceStyle match;
6750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fBraceStack.pop(&match);
6760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(match == kArrayBrace);
6770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
6780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            script++;
6790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            // !!! see if brace or bracket is correct closer
6800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
6810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
6820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        char nextChar = script[1];
6830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int advance = logicalOp(ch, nextChar);
6840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (advance == 0)
6850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            advance = arithmeticOp(ch, nextChar, lastPush);
6860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (advance == 0) // unknown token
6870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return false;
6880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (advance > 0)
6890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            script += advance;
6900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        lastPush = ch == ']' || ch == ')';
6910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
6920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fTokenLength > 0) {
6930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        success = handleProperty();
6940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(success);
6950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
6960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int branchIndex = 0;
6970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    branchBalance = fBranchStack.count() - branchBalance;
6980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fBranchPopAllowed = false;
6990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while (branchIndex < branchBalance) {
7000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Branch& branch = fBranchStack.index(branchIndex++);
7010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (branch.fPrimed == Branch::kIsPrimed)
7020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
7030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Op branchOp = branch.fOperator;
7040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkOperand2::OpType lastType = fValueStack.top().fType;
7050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        addTokenValue(fValueStack.top(), kAccumulator);
7060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fValueStack.pop();
7070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (branchOp == kLogicalAnd || branchOp == kLogicalOr) {
7080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (branch.fOperator == kLogicalAnd)
7090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                branch.prime();
7100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addToken(kToBool);
7110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else {
7120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            resolveBranch(branch);
7130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkScriptValue2 operand;
7140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            operand.fType = lastType;
7150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            // !!! note that many branching expressions could be constant
7160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            // today, we always evaluate branches as returning variables
7170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            operand.fIsConstant = SkScriptValue2::kVariable;
7180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fValueStack.push(operand);
7190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
7200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (branch.fDone == Branch::kIsNotDone)
7210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            branch.prime();
7220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fBranchPopAllowed = true;
7240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while (fBranchStack.top().fDone == Branch::kIsDone)
7250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fBranchStack.pop();
7260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while (fOpStack.count() > opBalance) {     // leave open paren
7270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (processOp() == false)
7280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return false;
7290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkOperand2::OpType topType = fValueStack.count() > 0 ? fValueStack.top().fType : SkOperand2::kNoType;
7310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (topType != fReturnType &&
7320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        topType == SkOperand2::kString && fReturnType != SkOperand2::kNoType) { // if result is a string, give handle property a chance to convert it to the property value
7330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkString* string = fValueStack.top().fOperand.fString;
7340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fToken = string->c_str();
7350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fTokenLength = string->size();
7360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fValueStack.pop();
7370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        success = handleProperty();
7380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (success == false) {    // if it couldn't convert, return string (error?)
7390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkScriptValue2 operand;
7400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            operand.fType = SkOperand2::kString;
7410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            operand.fOperand.fString = string;
7420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            operand.fIsConstant = SkScriptValue2::kVariable;     // !!! ?
7430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fValueStack.push(operand);
7440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
7450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (fStream.getOffset() > 0) {
7470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        addToken(kEnd);
7481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkAutoDataUnref data(fStream.copyToData());
7490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
7501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        decompile(data.bytes(), data.size());
7510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
7520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScriptRuntime runtime(fCallBackArray);
7531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        runtime.executeTokens((unsigned char*) data.bytes());
7540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScriptValue2 value1;
7550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        runtime.getResult(&value1.fOperand);
7560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        value1.fType = fReturnType;
7570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fValueStack.push(value1);
7580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (value) {
7600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (fValueStack.count() == 0)
7610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return false;
7620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fValueStack.pop(value);
7630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (value->fType != fReturnType && value->fType == SkOperand2::kObject &&
7640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fReturnType != SkOperand2::kNoType)
7650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            convertTo(fReturnType, value);
7660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    //    if (fBranchStack.top().fOpStackDepth > fOpStack.count())
7680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    //        resolveBranch();
7690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *scriptPtr = script;
7700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return true; // no error
7710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
7720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
7730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkScriptEngine2::handleArrayIndexer(const char** scriptPtr) {
7740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScriptValue2 scriptValue;
7750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    (*scriptPtr)++;
7760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *fOpStack.push() = (Op) kParen;
7770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    *fBraceStack.push() = kArrayBrace;
7780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkOperand2::OpType saveType = fReturnType;
7790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fReturnType = SkOperand2::kS32;
7800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool success = innerScript(scriptPtr, &scriptValue);
7810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fReturnType = saveType;
7820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(success);
7830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    success = convertTo(SkOperand2::kS32, &scriptValue);
7840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(success);
7850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int index = scriptValue.fOperand.fS32;
7860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fValueStack.pop(&scriptValue);
7870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (scriptValue.fType == SkOperand2::kObject) {
7880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        success = handleUnbox(&scriptValue);
7890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(success);
7900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(scriptValue.fType == SkOperand2::kArray);
7910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    scriptValue.fType = scriptValue.fOperand.fArray->getType();
7930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    //    SkASSERT(index >= 0);
7940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if ((unsigned) index >= (unsigned) scriptValue.fOperand.fArray->count()) {
7950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fError = kArrayIndexOutOfBounds;
7960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return false;
7970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
7980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    scriptValue.fOperand = scriptValue.fOperand.fArray->begin()[index];
7990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    scriptValue.fIsConstant = SkScriptValue2::kVariable;
8000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fValueStack.push(scriptValue);
8010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fOpStack.pop(); // pop paren
8020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return success;
8030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
8040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkScriptEngine2::handleFunction(const char** scriptPtr) {
8060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const char* functionName = fToken;
8070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    size_t functionNameLen = fTokenLength;
8080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fTokenLength = 0;
8090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkTDArray<SkScriptValue2> params;
8100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool success = functionParams(scriptPtr, &params);
8110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (success == false)
8120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        goto done;
8130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
8140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        for (SkScriptCallBack** callBack = fCallBackArray.begin(); callBack < fCallBackArray.end(); callBack++) {
8150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if ((*callBack)->getType() != SkScriptCallBack::kFunction)
8160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                continue;
8170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkScriptValue2 callbackResult;
8180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            success = (*callBack)->getReference(functionName, functionNameLen, &callbackResult);
8190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (success) {
8200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                callbackResult.fType = (*callBack)->getReturnType(callbackResult.fOperand.fReference, NULL);
8210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                callbackResult.fIsConstant = SkScriptValue2::kVariable;
8220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fValueStack.push(callbackResult);
8230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                goto done;
8240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
8250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
8260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
8270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return false;
8280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectdone:
8290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fOpStack.pop();
8300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return success;
8310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
8320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkScriptEngine2::handleMember(const char* field, size_t len, void* object) {
8340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool success = true;
8350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    for (SkScriptCallBack** callBack = fCallBackArray.begin(); callBack < fCallBackArray.end(); callBack++) {
8360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if ((*callBack)->getType() != SkScriptCallBack::kMember)
8370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            continue;
8380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScriptValue2 callbackResult;
8390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        success = (*callBack)->getReference(field, len, &callbackResult);
8400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (success) {
8410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (callbackResult.fType == SkOperand2::kString)
8420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                track(callbackResult.fOperand.fString);
8430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            callbackResult.fIsConstant = SkScriptValue2::kVariable;
8440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fValueStack.push(callbackResult);
8450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            goto done;
8460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
8470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
8480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return false;
8490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectdone:
8500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return success;
8510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
8520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkScriptEngine2::handleMemberFunction(const char* field, size_t len, void* object,
8540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                           SkTDArray<SkScriptValue2>* params) {
8550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool success = true;
8560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    for (SkScriptCallBack** callBack = fCallBackArray.begin(); callBack < fCallBackArray.end(); callBack++) {
8570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if ((*callBack)->getType() != SkScriptCallBack::kMemberFunction)
8580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            continue;
8590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScriptValue2 callbackResult;
8600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        success = (*callBack)->getReference(field, len, &callbackResult);
8610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (success) {
8620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (callbackResult.fType == SkOperand2::kString)
8630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                track(callbackResult.fOperand.fString);
8640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            callbackResult.fIsConstant = SkScriptValue2::kVariable;
8650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fValueStack.push(callbackResult);
8660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            goto done;
8670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
8680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
8690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return false;
8700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectdone:
8710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return success;
8720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
8730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkScriptEngine2::handleProperty() {
8750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool success = true;
8760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    for (SkScriptCallBack** callBack = fCallBackArray.begin(); callBack < fCallBackArray.end(); callBack++) {
8770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if ((*callBack)->getType() != SkScriptCallBack::kProperty)
8780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            continue;
8790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScriptValue2 callbackResult;
8800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        success = (*callBack)->getReference(fToken, fTokenLength, &callbackResult);
8810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (success) {
8820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (callbackResult.fType == SkOperand2::kString && callbackResult.fOperand.fString == NULL) {
8830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                callbackResult.fOperand.fString = new SkString(fToken, fTokenLength);
8840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                track(callbackResult.fOperand.fString);
8850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
8860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            callbackResult.fIsConstant = SkScriptValue2::kVariable;
8870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fValueStack.push(callbackResult);
8880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            goto done;
8890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
8900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
8910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectdone:
8920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fTokenLength = 0;
8930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return success;
8940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
8950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
8960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkScriptEngine2::handleUnbox(SkScriptValue2* scriptValue) {
8970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool success = true;
8980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    for (SkScriptCallBack** callBack = fCallBackArray.begin(); callBack < fCallBackArray.end(); callBack++) {
8990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if ((*callBack)->getType() != SkScriptCallBack::kUnbox)
9000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            continue;
9010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScriptCallBackConvert* callBackConvert = (SkScriptCallBackConvert*) *callBack;
9020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        success = callBackConvert->convert(scriptValue->fType, &scriptValue->fOperand);
9030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (success) {
9040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (scriptValue->fType == SkOperand2::kString)
9050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                track(scriptValue->fOperand.fString);
9060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            goto done;
9070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
9080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
9090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return false;
9100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectdone:
9110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return success;
9120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
9130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// note that entire expression is treated as if it were enclosed in parens
9150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// an open paren is always the first thing in the op stack
9160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectint SkScriptEngine2::logicalOp(char ch, char nextChar) {
9180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int advance = 1;
9190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    Op op;
9200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    signed char precedence;
9210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    switch (ch) {
9220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case ')':
9230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = (Op) kParen;
9240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
9250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case ']':
9260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = (Op) kArrayOp;
9270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
9280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '?':
9290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = (Op) kIf;
9300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
9310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case ':':
9320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = (Op) kElse;
9330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
9340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '&':
9350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (nextChar != '&')
9360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                goto noMatch;
9370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = kLogicalAnd;
9380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            advance = 2;
9390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
9400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case '|':
9410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (nextChar != '|')
9420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                goto noMatch;
9430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = kLogicalOr;
9440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            advance = 2;
9450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
9460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        default:
9470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            noMatch:
9480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return 0;
9490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
9500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    precedence = gPrecedence[op];
9510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int branchIndex = 0;
9520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fBranchPopAllowed = false;
9530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    do {
9540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        while (gPrecedence[fOpStack.top() & ~kArtificialOp] < precedence)
9550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            processOp();
9560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Branch& branch = fBranchStack.index(branchIndex++);
9570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        Op branchOp = branch.fOperator;
9580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (gPrecedence[branchOp] >= precedence)
9590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
9600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        addTokenValue(fValueStack.top(), kAccumulator);
9610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fValueStack.pop();
9620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (branchOp == kLogicalAnd || branchOp == kLogicalOr) {
9630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (branch.fOperator == kLogicalAnd)
9640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                branch.prime();
9650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addToken(kToBool);
9660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } else
9670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            resolveBranch(branch);
9680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (branch.fDone == Branch::kIsNotDone)
9690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            branch.prime();
9700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    } while (true);
9710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fBranchPopAllowed = true;
9720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while (fBranchStack.top().fDone == Branch::kIsDone)
9730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fBranchStack.pop();
9740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    processLogicalOp(op);
9750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return advance;
9760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
9770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
9780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScriptEngine2::processLogicalOp(Op op) {
9790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    switch (op) {
9800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kParen:
9810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kArrayOp:
9820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(fOpStack.count() > 1 && fOpStack.top() == op);    // !!! add error handling
9830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (op == kParen)
9840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fOpStack.pop();
9850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            else {
9860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkScriptValue2 value;
9870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fValueStack.pop(&value);
9880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(value.fType == SkOperand2::kS32 || value.fType == SkOperand2::kScalar); // !!! add error handling (although, could permit strings eventually)
9890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                int index = value.fType == SkOperand2::kScalar ? SkScalarFloor(value.fOperand.fScalar) :
9900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    value.fOperand.fS32;
9910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkScriptValue2 arrayValue;
9920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fValueStack.pop(&arrayValue);
9930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(arrayValue.fType == SkOperand2::kArray);  // !!! add error handling
9940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkOpArray* array = arrayValue.fOperand.fArray;
9950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkOperand2 operand;
9960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                bool success = array->getIndex(index, &operand);
9970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(success); // !!! add error handling
9980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkScriptValue2 resultValue;
9990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                resultValue.fType = array->getType();
10000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                resultValue.fOperand = operand;
10010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                resultValue.fIsConstant = SkScriptValue2::kVariable;
10020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fValueStack.push(resultValue);
10030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
10040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
10050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kIf: {
10060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (fAccumulatorType == SkOperand2::kNoType) {
10070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                addTokenValue(fValueStack.top(), kAccumulator);
10080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fValueStack.pop();
10090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
10100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(fAccumulatorType != SkOperand2::kString); // !!! add error handling
10110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addToken(kIfOp);
10120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            Branch branch(op, fOpStack.count(), getTokenOffset());
10130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            *fBranchStack.push() = branch;
10140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addTokenInt(0); // placeholder for future branch
10150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fAccumulatorType = SkOperand2::kNoType;
10160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } break;
10170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kElse: {
10180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addTokenValue(fValueStack.top(), kAccumulator);
10190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fValueStack.pop();
10200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addToken(kElseOp);
10210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            size_t newOffset = getTokenOffset();
10220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addTokenInt(0); // placeholder for future branch
10230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            Branch& branch = fBranchStack.top();
10240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            resolveBranch(branch);
10250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            branch.fOperator = op;
10260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            branch.fDone = Branch::kIsNotDone;
10270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(branch.fOpStackDepth == fOpStack.count());
10280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            branch.fOffset = newOffset;
10290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fAccumulatorType = SkOperand2::kNoType;
10300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } break;
10310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kLogicalAnd:
10320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case kLogicalOr: {
10330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            Branch& oldTop = fBranchStack.top();
10340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            Branch::Primed wasPrime = oldTop.fPrimed;
10350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            Branch::Done wasDone = oldTop.fDone;
10360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            oldTop.fPrimed = Branch::kIsNotPrimed;
10370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            oldTop.fDone = Branch::kIsNotDone;
10380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (fAccumulatorType == SkOperand2::kNoType) {
10390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(fValueStack.top().fType == SkOperand2::kS32); // !!! add error handling, and conversion to int?
10400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                addTokenValue(fValueStack.top(), kAccumulator);
10410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                fValueStack.pop();
10421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            } else {
10430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(fAccumulatorType == SkOperand2::kS32);
10441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
10450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            // if 'and', write beq goto opcode after end of predicate (after to bool)
10460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            // if 'or', write bne goto to bool
10470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addToken(op == kLogicalAnd ? kLogicalAndInt : kLogicalOrInt);
10480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            Branch branch(op, fOpStack.count(), getTokenOffset());
10490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addTokenInt(0); // placeholder for future branch
10500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            oldTop.fPrimed = wasPrime;
10510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            oldTop.fDone = wasDone;
10520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            *fBranchStack.push() = branch;
10530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fAccumulatorType = SkOperand2::kNoType;
10540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }    break;
10550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        default:
10560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(0);
10570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
10580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
10590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
10600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkScriptEngine2::processOp() {
10610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    Op op;
10620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fOpStack.pop(&op);
10630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    op = (Op) (op & ~kArtificialOp);
10640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const OperatorAttributes* attributes = &gOpAttributes[op];
10650b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    SkScriptValue2 value1;
10660b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    memset(&value1, 0, sizeof(SkScriptValue2));
10670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScriptValue2 value2;
10680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fValueStack.pop(&value2);
10690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    value2.fIsWritten = SkScriptValue2::kUnwritten;
10700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    //    SkScriptEngine2::SkTypeOp convert1[3];
10710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    //    SkScriptEngine2::SkTypeOp convert2[3];
10720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    //    SkScriptEngine2::SkTypeOp* convert2Ptr = convert2;
10730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool constantOperands = value2.fIsConstant == SkScriptValue2::kConstant;
10740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (attributes->fLeftType != SkOperand2::kNoType) {
10750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fValueStack.pop(&value1);
10760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        constantOperands &= value1.fIsConstant == SkScriptValue2::kConstant;
10770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        value1.fIsWritten = SkScriptValue2::kUnwritten;
10780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (op == kFlipOps) {
10790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkTSwap(value1, value2);
10800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            fOpStack.pop(&op);
10810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            op = (Op) (op & ~kArtificialOp);
10820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            attributes = &gOpAttributes[op];
10830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (constantOperands == false)
10840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                addToken(kFlipOpsOp);
10850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
10860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (value1.fType == SkOperand2::kObject && (value1.fType & attributes->fLeftType) == 0) {
10870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            value1.fType = getUnboxType(value1.fOperand);
10880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addToken(kUnboxToken);
10890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
10900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
10910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (value2.fType == SkOperand2::kObject && (value2.fType & attributes->fLeftType) == 0) {
10920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        value1.fType = getUnboxType(value2.fOperand);
10930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        addToken(kUnboxToken2);
10940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
10950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (attributes->fLeftType != SkOperand2::kNoType) {
10960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (value1.fType != value2.fType) {
10970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if ((attributes->fLeftType & SkOperand2::kString) && attributes->fBias & kTowardsString &&
10980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                ((value1.fType | value2.fType) & SkOperand2::kString)) {
10990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (value1.fType == SkOperand2::kS32 || value1.fType == SkOperand2::kScalar) {
11000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    addTokenConst(&value1, kAccumulator, SkOperand2::kString,
11010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                  value1.fType == SkOperand2::kS32 ? kIntToString : kScalarToString);
11020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
11030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (value2.fType == SkOperand2::kS32 || value2.fType == SkOperand2::kScalar) {
11040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    addTokenConst(&value2, kOperand, SkOperand2::kString,
11050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                  value2.fType == SkOperand2::kS32 ? kIntToString2 : kScalarToString2);
11060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                }
11070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            } else if (attributes->fLeftType & SkOperand2::kScalar && ((value1.fType | value2.fType) &
11080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                                                       SkOperand2::kScalar)) {
11090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (value1.fType == SkOperand2::kS32)
11100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    addTokenConst(&value1, kAccumulator, SkOperand2::kScalar, kIntToScalar);
11110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (value2.fType == SkOperand2::kS32)
11120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    addTokenConst(&value2, kOperand, SkOperand2::kScalar, kIntToScalar2);
11130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
11140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
11150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if ((value1.fType & attributes->fLeftType) == 0 || value1.fType != value2.fType) {
11160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (value1.fType == SkOperand2::kString)
11170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                addTokenConst(&value1, kAccumulator, SkOperand2::kScalar, kStringToScalar);
11180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (value1.fType == SkOperand2::kScalar && (attributes->fLeftType == SkOperand2::kS32 ||
11190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                                        value2.fType == SkOperand2::kS32))
11200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                addTokenConst(&value1, kAccumulator, SkOperand2::kS32, kScalarToInt);
11210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
11220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
11230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    AddTokenRegister rhRegister = attributes->fLeftType != SkOperand2::kNoType ?
11240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        kOperand : kAccumulator;
11250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if ((value2.fType & attributes->fRightType) == 0 || value1.fType != value2.fType) {
11260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (value2.fType == SkOperand2::kString)
11270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addTokenConst(&value2, rhRegister, SkOperand2::kScalar, kStringToScalar2);
11280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (value2.fType == SkOperand2::kScalar && (attributes->fRightType == SkOperand2::kS32 ||
11290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                                    value1.fType == SkOperand2::kS32))
11300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addTokenConst(&value2, rhRegister, SkOperand2::kS32, kScalarToInt2);
11310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
11320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    TypeOp typeOp = gTokens[op];
11330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (value2.fType == SkOperand2::kScalar)
11340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        typeOp = (TypeOp) (typeOp + 1);
11350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else if (value2.fType == SkOperand2::kString)
11360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        typeOp = (TypeOp) (typeOp + 2);
11370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkDynamicMemoryWStream stream;
11381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkOperand2::OpType saveType = SkOperand2::kNoType;
11391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkBool saveOperand = false;
11400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (constantOperands) {
11410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fActiveStream = &stream;
11420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        saveType = fAccumulatorType;
11430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        saveOperand = fOperandInUse;
11440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fAccumulatorType = SkOperand2::kNoType;
11450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fOperandInUse = false;
11460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
11470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (attributes->fLeftType != SkOperand2::kNoType) {    // two operands
11480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (value1.fIsWritten == SkScriptValue2::kUnwritten)
11490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            addTokenValue(value1, kAccumulator);
11500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
11510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (value2.fIsWritten == SkScriptValue2::kUnwritten)
11520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        addTokenValue(value2, rhRegister);
11530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    addToken(typeOp);
11540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (constantOperands) {
11550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        addToken(kEnd);
11561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkAutoDataUnref data(fStream.copyToData());
11570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
11581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        decompile(data.bytes(), data.size());
11590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
11600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScriptRuntime runtime(fCallBackArray);
11611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        runtime.executeTokens((unsigned char*)data.bytes());
11620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        runtime.getResult(&value1.fOperand);
11630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (attributes->fResultIsBoolean == kResultIsBoolean)
11640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            value1.fType = SkOperand2::kS32;
11650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else if (attributes->fLeftType == SkOperand2::kNoType) // unary operand
11660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            value1.fType = value2.fType;
11670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fValueStack.push(value1);
11680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (value1.fType == SkOperand2::kString)
11690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            runtime.untrack(value1.fOperand.fString);
11700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else if (value1.fType == SkOperand2::kArray)
11710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            runtime.untrack(value1.fOperand.fArray);
11720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fActiveStream = &fStream;
11730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fAccumulatorType = saveType;
11740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fOperandInUse = saveOperand;
11750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;
11760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
11770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    value2.fIsConstant = SkScriptValue2::kVariable;
11780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fValueStack.push(value2);
11790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return true;
11800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScriptEngine2::Branch::resolve(SkDynamicMemoryWStream* stream, size_t off) {
11830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(fDone == kIsNotDone);
11840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fPrimed = kIsNotPrimed;
11850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    fDone = kIsDone;
11860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(off > fOffset + sizeof(size_t));
11870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    size_t offset = off - fOffset - sizeof(offset);
11880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    stream->write(&offset, fOffset, sizeof(offset));
11890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScriptEngine2::resolveBranch(SkScriptEngine2::Branch& branch) {
11920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    branch.resolve(fActiveStream, getTokenOffset());
11930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
11940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
11950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkScriptEngine2::ConvertTo(SkScriptEngine2* engine, SkOperand2::OpType toType, SkScriptValue2* value ) {
11960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(value);
11970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkOperand2::OpType type = value->fType;
11980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (type == toType)
11990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return true;
12000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkOperand2& operand = value->fOperand;
12010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool success = true;
12020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    switch (toType) {
12030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkOperand2::kS32:
12040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (type == SkOperand2::kScalar)
12050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                operand.fS32 = SkScalarFloor(operand.fScalar);
12060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            else {
12070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(type == SkOperand2::kString);
12080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                success = SkParse::FindS32(operand.fString->c_str(), &operand.fS32) != NULL;
12090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
12100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
12110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkOperand2::kScalar:
12120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (type == SkOperand2::kS32)
12130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                operand.fScalar = IntToScalar(operand.fS32);
12140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            else {
12150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(type == SkOperand2::kString);
12160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                success = SkParse::FindScalar(operand.fString->c_str(), &operand.fScalar) != NULL;
12170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
12180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
12190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkOperand2::kString: {
12200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkString* strPtr = new SkString();
12210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(engine);
12220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            engine->track(strPtr);
12230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            if (type == SkOperand2::kS32)
12240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                strPtr->appendS32(operand.fS32);
12250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            else {
12260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(type == SkOperand2::kScalar);
12270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                strPtr->appendScalar(operand.fScalar);
12280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            }
12290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            operand.fString = strPtr;
12300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } break;
12310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkOperand2::kArray: {
12320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkOpArray* array = new SkOpArray(type);
12330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            *array->append() = operand;
12340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            engine->track(array);
12350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            operand.fArray = array;
12360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        } break;
12370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        default:
12380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(0);
12390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
12400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    value->fType = toType;
12410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return success;
12420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
12430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkScriptEngine2::IntToScalar(int32_t s32) {
12450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkScalar scalar;
12460b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    if (s32 == (int32_t) SK_NaN32)
12470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        scalar = SK_ScalarNaN;
12480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else if (SkAbs32(s32) == SK_MaxS32)
12490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        scalar = SkSign32(s32) * SK_ScalarMax;
12500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    else
12510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        scalar = SkIntToScalar(s32);
12520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return scalar;
12530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
12540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkScriptEngine2::ValueToString(const SkScriptValue2& value, SkString* string) {
12560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    switch (value.fType) {
12570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkOperand2::kS32:
12580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            string->reset();
12590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            string->appendS32(value.fOperand.fS32);
12600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
12610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkOperand2::kScalar:
12620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            string->reset();
12630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            string->appendScalar(value.fOperand.fScalar);
12640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
12650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        case SkOperand2::kString:
12660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            string->set(*value.fOperand.fString);
12670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            break;
12680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        default:
12690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            SkASSERT(0);
12700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            return false;
12710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
12720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return true; // no error
12730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
12740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG
12760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#define testInt(expression) { #expression, SkOperand2::kS32, expression, 0, NULL }
12780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_SCALAR_IS_FLOAT
12790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#define testScalar(expression) { #expression, SkOperand2::kScalar, 0, (float) expression, NULL }
12800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#define testRemainder(exp1, exp2) { #exp1 "%" #exp2, SkOperand2::kScalar, 0, fmodf(exp1, exp2), NULL }
12810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else
12820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_CAN_USE_FLOAT
12830b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#define testScalar(expression) { #expression, SkOperand2::kScalar, 0, (int) ((expression) * 65536.0f), NULL }
12840b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#define testRemainder(exp1, exp2) { #exp1 "%" #exp2, SkOperand2::kScalar, 0, (int) (fmod(exp1, exp2)  * 65536.0f), NULL }
12850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
12860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
12870b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#define testTrue(expression) { #expression, SkOperand2::kS32, 1, 0, NULL }
12880b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger#define testFalse(expression) { #expression, SkOperand2::kS32, 0, 0, NULL }
12890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
12900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic const SkScriptNAnswer2 scriptTests[]  = {
12910b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    testInt(1||(0&&3)),
12920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_CAN_USE_FLOAT
12930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testScalar(- -5.5- -1.5),
12940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testScalar(1.0+5),
12950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
12960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt((6+7)*8),
12970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(3*(4+5)),
12980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_CAN_USE_FLOAT
12990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testScalar(1.0+2.0),
13000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testScalar(3.0-1.0),
13010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testScalar(6-1.0),
13020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testScalar(2.5*6.),
13030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testScalar(0.5*4),
13040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testScalar(4.5/.5),
13050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testScalar(9.5/19),
13060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testRemainder(9.5, 0.5),
13070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testRemainder(9.,2),
13080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testRemainder(9,2.5),
13090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testRemainder(-9,2.5),
13100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue(-9==-9.0),
13110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue(-9.==-4.0-5),
13120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue(-9.*1==-4-5),
13130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse(-9!=-9.0),
13140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse(-9.!=-4.0-5),
13150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse(-9.*1!=-4-5),
13160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
13170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(0x123),
13180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(0XABC),
13190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(0xdeadBEEF),
13200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {    "'123'+\"456\"", SkOperand2::kString, 0, 0, "123456" },
13210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {    "123+\"456\"", SkOperand2::kString, 0, 0, "123456" },
13220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {    "'123'+456", SkOperand2::kString, 0, 0, "123456" },
13230b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    {    "'123'|\"456\"", SkOperand2::kS32, 123|456, 0, NULL },
13240b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    {    "123|\"456\"", SkOperand2::kS32, 123|456, 0, NULL },
13250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    {    "'123'|456", SkOperand2::kS32, 123|456, 0, NULL },
13260b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    {    "'2'<11", SkOperand2::kS32, 1, 0, NULL },
13270b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    {    "2<'11'", SkOperand2::kS32, 1, 0, NULL },
13280b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    {    "'2'<'11'", SkOperand2::kS32, 0, 0, NULL },
13290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(123),
13300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(-345),
13310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(+678),
13320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(1+2+3),
13330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(3*4+5),
13340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(6+7*8),
13350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(-1-2-8/4),
13360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(-9%4),
13370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(9%-4),
13380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(-9%-4),
13390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(123|978),
13400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(123&978),
13410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(123^978),
13420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2<<4),
13430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(99>>3),
13440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(~55),
13450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(~~55),
13460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(!55),
13470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(!!55),
13480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // both int
13490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2<2),
13500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2<11),
13510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20<11),
13520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2<=2),
13530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2<=11),
13540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20<=11),
13550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2>2),
13560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2>11),
13570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20>11),
13580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2>=2),
13590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2>=11),
13600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20>=11),
13610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2==2),
13620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2==11),
13630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20==11),
13640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2!=2),
13650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2!=11),
13660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20!=11),
13670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_CAN_USE_FLOAT
13680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // left int, right scalar
13690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2<2.),
13700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2<11.),
13710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20<11.),
13720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2<=2.),
13730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2<=11.),
13740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20<=11.),
13750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2>2.),
13760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2>11.),
13770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20>11.),
13780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2>=2.),
13790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2>=11.),
13800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20>=11.),
13810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2==2.),
13820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2==11.),
13830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20==11.),
13840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2!=2.),
13850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2!=11.),
13860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20!=11.),
13870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // left scalar, right int
13880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.<2),
13890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.<11),
13900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20.<11),
13910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.<=2),
13920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.<=11),
13930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20.<=11),
13940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.>2),
13950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.>11),
13960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20.>11),
13970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.>=2),
13980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.>=11),
13990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20.>=11),
14000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.==2),
14010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.==11),
14020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20.==11),
14030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.!=2),
14040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.!=11),
14050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20.!=11),
14060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // both scalar
14070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.<11.),
14080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20.<11.),
14090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.<=2.),
14100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.<=11.),
14110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20.<=11.),
14120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.>2.),
14130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.>11.),
14140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20.>11.),
14150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.>=2.),
14160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.>=11.),
14170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20.>=11.),
14180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.==2.),
14190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.==11.),
14200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20.==11.),
14210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.!=2.),
14220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(2.!=11.),
14230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(20.!=11.),
14240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
14250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // int, string (string is int)
14260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse(2<'2'),
14270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue(2<'11'),
14280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse(20<'11'),
14290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue(2<='2'),
14300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue(2<='11'),
14310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse(20<='11'),
14320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse(2>'2'),
14330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse(2>'11'),
14340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue(20>'11'),
14350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue(2>='2'),
14360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse(2>='11'),
14370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue(20>='11'),
14380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue(2=='2'),
14390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse(2=='11'),
14400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse(2!='2'),
14410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue(2!='11'),
14420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // int, string (string is scalar)
14430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse(2<'2.'),
14440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue(2<'11.'),
14450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse(20<'11.'),
14460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue(2=='2.'),
14470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse(2=='11.'),
14480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_CAN_USE_FLOAT
14490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // scalar, string
14500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse(2.<'2.'),
14510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue(2.<'11.'),
14520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse(20.<'11.'),
14530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue(2.=='2.'),
14540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse(2.=='11.'),
14550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // string, int
14560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse('2'<2),
14570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue('2'<11),
14580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse('20'<11),
14590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue('2'==2),
14600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse('2'==11),
14610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // string, scalar
14620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse('2'<2.),
14630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue('2'<11.),
14640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse('20'<11.),
14650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue('2'==2.),
14660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse('2'==11.),
14670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
14680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // string, string
14690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse('2'<'2'),
14700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse('2'<'11'),
14710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse('20'<'11'),
14720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testTrue('2'=='2'),
14730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testFalse('2'=='11'),
14740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // logic
14750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(1?2:3),
14760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(0?2:3),
14770b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    testInt((1&&2)||3),
14780b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    testInt((1&&0)||3),
14790b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    testInt((1&&0)||0),
14800b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    testInt(1||(0&&3)),
14810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    testInt(0||(0&&3)),
14820b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    testInt(0||(1&&3)),
14830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    testInt(0&&1?2:3)
14840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_CAN_USE_FLOAT
14850b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    , {    "123.5", SkOperand2::kScalar, 0, SkIntToScalar(123) + SK_Scalar1/2, NULL }
14860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
14870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
14880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
14890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkScriptNAnswer_testCount    SK_ARRAY_COUNT(scriptTests)
14900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
14910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkScriptEngine2::UnitTest() {
149287a2a317c4e99c547ecbfa81f40f7bd7f2932433Mike Reed#if defined(SK_SUPPORT_UNITTEST)
14930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    ValidateDecompileTable();
14940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    for (int index = 0; index < SkScriptNAnswer_testCount; index++) {
14950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScriptEngine2 engine(scriptTests[index].fType);
14960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScriptValue2 value;
14970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const char* script = scriptTests[index].fScript;
14980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        const char* scriptPtr = script;
14990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(engine.evaluateScript(&scriptPtr, &value) == true);
15000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT(value.fType == scriptTests[index].fType);
15010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkScalar error;
15020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        switch (value.fType) {
15030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            case SkOperand2::kS32:
15040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (value.fOperand.fS32 != scriptTests[index].fIntAnswer)
15050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkDEBUGF(("script '%s' == value %d != expected answer %d\n", script, value.fOperand.fS32, scriptTests[index].fIntAnswer));
15060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(value.fOperand.fS32 == scriptTests[index].fIntAnswer);
15070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
15080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            case SkOperand2::kScalar:
15090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                error = SkScalarAbs(value.fOperand.fScalar - scriptTests[index].fScalarAnswer);
15100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_CAN_USE_FLOAT
15110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                if (error >= SK_Scalar1 / 10000)
15120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                    SkDEBUGF(("script '%s' == value %g != expected answer %g\n", script, value.fOperand.fScalar / (1.0f * SK_Scalar1), scriptTests[index].fScalarAnswer / (1.0f * SK_Scalar1)));
15130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
15140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(error < SK_Scalar1 / 10000);
15150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
15160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            case SkOperand2::kString:
15170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(value.fOperand.fString->equals(scriptTests[index].fStringAnswer));
15180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                break;
15190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            default:
15200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                SkASSERT(0);
15210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        }
15220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
15230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
15240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
15250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
1526