blob: d52a7c98f0adb38a2edab08c9565287be5b9c98f [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* 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)
182#ifdef SK_SUPPORT_IMAGE_ENCODE
183JS_INIT(Sk, Snapshot)
184#endif
185// JS_INIT(SkDraw, Stroke)
186JS_INIT(Sk, Text)
187JS_INIT(Sk, TextOnPath)
188JS_INIT(Sk, TextToPath)
189JS_INIT(Sk, Translate)
190//JS_INIT(Sk, Use)
191
192#if SK_USE_CONDENSED_INFO == 0
193static void GenerateTables() {
194 for (int index = 0; index < kTypeNamesSize; index++) {
195 int infoCount;
196 SkDisplayTypes type = gTypeNames[index].fType;
197 const SkMemberInfo* info = SkDisplayType::GetMembers(NULL /* fMaker */, type, &infoCount);
198 if (info == NULL)
199 continue;
200 gDisplayableProperties[type] = new JSPropertySpec[infoCount + 1];
201 JSPropertySpec* propertySpec = gDisplayableProperties[type];
202 memset(propertySpec, 0, sizeof (JSPropertySpec) * (infoCount + 1));
203 for (int inner = 0; inner < infoCount; inner++) {
204 if (info[inner].fType == SkType_BaseClassInfo)
205 continue;
206 propertySpec[inner].name = info[inner].fName;
207 propertySpec[inner].tinyid = inner;
208 propertySpec[inner].flags = JSPROP_ENUMERATE;
209 }
210 gDisplayableClasses[type].name = gTypeNames[index].fName;
211 gDisplayableClasses[type].flags = JSCLASS_HAS_PRIVATE;
212 gDisplayableClasses[type].addProperty = JS_PropertyStub;
213 gDisplayableClasses[type].delProperty = JS_PropertyStub;
214 gDisplayableClasses[type].getProperty = SkJSDisplayable::GetProperty;
215 gDisplayableClasses[type].setProperty = SkJSDisplayable::SetProperty;
216 gDisplayableClasses[type].enumerate = JS_EnumerateStub;
217 gDisplayableClasses[type].resolve = JS_ResolveStub;
218 gDisplayableClasses[type].convert = JS_ConvertStub;
219 gDisplayableClasses[type].finalize = SkJSDisplayable::Destructor;
220 }
221}
222#endif
223
224void SkJSDisplayable::Destructor(JSContext *cx, JSObject *obj) {
225 delete (SkJSDisplayable*) JS_GetPrivate(cx, obj);
226}
227
228JSBool SkJSDisplayable::GetProperty(JSContext *cx, JSObject *obj, jsval id,
229 jsval *vp)
230{
231 if (JSVAL_IS_INT(id) == 0)
232 return JS_TRUE;
233 SkJSDisplayable *p = (SkJSDisplayable *) JS_GetPrivate(cx, obj);
234 SkDisplayable* displayable = p->fDisplayable;
235 SkDisplayTypes displayableType = displayable->getType();
236 int members;
237 const SkMemberInfo* info = SkDisplayType::GetMembers(NULL /* fMaker */, displayableType, &members);
238 int idIndex = JSVAL_TO_INT(id);
239 SkASSERT(idIndex >= 0 && idIndex < members);
240 info = &info[idIndex];
241 SkDisplayTypes infoType = (SkDisplayTypes) info->fType;
242 SkScalar scalar = 0;
243 S32 s32 = 0;
244 SkString* string= NULL;
245 JSString *str;
246 if (infoType == SkType_MemberProperty) {
247 infoType = info->propertyType();
248 switch (infoType) {
249 case SkType_Scalar: {
250 SkScriptValue scriptValue;
251 bool success = displayable->getProperty(info->propertyIndex(), &scriptValue);
252 SkASSERT(scriptValue.fType == SkType_Scalar);
253 scalar = scriptValue.fOperand.fScalar;
254 } break;
255 default:
256 SkASSERT(0); // !!! unimplemented
257 }
258 } else {
259 SkASSERT(info->fCount == 1);
260 switch (infoType) {
261 case SkType_Boolean:
262 case SkType_Color:
263 case SkType_S32:
264 s32 = *(S32*) info->memberData(displayable);
265 break;
266 case SkType_String:
267 info->getString(displayable, &string);
268 break;
269 case SkType_Scalar:
270 SkOperand operand;
271 info->getValue(displayable, &operand, 1);
272 scalar = operand.fScalar;
273 break;
274 default:
275 SkASSERT(0); // !!! unimplemented
276 }
277 }
278 switch (infoType) {
279 case SkType_Boolean:
280 *vp = BOOLEAN_TO_JSVAL(s32);
281 break;
282 case SkType_Color:
283 case SkType_S32:
284 *vp = INT_TO_JSVAL(s32);
285 break;
286 case SkType_Scalar:
287 if (SkScalarFraction(scalar) == 0)
288 *vp = INT_TO_JSVAL(SkScalarFloor(scalar));
289 else
290#ifdef SK_SCALAR_IS_FLOAT
291 *vp = DOUBLE_TO_JSVAL(scalar);
292#else
293 *vp = DOUBLE_TO_JSVAL(scalar / 65536.0f );
294#endif
295 break;
296 case SkType_String:
297 str = JS_NewStringCopyN(cx, string->c_str(), string->size());
298 *vp = STRING_TO_JSVAL(str);
299 break;
300 default:
301 SkASSERT(0); // !!! unimplemented
302 }
303 return JS_TRUE;
304}
305
306JSBool SkJSDisplayable::SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) {
307 if (JSVAL_IS_INT(id) == 0)
308 return JS_TRUE;
309 SkJSDisplayable *p = (SkJSDisplayable *) JS_GetPrivate(cx, obj);
310 SkDisplayable* displayable = p->fDisplayable;
311 SkDisplayTypes displayableType = displayable->getType();
312 int members;
313 const SkMemberInfo* info = SkDisplayType::GetMembers(NULL /* fMaker */, displayableType, &members);
314 int idIndex = JSVAL_TO_INT(id);
315 SkASSERT(idIndex >= 0 && idIndex < members);
316 info = &info[idIndex];
317 SkDisplayTypes infoType = info->getType();
318 SkScalar scalar = 0;
319 S32 s32 = 0;
320 SkString string;
321 JSString* str;
322 jsval value = *vp;
323 switch (infoType) {
324 case SkType_Boolean:
325 s32 = JSVAL_TO_BOOLEAN(value);
326 break;
327 case SkType_Color:
328 case SkType_S32:
329 s32 = JSVAL_TO_INT(value);
330 break;
331 case SkType_Scalar:
332 if (JSVAL_IS_INT(value))
333 scalar = SkIntToScalar(JSVAL_TO_INT(value));
334 else {
335 SkASSERT(JSVAL_IS_DOUBLE(value));
336#ifdef SK_SCALAR_IS_FLOAT
337 scalar = (float) *(double*) JSVAL_TO_DOUBLE(value);
338#else
339 scalar = (SkFixed) (*(double*)JSVAL_TO_DOUBLE(value) * 65536.0);
340#endif
341 }
342 break;
343 case SkType_String:
344 str = JS_ValueToString(cx, value);
345 string.set(JS_GetStringBytes(str));
346 break;
347 default:
348 SkASSERT(0); // !!! unimplemented
349 }
350 if (info->fType == SkType_MemberProperty) {
351 switch (infoType) {
352 case SkType_Scalar: {
353 SkScriptValue scriptValue;
354 scriptValue.fType = SkType_Scalar;
355 scriptValue.fOperand.fScalar = scalar;
356 displayable->setProperty(-1 - (int) info->fOffset, scriptValue);
357 } break;
358 default:
359 SkASSERT(0); // !!! unimplemented
360 }
361 } else {
362 SkASSERT(info->fCount == 1);
363 switch (infoType) {
364 case SkType_Boolean:
365 case SkType_Color:
366 case SkType_S32:
367 s32 = *(S32*) ((const char*) displayable + info->fOffset);
368 break;
369 case SkType_String:
370 info->setString(displayable, &string);
371 break;
372 case SkType_Scalar:
373 SkOperand operand;
374 operand.fScalar = scalar;
375 info->setValue(displayable, &operand, 1);
376 break;
377 default:
378 SkASSERT(0); // !!! unimplemented
379 }
380 }
381 return JS_TRUE;
382}
383
384void SkJS::InitializeDisplayables(const SkBitmap& bitmap, JSContext *cx, JSObject *obj, JSObject *proto) {
385 SkJSDisplayable::gCanvas = new SkCanvas(bitmap);
386 SkJSDisplayable::gPaint = new SkPaint();
387#if SK_USE_CONDENSED_INFO == 0
388 GenerateTables();
389#else
390 SkASSERT(0); // !!! compressed version hasn't been implemented
391#endif
392 AddInit(cx, obj, proto);
393 AddCircleInit(cx, obj, proto);
394 AddOvalInit(cx, obj, proto);
395 AddPathInit(cx, obj, proto);
396 AddRectangleInit(cx, obj, proto);
397 AddRoundRectInit(cx, obj, proto);
398// AfterInit(cx, obj, proto);
399 ApplyInit(cx, obj, proto);
400 // AnimateInit(cx, obj, proto);
401// AnimateColorInit(cx, obj, proto);
402 AnimateFieldInit(cx, obj, proto);
403// AnimateRotateInit(cx, obj, proto);
404// AnimateScaleInit(cx, obj, proto);
405// AnimateTranslateInit(cx, obj, proto);
406 BitmapInit(cx, obj, proto);
407// BaseBitmapInit(cx, obj, proto);
408// BeforeInit(cx, obj, proto);
409 BitmapShaderInit(cx, obj, proto);
410 BlurInit(cx, obj, proto);
411 ClipInit(cx, obj, proto);
412 ColorInit(cx, obj, proto);
413 CubicToInit(cx, obj, proto);
414 DashInit(cx, obj, proto);
415 DataInit(cx, obj, proto);
416// DimensionsInit(cx, obj, proto);
417 DiscreteInit(cx, obj, proto);
418 DrawToInit(cx, obj, proto);
419 EmbossInit(cx, obj, proto);
420 EventInit(cx, obj, proto);
421// FontInit(cx, obj, proto);
422// FocusInit(cx, obj, proto);
423 ImageInit(cx, obj, proto);
424 IncludeInit(cx, obj, proto);
425// InputInit(cx, obj, proto);
426 LineInit(cx, obj, proto);
427 LinearGradientInit(cx, obj, proto);
428 LineToInit(cx, obj, proto);
429 MatrixInit(cx, obj, proto);
430 MoveInit(cx, obj, proto);
431 MoveToInit(cx, obj, proto);
432 OvalInit(cx, obj, proto);
433 PathInit(cx, obj, proto);
434 PaintInit(cx, obj, proto);
435 DrawPointInit(cx, obj, proto);
436 PolyToPolyInit(cx, obj, proto);
437 PolygonInit(cx, obj, proto);
438 PolylineInit(cx, obj, proto);
439 PostInit(cx, obj, proto);
440 QuadToInit(cx, obj, proto);
441 RadialGradientInit(cx, obj, proto);
442 RandomInit(cx, obj, proto);
443 RectToRectInit(cx, obj, proto);
444 RectangleInit(cx, obj, proto);
445 RemoveInit(cx, obj, proto);
446 ReplaceInit(cx, obj, proto);
447 RotateInit(cx, obj, proto);
448 RoundRectInit(cx, obj, proto);
449 ScaleInit(cx, obj, proto);
450 SetInit(cx, obj, proto);
451 SkewInit(cx, obj, proto);
452 // 3D_CameraInit(cx, obj, proto);
453 // 3D_PatchInit(cx, obj, proto);
454 #ifdef SK_SUPPORT_IMAGE_ENCODE
455 SnapshotInit(cx, obj, proto);
456 #endif
457// StrokeInit(cx, obj, proto);
458 TextInit(cx, obj, proto);
459 TextOnPathInit(cx, obj, proto);
460 TextToPathInit(cx, obj, proto);
461 TranslateInit(cx, obj, proto);
462// UseInit(cx, obj, proto);
463}
464
465void SkJS::DisposeDisplayables() {
466 delete SkJSDisplayable::gPaint;
467 delete SkJSDisplayable::gCanvas;
468 for (int index = 0; index < kTypeNamesSize; index++) {
469 SkDisplayTypes type = gTypeNames[index].fType;
470 delete[] gDisplayableProperties[type];
471 }
472}