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