| |
| /* |
| * 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 |
| #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); |
| 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]; |
| } |
| } |