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