• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
SkJSDisplayable()60     SkJSDisplayable() : fDisplayable(NULL) {}
~SkJSDisplayable()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 
Draw(JSContext * cx,JSObject * obj,uintN argc,jsval * argv,jsval * rval)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 
JS_INIT(Sk,Add)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 
Destructor(JSContext * cx,JSObject * obj)214 void SkJSDisplayable::Destructor(JSContext *cx, JSObject *obj) {
215     delete (SkJSDisplayable*) JS_GetPrivate(cx, obj);
216 }
217 
GetProperty(JSContext * cx,JSObject * obj,jsval id,jsval * vp)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 
SetProperty(JSContext * cx,JSObject * obj,jsval id,jsval * vp)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 
InitializeDisplayables(const SkBitmap & bitmap,JSContext * cx,JSObject * obj,JSObject * proto)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 
DisposeDisplayables()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