|
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: |
|
60 SkJSDisplayable() : fDisplayable(NULL) {} |
|
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 |
|
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 |
|
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 |
|
214 void SkJSDisplayable::Destructor(JSContext *cx, JSObject *obj) { |
|
215 delete (SkJSDisplayable*) JS_GetPrivate(cx, obj); |
|
216 } |
|
217 |
|
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 *vp = DOUBLE_TO_JSVAL(scalar); |
|
281 break; |
|
282 case SkType_String: |
|
283 str = JS_NewStringCopyN(cx, string->c_str(), string->size()); |
|
284 *vp = STRING_TO_JSVAL(str); |
|
285 break; |
|
286 default: |
|
287 SkASSERT(0); // !!! unimplemented |
|
288 } |
|
289 return JS_TRUE; |
|
290 } |
|
291 |
|
292 JSBool SkJSDisplayable::SetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { |
|
293 if (JSVAL_IS_INT(id) == 0) |
|
294 return JS_TRUE; |
|
295 SkJSDisplayable *p = (SkJSDisplayable *) JS_GetPrivate(cx, obj); |
|
296 SkDisplayable* displayable = p->fDisplayable; |
|
297 SkDisplayTypes displayableType = displayable->getType(); |
|
298 int members; |
|
299 const SkMemberInfo* info = SkDisplayType::GetMembers(NULL /* fMaker */, displayableType, &members); |
|
300 int idIndex = JSVAL_TO_INT(id); |
|
301 SkASSERT(idIndex >= 0 && idIndex < members); |
|
302 info = &info[idIndex]; |
|
303 SkDisplayTypes infoType = info->getType(); |
|
304 SkScalar scalar = 0; |
|
305 S32 s32 = 0; |
|
306 SkString string; |
|
307 JSString* str; |
|
308 jsval value = *vp; |
|
309 switch (infoType) { |
|
310 case SkType_Boolean: |
|
311 s32 = JSVAL_TO_BOOLEAN(value); |
|
312 break; |
|
313 case SkType_Color: |
|
314 case SkType_S32: |
|
315 s32 = JSVAL_TO_INT(value); |
|
316 break; |
|
317 case SkType_Scalar: |
|
318 if (JSVAL_IS_INT(value)) |
|
319 scalar = SkIntToScalar(JSVAL_TO_INT(value)); |
|
320 else { |
|
321 SkASSERT(JSVAL_IS_DOUBLE(value)); |
|
322 scalar = (float) *(double*) JSVAL_TO_DOUBLE(value); |
|
323 } |
|
324 break; |
|
325 case SkType_String: |
|
326 str = JS_ValueToString(cx, value); |
|
327 string.set(JS_GetStringBytes(str)); |
|
328 break; |
|
329 default: |
|
330 SkASSERT(0); // !!! unimplemented |
|
331 } |
|
332 if (info->fType == SkType_MemberProperty) { |
|
333 switch (infoType) { |
|
334 case SkType_Scalar: { |
|
335 SkScriptValue scriptValue; |
|
336 scriptValue.fType = SkType_Scalar; |
|
337 scriptValue.fOperand.fScalar = scalar; |
|
338 displayable->setProperty(-1 - (int) info->fOffset, scriptValue); |
|
339 } break; |
|
340 default: |
|
341 SkASSERT(0); // !!! unimplemented |
|
342 } |
|
343 } else { |
|
344 SkASSERT(info->fCount == 1); |
|
345 switch (infoType) { |
|
346 case SkType_Boolean: |
|
347 case SkType_Color: |
|
348 case SkType_S32: |
|
349 s32 = *(S32*) ((const char*) displayable + info->fOffset); |
|
350 break; |
|
351 case SkType_String: |
|
352 info->setString(displayable, &string); |
|
353 break; |
|
354 case SkType_Scalar: |
|
355 SkOperand operand; |
|
356 operand.fScalar = scalar; |
|
357 info->setValue(displayable, &operand, 1); |
|
358 break; |
|
359 default: |
|
360 SkASSERT(0); // !!! unimplemented |
|
361 } |
|
362 } |
|
363 return JS_TRUE; |
|
364 } |
|
365 |
|
366 void SkJS::InitializeDisplayables(const SkBitmap& bitmap, JSContext *cx, JSObject *obj, JSObject *proto) { |
|
367 SkJSDisplayable::gCanvas = new SkCanvas(bitmap); |
|
368 SkJSDisplayable::gPaint = new SkPaint(); |
|
369 #if SK_USE_CONDENSED_INFO == 0 |
|
370 GenerateTables(); |
|
371 #else |
|
372 SkASSERT(0); // !!! compressed version hasn't been implemented |
|
373 #endif |
|
374 AddInit(cx, obj, proto); |
|
375 AddCircleInit(cx, obj, proto); |
|
376 AddOvalInit(cx, obj, proto); |
|
377 AddPathInit(cx, obj, proto); |
|
378 AddRectangleInit(cx, obj, proto); |
|
379 AddRoundRectInit(cx, obj, proto); |
|
380 // AfterInit(cx, obj, proto); |
|
381 ApplyInit(cx, obj, proto); |
|
382 // AnimateInit(cx, obj, proto); |
|
383 // AnimateColorInit(cx, obj, proto); |
|
384 AnimateFieldInit(cx, obj, proto); |
|
385 // AnimateRotateInit(cx, obj, proto); |
|
386 // AnimateScaleInit(cx, obj, proto); |
|
387 // AnimateTranslateInit(cx, obj, proto); |
|
388 BitmapInit(cx, obj, proto); |
|
389 // BaseBitmapInit(cx, obj, proto); |
|
390 // BeforeInit(cx, obj, proto); |
|
391 BitmapShaderInit(cx, obj, proto); |
|
392 BlurInit(cx, obj, proto); |
|
393 ClipInit(cx, obj, proto); |
|
394 ColorInit(cx, obj, proto); |
|
395 CubicToInit(cx, obj, proto); |
|
396 DashInit(cx, obj, proto); |
|
397 DataInit(cx, obj, proto); |
|
398 // DimensionsInit(cx, obj, proto); |
|
399 DiscreteInit(cx, obj, proto); |
|
400 DrawToInit(cx, obj, proto); |
|
401 EmbossInit(cx, obj, proto); |
|
402 EventInit(cx, obj, proto); |
|
403 // FontInit(cx, obj, proto); |
|
404 // FocusInit(cx, obj, proto); |
|
405 ImageInit(cx, obj, proto); |
|
406 IncludeInit(cx, obj, proto); |
|
407 // InputInit(cx, obj, proto); |
|
408 LineInit(cx, obj, proto); |
|
409 LinearGradientInit(cx, obj, proto); |
|
410 LineToInit(cx, obj, proto); |
|
411 MatrixInit(cx, obj, proto); |
|
412 MoveInit(cx, obj, proto); |
|
413 MoveToInit(cx, obj, proto); |
|
414 OvalInit(cx, obj, proto); |
|
415 PathInit(cx, obj, proto); |
|
416 PaintInit(cx, obj, proto); |
|
417 DrawPointInit(cx, obj, proto); |
|
418 PolyToPolyInit(cx, obj, proto); |
|
419 PolygonInit(cx, obj, proto); |
|
420 PolylineInit(cx, obj, proto); |
|
421 PostInit(cx, obj, proto); |
|
422 QuadToInit(cx, obj, proto); |
|
423 RadialGradientInit(cx, obj, proto); |
|
424 RandomInit(cx, obj, proto); |
|
425 RectToRectInit(cx, obj, proto); |
|
426 RectangleInit(cx, obj, proto); |
|
427 RemoveInit(cx, obj, proto); |
|
428 ReplaceInit(cx, obj, proto); |
|
429 RotateInit(cx, obj, proto); |
|
430 RoundRectInit(cx, obj, proto); |
|
431 ScaleInit(cx, obj, proto); |
|
432 SetInit(cx, obj, proto); |
|
433 SkewInit(cx, obj, proto); |
|
434 // 3D_CameraInit(cx, obj, proto); |
|
435 // 3D_PatchInit(cx, obj, proto); |
|
436 SnapshotInit(cx, obj, proto); |
|
437 // StrokeInit(cx, obj, proto); |
|
438 TextInit(cx, obj, proto); |
|
439 TextOnPathInit(cx, obj, proto); |
|
440 TextToPathInit(cx, obj, proto); |
|
441 TranslateInit(cx, obj, proto); |
|
442 // UseInit(cx, obj, proto); |
|
443 } |
|
444 |
|
445 void SkJS::DisposeDisplayables() { |
|
446 delete SkJSDisplayable::gPaint; |
|
447 delete SkJSDisplayable::gCanvas; |
|
448 for (int index = 0; index < kTypeNamesSize; index++) { |
|
449 SkDisplayTypes type = gTypeNames[index].fType; |
|
450 delete[] gDisplayableProperties[type]; |
|
451 } |
|
452 } |