grab from latest android



git-svn-id: http://skia.googlecode.com/svn/trunk@27 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/xml/SkJSDisplayable.cpp b/src/xml/SkJSDisplayable.cpp
new file mode 100644
index 0000000..d52a7c9
--- /dev/null
+++ b/src/xml/SkJSDisplayable.cpp
@@ -0,0 +1,472 @@
+/* libs/graphics/xml/SkJSDisplayable.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 <jsapi.h>
+#include "SkJS.h"
+#include "SkDisplayType.h"
+//#include "SkAnimateColor.h"
+#include "SkAnimateMaker.h"
+#include "SkAnimateSet.h"
+//#include "SkAnimateTransform.h"
+#include "SkCanvas.h"
+//#include "SkDimensions.h"
+#include "SkDisplayAdd.h"
+#include "SkDisplayApply.h"
+//#include "SkDisplayBefore.h"
+#include "SkDisplayEvent.h"
+//#include "SkDisplayFocus.h"
+#include "SkDisplayInclude.h"
+#include "SkDisplayPost.h"
+#include "SkDisplayRandom.h"
+#include "SkDraw3D.h"
+#include "SkDrawBitmap.h"
+#include "SkDrawClip.h"
+#include "SkDrawDash.h"
+#include "SkDrawDiscrete.h"
+#include "SkDrawEmboss.h"
+//#include "SkDrawFont.h"
+#include "SkDrawFull.h"
+#include "SkDrawGradient.h"
+#include "SkDrawLine.h"
+//#include "SkDrawMaskFilter.h"
+#include "SkDrawMatrix.h"
+#include "SkDrawOval.h"
+#include "SkDrawPaint.h"
+#include "SkDrawPath.h"
+#include "SkDrawPoint.h"
+// #include "SkDrawStroke.h"
+#include "SkDrawText.h"
+#include "SkDrawTo.h"
+//#include "SkDrawTransferMode.h"
+#include "SkDrawTransparentShader.h"
+//#include "SkDrawUse.h"
+#include "SkMatrixParts.h"
+#include "SkPathParts.h"
+#include "SkPostParts.h"
+#include "SkScript.h"
+#include "SkSnapshot.h"
+#include "SkTextOnPath.h"
+#include "SkTextToPath.h"
+
+
+class SkJSDisplayable {
+public:
+    SkJSDisplayable() : fDisplayable(NULL) {}
+    ~SkJSDisplayable() { delete fDisplayable; }
+    static void Destructor(JSContext *cx, JSObject *obj);
+    static JSBool GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+    static JSBool SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
+    static SkCanvas* gCanvas;
+    static SkPaint* gPaint;
+    static JSBool Draw(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
+    SkDisplayable* fDisplayable;
+};
+
+SkCanvas* SkJSDisplayable::gCanvas;
+SkPaint* SkJSDisplayable::gPaint;
+
+JSBool SkJSDisplayable::Draw(JSContext *cx, JSObject *obj, uintN argc,
+                                    jsval *argv, jsval *rval)
+{
+    SkJSDisplayable *p = (SkJSDisplayable*) JS_GetPrivate(cx, obj);
+    SkASSERT(p->fDisplayable->isDrawable());
+    SkDrawable* drawable = (SkDrawable*) p->fDisplayable;
+    SkAnimateMaker maker(NULL, gCanvas, gPaint);
+    drawable->draw(maker);
+    return JS_TRUE;
+}
+
+
+JSFunctionSpec SkJSDisplayable_methods[] = 
+{
+    { "draw", SkJSDisplayable::Draw, 1, 0, 0 },
+    { 0 }
+};
+
+static JSPropertySpec* gDisplayableProperties[kNumberOfTypes];
+static JSClass gDisplayableClasses[kNumberOfTypes];
+
+#define JS_INIT(_prefix, _class) \
+static JSBool _class##Constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { \
+    SkJSDisplayable* jsDisplayable = new SkJSDisplayable(); \
+    jsDisplayable->fDisplayable = new _prefix##_class(); \
+    JS_SetPrivate(cx, obj, (void*) jsDisplayable); \
+    return JS_TRUE; \
+} \
+    \
+static JSObject* _class##Init(JSContext *cx, JSObject *obj, JSObject *proto) { \
+    JSObject *newProtoObj = JS_InitClass(cx, obj, proto, &gDisplayableClasses[SkType_##_class], \
+        _class##Constructor, 0, \
+        NULL, SkJSDisplayable_methods , \
+        NULL, NULL); \
+    JS_DefineProperties(cx, newProtoObj, gDisplayableProperties[SkType_##_class]); \
+    return newProtoObj; \
+}
+
+JS_INIT(Sk, Add)
+JS_INIT(Sk, AddCircle)
+JS_INIT(Sk, AddOval)
+JS_INIT(Sk, AddPath)
+JS_INIT(Sk, AddRectangle)
+JS_INIT(Sk, AddRoundRect)
+//JS_INIT(Sk, After)
+JS_INIT(Sk, Apply)
+// JS_INIT(Sk, Animate)
+//JS_INIT(Sk, AnimateColor)
+JS_INIT(Sk, AnimateField)
+//JS_INIT(Sk, AnimateRotate)
+//JS_INIT(Sk, AnimateScale)
+//JS_INIT(Sk, AnimateTranslate)
+JS_INIT(SkDraw, Bitmap)
+JS_INIT(Sk, BaseBitmap)
+//JS_INIT(Sk, Before)
+JS_INIT(SkDraw, BitmapShader)
+JS_INIT(SkDraw, Blur)
+JS_INIT(SkDraw, Clip)
+JS_INIT(SkDraw, Color)
+JS_INIT(Sk, CubicTo)
+JS_INIT(Sk, Dash)
+JS_INIT(Sk, Data)
+//JS_INIT(Sk, Dimensions)
+JS_INIT(Sk, Discrete)
+JS_INIT(Sk, DrawTo)
+JS_INIT(SkDraw, Emboss)
+JS_INIT(SkDisplay, Event)
+// JS_INIT(SkDraw, Font)
+// JS_INIT(Sk, Focus)
+JS_INIT(Sk, Image)
+JS_INIT(Sk, Include)
+// JS_INIT(Sk, Input)
+JS_INIT(Sk, Line)
+JS_INIT(Sk, LinearGradient)
+JS_INIT(Sk, LineTo)
+JS_INIT(SkDraw, Matrix)
+JS_INIT(Sk, Move)
+JS_INIT(Sk, MoveTo)
+JS_INIT(Sk, Oval)
+JS_INIT(SkDraw, Path)
+JS_INIT(SkDraw, Paint)
+JS_INIT(Sk, DrawPoint)
+JS_INIT(Sk, PolyToPoly)
+JS_INIT(Sk, Polygon)
+JS_INIT(Sk, Polyline)
+JS_INIT(Sk, Post)
+JS_INIT(Sk, QuadTo)
+JS_INIT(Sk, RadialGradient)
+JS_INIT(SkDisplay, Random)
+JS_INIT(Sk, RectToRect)
+JS_INIT(Sk, Rectangle)
+JS_INIT(Sk, Remove)
+JS_INIT(Sk, Replace)
+JS_INIT(Sk, Rotate)
+JS_INIT(Sk, RoundRect)
+JS_INIT(Sk, Scale)
+JS_INIT(Sk, Set)
+JS_INIT(Sk, Skew)
+// JS_INIT(Sk, 3D_Camera)
+// JS_INIT(Sk, 3D_Patch)
+#ifdef SK_SUPPORT_IMAGE_ENCODE
+JS_INIT(Sk, Snapshot)
+#endif
+// JS_INIT(SkDraw, Stroke)
+JS_INIT(Sk, Text)
+JS_INIT(Sk, TextOnPath)
+JS_INIT(Sk, TextToPath)
+JS_INIT(Sk, Translate)
+//JS_INIT(Sk, Use)
+
+#if SK_USE_CONDENSED_INFO == 0
+static void GenerateTables() {
+    for (int index = 0; index < kTypeNamesSize; index++) {
+        int infoCount;
+        SkDisplayTypes type = gTypeNames[index].fType;
+        const SkMemberInfo* info = SkDisplayType::GetMembers(NULL /* fMaker */, type, &infoCount);
+        if (info == NULL)
+            continue;
+        gDisplayableProperties[type] = new JSPropertySpec[infoCount + 1];
+        JSPropertySpec* propertySpec = gDisplayableProperties[type];
+        memset(propertySpec, 0, sizeof (JSPropertySpec) * (infoCount + 1));
+        for (int inner = 0; inner < infoCount; inner++) {
+            if (info[inner].fType == SkType_BaseClassInfo)
+                continue;
+            propertySpec[inner].name = info[inner].fName;
+            propertySpec[inner].tinyid = inner;
+            propertySpec[inner].flags = JSPROP_ENUMERATE;
+        }
+        gDisplayableClasses[type].name = gTypeNames[index].fName;
+        gDisplayableClasses[type].flags = JSCLASS_HAS_PRIVATE;
+        gDisplayableClasses[type].addProperty = JS_PropertyStub;
+        gDisplayableClasses[type].delProperty = JS_PropertyStub;
+        gDisplayableClasses[type].getProperty = SkJSDisplayable::GetProperty;
+        gDisplayableClasses[type].setProperty = SkJSDisplayable::SetProperty;
+        gDisplayableClasses[type].enumerate = JS_EnumerateStub;
+        gDisplayableClasses[type].resolve = JS_ResolveStub;
+        gDisplayableClasses[type].convert = JS_ConvertStub;
+        gDisplayableClasses[type].finalize = SkJSDisplayable::Destructor;
+    }
+}
+#endif
+
+void SkJSDisplayable::Destructor(JSContext *cx, JSObject *obj) {
+    delete (SkJSDisplayable*) JS_GetPrivate(cx, obj);
+}
+
+JSBool SkJSDisplayable::GetProperty(JSContext *cx, JSObject *obj, jsval id,
+                                 jsval *vp)
+{
+    if (JSVAL_IS_INT(id) == 0)
+        return JS_TRUE; 
+    SkJSDisplayable *p = (SkJSDisplayable *) JS_GetPrivate(cx, obj);
+    SkDisplayable* displayable = p->fDisplayable;
+    SkDisplayTypes displayableType = displayable->getType();
+    int members;
+    const SkMemberInfo* info = SkDisplayType::GetMembers(NULL /* fMaker */, displayableType, &members);
+    int idIndex = JSVAL_TO_INT(id);
+    SkASSERT(idIndex >= 0 && idIndex < members);
+    info = &info[idIndex];
+    SkDisplayTypes infoType = (SkDisplayTypes) info->fType;
+    SkScalar scalar = 0;
+    S32 s32 = 0;
+    SkString* string= NULL;
+    JSString *str;
+    if (infoType == SkType_MemberProperty) {
+        infoType = info->propertyType();
+        switch (infoType) {
+            case SkType_Scalar: {
+                SkScriptValue scriptValue;
+                bool success = displayable->getProperty(info->propertyIndex(), &scriptValue);
+                SkASSERT(scriptValue.fType == SkType_Scalar);
+                scalar = scriptValue.fOperand.fScalar;
+                } break;
+            default:
+                SkASSERT(0); // !!! unimplemented
+        }
+    } else {
+        SkASSERT(info->fCount == 1);
+        switch (infoType) {
+            case SkType_Boolean:
+            case SkType_Color:
+            case SkType_S32:
+                s32 = *(S32*) info->memberData(displayable);
+                break;
+            case SkType_String:
+                info->getString(displayable, &string);
+                break;
+            case SkType_Scalar:
+                SkOperand operand;
+                info->getValue(displayable, &operand, 1);
+                scalar = operand.fScalar;
+                break;
+            default:
+                SkASSERT(0); // !!! unimplemented
+        }
+    }
+    switch (infoType) {
+        case SkType_Boolean:
+            *vp = BOOLEAN_TO_JSVAL(s32);
+            break;
+        case SkType_Color:
+        case SkType_S32:
+            *vp = INT_TO_JSVAL(s32);
+            break;
+        case SkType_Scalar:
+            if (SkScalarFraction(scalar) == 0)
+                *vp = INT_TO_JSVAL(SkScalarFloor(scalar));
+            else
+#ifdef SK_SCALAR_IS_FLOAT
+            *vp = DOUBLE_TO_JSVAL(scalar);
+#else
+            *vp = DOUBLE_TO_JSVAL(scalar / 65536.0f );
+#endif
+            break;
+        case SkType_String:
+            str = JS_NewStringCopyN(cx, string->c_str(), string->size());
+            *vp = STRING_TO_JSVAL(str);
+            break;
+        default:
+            SkASSERT(0); // !!! unimplemented
+    }
+    return JS_TRUE;
+}
+
+JSBool SkJSDisplayable::SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) {
+    if (JSVAL_IS_INT(id) == 0)
+        return JS_TRUE; 
+    SkJSDisplayable *p = (SkJSDisplayable *) JS_GetPrivate(cx, obj);
+    SkDisplayable* displayable = p->fDisplayable;
+    SkDisplayTypes displayableType = displayable->getType();
+    int members;
+    const SkMemberInfo* info = SkDisplayType::GetMembers(NULL /* fMaker */, displayableType, &members);
+    int idIndex = JSVAL_TO_INT(id);
+    SkASSERT(idIndex >= 0 && idIndex < members);
+    info = &info[idIndex];
+    SkDisplayTypes infoType = info->getType();
+    SkScalar scalar = 0;
+    S32 s32 = 0;
+    SkString string;
+    JSString* str;
+    jsval value = *vp;
+    switch (infoType) {
+        case SkType_Boolean:
+            s32 = JSVAL_TO_BOOLEAN(value);
+            break;
+        case SkType_Color:
+        case SkType_S32:
+            s32 = JSVAL_TO_INT(value);
+            break;
+        case SkType_Scalar:
+            if (JSVAL_IS_INT(value))
+                scalar = SkIntToScalar(JSVAL_TO_INT(value));
+            else {
+                SkASSERT(JSVAL_IS_DOUBLE(value));
+#ifdef SK_SCALAR_IS_FLOAT
+                scalar = (float) *(double*) JSVAL_TO_DOUBLE(value);
+#else
+                scalar = (SkFixed)  (*(double*)JSVAL_TO_DOUBLE(value) * 65536.0);
+#endif
+            }
+            break;
+        case SkType_String:
+            str = JS_ValueToString(cx, value);
+            string.set(JS_GetStringBytes(str));
+            break;
+        default:
+            SkASSERT(0); // !!! unimplemented
+    }
+    if (info->fType == SkType_MemberProperty) {
+        switch (infoType) {
+            case SkType_Scalar: {
+                SkScriptValue scriptValue;
+                scriptValue.fType = SkType_Scalar;
+                scriptValue.fOperand.fScalar = scalar;
+                displayable->setProperty(-1 - (int) info->fOffset, scriptValue);
+                } break;
+            default:
+                SkASSERT(0); // !!! unimplemented
+        }
+    } else {
+        SkASSERT(info->fCount == 1);
+        switch (infoType) {
+            case SkType_Boolean:
+            case SkType_Color:
+            case SkType_S32:
+                s32 = *(S32*) ((const char*) displayable + info->fOffset);
+                break;
+            case SkType_String:
+                info->setString(displayable, &string);
+                break;
+            case SkType_Scalar:
+                SkOperand operand;
+                operand.fScalar = scalar;
+                info->setValue(displayable, &operand, 1);
+                break;
+            default:
+                SkASSERT(0); // !!! unimplemented
+        }
+    }
+    return JS_TRUE;
+}
+
+void SkJS::InitializeDisplayables(const SkBitmap& bitmap, JSContext *cx, JSObject *obj, JSObject *proto) {
+    SkJSDisplayable::gCanvas = new SkCanvas(bitmap);
+    SkJSDisplayable::gPaint = new SkPaint();
+#if SK_USE_CONDENSED_INFO == 0
+    GenerateTables();
+#else
+    SkASSERT(0); // !!! compressed version hasn't been implemented
+#endif
+    AddInit(cx, obj, proto);
+    AddCircleInit(cx, obj, proto);
+    AddOvalInit(cx, obj, proto);
+    AddPathInit(cx, obj, proto);
+    AddRectangleInit(cx, obj, proto);
+    AddRoundRectInit(cx, obj, proto);
+//  AfterInit(cx, obj, proto);
+    ApplyInit(cx, obj, proto);
+    // AnimateInit(cx, obj, proto);
+//  AnimateColorInit(cx, obj, proto);
+    AnimateFieldInit(cx, obj, proto);
+//  AnimateRotateInit(cx, obj, proto);
+//  AnimateScaleInit(cx, obj, proto);
+//  AnimateTranslateInit(cx, obj, proto);
+    BitmapInit(cx, obj, proto);
+//  BaseBitmapInit(cx, obj, proto);
+//  BeforeInit(cx, obj, proto);
+    BitmapShaderInit(cx, obj, proto);
+    BlurInit(cx, obj, proto);
+    ClipInit(cx, obj, proto);
+    ColorInit(cx, obj, proto);
+    CubicToInit(cx, obj, proto);
+    DashInit(cx, obj, proto);
+    DataInit(cx, obj, proto);
+//  DimensionsInit(cx, obj, proto);
+    DiscreteInit(cx, obj, proto);
+    DrawToInit(cx, obj, proto);
+    EmbossInit(cx, obj, proto);
+    EventInit(cx, obj, proto);
+//  FontInit(cx, obj, proto);
+//  FocusInit(cx, obj, proto);
+    ImageInit(cx, obj, proto);
+    IncludeInit(cx, obj, proto);
+//  InputInit(cx, obj, proto);
+    LineInit(cx, obj, proto);
+    LinearGradientInit(cx, obj, proto);
+    LineToInit(cx, obj, proto);
+    MatrixInit(cx, obj, proto);
+    MoveInit(cx, obj, proto);
+    MoveToInit(cx, obj, proto);
+    OvalInit(cx, obj, proto);
+    PathInit(cx, obj, proto);
+    PaintInit(cx, obj, proto);
+    DrawPointInit(cx, obj, proto);
+    PolyToPolyInit(cx, obj, proto);
+    PolygonInit(cx, obj, proto);
+    PolylineInit(cx, obj, proto);
+    PostInit(cx, obj, proto);
+    QuadToInit(cx, obj, proto);
+    RadialGradientInit(cx, obj, proto);
+    RandomInit(cx, obj, proto);
+    RectToRectInit(cx, obj, proto);
+    RectangleInit(cx, obj, proto);
+    RemoveInit(cx, obj, proto);
+    ReplaceInit(cx, obj, proto);
+    RotateInit(cx, obj, proto);
+    RoundRectInit(cx, obj, proto);
+    ScaleInit(cx, obj, proto);
+    SetInit(cx, obj, proto);
+    SkewInit(cx, obj, proto);
+    // 3D_CameraInit(cx, obj, proto);
+    // 3D_PatchInit(cx, obj, proto);
+    #ifdef SK_SUPPORT_IMAGE_ENCODE
+    SnapshotInit(cx, obj, proto);
+    #endif
+//  StrokeInit(cx, obj, proto);
+    TextInit(cx, obj, proto);
+    TextOnPathInit(cx, obj, proto);
+    TextToPathInit(cx, obj, proto);
+    TranslateInit(cx, obj, proto);
+//  UseInit(cx, obj, proto);
+}
+
+void SkJS::DisposeDisplayables() {
+    delete SkJSDisplayable::gPaint;
+    delete SkJSDisplayable::gCanvas;
+    for (int index = 0; index < kTypeNamesSize; index++) {
+        SkDisplayTypes type = gTypeNames[index].fType;
+        delete[] gDisplayableProperties[type];
+    }
+}