SkJSDisplayable.cpp revision 03202c9c3dfbf8c4feb0a1ee9b3680817e633f58
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 66class SkJSDisplayable { 67public: 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 79SkCanvas* SkJSDisplayable::gCanvas; 80SkPaint* SkJSDisplayable::gPaint; 81 82JSBool 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 94JSFunctionSpec SkJSDisplayable_methods[] = 95{ 96 { "draw", SkJSDisplayable::Draw, 1, 0, 0 }, 97 { 0 } 98}; 99 100static JSPropertySpec* gDisplayableProperties[kNumberOfTypes]; 101static JSClass gDisplayableClasses[kNumberOfTypes]; 102 103#define JS_INIT(_prefix, _class) \ 104static 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 \ 111static 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 120JS_INIT(Sk, Add) 121JS_INIT(Sk, AddCircle) 122JS_INIT(Sk, AddOval) 123JS_INIT(Sk, AddPath) 124JS_INIT(Sk, AddRectangle) 125JS_INIT(Sk, AddRoundRect) 126//JS_INIT(Sk, After) 127JS_INIT(Sk, Apply) 128// JS_INIT(Sk, Animate) 129//JS_INIT(Sk, AnimateColor) 130JS_INIT(Sk, AnimateField) 131//JS_INIT(Sk, AnimateRotate) 132//JS_INIT(Sk, AnimateScale) 133//JS_INIT(Sk, AnimateTranslate) 134JS_INIT(SkDraw, Bitmap) 135JS_INIT(Sk, BaseBitmap) 136//JS_INIT(Sk, Before) 137JS_INIT(SkDraw, BitmapShader) 138JS_INIT(SkDraw, Blur) 139JS_INIT(SkDraw, Clip) 140JS_INIT(SkDraw, Color) 141JS_INIT(Sk, CubicTo) 142JS_INIT(Sk, Dash) 143JS_INIT(Sk, Data) 144//JS_INIT(Sk, Dimensions) 145JS_INIT(Sk, Discrete) 146JS_INIT(Sk, DrawTo) 147JS_INIT(SkDraw, Emboss) 148JS_INIT(SkDisplay, Event) 149// JS_INIT(SkDraw, Font) 150// JS_INIT(Sk, Focus) 151JS_INIT(Sk, Image) 152JS_INIT(Sk, Include) 153// JS_INIT(Sk, Input) 154JS_INIT(Sk, Line) 155JS_INIT(Sk, LinearGradient) 156JS_INIT(Sk, LineTo) 157JS_INIT(SkDraw, Matrix) 158JS_INIT(Sk, Move) 159JS_INIT(Sk, MoveTo) 160JS_INIT(Sk, Oval) 161JS_INIT(SkDraw, Path) 162JS_INIT(SkDraw, Paint) 163JS_INIT(Sk, DrawPoint) 164JS_INIT(Sk, PolyToPoly) 165JS_INIT(Sk, Polygon) 166JS_INIT(Sk, Polyline) 167JS_INIT(Sk, Post) 168JS_INIT(Sk, QuadTo) 169JS_INIT(Sk, RadialGradient) 170JS_INIT(SkDisplay, Random) 171JS_INIT(Sk, RectToRect) 172JS_INIT(Sk, Rectangle) 173JS_INIT(Sk, Remove) 174JS_INIT(Sk, Replace) 175JS_INIT(Sk, Rotate) 176JS_INIT(Sk, RoundRect) 177JS_INIT(Sk, Scale) 178JS_INIT(Sk, Set) 179JS_INIT(Sk, Skew) 180// JS_INIT(Sk, 3D_Camera) 181// JS_INIT(Sk, 3D_Patch) 182JS_INIT(Sk, Snapshot) 183// JS_INIT(SkDraw, Stroke) 184JS_INIT(Sk, Text) 185JS_INIT(Sk, TextOnPath) 186JS_INIT(Sk, TextToPath) 187JS_INIT(Sk, Translate) 188//JS_INIT(Sk, Use) 189 190#if SK_USE_CONDENSED_INFO == 0 191static 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 222void SkJSDisplayable::Destructor(JSContext *cx, JSObject *obj) { 223 delete (SkJSDisplayable*) JS_GetPrivate(cx, obj); 224} 225 226JSBool 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 304JSBool 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 382void 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 461void 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