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 *vp = DOUBLE_TO_JSVAL(scalar); 281 break; 282 case SkType_String: 283 str = JS_NewStringCopyN(cx, string->c_str(), string->size()); 284 *vp = STRING_TO_JSVAL(str); 285 break; 286 default: 287 SkASSERT(0); // !!! unimplemented 288 } 289 return JS_TRUE; 290 } 291 292 JSBool SkJSDisplayable::SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { 293 if (JSVAL_IS_INT(id) == 0) 294 return JS_TRUE; 295 SkJSDisplayable *p = (SkJSDisplayable *) JS_GetPrivate(cx, obj); 296 SkDisplayable* displayable = p->fDisplayable; 297 SkDisplayTypes displayableType = displayable->getType(); 298 int members; 299 const SkMemberInfo* info = SkDisplayType::GetMembers(NULL /* fMaker */, displayableType, &members); 300 int idIndex = JSVAL_TO_INT(id); 301 SkASSERT(idIndex >= 0 && idIndex < members); 302 info = &info[idIndex]; 303 SkDisplayTypes infoType = info->getType(); 304 SkScalar scalar = 0; 305 S32 s32 = 0; 306 SkString string; 307 JSString* str; 308 jsval value = *vp; 309 switch (infoType) { 310 case SkType_Boolean: 311 s32 = JSVAL_TO_BOOLEAN(value); 312 break; 313 case SkType_Color: 314 case SkType_S32: 315 s32 = JSVAL_TO_INT(value); 316 break; 317 case SkType_Scalar: 318 if (JSVAL_IS_INT(value)) 319 scalar = SkIntToScalar(JSVAL_TO_INT(value)); 320 else { 321 SkASSERT(JSVAL_IS_DOUBLE(value)); 322 scalar = (float) *(double*) JSVAL_TO_DOUBLE(value); 323 } 324 break; 325 case SkType_String: 326 str = JS_ValueToString(cx, value); 327 string.set(JS_GetStringBytes(str)); 328 break; 329 default: 330 SkASSERT(0); // !!! unimplemented 331 } 332 if (info->fType == SkType_MemberProperty) { 333 switch (infoType) { 334 case SkType_Scalar: { 335 SkScriptValue scriptValue; 336 scriptValue.fType = SkType_Scalar; 337 scriptValue.fOperand.fScalar = scalar; 338 displayable->setProperty(-1 - (int) info->fOffset, scriptValue); 339 } break; 340 default: 341 SkASSERT(0); // !!! unimplemented 342 } 343 } else { 344 SkASSERT(info->fCount == 1); 345 switch (infoType) { 346 case SkType_Boolean: 347 case SkType_Color: 348 case SkType_S32: 349 s32 = *(S32*) ((const char*) displayable + info->fOffset); 350 break; 351 case SkType_String: 352 info->setString(displayable, &string); 353 break; 354 case SkType_Scalar: 355 SkOperand operand; 356 operand.fScalar = scalar; 357 info->setValue(displayable, &operand, 1); 358 break; 359 default: 360 SkASSERT(0); // !!! unimplemented 361 } 362 } 363 return JS_TRUE; 364 } 365 366 void SkJS::InitializeDisplayables(const SkBitmap& bitmap, JSContext *cx, JSObject *obj, JSObject *proto) { 367 SkJSDisplayable::gCanvas = new SkCanvas(bitmap); 368 SkJSDisplayable::gPaint = new SkPaint(); 369 #if SK_USE_CONDENSED_INFO == 0 370 GenerateTables(); 371 #else 372 SkASSERT(0); // !!! compressed version hasn't been implemented 373 #endif 374 AddInit(cx, obj, proto); 375 AddCircleInit(cx, obj, proto); 376 AddOvalInit(cx, obj, proto); 377 AddPathInit(cx, obj, proto); 378 AddRectangleInit(cx, obj, proto); 379 AddRoundRectInit(cx, obj, proto); 380 // AfterInit(cx, obj, proto); 381 ApplyInit(cx, obj, proto); 382 // AnimateInit(cx, obj, proto); 383 // AnimateColorInit(cx, obj, proto); 384 AnimateFieldInit(cx, obj, proto); 385 // AnimateRotateInit(cx, obj, proto); 386 // AnimateScaleInit(cx, obj, proto); 387 // AnimateTranslateInit(cx, obj, proto); 388 BitmapInit(cx, obj, proto); 389 // BaseBitmapInit(cx, obj, proto); 390 // BeforeInit(cx, obj, proto); 391 BitmapShaderInit(cx, obj, proto); 392 BlurInit(cx, obj, proto); 393 ClipInit(cx, obj, proto); 394 ColorInit(cx, obj, proto); 395 CubicToInit(cx, obj, proto); 396 DashInit(cx, obj, proto); 397 DataInit(cx, obj, proto); 398 // DimensionsInit(cx, obj, proto); 399 DiscreteInit(cx, obj, proto); 400 DrawToInit(cx, obj, proto); 401 EmbossInit(cx, obj, proto); 402 EventInit(cx, obj, proto); 403 // FontInit(cx, obj, proto); 404 // FocusInit(cx, obj, proto); 405 ImageInit(cx, obj, proto); 406 IncludeInit(cx, obj, proto); 407 // InputInit(cx, obj, proto); 408 LineInit(cx, obj, proto); 409 LinearGradientInit(cx, obj, proto); 410 LineToInit(cx, obj, proto); 411 MatrixInit(cx, obj, proto); 412 MoveInit(cx, obj, proto); 413 MoveToInit(cx, obj, proto); 414 OvalInit(cx, obj, proto); 415 PathInit(cx, obj, proto); 416 PaintInit(cx, obj, proto); 417 DrawPointInit(cx, obj, proto); 418 PolyToPolyInit(cx, obj, proto); 419 PolygonInit(cx, obj, proto); 420 PolylineInit(cx, obj, proto); 421 PostInit(cx, obj, proto); 422 QuadToInit(cx, obj, proto); 423 RadialGradientInit(cx, obj, proto); 424 RandomInit(cx, obj, proto); 425 RectToRectInit(cx, obj, proto); 426 RectangleInit(cx, obj, proto); 427 RemoveInit(cx, obj, proto); 428 ReplaceInit(cx, obj, proto); 429 RotateInit(cx, obj, proto); 430 RoundRectInit(cx, obj, proto); 431 ScaleInit(cx, obj, proto); 432 SetInit(cx, obj, proto); 433 SkewInit(cx, obj, proto); 434 // 3D_CameraInit(cx, obj, proto); 435 // 3D_PatchInit(cx, obj, proto); 436 SnapshotInit(cx, obj, proto); 437 // StrokeInit(cx, obj, proto); 438 TextInit(cx, obj, proto); 439 TextOnPathInit(cx, obj, proto); 440 TextToPathInit(cx, obj, proto); 441 TranslateInit(cx, obj, proto); 442 // UseInit(cx, obj, proto); 443 } 444 445 void SkJS::DisposeDisplayables() { 446 delete SkJSDisplayable::gPaint; 447 delete SkJSDisplayable::gCanvas; 448 for (int index = 0; index < kTypeNamesSize; index++) { 449 SkDisplayTypes type = gTypeNames[index].fType; 450 delete[] gDisplayableProperties[type]; 451 } 452 } 453