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