Home | History | Annotate | Download | only in xml
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #include <jsapi.h>
     11 #include "SkJS.h"
     12 #include "SkDisplayType.h"
     13 //#include "SkAnimateColor.h"
     14 #include "SkAnimateMaker.h"
     15 #include "SkAnimateSet.h"
     16 //#include "SkAnimateTransform.h"
     17 #include "SkCanvas.h"
     18 //#include "SkDimensions.h"
     19 #include "SkDisplayAdd.h"
     20 #include "SkDisplayApply.h"
     21 //#include "SkDisplayBefore.h"
     22 #include "SkDisplayEvent.h"
     23 //#include "SkDisplayFocus.h"
     24 #include "SkDisplayInclude.h"
     25 #include "SkDisplayPost.h"
     26 #include "SkDisplayRandom.h"
     27 #include "SkDraw3D.h"
     28 #include "SkDrawBitmap.h"
     29 #include "SkDrawClip.h"
     30 #include "SkDrawDash.h"
     31 #include "SkDrawDiscrete.h"
     32 #include "SkDrawEmboss.h"
     33 //#include "SkDrawFont.h"
     34 #include "SkDrawFull.h"
     35 #include "SkDrawGradient.h"
     36 #include "SkDrawLine.h"
     37 //#include "SkDrawMaskFilter.h"
     38 #include "SkDrawMatrix.h"
     39 #include "SkDrawOval.h"
     40 #include "SkDrawPaint.h"
     41 #include "SkDrawPath.h"
     42 #include "SkDrawPoint.h"
     43 // #include "SkDrawStroke.h"
     44 #include "SkDrawText.h"
     45 #include "SkDrawTo.h"
     46 //#include "SkDrawTransferMode.h"
     47 #include "SkDrawTransparentShader.h"
     48 //#include "SkDrawUse.h"
     49 #include "SkMatrixParts.h"
     50 #include "SkPathParts.h"
     51 #include "SkPostParts.h"
     52 #include "SkScript.h"
     53 #include "SkSnapshot.h"
     54 #include "SkTextOnPath.h"
     55 #include "SkTextToPath.h"
     56 
     57 
     58 class SkJSDisplayable {
     59 public:
     60     SkJSDisplayable() : fDisplayable(NULL) {}
     61     ~SkJSDisplayable() { delete fDisplayable; }
     62     static void Destructor(JSContext *cx, JSObject *obj);
     63     static JSBool GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
     64     static JSBool SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp);
     65     static SkCanvas* gCanvas;
     66     static SkPaint* gPaint;
     67     static JSBool Draw(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);
     68     SkDisplayable* fDisplayable;
     69 };
     70 
     71 SkCanvas* SkJSDisplayable::gCanvas;
     72 SkPaint* SkJSDisplayable::gPaint;
     73 
     74 JSBool SkJSDisplayable::Draw(JSContext *cx, JSObject *obj, uintN argc,
     75                                     jsval *argv, jsval *rval)
     76 {
     77     SkJSDisplayable *p = (SkJSDisplayable*) JS_GetPrivate(cx, obj);
     78     SkASSERT(p->fDisplayable->isDrawable());
     79     SkDrawable* drawable = (SkDrawable*) p->fDisplayable;
     80     SkAnimateMaker maker(NULL, gCanvas, gPaint);
     81     drawable->draw(maker);
     82     return JS_TRUE;
     83 }
     84 
     85 
     86 JSFunctionSpec SkJSDisplayable_methods[] =
     87 {
     88     { "draw", SkJSDisplayable::Draw, 1, 0, 0 },
     89     { 0 }
     90 };
     91 
     92 static JSPropertySpec* gDisplayableProperties[kNumberOfTypes];
     93 static JSClass gDisplayableClasses[kNumberOfTypes];
     94 
     95 #define JS_INIT(_prefix, _class) \
     96 static JSBool _class##Constructor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { \
     97     SkJSDisplayable* jsDisplayable = new SkJSDisplayable(); \
     98     jsDisplayable->fDisplayable = new _prefix##_class(); \
     99     JS_SetPrivate(cx, obj, (void*) jsDisplayable); \
    100     return JS_TRUE; \
    101 } \
    102     \
    103 static JSObject* _class##Init(JSContext *cx, JSObject *obj, JSObject *proto) { \
    104     JSObject *newProtoObj = JS_InitClass(cx, obj, proto, &gDisplayableClasses[SkType_##_class], \
    105         _class##Constructor, 0, \
    106         NULL, SkJSDisplayable_methods , \
    107         NULL, NULL); \
    108     JS_DefineProperties(cx, newProtoObj, gDisplayableProperties[SkType_##_class]); \
    109     return newProtoObj; \
    110 }
    111 
    112 JS_INIT(Sk, Add)
    113 JS_INIT(Sk, AddCircle)
    114 JS_INIT(Sk, AddOval)
    115 JS_INIT(Sk, AddPath)
    116 JS_INIT(Sk, AddRectangle)
    117 JS_INIT(Sk, AddRoundRect)
    118 //JS_INIT(Sk, After)
    119 JS_INIT(Sk, Apply)
    120 // JS_INIT(Sk, Animate)
    121 //JS_INIT(Sk, AnimateColor)
    122 JS_INIT(Sk, AnimateField)
    123 //JS_INIT(Sk, AnimateRotate)
    124 //JS_INIT(Sk, AnimateScale)
    125 //JS_INIT(Sk, AnimateTranslate)
    126 JS_INIT(SkDraw, Bitmap)
    127 JS_INIT(Sk, BaseBitmap)
    128 //JS_INIT(Sk, Before)
    129 JS_INIT(SkDraw, BitmapShader)
    130 JS_INIT(SkDraw, Blur)
    131 JS_INIT(SkDraw, Clip)
    132 JS_INIT(SkDraw, Color)
    133 JS_INIT(Sk, CubicTo)
    134 JS_INIT(Sk, Dash)
    135 JS_INIT(Sk, Data)
    136 //JS_INIT(Sk, Dimensions)
    137 JS_INIT(Sk, Discrete)
    138 JS_INIT(Sk, DrawTo)
    139 JS_INIT(SkDraw, Emboss)
    140 JS_INIT(SkDisplay, Event)
    141 // JS_INIT(SkDraw, Font)
    142 // JS_INIT(Sk, Focus)
    143 JS_INIT(Sk, Image)
    144 JS_INIT(Sk, Include)
    145 // JS_INIT(Sk, Input)
    146 JS_INIT(Sk, Line)
    147 JS_INIT(Sk, LinearGradient)
    148 JS_INIT(Sk, LineTo)
    149 JS_INIT(SkDraw, Matrix)
    150 JS_INIT(Sk, Move)
    151 JS_INIT(Sk, MoveTo)
    152 JS_INIT(Sk, Oval)
    153 JS_INIT(SkDraw, Path)
    154 JS_INIT(SkDraw, Paint)
    155 JS_INIT(Sk, DrawPoint)
    156 JS_INIT(Sk, PolyToPoly)
    157 JS_INIT(Sk, Polygon)
    158 JS_INIT(Sk, Polyline)
    159 JS_INIT(Sk, Post)
    160 JS_INIT(Sk, QuadTo)
    161 JS_INIT(Sk, RadialGradient)
    162 JS_INIT(SkDisplay, Random)
    163 JS_INIT(Sk, RectToRect)
    164 JS_INIT(Sk, Rectangle)
    165 JS_INIT(Sk, Remove)
    166 JS_INIT(Sk, Replace)
    167 JS_INIT(Sk, Rotate)
    168 JS_INIT(Sk, RoundRect)
    169 JS_INIT(Sk, Scale)
    170 JS_INIT(Sk, Set)
    171 JS_INIT(Sk, Skew)
    172 // JS_INIT(Sk, 3D_Camera)
    173 // JS_INIT(Sk, 3D_Patch)
    174 JS_INIT(Sk, Snapshot)
    175 // JS_INIT(SkDraw, Stroke)
    176 JS_INIT(Sk, Text)
    177 JS_INIT(Sk, TextOnPath)
    178 JS_INIT(Sk, TextToPath)
    179 JS_INIT(Sk, Translate)
    180 //JS_INIT(Sk, Use)
    181 
    182 #if SK_USE_CONDENSED_INFO == 0
    183 static void GenerateTables() {
    184     for (int index = 0; index < kTypeNamesSize; index++) {
    185         int infoCount;
    186         SkDisplayTypes type = gTypeNames[index].fType;
    187         const SkMemberInfo* info = SkDisplayType::GetMembers(NULL /* fMaker */, type, &infoCount);
    188         if (info == NULL)
    189             continue;
    190         gDisplayableProperties[type] = new JSPropertySpec[infoCount + 1];
    191         JSPropertySpec* propertySpec = gDisplayableProperties[type];
    192         memset(propertySpec, 0, sizeof (JSPropertySpec) * (infoCount + 1));
    193         for (int inner = 0; inner < infoCount; inner++) {
    194             if (info[inner].fType == SkType_BaseClassInfo)
    195                 continue;
    196             propertySpec[inner].name = info[inner].fName;
    197             propertySpec[inner].tinyid = inner;
    198             propertySpec[inner].flags = JSPROP_ENUMERATE;
    199         }
    200         gDisplayableClasses[type].name = gTypeNames[index].fName;
    201         gDisplayableClasses[type].flags = JSCLASS_HAS_PRIVATE;
    202         gDisplayableClasses[type].addProperty = JS_PropertyStub;
    203         gDisplayableClasses[type].delProperty = JS_PropertyStub;
    204         gDisplayableClasses[type].getProperty = SkJSDisplayable::GetProperty;
    205         gDisplayableClasses[type].setProperty = SkJSDisplayable::SetProperty;
    206         gDisplayableClasses[type].enumerate = JS_EnumerateStub;
    207         gDisplayableClasses[type].resolve = JS_ResolveStub;
    208         gDisplayableClasses[type].convert = JS_ConvertStub;
    209         gDisplayableClasses[type].finalize = SkJSDisplayable::Destructor;
    210     }
    211 }
    212 #endif
    213 
    214 void SkJSDisplayable::Destructor(JSContext *cx, JSObject *obj) {
    215     delete (SkJSDisplayable*) JS_GetPrivate(cx, obj);
    216 }
    217 
    218 JSBool SkJSDisplayable::GetProperty(JSContext *cx, JSObject *obj, jsval id,
    219                                  jsval *vp)
    220 {
    221     if (JSVAL_IS_INT(id) == 0)
    222         return JS_TRUE;
    223     SkJSDisplayable *p = (SkJSDisplayable *) JS_GetPrivate(cx, obj);
    224     SkDisplayable* displayable = p->fDisplayable;
    225     SkDisplayTypes displayableType = displayable->getType();
    226     int members;
    227     const SkMemberInfo* info = SkDisplayType::GetMembers(NULL /* fMaker */, displayableType, &members);
    228     int idIndex = JSVAL_TO_INT(id);
    229     SkASSERT(idIndex >= 0 && idIndex < members);
    230     info = &info[idIndex];
    231     SkDisplayTypes infoType = (SkDisplayTypes) info->fType;
    232     SkScalar scalar = 0;
    233     S32 s32 = 0;
    234     SkString* string= NULL;
    235     JSString *str;
    236     if (infoType == SkType_MemberProperty) {
    237         infoType = info->propertyType();
    238         switch (infoType) {
    239             case SkType_Scalar: {
    240                 SkScriptValue scriptValue;
    241                 bool success = displayable->getProperty(info->propertyIndex(), &scriptValue);
    242                 SkASSERT(scriptValue.fType == SkType_Scalar);
    243                 scalar = scriptValue.fOperand.fScalar;
    244                 } break;
    245             default:
    246                 SkASSERT(0); // !!! unimplemented
    247         }
    248     } else {
    249         SkASSERT(info->fCount == 1);
    250         switch (infoType) {
    251             case SkType_Boolean:
    252             case SkType_Color:
    253             case SkType_S32:
    254                 s32 = *(S32*) info->memberData(displayable);
    255                 break;
    256             case SkType_String:
    257                 info->getString(displayable, &string);
    258                 break;
    259             case SkType_Scalar:
    260                 SkOperand operand;
    261                 info->getValue(displayable, &operand, 1);
    262                 scalar = operand.fScalar;
    263                 break;
    264             default:
    265                 SkASSERT(0); // !!! unimplemented
    266         }
    267     }
    268     switch (infoType) {
    269         case SkType_Boolean:
    270             *vp = BOOLEAN_TO_JSVAL(s32);
    271             break;
    272         case SkType_Color:
    273         case SkType_S32:
    274             *vp = INT_TO_JSVAL(s32);
    275             break;
    276         case SkType_Scalar:
    277             if (SkScalarFraction(scalar) == 0)
    278                 *vp = INT_TO_JSVAL(SkScalarFloor(scalar));
    279             else
    280 #ifdef SK_SCALAR_IS_FLOAT
    281             *vp = DOUBLE_TO_JSVAL(scalar);
    282 #else
    283             *vp = DOUBLE_TO_JSVAL(scalar / 65536.0f );
    284 #endif
    285             break;
    286         case SkType_String:
    287             str = JS_NewStringCopyN(cx, string->c_str(), string->size());
    288             *vp = STRING_TO_JSVAL(str);
    289             break;
    290         default:
    291             SkASSERT(0); // !!! unimplemented
    292     }
    293     return JS_TRUE;
    294 }
    295 
    296 JSBool SkJSDisplayable::SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) {
    297     if (JSVAL_IS_INT(id) == 0)
    298         return JS_TRUE;
    299     SkJSDisplayable *p = (SkJSDisplayable *) JS_GetPrivate(cx, obj);
    300     SkDisplayable* displayable = p->fDisplayable;
    301     SkDisplayTypes displayableType = displayable->getType();
    302     int members;
    303     const SkMemberInfo* info = SkDisplayType::GetMembers(NULL /* fMaker */, displayableType, &members);
    304     int idIndex = JSVAL_TO_INT(id);
    305     SkASSERT(idIndex >= 0 && idIndex < members);
    306     info = &info[idIndex];
    307     SkDisplayTypes infoType = info->getType();
    308     SkScalar scalar = 0;
    309     S32 s32 = 0;
    310     SkString string;
    311     JSString* str;
    312     jsval value = *vp;
    313     switch (infoType) {
    314         case SkType_Boolean:
    315             s32 = JSVAL_TO_BOOLEAN(value);
    316             break;
    317         case SkType_Color:
    318         case SkType_S32:
    319             s32 = JSVAL_TO_INT(value);
    320             break;
    321         case SkType_Scalar:
    322             if (JSVAL_IS_INT(value))
    323                 scalar = SkIntToScalar(JSVAL_TO_INT(value));
    324             else {
    325                 SkASSERT(JSVAL_IS_DOUBLE(value));
    326 #ifdef SK_SCALAR_IS_FLOAT
    327                 scalar = (float) *(double*) JSVAL_TO_DOUBLE(value);
    328 #else
    329                 scalar = (SkFixed)  (*(double*)JSVAL_TO_DOUBLE(value) * 65536.0);
    330 #endif
    331             }
    332             break;
    333         case SkType_String:
    334             str = JS_ValueToString(cx, value);
    335             string.set(JS_GetStringBytes(str));
    336             break;
    337         default:
    338             SkASSERT(0); // !!! unimplemented
    339     }
    340     if (info->fType == SkType_MemberProperty) {
    341         switch (infoType) {
    342             case SkType_Scalar: {
    343                 SkScriptValue scriptValue;
    344                 scriptValue.fType = SkType_Scalar;
    345                 scriptValue.fOperand.fScalar = scalar;
    346                 displayable->setProperty(-1 - (int) info->fOffset, scriptValue);
    347                 } break;
    348             default:
    349                 SkASSERT(0); // !!! unimplemented
    350         }
    351     } else {
    352         SkASSERT(info->fCount == 1);
    353         switch (infoType) {
    354             case SkType_Boolean:
    355             case SkType_Color:
    356             case SkType_S32:
    357                 s32 = *(S32*) ((const char*) displayable + info->fOffset);
    358                 break;
    359             case SkType_String:
    360                 info->setString(displayable, &string);
    361                 break;
    362             case SkType_Scalar:
    363                 SkOperand operand;
    364                 operand.fScalar = scalar;
    365                 info->setValue(displayable, &operand, 1);
    366                 break;
    367             default:
    368                 SkASSERT(0); // !!! unimplemented
    369         }
    370     }
    371     return JS_TRUE;
    372 }
    373 
    374 void SkJS::InitializeDisplayables(const SkBitmap& bitmap, JSContext *cx, JSObject *obj, JSObject *proto) {
    375     SkJSDisplayable::gCanvas = new SkCanvas(bitmap);
    376     SkJSDisplayable::gPaint = new SkPaint();
    377 #if SK_USE_CONDENSED_INFO == 0
    378     GenerateTables();
    379 #else
    380     SkASSERT(0); // !!! compressed version hasn't been implemented
    381 #endif
    382     AddInit(cx, obj, proto);
    383     AddCircleInit(cx, obj, proto);
    384     AddOvalInit(cx, obj, proto);
    385     AddPathInit(cx, obj, proto);
    386     AddRectangleInit(cx, obj, proto);
    387     AddRoundRectInit(cx, obj, proto);
    388 //  AfterInit(cx, obj, proto);
    389     ApplyInit(cx, obj, proto);
    390     // AnimateInit(cx, obj, proto);
    391 //  AnimateColorInit(cx, obj, proto);
    392     AnimateFieldInit(cx, obj, proto);
    393 //  AnimateRotateInit(cx, obj, proto);
    394 //  AnimateScaleInit(cx, obj, proto);
    395 //  AnimateTranslateInit(cx, obj, proto);
    396     BitmapInit(cx, obj, proto);
    397 //  BaseBitmapInit(cx, obj, proto);
    398 //  BeforeInit(cx, obj, proto);
    399     BitmapShaderInit(cx, obj, proto);
    400     BlurInit(cx, obj, proto);
    401     ClipInit(cx, obj, proto);
    402     ColorInit(cx, obj, proto);
    403     CubicToInit(cx, obj, proto);
    404     DashInit(cx, obj, proto);
    405     DataInit(cx, obj, proto);
    406 //  DimensionsInit(cx, obj, proto);
    407     DiscreteInit(cx, obj, proto);
    408     DrawToInit(cx, obj, proto);
    409     EmbossInit(cx, obj, proto);
    410     EventInit(cx, obj, proto);
    411 //  FontInit(cx, obj, proto);
    412 //  FocusInit(cx, obj, proto);
    413     ImageInit(cx, obj, proto);
    414     IncludeInit(cx, obj, proto);
    415 //  InputInit(cx, obj, proto);
    416     LineInit(cx, obj, proto);
    417     LinearGradientInit(cx, obj, proto);
    418     LineToInit(cx, obj, proto);
    419     MatrixInit(cx, obj, proto);
    420     MoveInit(cx, obj, proto);
    421     MoveToInit(cx, obj, proto);
    422     OvalInit(cx, obj, proto);
    423     PathInit(cx, obj, proto);
    424     PaintInit(cx, obj, proto);
    425     DrawPointInit(cx, obj, proto);
    426     PolyToPolyInit(cx, obj, proto);
    427     PolygonInit(cx, obj, proto);
    428     PolylineInit(cx, obj, proto);
    429     PostInit(cx, obj, proto);
    430     QuadToInit(cx, obj, proto);
    431     RadialGradientInit(cx, obj, proto);
    432     RandomInit(cx, obj, proto);
    433     RectToRectInit(cx, obj, proto);
    434     RectangleInit(cx, obj, proto);
    435     RemoveInit(cx, obj, proto);
    436     ReplaceInit(cx, obj, proto);
    437     RotateInit(cx, obj, proto);
    438     RoundRectInit(cx, obj, proto);
    439     ScaleInit(cx, obj, proto);
    440     SetInit(cx, obj, proto);
    441     SkewInit(cx, obj, proto);
    442     // 3D_CameraInit(cx, obj, proto);
    443     // 3D_PatchInit(cx, obj, proto);
    444     SnapshotInit(cx, obj, proto);
    445 //  StrokeInit(cx, obj, proto);
    446     TextInit(cx, obj, proto);
    447     TextOnPathInit(cx, obj, proto);
    448     TextToPathInit(cx, obj, proto);
    449     TranslateInit(cx, obj, proto);
    450 //  UseInit(cx, obj, proto);
    451 }
    452 
    453 void SkJS::DisposeDisplayables() {
    454     delete SkJSDisplayable::gPaint;
    455     delete SkJSDisplayable::gCanvas;
    456     for (int index = 0; index < kTypeNamesSize; index++) {
    457         SkDisplayTypes type = gTypeNames[index].fType;
    458         delete[] gDisplayableProperties[type];
    459     }
    460 }
    461