SkJSDisplayable.cpp revision 03202c9c3dfbf8c4feb0a1ee9b3680817e633f58
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
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)
182JS_INIT(Sk, Snapshot)
183// JS_INIT(SkDraw, Stroke)
184JS_INIT(Sk, Text)
185JS_INIT(Sk, TextOnPath)
186JS_INIT(Sk, TextToPath)
187JS_INIT(Sk, Translate)
188//JS_INIT(Sk, Use)
189
190#if SK_USE_CONDENSED_INFO == 0
191static 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
222void SkJSDisplayable::Destructor(JSContext *cx, JSObject *obj) {
223    delete (SkJSDisplayable*) JS_GetPrivate(cx, obj);
224}
225
226JSBool 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
304JSBool 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
382void 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
461void 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