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