📄 swfdec_js_movie.c
字号:
/* Swfdec * Copyright (C) 2003-2006 David Schleef <ds@schleef.org> * 2005-2006 Eric Anholt <eric@anholt.net> * 2006-2007 Benjamin Otte <otte@gnome.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <string.h>#include <math.h>#include <js/jsapi.h>#include <js/jsinterp.h> /* for JS_IntetrnalCall */#include "swfdec_js.h"#include "swfdec_movie.h"#include "swfdec_bits.h"#include "swfdec_debug.h"#include "swfdec_decoder.h"#include "swfdec_player_internal.h"#include "swfdec_root_movie.h"#include "swfdec_sprite.h"#include "swfdec_sprite_movie.h"#include "swfdec_swf_decoder.h"JSBool swfdec_js_global_eval (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);const JSClass movieclip_class = { "MovieClip", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, swfdec_scriptable_finalize, JSCLASS_NO_OPTIONAL_MEMBERS};static voidswfdec_js_movie_add_property (SwfdecMovie *movie){ SwfdecScriptable *script = SWFDEC_SCRIPTABLE (movie); jsval val; JSObject *jsobj; JSContext *cx; JSBool found = JS_FALSE; if (!movie->has_name) return; jsobj = swfdec_scriptable_get_object (script); val = OBJECT_TO_JSVAL (jsobj); cx = script->jscx; if (movie->parent) { jsobj = SWFDEC_SCRIPTABLE (movie->parent)->jsobj; if (jsobj == NULL) return; SWFDEC_LOG ("setting %s as property for %s", movie->name, movie->parent->name); } else { jsobj = SWFDEC_ROOT_MOVIE (movie)->player->jsobj; SWFDEC_LOG ("setting %s as property for _global", movie->name); } if (!JS_SetProperty (cx, jsobj, movie->name, &val) || !JS_SetPropertyAttributes (cx, jsobj, movie->name, JSPROP_READONLY | JSPROP_PERMANENT, &found) || found != JS_TRUE) { SWFDEC_ERROR ("could not set property %s correctly", movie->name); }}static voidswfdec_js_movie_remove_property (SwfdecMovie *movie){ SwfdecScriptable *script = SWFDEC_SCRIPTABLE (movie); JSObject *jsobj; JSContext *cx; JSBool found = JS_FALSE; jsval deleted = JSVAL_FALSE; if (!movie->has_name || script->jsobj == NULL) return; cx = script->jscx; if (movie->parent) { jsobj = SWFDEC_SCRIPTABLE (movie->parent)->jsobj; if (jsobj == NULL) return; } else { jsobj = SWFDEC_ROOT_MOVIE (movie)->player->jsobj; } SWFDEC_LOG ("removing %s as property", movie->name); if (!JS_SetPropertyAttributes (cx, jsobj, movie->name, 0, &found) || found != JS_TRUE || !JS_DeleteProperty2 (cx, jsobj, movie->name, &deleted) || deleted == JSVAL_FALSE) { SWFDEC_ERROR ("could not remove property %s correctly", movie->name); }}static JSBoolmc_play (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ SwfdecMovie *movie; movie = swfdec_scriptable_from_object (cx, obj, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("not a movie"); return JS_TRUE; } g_assert (movie); movie->stopped = FALSE; return JS_TRUE;}static JSBoolmc_stop (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ SwfdecMovie *movie; movie = swfdec_scriptable_from_object (cx, obj, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("not a movie"); return JS_TRUE; } movie->stopped = TRUE; return JS_TRUE;}static JSBoolmc_getBytesLoaded (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ SwfdecMovie *movie; SwfdecDecoder *dec; movie = swfdec_scriptable_from_object (cx, obj, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("not a movie"); return JS_TRUE; } dec = SWFDEC_ROOT_MOVIE (movie->root)->decoder; *rval = INT_TO_JSVAL(MIN (dec->bytes_loaded, dec->bytes_total)); return JS_TRUE;}static JSBoolmc_getBytesTotal (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ SwfdecMovie *movie; SwfdecDecoder *dec; movie = swfdec_scriptable_from_object (cx, obj, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("not a movie"); return JS_TRUE; } dec = SWFDEC_ROOT_MOVIE (movie->root)->decoder; *rval = INT_TO_JSVAL (dec->bytes_total); return JS_TRUE;}static JSBoolmc_getNextHighestDepth (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ SwfdecMovie *movie; int depth; movie = swfdec_scriptable_from_object (cx, obj, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("not a movie"); return JS_TRUE; } if (movie->list) { depth = SWFDEC_MOVIE (g_list_last (movie->list)->data)->depth + 1; if (depth < 0) depth = 0; } else { depth = 0; } return JS_NewNumberValue (cx, depth, rval);}static JSBoolmc_do_goto (JSContext *cx, SwfdecMovie *movie, jsval target){ int32 frame; if (JSVAL_IS_STRING (target)) { const char *label = swfdec_js_to_string (cx, target); frame = swfdec_sprite_get_frame (SWFDEC_SPRITE_MOVIE (movie)->sprite, label); /* FIXME: nonexisting frames? */ if (frame == -1) return JS_TRUE; frame++; } else if (!JS_ValueToInt32 (cx, target, &frame)) { return JS_FALSE; } /* FIXME: how to handle overflow? */ frame = CLAMP (frame, 1, (int) movie->n_frames) - 1; swfdec_movie_goto (movie, frame); return JS_TRUE;}static JSBoolmc_gotoAndPlay (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ SwfdecMovie *movie; movie = swfdec_scriptable_from_object (cx, obj, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("not a movie"); return JS_TRUE; } if (!mc_do_goto (cx, movie, argv[0])) return JS_FALSE; movie->stopped = FALSE; return JS_TRUE;}static JSBoolmc_gotoAndStop (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ SwfdecMovie *movie; movie = swfdec_scriptable_from_object (cx, obj, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("not a movie"); return JS_TRUE; } if (!mc_do_goto (cx, movie, argv[0])) return JS_FALSE; movie->stopped = TRUE; return JS_TRUE;}static JSBoolswfdec_js_nextFrame (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ SwfdecMovie *movie; jsval frame; movie = swfdec_scriptable_from_object (cx, obj, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("not a movie"); return JS_TRUE; } frame = INT_TO_JSVAL (movie->frame + 2); /* 1-indexed */ if (!mc_do_goto (cx, movie, frame)) return JS_FALSE; movie->stopped = TRUE; return JS_TRUE;}static JSBoolswfdec_js_prevFrame (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ SwfdecMovie *movie; jsval frame; movie = swfdec_scriptable_from_object (cx, obj, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("not a movie"); return JS_TRUE; } if (movie->frame == 0) frame = INT_TO_JSVAL (movie->n_frames); else frame = INT_TO_JSVAL (movie->frame); /* 1-indexed */ if (!mc_do_goto (cx, movie, frame)) return JS_FALSE; movie->stopped = TRUE; return JS_TRUE;}static JSBoolmc_hitTest (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ SwfdecMovie *movie; movie = swfdec_scriptable_from_object (cx, obj, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("not a movie"); return JS_TRUE; } if (argc == 1) { SwfdecMovie *other; other = swfdec_scriptable_from_jsval (cx, argv[0], SWFDEC_TYPE_MOVIE); if (other == NULL) { SWFDEC_ERROR ("FIXME: what happens now?"); return JS_TRUE; } other = SWFDEC_MOVIE (JS_GetPrivate(cx, JSVAL_TO_OBJECT (argv[0]))); swfdec_movie_update (movie); swfdec_movie_update (other); /* FIXME */ g_assert (movie->parent == other->parent);#if 0 g_print ("%g %g %g %g --- %g %g %g %g\n", SWFDEC_OBJECT (movie)->extents.x0, SWFDEC_OBJECT (movie)->extents.y0, SWFDEC_OBJECT (movie)->extents.x1, SWFDEC_OBJECT (movie)->extents.y1, SWFDEC_OBJECT (other)->extents.x0, SWFDEC_OBJECT (other)->extents.y0, SWFDEC_OBJECT (other)->extents.x1, SWFDEC_OBJECT (other)->extents.y1);#endif if (swfdec_rect_intersect (NULL, &movie->extents, &other->extents)) { *rval = BOOLEAN_TO_JSVAL (JS_TRUE); } else { *rval = BOOLEAN_TO_JSVAL (JS_FALSE); } } else if (argc == 3) { g_assert_not_reached (); } else { return JS_FALSE; } return JS_TRUE;}static JSPropertySpec movieclip_props[];static JSBoolswfdec_js_getProperty (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ uint32 id; SwfdecMovie *movie; JSObject *jsobj; jsval tmp; swfdec_js_global_eval (cx, obj, 1, argv, &tmp); movie = swfdec_scriptable_from_jsval (cx, tmp, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("specified target does not reference a movie clip"); return JS_TRUE; } if (!JS_ValueToECMAUint32 (cx, argv[1], &id)) return JS_FALSE; if (id > 19) return JS_FALSE; if (!(jsobj = swfdec_scriptable_get_object (SWFDEC_SCRIPTABLE (movie)))) return JS_FALSE; return movieclip_props[id].getter (cx, jsobj, INT_TO_JSVAL (id) /* FIXME */, rval);}static JSBoolswfdec_js_setProperty (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ uint32 id; SwfdecMovie *movie; jsval tmp; JSObject *jsobj; swfdec_js_global_eval (cx, obj, 1, argv, &tmp); movie = swfdec_scriptable_from_jsval (cx, tmp, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("specified target does not reference a movie clip"); return JS_TRUE; } if (!JS_ValueToECMAUint32 (cx, argv[1], &id)) return JS_FALSE; if (id > 19) return JS_FALSE; if (!(jsobj = swfdec_scriptable_get_object (SWFDEC_SCRIPTABLE (movie)))) return JS_FALSE; *rval = argv[2]; return movieclip_props[id].setter (cx, jsobj, INT_TO_JSVAL (id) /* FIXME */, rval);}static JSBoolswfdec_js_startDrag (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ SwfdecMovie *movie; JSBool center = JS_FALSE; SwfdecRect rect; movie = swfdec_scriptable_from_object (cx, obj, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("not a movie"); return JS_TRUE; } if (argc > 0) { if (!JS_ValueToBoolean (cx, argv[0], ¢er)) return JS_FALSE; } if (argc >= 5) { if (!JS_ValueToNumber (cx, argv[1], &rect.x0) || !JS_ValueToNumber (cx, argv[2], &rect.y0) || !JS_ValueToNumber (cx, argv[3], &rect.x1) || !JS_ValueToNumber (cx, argv[4], &rect.y1)) return JS_FALSE; swfdec_rect_scale (&rect, &rect, SWFDEC_TWIPS_SCALE_FACTOR); swfdec_player_set_drag_movie (SWFDEC_ROOT_MOVIE (movie->root)->player, movie, center, &rect); } else { swfdec_player_set_drag_movie (SWFDEC_ROOT_MOVIE (movie->root)->player, movie, center, NULL); } return JS_TRUE;}static JSBoolswfdec_js_stopDrag (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ SwfdecMovie *movie; SwfdecPlayer *player; movie = swfdec_scriptable_from_object (cx, obj, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("not a movie"); return JS_TRUE; } player = SWFDEC_ROOT_MOVIE (movie->root)->player; swfdec_player_set_drag_movie (player, NULL, FALSE, NULL); return JS_TRUE;}static JSBoolswfdec_js_movie_swapDepths (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ SwfdecMovie *movie; SwfdecMovie *other; int depth; movie = swfdec_scriptable_from_object (cx, obj, SWFDEC_TYPE_MOVIE); if (movie == NULL) { SWFDEC_WARNING ("not a movie"); return JS_TRUE; } if (JSVAL_IS_OBJECT (argv[0])) { other = swfdec_scriptable_from_jsval (cx, argv[0], SWFDEC_TYPE_MOVIE); if (other == NULL) return JS_TRUE; if (other->parent != movie->parent) return JS_TRUE; swfdec_movie_invalidate (other); depth = other->depth; other->depth = movie->depth; } else { if (!JS_ValueToECMAInt32 (cx, argv[0], &depth)) return JS_FALSE; other = swfdec_movie_find (movie->parent, depth); if (other) { swfdec_movie_invalidate (other); other->depth = movie->depth; } } swfdec_movie_invalidate (movie); movie->depth = depth; movie->parent->list = g_list_sort (movie->parent->list, swfdec_movie_compare_depths); return JS_TRUE;}static voidswfdec_js_copy_props (SwfdecMovie *target, SwfdecMovie *src){ target->matrix = src->matrix; target->color_transform = src->color_transform; swfdec_movie_queue_update (target, SWFDEC_MOVIE_INVALID_MATRIX);}static voidswfdec_js_movie_init_from_object (SwfdecMovie *movie, JSObject *obj){ SwfdecPlayer *player; player = SWFDEC_ROOT_MOVIE (movie->root)->player; g_queue_remove (player->init_queue, movie);}static JSBool
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -