grab from latest android



git-svn-id: http://skia.googlecode.com/svn/trunk@27 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/animator/SkScriptDecompile.cpp b/src/animator/SkScriptDecompile.cpp
new file mode 100644
index 0000000..d582d33
--- /dev/null
+++ b/src/animator/SkScriptDecompile.cpp
@@ -0,0 +1,221 @@
+/* libs/graphics/animator/SkScriptDecompile.cpp
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+
+#include "SkScript2.h"
+
+#ifdef SK_DEBUG
+
+#define TypeOpName(op) {SkScriptEngine2::op, #op }
+
+static const struct OpName {
+    SkScriptEngine2::TypeOp fOp;
+    const char* fName;
+} gOpNames[] = {
+    TypeOpName(kNop), // should never get generated
+    TypeOpName(kAccumulatorPop),
+    TypeOpName(kAccumulatorPush),
+    TypeOpName(kAddInt),
+    TypeOpName(kAddScalar),
+    TypeOpName(kAddString), // string concat
+    TypeOpName(kArrayIndex),
+    TypeOpName(kArrayParam),
+    TypeOpName(kArrayToken),
+    TypeOpName(kBitAndInt),
+    TypeOpName(kBitNotInt),
+    TypeOpName(kBitOrInt),
+    TypeOpName(kBoxToken),
+    TypeOpName(kCallback),
+    TypeOpName(kDivideInt),
+    TypeOpName(kDivideScalar),
+    TypeOpName(kDotOperator),
+    TypeOpName(kElseOp),
+    TypeOpName(kEnd),
+    TypeOpName(kEqualInt),
+    TypeOpName(kEqualScalar),
+    TypeOpName(kEqualString),
+    TypeOpName(kFunctionCall),
+    TypeOpName(kFlipOpsOp),
+    TypeOpName(kFunctionToken),
+    TypeOpName(kGreaterEqualInt),
+    TypeOpName(kGreaterEqualScalar),
+    TypeOpName(kGreaterEqualString),
+    TypeOpName(kIfOp),
+    TypeOpName(kIntToScalar),
+    TypeOpName(kIntToScalar2),
+    TypeOpName(kIntToString),
+    TypeOpName(kIntToString2),
+    TypeOpName(kIntegerAccumulator),
+    TypeOpName(kIntegerOperand),
+    TypeOpName(kLogicalAndInt),
+    TypeOpName(kLogicalNotInt),
+    TypeOpName(kLogicalOrInt),
+    TypeOpName(kMemberOp),
+    TypeOpName(kMinusInt),
+    TypeOpName(kMinusScalar),
+    TypeOpName(kModuloInt),
+    TypeOpName(kModuloScalar),
+    TypeOpName(kMultiplyInt),
+    TypeOpName(kMultiplyScalar),
+    TypeOpName(kPropertyOp),
+    TypeOpName(kScalarAccumulator),
+    TypeOpName(kScalarOperand),
+    TypeOpName(kScalarToInt),
+    TypeOpName(kScalarToInt2),
+    TypeOpName(kScalarToString),
+    TypeOpName(kScalarToString2),
+    TypeOpName(kShiftLeftInt),
+    TypeOpName(kShiftRightInt), // signed
+    TypeOpName(kStringAccumulator),
+    TypeOpName(kStringOperand),
+    TypeOpName(kStringToInt),
+    TypeOpName(kStringToScalar),
+    TypeOpName(kStringToScalar2),
+    TypeOpName(kStringTrack),
+    TypeOpName(kSubtractInt),
+    TypeOpName(kSubtractScalar),
+    TypeOpName(kToBool),
+    TypeOpName(kUnboxToken),
+    TypeOpName(kUnboxToken2),
+    TypeOpName(kXorInt)
+};
+
+static size_t gOpNamesSize = sizeof(gOpNames) / sizeof(gOpNames[0]);
+
+#define OperandName(op) {SkOperand2::op, #op }
+
+static const struct OperName {
+    SkOperand2::OpType fType;
+    const char* fName;
+} gOperandNames[] = {
+    OperandName(kNoType),
+    OperandName(kS32),
+    OperandName(kScalar),
+    OperandName(kString),
+    OperandName(kArray),
+    OperandName(kObject)
+};  
+
+static size_t gOperandNamesSize = sizeof(gOperandNames) / sizeof(gOperandNames[0]);
+
+// check to see that there are no missing or duplicate entries
+void SkScriptEngine2::ValidateDecompileTable() {
+    SkScriptEngine2::TypeOp op = SkScriptEngine2::kNop;
+    int index;
+    for (index = 0; index < gOpNamesSize; index++) {
+        SkASSERT(gOpNames[index].fOp == op);
+        op = (SkScriptEngine2::TypeOp) (op + 1);
+    }
+    index = 0;
+    SkOperand2::OpType type = SkOperand2::kNoType;
+    SkASSERT(gOperandNames[index].fType == type);
+    for (; index < gOperandNamesSize - 1; ) {
+        type = (SkOperand2::OpType) (1 << index);
+        SkASSERT(gOperandNames[++index].fType == type);
+    }
+}
+
+void SkScriptEngine2::decompile(const unsigned char* start, size_t length) {
+    SkASSERT(length > 0);
+    const unsigned char* opCode = start;
+    do {
+        SkASSERT(opCode - start < length);
+        SkScriptEngine2::TypeOp op = (SkScriptEngine2::TypeOp) *opCode++;
+        SkASSERT(op < gOpNamesSize);
+        SkDebugf("%d: %s", opCode - start - 1, gOpNames[op].fName);
+        switch (op) {
+        case SkScriptEngine2::kCallback: {
+            int index;
+            memcpy(&index, opCode, sizeof(index));
+            opCode += sizeof(index);
+            SkDebugf(" index: %d", index);
+            } break;
+        case SkScriptEngine2::kFunctionCall: 
+        case SkScriptEngine2::kMemberOp:
+        case SkScriptEngine2::kPropertyOp: {
+            size_t ref;
+            memcpy(&ref, opCode, sizeof(ref));
+            opCode += sizeof(ref);
+            SkDebugf(" ref: %d", ref);
+            } break;
+        case SkScriptEngine2::kIntegerAccumulator:
+        case SkScriptEngine2::kIntegerOperand: {
+            int32_t integer;
+            memcpy(&integer, opCode, sizeof(integer));
+            opCode += sizeof(int32_t);
+            SkDebugf(" integer: %d", integer);
+            } break;
+        case SkScriptEngine2::kScalarAccumulator:
+        case SkScriptEngine2::kScalarOperand: {
+            SkScalar scalar;
+            memcpy(&scalar, opCode, sizeof(scalar));
+            opCode += sizeof(SkScalar);
+#ifdef SK_CAN_USE_FLOAT
+            SkDebugf(" scalar: %g", SkScalarToFloat(scalar));
+#else
+            SkDebugf(" scalar: %x", scalar);
+#endif
+            } break;
+        case SkScriptEngine2::kStringAccumulator:
+        case SkScriptEngine2::kStringOperand: {
+            int size;
+            SkString* strPtr = new SkString();
+            memcpy(&size, opCode, sizeof(size));
+            opCode += sizeof(size);
+            strPtr->set((char*) opCode, size);
+            opCode += size;
+            SkDebugf(" string: %s", strPtr->c_str());
+            delete strPtr;
+            } break;
+        case SkScriptEngine2::kBoxToken: {
+            SkOperand2::OpType type;
+            memcpy(&type, opCode, sizeof(type));
+            opCode += sizeof(type);
+            int index = 0;
+            if (type == 0)
+                SkDebugf(" type: %s", gOperandNames[index].fName);
+            else {
+                while (type != 0) {
+                    SkASSERT(index + 1 < gOperandNamesSize);
+                    if (type & (1 << index)) {
+                        type = (SkOperand2::OpType) (type & ~(1 << index));
+                        SkDebugf(" type: %s", gOperandNames[index + 1].fName);
+                    }
+                    index++;
+                }
+            }
+            } break;
+        case SkScriptEngine2::kIfOp:
+        case SkScriptEngine2::kLogicalAndInt:
+        case SkScriptEngine2::kElseOp:
+        case SkScriptEngine2::kLogicalOrInt: {
+            int size;
+            memcpy(&size, opCode, sizeof(size));
+            opCode += sizeof(size);
+            SkDebugf(" offset (address): %d (%d)", size, opCode - start + size);
+            } break;
+        case SkScriptEngine2::kEnd:
+            goto done;
+        case SkScriptEngine2::kNop:
+                SkASSERT(0);
+    }
+    SkDebugf("\n");
+    } while (true);
+done:
+    SkDebugf("\n");
+}
+
+#endif