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