| /* | |
| * Copyright 2006 The Android Open Source Project | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #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) | |
| JS_INIT(Sk, Snapshot) | |
| // 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 | |
| *vp = DOUBLE_TO_JSVAL(scalar); | |
| 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)); | |
| scalar = (float) *(double*) JSVAL_TO_DOUBLE(value); | |
| } | |
| 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); | |
| SnapshotInit(cx, obj, proto); | |
| // 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]; | |
| } | |
| } |