[Swfdec] 109 commits - configure.ac libswfdec/js
libswfdec/Makefile.am libswfdec/swfdec_bits.c
libswfdec/swfdec_bits.h libswfdec/swfdec_buffer.c
libswfdec/swfdec_button_movie.c
libswfdec/swfdec_codec_screen.c libswfdec/swfdec_color.c
libswfdec/swfdec_color.h libswfdec/swfdec_compiler.c
libswfdec/swfdec_compiler.h libswfdec/swfdec_debugger.c
libswfdec/swfdec_debugger.h libswfdec/swfdec_event.c
libswfdec/swfdec_event.h libswfdec/swfdec_image.c
libswfdec/swfdec_js.c libswfdec/swfdec_js_color.c
libswfdec/swfdec_js_global.c libswfdec/swfdec_js.h
libswfdec/swfdec_js_movie.c libswfdec/swfdec_js_sound.c
libswfdec/swfdec_movie.c libswfdec/swfdec_movie.h
libswfdec/swfdec_player.c libswfdec/swfdec_player_internal.h
libswfdec/swfdec_root_movie.c libswfdec/swfdec_scriptable.c
libswfdec/swfdec_script.c libswfdec/swfdec_script.h
libswfdec/swfdec_sound.c libswfdec/swfdec_sound.h
libswfdec/swfdec_sprite.c libswfdec/swfdec_sprite_movie.c
libswfdec/swfdec_swf_decoder.c libswfdec/swfdec_tag.c
libswfdec/swfdec_text.c libswfdec/swfdec_types.h
player/swfdebug.c player/swfdec_debug_scripts.c
player/swfdec_debug_stack.c player/swfdec_player_manager.c
test/dump.c test/Makefile.am test/swfdec-extract.c
test/swfdec_out.c test/swfdec_out.h test/swfedit.c
test/swfedit_file.c test/swfedit_file.h test/swfedit_tag.c
test/swfedit_tag.h test/swfedit_token.c test/swfedit_token.h
test/trace
Benjamin Otte
company at kemper.freedesktop.org
Tue Feb 6 05:59:20 PST 2007
configure.ac | 2
libswfdec/Makefile.am | 4
libswfdec/js/jsfun.c | 11
libswfdec/js/jsfun.h | 1
libswfdec/js/jsgc.c | 29
libswfdec/js/jsinterp.c | 14
libswfdec/js/jsinterp.h | 4
libswfdec/js/jsnum.c | 10
libswfdec/js/jsobj.c | 2
libswfdec/swfdec_bits.c | 61
libswfdec/swfdec_bits.h | 13
libswfdec/swfdec_buffer.c | 7
libswfdec/swfdec_button_movie.c | 3
libswfdec/swfdec_codec_screen.c | 2
libswfdec/swfdec_color.c | 4
libswfdec/swfdec_color.h | 2
libswfdec/swfdec_compiler.c | 1521 -----------------------
libswfdec/swfdec_compiler.h | 22
libswfdec/swfdec_debugger.c | 116 +
libswfdec/swfdec_debugger.h | 16
libswfdec/swfdec_event.c | 14
libswfdec/swfdec_event.h | 2
libswfdec/swfdec_image.c | 165 +-
libswfdec/swfdec_js.c | 154 +-
libswfdec/swfdec_js.h | 4
libswfdec/swfdec_js_color.c | 39
libswfdec/swfdec_js_global.c | 3
libswfdec/swfdec_js_movie.c | 29
libswfdec/swfdec_js_sound.c | 7
libswfdec/swfdec_movie.c | 26
libswfdec/swfdec_movie.h | 1
libswfdec/swfdec_player.c | 10
libswfdec/swfdec_player_internal.h | 2
libswfdec/swfdec_root_movie.c | 8
libswfdec/swfdec_script.c | 2374 +++++++++++++++++++++++++++++++++++++
libswfdec/swfdec_script.h | 71 +
libswfdec/swfdec_scriptable.c | 2
libswfdec/swfdec_sound.c | 13
libswfdec/swfdec_sound.h | 2
libswfdec/swfdec_sprite.c | 4
libswfdec/swfdec_sprite_movie.c | 4
libswfdec/swfdec_swf_decoder.c | 48
libswfdec/swfdec_tag.c | 29
libswfdec/swfdec_text.c | 3
libswfdec/swfdec_types.h | 1
player/swfdebug.c | 4
player/swfdec_debug_scripts.c | 2
player/swfdec_debug_stack.c | 33
player/swfdec_player_manager.c | 8
test/Makefile.am | 21
test/dump.c | 34
test/swfdec-extract.c | 2
test/swfdec_out.c | 258 ++++
test/swfdec_out.h | 78 +
test/swfedit.c | 131 ++
test/swfedit_file.c | 287 ++++
test/swfedit_file.h | 59
test/swfedit_tag.c | 253 +++
test/swfedit_tag.h | 66 +
test/swfedit_token.c | 573 ++++++++
test/swfedit_token.h | 90 +
test/trace/.gitignore | 1
test/trace/Makefile.am | 14
test/trace/color-new.swf |binary
test/trace/color-new.swf.trace | 10
test/trace/function1.swf |binary
test/trace/function1.swf.trace | 50
test/trace/function2.swf |binary
test/trace/function2.swf.trace | 2
test/trace/number.swf |binary
test/trace/number.swf.trace | 9
test/trace/object-math-5.swf |binary
test/trace/object-math-5.swf.trace | 17
test/trace/object-math-6.swf |binary
test/trace/object-math-6.swf.trace | 17
test/trace/object-math-7.swf |binary
test/trace/object-math-7.swf.trace | 17
77 files changed, 4969 insertions(+), 1926 deletions(-)
New commits:
diff-tree ee3339e4cb9af7e52a6ecb381206f1ea5adb07c0 (from 24e1974f101eb00c1d7017dc3b90ba7009c7808f)
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Feb 6 14:59:28 2007 +0100
s/unsigned int/SwfdecColor/ for colors
diff --git a/libswfdec/swfdec_color.c b/libswfdec/swfdec_color.c
index ee3a63f..c4fa52e 100644
--- a/libswfdec/swfdec_color.c
+++ b/libswfdec/swfdec_color.c
@@ -82,8 +82,8 @@ swfdec_color_apply_transform_premultipli
return SWFDEC_COLOR_COMBINE (r, g, b, a);
}
-unsigned int
-swfdec_color_apply_transform (unsigned int in, const SwfdecColorTransform * trans)
+SwfdecColor
+swfdec_color_apply_transform (SwfdecColor in, const SwfdecColorTransform * trans)
{
int r, g, b, a;
diff --git a/libswfdec/swfdec_color.h b/libswfdec/swfdec_color.h
index 54ce268..a7a7723 100644
--- a/libswfdec/swfdec_color.h
+++ b/libswfdec/swfdec_color.h
@@ -75,7 +75,7 @@ void swfdec_color_transform_init_color (
gboolean swfdec_color_transform_is_identity (const SwfdecColorTransform * trans);
void swfdec_color_transform_chain (SwfdecColorTransform *dest,
const SwfdecColorTransform *last, const SwfdecColorTransform *first);
-unsigned int swfdec_color_apply_transform (unsigned int in,
+SwfdecColor swfdec_color_apply_transform (SwfdecColor in,
const SwfdecColorTransform * trans);
SwfdecColor swfdec_color_apply_transform_premultiplied (SwfdecColor in,
const SwfdecColorTransform * trans);
diff --git a/libswfdec/swfdec_text.c b/libswfdec/swfdec_text.c
index 4d3ad03..d7ca655 100644
--- a/libswfdec/swfdec_text.c
+++ b/libswfdec/swfdec_text.c
@@ -58,7 +58,8 @@ static void
swfdec_text_render (SwfdecGraphic *graphic, cairo_t *cr,
const SwfdecColorTransform *trans, const SwfdecRect *inval, gboolean fill)
{
- unsigned int i, color;
+ unsigned int i;
+ SwfdecColor color;
SwfdecText *text = SWFDEC_TEXT (graphic);
SwfdecColorTransform force_color;
SwfdecRect rect, inval_moved;
diff-tree 24e1974f101eb00c1d7017dc3b90ba7009c7808f (from 7224f1a88cc0de6a42f05f44a5c96a366a8b775b)
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Feb 6 14:53:54 2007 +0100
fix code assuming sound->n_samples is in decoded format instead of 44100kHz
diff --git a/libswfdec/swfdec_sound.c b/libswfdec/swfdec_sound.c
index 1620f5d..7f302c1 100644
--- a/libswfdec/swfdec_sound.c
+++ b/libswfdec/swfdec_sound.c
@@ -235,17 +235,22 @@ swfdec_sound_get_decoded (SwfdecSound *s
tmp = tmp2;
}
/* sound buffer may be bigger due to mp3 not having sample boundaries */
- if (tmp->length > sound->n_samples * sample_bytes) {
- SwfdecBuffer *tmp2 = swfdec_buffer_new_subbuffer (tmp, 0, sound->n_samples * sample_bytes);
+ if (tmp->length * SWFDEC_AUDIO_OUT_GRANULARITY (sound->decoded_format)
+ > sound->n_samples * sample_bytes) {
+ SwfdecBuffer *tmp2 = swfdec_buffer_new_subbuffer (tmp, 0,
+ sound->n_samples * sample_bytes / SWFDEC_AUDIO_OUT_GRANULARITY (sound->decoded_format));
swfdec_buffer_unref (tmp);
tmp = tmp2;
}
- if (tmp->length < sound->n_samples * sample_bytes) {
+ if (tmp->length * SWFDEC_AUDIO_OUT_GRANULARITY (sound->decoded_format)
+ < sound->n_samples * sample_bytes) {
/* we handle this case in swfdec_sound_render */
/* FIXME: this message is important when writing new codecs, so I made it a warning.
* It's probably not worth more than INFO for the usual case though */
SWFDEC_WARNING ("%u samples in %u bytes should be available, but only %u bytes are",
- sound->n_samples, sound->n_samples * sample_bytes, tmp->length);
+ sound->n_samples / SWFDEC_AUDIO_OUT_GRANULARITY (sound->decoded_format),
+ sound->n_samples * sample_bytes / SWFDEC_AUDIO_OUT_GRANULARITY (sound->decoded_format),
+ tmp->length);
}
/* only assign here, the decoding code checks this variable */
sound->decoded = tmp;
diff --git a/libswfdec/swfdec_sound.h b/libswfdec/swfdec_sound.h
index 7bf26ec..ce837db 100644
--- a/libswfdec/swfdec_sound.h
+++ b/libswfdec/swfdec_sound.h
@@ -66,7 +66,7 @@ struct _SwfdecSound
SwfdecAudioFormat format; /* format in use */
gboolean width; /* TRUE for 16bit, FALSE for 8bit */
SwfdecAudioOut original_format; /* channel/rate information */
- unsigned int n_samples; /* total number of samples */
+ unsigned int n_samples; /* total number of samples when decoded to 44100kHz */
unsigned int skip; /* samples to skip at start */
SwfdecBuffer * encoded; /* encoded data */
diff-tree 7224f1a88cc0de6a42f05f44a5c96a366a8b775b (from ffeec3ded24753fe7b291e6054146d641425233c)
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Feb 6 14:39:21 2007 +0100
add the temporary tmp file
diff --git a/test/trace/.gitignore b/test/trace/.gitignore
index 25a10a8..8840a6f 100644
--- a/test/trace/.gitignore
+++ b/test/trace/.gitignore
@@ -8,4 +8,5 @@ Makefile
Makefile.in
*.o
+tmp
trace
diff-tree ffeec3ded24753fe7b291e6054146d641425233c (from 375b6d4dc5d4335c3fcafa0ce96076287ae2b9ac)
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Feb 6 12:43:55 2007 +0100
delete the old compiler source files
diff --git a/libswfdec/swfdec_compiler.c b/libswfdec/swfdec_compiler.c
deleted file mode 100644
index 9947f19..0000000
--- a/libswfdec/swfdec_compiler.c
+++ /dev/null
@@ -1,1504 +0,0 @@
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <js/jsapi.h>
-#include <js/jsarena.h>
-#include <js/jsatom.h>
-#include <js/jsemit.h>
-#include <js/jsscript.h>
-#include <js/jsopcode.h>
-
-#include "swfdec_bits.h"
-#include "swfdec_compiler.h"
-#include "swfdec_debug.h"
-#include "swfdec_debugger.h"
-#include "swfdec_player_internal.h"
-#include "swfdec_sprite.h"
-
-/*** NOTE TO HACKERS ***
-
- This file is supposed to contain a compiler that compiles ActionScript code
- as found in an swf file to Javascript bytecode ready to be interpreted by
- the Spidermonkey engine.
- The problem here is that I have not much of a clue on how to do such a thing
- right, the SpiderMonkey docs are very nice for users but unfortunately not for
- people mocking with bytecode. I guess the contents of this file reflects that.
- So if you can do better, this file has just one public function:
- swfdec_compile (). Feel free to reimplement it in a better way.
-
- *** END NOTE TO HACKERS ***/
-
-/*** COMPILE STATE ***/
-
-typedef struct {
- guint bytecode; /* offset into bytecode where jump address goes */
- gboolean extended; /* if this is an extended jump */
- gboolean use_bytes; /* if TRUE, the offset is in bytes, otherwise it's in actions */
- guint offset; /* action to jump to */
-} Jump;
-
-typedef struct {
- guint original; /* amount of bytes we've advanced in the input */
- guint compiled; /* amount of bytes we've advancecd in the bytecode */
-} Offset;
-
-typedef struct {
- JSContext * cx; /* JSContext from player */
- JSAtomList atoms; /* accumulated atoms */
-
- SwfdecBits * bits; /* where to read the code from */
- int version; /* Flash version we're compiling for */
- GByteArray * bytecode; /* generated bytecode so far */
- char * error; /* error encountered while compiling */
- GArray * offsets; /* offsets of actions */
- GArray * jumps; /* accumulated jumps */
- GArray * trynotes; /* try/catch blocks */
- GPtrArray * pool; /* ConstantPool data */
- GArray * commands; /* debug informations */
- guint command_last; /* offset to last command */
-} CompileState;
-
-/*** DEBUGGING STUFF ***/
-
-/* NB: this must be called _before_ adding bytecode */
-static void
-compile_state_debug_add (CompileState *state, const char *format, ...) G_GNUC_PRINTF (2, 3);
-static void
-compile_state_debug_add (CompileState *state, const char *format, ...)
-{
- va_list args;
- SwfdecDebuggerCommand command = { NULL, };
-
- command.code = NULL + state->bytecode->len;
- command.breakpoint = 0;
- va_start (args, format);
- command.description = g_strdup_vprintf (format, args);
- SWFDEC_DEBUG ("%s", command.description);
- va_end (args);
- state->command_last = G_MAXUINT;
- g_array_append_val (state->commands, command);
-}
-
-static void
-compile_state_debug_add_default (CompileState *state, guint action, const char *name)
-{
- SwfdecDebuggerCommand command = { NULL, };
-
- if (state->command_last == G_MAXUINT)
- return;
- if (action & 0x80) {
- SWFDEC_WARNING ("FIXME: action %s does not provide debugger statements", name);
- }
- command.code = GUINT_TO_POINTER (state->command_last);
- command.description = g_strdup (name);
- state->command_last = G_MAXUINT;
- g_array_append_val (state->commands, command);
- SWFDEC_DEBUG ("%s", command.description);
-}
-
-static void
-compile_state_debug_finish (CompileState *state, SwfdecPlayer *player, JSScript *script, const char *name)
-{
- SwfdecDebuggerCommand *command;
- guint i;
-
- if (SWFDEC_IS_DEBUGGER (player)) {
- for (i = 0; i < state->commands->len; i++) {
- command = &g_array_index (state->commands, SwfdecDebuggerCommand, i);
- command->code = script->code + GPOINTER_TO_UINT (command->code);
- }
- swfdec_debugger_add_script (SWFDEC_DEBUGGER (player), script, name,
- (SwfdecDebuggerCommand *) state->commands->data, state->commands->len);
- g_array_free (state->commands, FALSE);
- } else {
- g_array_free (state->commands, TRUE);
- }
-}
-
-/*** GENERAL FUNCTIONS ***/
-
-static void
-compile_state_error (CompileState *state, char *format, ...) G_GNUC_PRINTF (2, 3);
-static void
-compile_state_error (CompileState *state, char *format, ...)
-{
- va_list args;
-
- g_assert (state->error == NULL);
-
- va_start (args, format);
- state->error = g_strdup_vprintf (format, args);
- va_end (args);
-}
-
-/*** ACTION COMPILATION FUNCTIONS ***/
-
-static void
-compile_state_push_offset (CompileState *state, guint command_len)
-{
- Offset offset = { command_len, state->bytecode->len };
- if (state->offsets->len > 0)
- offset.original += g_array_index (state->offsets, Offset, state->offsets->len - 1).original;
- g_array_append_val (state->offsets, offset);
-}
-
-static jsatomid
-atomize_string (CompileState *state, const char *name)
-{
- JSAtom *atom;
- JSAtomListElement *ale;
-
- atom = js_Atomize (state->cx, name, strlen (name), 0);
- ale = js_IndexAtom (state->cx, atom, &state->atoms);
- if (ale == NULL) {
- compile_state_error (state, "Failed to add name %s", name);
- return 0;
- }
- return ALE_INDEX (ale);
-}
-
-static jsatomid
-atomize_double (CompileState *state, jsdouble d)
-{
- JSAtom *atom;
- JSAtomListElement *ale;
-
- atom = js_AtomizeDouble (state->cx, d, 0);
- ale = js_IndexAtom (state->cx, atom, &state->atoms);
- if (ale == NULL) {
- compile_state_error (state, "Failed to add double %g", d);
- return 0;
- }
- return ALE_INDEX (ale);
-}
-
-static jsatomid
-atomize_int32 (CompileState *state, int i)
-{
- JSAtom *atom;
- JSAtomListElement *ale;
-
- g_assert (i >= G_MININT32 && i <= G_MAXINT32);
- atom = js_AtomizeInt (state->cx, i, 0);
- ale = js_IndexAtom (state->cx, atom, &state->atoms);
- if (ale == NULL) {
- compile_state_error (state, "Failed to add int %d", i);
- return 0;
- }
- return ALE_INDEX (ale);
-}
-
-#define ONELINER(state, opcode) G_STMT_START { \
- guint8 command = opcode; \
- compile_state_add_code (state, &command, 1); \
-} G_STMT_END
-#define THREELINER(state, opcode, id1, id2) G_STMT_START { \
- guint8 command[3] = { opcode, id1, id2 }; \
- compile_state_add_code (state, command, 3); \
-} G_STMT_END
-#define THREELINER_INT(state, opcode, _int) THREELINER (state, opcode, (_int) >> 8, (_int))
-#define THREELINER_ATOM(state, opcode, str) G_STMT_START { \
- jsatomid id; \
- id = atomize_string (state, str); \
- THREELINER_INT (state, opcode, id); \
-} G_STMT_END
-
-#define PUSH_OBJ(state) ONELINER (state, JSOP_PUSHOBJ)
-#define POP(state) ONELINER (state, JSOP_POP)
-#define GE(state) ONELINER (state, JSOP_GE)
-#define THIS(state) ONELINER (state, JSOP_THIS)
-#define SWAP(state) ONELINER (state, JSOP_SWAP)
-#define DUP(state) ONELINER (state, JSOP_DUP)
-#define FLASHCALL(state) ONELINER (state, JSOP_FLASHCALL)
-#define FLASHSWAP(state, n) THREELINER_INT (state, JSOP_FLASHSWAP, n)
-
-#define DO_JUMP(state, opcode, offset) G_STMT_START {\
- guint8 command[3] = { opcode, 0, 0 }; \
- compile_state_add_bytes_jump (state, offset, FALSE); \
- compile_state_add_code (state, command, 3); \
-} G_STMT_END
-#define IFEQ(state, offset) DO_JUMP (state, JSOP_IFEQ, offset)
-#define IFNE(state, offset) DO_JUMP (state, JSOP_IFNE, offset)
-
-static void
-compile_state_add_code (CompileState *state, const guint8 *code, guint len)
-{
- if (state->error)
- return;
- g_byte_array_append (state->bytecode, code, len);
-}
-
-static void
-bind_name (CompileState *state, const char *name)
-{
- THREELINER_ATOM (state, JSOP_BINDNAME, name);
-}
-
-#define TARGET_NAME "__swfdec_target"
-static void
-compile_state_set_target (CompileState *state)
-{
- guint8 command[3] = { JSOP_BINDNAME, 0, 0 };
- compile_state_add_code (state, command, 3);
- SWAP (state);
- command[0] = JSOP_SETNAME;
- compile_state_add_code (state, command, 3);
- POP (state);
-}
-static void
-compile_state_add_target (CompileState *state)
-{
- guint8 command[3] = { JSOP_DEFVAR, 0, 0 };
- /* add the TARGET variable */
- if (atomize_string (state, TARGET_NAME) != 0) {
- g_assert_not_reached ();
- }
- compile_state_add_code (state, command, 3);
- THIS (state);
- compile_state_set_target (state);
-}
-
-static void
-compile_state_init (JSContext *cx, SwfdecBits *bits, int version, CompileState *state)
-{
- state->cx = cx;
- state->bits = bits;
- state->version = version;
- ATOM_LIST_INIT (&state->atoms);
- state->bytecode = g_byte_array_new ();
- state->error = NULL;
- state->offsets = g_array_new (FALSE, FALSE, sizeof (Offset));
- state->jumps = g_array_new (FALSE, FALSE, sizeof (Jump));
- state->trynotes = g_array_new (TRUE, FALSE, sizeof (JSTryNote));
- state->pool = g_ptr_array_new ();
- state->commands = g_array_new (TRUE, FALSE, sizeof (SwfdecDebuggerCommand));
- state->command_last = G_MAXUINT;
-
- compile_state_add_target (state);
- compile_state_push_offset (state, 0);
-}
-
-static void
-compile_state_resolve_jumps (CompileState *state)
-{
- guint i, j;
- int offset;
- Jump *jump;
- guint8 *bytecode;
-
- for (i = 0; i < state->jumps->len; i++) {
- jump = &g_array_index (state->jumps, Jump, i);
- bytecode = state->bytecode->data + jump->bytecode + 1;
- if (jump->use_bytes) {
- for (j = 0; j < state->offsets->len; j++) {
- if (g_array_index (state->offsets, Offset, j).original == jump->offset) {
- offset = g_array_index (state->offsets, Offset, j).compiled;
- offset -= jump->bytecode;
- goto finished;
- }
- }
- compile_state_error (state, "Jumped into action");
- return;
- } else {
- offset = g_array_index (state->offsets, Offset,
- MIN (state->offsets->len - 1, jump->offset)).compiled;
- offset -= jump->bytecode;
- }
-finished:
- if (jump->extended) {
- gint32 *data = (gint32 *) bytecode;
- *data = GINT32_TO_BE (offset);
- } else {
- gint16 *data = (gint16 *) bytecode;
- if (offset > G_MAXINT32 || offset < G_MININT32) {
- compile_state_error (state, "jump from %u to %u is too big",
- jump->bytecode, MIN (state->offsets->len - 1, jump->offset));
- return;
- }
- *data = GINT16_TO_BE (offset);
- }
- }
-}
-
-#define OFFSET_MAIN 3
-static JSScript *
-compile_state_finish (CompileState *state, SwfdecPlayer *player, const char *name)
-{
- JSContext *cx = state->cx;
- JSScript *script = NULL;
-
- if (state->error == NULL)
- compile_state_resolve_jumps (state);
-
- if (state->error != NULL) {
- JSAtomMap clear;
- js_InitAtomMap (cx, &clear, &state->atoms);
- js_FreeAtomMap (cx, &clear);
- SWFDEC_ERROR ("%s", state->error);
- g_free (state->error);
- goto cleanup;
- }
-
- script = js_NewScript (cx, state->bytecode->len, 1, state->trynotes->len + 1);
- memcpy (script->code, state->bytecode->data, state->bytecode->len);
- memcpy (script->trynotes, state->trynotes->data, (state->trynotes->len + 1) * sizeof (JSTryNote));
- js_InitAtomMap (cx, &script->atomMap, &state->atoms);
- /* FIXME: figure out a correct value here */
- script->depth = 100;
- script->main = script->code + OFFSET_MAIN;
- SN_MAKE_TERMINATOR (SCRIPT_NOTES (script));
- compile_state_debug_finish (state, player, script, name);
-
-cleanup:
- g_ptr_array_free (state->pool, TRUE);
- g_array_free (state->offsets, TRUE);
- g_array_free (state->jumps, TRUE);
- g_array_free (state->trynotes, TRUE);
- g_byte_array_free (state->bytecode, TRUE);
- return script;
-}
-
-static void
-add_try_catch_block (CompileState *state, guint n_bytes, guint pc_offset)
-{
- ptrdiff_t last = 0;
- ptrdiff_t cur_offset;
- JSTryNote tn;
-
- g_assert (state->bytecode->len >= OFFSET_MAIN);
- cur_offset = state->bytecode->len - OFFSET_MAIN;
- if (state->trynotes->len > 0) {
- JSTryNote *tmp = &g_array_index (state->trynotes, JSTryNote, state->trynotes->len - 1);
- last = tmp->start + tmp->length;
- /* FIXME: allow nesting of try/catch blocks */
- g_assert (last <= cur_offset);
- }
- if (last < cur_offset) {
- /* add "no catching here" note */
- tn.start = last;
- tn.length = cur_offset - last;
- tn.catchStart = 0;
- g_array_append_val (state->trynotes, tn);
- }
- tn.start = cur_offset;
- tn.length = n_bytes;
- tn.catchStart = state->bytecode->len + pc_offset - OFFSET_MAIN;
- SWFDEC_LOG ("adding try/catch at %u (len %u) to offset %u",
- tn.start, tn.length, tn.catchStart);
- g_array_append_val (state->trynotes, tn);
-}
-
-/* NB: n_bytes is relative to the start of this action */
-static void
-compile_state_add_bytes_jump (CompileState *state, int n_bytes, gboolean extended)
-{
- Jump jump = { state->bytecode->len, extended, TRUE,
- n_bytes + g_array_index (state->offsets, Offset, state->offsets->len - 1).original };
-
- SWFDEC_LOG ("adding jump to byte %u", jump.offset);
- if (n_bytes < 0 &&
- (guint) -n_bytes > g_array_index (state->offsets, Offset, state->offsets->len - 1).original) {
- compile_state_error (state, "attempting to jump %d bytess backwards at byte %u",
- -n_bytes, g_array_index (state->offsets, Offset, state->offsets->len - 1).original);
- return;
- }
- g_array_append_val (state->jumps, jump);
-}
-
-/* must be called before adding the jump command to the bytecode */
-static void
-compile_state_add_action_jump (CompileState *state, int n_actions, gboolean extended)
-{
- Jump jump = { state->bytecode->len, extended, FALSE, state->offsets->len + n_actions };
-
- if (n_actions < 0 && state->offsets->len < (guint) -n_actions) {
- compile_state_error (state, "attempting to jump %d actions backwards in %u. action",
- -n_actions, state->offsets->len);
- return;
- }
- g_array_append_val (state->jumps, jump);
-}
-
-static void
-push_target (CompileState *state)
-{
- THREELINER (state, JSOP_NAME, 0, 0);
-}
-
-static void
-push_prop (CompileState *state, const char *name)
-{
- THREELINER_ATOM (state, JSOP_GETPROP, name);
-}
-
-static void
-name (CompileState *state, const char *name)
-{
- THREELINER_ATOM (state, JSOP_NAME, name);
-}
-
-#if 0
-static void
-push_prop_without_target (CompileState *state, const char *name)
-{
- jsatomid id;
- guint8 command[3];
-
- id = atomize_string (state, name);
- command[0] = JSOP_BINDNAME;
- command[1] = id >> 8;
- command[2] = id;
- compile_state_add_code (state, command, 3);
- command[0] = JSOP_GETPROP;
- compile_state_add_code (state, command, 3);
-}
-#endif
-
-static void
-push_uint16 (CompileState *state, unsigned int i)
-{
- g_assert (i <= G_MAXUINT16);
- SWFDEC_LOG ("pushing %u", i);
- THREELINER_INT (state, JSOP_UINT16, i);
-}
-
-static void
-call (CompileState *state, guint n_arguments)
-{
- THREELINER_INT (state, JSOP_CALL, n_arguments);
-}
-
-static void
-call_void_function (CompileState *state, const char *name)
-{
- push_prop (state, name);
- PUSH_OBJ (state);
- call (state, 0);
- POP (state);
-}
-
-/* 13 bytes */
-#define DEBUG_TRACE(state) G_STMT_START { \
- ONELINER (state, JSOP_DUP); \
- compile_trace (state, 0, 0); \
-}G_STMT_END
-
-static void
-compile_trace (CompileState *state, guint action, guint len)
-{
- push_uint16 (state, 1);
- bind_name (state, "trace");
- push_prop (state, "trace");
- PUSH_OBJ (state);
- FLASHCALL (state);
- POP (state);
-}
-
-static void
-compile_get_variable (CompileState *state, guint action, guint len)
-{
- push_uint16 (state, 1);
- push_target (state);
- push_prop (state, "eval");
- push_target (state);
- FLASHCALL (state);
-}
-
-static void
-compile_set_variable (CompileState *state, guint action, guint len)
-{
- /* FIXME: handle paths */
- push_target (state);
- FLASHSWAP (state, 3);
- SWAP (state);
- ONELINER (state, JSOP_SETELEM);
- POP (state);
-}
-
-static void
-push_string (CompileState *state, const char *s)
-{
- SWFDEC_LOG ("pushing string: %s", s);
- THREELINER_ATOM (state, JSOP_STRING, s);
-}
-
-static void
-push_double (CompileState *state, double d)
-{
- jsatomid id = atomize_double (state, d);
-
- SWFDEC_LOG ("pushing double: %g", d);
- THREELINER_INT (state, JSOP_NUMBER, id);
-}
-
-static void
-push_int32 (CompileState *state, gint32 i)
-{
- jsatomid id = atomize_int32 (state, i);
- SWFDEC_LOG ("pushing int: %d", i);
- THREELINER_INT (state, JSOP_NUMBER, id);
-}
-
-static void
-compile_push (CompileState *state, guint action, guint len)
-{
- SwfdecBits *bits = state->bits;
- guint type;
- unsigned char *end = bits->ptr + len;
- double d;
- int i;
- const char *s;
-
- while (bits->ptr < end) {
- type = swfdec_bits_get_u8 (bits);
- SWFDEC_LOG ("push type %u", type);
- switch (type) {
- case 0: /* string */
- s = swfdec_bits_skip_string (state->bits);
- if (s == NULL) {
- compile_state_error (state, "Push: Could not get string");
- return;
- }
- compile_state_debug_add (state, "Push \"%s\"", s);
- push_string (state, s);
- break;
- case 1: /* float */
- d = swfdec_bits_get_float (state->bits);
- compile_state_debug_add (state, "Push %g", d);
- push_double (state, d);
- break;
- case 2: /* null */
- compile_state_debug_add (state, "Push null");
- ONELINER (state, JSOP_NULL);
- break;
- case 3: /* undefined */
- compile_state_debug_add (state, "Push undefined");
- ONELINER (state, JSOP_NULL);
- ONELINER (state, JSOP_VOID);
- break;
- case 5: /* boolean */
- type = swfdec_bits_get_u8 (bits);
- if (type) {
- compile_state_debug_add (state, "Push TRUE");
- ONELINER (state, JSOP_TRUE);
- } else {
- compile_state_debug_add (state, "Push FALSE");
- ONELINER (state, JSOP_FALSE);
- }
- break;
- case 6: /* double */
- d = swfdec_bits_get_double (state->bits);
- compile_state_debug_add (state, "Push %g", d);
- push_double (state, d);
- break;
- case 7: /* 32bit int */
- /* FIXME: spec says U32, do they mean this? */
- i = swfdec_bits_get_u32 (state->bits);
- compile_state_debug_add (state, "Push %d", i);
- push_int32 (state, i);
- break;
- case 8: /* 8bit ConstantPool address */
- type = swfdec_bits_get_u8 (bits);
- if (type >= state->pool->len) {
- compile_state_error (state, "Constant pool index %u out of range %u",
- type, state->pool->len);
- return;
- }
- s = (const char *) g_ptr_array_index (state->pool, type);
- compile_state_debug_add (state, "Push \"%s\"", s);
- push_string (state, s);
- break;
- case 9: /* 16bit ConstantPool address */
- type = swfdec_bits_get_u16 (bits);
- if (type >= state->pool->len) {
- compile_state_error (state, "Constant pool index %u out of range %u",
- type, state->pool->len);
- return;
- }
- s = (const char *) g_ptr_array_index (state->pool, type);
- compile_state_debug_add (state, "Push \"%s\"", s);
- push_string (state, s);
- break;
- case 4: /* register */
- default:
- compile_state_error (state, "Push: type %u not implemented", type);
- swfdec_bits_getbits (bits, 8 * (end - bits->ptr));
- }
- }
-}
-
-static void
-compile_goto_label (CompileState *state, guint action, guint len)
-{
- const char *s;
-
- s = swfdec_bits_skip_string (state->bits);
- compile_state_debug_add (state, "GotoLabel \"%s\"s", s);
- push_target (state);
- push_prop (state, "gotoAndStop");
- PUSH_OBJ (state);
- push_string (state, s);
- call (state, 1);
- POP (state);
-}
-
-static void
-compile_goto_frame (CompileState *state, guint action, guint len)
-{
- unsigned int i;
-
- i = swfdec_bits_get_u16 (state->bits);
- compile_state_debug_add (state, "GotoFrame %u", i);
- push_target (state);
- push_prop (state, "gotoAndStop");
- PUSH_OBJ (state);
- push_uint16 (state, i + 1);
- call (state, 1);
- POP (state);
-}
-
-static void
-compile_goto_frame2 (CompileState *state, guint action, guint len)
-{
- int bias, play;
- if (swfdec_bits_getbits (state->bits, 6)) {
- SWFDEC_WARNING ("reserved bits in GotoFrame2 aren't 0");
- }
- bias = swfdec_bits_getbit (state->bits);
- play = swfdec_bits_getbit (state->bits);
- compile_state_debug_add (state, "GotoFrame2 %s", play ? "Play" : "Stop");
- if (bias) {
- SWFDEC_ERROR ("scene bias not implemented");
- }
- push_uint16 (state, 1);
- push_target (state);
- if (play)
- push_prop (state, "gotoAndPlay");
- else
- push_prop (state, "gotoAndStop");
- PUSH_OBJ (state);
- FLASHCALL (state);
-}
-
-static void
-compile_wait_for_frame (CompileState *state, guint action, guint len)
-{
- guint frame, jump;
- guint8 command[3] = { JSOP_IFEQ, 0, 0 };
-
- frame = swfdec_bits_get_u16 (state->bits);
- jump = swfdec_bits_get_u8 (state->bits);
- compile_state_debug_add (state, "WaitForFrame %u %u", frame, jump);
- push_target (state);
- push_prop (state, "_framesloaded");
- push_uint16 (state, frame);
- GE (state);
- compile_state_add_action_jump (state, jump, FALSE);
- compile_state_add_code (state, command, 3);
-}
-
-static void
-compile_jump (CompileState *state, guint action, guint len)
-{
- int amount = swfdec_bits_get_s16 (state->bits);
- compile_state_debug_add (state, "Goto %d", amount);
- DO_JUMP (state, JSOP_GOTO, amount + 5);
-}
-
-static void
-compile_if (CompileState *state, guint action, guint len)
-{
- int amount = swfdec_bits_get_s16 (state->bits);
- /* FIXME: Flash 4 does this differently */
-
- compile_state_debug_add (state, "If %d", amount);
- IFNE (state, amount + 5);
-}
-
-static void
-compile_set_target (CompileState *state, guint action, guint len)
-{
- const char *s = swfdec_bits_skip_string (state->bits);
-
- compile_state_debug_add (state, "SetTarget \"%s\"", s);
- THIS (state);
- push_prop (state, "eval");
- PUSH_OBJ (state);
- push_string (state, s);
- call (state, 1);
- compile_state_set_target (state);
-}
-
-static void
-compile_set_target_2 (CompileState *state, guint action, guint len)
-{
- compile_state_set_target (state);
-}
-
-static void
-compile_constant_pool (CompileState *state, guint action, guint len)
-{
- unsigned int i;
- SwfdecBits *bits = state->bits;
-
- /* no debug info please */
- state->command_last = G_MAXUINT;
- g_ptr_array_set_size (state->pool, swfdec_bits_get_u16 (bits));
- for (i = 0; i < state->pool->len; i++) {
- g_ptr_array_index (state->pool, i) = (gpointer) swfdec_bits_skip_string (bits);
- if (g_ptr_array_index (state->pool, i) == 0) {
- compile_state_error (state, "Couldn't get string %u/%ufor constant pool",
- i, state->pool->len);
- return;
- }
- }
-}
-
-static void
-compile_get_url (CompileState *state, guint action, guint len)
-{
- const char *target, *url;
-
- url = swfdec_bits_skip_string (state->bits);
- target = swfdec_bits_skip_string (state->bits);
- compile_state_debug_add (state, "GetURL \"%s\" \"%s\" ", url, target);
- push_target (state);
- push_prop (state, "getURL");
- PUSH_OBJ (state);
- push_string (state, url);
- push_string (state, target);
- call (state, 2);
- POP (state);
-}
-
-static void
-compile_oneliner_pop (CompileState *state, guint action, guint len)
-{
- JSOp op;
- switch (action) {
- case 0x4f:
- op = JSOP_SETELEM;
- break;
- default:
- g_assert_not_reached ();
- op = JSOP_NOP;
- }
- ONELINER (state, op);
- POP (state);
-}
-
-static void
-compile_get_member (CompileState *state, guint action, guint len)
-{
- add_try_catch_block (state, 1, 4);
- ONELINER (state, JSOP_GETELEM);
- THREELINER_INT (state, JSOP_GOTO, 5);
- POP (state);
- ONELINER (state, JSOP_VOID);
-}
-
-/* Flash < 7 does conversions to numbers way different than JS or Flash 7+
- * This function is supposed to do that conversion */
-static void
-ensure_number_flash6 (CompileState *state)
-{
- if (state->version < 7) {
- ONELINER (state, JSOP_DUP);
- ONELINER (state, JSOP_DUP);
- ONELINER (state, JSOP_VOID);
- ONELINER (state, JSOP_EQ);
- THREELINER_INT (state, JSOP_IFEQ, 5);
- POP (state);
- ONELINER (state, JSOP_ZERO);
- }
-}
-
-/* Flash < 5 does not know numbers. Therefore we convert booleans to 1 or 0 */
-static void
-boolean_to_number_flash4 (CompileState *state)
-{
- if (state->version < 5) {
- ONELINER (state, JSOP_ZERO);
- ONELINER (state, JSOP_ADD);
- }
-}
-
-static void
-compile_binary_op (CompileState *state, guint action, guint len)
-{
- JSOp op;
-
- if (state->version < 7) {
- /* lots of code to ensure that non-numeric arguments equal 0. */
- SWAP (state);
- ensure_number_flash6 (state);
- SWAP (state);
- ensure_number_flash6 (state);
- }
- switch (action) {
- case 0x0A:
- op = JSOP_ADD;
- break;
- case 0x0B:
- op = JSOP_SUB;
- break;
- case 0x0C:
- op = JSOP_MUL;
- break;
- case 0x0D:
- if (state->version >= 7) {
- /* division by undefined isn't NaN, but +-Infinity */
- ONELINER (state, JSOP_DUP);
- ONELINER (state, JSOP_DUP);
- ONELINER (state, JSOP_VOID);
- ONELINER (state, JSOP_EQ);
- THREELINER_INT (state, JSOP_IFEQ, 5);
- POP (state);
- ONELINER (state, JSOP_ZERO);
- }
- op = JSOP_DIV;
- break;
- default:
- g_assert_not_reached ();
- op = JSOP_NOP;
- }
- ONELINER (state, op);
-}
-
-static void
-compile_add2 (CompileState *state, guint action, guint len)
-{
- if (state->version >= 7) {
- ONELINER (state, JSOP_ADD);
- return;
- }
- /* pop void arguments and ignore them - special case void + void = 0 */
- ONELINER (state, JSOP_DUP);
- ONELINER (state, JSOP_DUP);
- ONELINER (state, JSOP_VOID);
- ONELINER (state, JSOP_EQ);
- THREELINER_INT (state, JSOP_IFEQ, 16);
- POP (state);
- ONELINER (state, JSOP_DUP);
- ONELINER (state, JSOP_DUP);
- ONELINER (state, JSOP_VOID);
- ONELINER (state, JSOP_EQ);
- THREELINER_INT (state, JSOP_IFEQ, 5);
- POP (state);
- ONELINER (state, JSOP_ZERO);
- THREELINER_INT (state, JSOP_GOTO, 17);
- SWAP (state);
- ONELINER (state, JSOP_DUP);
- ONELINER (state, JSOP_DUP);
- ONELINER (state, JSOP_VOID);
- ONELINER (state, JSOP_EQ);
- THREELINER_INT (state, JSOP_IFEQ, 7);
- POP (state);
- THREELINER_INT (state, JSOP_GOTO, 5);
- SWAP (state);
- ONELINER (state, JSOP_ADD);
-}
-
-static void
-compile_less (CompileState *state, guint action, guint len)
-{
- if (state->version < 7) {
- /* lots of code to ensure that non-numeric arguments equal 0. */
- SWAP (state);
- ensure_number_flash6 (state);
- SWAP (state);
- ensure_number_flash6 (state);
- }
- ONELINER (state, JSOP_LT);
-
- boolean_to_number_flash4 (state);
-}
-
-static void
-compile_comparison (CompileState *state, guint action, guint len)
-{
- JSOp op;
-
- if (state->version < 7) {
- /* lots of code to ensure that non-numeric arguments equal 0. */
- SWAP (state);
- ensure_number_flash6 (state);
- SWAP (state);
- ensure_number_flash6 (state);
- } else if (state->version == 7) {
- /* Flash 7 returns undefined when one of the inputs is undefined */
- ONELINER (state, JSOP_DUP);
- ONELINER (state, JSOP_DUP);
- ONELINER (state, JSOP_VOID);
- ONELINER (state, JSOP_EQ);
- THREELINER_INT (state, JSOP_IFEQ, 8);
- POP (state);
- ONELINER (state, JSOP_VOID);
- THREELINER_INT (state, JSOP_GOTO, 18);
- SWAP (state);
- ONELINER (state, JSOP_DUP);
- ONELINER (state, JSOP_DUP);
- ONELINER (state, JSOP_VOID);
- ONELINER (state, JSOP_EQ);
- THREELINER_INT (state, JSOP_IFEQ, 8);
- POP (state);
- ONELINER (state, JSOP_VOID);
- THREELINER_INT (state, JSOP_GOTO, 5);
- SWAP (state);
- }
- /* FIXME: what about Flash > 7? */
-
- switch (action) {
- case 0x48:
- op = JSOP_LT;
- break;
- case 0x67:
- op = JSOP_GT;
- break;
- default:
- g_assert_not_reached ();
- op = JSOP_NOP;
- }
- ONELINER (state, op);
-}
-
-static void
-compile_oneliner (CompileState *state, guint action, guint len)
-{
- JSOp op;
-
- switch (action) {
- case 0x12:
- op = JSOP_NOT;
- break;
- case 0x17:
- op = JSOP_POP;
- break;
- case 0x47:
- op = JSOP_ADD;
- break;
- case 0x49:
- op = JSOP_NEW_EQ;
- break;
- case 0x4c:
- op = JSOP_DUP;
- break;
- case 0x67:
- op = JSOP_GT;
- break;
- default:
- g_assert_not_reached ();
- op = JSOP_NOP;
- }
- ONELINER (state, op);
-}
-
-static void
-compile_call_function (CompileState *state, guint action, guint len)
-{
- push_target (state);
- SWAP (state);
- ONELINER (state, JSOP_GETELEM);
- ONELINER (state, JSOP_PUSHOBJ);
- ONELINER (state, JSOP_FLASHCALL);
-}
-
-static void
-compile_call_method (CompileState *state, guint action, guint len)
-{
- add_try_catch_block (state, 1, 6);
- ONELINER (state, JSOP_GETELEM);
- ONELINER (state, JSOP_PUSHOBJ);
-#if 0
- /* FIXME: can't add try/catch here, because FLASHCALL removes argument count from the stack (oops) */
- add_try_catch_block (state, 1, 5);
-#endif
- ONELINER (state, JSOP_FLASHCALL);
- THREELINER_INT (state, JSOP_GOTO, 17);
- /* exception handling goes here: clean up the stack */
- POP (state);
- POP (state);
- ONELINER (state, JSOP_DUP);
- THREELINER_INT (state, JSOP_IFEQ, 10);
- SWAP (state);
- POP (state);
- ONELINER (state, JSOP_ONE);
- ONELINER (state, JSOP_SUB);
- THREELINER_INT (state, JSOP_GOTO, -8);
- ONELINER (state, JSOP_VOID);
-}
-
-static void
-compile_start_drag (CompileState *state, guint action, guint len)
-{
- guint8 command[3] = { JSOP_IFEQ, 0, 27 };
- /* FIXME: target relative to this or target? */
- push_uint16 (state, 1);
- push_target (state);
- push_prop (state, "eval");
- PUSH_OBJ (state);
- FLASHCALL (state);
- FLASHSWAP (state, 3);
- compile_state_add_code (state, command, 3);
- FLASHSWAP (state, 3);
- FLASHSWAP (state, 6);
- FLASHSWAP (state, 3);
- FLASHSWAP (state, 4);
- FLASHSWAP (state, 5);
- FLASHSWAP (state, 4);
- push_uint16 (state, 5);
- command[0] = JSOP_GOTO;
- command[2] = 6;
- compile_state_add_code (state, command, 3);
- push_uint16 (state, 1);
- SWAP (state);
- FLASHSWAP (state, 3);
- push_prop (state, "startDrag");
- PUSH_OBJ (state);
- FLASHCALL (state);
- POP (state);
-}
-
-static void
-compile_increment (CompileState *state, guint action, guint len)
-{
- ONELINER (state, JSOP_ONE);
- ONELINER (state, JSOP_ADD);
-}
-
-static void
-compile_decrement (CompileState *state, guint action, guint len)
-{
- ONELINER (state, JSOP_ONE);
- ONELINER (state, JSOP_SUB);
-}
-
-static void
-compile_random (CompileState *state, guint action, guint len)
-{
- push_uint16 (state, 1);
- bind_name (state, "random");
- push_prop (state, "random");
- PUSH_OBJ (state);
- FLASHCALL (state);
-}
-
-static void
-compile_get_property (CompileState *state, guint action, guint len)
-{
- SWAP (state);
- push_uint16 (state, 2);
- push_target (state);
- push_prop (state, "getProperty");
- PUSH_OBJ (state);
- FLASHCALL (state);
-}
-
-static void
-compile_set_property (CompileState *state, guint action, guint len)
-{
- FLASHSWAP (state, 3);
- push_uint16 (state, 3);
- bind_name (state, "setProperty");
- push_prop (state, "setProperty");
- PUSH_OBJ (state);
- FLASHCALL (state);
- POP (state);
-}
-
-static void
-compile_string_add (CompileState *state, guint action, guint len)
-{
- /* be sure to have strings */
- push_string (state, "");
- ONELINER (state, JSOP_ADD);
- ONELINER (state, JSOP_ADD);
-}
-
-static void
-compile_equals (CompileState *state, guint action, guint len)
-{
- /* ensure we compare numbers */
- ONELINER (state, JSOP_POS);
- ONELINER (state, JSOP_EQ);
- if (state->version <= 4) {
- /* FLash 4 wants 1 or 0 on the stack instead of TRUE or FALSE */
- ONELINER (state, JSOP_ZERO);
- ONELINER (state, JSOP_BITOR);
- }
-}
-
-static void
-compile_to_integer (CompileState *state, guint action, guint len)
-{
- /* There's no opcode so we use a bitwise operation that forces a conversion */
- ONELINER (state, JSOP_ZERO);
- ONELINER (state, JSOP_BITOR);
-}
-
-static void
-compile_target_path (CompileState *state, guint action, guint len)
-{
- ONELINER (state, JSOP_DUP);
- name (state, "MovieClip");
- ONELINER (state, JSOP_INSTANCEOF);
- THREELINER_INT (state, JSOP_IFEQ, 13);
- push_prop (state, "toString");
- PUSH_OBJ (state);
- call (state, 0);
- THREELINER_INT (state, JSOP_GOTO, 4);
- ONELINER (state, JSOP_VOID);
-}
-
-static void
-compile_new_object (CompileState *state, guint action, guint len)
-{
- /* use eval to get at the constructor - spidermonkey doesn't like
- * new with strings */
- push_uint16 (state, 1);
- bind_name (state, "eval");
- push_prop (state, "eval");
- PUSH_OBJ (state);
- FLASHCALL (state);
- /* use call instead of new here - if this doesn't work, a FLASHNEW opcode is needed */
- PUSH_OBJ (state);
- FLASHCALL (state);
-}
-
-static void
-compile_init_object (CompileState *state, guint action, guint len)
-{
- name (state, "Object");
- PUSH_OBJ (state);
- THREELINER_INT (state, JSOP_NEW, 0);
- DUP (state);
- FLASHSWAP (state, 3);
- DUP (state);
- THREELINER_INT (state, JSOP_IFEQ, 17);
- ONELINER (state, JSOP_ONE);
- ONELINER (state, JSOP_SUB);
- FLASHSWAP (state, 5);
- SWAP (state);
- FLASHSWAP (state, 4);
- ONELINER (state, JSOP_SETELEM);
- POP (state);
- THREELINER_INT (state, JSOP_GOTO, -19);
- POP (state);
- POP (state);
-}
-
-static void
-compile_simple_bind_call (CompileState *state, guint action, guint len)
-{
- char *name;
- switch (action) {
- case 0x09:
- name = "stopAllSounds";
- break;
- default:
- g_assert_not_reached ();
- return;
- }
- bind_name (state, name);
- call_void_function (state, name);
-}
-
-static void
-compile_simple_call (CompileState *state, guint action, guint len)
-{
- char *name;
-
- /* FIXME: shouldn't some functions here PUSH_OBJ instead of push_target? */
- push_target (state);
- switch (action) {
- case 0x04:
- name = "nextFrame";
- break;
- case 0x05:
- name = "prevFrame";
- break;
- case 0x06:
- name = "play";
- break;
- case 0x07:
- name = "stop";
- break;
- case 0x09:
- name = "stopAllSounds";
- break;
- case 0x28:
- name = "stopDrag";
- break;
- default:
- g_assert_not_reached ();
- return;
- }
- call_void_function (state, name);
-}
-
-/*** COMPILER ***/
-
-typedef struct {
- guint action;
- const char *name;
- void (* compile) (CompileState *state, guint action, guint len);
-} SwfdecActionSpec;
-
-static const SwfdecActionSpec * swfdec_action_find (guint action);
-
-/**
- * swfdec_compile:
- * @player: a #SwfdecPlayer
- * @bits: the data to read
- * @version: ActionScript version to compile for
- * @name: name describing the script or NULL
- *
- * parses the data pointed to by @bits and compiles the ActionScript commands
- * encountered into a script for later execution.
- *
- * Returns: A new JSScript or NULL on failure
- **/
-JSScript *
-swfdec_compile (SwfdecPlayer *player, SwfdecBits *bits, int version, const char *name)
-{
- unsigned int action, len;
- const SwfdecActionSpec *current;
- CompileState state;
- JSScript *ret;
-#ifndef SWFDEC_DISABLE_DEBUG
- unsigned char *start = bits->ptr;
-#endif
-#ifndef G_DISABLE_ASSERT
- unsigned char *target;
-#endif
-//#define SWFDEC_DUMP_SCRIPTS
-#ifdef SWFDEC_DUMP_SCRIPTS
- SwfdecBits dump = *bits;
-#endif
-
- g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
- g_return_val_if_fail (bits != NULL, NULL);
-
- if (name == NULL)
- name = "Unnamed script";
- compile_state_init (player->jscx, bits, version, &state);
- SWFDEC_INFO ("Creating new script in frame");
- while (swfdec_bits_left (bits) && (action = swfdec_bits_get_u8 (bits))) {
- if (action & 0x80) {
- len = swfdec_bits_get_u16 (bits);
- } else {
- len = 0;
- }
- if (swfdec_bits_left (bits) < len * 8) {
- compile_state_error (&state, "Not enough data available to parse next action");
- }
-#ifndef G_DISABLE_ASSERT
- target = bits->ptr + len;
-#endif
- current = swfdec_action_find (action);
- SWFDEC_LOG ("compiling action %d %s (len %d, total %d)", action,
- current ? current->name : "unknown", len > 0 ? 3 + len : 1,
- bits->ptr - start);
-#if 0
- if (state.error == NULL)
- g_print (" compiling action %d %s (len %d, total %d)\n", action,
- current ? current->name : "unknown", len > 0 ? 3 + len : 1,
- bits->ptr - start);
-#endif
- if (state.error == NULL && current && current->compile) {
- state.command_last = state.bytecode->len;
- current->compile (&state, action, len);
- compile_state_debug_add_default (&state, action, current->name);
- compile_state_push_offset (&state, len ? 3 + len : 1);
-#ifndef G_DISABLE_ASSERT
- if (target != bits->ptr) {
- SWFDEC_ERROR ("parsed length and supposed length differ by %d bytes in %s action",
- bits->ptr - target, current->name);
- }
- bits->ptr = target;
-#endif
- } else {
- swfdec_bits_getbits (bits, len * 8);
- if (state.error == NULL) {
- if (current) {
- compile_state_error (&state, "No compilation function for %s action", current->name);
- } else {
- compile_state_error (&state, "unknown action 0x%02X", action);
- }
- }
- }
- }
- ret = compile_state_finish (&state, player, name);
-#if 0
- if (ret)
- swfdec_disassemble (s, ret);
-#endif
-#ifdef SWFDEC_DUMP_SCRIPTS
- {
- static int dump_count = 0;
- char *filename = g_strdup_printf ("script%d", dump_count++);
- g_file_set_contents (filename, (char *) dump.ptr, bits->ptr - dump.ptr, NULL);
- g_free (filename);
- }
-#endif
-
- return ret;
-}
-
-/**
- * swfdec_compiler_destroy_script:
- * @player: a #SwfdecPlayer
- * @script: a JSScript created via swfdec_compile()
- *
- * Destroys a script that was previously created via swfdec_compile () for @player.
- * All scripts created via swfdec_compile must be removed with this function.
- **/
-void
-swfdec_compiler_destroy_script (SwfdecPlayer *player, JSScript *script)
-{
- g_return_if_fail (SWFDEC_IS_PLAYER (player));
- g_return_if_fail (script != NULL);
-
- if (SWFDEC_IS_DEBUGGER (player))
- swfdec_debugger_remove_script (SWFDEC_DEBUGGER (player), script);
- JS_DestroyScript (player->jscx, script);
-}
-
-/* must be sorted! */
-SwfdecActionSpec actions[] = {
- /* version 3 */
- { 0x04, "NextFrame", compile_simple_call },
- { 0x05, "PreviousFrame", compile_simple_call },
- { 0x06, "Play", compile_simple_call },
- { 0x07, "Stop", compile_simple_call },
- { 0x08, "ToggleQuality", NULL },
- { 0x09, "StopSounds", compile_simple_bind_call },
- /* version 4 */
- { 0x0a, "Add", compile_binary_op },
- { 0x0b, "Subtract", compile_binary_op },
- { 0x0c, "Multiply", compile_binary_op },
- { 0x0d, "Divide", compile_binary_op },
- { 0x0e, "Equals", compile_equals },
- { 0x0f, "Less", compile_less },
- { 0x10, "And", NULL },
- { 0x11, "Or", NULL },
- { 0x12, "Not", compile_oneliner },
- { 0x13, "StringEquals", NULL },
- { 0x14, "StringLength", NULL },
- { 0x15, "StringExtract", NULL },
- { 0x17, "Pop", compile_oneliner },
- { 0x18, "ToInteger", compile_to_integer },
- { 0x1c, "GetVariable", compile_get_variable },
- { 0x1d, "SetVariable", compile_set_variable },
- { 0x20, "SetTarget2", compile_set_target_2 },
- { 0x21, "StringAdd", compile_string_add },
- { 0x22, "GetProperty", compile_get_property },
- { 0x23, "SetProperty", compile_set_property },
- { 0x24, "CloneSprite", NULL },
- { 0x25, "RemoveSprite", NULL },
- { 0x26, "Trace", compile_trace },
- { 0x27, "StartDrag", compile_start_drag },
- { 0x28, "EndDrag", compile_simple_call },
- { 0x29, "StringLess", NULL },
- /* version 7 */
- { 0x2a, "Throw", NULL },
- { 0x2b, "Cast", NULL },
- { 0x2c, "Implements", NULL },
- /* version 4 */
- { 0x30, "RandomNumber", compile_random },
- { 0x31, "MBStringLength", NULL },
- { 0x32, "CharToAscii", NULL },
- { 0x33, "AsciiToChar", NULL },
- { 0x34, "GetTime", NULL },
- { 0x35, "MBStringExtract", NULL },
- { 0x36, "MBCharToAscii", NULL },
- { 0x37, "MVAsciiToChar", NULL },
- /* version 5 */
- { 0x3a, "Delete", NULL },
- { 0x3b, "Delete2", NULL },
- { 0x3c, "DefineLocal", NULL },
- { 0x3d, "CallFunction", compile_call_function },
- { 0x3e, "Return", NULL },
- { 0x3f, "Modulo", NULL },
- { 0x40, "NewObject", compile_new_object },
- { 0x41, "DefineLocal2", NULL },
- { 0x42, "InitArray", NULL },
- { 0x43, "InitObject", compile_init_object },
- { 0x44, "Typeof", NULL },
- { 0x45, "TargetPath", compile_target_path },
- { 0x46, "Enumerate", NULL },
- { 0x47, "Add2", compile_add2 },
- { 0x48, "Less2", compile_comparison },
- { 0x49, "Equals2", compile_oneliner },
- { 0x4a, "ToNumber", NULL },
- { 0x4b, "ToString", NULL },
- { 0x4c, "PushDuplicate", compile_oneliner },
- { 0x4d, "Swap", NULL },
- { 0x4e, "GetMember", compile_get_member },
- { 0x4f, "SetMember", compile_oneliner_pop }, /* apparently the result is ignored */
- { 0x50, "Increment", compile_increment },
- { 0x51, "Decrement", compile_decrement },
- { 0x52, "CallMethod", compile_call_method },
- { 0x53, "NewMethod", NULL },
- /* version 6 */
- { 0x54, "InstanceOf", NULL },
- { 0x55, "Enumerate2", NULL },
- /* version 5 */
- { 0x60, "BitAnd", NULL },
- { 0x61, "BitOr", NULL },
- { 0x62, "BitXor", NULL },
- { 0x63, "BitLShift", NULL },
- { 0x64, "BitRShift", NULL },
- { 0x65, "BitURShift", NULL },
- /* version 6 */
- { 0x66, "StrictEquals", NULL },
- { 0x67, "Greater", compile_comparison },
- { 0x68, "StringGreater", NULL },
- /* version 7 */
- { 0x69, "Extends", NULL },
-
- /* version 3 */
- { 0x81, "GotoFrame", compile_goto_frame },
- { 0x83, "GetURL", compile_get_url },
- /* version 5 */
- { 0x87, "StoreRegister", NULL },
- { 0x88, "ConstantPool", compile_constant_pool },
- /* version 3 */
- { 0x8a, "WaitForFrame", compile_wait_for_frame },
- { 0x8b, "SetTarget", compile_set_target },
- { 0x8c, "GotoLabel", compile_goto_label },
- /* version 4 */
- { 0x8d, "WaitForFrame2", NULL },
- /* version 7 */
- { 0x8e, "DefineFunction2", NULL },
- { 0x8f, "Try", NULL },
- /* version 5 */
- { 0x94, "With", NULL },
- /* version 4 */
- { 0x96, "Push", compile_push },
- { 0x99, "Jump", compile_jump },
- { 0x9a, "GetURL2", NULL },
- /* version 5 */
- { 0x9b, "DefineFunction", NULL },
- /* version 4 */
- { 0x9d, "If", compile_if },
- { 0x9e, "Call", NULL },
- { 0x9f, "GotoFrame2", compile_goto_frame2 }
-};
-
-int
-uint_compare (gconstpointer v1, gconstpointer v2)
-{
- return *((const unsigned int*) v1) - *((const unsigned int*) v2);
-}
-
-static const SwfdecActionSpec *
-swfdec_action_find (guint action)
-{
- return bsearch (&action, actions, G_N_ELEMENTS (actions),
- sizeof (SwfdecActionSpec), uint_compare);
-}
diff --git a/libswfdec/swfdec_compiler.h b/libswfdec/swfdec_compiler.h
deleted file mode 100644
index d3b8c9c..0000000
--- a/libswfdec/swfdec_compiler.h
+++ /dev/null
@@ -1,21 +0,0 @@
-
-#ifndef __SWFDEC_COMPILER_H__
-#define __SWFDEC_COMPILER_H__
-
-#include <libswfdec/js/jsapi.h>
-#include <libswfdec/swfdec_bits.h>
-#include <libswfdec/swfdec_player.h>
-
-#error "swfdec_compiler.h is out of the game now!"
-G_BEGIN_DECLS
-
-JSScript * swfdec_compile (SwfdecPlayer * player,
- SwfdecBits * bits,
- int version,
- const char * name);
-void swfdec_compiler_destroy_script (SwfdecPlayer * player,
- JSScript * script);
-
-G_END_DECLS
-
-#endif
diff-tree 375b6d4dc5d4335c3fcafa0ce96076287ae2b9ac (from parents)
Merge: a86c50354559053bfdba86f13cdf8ec9c455205a bdc67ff4e611ed187083eb9a45db630eecb260dd
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Feb 6 12:20:07 2007 +0100
Merge branch 'master' into interpreter
diff --cc test/Makefile.am
index 33a647c,e0957af..00c8203
@@@ -1,10 -1,6 +1,10 @@@
- SUBDIRS = sound trace various
+ SUBDIRS = image sound trace various
-noinst_PROGRAMS = swfdec-extract dump parse
+if WITH_GTK
+noinst_PROGRAMS = swfdec-extract dump parse swfedit
+else
+noinst_PROGRAMS = swfdec-extract dump parse
+endif
dump_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(CAIRO_CFLAGS) $(PANGO_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
dump_LDFLAGS = $(SWF_LIBS) $(CAIRO_LIBS) $(PANGO_LIBS)
diff-tree a86c50354559053bfdba86f13cdf8ec9c455205a (from parents)
Merge: 940ef9614313d253bb9282e26f48968b4af13c85 d7db95f092791ed1e81ad2d2e4f9e3fb345d6f79
Author: Benjamin Otte <otte at gnome.org>
Date: Sun Feb 4 18:39:22 2007 +0100
Merge branch 'master' into interpreter
Conflicts:
libswfdec/swfdec_image.c
diff --cc libswfdec/swfdec_bits.c
index f3ea7c4,5013e49..21172f2
@@@ -482,13 -450,13 +482,13 @@@
g = swfdec_bits_get_u8 (bits);
b = swfdec_bits_get_u8 (bits);
- return SWF_COLOR_COMBINE (r, g, b, 0xff);
+ return SWFDEC_COLOR_COMBINE (r, g, b, 0xff);
}
-unsigned int
+SwfdecColor
swfdec_bits_get_rgba (SwfdecBits * bits)
{
- int r, g, b, a;
+ unsigned int r, g, b, a;
r = swfdec_bits_get_u8 (bits);
g = swfdec_bits_get_u8 (bits);
diff --cc libswfdec/swfdec_image.c
index 23602c4,224e101..53dad98
@@@ -290,18 -288,19 +267,17 @@@
swfdec_image_jpeg3_load (SwfdecImage *image)
{
JpegRGBDecoder *dec;
- unsigned char *image_data;
unsigned char *alpha_data;
SwfdecBits bits;
- int len;
+ SwfdecBuffer *buffer;
int jpeg_length;
- bits.buffer = image->raw_data;
- bits.ptr = image->raw_data->data;
- bits.idx = 0;
- bits.end = bits.ptr + image->raw_data->length;
-
- bits.ptr += 2;
+ swfdec_bits_init (&bits, image->raw_data);
jpeg_length = swfdec_bits_get_u32 (&bits);
+ buffer = swfdec_bits_get_buffer (&bits, jpeg_length);
+ if (buffer == NULL)
+ return;
dec = jpeg_rgb_decoder_new ();
@@@ -318,15 -316,13 +294,13 @@@
&image->rowstride, &image->width, &image->height);
jpeg_rgb_decoder_free (dec);
- bits.ptr += jpeg_length;
-
- alpha_data = lossless (bits.ptr, bits.end - bits.ptr, &len);
+ buffer = swfdec_bits_get_buffer (&bits, -1);
+ alpha_data = lossless (buffer->data, buffer->length, image->width * image->height);
+ swfdec_buffer_unref (buffer);
- merge_alpha (image, image_data, alpha_data);
+ merge_alpha (image, image->data, alpha_data);
g_free (alpha_data);
- swfdec_image_create_surface (image, image_data);
-
SWFDEC_LOG (" width = %d", image->width);
SWFDEC_LOG (" height = %d", image->height);
}
@@@ -356,13 -348,20 +326,12 @@@
swfdec_image_lossless_load (SwfdecImage *image)
{
int format;
- int color_table_size;
+ guint color_table_size;
unsigned char *ptr;
- int len;
- unsigned char *endptr;
SwfdecBits bits;
- unsigned char *image_data = NULL;
int have_alpha = (image->type == SWFDEC_IMAGE_TYPE_LOSSLESS2);
- bits.buffer = image->raw_data;
- bits.ptr = image->raw_data->data;
- bits.idx = 0;
- bits.end = bits.ptr + image->raw_data->length;
- endptr = bits.ptr + bits.buffer->length;
-
- bits.ptr += 2;
+ swfdec_bits_init (&bits, image->raw_data);
format = swfdec_bits_get_u8 (&bits);
SWFDEC_LOG (" format = %d", format);
@@@ -384,29 -383,31 +353,29 @@@
if (image->width == 0 || image->height == 0)
return;
swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height);
- ptr = lossless (bits.ptr, endptr - bits.ptr, &len);
- bits.ptr = endptr;
if (format == 3) {
- unsigned char *color_table;
unsigned char *indexed_data;
- int i;
+ guint i;
+ unsigned int rowstride = (image->width + 3) & ~3;
- image_data = g_malloc (4 * image->width * image->height);
+ image->data = g_malloc (4 * image->width * image->height);
image->rowstride = image->width * 4;
- color_table = g_malloc (color_table_size * 4);
-
if (have_alpha) {
+ ptr = lossless (bits.ptr, bits.end - bits.ptr,
+ color_table_size * 4 + rowstride * image->height);
for (i = 0; i < color_table_size; i++) {
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- color_table[i * 4 + 0] = ptr[i * 4 + 2];
- color_table[i * 4 + 1] = ptr[i * 4 + 1];
- color_table[i * 4 + 2] = ptr[i * 4 + 0];
- color_table[i * 4 + 3] = ptr[i * 4 + 3];
+ guint8 tmp = ptr[i * 4 + 0];
+ ptr[i * 4 + 0] = ptr[i * 4 + 2];
+ ptr[i * 4 + 2] = tmp;
#else
- color_table[i * 4 + 0] = ptr[i * 4 + 3];
- color_table[i * 4 + 1] = ptr[i * 4 + 0];
- color_table[i * 4 + 2] = ptr[i * 4 + 1];
- color_table[i * 4 + 3] = ptr[i * 4 + 2];
+ guint8 tmp = ptr[i * 4 + 3];
+ ptr[i * 4 + 3] = ptr[i * 4 + 2];
+ ptr[i * 4 + 2] = ptr[i * 4 + 1];
+ ptr[i * 4 + 1] = ptr[i * 4 + 0];
+ ptr[i * 4 + 0] = tmp;
#endif
}
indexed_data = ptr + color_table_size * 4;
@@@ -432,70 -427,55 +401,51 @@@
}
indexed_data = ptr + color_table_size * 3;
}
- swfdec_image_colormap_decode (image, image_data, indexed_data,
+ swfdec_image_colormap_decode (image, image->data, indexed_data,
- color_table, color_table_size);
+ ptr, color_table_size);
- g_free (color_table);
g_free (ptr);
-- }
-- if (format == 4) {
- unsigned char *p = ptr;
++ } else if (format == 4) {
int i, j;
unsigned int c;
unsigned char *idata;
++ guint8 *p;
if (have_alpha) {
SWFDEC_INFO("16bit images aren't allowed to have alpha, ignoring");
have_alpha = FALSE;
}
- ptr = lossless (bits.ptr, bits.end - bits.ptr, 2 * image->width * image->height);
- image_data = g_malloc (4 * image->width * image->height);
- idata = image_data;
++ p = ptr = lossless (bits.ptr, bits.end - bits.ptr, 2 * image->width * image->height);
+ image->data = g_malloc (4 * image->width * image->height);
+ idata = image->data;
image->rowstride = image->width * 4;
/* 15 bit packed */
for (j = 0; j < image->height; j++) {
for (i = 0; i < image->width; i++) {
- c = ptr[1] | (ptr[0] << 8);
- #if G_BYTE_ORDER == G_LITTLE_ENDIAN
- idata[0] = (c << 3) | ((c >> 2) & 0x7);
- idata[1] = ((c >> 2) & 0xf8) | ((c >> 7) & 0x7);
- idata[2] = ((c >> 7) & 0xf8) | ((c >> 12) & 0x7);
- idata[3] = 0xff;
- #else
- idata[3] = (c << 3) | ((c >> 2) & 0x7);
- idata[2] = ((c >> 2) & 0xf8) | ((c >> 7) & 0x7);
- idata[1] = ((c >> 7) & 0xf8) | ((c >> 12) & 0x7);
- idata[0] = 0xff;
- #endif
+ c = p[1] | (p[0] << 8);
+ idata[SWFDEC_COLOR_INDEX_BLUE] = (c << 3) | ((c >> 2) & 0x7);
+ idata[SWFDEC_COLOR_INDEX_GREEN] = ((c >> 2) & 0xf8) | ((c >> 7) & 0x7);
+ idata[SWFDEC_COLOR_INDEX_RED] = ((c >> 7) & 0xf8) | ((c >> 12) & 0x7);
+ idata[SWFDEC_COLOR_INDEX_ALPHA] = 0xff;
- p += 2;
+ ptr += 2;
idata += 4;
}
}
g_free (ptr);
}
if (format == 5) {
-
- image_data = lossless (bits.ptr, bits.end - bits.ptr, 4 * image->width * image->height);
- image->rowstride = image->width * 4;
-
- #if G_BYTE_ORDER == G_LITTLE_ENDIAN
- {
- int i, j;
- /* image is stored in 0RGB format. We use ARGB/BGRA. */
- for (j = 0; j < image->height; j++) {
- for (i = 0; i < image->width; i++) {
- ptr[0] = ptr[3];
- ptr[1] = ptr[2];
- ptr[2] = ptr[1];
- ptr[3] = 255;
- ptr += 4;
- }
+ int i, j;
-
- image->data = ptr;
- image->rowstride = image->width * 4;
-
++ ptr = image->data = lossless (bits.ptr, bits.end - bits.ptr, 4 * image->width * image->height);
+ /* image is stored in 0RGB format. We use ARGB/BGRA. */
+ for (j = 0; j < image->height; j++) {
+ for (i = 0; i < image->width; i++) {
+ *((guint32 *) ptr) = GUINT32_FROM_BE (*((guint32 *) ptr));
+ ptr += 4;
}
}
- #endif
}
-
- swfdec_image_create_surface (image, image_data);
}
int
diff --cc test/dump.c
index 9ee0524,9ee0524..efddeee
@@@ -1,7 -1,7 +1,7 @@@
/* Swfdec
* Copyright (C) 2003-2006 David Schleef <ds at schleef.org>
* 2005-2006 Eric Anholt <eric at anholt.net>
-- * 2006 Benjamin Otte <otte at gnome.org>
++ * 2006-2007 Benjamin Otte <otte at gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@@ -34,6 -34,6 +34,7 @@@
#include <libswfdec/swfdec_button.h>
#include <libswfdec/swfdec_edittext.h>
#include <libswfdec/swfdec_font.h>
++#include <libswfdec/swfdec_image.h>
#include <libswfdec/swfdec_movie.h>
#include <libswfdec/swfdec_player_internal.h>
#include <libswfdec/swfdec_root_movie.h>
@@@ -287,6 -287,6 +288,34 @@@
}
}
++const char *
++get_image_type_name (SwfdecImageType type)
++{
++ switch (type) {
++ case SWFDEC_IMAGE_TYPE_JPEG:
++ return "JPEG with global table";
++ case SWFDEC_IMAGE_TYPE_JPEG2:
++ return "JPEG";
++ case SWFDEC_IMAGE_TYPE_JPEG3:
++ return "JPEG with alpha";
++ case SWFDEC_IMAGE_TYPE_LOSSLESS:
++ return "lossless";
++ case SWFDEC_IMAGE_TYPE_LOSSLESS2:
++ return "lossless with alpha";
++ default:
++ g_assert_not_reached ();
++ return "Unknown";
++ }
++}
++
++static void
++dump_image (SwfdecImage *image)
++{
++ cairo_surface_destroy (swfdec_image_create_surface (image));
++ g_print (" %s %u x %u\n", get_image_type_name (image->type),
++ image->width, image->height);
++}
++
static void
dump_objects (SwfdecSwfDecoder *s)
{
@@@ -301,6 -301,6 +330,9 @@@
g_print (" extents: %g %g %g %g\n", graphic->extents.x0, graphic->extents.y0,
graphic->extents.x1, graphic->extents.y1);
}
++ if (SWFDEC_IS_IMAGE (c)) {
++ dump_image (SWFDEC_IMAGE (c));
++ }
if (SWFDEC_IS_SPRITE (c)) {
dump_sprite (SWFDEC_SPRITE (c));
}
diff --cc test/swfdec-extract.c
index ac79124,b4a2951..47e8234
@@@ -258,8 -269,11 +269,11 @@@
} else if (SWFDEC_IS_GRAPHIC (character)) {
if (!export_graphic (SWFDEC_GRAPHIC (character), argv[3]))
ret = 1;
+ } else if (SWFDEC_IS_IMAGE (character)) {
+ if (!export_image (SWFDEC_IMAGE (character), argv[3]))
+ ret = 1;
} else {
- g_printerr ("id %ld does not specify an exportable object", id);
+ g_printerr ("id %ld does not specify an exportable object\n", id);
ret = 1;
}
diff --cc test/swfdec_out.c
index bf7aa9e,0000000..0719b0f
mode 100644,000000..100644
@@@ -1,258 -1,0 +1,258 @@@
+/* Swfdec
+ * Copyright (C) 2007 Benjamin Otte <otte at 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 "swfdec_out.h"
+
+SwfdecOut *
+swfdec_out_open (void)
+{
+ SwfdecOut *out = g_new0 (SwfdecOut, 1);
+
+ out->data = g_malloc (SWFDEC_OUT_INITIAL);
+ out->ptr = out->data;
+ out->end = out->data + SWFDEC_OUT_INITIAL;
+
+ return out;
+}
+
+static void
+swfdec_out_syncbits (SwfdecOut *out)
+{
+ g_return_if_fail (out != NULL);
+
+ if (out->idx > 0) {
+ out->ptr++;
+ out->idx = 0;
+ }
+}
+
+SwfdecBuffer *
+swfdec_out_close (SwfdecOut *out)
+{
+ SwfdecBuffer *buffer;
+
+ g_return_val_if_fail (out != NULL, NULL);
+
+ swfdec_out_syncbits (out);
+
+ buffer = swfdec_buffer_new ();
+ buffer->data = out->data;
+ buffer->length = out->ptr - out->data;
+
+ g_free (out);
+
+ return buffer;
+}
+
+unsigned int
+swfdec_out_left (SwfdecOut *out)
+{
+ g_return_val_if_fail (out != NULL, 0);
+
+ return (out->end - out->ptr) * 8 - out->idx;
+}
+
+void
+swfdec_out_ensure_bits (SwfdecOut *out, unsigned int bits)
+{
+ unsigned int current, taken, needed;
+
+ g_return_if_fail (out != NULL);
+
+ current = swfdec_out_left (out);
+ if (current >= bits)
+ return;
+ taken = out->ptr - out->data;
+ needed = (bits - current + 7) / 8;
+ needed += SWFDEC_OUT_STEP;
+ needed -= needed % SWFDEC_OUT_STEP;
+ needed += out->end - out->data;
+ out->data = g_realloc (out->data, needed);
+ out->ptr = out->data + taken;
+ out->end = out->data + needed;
+}
+
+void
+swfdec_out_prepare_bytes (SwfdecOut *out, unsigned int bytes)
+{
+ g_return_if_fail (out != NULL);
+
+ swfdec_out_syncbits (out);
+ swfdec_out_ensure_bits (out, bytes * 8);
+}
+
+void
+swfdec_out_put_buffer (SwfdecOut *out, SwfdecBuffer *buffer)
+{
+ g_return_if_fail (out != NULL);
+
+ swfdec_out_prepare_bytes (out, buffer->length);
+ memcpy (out->ptr, buffer->data, buffer->length);
+ out->ptr += buffer->length;
+}
+
+void
+swfdec_out_put_u8 (SwfdecOut *out, guint i)
+{
+ g_return_if_fail (i <= G_MAXUINT8);
+
+ swfdec_out_prepare_bytes (out, 1);
+ *out->ptr = i;
+ out->ptr++;
+}
+
+void
+swfdec_out_put_u16 (SwfdecOut *out, guint i)
+{
+ g_return_if_fail (i <= G_MAXUINT16);
+
+ swfdec_out_prepare_bytes (out, 2);
+ *(guint16 *)out->ptr = GUINT16_TO_LE (i);
+ out->ptr += 2;
+}
+
+void
+swfdec_out_put_u32 (SwfdecOut *out, guint i)
+{
+ g_return_if_fail (i <= G_MAXUINT32);
+
+ swfdec_out_prepare_bytes (out, 4);
+ *(guint32 *)out->ptr = GUINT32_TO_LE (i);
+ out->ptr += 4;
+}
+
+void
+swfdec_out_put_bit (SwfdecOut *out, gboolean bit)
+{
+ g_return_if_fail (out != NULL);
+
+ swfdec_out_put_bits (out, bit ? 1 : 0, 1);
+}
+
+void
+swfdec_out_put_bits (SwfdecOut *out, guint bits, guint n_bits)
+{
+ g_return_if_fail (out != NULL);
+
+ swfdec_out_ensure_bits (out, n_bits);
+
+ /* FIXME: implement this less braindead */
+ while (n_bits) {
+ guint bits_now = MIN (n_bits, 8 - out->idx);
+ guint value = bits >> (n_bits - bits_now);
+
+ /* clear data if necessary */
+ if (out->idx == 0)
+ *out->ptr = 0;
+ value &= (1 << bits_now) - 1;
+ value <<= 8 - out->idx - bits_now;
+ *out->ptr |= value;
+ out->idx += bits_now;
+ g_assert (out->idx <= 8);
+ if (out->idx == 8) {
+ out->ptr ++;
+ out->idx = 0;
+ }
+ n_bits -= bits_now;
+ }
+}
+
+void
+swfdec_out_put_sbits (SwfdecOut *out, int bits, guint n_bits)
+{
+ g_return_if_fail (out != NULL);
+ swfdec_out_put_bits (out, bits, n_bits);
+}
+
+static guint
+swfdec_out_bits_required (guint x)
+{
+ guint ret = 0;
+
+ while (x > 0) {
+ x >>= 1;
+ ret++;
+ }
+ return ret;
+}
+
+static guint
+swfdec_out_sbits_required (int x)
+{
+ if (x < 0)
+ x = -x;
+ return swfdec_out_bits_required (x) + 1;
+}
+
+void
+swfdec_out_put_rect (SwfdecOut *out, SwfdecRect *rect)
+{
+ int x0, x1, y0, y1;
+ guint req, tmp;
+
+ g_return_if_fail (out != NULL);
+ g_return_if_fail (rect != NULL);
+
+ x0 = rect->x0;
+ y0 = rect->y0;
+ x1 = rect->x1;
+ y1 = rect->y1;
+ req = swfdec_out_sbits_required (x0);
+ tmp = swfdec_out_sbits_required (y0);
+ req = MAX (req, tmp);
+ tmp = swfdec_out_sbits_required (x1);
+ req = MAX (req, tmp);
+ tmp = swfdec_out_sbits_required (y1);
+ req = MAX (req, tmp);
+ swfdec_out_syncbits (out);
+ swfdec_out_put_bits (out, req, 5);
+ swfdec_out_put_sbits (out, x0, req);
+ swfdec_out_put_sbits (out, x1, req);
+ swfdec_out_put_sbits (out, y0, req);
+ swfdec_out_put_sbits (out, y1, req);
+ swfdec_out_syncbits (out);
+}
+
+void
+swfdec_out_put_rgb (SwfdecOut *out, SwfdecColor color)
+{
+ g_return_if_fail (out != NULL);
+
- swfdec_out_put_u8 (out, SWF_COLOR_R (color));
- swfdec_out_put_u8 (out, SWF_COLOR_G (color));
- swfdec_out_put_u8 (out, SWF_COLOR_B (color));
++ swfdec_out_put_u8 (out, SWFDEC_COLOR_R (color));
++ swfdec_out_put_u8 (out, SWFDEC_COLOR_G (color));
++ swfdec_out_put_u8 (out, SWFDEC_COLOR_B (color));
+}
+
+void
+swfdec_out_put_rgba (SwfdecOut *out, SwfdecColor color)
+{
+ g_return_if_fail (out != NULL);
+
- swfdec_out_put_u8 (out, SWF_COLOR_R (color));
- swfdec_out_put_u8 (out, SWF_COLOR_G (color));
- swfdec_out_put_u8 (out, SWF_COLOR_B (color));
- swfdec_out_put_u8 (out, SWF_COLOR_A (color));
++ swfdec_out_put_u8 (out, SWFDEC_COLOR_R (color));
++ swfdec_out_put_u8 (out, SWFDEC_COLOR_G (color));
++ swfdec_out_put_u8 (out, SWFDEC_COLOR_B (color));
++ swfdec_out_put_u8 (out, SWFDEC_COLOR_A (color));
+}
+
diff --cc test/swfedit_token.c
index 8c8b075,0000000..f3f2bcc
mode 100644,000000..100644
@@@ -1,573 -1,0 +1,573 @@@
+/* Swfedit
+ * Copyright (C) 2007 Benjamin Otte <otte at 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, to_string 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 <stdlib.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <libswfdec/swfdec_buffer.h>
+#include <libswfdec/swfdec_color.h>
+#include "swfedit_token.h"
+
+/*** CONVERTERS ***/
+
+static gboolean
+swfedit_parse_hex (const char *s, guint *result)
+{
+ guint byte;
+
+ if (s[0] >= '0' && s[0] <= '9')
+ byte = s[0] - '0';
+ else if (s[0] >= 'a' && s[0] <= 'f')
+ byte = s[0] + 10 - 'a';
+ else if (s[0] >= 'A' && s[0] <= 'F')
+ byte = s[0] + 10 - 'A';
+ else
+ return FALSE;
+ s++;
+ byte *= 16;
+ if (s[0] >= '0' && s[0] <= '9')
+ byte += s[0] - '0';
+ else if (s[0] >= 'a' && s[0] <= 'f')
+ byte += s[0] + 10 - 'a';
+ else if (s[0] >= 'A' && s[0] <= 'F')
+ byte += s[0] + 10 - 'A';
+ else
+ return FALSE;
+ *result = byte;
+ return TRUE;
+}
+
+static gboolean
+swfedit_binary_from_string (const char *s, gpointer* result)
+{
+ GByteArray *array = g_byte_array_new ();
+ guint byte;
+ guint8 add;
+
+ while (g_ascii_isspace (*s)) s++;
+ do {
+ if (!swfedit_parse_hex (s, &byte))
+ break;
+ s += 2;
+ add = byte;
+ g_byte_array_append (array, &add, 1);
+ while (g_ascii_isspace (*s)) s++;
+ } while (*s != '\0');
+ if (*s == '\0') {
+ SwfdecBuffer *buffer = swfdec_buffer_new ();
+ buffer->length = array->len;
+ buffer->data = array->data;
+ g_byte_array_free (array, FALSE);
+ *result = buffer;
+ return TRUE;
+ }
+ g_byte_array_free (array, TRUE);
+ return FALSE;
+}
+
+static char *
+swfedit_binary_to_string (gconstpointer value)
+{
+ guint i;
+ const SwfdecBuffer *buffer = value;
+ GString *string = g_string_new ("");
+
+ for (i = 0; i < buffer->length; i++) {
+ if (i && i % 4 == 0)
+ g_string_append_c (string, ' ');
+ g_string_append_printf (string, "%02X", buffer->data[i]);
+ }
+ return g_string_free (string, FALSE);
+}
+
+static gboolean
+swfedit_from_string_unsigned (const char *s, gulong max, gpointer* result)
+{
+ char *end;
+ gulong u;
+
+ g_assert (max <= G_MAXUINT);
+ u = strtoul (s, &end, 10);
+ if (*end != '\0')
+ return FALSE;
+ if (u > max)
+ return FALSE;
+ *result = GUINT_TO_POINTER (u);
+ return TRUE;
+}
+
+static gboolean
+swfedit_uint8_from_string (const char *s, gpointer* result)
+{
+ return swfedit_from_string_unsigned (s, G_MAXUINT8, result);
+}
+
+static gboolean
+swfedit_uint16_from_string (const char *s, gpointer* result)
+{
+ return swfedit_from_string_unsigned (s, G_MAXUINT16, result);
+}
+
+static gboolean
+swfedit_uint32_from_string (const char *s, gpointer* result)
+{
+ return swfedit_from_string_unsigned (s, G_MAXUINT32, result);
+}
+
+static char *
+swfedit_to_string_unsigned (gconstpointer value)
+{
+ return g_strdup_printf ("%u", GPOINTER_TO_UINT (value));
+}
+
+static gboolean
+swfedit_rect_from_string (const char *s, gpointer* result)
+{
+ return FALSE;
+}
+
+static char *
+swfedit_rect_to_string (gconstpointer value)
+{
+ const SwfdecRect *rect = value;
+
+ return g_strdup_printf ("%d, %d, %d, %d", (int) rect->x0, (int) rect->y0,
+ (int) rect->x1, (int) rect->y1);
+}
+
+static gboolean
+swfedit_rgb_from_string (const char *s, gpointer* result)
+{
+ guint r, g, b;
+ if (strlen (s) != 6)
+ return FALSE;
+ if (!swfedit_parse_hex (s, &r))
+ return FALSE;
+ s += 2;
+ if (!swfedit_parse_hex (s, &g))
+ return FALSE;
+ s += 2;
+ if (!swfedit_parse_hex (s, &b))
+ return FALSE;
- *result = GUINT_TO_POINTER (SWF_COLOR_COMBINE (r, g, b, 0xFF));
++ *result = GUINT_TO_POINTER (SWFDEC_COLOR_COMBINE (r, g, b, 0xFF));
+ return TRUE;
+}
+
+static char *
+swfedit_rgb_to_string (gconstpointer value)
+{
+ guint c = GPOINTER_TO_UINT (value);
+
- return g_strdup_printf ("%02X%02X%02X", SWF_COLOR_R (c),
- SWF_COLOR_G (c), SWF_COLOR_B (c));
++ return g_strdup_printf ("%02X%02X%02X", SWFDEC_COLOR_R (c),
++ SWFDEC_COLOR_G (c), SWFDEC_COLOR_B (c));
+}
+
+static gboolean
+swfedit_rgba_from_string (const char *s, gpointer* result)
+{
+ guint r, g, b, a;
+ if (strlen (s) != 8)
+ return FALSE;
+ if (!swfedit_parse_hex (s, &a))
+ return FALSE;
+ s += 2;
+ if (!swfedit_parse_hex (s, &r))
+ return FALSE;
+ s += 2;
+ if (!swfedit_parse_hex (s, &g))
+ return FALSE;
+ s += 2;
+ if (!swfedit_parse_hex (s, &b))
+ return FALSE;
- *result = GUINT_TO_POINTER (SWF_COLOR_COMBINE (r, g, b, a));
++ *result = GUINT_TO_POINTER (SWFDEC_COLOR_COMBINE (r, g, b, a));
+ return TRUE;
+}
+
+static char *
+swfedit_rgba_to_string (gconstpointer value)
+{
+ guint c = GPOINTER_TO_UINT (value);
+
- return g_strdup_printf ("%02X%02X%02X%02X", SWF_COLOR_R (c),
- SWF_COLOR_G (c), SWF_COLOR_B (c), SWF_COLOR_A (c));
++ return g_strdup_printf ("%02X%02X%02X%02X", SWFDEC_COLOR_R (c),
++ SWFDEC_COLOR_G (c), SWFDEC_COLOR_B (c), SWFDEC_COLOR_A (c));
+}
+
+struct {
+ gboolean (* from_string) (const char *s, gpointer *);
+ char * (* to_string) (gconstpointer value);
+ void (* free) (gpointer value);
+} converters[SWFEDIT_N_TOKENS] = {
+ { NULL, NULL, g_object_unref },
+ { swfedit_binary_from_string, swfedit_binary_to_string, (GDestroyNotify) swfdec_buffer_unref },
+ { swfedit_uint8_from_string, swfedit_to_string_unsigned, NULL },
+ { swfedit_uint16_from_string, swfedit_to_string_unsigned, NULL },
+ { swfedit_uint32_from_string, swfedit_to_string_unsigned, NULL },
+ { swfedit_rect_from_string, swfedit_rect_to_string, g_free },
+ { swfedit_rgb_from_string, swfedit_rgb_to_string, NULL },
+ { swfedit_rgba_from_string, swfedit_rgba_to_string, NULL },
+};
+
+/*** GTK_TREE_MODEL ***/
+
+#if 0
+# define REPORT g_print ("%s\n", G_STRFUNC)
+#else
+# define REPORT
+#endif
+static GtkTreeModelFlags
+swfedit_token_get_flags (GtkTreeModel *tree_model)
+{
+ REPORT;
+ return 0;
+}
+
+static gint
+swfedit_token_get_n_columns (GtkTreeModel *tree_model)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (tree_model);
+
+ REPORT;
+ return token->tokens->len;
+}
+
+static GType
+swfedit_token_get_column_type (GtkTreeModel *tree_model, gint index_)
+{
+ REPORT;
+ switch (index_) {
+ case SWFEDIT_COLUMN_NAME:
+ return G_TYPE_STRING;
+ case SWFEDIT_COLUMN_VALUE_VISIBLE:
+ return G_TYPE_BOOLEAN;
+ case SWFEDIT_COLUMN_VALUE:
+ return G_TYPE_STRING;
+ default:
+ break;
+ }
+ g_assert_not_reached ();
+ return G_TYPE_NONE;
+}
+
+static gboolean
+swfedit_token_get_iter (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (tree_model);
+ guint i = gtk_tree_path_get_indices (path)[0];
+ SwfeditTokenEntry *entry;
+
+ REPORT;
+ if (i > token->tokens->len)
+ return FALSE;
+ entry = &g_array_index (token->tokens, SwfeditTokenEntry, i);
+ if (gtk_tree_path_get_depth (path) > 1) {
+ GtkTreePath *new;
+ int j;
+ int *indices;
+ gboolean ret;
+
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ return FALSE;
+ new = gtk_tree_path_new ();
+ indices = gtk_tree_path_get_indices (path);
+ for (j = 1; j < gtk_tree_path_get_depth (path); j++) {
+ gtk_tree_path_append_index (new, indices[j]);
+ }
+ ret = swfedit_token_get_iter (GTK_TREE_MODEL (entry->value), iter, new);
+ gtk_tree_path_free (new);
+ return ret;
+ } else {
+ iter->stamp = 0; /* FIXME */
+ iter->user_data = token;
+ iter->user_data2 = GINT_TO_POINTER (i);
+ return TRUE;
+ }
+}
+
+static GtkTreePath *
+swfedit_token_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
+ GtkTreePath *path = gtk_tree_path_new_from_indices (GPOINTER_TO_INT (iter->user_data2), -1);
+
+ REPORT;
+ while (token->parent) {
+ guint i;
+ SwfeditToken *parent = token->parent;
+ for (i = 0; i < parent->tokens->len; i++) {
+ SwfeditTokenEntry *entry = &g_array_index (parent->tokens, SwfeditTokenEntry, i);
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ continue;
+ if (entry->value == token)
+ break;
+ }
+ gtk_tree_path_prepend_index (path, i);
+ token = parent;
+ }
+ return path;
+}
+
+static void
+swfedit_token_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter,
+ gint column, GValue *value)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
+ SwfeditTokenEntry *entry = &g_array_index (token->tokens, SwfeditTokenEntry, GPOINTER_TO_INT (iter->user_data2));
+
+ REPORT;
+ switch (column) {
+ case SWFEDIT_COLUMN_NAME:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, entry->name);
+ return;
+ case SWFEDIT_COLUMN_VALUE_VISIBLE:
+ g_value_init (value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (value, converters[entry->type].to_string != NULL);
+ return;
+ case SWFEDIT_COLUMN_VALUE:
+ g_value_init (value, G_TYPE_STRING);
+ if (converters[entry->type].to_string)
+ g_value_take_string (value, converters[entry->type].to_string (entry->value));
+ return;
+ default:
+ break;
+ }
+ g_assert_not_reached ();
+}
+
+static gboolean
+swfedit_token_iter_next (GtkTreeModel *tree_model, GtkTreeIter *iter)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
+
+ REPORT;
+ if ((guint) GPOINTER_TO_INT (iter->user_data2) + 1 >= token->tokens->len)
+ return FALSE;
+
+ iter->user_data2++;
+ return TRUE;
+}
+
+static gboolean
+swfedit_token_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent)
+{
+ SwfeditToken *token;
+ SwfeditTokenEntry *entry;
+
+ REPORT;
+ if (parent) {
+ token = SWFEDIT_TOKEN (parent->user_data);
+ entry = &g_array_index (token->tokens, SwfeditTokenEntry, GPOINTER_TO_INT (parent->user_data2));
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ return FALSE;
+ token = entry->value;
+ } else {
+ token = SWFEDIT_TOKEN (tree_model);
+ }
+ if (token->tokens->len == 0)
+ return FALSE;
+ iter->stamp = 0; /* FIXME */
+ iter->user_data = token;
+ iter->user_data2 = GINT_TO_POINTER (0);
+ return TRUE;
+}
+
+static gboolean
+swfedit_token_iter_has_child (GtkTreeModel *tree_model, GtkTreeIter *iter)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
+ SwfeditTokenEntry *entry = &g_array_index (token->tokens, SwfeditTokenEntry, GPOINTER_TO_INT (iter->user_data2));
+
+ REPORT;
+ return entry->type == SWFEDIT_TOKEN_OBJECT && SWFEDIT_TOKEN (entry->value)->tokens->len > 0;
+}
+
+static gint
+swfedit_token_iter_n_children (GtkTreeModel *tree_model, GtkTreeIter *iter)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
+ SwfeditTokenEntry *entry = &g_array_index (token->tokens, SwfeditTokenEntry, GPOINTER_TO_INT (iter->user_data2));
+
+ REPORT;
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ return 0;
+
+ token = entry->value;
+ return token->tokens->len;
+}
+
+static gboolean
+swfedit_token_iter_nth_child (GtkTreeModel *tree_model, GtkTreeIter *iter,
+ GtkTreeIter *parent, gint n)
+{
+ SwfeditToken *token;
+ SwfeditTokenEntry *entry;
+
+ REPORT;
+ if (parent) {
+ token = SWFEDIT_TOKEN (parent->user_data);
+ entry = &g_array_index (token->tokens, SwfeditTokenEntry, GPOINTER_TO_INT (parent->user_data2));
+
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ return FALSE;
+
+ token = entry->value;
+ } else {
+ token = SWFEDIT_TOKEN (tree_model);
+ }
+ if ((guint) n >= token->tokens->len)
+ return FALSE;
+ iter->stamp = 0; /* FIXME */
+ iter->user_data = token;
+ iter->user_data2 = GINT_TO_POINTER (n);
+ return TRUE;
+}
+
+static gboolean
+swfedit_token_iter_parent (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child)
+{
+ guint i;
+ SwfeditToken *token = SWFEDIT_TOKEN (child->user_data);
+ SwfeditToken *parent = token->parent;
+
+ REPORT;
+ if (parent == NULL)
+ return FALSE;
+
+ for (i = 0; i < parent->tokens->len; i++) {
+ SwfeditTokenEntry *entry = &g_array_index (parent->tokens, SwfeditTokenEntry, i);
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ continue;
+ if (entry->value == token)
+ break;
+ }
+ iter->stamp = 0; /* FIXME */
+ iter->user_data = parent;
+ iter->user_data2 = GINT_TO_POINTER (i);
+ return TRUE;
+}
+
+static void
+swfedit_token_tree_model_init (GtkTreeModelIface *iface)
+{
+ iface->get_flags = swfedit_token_get_flags;
+ iface->get_n_columns = swfedit_token_get_n_columns;
+ iface->get_column_type = swfedit_token_get_column_type;
+ iface->get_iter = swfedit_token_get_iter;
+ iface->get_path = swfedit_token_get_path;
+ iface->get_value = swfedit_token_get_value;
+ iface->iter_next = swfedit_token_iter_next;
+ iface->iter_children = swfedit_token_iter_children;
+ iface->iter_has_child = swfedit_token_iter_has_child;
+ iface->iter_n_children = swfedit_token_iter_n_children;
+ iface->iter_nth_child = swfedit_token_iter_nth_child;
+ iface->iter_parent = swfedit_token_iter_parent;
+}
+
+/*** SWFEDIT_TOKEN ***/
+
+G_DEFINE_TYPE_WITH_CODE (SwfeditToken, swfedit_token, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, swfedit_token_tree_model_init))
+
+static void
+swfedit_token_dispose (GObject *object)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (object);
+ guint i;
+
+ for (i = 0; i < token->tokens->len; i++) {
+ SwfeditTokenEntry *entry = &g_array_index (token->tokens, SwfeditTokenEntry, i);
+ g_free (entry->name);
+ if (converters[entry->type].free)
+ converters[entry->type].free (entry->value);
+ }
+ g_array_free (token->tokens, TRUE);
+
+ G_OBJECT_CLASS (swfedit_token_parent_class)->dispose (object);
+}
+
+static void
+swfedit_token_class_init (SwfeditTokenClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->dispose = swfedit_token_dispose;
+}
+
+static void
+swfedit_token_init (SwfeditToken *token)
+{
+ token->tokens = g_array_new (FALSE, FALSE, sizeof (SwfeditTokenEntry));
+}
+
+SwfeditToken *
+swfedit_token_new (void)
+{
+ SwfeditToken *token;
+
+ token = g_object_new (SWFEDIT_TYPE_TOKEN, NULL);
+ return token;
+}
+
+void
+swfedit_token_add (SwfeditToken *token, const char *name, SwfeditTokenType type, gpointer value)
+{
+ SwfeditTokenEntry entry = { NULL, type, value };
+
+ g_return_if_fail (SWFEDIT_IS_TOKEN (token));
+ g_return_if_fail (name != NULL);
+ g_return_if_fail (type < SWFEDIT_N_TOKENS);
+
+ entry.name = g_strdup (name);
+ g_array_append_val (token->tokens, entry);
+}
+
+void
+swfedit_token_set (SwfeditToken *token, GtkTreeIter *iter, const char *value)
+{
+ GtkTreeModel *model;
+ SwfeditTokenEntry *entry;
+ guint i;
+ gpointer new;
+ GtkTreePath *path;
+
+ g_return_if_fail (SWFEDIT_IS_TOKEN (token));
+ g_return_if_fail (iter != NULL);
+ g_return_if_fail (value != NULL);
+
+ model = GTK_TREE_MODEL (token);
+ token = iter->user_data;
+ i = GPOINTER_TO_UINT (iter->user_data2);
+ entry = &g_array_index (token->tokens, SwfeditTokenEntry, i);
+ if (converters[entry->type].from_string == NULL)
+ return;
+ if (!converters[entry->type].from_string (value, &new))
+ return;
+ if (converters[entry->type].free != NULL)
+ converters[entry->type].free (entry->value);
+ entry->value = new;
+
+ path = gtk_tree_model_get_path (model, iter);
+ gtk_tree_model_row_changed (model, path, iter);
+ gtk_tree_path_free (path);
+}
+
diff-tree 940ef9614313d253bb9282e26f48968b4af13c85 (from 828ab7af700ce3d9b4e44b90c4f7d804b5d243cc)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Feb 2 21:30:02 2007 +0100
missing \n
diff --git a/test/swfdec-extract.c b/test/swfdec-extract.c
index bea068e..ac79124 100644
--- a/test/swfdec-extract.c
+++ b/test/swfdec-extract.c
@@ -259,7 +259,7 @@ main (int argc, char *argv[])
if (!export_graphic (SWFDEC_GRAPHIC (character), argv[3]))
ret = 1;
} else {
- g_printerr ("id %ld does not specify an exportable object", id);
+ g_printerr ("id %ld does not specify an exportable object\n", id);
ret = 1;
}
diff-tree 828ab7af700ce3d9b4e44b90c4f7d804b5d243cc (from parents)
Merge: 94e07c556a4e4f471f6700af54f35e55edf79a85 12bf86eb10e873ca735fad310d7ab9e517f6662b
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Feb 2 19:00:13 2007 +0100
Merge branch 'master' into interpreter
diff-tree 94e07c556a4e4f471f6700af54f35e55edf79a85 (from 18aff9069e571bda0bf49290c7ad415597d1d16e)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 16:11:16 2007 +0100
implement WaitForFrame2
videostar.swf works now
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 39b3b8b..c416f64 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -267,6 +267,27 @@ swfdec_action_goto_label (JSContext *cx,
return JS_TRUE;
}
+static int
+swfdec_value_to_frame (JSContext *cx, SwfdecMovie *movie, jsval val)
+{
+ int frame;
+
+ if (JSVAL_IS_STRING (val)) {
+ const char *name = swfdec_js_to_string (cx, val);
+ if (name == NULL ||
+ !SWFDEC_IS_SPRITE_MOVIE (movie))
+ return -1;
+ if (strchr (name, ':')) {
+ SWFDEC_ERROR ("FIXME: handle targets");
+ }
+ frame = swfdec_sprite_get_frame (SWFDEC_SPRITE_MOVIE (movie)->sprite, name);
+ } else {
+ /* FIXME: how do we treat undefined etc? */
+ frame = swfdec_action_to_number (cx, val);
+ }
+ return frame;
+}
+
static JSBool
swfdec_action_goto_frame2 (JSContext *cx, guint action, const guint8 *data, guint len)
{
@@ -274,7 +295,6 @@ swfdec_action_goto_frame2 (JSContext *cx
guint bias;
gboolean play;
jsval val;
- int frame;
SwfdecMovie *movie;
swfdec_bits_init_data (&bits, data, len);
@@ -288,24 +308,13 @@ swfdec_action_goto_frame2 (JSContext *cx
}
val = cx->fp->sp[-1];
cx->fp->sp--;
- if (JSVAL_IS_STRING (val)) {
- const char *name = swfdec_js_to_string (cx, val);
- if (name == NULL)
- return JS_FALSE;
- if (strchr (name, ':')) {
- SWFDEC_ERROR ("FIXME: handle targets");
- }
- frame = swfdec_sprite_get_frame (SWFDEC_SPRITE_MOVIE (movie)->sprite, name);
- if (frame == -1)
- return JS_TRUE;
- } else {
- /* FIXME: how do we treat undefined etc? */
- frame = swfdec_action_to_number (cx, val);
- }
- frame += bias;
- /* now set it */
movie = swfdec_action_get_target (cx);
+ /* now set it */
if (movie) {
+ int frame = swfdec_value_to_frame (cx, movie, val);
+ if (frame < 0)
+ return JS_TRUE;
+ frame += bias;
frame = CLAMP (frame, 0, (int) movie->n_frames - 1);
swfdec_movie_goto (movie, frame);
movie->stopped = !play;
@@ -315,6 +324,63 @@ swfdec_action_goto_frame2 (JSContext *cx
return JS_TRUE;
}
+static void
+swfdec_script_skip_actions (JSContext *cx, guint jump)
+{
+ SwfdecScript *script = cx->fp->swf;
+ guint8 *pc = cx->fp->pc;
+ guint8 *endpc = script->buffer->data + script->buffer->length;
+
+ /* jump instructions */
+ g_assert (script);
+ do {
+ if (pc >= endpc)
+ break;
+ if (*pc & 0x80) {
+ if (pc + 2 >= endpc)
+ break;
+ pc += 3 + GUINT16_FROM_LE (*((guint16 *) (pc + 1)));
+ } else {
+ pc++;
+ }
+ } while (jump-- > 0);
+ cx->fp->pc = pc;
+}
+
+static JSBool
+swfdec_action_wait_for_frame2 (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ jsval val;
+ SwfdecMovie *movie;
+
+ if (len != 1) {
+ SWFDEC_ERROR ("WaitForFrame2 needs a 1-byte data");
+ return JS_FALSE;
+ }
+ val = cx->fp->sp[-1];
+ cx->fp->sp--;
+ movie = swfdec_action_get_target (cx);
+ if (movie) {
+ int frame = swfdec_value_to_frame (cx, movie, val);
+ guint jump = data[2];
+ guint loaded;
+ if (frame < 0)
+ return JS_TRUE;
+ if (SWFDEC_IS_ROOT_MOVIE (movie)) {
+ SwfdecDecoder *dec = SWFDEC_ROOT_MOVIE (movie)->decoder;
+ loaded = dec->frames_loaded;
+ g_assert (loaded <= movie->n_frames);
+ } else {
+ loaded = movie->n_frames;
+ }
+ if (loaded < (guint) frame)
+ swfdec_script_skip_actions (cx, jump);
+ } else {
+ SWFDEC_ERROR ("no movie to WaitForFrame2 on");
+ }
+ return JS_TRUE;
+}
+
static JSBool
swfdec_action_wait_for_frame (JSContext *cx, guint action, const guint8 *data, guint len)
{
@@ -333,32 +399,14 @@ swfdec_action_wait_for_frame (JSContext
frame = GUINT16_FROM_LE (*((guint16 *) data));
jump = data[2];
if (SWFDEC_IS_ROOT_MOVIE (movie)) {
- SwfdecDecoder *dec = SWFDEC_ROOT_MOVIE (movie->root)->decoder;
+ SwfdecDecoder *dec = SWFDEC_ROOT_MOVIE (movie)->decoder;
loaded = dec->frames_loaded;
g_assert (loaded <= movie->n_frames);
} else {
loaded = movie->n_frames;
}
- if (loaded < frame) {
- SwfdecScript *script = cx->fp->swf;
- guint8 *pc = cx->fp->pc;
- guint8 *endpc = script->buffer->data + script->buffer->length;
-
- /* jump instructions */
- g_assert (script);
- do {
- if (pc >= endpc)
- break;
- if (*pc & 0x80) {
- if (pc + 2 >= endpc)
- break;
- pc += 3 + GUINT16_FROM_LE (*((guint16 *) (pc + 1)));
- } else {
- pc++;
- }
- } while (jump-- > 0);
- cx->fp->pc = pc;
- }
+ if (loaded < frame)
+ swfdec_script_skip_actions (cx, jump);
return JS_TRUE;
}
@@ -1693,6 +1741,16 @@ swfdec_action_print_constant_pool (guint
}
static char *
+swfdec_action_print_wait_for_frame2 (guint action, const guint8 *data, guint len)
+{
+ if (len != 1) {
+ SWFDEC_ERROR ("WaitForFrame2 needs a 1-byte data");
+ return NULL;
+ }
+ return g_strdup_printf ("WaitForFrame2 %u", (guint) *data);
+}
+
+static char *
swfdec_action_print_goto_frame2 (guint action, const guint8 *data, guint len)
{
gboolean play, bias;
@@ -1868,7 +1926,7 @@ static const SwfdecActionSpec actions[25
[0x8b] = { "SetTarget", swfdec_action_print_set_target, 0, 0, { swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target } },
[0x8c] = { "GotoLabel", swfdec_action_print_goto_label, 0, 0, { swfdec_action_goto_label, swfdec_action_goto_label, swfdec_action_goto_label, swfdec_action_goto_label, swfdec_action_goto_label } },
/* version 4 */
- [0x8d] = { "WaitForFrame2", NULL },
+ [0x8d] = { "WaitForFrame2", swfdec_action_print_wait_for_frame2, 1, 0, { NULL, swfdec_action_wait_for_frame2, swfdec_action_wait_for_frame2, swfdec_action_wait_for_frame2, swfdec_action_wait_for_frame2 } },
/* version 7 */
[0x8e] = { "DefineFunction2", NULL },
[0x8f] = { "Try", NULL },
diff-tree 18aff9069e571bda0bf49290c7ad415597d1d16e (from 81d2a042d8772f2837e088c2fba410ea9b0df082)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 14:38:22 2007 +0100
add another test that resulted from trying various stuff
diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index a5d85ea..d931702 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -76,6 +76,8 @@ EXTRA_DIST = \
name2.swf.trace \
names.swf \
names.swf.trace \
+ number.swf \
+ number.swf.trace \
object-math-5.swf \
object-math-5.swf.trace \
object-math-6.swf \
diff --git a/test/trace/number.swf b/test/trace/number.swf
new file mode 100755
index 0000000..bf729ef
Binary files /dev/null and b/test/trace/number.swf differ
diff --git a/test/trace/number.swf.trace b/test/trace/number.swf.trace
new file mode 100755
index 0000000..de6a5e2
--- /dev/null
+++ b/test/trace/number.swf.trace
@@ -0,0 +1,9 @@
+Check various things with Number class and prototypes
+[type Function]
+[type Object]
+[type Function]
+NaN
+42
+1234
+4
+undefined
diff-tree 81d2a042d8772f2837e088c2fba410ea9b0df082 (from b6dcac3542c5de3b38b7505ea44be99c95b50de9)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 14:37:13 2007 +0100
various fixes for tests
- apparently all objects evaluate to NaN in Flash 7
- handle error case ValueToObject == NULL in CallMethod
- walk the whole scope chain in CallFunction when trying to find the function
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index ad08eef..39b3b8b 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -161,7 +161,7 @@ swfdec_action_to_number (JSContext *cx,
static JSBool
swfdec_value_to_number_7 (JSContext *cx, jsval val, double *d)
{
- if (JSVAL_IS_NULL (val)) {
+ if (JSVAL_IS_OBJECT (val)) {
*d = *cx->runtime->jsNaN;
return JS_TRUE;
} else {
@@ -550,8 +550,10 @@ swfdec_action_call_function (JSContext *
JSStackFrame *fp = cx->fp;
const char *s;
guint32 n_args;
- JSObject *obj;
+ JSObject *obj, *pobj;
+ JSProperty *prop;
jsval fun;
+ JSAtom *atom;
s = swfdec_js_to_string (cx, fp->sp[-1]);
if (s == NULL)
@@ -561,7 +563,9 @@ swfdec_action_call_function (JSContext *
if (n_args + 2 > (guint) (fp->sp - fp->spbase))
return JS_FALSE;
- obj = OBJ_THIS_OBJECT (cx, cx->fp->scopeChain);
+ if (!(atom = js_Atomize (cx, s, strlen (s), 0)) ||
+ !js_FindProperty (cx, (jsid) atom, &obj, &pobj, &prop))
+ return JS_FALSE;
if (!JS_GetProperty (cx, obj, s, &fun))
return JS_FALSE;
fp->sp[-1] = fun;
@@ -589,6 +593,8 @@ swfdec_action_call_method (JSContext *cx
if (!JS_ValueToObject (cx, fp->sp[-2], &obj))
return JS_FALSE;
+ if (obj == NULL)
+ goto fail;
if (s[0] == '\0') {
fun = OBJECT_TO_JSVAL (obj);
} else {
@@ -600,6 +606,11 @@ swfdec_action_call_method (JSContext *cx
fp->sp[-2] = OBJECT_TO_JSVAL (obj);
swfdec_action_call (cx, n_args, 0);
return JS_TRUE;
+
+fail:
+ fp->sp -= 2 + n_args;
+ fp->sp[-1] = JSVAL_VOID;
+ return JS_TRUE;
}
static JSBool
diff-tree b6dcac3542c5de3b38b7505ea44be99c95b50de9 (from c806924bb1038dd655fef7d2ede3dad8d61dffe6)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 14:30:42 2007 +0100
toString is supposed to output [type Object] for numbers
diff --git a/libswfdec/js/jsnum.c b/libswfdec/js/jsnum.c
index 1e92a7a..d9063f4 100644
--- a/libswfdec/js/jsnum.c
+++ b/libswfdec/js/jsnum.c
@@ -249,6 +249,15 @@ IntToString(jsint i, char *buf, size_t b
static JSBool
num_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
+ JSString *string;
+
+ string = JS_InternString (cx, "[type Object]");
+ if (string == NULL)
+ return JS_FALSE;
+
+ *rval = STRING_TO_JSVAL (string);
+ return JS_TRUE;
+#if 0
jsval v;
jsdouble d;
jsint base;
@@ -286,6 +295,7 @@ num_toString(JSContext *cx, JSObject *ob
return JS_FALSE;
*rval = STRING_TO_JSVAL(str);
return JS_TRUE;
+#endif
}
static JSBool
diff-tree c806924bb1038dd655fef7d2ede3dad8d61dffe6 (from dad7fc07302b9f0b6a13ce837e5ef997d95e75c2)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 13:13:15 2007 +0100
add test for mathematical operations + - * / on objects
diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 27f0cac..a5d85ea 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -76,6 +76,12 @@ EXTRA_DIST = \
name2.swf.trace \
names.swf \
names.swf.trace \
+ object-math-5.swf \
+ object-math-5.swf.trace \
+ object-math-6.swf \
+ object-math-6.swf.trace \
+ object-math-7.swf \
+ object-math-7.swf.trace \
order.swf \
order.swf.trace \
rotation-5.swf \
diff --git a/test/trace/object-math-5.swf b/test/trace/object-math-5.swf
new file mode 100755
index 0000000..7ceac67
Binary files /dev/null and b/test/trace/object-math-5.swf differ
diff --git a/test/trace/object-math-5.swf.trace b/test/trace/object-math-5.swf.trace
new file mode 100755
index 0000000..03b77fa
--- /dev/null
+++ b/test/trace/object-math-5.swf.trace
@@ -0,0 +1,17 @@
+Check mathematical operations with objects in Flash 5
+2
+2
+2
+2
+2
+-2
+-2
+2
+0
+0
+0
+0
+Infinity
+0
+0
+Infinity
diff --git a/test/trace/object-math-6.swf b/test/trace/object-math-6.swf
new file mode 100755
index 0000000..5f98f7c
Binary files /dev/null and b/test/trace/object-math-6.swf differ
diff --git a/test/trace/object-math-6.swf.trace b/test/trace/object-math-6.swf.trace
new file mode 100755
index 0000000..87fc74d
--- /dev/null
+++ b/test/trace/object-math-6.swf.trace
@@ -0,0 +1,17 @@
+Check mathematical operations with objects in Flash 6
+NaN
+NaN
+2
+2
+NaN
+NaN
+-2
+2
+NaN
+NaN
+0
+0
+Infinity
+NaN
+0
+Infinity
diff --git a/test/trace/object-math-7.swf b/test/trace/object-math-7.swf
new file mode 100755
index 0000000..9d9392a
Binary files /dev/null and b/test/trace/object-math-7.swf differ
diff --git a/test/trace/object-math-7.swf.trace b/test/trace/object-math-7.swf.trace
new file mode 100755
index 0000000..751247d
--- /dev/null
+++ b/test/trace/object-math-7.swf.trace
@@ -0,0 +1,17 @@
+Check mathematical operations with objects in Flash 7
+NaN
+NaN
+NaN
+NaN
+NaN
+NaN
+NaN
+NaN
+NaN
+NaN
+NaN
+NaN
+Infinity
+NaN
+NaN
+Infinity
diff-tree dad7fc07302b9f0b6a13ce837e5ef997d95e75c2 (from 1677a15cf65bf31fffa806f5e56c5b61e6ae4ffa)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 12:49:46 2007 +0100
fix object to number conversions in Flash 6
Flash <=5 converts all objects to 0
Flash 6 converts non-null objects to NaN and null objects to 0
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index d79a3d1..ad08eef 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -151,6 +151,8 @@ swfdec_action_to_number (JSContext *cx,
if (!JS_ValueToNumber (cx, val, &d))
return 0;
return isnan (d) ? 0 : d;
+ } else if (JSVAL_IS_OBJECT(val) && (((SwfdecScript *) cx->fp->swf)->version >= 6)) {
+ return JSVAL_IS_NULL (val) ? 0 : *cx->runtime->jsNaN;
} else {
return 0;
}
@@ -727,6 +729,8 @@ swfdec_action_binary (JSContext *cx, gui
l = l * r;
break;
case 0x0d:
+ if (isnan (r))
+ r = 0;
if (r == 0 && ((SwfdecScript *) cx->fp->swf)->version < 5) {
JSString *str = JS_InternString (cx, "#ERROR#");
if (str == NULL)
@@ -734,7 +738,7 @@ swfdec_action_binary (JSContext *cx, gui
cx->fp->sp[-1] = STRING_TO_JSVAL (str);
return JS_TRUE;
} else if (((SwfdecScript *) cx->fp->swf)->version >= 7 &&
- (r == 0 || isnan (r))) {
+ r == 0) {
cx->fp->sp[-1] = DOUBLE_TO_JSVAL (r < 0 ?
cx->runtime->jsNegativeInfinity :
cx->runtime->jsPositiveInfinity);
diff-tree 1677a15cf65bf31fffa806f5e56c5b61e6ae4ffa (from f7160413607ea6b82e876fb453c1c4303d3479d5)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 12:29:09 2007 +0100
fix to_number conversions for null in Flash 7
Flash 7 seems to treat null as NaN as opposed to SpiderMonkey, where null is 0.
This patch fixes mathematical operations to do this correctly.
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 4c0b163..d79a3d1 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -156,6 +156,17 @@ swfdec_action_to_number (JSContext *cx,
}
}
+static JSBool
+swfdec_value_to_number_7 (JSContext *cx, jsval val, double *d)
+{
+ if (JSVAL_IS_NULL (val)) {
+ *d = *cx->runtime->jsNaN;
+ return JS_TRUE;
+ } else {
+ return JS_ValueToNumber (cx, val, d);
+ }
+}
+
/*** ALL THE ACTION IS HERE ***/
static JSBool
@@ -700,8 +711,8 @@ swfdec_action_binary (JSContext *cx, gui
l = swfdec_action_to_number (cx, lval);
r = swfdec_action_to_number (cx, rval);
} else {
- if (!JS_ValueToNumber(cx, lval, &l) ||
- !JS_ValueToNumber(cx, rval, &r))
+ if (!swfdec_value_to_number_7 (cx, lval, &l) ||
+ !swfdec_value_to_number_7 (cx, rval, &r))
return JS_FALSE;
}
cx->fp->sp--;
@@ -722,9 +733,8 @@ swfdec_action_binary (JSContext *cx, gui
return JS_FALSE;
cx->fp->sp[-1] = STRING_TO_JSVAL (str);
return JS_TRUE;
- }
- if (((SwfdecScript *) cx->fp->swf)->version >= 7 &&
- JSVAL_IS_VOID (rval)) {
+ } else if (((SwfdecScript *) cx->fp->swf)->version >= 7 &&
+ (r == 0 || isnan (r))) {
cx->fp->sp[-1] = DOUBLE_TO_JSVAL (r < 0 ?
cx->runtime->jsNegativeInfinity :
cx->runtime->jsPositiveInfinity);
@@ -790,14 +800,6 @@ swfdec_action_add2_7 (JSContext *cx, gui
rval = cx->fp->sp[-1];
lval = cx->fp->sp[-2];
- if (!JSVAL_IS_PRIMITIVE (rval)) {
- if (!OBJ_DEFAULT_VALUE (cx, JSVAL_TO_OBJECT (rval), 0 , &rval))
- return JS_FALSE;
- }
- if (!JSVAL_IS_PRIMITIVE (lval)) {
- if (!OBJ_DEFAULT_VALUE (cx, JSVAL_TO_OBJECT (lval), 0 , &lval))
- return JS_FALSE;
- }
if ((cond = JSVAL_IS_STRING (lval)) || JSVAL_IS_STRING (rval)) {
JSString *str, *str2;
if (cond) {
@@ -816,8 +818,8 @@ swfdec_action_add2_7 (JSContext *cx, gui
cx->fp->sp[-1] = STRING_TO_JSVAL (str);
} else {
double d, d2;
- if (!JS_ValueToNumber(cx, lval, &d) ||
- !JS_ValueToNumber(cx, rval, &d2))
+ if (!swfdec_value_to_number_7 (cx, lval, &d) ||
+ !swfdec_value_to_number_7 (cx, rval, &d2))
return JS_FALSE;
d += d2;
cx->fp->sp--;
diff-tree f7160413607ea6b82e876fb453c1c4303d3479d5 (from ecffa559b35162ca6e2cb8bc20fe9f2ee7c43ba6)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 11:35:42 2007 +0100
allow calling functions on numbers and strings by converting them to proper objects
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 85e6f7c..4c0b163 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -574,9 +574,8 @@ swfdec_action_call_method (JSContext *cx
if (n_args + 3 > (guint) (fp->sp - fp->spbase))
return JS_FALSE;
- if (!JSVAL_IS_OBJECT (fp->sp[-2]) || JSVAL_IS_NULL (fp->sp[-2]))
- goto fail;
- obj = JSVAL_TO_OBJECT (fp->sp[-2]);
+ if (!JS_ValueToObject (cx, fp->sp[-2], &obj))
+ return JS_FALSE;
if (s[0] == '\0') {
fun = OBJECT_TO_JSVAL (obj);
} else {
@@ -588,11 +587,6 @@ swfdec_action_call_method (JSContext *cx
fp->sp[-2] = OBJECT_TO_JSVAL (obj);
swfdec_action_call (cx, n_args, 0);
return JS_TRUE;
-
-fail:
- fp->sp -= 2 + n_args;
- fp->sp[-1] = JSVAL_VOID;
- return JS_TRUE;
}
static JSBool
diff-tree ecffa559b35162ca6e2cb8bc20fe9f2ee7c43ba6 (from 320efb52606b8b376880b9c3bc222a1f9810896a)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Feb 1 11:35:08 2007 +0100
add a column for the type of the object on the stack
diff --git a/player/swfdec_debug_stack.c b/player/swfdec_debug_stack.c
index 2eef4ed..5b25626 100644
--- a/player/swfdec_debug_stack.c
+++ b/player/swfdec_debug_stack.c
@@ -30,17 +30,37 @@ G_DEFINE_TYPE (SwfdecDebugStack, swfdec_
enum {
COLUMN_LINE,
+ COLUMN_TYPE,
COLUMN_CONTENT,
N_COLUMNS
};
+static const char *
+swfdec_get_jsval_type (JSContext *cx, jsval val)
+{
+ if (JSVAL_IS_VOID (val))
+ return "undefined";
+ if (JSVAL_IS_NULL (val))
+ return "null";
+ if (JSVAL_IS_INT (val))
+ return "Integer";
+ if (JSVAL_IS_DOUBLE (val))
+ return "Double";
+ if (JSVAL_IS_BOOLEAN (val))
+ return "Boolean";
+ if (JSVAL_IS_STRING (val))
+ return "String";
+ g_assert (JSVAL_IS_OBJECT (val));
+ return "Object";
+}
+
static void
swfdec_debug_stack_set_model (SwfdecDebugStack *debug)
{
JSStackFrame *frame = NULL;
guint i, min, max;
GtkListStore *store = gtk_list_store_new (N_COLUMNS, G_TYPE_UINT,
- G_TYPE_STRING);
+ G_TYPE_STRING, G_TYPE_STRING);
GtkTreeIter iter;
JS_FrameIterator (debug->manager->player->jscx, &frame);
@@ -49,7 +69,9 @@ swfdec_debug_stack_set_model (SwfdecDebu
for (i = min; i <= max; i++) {
const char *s = swfdec_js_to_string (debug->manager->player->jscx, frame->sp[-i]);
gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter, COLUMN_LINE, i, COLUMN_CONTENT, s, -1);
+ gtk_list_store_set (store, &iter, COLUMN_LINE, i,
+ COLUMN_TYPE, swfdec_get_jsval_type (debug->manager->player->jscx, frame->sp[-i]),
+ COLUMN_CONTENT, s, -1);
}
gtk_tree_view_set_model (GTK_TREE_VIEW (debug), GTK_TREE_MODEL (store));
@@ -119,6 +141,13 @@ swfdec_debug_stack_add_columns (GtkTreeV
gtk_tree_view_append_column (treeview, column);
renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Type", renderer,
+ "text", COLUMN_TYPE, NULL);
+ gtk_tree_view_column_set_sort_column_id (column, COLUMN_TYPE);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_append_column (treeview, column);
+
+ renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Content", renderer,
"text", COLUMN_CONTENT, NULL);
gtk_tree_view_column_set_sort_column_id (column, COLUMN_CONTENT);
diff-tree 320efb52606b8b376880b9c3bc222a1f9810896a (from ae64862c94f18618313c90c28b4071d84693b7b5)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 31 23:33:40 2007 +0100
implement ConstantPool inheritance for DefineFunction
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 46ba618..85e6f7c 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -97,6 +97,26 @@ swfdec_constant_pool_free (SwfdecConstan
g_ptr_array_free (pool, TRUE);
}
+/* FIXME: this is a bit hacky */
+static SwfdecBuffer *
+swfdec_constant_pool_get_area (SwfdecScript *script, SwfdecConstantPool *pool)
+{
+ guint8 *start;
+ SwfdecBuffer *buffer;
+ guint len;
+
+ if (pool->len == 0)
+ return NULL;
+ start = (guint8 *) g_ptr_array_index (pool, 0) - 5;
+ buffer = script->buffer;
+ g_assert (start >= buffer->data);
+ g_assert (start + 3 < buffer->data + buffer->length);
+ g_assert (*start == 0x88);
+ len = 3 + (start[1] | start[2] << 8);
+ g_assert (start + len < buffer->data + buffer->length);
+ return swfdec_buffer_new_subbuffer (buffer, start - buffer->data, len);
+}
+
/*** SUPPORT FUNCTIONS ***/
static SwfdecMovie *
@@ -1334,6 +1354,10 @@ swfdec_action_define_function (JSContext
&bits, *function_name ? function_name : "<lambda>",
((SwfdecScript *) cx->fp->swf)->version);
swfdec_buffer_unref (buffer);
+ if (cx->fp->constant_pool) {
+ script->constant_pool = swfdec_constant_pool_get_area (cx->fp->swf,
+ cx->fp->constant_pool);
+ }
}
if (script == NULL) {
SWFDEC_ERROR ("failed to create script");
@@ -1638,6 +1662,7 @@ swfdec_action_print_push (guint action,
return g_string_free (string, FALSE);
}
+/* NB: constant pool actions are special in that they are called at init time */
static char *
swfdec_action_print_constant_pool (guint action, const guint8 *data, guint len)
{
@@ -2010,6 +2035,8 @@ swfdec_script_unref (SwfdecScript *scrip
return;
swfdec_buffer_unref (script->buffer);
+ if (script->constant_pool)
+ swfdec_buffer_unref (script->constant_pool);
g_free (script->name);
g_free (script);
}
@@ -2068,6 +2095,16 @@ swfdec_script_interpret (SwfdecScript *s
ok = JS_FALSE;
goto out;
}
+ /* initialize the constant pool */
+ if (script->constant_pool) {
+ spec = actions + 0x88;
+ ok = spec->exec[version] (cx, 0x88, script->constant_pool->data + 3,
+ script->constant_pool->length - 3);
+ if (!ok) {
+ SWFDEC_WARNING ("Constant pool initialization failed");
+ goto out;
+ }
+ }
while (TRUE) {
/* check pc */
diff --git a/libswfdec/swfdec_script.h b/libswfdec/swfdec_script.h
index 1cea4a7..e202aa0 100644
--- a/libswfdec/swfdec_script.h
+++ b/libswfdec/swfdec_script.h
@@ -39,6 +39,8 @@ struct _SwfdecScript {
char * name; /* name identifying this script */
unsigned int version; /* version of the script */
gpointer debugger; /* debugger owning us or NULL */
+ /* needed by functions */
+ SwfdecBuffer * constant_pool; /* constant pool action */
};
SwfdecScript * swfdec_script_new (SwfdecBits * bits,
diff-tree ae64862c94f18618313c90c28b4071d84693b7b5 (from 71b090ccdeedb1e96b2f8590844844139b00bd85)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 31 21:35:50 2007 +0100
implement BitAnd, BitOr, BitXor, DefineLocal, DefineLocal2 and Return
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 9b3a328..46ba618 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -1359,6 +1359,35 @@ swfdec_action_define_function (JSContext
}
static JSBool
+swfdec_action_bitwise (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ guint32 a, b;
+ double d;
+
+ if (!JS_ValueToECMAUint32 (cx, cx->fp->sp[-1], &a) ||
+ !JS_ValueToECMAUint32 (cx, cx->fp->sp[-2], &b))
+ return JS_FALSE;
+
+ switch (action) {
+ case 0x60:
+ d = (int) (a & b);
+ break;
+ case 0x61:
+ d = (int) (a | b);
+ break;
+ case 0x62:
+ d = (int) (a ^ b);
+ break;
+ default:
+ g_assert_not_reached ();
+ return JS_FALSE;
+ }
+
+ cx->fp->sp--;
+ return JS_NewNumberValue (cx, d, &cx->fp->sp[-1]);
+}
+
+static JSBool
swfdec_action_shift (JSContext *cx, guint action, const guint8 *data, guint len)
{
guint32 amount, value;
@@ -1414,6 +1443,54 @@ swfdec_action_target_path (JSContext *cx
return JS_TRUE;
}
+static JSBool
+swfdec_action_define_local (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ const char *name;
+
+ if (cx->fp->callobj == NULL) {
+ SWFDEC_ERROR ("FIXME: no local scope");
+ return JS_FALSE;
+ }
+ name = swfdec_js_to_string (cx, cx->fp->sp[-2]);
+ if (name == NULL)
+ return JS_FALSE;
+ if (!JS_SetProperty (cx, cx->fp->callobj, name, &cx->fp->sp[-1]))
+ return JS_FALSE;
+ cx->fp->sp -= 2;
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_define_local2 (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ const char *name;
+ jsval val = JSVAL_VOID;
+
+ if (cx->fp->callobj == NULL) {
+ SWFDEC_ERROR ("FIXME: no local scope");
+ return JS_FALSE;
+ }
+ name = swfdec_js_to_string (cx, cx->fp->sp[-1]);
+ if (name == NULL)
+ return JS_FALSE;
+ if (!JS_SetProperty (cx, cx->fp->callobj, name, &val))
+ return JS_FALSE;
+ cx->fp->sp--;
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_return (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ SwfdecScript *script = cx->fp->swf;
+
+ cx->fp->rval = cx->fp->sp[-1];
+ cx->fp->pc = script->buffer->data + script->buffer->length;
+ cx->fp->sp--;
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -1703,12 +1780,12 @@ static const SwfdecActionSpec actions[25
/* version 5 */
[0x3a] = { "Delete", NULL },
[0x3b] = { "Delete2", NULL },
- [0x3c] = { "DefineLocal", NULL }, //, 2, 0, { NULL, NULL, swfdec_action_define_local, swfdec_action_define_local, swfdec_action_define_local } },
+ [0x3c] = { "DefineLocal", NULL, 2, 0, { NULL, NULL, swfdec_action_define_local, swfdec_action_define_local, swfdec_action_define_local } },
[0x3d] = { "CallFunction", NULL, -1, 1, { NULL, NULL, swfdec_action_call_function, swfdec_action_call_function, swfdec_action_call_function } },
- [0x3e] = { "Return", NULL },
+ [0x3e] = { "Return", NULL, 1, 0, { NULL, NULL, swfdec_action_return, swfdec_action_return, swfdec_action_return } },
[0x3f] = { "Modulo", NULL },
[0x40] = { "NewObject", NULL, -1, 1, { NULL, NULL, swfdec_action_new_object, swfdec_action_new_object, swfdec_action_new_object } },
- [0x41] = { "DefineLocal2", NULL },
+ [0x41] = { "DefineLocal2", NULL, 1, 0, { NULL, NULL, swfdec_action_define_local2, swfdec_action_define_local2, swfdec_action_define_local2 } },
[0x42] = { "InitArray", NULL },
[0x43] = { "InitObject", NULL, -1, 1, { NULL, NULL, swfdec_action_init_object, swfdec_action_init_object, swfdec_action_init_object } },
[0x44] = { "Typeof", NULL },
@@ -1731,9 +1808,9 @@ static const SwfdecActionSpec actions[25
[0x54] = { "InstanceOf", NULL },
[0x55] = { "Enumerate2", NULL },
/* version 5 */
- [0x60] = { "BitAnd", NULL },
- [0x61] = { "BitOr", NULL },
- [0x62] = { "BitXor", NULL },
+ [0x60] = { "BitAnd", NULL, 2, 1, { NULL, NULL, swfdec_action_bitwise, swfdec_action_bitwise, swfdec_action_bitwise } },
+ [0x61] = { "BitOr", NULL, 2, 1, { NULL, NULL, swfdec_action_bitwise, swfdec_action_bitwise, swfdec_action_bitwise } },
+ [0x62] = { "BitXor", NULL, 2, 1, { NULL, NULL, swfdec_action_bitwise, swfdec_action_bitwise, swfdec_action_bitwise } },
[0x63] = { "BitLShift", NULL, 2, 1, { NULL, NULL, swfdec_action_shift, swfdec_action_shift, swfdec_action_shift } },
[0x64] = { "BitRShift", NULL, 2, 1, { NULL, NULL, swfdec_action_shift, swfdec_action_shift, swfdec_action_shift } },
[0x65] = { "BitURShift", NULL, 2, 1, { NULL, NULL, swfdec_action_shift, swfdec_action_shift, swfdec_action_shift } },
@@ -1994,8 +2071,11 @@ swfdec_script_interpret (SwfdecScript *s
while (TRUE) {
/* check pc */
- if (pc == endpc) /* needed for scripts created via DefineFunction */
+ if (pc == endpc) {
+ /* scripts created via DefineFunction or the Return action use this way out */
+ *rval = fp->rval;
break;
+ }
if (pc < startpc || pc >= endpc) {
SWFDEC_ERROR ("pc %p not in valid range [%p, %p) anymore", pc, startpc, endpc);
goto internal_error;
diff-tree 71b090ccdeedb1e96b2f8590844844139b00bd85 (from fa4f57c436b5f6232efacfa2b4ac94d14af1f409)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 31 19:59:15 2007 +0100
initialize the constant pool as empty
diff --git a/libswfdec/js/jsinterp.c b/libswfdec/js/jsinterp.c
index ce8d014..910087a 100644
--- a/libswfdec/js/jsinterp.c
+++ b/libswfdec/js/jsinterp.c
@@ -847,6 +847,7 @@ have_fun:
frame.sharpArray = NULL;
frame.dormantNext = NULL;
frame.objAtomMap = NULL;
+ frame.constant_pool = NULL;
/* Compute the 'this' parameter and store it in frame as frame.thisp. */
ok = ComputeThis(cx, thisp, &frame);
@@ -1140,6 +1141,7 @@ js_Execute(JSContext *cx, JSObject *chai
frame.flags = special;
frame.dormantNext = NULL;
frame.objAtomMap = NULL;
+ frame.constant_pool = NULL;
/*
* Here we wrap the call to js_Interpret with code to (conditionally)
diff-tree fa4f57c436b5f6232efacfa2b4ac94d14af1f409 (from 9335e136a9a1f2f3dbbbda7a7b156b55d94e7c4c)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 31 17:28:14 2007 +0100
implement Equals
This is the last action that the compiler had implemented and this branch hadn't
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 7c24b10..9b3a328 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -1019,7 +1019,7 @@ swfdec_action_random_number (JSContext *
}
static JSBool
-swfdec_action_less (JSContext *cx, guint action, const guint8 *data, guint len)
+swfdec_action_old_compare (JSContext *cx, guint action, const guint8 *data, guint len)
{
jsval rval, lval;
double l, r;
@@ -1029,7 +1029,17 @@ swfdec_action_less (JSContext *cx, guint
lval = cx->fp->sp[-2];
l = swfdec_action_to_number (cx, lval);
r = swfdec_action_to_number (cx, rval);
- cond = l < r;
+ switch (action) {
+ case 0x0e:
+ cond = l == r;
+ break;
+ case 0x0f:
+ cond = l < r;
+ break;
+ default:
+ g_assert_not_reached ();
+ return JS_FALSE;
+ }
cx->fp->sp--;
if (((SwfdecScript *) cx->fp->swf)->version < 5) {
cx->fp->sp[-1] = INT_TO_JSVAL (cond ? 1 : 0);
@@ -1655,8 +1665,8 @@ static const SwfdecActionSpec actions[25
[0x0b] = { "Subtract", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
[0x0c] = { "Multiply", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
[0x0d] = { "Divide", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
- [0x0e] = { "Equals", NULL },
- [0x0f] = { "Less", NULL, 2, 1, { NULL, swfdec_action_less, swfdec_action_less, swfdec_action_less, swfdec_action_less } },
+ [0x0e] = { "Equals", NULL, 2, 1, { NULL, swfdec_action_old_compare, swfdec_action_old_compare, swfdec_action_old_compare, swfdec_action_old_compare } },
+ [0x0f] = { "Less", NULL, 2, 1, { NULL, swfdec_action_old_compare, swfdec_action_old_compare, swfdec_action_old_compare, swfdec_action_old_compare } },
[0x10] = { "And", NULL },
[0x11] = { "Or", NULL },
[0x12] = { "Not", NULL, 1, 1, { NULL, swfdec_action_not_4, swfdec_action_not_5, swfdec_action_not_5, swfdec_action_not_5 } },
@@ -1705,7 +1715,7 @@ static const SwfdecActionSpec actions[25
[0x45] = { "TargetPath", NULL, 1, 1, { NULL, NULL, swfdec_action_target_path, swfdec_action_target_path, swfdec_action_target_path } },
[0x46] = { "Enumerate", NULL },
[0x47] = { "Add2", NULL, 2, 1, { NULL, NULL, swfdec_action_add2_5, swfdec_action_add2_5, swfdec_action_add2_7 } },
- [0x48] = { "Less2", NULL, 2, 1, { NULL, NULL, swfdec_action_new_comparison_6, swfdec_action_new_comparison_6, swfdec_action_new_comparison_7 } },
+ [0x48] = { "Less2", NULL, 2, 1, { NULL, NULL, swfdec_action_new_comparison_6, swfdec_action_new_comparison_6, swfdec_action_new_comparison_7 } },
[0x49] = { "Equals2", NULL, 2, 1, { NULL, NULL, swfdec_action_equals2, swfdec_action_equals2, swfdec_action_equals2 } },
[0x4a] = { "ToNumber", NULL },
[0x4b] = { "ToString", NULL },
diff-tree 9335e136a9a1f2f3dbbbda7a7b156b55d94e7c4c (from 90bd9323aab5388329dfac37a165bd421818875c)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 31 16:28:09 2007 +0100
handle colors not referring to movies
This also fixes the color-new test
diff --git a/libswfdec/swfdec_js_color.c b/libswfdec/swfdec_js_color.c
index ade8d6a..095abd7 100644
--- a/libswfdec/swfdec_js_color.c
+++ b/libswfdec/swfdec_js_color.c
@@ -32,7 +32,8 @@ swfdec_js_color_get_rgb (JSContext *cx,
int result;
SwfdecMovie *movie = JS_GetPrivate (cx, obj);
- g_assert (movie);
+ if (!movie)
+ return JS_TRUE;
result = (movie->color_transform.rb << 16) |
((movie->color_transform.gb % 256) << 8) |
(movie->color_transform.bb % 256);
@@ -55,7 +56,8 @@ swfdec_js_color_get_transform (JSContext
JSObject *ret;
SwfdecMovie *movie = JS_GetPrivate (cx, obj);
- g_assert (movie);
+ if (!movie)
+ return JS_TRUE;
ret = JS_NewObject (cx, NULL, NULL, NULL);
if (ret == NULL)
return JS_TRUE;
@@ -78,7 +80,8 @@ swfdec_js_color_set_rgb (JSContext *cx,
unsigned int color;
SwfdecMovie *movie = JS_GetPrivate (cx, obj);
- g_assert (movie);
+ if (!movie)
+ return JS_TRUE;
if (!JS_ValueToECMAUint32 (cx, argv[0], &color))
return JS_TRUE;
@@ -117,8 +120,9 @@ swfdec_js_color_set_transform (JSContext
JSObject *parse;
SwfdecMovie *movie = JS_GetPrivate (cx, obj);
- g_assert (movie);
- if (!JSVAL_IS_OBJECT (argv[0]))
+ if (!movie)
+ return JS_TRUE;
+ if (!movie)
return JS_TRUE;
parse = JSVAL_TO_OBJECT (argv[0]);
parse_property (cx, parse, "ra", &movie->color_transform.ra, TRUE);
@@ -161,7 +165,6 @@ swfdec_js_color_finalize (JSContext *cx,
SwfdecMovie *movie;
movie = JS_GetPrivate (cx, obj);
- /* since we also finalize the class, not everyone has a private object */
if (movie) {
g_object_unref (movie);
}
@@ -179,14 +182,16 @@ swfdec_js_color_new (JSContext *cx, JSOb
{
SwfdecMovie *movie;
- movie = swfdec_scriptable_from_jsval (cx, argv[0], SWFDEC_TYPE_MOVIE);
- if (movie == NULL) {
- SWFDEC_INFO ("attempted to construct a color without a movie");
- return JS_TRUE;
+ if (argc > 0) {
+ movie = swfdec_scriptable_from_jsval (cx, argv[0], SWFDEC_TYPE_MOVIE);
+ } else {
+ movie = NULL;
+ }
+ if (movie != NULL) {
+ if (!JS_SetPrivate (cx, obj, movie))
+ return JS_FALSE;
+ g_object_ref (movie);
}
- if (!JS_SetPrivate (cx, obj, movie))
- return JS_TRUE;
- g_object_ref (movie);
*rval = OBJECT_TO_JSVAL (obj);
return JS_TRUE;
}
@@ -195,7 +200,7 @@ void
swfdec_js_add_color (SwfdecPlayer *player)
{
JS_InitClass (player->jscx, player->jsobj, NULL,
- &color_class, swfdec_js_color_new, 1, NULL, color_methods,
+ &color_class, swfdec_js_color_new, 0, NULL, color_methods,
NULL, NULL);
}
diff-tree 90bd9323aab5388329dfac37a165bd421818875c (from 97a972c232892d919de3045f69e6fc3fac4b8ad3)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 31 16:27:20 2007 +0100
add print function for SetTarget
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 9921af8..7c24b10 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -1407,6 +1407,15 @@ swfdec_action_target_path (JSContext *cx
/*** PRINT FUNCTIONS ***/
static char *
+swfdec_action_print_set_target (guint action, const guint8 *data, guint len)
+{
+ if (!memchr (data, 0, len)) {
+ SWFDEC_ERROR ("SetTarget action does not specify a string");
+ return JS_FALSE;
+ }
+ return g_strconcat ("SetTarget ", data, NULL);
+}
+static char *
swfdec_action_print_define_function (guint action, const guint8 *data, guint len)
{
SwfdecBits bits;
@@ -1733,7 +1742,7 @@ static const SwfdecActionSpec actions[25
[0x88] = { "ConstantPool", swfdec_action_print_constant_pool, 0, 0, { NULL, NULL, swfdec_action_constant_pool, swfdec_action_constant_pool, swfdec_action_constant_pool } },
/* version 3 */
[0x8a] = { "WaitForFrame", swfdec_action_print_wait_for_frame, 0, 0, { swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame } },
- [0x8b] = { "SetTarget", NULL, 0, 0, { swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target } },
+ [0x8b] = { "SetTarget", swfdec_action_print_set_target, 0, 0, { swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target } },
[0x8c] = { "GotoLabel", swfdec_action_print_goto_label, 0, 0, { swfdec_action_goto_label, swfdec_action_goto_label, swfdec_action_goto_label, swfdec_action_goto_label, swfdec_action_goto_label } },
/* version 4 */
[0x8d] = { "WaitForFrame2", NULL },
diff-tree 97a972c232892d919de3045f69e6fc3fac4b8ad3 (from 4b0e92902dcfd08e55f34d6d56aecb10efac9314)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 31 16:26:51 2007 +0100
make eval (obj, "") return obj and not undefined
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index 829c1ad..4c14100 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -343,7 +343,7 @@ static gboolean
swfdec_js_eval_internal (JSContext *cx, JSObject *obj, const char *str,
jsval *val, gboolean set)
{
- jsval cur = JSVAL_NULL;
+ jsval cur;
char *work = NULL;
SWFDEC_LOG ("eval called with \"%s\" on %p", str, obj);
@@ -358,8 +358,8 @@ swfdec_js_eval_internal (JSContext *cx,
if (cx->fp == NULL)
goto out;
obj = cx->fp->thisp;
- cur = OBJECT_TO_JSVAL (obj);
}
+ cur = OBJECT_TO_JSVAL (obj);
while (str != NULL && *str != '\0') {
char *dot = strchr (str, '.');
if (!JSVAL_IS_OBJECT (cur))
diff-tree 4b0e92902dcfd08e55f34d6d56aecb10efac9314 (from 29607ca556843663468425ffad907e69839a0d8f)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 31 16:26:04 2007 +0100
add test for Color constructor
diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 443cba2..27f0cac 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -16,6 +16,8 @@ EXTRA_DIST = \
children.swf.trace \
color-getters.swf \
color-getters.swf.trace \
+ color-new.swf \
+ color-new.swf.trace \
color-setRGB.swf \
color-setRGB.swf.trace \
color-setTransform-alpha.swf \
diff --git a/test/trace/color-new.swf b/test/trace/color-new.swf
new file mode 100755
index 0000000..e9f9727
Binary files /dev/null and b/test/trace/color-new.swf differ
diff --git a/test/trace/color-new.swf.trace b/test/trace/color-new.swf.trace
new file mode 100755
index 0000000..eb220d7
--- /dev/null
+++ b/test/trace/color-new.swf.trace
@@ -0,0 +1,10 @@
+test behaviour of Color when created without a movie
+[object Object]
+undefined
+undefined
+[object Object]
+undefined
+undefined
+[object Object]
+undefined
+undefined
diff-tree 29607ca556843663468425ffad907e69839a0d8f (from 62447e55d8fb4b74154694683d47070cd49e9868)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 31 14:50:27 2007 +0100
implement NextFrame, PreviousFrame, ToInteger, TargetPath, GotoLabel, GotoFrame2
Those are the actions needed by South Park studio
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index b172ec6..9921af8 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -35,6 +35,8 @@
#include "swfdec_movie.h"
#include "swfdec_player_internal.h"
#include "swfdec_root_movie.h"
+#include "swfdec_sprite.h"
+#include "swfdec_sprite_movie.h"
#include "js/jsfun.h"
#include "js/jsscope.h"
@@ -115,6 +117,25 @@ swfdec_action_push_string (JSContext *cx
return JS_TRUE;
}
+static double
+swfdec_action_to_number (JSContext *cx, jsval val)
+{
+ if (JSVAL_IS_INT (val)) {
+ return JSVAL_TO_INT (val);
+ } else if (JSVAL_IS_DOUBLE (val)) {
+ return *JSVAL_TO_DOUBLE (val);
+ } else if (JSVAL_IS_BOOLEAN (val)) {
+ return JSVAL_TO_BOOLEAN (val);
+ } else if (JSVAL_IS_STRING (val)) {
+ double d;
+ if (!JS_ValueToNumber (cx, val, &d))
+ return 0;
+ return isnan (d) ? 0 : d;
+ } else {
+ return 0;
+ }
+}
+
/*** ALL THE ACTION IS HERE ***/
static JSBool
@@ -140,6 +161,38 @@ swfdec_action_play (JSContext *cx, guint
}
static JSBool
+swfdec_action_next_frame (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ SwfdecMovie *movie = swfdec_action_get_target (cx);
+ if (movie) {
+ if (movie->frame + 1 < movie->n_frames) {
+ swfdec_movie_goto (movie, movie->frame + 1);
+ } else {
+ SWFDEC_INFO ("can't execute nextFrame, already at last frame");
+ }
+ } else {
+ SWFDEC_ERROR ("no movie to nextFrame on");
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_previous_frame (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ SwfdecMovie *movie = swfdec_action_get_target (cx);
+ if (movie) {
+ if (movie->frame > 0) {
+ swfdec_movie_goto (movie, movie->frame - 1);
+ } else {
+ SWFDEC_INFO ("can't execute previousFrame, already at first frame");
+ }
+ } else {
+ SWFDEC_ERROR ("no movie to previousFrame on");
+ }
+ return JS_TRUE;
+}
+
+static JSBool
swfdec_action_goto_frame (JSContext *cx, guint action, const guint8 *data, guint len)
{
SwfdecMovie *movie = swfdec_action_get_target (cx);
@@ -160,6 +213,76 @@ swfdec_action_goto_frame (JSContext *cx,
}
static JSBool
+swfdec_action_goto_label (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ SwfdecMovie *movie = swfdec_action_get_target (cx);
+
+ if (!memchr (data, 0, len)) {
+ SWFDEC_ERROR ("GotoLabel action does not specify a string");
+ return JS_FALSE;
+ }
+
+ if (SWFDEC_IS_SPRITE_MOVIE (movie)) {
+ int frame = swfdec_sprite_get_frame (SWFDEC_SPRITE_MOVIE (movie)->sprite, (const char *) data);
+ if (frame == -1)
+ return JS_TRUE;
+ swfdec_movie_goto (movie, frame);
+ movie->stopped = TRUE;
+ } else {
+ SWFDEC_ERROR ("no movie to goto on");
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_goto_frame2 (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ SwfdecBits bits;
+ guint bias;
+ gboolean play;
+ jsval val;
+ int frame;
+ SwfdecMovie *movie;
+
+ swfdec_bits_init_data (&bits, data, len);
+ if (swfdec_bits_getbits (&bits, 6)) {
+ SWFDEC_WARNING ("reserved bits in GotoFrame2 aren't 0");
+ }
+ bias = swfdec_bits_getbit (&bits);
+ play = swfdec_bits_getbit (&bits);
+ if (bias) {
+ bias = swfdec_bits_get_u16 (&bits);
+ }
+ val = cx->fp->sp[-1];
+ cx->fp->sp--;
+ if (JSVAL_IS_STRING (val)) {
+ const char *name = swfdec_js_to_string (cx, val);
+ if (name == NULL)
+ return JS_FALSE;
+ if (strchr (name, ':')) {
+ SWFDEC_ERROR ("FIXME: handle targets");
+ }
+ frame = swfdec_sprite_get_frame (SWFDEC_SPRITE_MOVIE (movie)->sprite, name);
+ if (frame == -1)
+ return JS_TRUE;
+ } else {
+ /* FIXME: how do we treat undefined etc? */
+ frame = swfdec_action_to_number (cx, val);
+ }
+ frame += bias;
+ /* now set it */
+ movie = swfdec_action_get_target (cx);
+ if (movie) {
+ frame = CLAMP (frame, 0, (int) movie->n_frames - 1);
+ swfdec_movie_goto (movie, frame);
+ movie->stopped = !play;
+ } else {
+ SWFDEC_ERROR ("no movie to GotoFrame2 on");
+ }
+ return JS_TRUE;
+}
+
+static JSBool
swfdec_action_wait_for_frame (JSContext *cx, guint action, const guint8 *data, guint len)
{
SwfdecMovie *movie = swfdec_action_get_target (cx);
@@ -551,25 +674,6 @@ out:
return JS_TRUE;
}
-static double
-swfdec_action_to_number (JSContext *cx, jsval val)
-{
- if (JSVAL_IS_INT (val)) {
- return JSVAL_TO_INT (val);
- } else if (JSVAL_IS_DOUBLE (val)) {
- return *JSVAL_TO_DOUBLE (val);
- } else if (JSVAL_IS_BOOLEAN (val)) {
- return JSVAL_TO_BOOLEAN (val);
- } else if (JSVAL_IS_STRING (val)) {
- double d;
- if (!JS_ValueToNumber (cx, val, &d))
- return 0;
- return isnan (d) ? 0 : d;
- } else {
- return 0;
- }
-}
-
static JSBool
swfdec_action_binary (JSContext *cx, guint action, const guint8 *data, guint len)
{
@@ -1274,6 +1378,32 @@ swfdec_action_shift (JSContext *cx, guin
return JS_NewNumberValue (cx, d, &cx->fp->sp[-1]);
}
+static JSBool
+swfdec_action_to_integer (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ double d = swfdec_action_to_number (cx, cx->fp->sp[-1]);
+
+ return JS_NewNumberValue (cx, (int) d, &cx->fp->sp[-1]);
+}
+
+static JSBool
+swfdec_action_target_path (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ SwfdecMovie *movie = swfdec_scriptable_from_jsval (cx, cx->fp->sp[-1], SWFDEC_TYPE_MOVIE);
+
+ if (movie == NULL) {
+ cx->fp->sp[-1] = JSVAL_VOID;
+ } else {
+ char *s = swfdec_movie_get_path (movie);
+ JSString *string = JS_NewStringCopyZ (cx, s);
+ g_free (s);
+ if (string == NULL)
+ return JS_FALSE;
+ cx->fp->sp[-1] = STRING_TO_JSVAL (string);
+ }
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -1431,6 +1561,26 @@ swfdec_action_print_constant_pool (guint
}
static char *
+swfdec_action_print_goto_frame2 (guint action, const guint8 *data, guint len)
+{
+ gboolean play, bias;
+ SwfdecBits bits;
+
+ swfdec_bits_init_data (&bits, data, len);
+ if (swfdec_bits_getbits (&bits, 6)) {
+ SWFDEC_WARNING ("reserved bits in GotoFrame2 aren't 0");
+ }
+ bias = swfdec_bits_getbit (&bits);
+ play = swfdec_bits_getbit (&bits);
+ if (bias) {
+ return g_strdup_printf ("GotoFrame2 %s +%u", play ? "play" : "stop",
+ swfdec_bits_get_u16 (&bits));
+ } else {
+ return g_strdup_printf ("GotoFrame2 %s", play ? "play" : "stop");
+ }
+}
+
+static char *
swfdec_action_print_goto_frame (guint action, const guint8 *data, guint len)
{
guint frame;
@@ -1443,6 +1593,17 @@ swfdec_action_print_goto_frame (guint ac
}
static char *
+swfdec_action_print_goto_label (guint action, const guint8 *data, guint len)
+{
+ if (!memchr (data, 0, len)) {
+ SWFDEC_ERROR ("GotoLabel action does not specify a string");
+ return NULL;
+ }
+
+ return g_strdup_printf ("GotoLabel %s", data);
+}
+
+static char *
swfdec_action_print_wait_for_frame (guint action, const guint8 *data, guint len)
{
guint frame, jump;
@@ -1474,8 +1635,8 @@ typedef struct {
static const SwfdecActionSpec actions[256] = {
/* version 3 */
- [0x04] = { "NextFrame", NULL },
- [0x05] = { "PreviousFrame", NULL },
+ [0x04] = { "NextFrame", NULL, 0, 0, { swfdec_action_next_frame, swfdec_action_next_frame, swfdec_action_next_frame, swfdec_action_next_frame, swfdec_action_next_frame } },
+ [0x05] = { "PreviousFrame", NULL, 0, 0, { swfdec_action_previous_frame, swfdec_action_previous_frame, swfdec_action_previous_frame, swfdec_action_previous_frame, swfdec_action_previous_frame } },
[0x06] = { "Play", NULL, 0, 0, { swfdec_action_play, swfdec_action_play, swfdec_action_play, swfdec_action_play, swfdec_action_play } },
[0x07] = { "Stop", NULL, 0, 0, { swfdec_action_stop, swfdec_action_stop, swfdec_action_stop, swfdec_action_stop, swfdec_action_stop } },
[0x08] = { "ToggleQuality", NULL },
@@ -1494,10 +1655,10 @@ static const SwfdecActionSpec actions[25
[0x14] = { "StringLength", NULL },
[0x15] = { "StringExtract", NULL },
[0x17] = { "Pop", NULL, 1, 0, { NULL, swfdec_action_pop, swfdec_action_pop, swfdec_action_pop, swfdec_action_pop } },
- [0x18] = { "ToInteger", NULL },
+ [0x18] = { "ToInteger", NULL, 1, 1, { NULL, swfdec_action_to_integer, swfdec_action_to_integer, swfdec_action_to_integer, swfdec_action_to_integer } },
[0x1c] = { "GetVariable", NULL, 1, 1, { NULL, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable } },
[0x1d] = { "SetVariable", NULL, 2, 0, { NULL, swfdec_action_set_variable, swfdec_action_set_variable, swfdec_action_set_variable, swfdec_action_set_variable } },
- [0x20] = { "SetTarget22", NULL, 1, 0, { swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2 } },
+ [0x20] = { "SetTarget2", NULL, 1, 0, { swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2 } },
[0x21] = { "StringAdd", NULL, 2, 1, { NULL, swfdec_action_string_add, swfdec_action_string_add, swfdec_action_string_add, swfdec_action_string_add } },
[0x22] = { "GetProperty", NULL, 2, 1, { NULL, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property } },
[0x23] = { "SetProperty", NULL, 3, 0, { NULL, swfdec_action_set_property, swfdec_action_set_property, swfdec_action_set_property, swfdec_action_set_property } },
@@ -1532,7 +1693,7 @@ static const SwfdecActionSpec actions[25
[0x42] = { "InitArray", NULL },
[0x43] = { "InitObject", NULL, -1, 1, { NULL, NULL, swfdec_action_init_object, swfdec_action_init_object, swfdec_action_init_object } },
[0x44] = { "Typeof", NULL },
- [0x45] = { "TargetPath", NULL },
+ [0x45] = { "TargetPath", NULL, 1, 1, { NULL, NULL, swfdec_action_target_path, swfdec_action_target_path, swfdec_action_target_path } },
[0x46] = { "Enumerate", NULL },
[0x47] = { "Add2", NULL, 2, 1, { NULL, NULL, swfdec_action_add2_5, swfdec_action_add2_5, swfdec_action_add2_7 } },
[0x48] = { "Less2", NULL, 2, 1, { NULL, NULL, swfdec_action_new_comparison_6, swfdec_action_new_comparison_6, swfdec_action_new_comparison_7 } },
@@ -1573,7 +1734,7 @@ static const SwfdecActionSpec actions[25
/* version 3 */
[0x8a] = { "WaitForFrame", swfdec_action_print_wait_for_frame, 0, 0, { swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame } },
[0x8b] = { "SetTarget", NULL, 0, 0, { swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target } },
- [0x8c] = { "GotoLabel", NULL },
+ [0x8c] = { "GotoLabel", swfdec_action_print_goto_label, 0, 0, { swfdec_action_goto_label, swfdec_action_goto_label, swfdec_action_goto_label, swfdec_action_goto_label, swfdec_action_goto_label } },
/* version 4 */
[0x8d] = { "WaitForFrame2", NULL },
/* version 7 */
@@ -1590,7 +1751,7 @@ static const SwfdecActionSpec actions[25
/* version 4 */
[0x9d] = { "If", swfdec_action_print_if, 1, 0, { NULL, swfdec_action_if, swfdec_action_if, swfdec_action_if, swfdec_action_if } },
[0x9e] = { "Call", NULL },
- [0x9f] = { "GotoFrame2", NULL }
+ [0x9f] = { "GotoFrame2", swfdec_action_print_goto_frame2, 1, 0, { NULL, swfdec_action_goto_frame2, swfdec_action_goto_frame2, swfdec_action_goto_frame2, swfdec_action_goto_frame2 } }
};
char *
diff-tree 62447e55d8fb4b74154694683d47070cd49e9868 (from 75e9e227691415642b037d6be0ff7c2ccc90772c)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 31 14:48:56 2007 +0100
add swfdec_movie_get_path
The function returns the "path" as used in ActionScript
diff --git a/libswfdec/swfdec_js_movie.c b/libswfdec/swfdec_js_movie.c
index 70ddece..d33ba94 100644
--- a/libswfdec/swfdec_js_movie.c
+++ b/libswfdec/swfdec_js_movie.c
@@ -464,36 +464,19 @@ swfdec_js_getURL (JSContext *cx, JSObjec
return JS_TRUE;
}
-static GString *
-get_name (SwfdecMovie *movie)
-{
- GString *s;
-
- if (movie->parent) {
- s = get_name (movie->parent);
- g_string_append_c (s, '.');
- g_string_append (s, movie->name);
- } else {
- /* the name can be changed */
- s = g_string_new ("_level");
- g_string_append_printf (s, "%u", movie->depth + 16384);
- }
- return s;
-}
-
static JSBool
swfdec_js_movie_to_string (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
- GString *s;
+ char *s;
JSString *string;
SwfdecMovie *movie;
movie = JS_GetPrivate (cx, obj);
g_assert (movie);
- s = get_name (movie);
- string = JS_NewStringCopyZ (cx, s->str);
- g_string_free (s, TRUE);
+ s = swfdec_movie_get_path (movie);
+ string = JS_NewStringCopyZ (cx, s);
+ g_free (s);
if (string == NULL)
return JS_FALSE;
*rval = STRING_TO_JSVAL (string);
diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index a851cd2..3ab9c88 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -787,6 +787,30 @@ swfdec_movie_goto (SwfdecMovie *movie, g
klass->goto_frame (movie, frame);
}
+char *
+swfdec_movie_get_path (SwfdecMovie *movie)
+{
+ GString *s;
+
+ g_return_val_if_fail (SWFDEC_IS_MOVIE (movie), NULL);
+
+ s = g_string_new ("");
+ do {
+ if (movie->parent) {
+ g_string_prepend (s, movie->name);
+ g_string_prepend_c (s, '.');
+ } else {
+ char *ret = g_strdup_printf ("_level%u%s",
+ movie->depth + 16384, s->str);
+ g_string_free (s, TRUE);
+ return ret;
+ }
+ movie = movie->parent;
+ } while (TRUE);
+ g_assert_not_reached ();
+ return NULL;
+}
+
int
swfdec_movie_compare_depths (gconstpointer a, gconstpointer b)
{
diff --git a/libswfdec/swfdec_movie.h b/libswfdec/swfdec_movie.h
index 61f495c..0351b54 100644
--- a/libswfdec/swfdec_movie.h
+++ b/libswfdec/swfdec_movie.h
@@ -177,6 +177,7 @@ void swfdec_movie_send_mouse_change (Sw
SwfdecMovie * swfdec_movie_get_movie_at (SwfdecMovie * movie,
double x,
double y);
+char * swfdec_movie_get_path (SwfdecMovie * movie);
void swfdec_movie_render (SwfdecMovie * movie,
cairo_t * cr,
const SwfdecColorTransform *trans,
diff-tree 75e9e227691415642b037d6be0ff7c2ccc90772c (from ae5cb38d44ea9dabd46c38fd5231ef3afcfd86ac)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 31 10:32:33 2007 +0100
add 2 tests for DefineFunction
diff --git a/test/trace/Makefile.am b/test/trace/Makefile.am
index 635e098..443cba2 100644
--- a/test/trace/Makefile.am
+++ b/test/trace/Makefile.am
@@ -42,6 +42,10 @@ EXTRA_DIST = \
currentframe.swf.trace \
double.swf \
double.swf.trace \
+ function1.swf \
+ function1.swf.trace \
+ function2.swf \
+ function2.swf.trace \
goto1.swf \
goto1.swf.trace \
goto2.swf \
diff --git a/test/trace/function1.swf b/test/trace/function1.swf
new file mode 100755
index 0000000..63f85d4
Binary files /dev/null and b/test/trace/function1.swf differ
diff --git a/test/trace/function1.swf.trace b/test/trace/function1.swf.trace
new file mode 100755
index 0000000..8403c7e
--- /dev/null
+++ b/test/trace/function1.swf.trace
@@ -0,0 +1,50 @@
+undefined
+0
+_level0
+1
+_level0
+undefined
+0
+_level0
+1
+_level0
+undefined
+0
+_level0
+1
+_level0
+undefined
+0
+_level0
+1
+_level0
+undefined
+0
+_level0
+1
+_level0
+undefined
+0
+_level0
+1
+_level0
+undefined
+0
+_level0
+1
+_level0
+undefined
+0
+_level0
+1
+_level0
+undefined
+0
+_level0
+1
+_level0
+undefined
+0
+_level0
+1
+_level0
diff --git a/test/trace/function2.swf b/test/trace/function2.swf
new file mode 100755
index 0000000..23a6b46
Binary files /dev/null and b/test/trace/function2.swf differ
diff --git a/test/trace/function2.swf.trace b/test/trace/function2.swf.trace
new file mode 100755
index 0000000..59c46d4
--- /dev/null
+++ b/test/trace/function2.swf.trace
@@ -0,0 +1,2 @@
+[type Function]
+3
diff-tree ae5cb38d44ea9dabd46c38fd5231ef3afcfd86ac (from e2aa7731c273e897af818cadf20d5bb923d8c01e)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 31 10:30:41 2007 +0100
implement CallFunction, BitRShift, BitLShift and BitURShift
includes some fixes like implementing the function with name case
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index c398e62..b172ec6 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -387,6 +387,33 @@ swfdec_action_call (JSContext *cx, guint
return js_Invoke (cx, n_args, flags);
}
+/* FIXME: lots of overlap with swfdec_action_call_method */
+static JSBool
+swfdec_action_call_function (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ JSStackFrame *fp = cx->fp;
+ const char *s;
+ guint32 n_args;
+ JSObject *obj;
+ jsval fun;
+
+ s = swfdec_js_to_string (cx, fp->sp[-1]);
+ if (s == NULL)
+ return JS_FALSE;
+ if (!JS_ValueToECMAUint32 (cx, fp->sp[-2], &n_args))
+ return JS_FALSE;
+ if (n_args + 2 > (guint) (fp->sp - fp->spbase))
+ return JS_FALSE;
+
+ obj = OBJ_THIS_OBJECT (cx, cx->fp->scopeChain);
+ if (!JS_GetProperty (cx, obj, s, &fun))
+ return JS_FALSE;
+ fp->sp[-1] = fun;
+ fp->sp[-2] = OBJECT_TO_JSVAL (obj);
+ swfdec_action_call (cx, n_args, 0);
+ return JS_TRUE;
+}
+
static JSBool
swfdec_action_call_method (JSContext *cx, guint action, const guint8 *data, guint len)
{
@@ -1207,7 +1234,9 @@ swfdec_action_define_function (JSContext
}
*cx->fp->sp++ = OBJECT_TO_JSVAL (fun->object);
} else {
- SWFDEC_ERROR ("FIXME: implement");
+ jsval val = OBJECT_TO_JSVAL (fun->object);
+ if (!JS_SetProperty (cx, OBJ_THIS_OBJECT (cx, cx->fp->scopeChain), function_name, &val))
+ return JS_FALSE;
}
/* update current context */
@@ -1215,6 +1244,36 @@ swfdec_action_define_function (JSContext
return JS_TRUE;
}
+static JSBool
+swfdec_action_shift (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ guint32 amount, value;
+ double d;
+
+ if (!JS_ValueToECMAUint32 (cx, cx->fp->sp[-1], &amount) ||
+ !JS_ValueToECMAUint32 (cx, cx->fp->sp[-2], &value))
+ return JS_FALSE;
+
+ amount &= 31;
+ switch (action) {
+ case 0x63:
+ d = value << amount;
+ break;
+ case 0x64:
+ d = ((gint) value) >> amount;
+ break;
+ case 0x65:
+ d = ((guint) value) >> amount;
+ break;
+ default:
+ g_assert_not_reached ();
+ return JS_FALSE;
+ }
+
+ cx->fp->sp--;
+ return JS_NewNumberValue (cx, d, &cx->fp->sp[-1]);
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -1464,8 +1523,8 @@ static const SwfdecActionSpec actions[25
/* version 5 */
[0x3a] = { "Delete", NULL },
[0x3b] = { "Delete2", NULL },
- [0x3c] = { "DefineLocal", NULL },
- [0x3d] = { "CallFunction", NULL },
+ [0x3c] = { "DefineLocal", NULL }, //, 2, 0, { NULL, NULL, swfdec_action_define_local, swfdec_action_define_local, swfdec_action_define_local } },
+ [0x3d] = { "CallFunction", NULL, -1, 1, { NULL, NULL, swfdec_action_call_function, swfdec_action_call_function, swfdec_action_call_function } },
[0x3e] = { "Return", NULL },
[0x3f] = { "Modulo", NULL },
[0x40] = { "NewObject", NULL, -1, 1, { NULL, NULL, swfdec_action_new_object, swfdec_action_new_object, swfdec_action_new_object } },
@@ -1495,9 +1554,9 @@ static const SwfdecActionSpec actions[25
[0x60] = { "BitAnd", NULL },
[0x61] = { "BitOr", NULL },
[0x62] = { "BitXor", NULL },
- [0x63] = { "BitLShift", NULL },
- [0x64] = { "BitRShift", NULL },
- [0x65] = { "BitURShift", NULL },
+ [0x63] = { "BitLShift", NULL, 2, 1, { NULL, NULL, swfdec_action_shift, swfdec_action_shift, swfdec_action_shift } },
+ [0x64] = { "BitRShift", NULL, 2, 1, { NULL, NULL, swfdec_action_shift, swfdec_action_shift, swfdec_action_shift } },
+ [0x65] = { "BitURShift", NULL, 2, 1, { NULL, NULL, swfdec_action_shift, swfdec_action_shift, swfdec_action_shift } },
/* version 6 */
[0x66] = { "StrictEquals", NULL },
[0x67] = { "Greater", NULL, 2, 1, { NULL, NULL, NULL, swfdec_action_new_comparison_6, swfdec_action_new_comparison_7 } },
diff-tree e2aa7731c273e897af818cadf20d5bb923d8c01e (from ee7ecfa22195201642e114bfdb24d28aa690e00c)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 31 10:29:46 2007 +0100
create a call object for calls to SWF code
diff --git a/libswfdec/js/jsinterp.c b/libswfdec/js/jsinterp.c
index 1d15966..ce8d014 100644
--- a/libswfdec/js/jsinterp.c
+++ b/libswfdec/js/jsinterp.c
@@ -963,7 +963,10 @@ have_fun:
}
ok = js_Interpret(cx, &v);
} else if (swf) {
- frame.scopeChain = funobj; /* FIXME */
+ if (!js_GetCallObject(cx, &frame, parent)) {
+ ok = JS_FALSE;
+ goto out;
+ }
ok = swfdec_script_interpret(swf, cx, &v);
} else {
/* fun might be onerror trying to report a syntax error in itself. */
diff-tree ee7ecfa22195201642e114bfdb24d28aa690e00c (from 56d6b7a99657f96cc093d7136ff7eea4a6acfcfd)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 31 10:28:46 2007 +0100
return "[type Function]" from function.toString()
diff --git a/libswfdec/js/jsfun.c b/libswfdec/js/jsfun.c
index 84121de..a085673 100644
--- a/libswfdec/js/jsfun.c
+++ b/libswfdec/js/jsfun.c
@@ -1418,7 +1418,12 @@ js_fun_toString(JSContext *cx, JSObject
static JSBool
fun_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
- return js_fun_toString(cx, obj, 0, argc, argv, rval);
+ JSString *string = JS_InternString (cx, "[type Function]");
+
+ if (string == NULL)
+ return JS_FALSE;
+ *rval = STRING_TO_JSVAL (string);
+ return JS_TRUE;
}
#if JS_HAS_TOSOURCE
diff-tree 56d6b7a99657f96cc093d7136ff7eea4a6acfcfd (from bd449d3ebe7adc1a6fc90beafef2f192a6c23ac4)
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Jan 30 14:54:17 2007 +0100
implement DefineFunction
contains some changes to script handling that are required to make this
work properly, like allowing scripts that don't end with a 0 action
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index e2ddcec..c398e62 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -36,6 +36,7 @@
#include "swfdec_player_internal.h"
#include "swfdec_root_movie.h"
#include "js/jsfun.h"
+#include "js/jsscope.h"
/*** CONSTANT POOLS ***/
@@ -1134,9 +1135,129 @@ swfdec_action_init_object (JSContext *cx
return JS_TRUE;
}
+static JSBool
+swfdec_action_define_function (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ const char *function_name;
+ guint i, n_args, size;
+ SwfdecBits bits;
+ JSFunction *fun;
+ SwfdecScript *script;
+
+ swfdec_bits_init_data (&bits, data, len);
+ function_name = swfdec_bits_get_string (&bits);
+ if (function_name == NULL) {
+ SWFDEC_ERROR ("could not parse function name");
+ return JS_FALSE;
+ }
+ n_args = swfdec_bits_get_u16 (&bits);
+ if (*function_name == '\0') {
+ /* anonymous function */
+ fun = JS_NewFunction (cx, NULL, n_args, JSFUN_LAMBDA, NULL, NULL);
+ } else {
+ /* named function */
+ fun = JS_NewFunction (cx, NULL, n_args, 0, NULL, function_name);
+ }
+ if (fun == NULL)
+ return JS_FALSE;
+ for (i = 0; i < n_args; i++) {
+ JSAtom *atom;
+ const char *arg_name = swfdec_bits_get_string (&bits);
+ if (arg_name == NULL || *arg_name == '\0') {
+ SWFDEC_ERROR ("empty argument name not allowed");
+ return JS_FALSE;
+ }
+ /* FIXME: check duplicate arguments */
+ atom = js_Atomize (cx, arg_name, strlen (arg_name), 0);
+ if (atom == NULL)
+ return JS_FALSE;
+ if (!js_AddNativeProperty (cx, fun->object, (jsid) atom,
+ js_GetArgument, js_SetArgument, SPROP_INVALID_SLOT,
+ JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED,
+ SPROP_HAS_SHORTID, i)) {
+ return JS_FALSE;
+ }
+ }
+ size = swfdec_bits_get_u16 (&bits);
+ /* check the script can be created */
+ script = cx->fp->swf;
+ if (script->buffer->data + script->buffer->length < cx->fp->pc + 3 + len + size) {
+ SWFDEC_ERROR ("size of function is too big");
+ return FALSE;
+ } else {
+ /* create the script */
+ SwfdecBuffer *buffer = swfdec_buffer_new_subbuffer (script->buffer,
+ cx->fp->pc + 3 + len - script->buffer->data, size);
+ swfdec_bits_init (&bits, buffer);
+ script = swfdec_script_new_for_player (JS_GetContextPrivate (cx),
+ &bits, *function_name ? function_name : "<lambda>",
+ ((SwfdecScript *) cx->fp->swf)->version);
+ swfdec_buffer_unref (buffer);
+ }
+ if (script == NULL) {
+ SWFDEC_ERROR ("failed to create script");
+ return JS_FALSE;
+ }
+ fun->swf = script;
+ /* attach the function */
+ if (*function_name == '\0') {
+ if (action == 0) {
+ SWFDEC_ERROR ("not enough stack space available");
+ return JS_FALSE;
+ }
+ *cx->fp->sp++ = OBJECT_TO_JSVAL (fun->object);
+ } else {
+ SWFDEC_ERROR ("FIXME: implement");
+ }
+
+ /* update current context */
+ cx->fp->pc += 3 + len + size;
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
+swfdec_action_print_define_function (guint action, const guint8 *data, guint len)
+{
+ SwfdecBits bits;
+ GString *string;
+ const char *function_name;
+ guint i, n_args, size;
+
+ string = g_string_new ("DefineFunction ");
+ swfdec_bits_init_data (&bits, data, len);
+ function_name = swfdec_bits_get_string (&bits);
+ if (function_name == NULL) {
+ SWFDEC_ERROR ("could not parse function name");
+ g_string_free (string, TRUE);
+ return NULL;
+ }
+ if (*function_name) {
+ g_string_append (string, function_name);
+ g_string_append_c (string, ' ');
+ }
+ n_args = swfdec_bits_get_u16 (&bits);
+ g_string_append_c (string, '(');
+
+ for (i = 0; i < n_args; i++) {
+ const char *arg_name = swfdec_bits_get_string (&bits);
+ if (arg_name == NULL || *arg_name == '\0') {
+ SWFDEC_ERROR ("empty argument name not allowed");
+ g_string_free (string, TRUE);
+ return NULL;
+ }
+ if (i)
+ g_string_append (string, ", ");
+ g_string_append (string, arg_name);
+ }
+ g_string_append_c (string, ')');
+ size = swfdec_bits_get_u16 (&bits);
+ g_string_append_printf (string, " %u", size);
+ return g_string_free (string, FALSE);
+}
+
+static char *
swfdec_action_print_get_url (guint action, const guint8 *data, guint len)
{
SwfdecBits bits;
@@ -1406,7 +1527,7 @@ static const SwfdecActionSpec actions[25
[0x99] = { "Jump", swfdec_action_print_jump, 0, 0, { NULL, swfdec_action_jump, swfdec_action_jump, swfdec_action_jump, swfdec_action_jump } },
[0x9a] = { "GetURL2", NULL },
/* version 5 */
- [0x9b] = { "DefineFunction", NULL },
+ [0x9b] = { "DefineFunction", swfdec_action_print_define_function, 0, -1, { NULL, NULL, swfdec_action_define_function, swfdec_action_define_function, swfdec_action_define_function } },
/* version 4 */
[0x9d] = { "If", swfdec_action_print_if, 1, 0, { NULL, swfdec_action_if, swfdec_action_if, swfdec_action_if, swfdec_action_if } },
[0x9e] = { "Call", NULL },
@@ -1442,7 +1563,7 @@ swfdec_script_foreach_internal (SwfdecBi
gconstpointer bytecode;
bytecode = bits->ptr;
- while ((action = swfdec_bits_get_u8 (bits))) {
+ while (swfdec_bits_left (bits) && (action = swfdec_bits_get_u8 (bits))) {
if (action & 0x80) {
len = swfdec_bits_get_u16 (bits);
data = bits->ptr;
@@ -1634,8 +1755,10 @@ swfdec_script_interpret (SwfdecScript *s
while (TRUE) {
/* check pc */
+ if (pc == endpc) /* needed for scripts created via DefineFunction */
+ break;
if (pc < startpc || pc >= endpc) {
- SWFDEC_ERROR ("pc %p not in valid range [%p, %p] anymore", pc, startpc, endpc);
+ SWFDEC_ERROR ("pc %p not in valid range [%p, %p) anymore", pc, startpc, endpc);
goto internal_error;
}
diff-tree bd449d3ebe7adc1a6fc90beafef2f192a6c23ac4 (from 2ae8e627b6ad7d5c5cba649db11cde9758e43815)
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Jan 30 14:52:20 2007 +0100
fix SwfdecScript reference handling
- intitialize fun->swf to NULL
- unref fun->swf on finalization
diff --git a/libswfdec/js/jsfun.c b/libswfdec/js/jsfun.c
index 1ba58f8..84121de 100644
--- a/libswfdec/js/jsfun.c
+++ b/libswfdec/js/jsfun.c
@@ -1042,6 +1042,7 @@ fun_convert(JSContext *cx, JSObject *obj
}
}
+extern void swfdec_script_unref (void *script);
static void
fun_finalize(JSContext *cx, JSObject *obj)
{
@@ -1058,6 +1059,8 @@ fun_finalize(JSContext *cx, JSObject *ob
return;
if (fun->script)
js_DestroyScript(cx, fun->script);
+ if (fun->swf)
+ swfdec_script_unref (fun->swf);
JS_free(cx, fun);
}
@@ -1928,6 +1931,7 @@ js_NewFunction(JSContext *cx, JSObject *
fun->object = NULL;
fun->native = native;
fun->script = NULL;
+ fun->swf = NULL;
fun->nargs = nargs;
fun->extra = 0;
fun->nvars = 0;
diff-tree 2ae8e627b6ad7d5c5cba649db11cde9758e43815 (from 7b858d98456af8c801b9c346ef7abc8ebd4a0453)
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Jan 30 12:38:28 2007 +0100
check !JSVAL_IS_NULL in all JSVAL_IS_OBJECT checks
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 64f0746..e2ddcec 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -403,7 +403,7 @@ swfdec_action_call_method (JSContext *cx
if (n_args + 3 > (guint) (fp->sp - fp->spbase))
return JS_FALSE;
- if (!JSVAL_IS_OBJECT (fp->sp[-2]))
+ if (!JSVAL_IS_OBJECT (fp->sp[-2]) || JSVAL_IS_NULL (fp->sp[-2]))
goto fail;
obj = JSVAL_TO_OBJECT (fp->sp[-2]);
if (s[0] == '\0') {
@@ -689,7 +689,7 @@ swfdec_action_get_member (JSContext *cx,
if (s == NULL)
return JS_FALSE;
- if (JSVAL_IS_OBJECT (cx->fp->sp[-2])) {
+ if (JSVAL_IS_OBJECT (cx->fp->sp[-2]) && !JSVAL_IS_NULL (cx->fp->sp[-2])) {
if (!JS_GetProperty (cx, JSVAL_TO_OBJECT (cx->fp->sp[-2]), s, &cx->fp->sp[-2]))
return JS_FALSE;
} else {
@@ -708,7 +708,7 @@ swfdec_action_set_member (JSContext *cx,
if (s == NULL)
return JS_FALSE;
- if (JSVAL_IS_OBJECT (cx->fp->sp[-3])) {
+ if (JSVAL_IS_OBJECT (cx->fp->sp[-3]) && !JSVAL_IS_NULL (cx->fp->sp[-3])) {
if (!JS_SetProperty (cx, JSVAL_TO_OBJECT (cx->fp->sp[-3]), s, &cx->fp->sp[-1]))
return JS_FALSE;
}
@@ -989,7 +989,7 @@ swfdec_action_set_target (JSContext *cx,
}
/* evaluate relative to this to not get trapped by previous SetTarget calls */
target = swfdec_js_eval (cx, cx->fp->thisp, (const char *) data);
- if (!JSVAL_IS_OBJECT (target)) {
+ if (!JSVAL_IS_OBJECT (target) || JSVAL_IS_NULL (target)) {
SWFDEC_WARNING ("target is not an object");
return JS_TRUE;
}
@@ -1003,7 +1003,7 @@ swfdec_action_set_target2 (JSContext *cx
val = cx->fp->sp[-1];
cx->fp->sp--;
- if (!JSVAL_IS_OBJECT (val)) {
+ if (!JSVAL_IS_OBJECT (val) || JSVAL_IS_NULL (val)) {
SWFDEC_WARNING ("target is not an object");
return JS_TRUE;
}
@@ -1034,7 +1034,7 @@ swfdec_action_start_drag (JSContext *cx,
fp->sp[-6] = fp->sp[-5];
fp->sp[-5] = tmp;
}
- if (!JSVAL_IS_OBJECT (fp->sp[-1])) {
+ if (!JSVAL_IS_OBJECT (fp->sp[-1]) || JSVAL_IS_NULL (fp->sp[-1])) {
fp->sp -= n_args + 2;
return JS_TRUE;
}
@@ -1084,7 +1084,7 @@ swfdec_action_new_object (JSContext *cx,
}
fp->sp[-1] = constructor;
- if (!JSVAL_IS_OBJECT (constructor))
+ if (!JSVAL_IS_OBJECT (constructor) || JSVAL_IS_NULL (constructor))
goto fail;
object = JSVAL_TO_OBJECT (constructor);
if (JS_GetClass (object) != &js_FunctionClass)
diff-tree 7b858d98456af8c801b9c346ef7abc8ebd4a0453 (from abfaad4612d9129e2cf0de1402f623e22d356831)
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Jan 30 12:34:20 2007 +0100
catch a case where fun->script is accessed unconditionally
diff --git a/libswfdec/js/jsobj.c b/libswfdec/js/jsobj.c
index 2033c97..112bdc8 100644
--- a/libswfdec/js/jsobj.c
+++ b/libswfdec/js/jsobj.c
@@ -2356,6 +2356,8 @@ Detecting(JSContext *cx, jsbytecode *pc)
JSAtom *atom;
script = cx->fp->script;
+ if (script == NULL)
+ return JS_FALSE;
for (endpc = script->code + script->length; pc < endpc; pc++) {
/* General case: a branch or equality op follows the access. */
op = (JSOp) *pc;
diff-tree abfaad4612d9129e2cf0de1402f623e22d356831 (from parents)
Merge: d8b4748701572b483c96bbb4a66a6f026cd1c1d7 a7b8850adba4086c321e69c8933f6248b3de0803
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Jan 30 09:59:37 2007 +0100
Merge branch 'master' into interpreter
diff-tree d8b4748701572b483c96bbb4a66a6f026cd1c1d7 (from 1986ae14a62fc9d28ac38f53621fadaf9b42877f)
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 29 19:07:12 2007 +0100
implement InitObject action
all tests pass now
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index b1f1a63..64f0746 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -1105,6 +1105,35 @@ fail:
return JS_TRUE;
}
+static JSBool
+swfdec_action_init_object (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ JSStackFrame *fp = cx->fp;
+ JSObject *object;
+ guint i, n_args;
+
+ if (!JS_ValueToECMAUint32 (cx, fp->sp[-1], &n_args))
+ return JS_FALSE;
+ if ((guint) (fp->sp - fp->spbase) < 2 * n_args + 1) {
+ SWFDEC_ERROR ("not enough stack space");
+ return JS_FALSE;
+ }
+
+ object = JS_NewObject (cx, &js_ObjectClass, NULL, NULL);
+ if (object == NULL)
+ return JS_FALSE;
+ for (i = 0; i < n_args; i++) {
+ const char *s = swfdec_js_to_string (cx, fp->sp[-3 - 2 * i]);
+ if (s == NULL)
+ return JS_FALSE;
+ if (!JS_SetProperty (cx, object, s, &fp->sp[-2 - 2 * i]))
+ return JS_FALSE;
+ }
+ fp->sp -= 2 * n_args;
+ fp->sp[-1] = OBJECT_TO_JSVAL (object);
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -1321,7 +1350,7 @@ static const SwfdecActionSpec actions[25
[0x40] = { "NewObject", NULL, -1, 1, { NULL, NULL, swfdec_action_new_object, swfdec_action_new_object, swfdec_action_new_object } },
[0x41] = { "DefineLocal2", NULL },
[0x42] = { "InitArray", NULL },
- [0x43] = { "InitObject", NULL },
+ [0x43] = { "InitObject", NULL, -1, 1, { NULL, NULL, swfdec_action_init_object, swfdec_action_init_object, swfdec_action_init_object } },
[0x44] = { "Typeof", NULL },
[0x45] = { "TargetPath", NULL },
[0x46] = { "Enumerate", NULL },
diff-tree 1986ae14a62fc9d28ac38f53621fadaf9b42877f (from 7718526823b5db8d2d81c0caaed70500cb575c6f)
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 29 18:15:06 2007 +0100
implement NewObject
also fixes the constructors to work with it.
5/44 failures
diff --git a/libswfdec/swfdec_js_color.c b/libswfdec/swfdec_js_color.c
index a117118..ade8d6a 100644
--- a/libswfdec/swfdec_js_color.c
+++ b/libswfdec/swfdec_js_color.c
@@ -178,20 +178,16 @@ static JSBool
swfdec_js_color_new (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
SwfdecMovie *movie;
- JSObject *new;
movie = swfdec_scriptable_from_jsval (cx, argv[0], SWFDEC_TYPE_MOVIE);
if (movie == NULL) {
SWFDEC_INFO ("attempted to construct a color without a movie");
return JS_TRUE;
}
- new = JS_NewObject (cx, &color_class, NULL, NULL);
- if (new == NULL)
- return JS_TRUE;
- if (!JS_SetPrivate (cx, new, movie))
+ if (!JS_SetPrivate (cx, obj, movie))
return JS_TRUE;
g_object_ref (movie);
- *rval = OBJECT_TO_JSVAL (new);
+ *rval = OBJECT_TO_JSVAL (obj);
return JS_TRUE;
}
diff --git a/libswfdec/swfdec_js_sound.c b/libswfdec/swfdec_js_sound.c
index 67e11bd..b9f8d57 100644
--- a/libswfdec/swfdec_js_sound.c
+++ b/libswfdec/swfdec_js_sound.c
@@ -61,12 +61,7 @@ static JSClass sound_class = {
static JSBool
swfdec_js_sound_new (JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
- JSObject *new;
-
- new = JS_NewObject (cx, &sound_class, NULL, NULL);
- if (new == NULL)
- return JS_TRUE;
- *rval = OBJECT_TO_JSVAL (new);
+ *rval = OBJECT_TO_JSVAL (obj);
return JS_TRUE;
}
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 8a0d3a6..b1f1a63 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -35,6 +35,7 @@
#include "swfdec_movie.h"
#include "swfdec_player_internal.h"
#include "swfdec_root_movie.h"
+#include "js/jsfun.h"
/*** CONSTANT POOLS ***/
@@ -1063,6 +1064,47 @@ swfdec_action_stop_sounds (JSContext *cx
return JS_TRUE;
}
+static JSBool
+swfdec_action_new_object (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ JSStackFrame *fp = cx->fp;
+ jsval constructor;
+ JSObject *object;
+ const JSClass *clasp;
+ guint n_args;
+
+ constructor = fp->sp[-1];
+ if (!swfdec_eval_jsval (cx, NULL, &constructor))
+ return JS_FALSE;
+ if (!JS_ValueToECMAUint32 (cx, fp->sp[-2], &n_args))
+ return JS_FALSE;
+ if ((guint) (fp->sp - fp->spbase) < n_args + 2) {
+ SWFDEC_ERROR ("not enough stack space");
+ return JS_FALSE;
+ }
+ fp->sp[-1] = constructor;
+
+ if (!JSVAL_IS_OBJECT (constructor))
+ goto fail;
+ object = JSVAL_TO_OBJECT (constructor);
+ if (JS_GetClass (object) != &js_FunctionClass)
+ goto fail;
+ clasp = ((JSFunction *) JS_GetPrivate (cx, object))->clasp;
+ object = JS_NewObject (cx, clasp, NULL, NULL);
+ if (object == NULL)
+ return JS_FALSE;
+ fp->sp[-2] = OBJECT_TO_JSVAL (object);
+ if (!swfdec_action_call (cx, n_args, JSINVOKE_CONSTRUCT))
+ return JS_FALSE;
+ fp->sp[-1] = OBJECT_TO_JSVAL (object);
+ return JS_TRUE;
+
+fail:
+ fp->sp -= n_args + 1;
+ fp->sp[-1] = JSVAL_VOID;
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -1276,7 +1318,7 @@ static const SwfdecActionSpec actions[25
[0x3d] = { "CallFunction", NULL },
[0x3e] = { "Return", NULL },
[0x3f] = { "Modulo", NULL },
- [0x40] = { "NewObject", NULL },
+ [0x40] = { "NewObject", NULL, -1, 1, { NULL, NULL, swfdec_action_new_object, swfdec_action_new_object, swfdec_action_new_object } },
[0x41] = { "DefineLocal2", NULL },
[0x42] = { "InitArray", NULL },
[0x43] = { "InitObject", NULL },
diff-tree 7718526823b5db8d2d81c0caaed70500cb575c6f (from 766926a5baf0ca465c0010f2cf157a41498cd841)
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 29 12:35:59 2007 +0100
implement StopSounds
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 1decae7..8a0d3a6 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -1054,6 +1054,15 @@ swfdec_action_end_drag (JSContext *cx, g
return JS_TRUE;
}
+static JSBool
+swfdec_action_stop_sounds (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ SwfdecPlayer *player = JS_GetContextPrivate (cx);
+
+ swfdec_player_stop_all_sounds (player);
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -1219,7 +1228,7 @@ static const SwfdecActionSpec actions[25
[0x06] = { "Play", NULL, 0, 0, { swfdec_action_play, swfdec_action_play, swfdec_action_play, swfdec_action_play, swfdec_action_play } },
[0x07] = { "Stop", NULL, 0, 0, { swfdec_action_stop, swfdec_action_stop, swfdec_action_stop, swfdec_action_stop, swfdec_action_stop } },
[0x08] = { "ToggleQuality", NULL },
- [0x09] = { "StopSounds", NULL },
+ [0x09] = { "StopSounds", NULL, 0, 0, { swfdec_action_stop_sounds, swfdec_action_stop_sounds, swfdec_action_stop_sounds, swfdec_action_stop_sounds, swfdec_action_stop_sounds } },
/* version 4 */
[0x0a] = { "Add", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
[0x0b] = { "Subtract", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
diff-tree 766926a5baf0ca465c0010f2cf157a41498cd841 (from e5233b84a86161a483eb16754dfd89f8f194b0d6)
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 29 12:30:39 2007 +0100
implement StartDrag and EndDrag actions
this makes speedball.swf work again
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 537fced..1decae7 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -359,23 +359,26 @@ swfdec_action_trace (JSContext *cx, guin
* This function is similar to js_Invoke, however it uses a reversed stack
* order. sp[-1] has to be the function to call, sp[-2] will be the object the
* function is called on, sp[-3] is the first argument, followed by the rest of
- * the arguments. The function reorders the stack on success and pushes the
- * return value on top.
+ * the arguments. The function removes all of these argumends from the stack
+ * and pushes the return value on top.
*
* Returns: JS_TRUE on success, JS_FALSE on failure.
**/
static JSBool
swfdec_action_call (JSContext *cx, guint n_args, guint flags)
{
+ JSStackFrame *fp = cx->fp;
int i, j;
jsval tmp;
+ g_assert ((guint) (fp->sp - fp->spbase) >= n_args + 2);
+
j = -1;
i = - (n_args + 2);
while (i < j) {
- tmp = cx->fp->sp[j];
- cx->fp->sp[j] = cx->fp->sp[i];
- cx->fp->sp[i] = tmp;
+ tmp = fp->sp[j];
+ fp->sp[j] = fp->sp[i];
+ fp->sp[i] = tmp;
j--;
i++;
}
@@ -1006,6 +1009,51 @@ swfdec_action_set_target2 (JSContext *cx
return swfdec_action_do_set_target (cx, JSVAL_TO_OBJECT (val));
}
+static JSBool
+swfdec_action_start_drag (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ JSStackFrame *fp = cx->fp;
+ guint stack_size = fp->sp - fp->spbase;
+ guint n_args = 1;
+
+ if (stack_size < 3)
+ return JS_FALSE;
+ if (!swfdec_eval_jsval (cx, NULL, &fp->sp[-1]))
+ return JS_FALSE;
+ if (swfdec_action_to_number (cx, fp->sp[-3])) {
+ jsval tmp;
+ if (stack_size < 7)
+ return JS_FALSE;
+ n_args = 5;
+ /* yay for order */
+ tmp = fp->sp[-4];
+ fp->sp[-4] = fp->sp[-7];
+ fp->sp[-7] = tmp;
+ tmp = fp->sp[-6];
+ fp->sp[-6] = fp->sp[-5];
+ fp->sp[-5] = tmp;
+ }
+ if (!JSVAL_IS_OBJECT (fp->sp[-1])) {
+ fp->sp -= n_args + 2;
+ return JS_TRUE;
+ }
+ fp->sp[-3] = fp->sp[-2];
+ fp->sp[-2] = fp->sp[-1];
+ if (!JS_GetProperty (cx, JSVAL_TO_OBJECT (fp->sp[-2]), "startDrag", &fp->sp[-1]))
+ return JS_FALSE;
+ swfdec_action_call (cx, n_args, 0);
+ fp->sp--;
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_end_drag (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ SwfdecPlayer *player = JS_GetContextPrivate (cx);
+ swfdec_player_set_drag_movie (player, NULL, FALSE, NULL);
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -1196,8 +1244,8 @@ static const SwfdecActionSpec actions[25
[0x24] = { "CloneSprite", NULL },
[0x25] = { "RemoveSprite", NULL },
[0x26] = { "Trace", NULL, 1, 0, { NULL, swfdec_action_trace, swfdec_action_trace, swfdec_action_trace, swfdec_action_trace } },
- [0x27] = { "StartDrag", NULL },
- [0x28] = { "EndDrag", NULL },
+ [0x27] = { "StartDrag", NULL, -1, 0, { NULL, swfdec_action_start_drag, swfdec_action_start_drag, swfdec_action_start_drag, swfdec_action_start_drag } },
+ [0x28] = { "EndDrag", NULL, 0, 0, { NULL, swfdec_action_end_drag, swfdec_action_end_drag, swfdec_action_end_drag, swfdec_action_end_drag } },
[0x29] = { "StringLess", NULL },
/* version 7 */
[0x2a] = { "Throw", NULL },
diff-tree e5233b84a86161a483eb16754dfd89f8f194b0d6 (from 5a4bd5f45bc800d333c356097037c13d13152850)
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 29 10:30:56 2007 +0100
various fixes to reference the correct this object
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index e501c4f..829c1ad 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -384,7 +384,7 @@ swfdec_js_eval_internal (JSContext *cx,
if (cx->fp == NULL)
goto out;
g_assert (cx->fp->scopeChain);
- cur = OBJECT_TO_JSVAL (cx->fp->scopeChain);
+ cur = OBJECT_TO_JSVAL (OBJ_THIS_OBJECT (cx, cx->fp->scopeChain));
}
finish:
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index dca72e0..537fced 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -98,7 +98,9 @@ swfdec_constant_pool_free (SwfdecConstan
static SwfdecMovie *
swfdec_action_get_target (JSContext *cx)
{
- return swfdec_scriptable_from_jsval (cx, OBJECT_TO_JSVAL (cx->fp->scopeChain), SWFDEC_TYPE_MOVIE);
+ JSObject *object = cx->fp->scopeChain;
+ object = OBJ_THIS_OBJECT (cx, object);
+ return swfdec_scriptable_from_jsval (cx, OBJECT_TO_JSVAL (object), SWFDEC_TYPE_MOVIE);
}
static JSBool
@@ -442,6 +444,8 @@ swfdec_eval_jsval (JSContext *cx, JSObje
return JS_FALSE;
*val = swfdec_js_eval (cx, obj, bytes);
} else {
+ if (obj == NULL)
+ obj = OBJ_THIS_OBJECT (cx, cx->fp->scopeChain);
*val = OBJECT_TO_JSVAL (obj);
}
return JS_TRUE;
diff-tree 5a4bd5f45bc800d333c356097037c13d13152850 (from 7f5416c27464e7f7f59444e8b2fff80eb65a43c2)
Author: Benjamin Otte <otte at gnome.org>
Date: Sun Jan 28 22:17:14 2007 +0100
implement SetTarget and SetTarget2
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 8f86eea..dca72e0 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -949,6 +949,59 @@ swfdec_action_equals2 (JSContext *cx, gu
return JS_TRUE;
}
+static JSBool
+swfdec_action_do_set_target (JSContext *cx, JSObject *target)
+{
+ JSObject *with;
+
+ /* FIXME: this whole function stops working the moment it's used together
+ * with With */
+ if (target == cx->fp->scopeChain)
+ return JS_TRUE;
+ if (target == cx->fp->thisp) {
+ /* FIXME: will probably break once SetTarget is called inside DefineFunctions */
+ cx->fp->scopeChain = cx->fp->thisp;
+ return JS_TRUE;
+ }
+ with = js_NewObject(cx, &js_WithClass, target, cx->fp->scopeChain);
+ if (!with)
+ return JS_FALSE;
+ cx->fp->scopeChain = with;
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_set_target (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ jsval target;
+
+ if (!memchr (data, 0, len)) {
+ SWFDEC_ERROR ("SetTarget action does not specify a string");
+ return JS_FALSE;
+ }
+ /* evaluate relative to this to not get trapped by previous SetTarget calls */
+ target = swfdec_js_eval (cx, cx->fp->thisp, (const char *) data);
+ if (!JSVAL_IS_OBJECT (target)) {
+ SWFDEC_WARNING ("target is not an object");
+ return JS_TRUE;
+ }
+ return swfdec_action_do_set_target (cx, JSVAL_TO_OBJECT (target));
+}
+
+static JSBool
+swfdec_action_set_target2 (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ jsval val;
+
+ val = cx->fp->sp[-1];
+ cx->fp->sp--;
+ if (!JSVAL_IS_OBJECT (val)) {
+ SWFDEC_WARNING ("target is not an object");
+ return JS_TRUE;
+ }
+ return swfdec_action_do_set_target (cx, JSVAL_TO_OBJECT (val));
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -1132,7 +1185,7 @@ static const SwfdecActionSpec actions[25
[0x18] = { "ToInteger", NULL },
[0x1c] = { "GetVariable", NULL, 1, 1, { NULL, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable } },
[0x1d] = { "SetVariable", NULL, 2, 0, { NULL, swfdec_action_set_variable, swfdec_action_set_variable, swfdec_action_set_variable, swfdec_action_set_variable } },
- [0x20] = { "SetTarget2", NULL },
+ [0x20] = { "SetTarget22", NULL, 1, 0, { swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2, swfdec_action_set_target2 } },
[0x21] = { "StringAdd", NULL, 2, 1, { NULL, swfdec_action_string_add, swfdec_action_string_add, swfdec_action_string_add, swfdec_action_string_add } },
[0x22] = { "GetProperty", NULL, 2, 1, { NULL, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property } },
[0x23] = { "SetProperty", NULL, 3, 0, { NULL, swfdec_action_set_property, swfdec_action_set_property, swfdec_action_set_property, swfdec_action_set_property } },
@@ -1207,7 +1260,7 @@ static const SwfdecActionSpec actions[25
[0x88] = { "ConstantPool", swfdec_action_print_constant_pool, 0, 0, { NULL, NULL, swfdec_action_constant_pool, swfdec_action_constant_pool, swfdec_action_constant_pool } },
/* version 3 */
[0x8a] = { "WaitForFrame", swfdec_action_print_wait_for_frame, 0, 0, { swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame } },
- [0x8b] = { "SetTarget", NULL },
+ [0x8b] = { "SetTarget", NULL, 0, 0, { swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target, swfdec_action_set_target } },
[0x8c] = { "GotoLabel", NULL },
/* version 4 */
[0x8d] = { "WaitForFrame2", NULL },
diff-tree 7f5416c27464e7f7f59444e8b2fff80eb65a43c2 (from 2f1ed9bb15785a9dfde7fdef1adc92346c11ab82)
Author: Benjamin Otte <otte at gnome.org>
Date: Sun Jan 28 22:16:50 2007 +0100
didn't catch NULL here, oops
diff --git a/libswfdec/swfdec_scriptable.c b/libswfdec/swfdec_scriptable.c
index 479bad9..d1ff8da 100644
--- a/libswfdec/swfdec_scriptable.c
+++ b/libswfdec/swfdec_scriptable.c
@@ -144,6 +144,8 @@ swfdec_scriptable_from_jsval (JSContext
if (!JSVAL_IS_OBJECT (val))
return NULL;
+ if (JSVAL_IS_NULL (val))
+ return NULL;
object = JSVAL_TO_OBJECT (val);
klass = g_type_class_peek (type);
if (klass == NULL)
diff-tree 2f1ed9bb15785a9dfde7fdef1adc92346c11ab82 (from 2c8b93b57d2d93c187ac1e0c45667884047fc48d)
Author: Benjamin Otte <otte at gnome.org>
Date: Sun Jan 28 20:53:14 2007 +0100
implement Equals2 and fix If and Goto to jump correctly
7/44 failures (all due to NewObject)
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index b736136..8f86eea 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -776,7 +776,7 @@ swfdec_action_jump (JSContext *cx, guint
SWFDEC_ERROR ("Jump action length invalid (is %u, should be 2", len);
return JS_FALSE;
}
- cx->fp->pc += 4 + GINT16_FROM_LE (*((gint16*) data));
+ cx->fp->pc += 5 + GINT16_FROM_LE (*((gint16*) data));
return JS_TRUE;
}
@@ -792,7 +792,7 @@ swfdec_action_if (JSContext *cx, guint a
d = swfdec_action_to_number (cx, cx->fp->sp[-1]);
cx->fp->sp--;
if (d != 0)
- cx->fp->pc += 4 + GINT16_FROM_LE (*((gint16*) data));
+ cx->fp->pc += 5 + GINT16_FROM_LE (*((gint16*) data));
return JS_TRUE;
}
@@ -899,6 +899,56 @@ swfdec_action_less (JSContext *cx, guint
return JS_TRUE;
}
+static JSBool
+swfdec_action_equals2 (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ jsval rval, lval;
+ int ltag, rtag;
+ JSBool cond;
+
+ rval = cx->fp->sp[-1];
+ lval = cx->fp->sp[-2];
+ ltag = JSVAL_TAG(lval);
+ rtag = JSVAL_TAG(rval);
+ if (ltag == rtag) {
+ if (ltag == JSVAL_STRING) {
+ cond = js_CompareStrings (JSVAL_TO_STRING (lval), JSVAL_TO_STRING (rval)) == 0;
+ } else if (ltag == JSVAL_DOUBLE) {
+ cond = *JSVAL_TO_DOUBLE(lval) == *JSVAL_TO_DOUBLE(rval);
+ } else {
+ cond = lval == rval;
+ }
+ } else {
+ if (JSVAL_IS_NULL(lval) || JSVAL_IS_VOID(lval)) {
+ cond = (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval));
+ } else if (JSVAL_IS_NULL(rval) || JSVAL_IS_VOID(rval)) {
+ cond = JS_FALSE;
+ } else {
+ if (ltag == JSVAL_OBJECT) {
+ if (!OBJ_DEFAULT_VALUE (cx, JSVAL_TO_OBJECT(lval), 0, &lval))
+ return JS_FALSE;
+ ltag = JSVAL_TAG(lval);
+ } else if (rtag == JSVAL_OBJECT) {
+ if (!OBJ_DEFAULT_VALUE (cx, JSVAL_TO_OBJECT(rval), 0, &rval))
+ return JS_FALSE;
+ rtag = JSVAL_TAG(rval);
+ }
+ if (ltag == JSVAL_STRING && rtag == JSVAL_STRING) {
+ cond = js_CompareStrings (JSVAL_TO_STRING (lval), JSVAL_TO_STRING (rval)) == 0;
+ } else {
+ double d, d2;
+ if (!JS_ValueToNumber (cx, lval, &d) ||
+ !JS_ValueToNumber (cx, rval, &d2))
+ return JS_FALSE;
+ cond = d == d2;
+ }
+ }
+ }
+ cx->fp->sp--;
+ cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (cond);
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -1121,7 +1171,7 @@ static const SwfdecActionSpec actions[25
[0x46] = { "Enumerate", NULL },
[0x47] = { "Add2", NULL, 2, 1, { NULL, NULL, swfdec_action_add2_5, swfdec_action_add2_5, swfdec_action_add2_7 } },
[0x48] = { "Less2", NULL, 2, 1, { NULL, NULL, swfdec_action_new_comparison_6, swfdec_action_new_comparison_6, swfdec_action_new_comparison_7 } },
- [0x49] = { "Equals2", NULL },
+ [0x49] = { "Equals2", NULL, 2, 1, { NULL, NULL, swfdec_action_equals2, swfdec_action_equals2, swfdec_action_equals2 } },
[0x4a] = { "ToNumber", NULL },
[0x4b] = { "ToString", NULL },
[0x4c] = { "PushDuplicate", NULL, 1, 2, { NULL, NULL, swfdec_action_push_duplicate, swfdec_action_push_duplicate, swfdec_action_push_duplicate } },
diff-tree 2c8b93b57d2d93c187ac1e0c45667884047fc48d (from 0a490e81dada959efc3ed155a98b8de577ff4dd2)
Author: Benjamin Otte <otte at gnome.org>
Date: Sun Jan 28 20:52:23 2007 +0100
another fix for swfdec_js_internal
This code is nasty, I seriously have to clean it up
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index 62cf665..e501c4f 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -376,7 +376,7 @@ swfdec_js_eval_internal (JSContext *cx,
if (!swfdec_js_eval_get_property (cx, obj, str, strlen (str), &cur))
goto out;
}
- str = NULL;
+ goto finish;
}
obj = JSVAL_TO_OBJECT (cur);
}
@@ -387,6 +387,7 @@ swfdec_js_eval_internal (JSContext *cx,
cur = OBJECT_TO_JSVAL (cx->fp->scopeChain);
}
+finish:
g_free (work);
*val = cur;
return TRUE;
diff-tree 0a490e81dada959efc3ed155a98b8de577ff4dd2 (from 25d626bfbf646328e7209d72a6ebe73e1036b5b1)
Author: Benjamin Otte <otte at gnome.org>
Date: Sun Jan 28 19:32:59 2007 +0100
implement ActionLess
this includes a fix to swfdec_action_to_number since apparently Flash 4 pushes
numbers as strings and converts them for numerical operations.
9/44 failures in the testsuite
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index acb34fa..b736136 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -29,6 +29,7 @@
#include "js/jsinterp.h"
#include <string.h>
+#include <math.h>
#include "swfdec_decoder.h"
#include "swfdec_js.h"
#include "swfdec_movie.h"
@@ -523,6 +524,11 @@ swfdec_action_to_number (JSContext *cx,
return *JSVAL_TO_DOUBLE (val);
} else if (JSVAL_IS_BOOLEAN (val)) {
return JSVAL_TO_BOOLEAN (val);
+ } else if (JSVAL_IS_STRING (val)) {
+ double d;
+ if (!JS_ValueToNumber (cx, val, &d))
+ return 0;
+ return isnan (d) ? 0 : d;
} else {
return 0;
}
@@ -872,6 +878,27 @@ swfdec_action_random_number (JSContext *
return JS_NewNumberValue(cx, result, &cx->fp->sp[-1]);
}
+static JSBool
+swfdec_action_less (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ jsval rval, lval;
+ double l, r;
+ JSBool cond;
+
+ rval = cx->fp->sp[-1];
+ lval = cx->fp->sp[-2];
+ l = swfdec_action_to_number (cx, lval);
+ r = swfdec_action_to_number (cx, rval);
+ cond = l < r;
+ cx->fp->sp--;
+ if (((SwfdecScript *) cx->fp->swf)->version < 5) {
+ cx->fp->sp[-1] = INT_TO_JSVAL (cond ? 1 : 0);
+ } else {
+ cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (cond);
+ }
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -1044,7 +1071,7 @@ static const SwfdecActionSpec actions[25
[0x0c] = { "Multiply", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
[0x0d] = { "Divide", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
[0x0e] = { "Equals", NULL },
- [0x0f] = { "Less", NULL },
+ [0x0f] = { "Less", NULL, 2, 1, { NULL, swfdec_action_less, swfdec_action_less, swfdec_action_less, swfdec_action_less } },
[0x10] = { "And", NULL },
[0x11] = { "Or", NULL },
[0x12] = { "Not", NULL, 1, 1, { NULL, swfdec_action_not_4, swfdec_action_not_5, swfdec_action_not_5, swfdec_action_not_5 } },
diff-tree 25d626bfbf646328e7209d72a6ebe73e1036b5b1 (from ca7b42ca13e0758954f41e5f0dc673a90c07a89b)
Author: Benjamin Otte <otte at gnome.org>
Date: Sun Jan 28 19:11:03 2007 +0100
stop printing out all actions
That part of the code should work well enough now :)
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 0a40480..acb34fa 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -1227,7 +1227,7 @@ validate_action (gconstpointer bytecode,
return FALSE;
}
/* we might want to do stuff here for certain actions */
-#if 1
+#if 0
{
char *foo = swfdec_script_print_action (action, data, len);
if (foo == NULL)
diff-tree ca7b42ca13e0758954f41e5f0dc673a90c07a89b (from 635f8982ba523747ac79bc87a4d106ba61ba3b44)
Author: Benjamin Otte <otte at gnome.org>
Date: Sun Jan 28 19:04:42 2007 +0100
ints are ints not uints in Push action
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index a98b165..0a40480 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -260,8 +260,7 @@ swfdec_action_push (JSContext *cx, guint
}
case 7: /* 32bit int */
{
- /* FIXME: spec says U32, do they mean this? */
- guint i = swfdec_bits_get_u32 (&bits);
+ int i = swfdec_bits_get_u32 (&bits);
*cx->fp->sp++ = INT_TO_JSVAL (i);
break;
}
@@ -954,7 +953,7 @@ swfdec_action_print_push (guint action,
g_string_append_printf (string, "%g", swfdec_bits_get_double (&bits));
break;
case 7: /* 32bit int */
- g_string_append_printf (string, "%u", swfdec_bits_get_u32 (&bits));
+ g_string_append_printf (string, "%d", swfdec_bits_get_u32 (&bits));
break;
case 8: /* 8bit ConstantPool address */
g_string_append_printf (string, "Pool %u", swfdec_bits_get_u8 (&bits));
diff-tree 635f8982ba523747ac79bc87a4d106ba61ba3b44 (from 56d1844f206f946a24755bdb03ccfafdb5c51571)
Author: Benjamin Otte <otte at gnome.org>
Date: Sun Jan 28 19:00:06 2007 +0100
implement RandomNumber and PushDuplicate
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 22ada41..a98b165 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -849,6 +849,30 @@ swfdec_action_string_add (JSContext *cx,
return JS_TRUE;
}
+static JSBool
+swfdec_action_push_duplicate (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ cx->fp->sp++;
+ cx->fp->sp[-1] = cx->fp->sp[-2];
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_random_number (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ gint32 max, result;
+
+ if (!JS_ValueToECMAInt32 (cx, cx->fp->sp[-1], &max))
+ return JS_FALSE;
+
+ if (max <= 0)
+ result = 0;
+ else
+ result = g_random_int_range (0, max);
+
+ return JS_NewNumberValue(cx, result, &cx->fp->sp[-1]);
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -1047,7 +1071,7 @@ static const SwfdecActionSpec actions[25
[0x2b] = { "Cast", NULL },
[0x2c] = { "Implements", NULL },
/* version 4 */
- [0x30] = { "RandomNumber", NULL },
+ [0x30] = { "RandomNumber", NULL, 1, 1, { NULL, swfdec_action_random_number, swfdec_action_random_number, swfdec_action_random_number, swfdec_action_random_number } },
[0x31] = { "MBStringLength", NULL },
[0x32] = { "CharToAscii", NULL },
[0x33] = { "AsciiToChar", NULL },
@@ -1074,7 +1098,7 @@ static const SwfdecActionSpec actions[25
[0x49] = { "Equals2", NULL },
[0x4a] = { "ToNumber", NULL },
[0x4b] = { "ToString", NULL },
- [0x4c] = { "PushDuplicate", NULL },
+ [0x4c] = { "PushDuplicate", NULL, 1, 2, { NULL, NULL, swfdec_action_push_duplicate, swfdec_action_push_duplicate, swfdec_action_push_duplicate } },
[0x4d] = { "Swap", NULL },
[0x4e] = { "GetMember", NULL, 2, 1, { NULL, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member } },
[0x4f] = { "SetMember", NULL, 3, 0, { NULL, swfdec_action_set_member, swfdec_action_set_member, swfdec_action_set_member, swfdec_action_set_member } },
diff-tree 56d1844f206f946a24755bdb03ccfafdb5c51571 (from ca1d6d627bbc5c221ae0ef51d5b7a1c573fe32e5)
Author: Benjamin Otte <otte at gnome.org>
Date: Sun Jan 28 18:48:41 2007 +0100
implement naive Add2 for Flash 5 and 6
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 7848e14..22ada41 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -580,6 +580,49 @@ swfdec_action_binary (JSContext *cx, gui
return JS_NewNumberValue (cx, l, &cx->fp->sp[-1]);
}
+static JSString *
+swfdec_action_to_string_5 (JSContext *cx, jsval val)
+{
+ if (JSVAL_IS_VOID (val) || JSVAL_IS_NULL (val))
+ return cx->runtime->emptyString;
+ return js_ValueToString (cx, val);
+}
+
+static JSBool
+swfdec_action_add2_5 (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ jsval rval, lval;
+ gboolean cond;
+
+ rval = cx->fp->sp[-1];
+ lval = cx->fp->sp[-2];
+ if ((cond = JSVAL_IS_STRING (lval)) || JSVAL_IS_STRING (rval)) {
+ JSString *str, *str2;
+ if (cond) {
+ str = JSVAL_TO_STRING (lval);
+ if ((str2 = swfdec_action_to_string_5 (cx, rval)) == NULL)
+ return JS_FALSE;
+ } else {
+ str2 = JSVAL_TO_STRING (rval);
+ if ((str = swfdec_action_to_string_5 (cx, lval)) == NULL)
+ return JS_FALSE;
+ }
+ str = js_ConcatStrings (cx, str, str2);
+ if (!str)
+ return JS_FALSE;
+ cx->fp->sp--;
+ cx->fp->sp[-1] = STRING_TO_JSVAL (str);
+ } else {
+ double d, d2;
+ d = swfdec_action_to_number (cx, lval);
+ d2 = swfdec_action_to_number (cx, rval);
+ d += d2;
+ cx->fp->sp--;
+ return JS_NewNumberValue(cx, d, &cx->fp->sp[-1]);
+ }
+ return JS_TRUE;
+}
+
static JSBool
swfdec_action_add2_7 (JSContext *cx, guint action, const guint8 *data, guint len)
{
@@ -1026,7 +1069,7 @@ static const SwfdecActionSpec actions[25
[0x44] = { "Typeof", NULL },
[0x45] = { "TargetPath", NULL },
[0x46] = { "Enumerate", NULL },
- [0x47] = { "Add2", NULL, 2, 1, { NULL, NULL, NULL, NULL, swfdec_action_add2_7 } },
+ [0x47] = { "Add2", NULL, 2, 1, { NULL, NULL, swfdec_action_add2_5, swfdec_action_add2_5, swfdec_action_add2_7 } },
[0x48] = { "Less2", NULL, 2, 1, { NULL, NULL, swfdec_action_new_comparison_6, swfdec_action_new_comparison_6, swfdec_action_new_comparison_7 } },
[0x49] = { "Equals2", NULL },
[0x4a] = { "ToNumber", NULL },
diff-tree ca1d6d627bbc5c221ae0ef51d5b7a1c573fe32e5 (from 10d7419e68981104fb2e59b6d3df874170a977f1)
Author: Benjamin Otte <otte at gnome.org>
Date: Sun Jan 28 18:11:16 2007 +0100
implement alpha handling in a smarter way
diff --git a/libswfdec/swfdec_image.c b/libswfdec/swfdec_image.c
index 725ce74..23602c4 100644
--- a/libswfdec/swfdec_image.c
+++ b/libswfdec/swfdec_image.c
@@ -168,10 +168,18 @@ tag_func_define_bits_jpeg (SwfdecSwfDeco
return SWFDEC_STATUS_OK;
}
+static gboolean
+swfdec_image_has_alpha (SwfdecImage *image)
+{
+ return image->type == SWFDEC_IMAGE_TYPE_LOSSLESS2 ||
+ image->type == SWFDEC_IMAGE_TYPE_JPEG3;
+}
+
static void
-swfdec_image_create_surface (SwfdecImage *image, guint8 *data, gboolean has_alpha)
+swfdec_image_create_surface (SwfdecImage *image, guint8 *data)
{
static const cairo_user_data_key_t key;
+ gboolean has_alpha = swfdec_image_has_alpha (image);
g_assert (image->surface == NULL);
@@ -204,7 +212,7 @@ swfdec_image_jpeg_load (SwfdecImage *ima
jpeg_rgb_decoder_get_image (dec, &image_data,
&image->rowstride, NULL, NULL);
jpeg_rgb_decoder_free (dec);
- swfdec_image_create_surface (image, image_data, FALSE);
+ swfdec_image_create_surface (image, image_data);
SWFDEC_LOG (" width = %d", image->width);
SWFDEC_LOG (" height = %d", image->height);
@@ -252,7 +260,7 @@ swfdec_image_jpeg2_load (SwfdecImage *im
jpeg_rgb_decoder_get_image (dec, &image_data,
&image->rowstride, &image->width, &image->height);
jpeg_rgb_decoder_free (dec);
- swfdec_image_create_surface (image, image_data, FALSE);
+ swfdec_image_create_surface (image, image_data);
SWFDEC_LOG (" width = %d", image->width);
SWFDEC_LOG (" height = %d", image->height);
@@ -317,7 +325,7 @@ swfdec_image_jpeg3_load (SwfdecImage *im
merge_alpha (image, image_data, alpha_data);
g_free (alpha_data);
- swfdec_image_create_surface (image, image_data, TRUE);
+ swfdec_image_create_surface (image, image_data);
SWFDEC_LOG (" width = %d", image->width);
SWFDEC_LOG (" height = %d", image->height);
@@ -487,7 +495,7 @@ swfdec_image_lossless_load (SwfdecImage
#endif
}
- swfdec_image_create_surface (image, image_data, have_alpha);
+ swfdec_image_create_surface (image, image_data);
}
int
@@ -611,11 +619,7 @@ swfdec_image_get_surface_for_target (Swf
/* FIXME: we might want to create multiple surfaces here if there's multiple
* live rendering sources. Right now, this is the quick fix, that transforms
* the cache to the most recent used type */
- if (cairo_surface_get_type (current) == CAIRO_SURFACE_TYPE_IMAGE &&
- cairo_image_surface_get_format (current) == CAIRO_FORMAT_RGB24)
- content = CAIRO_CONTENT_COLOR;
- else
- content = CAIRO_CONTENT_COLOR_ALPHA;
+ content = swfdec_image_has_alpha (image) ? CAIRO_CONTENT_COLOR_ALPHA : CAIRO_CONTENT_COLOR;
similar = cairo_surface_create_similar (target,
content,
image->width, image->height);
diff-tree 10d7419e68981104fb2e59b6d3df874170a977f1 (from parents)
Merge: bf21308d97b50d9867f2c084122e5fc0cfd85f6e 2cb8680a8577ff5d018b50e7da55c233e8eaa4af
Author: Benjamin Otte <otte at gnome.org>
Date: Sun Jan 28 15:02:44 2007 +0100
Merge branch 'master' into interpreter
diff --cc libswfdec/swfdec_image.c
index 2810291,0cf6502..725ce74
@@@ -484,10 -512,9 +484,10 @@@
}
}
}
+#endif
}
- swfdec_image_create_surface (image, image_data);
+ swfdec_image_create_surface (image, image_data, have_alpha);
}
int
diff-tree bf21308d97b50d9867f2c084122e5fc0cfd85f6e (from e06edd91cd480f68e8612517abac3aa7a287abab)
Author: Benjamin Otte <otte at gnome.org>
Date: Sun Jan 28 14:52:16 2007 +0100
various fixes for the previous image decoding cleanups
diff --git a/libswfdec/swfdec_image.c b/libswfdec/swfdec_image.c
index c9df0de..2810291 100644
--- a/libswfdec/swfdec_image.c
+++ b/libswfdec/swfdec_image.c
@@ -117,7 +117,7 @@ lossless (const guint8 *zptr, int zlen,
z.avail_out = len;
ret = inflateInit (&z);
- ret = inflate (&z, Z_SYNC_FLUSH);
+ ret = inflate (&z, Z_FINISH);
if (ret != Z_STREAM_END) {
SWFDEC_WARNING ("lossless: ret == %d", ret);
}
@@ -348,9 +348,8 @@ static void
swfdec_image_lossless_load (SwfdecImage *image)
{
int format;
- int color_table_size;
+ guint color_table_size;
unsigned char *ptr;
- unsigned char *endptr;
SwfdecBits bits;
unsigned char *image_data = NULL;
int have_alpha = (image->type == SWFDEC_IMAGE_TYPE_LOSSLESS2);
@@ -377,66 +376,70 @@ swfdec_image_lossless_load (SwfdecImage
if (image->width == 0 || image->height == 0)
return;
swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height);
- ptr = lossless (bits.ptr, endptr - bits.ptr, image->width * image->height);
- bits.ptr = endptr;
if (format == 3) {
- unsigned char *color_table;
unsigned char *indexed_data;
- int i;
+ guint i;
+ unsigned int rowstride = (image->width + 3) & ~3;
image_data = g_malloc (4 * image->width * image->height);
image->rowstride = image->width * 4;
- color_table = g_malloc (color_table_size * 4);
-
if (have_alpha) {
+ ptr = lossless (bits.ptr, bits.end - bits.ptr,
+ color_table_size * 4 + rowstride * image->height);
for (i = 0; i < color_table_size; i++) {
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- color_table[i * 4 + 0] = ptr[i * 4 + 2];
- color_table[i * 4 + 1] = ptr[i * 4 + 1];
- color_table[i * 4 + 2] = ptr[i * 4 + 0];
- color_table[i * 4 + 3] = ptr[i * 4 + 3];
+ guint8 tmp = ptr[i * 4 + 0];
+ ptr[i * 4 + 0] = ptr[i * 4 + 2];
+ ptr[i * 4 + 2] = tmp;
#else
- color_table[i * 4 + 0] = ptr[i * 4 + 3];
- color_table[i * 4 + 1] = ptr[i * 4 + 0];
- color_table[i * 4 + 2] = ptr[i * 4 + 1];
- color_table[i * 4 + 3] = ptr[i * 4 + 2];
+ guint8 tmp = ptr[i * 4 + 3];
+ ptr[i * 4 + 3] = ptr[i * 4 + 2];
+ ptr[i * 4 + 2] = ptr[i * 4 + 1];
+ ptr[i * 4 + 1] = ptr[i * 4 + 0];
+ ptr[i * 4 + 0] = tmp;
#endif
}
indexed_data = ptr + color_table_size * 4;
} else {
- for (i = 0; i < color_table_size; i++) {
+ ptr = lossless (bits.ptr, bits.end - bits.ptr,
+ color_table_size * 3 + rowstride * image->height);
+ for (i = color_table_size - 1; i < color_table_size; i--) {
+ guint8 color[3];
+ color[0] = ptr[i * 3 + 0];
+ color[1] = ptr[i * 3 + 1];
+ color[2] = ptr[i * 3 + 2];
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- color_table[i * 4 + 0] = ptr[i * 3 + 2];
- color_table[i * 4 + 1] = ptr[i * 3 + 1];
- color_table[i * 4 + 2] = ptr[i * 3 + 0];
- color_table[i * 4 + 3] = 255;
+ ptr[i * 4 + 0] = color[2];
+ ptr[i * 4 + 1] = color[1];
+ ptr[i * 4 + 2] = color[0];
+ ptr[i * 4 + 3] = 255;
#else
- color_table[i * 4 + 0] = 255;
- color_table[i * 4 + 1] = ptr[i * 3 + 0];
- color_table[i * 4 + 2] = ptr[i * 3 + 1];
- color_table[i * 4 + 3] = ptr[i * 3 + 2];
+ ptr[i * 4 + 0] = 255;
+ ptr[i * 4 + 1] = color[0];
+ ptr[i * 4 + 2] = color[1];
+ ptr[i * 4 + 3] = color[2];
#endif
}
indexed_data = ptr + color_table_size * 3;
}
swfdec_image_colormap_decode (image, image_data, indexed_data,
- color_table, color_table_size);
+ ptr, color_table_size);
- g_free (color_table);
g_free (ptr);
}
if (format == 4) {
- unsigned char *p = ptr;
int i, j;
unsigned int c;
unsigned char *idata;
if (have_alpha) {
SWFDEC_INFO("16bit images aren't allowed to have alpha, ignoring");
+ have_alpha = FALSE;
}
+ ptr = lossless (bits.ptr, bits.end - bits.ptr, 2 * image->width * image->height);
image_data = g_malloc (4 * image->width * image->height);
idata = image_data;
image->rowstride = image->width * 4;
@@ -444,7 +447,7 @@ swfdec_image_lossless_load (SwfdecImage
/* 15 bit packed */
for (j = 0; j < image->height; j++) {
for (i = 0; i < image->width; i++) {
- c = p[1] | (p[0] << 8);
+ c = ptr[1] | (ptr[0] << 8);
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
idata[0] = (c << 3) | ((c >> 2) & 0x7);
idata[1] = ((c >> 2) & 0xf8) | ((c >> 7) & 0x7);
@@ -456,32 +459,32 @@ swfdec_image_lossless_load (SwfdecImage
idata[1] = ((c >> 7) & 0xf8) | ((c >> 12) & 0x7);
idata[0] = 0xff;
#endif
- p += 2;
+ ptr += 2;
idata += 4;
}
}
g_free (ptr);
}
if (format == 5) {
- int i, j;
- image_data = ptr;
+ image_data = lossless (bits.ptr, bits.end - bits.ptr, 4 * image->width * image->height);
image->rowstride = image->width * 4;
- if (!have_alpha) {
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ {
+ int i, j;
/* image is stored in 0RGB format. We use ARGB/BGRA. */
for (j = 0; j < image->height; j++) {
for (i = 0; i < image->width; i++) {
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
ptr[0] = ptr[3];
ptr[1] = ptr[2];
ptr[2] = ptr[1];
ptr[3] = 255;
-#endif
ptr += 4;
}
}
}
+#endif
}
swfdec_image_create_surface (image, image_data);
diff-tree e06edd91cd480f68e8612517abac3aa7a287abab (from 6f0034ba32dd13577f1f2fb050734a7c55b4fdec)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Jan 26 21:50:33 2007 +0100
fix "this" in swfdec_js_eval
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index 68e89ff..62cf665 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -351,13 +351,14 @@ swfdec_js_eval_internal (JSContext *cx,
work = swfdec_js_slash_to_dot (str);
str = work;
}
- if (g_str_has_prefix (str, "this")) {
+ if (obj == NULL && g_str_has_prefix (str, "this")) {
str += 4;
if (*str == '.')
str++;
if (cx->fp == NULL)
goto out;
obj = cx->fp->thisp;
+ cur = OBJECT_TO_JSVAL (obj);
}
while (str != NULL && *str != '\0') {
char *dot = strchr (str, '.');
diff-tree 6f0034ba32dd13577f1f2fb050734a7c55b4fdec (from db8da8e1714ce0839759c2fd0e65fbd6debf51fa)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Jan 26 21:32:40 2007 +0100
use NULL in _eval of SetVariable and GetVariable to walk the scope chain
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index a3bb563..7848e14 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -316,7 +316,7 @@ swfdec_action_get_variable (JSContext *c
s = swfdec_js_to_string (cx, cx->fp->sp[-1]);
if (s == NULL)
return JS_FALSE;
- cx->fp->sp[-1] = swfdec_js_eval (cx, cx->fp->scopeChain, s);
+ cx->fp->sp[-1] = swfdec_js_eval (cx, NULL, s);
return JS_TRUE;
}
@@ -329,7 +329,7 @@ swfdec_action_set_variable (JSContext *c
if (s == NULL)
return JS_FALSE;
- swfdec_js_eval_set (cx, cx->fp->scopeChain, s, cx->fp->sp[-1]);
+ swfdec_js_eval_set (cx, NULL, s, cx->fp->sp[-1]);
cx->fp->sp -= 2;
return JS_TRUE;
}
diff-tree db8da8e1714ce0839759c2fd0e65fbd6debf51fa (from 2321fe755e190939f34b1d27b306a5270f17f43c)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Jan 26 21:32:04 2007 +0100
more fixes for swfdec_eval when parsing the scope chain
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index 84a1113..68e89ff 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -318,8 +318,6 @@ swfdec_js_eval_get_property (JSContext *
return JS_FALSE;
if (!prop)
return JS_FALSE;
- if (pobj)
- obj = pobj;
return OBJ_GET_PROPERTY (cx, obj, (jsid) prop->id, ret);
}
}
@@ -345,7 +343,7 @@ static gboolean
swfdec_js_eval_internal (JSContext *cx, JSObject *obj, const char *str,
jsval *val, gboolean set)
{
- jsval cur;
+ jsval cur = JSVAL_NULL;
char *work = NULL;
SWFDEC_LOG ("eval called with \"%s\" on %p", str, obj);
@@ -361,12 +359,10 @@ swfdec_js_eval_internal (JSContext *cx,
goto out;
obj = cx->fp->thisp;
}
- cur = OBJECT_TO_JSVAL (obj);
while (str != NULL && *str != '\0') {
char *dot = strchr (str, '.');
if (!JSVAL_IS_OBJECT (cur))
goto out;
- obj = JSVAL_TO_OBJECT (cur);
if (dot) {
if (!swfdec_js_eval_get_property (cx, obj, str, dot - str, &cur))
goto out;
@@ -381,6 +377,7 @@ swfdec_js_eval_internal (JSContext *cx,
}
str = NULL;
}
+ obj = JSVAL_TO_OBJECT (cur);
}
if (obj == NULL) {
if (cx->fp == NULL)
diff-tree 2321fe755e190939f34b1d27b306a5270f17f43c (from 5fbaf958eeb90c6052933d2df118dc77fe18b15d)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Jan 26 18:17:39 2007 +0100
avoid strdup in js_eval
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index 9c01869..84a1113 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -300,13 +300,13 @@ fail:
static JSBool
swfdec_js_eval_get_property (JSContext *cx, JSObject *obj,
- const char *name, jsval *ret)
+ const char *name, guint name_len, jsval *ret)
{
JSAtom *atom;
JSObject *pobj;
JSProperty *prop;
- atom = js_Atomize (cx, name, strlen(name), 0);
+ atom = js_Atomize (cx, name, name_len, 0);
if (!atom)
return JS_FALSE;
if (obj) {
@@ -326,11 +326,11 @@ swfdec_js_eval_get_property (JSContext *
static JSBool
swfdec_js_eval_set_property (JSContext *cx, JSObject *obj,
- const char *name, jsval *ret)
+ const char *name, guint name_len, jsval *ret)
{
JSAtom *atom;
- atom = js_Atomize (cx, name, strlen(name), 0);
+ atom = js_Atomize (cx, name, name_len, 0);
if (!atom)
return JS_FALSE;
if (obj == NULL) {
@@ -368,17 +368,15 @@ swfdec_js_eval_internal (JSContext *cx,
goto out;
obj = JSVAL_TO_OBJECT (cur);
if (dot) {
- char *name = g_strndup (str, dot - str);
- if (!swfdec_js_eval_get_property (cx, obj, name, &cur))
+ if (!swfdec_js_eval_get_property (cx, obj, str, dot - str, &cur))
goto out;
- g_free (name);
str = dot + 1;
} else {
if (set) {
- if (!swfdec_js_eval_set_property (cx, obj, str, val))
+ if (!swfdec_js_eval_set_property (cx, obj, str, strlen (str), val))
goto out;
} else {
- if (!swfdec_js_eval_get_property (cx, obj, str, &cur))
+ if (!swfdec_js_eval_get_property (cx, obj, str, strlen (str), &cur))
goto out;
}
str = NULL;
diff-tree 5fbaf958eeb90c6052933d2df118dc77fe18b15d (from 6e0acc92fadc5b3ae1eaab51f3e16f3f96830e7a)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Jan 26 18:15:16 2007 +0100
fix _eval to work with the empty string
This is a regression fix
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index 7111833..9c01869 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -384,6 +384,12 @@ swfdec_js_eval_internal (JSContext *cx,
str = NULL;
}
}
+ if (obj == NULL) {
+ if (cx->fp == NULL)
+ goto out;
+ g_assert (cx->fp->scopeChain);
+ cur = OBJECT_TO_JSVAL (cx->fp->scopeChain);
+ }
g_free (work);
*val = cur;
diff-tree 6e0acc92fadc5b3ae1eaab51f3e16f3f96830e7a (from ea89d7b542169e7173d93938041a16515b93c896)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Jan 26 18:12:00 2007 +0100
set property on the right object
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index 524707c..7111833 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -329,25 +329,16 @@ swfdec_js_eval_set_property (JSContext *
const char *name, jsval *ret)
{
JSAtom *atom;
- JSObject *pobj;
- JSProperty *prop;
atom = js_Atomize (cx, name, strlen(name), 0);
if (!atom)
return JS_FALSE;
- if (obj) {
- return OBJ_SET_PROPERTY (cx, obj, (jsid) atom, ret);
- } else {
+ if (obj == NULL) {
if (cx->fp == NULL || cx->fp->scopeChain == NULL)
return JS_FALSE;
- if (!js_FindProperty (cx, (jsid) atom, &obj, &pobj, &prop))
- return JS_FALSE;
- if (!prop)
- return JS_FALSE;
- if (pobj)
- obj = pobj;
- return OBJ_SET_PROPERTY (cx, obj, (jsid) prop->id, ret);
+ obj = cx->fp->scopeChain;
}
+ return OBJ_SET_PROPERTY (cx, obj, (jsid) atom, ret);
}
static gboolean
diff-tree ea89d7b542169e7173d93938041a16515b93c896 (from 52828a39c261a28bf65734800692391b4f76b7c8)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Jan 26 18:06:33 2007 +0100
makee debugging work again
I don't like the debugging implementation in SpiderMonkey at all,
since it's too intrusive, but oh well...
diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am
index 7233f02..0216266 100644
--- a/libswfdec/Makefile.am
+++ b/libswfdec/Makefile.am
@@ -15,7 +15,6 @@ lib_LTLIBRARIES = libswfdec- at SWFDEC_MAJO
js_cflags = -I$(srcdir)/js/ -I./js -DXP_UNIX -DDEBUG
-# swfdec_debugger.c
libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES = \
swfdec_audio.c \
swfdec_audio_event.c \
@@ -34,6 +33,7 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES
swfdec_codec_screen.c \
swfdec_color.c \
swfdec_debug.c \
+ swfdec_debugger.c \
swfdec_decoder.c \
swfdec_edittext.c \
swfdec_edittext_movie.c \
diff --git a/libswfdec/swfdec_debugger.c b/libswfdec/swfdec_debugger.c
index 6123389..9a255b8 100644
--- a/libswfdec/swfdec_debugger.c
+++ b/libswfdec/swfdec_debugger.c
@@ -28,20 +28,36 @@
#include "swfdec_movie.h"
#include "swfdec_player_internal.h"
#include "js/jsdbgapi.h"
+#include "js/jsinterp.h" /* for frame->swf */
/*** SwfdecDebuggerScript ***/
+static gboolean
+swfdec_debugger_add_command (gconstpointer bytecode, guint action,
+ const guint8 *data, guint len, gpointer arrayp)
+{
+ SwfdecDebuggerCommand command;
+
+ command.code = bytecode;
+ command.breakpoint = 0;
+ command.description = swfdec_script_print_action (action, data, len);
+ g_array_append_val (arrayp, command);
+ return TRUE;
+}
+
static SwfdecDebuggerScript *
-swfdec_debugger_script_new (JSScript *script, const char *name,
- SwfdecDebuggerCommand *commands, guint n_commands)
+swfdec_debugger_script_new (SwfdecScript *script)
{
+ GArray *array;
SwfdecDebuggerScript *ret;
ret = g_new0 (SwfdecDebuggerScript, 1);
ret->script = script;
- ret->name = g_strdup (name);
- ret->commands = commands;
- ret->n_commands = n_commands;
+ swfdec_script_ref (script);
+ array = g_array_new (TRUE, FALSE, sizeof (SwfdecDebuggerCommand));
+ swfdec_script_foreach (script, swfdec_debugger_add_command, array);
+ ret->n_commands = array->len;
+ ret->commands = (SwfdecDebuggerCommand *) g_array_free (array, FALSE);
return ret;
}
@@ -49,7 +65,13 @@ swfdec_debugger_script_new (JSScript *sc
static void
swfdec_debugger_script_free (SwfdecDebuggerScript *script)
{
+ guint i;
+
g_assert (script);
+ swfdec_script_unref (script->script);
+ for (i = 0; i < script->n_commands; i++) {
+ g_free (script->commands[i].description);
+ }
g_free (script->commands);
g_free (script);
}
@@ -131,17 +153,16 @@ swfdec_debugger_new (void)
}
void
-swfdec_debugger_add_script (SwfdecDebugger *debugger, JSScript *jscript, const char *name,
- SwfdecDebuggerCommand *commands, guint n_commands)
+swfdec_debugger_add_script (SwfdecDebugger *debugger, SwfdecScript *script)
{
- SwfdecDebuggerScript *dscript = swfdec_debugger_script_new (jscript, name, commands, n_commands);
+ SwfdecDebuggerScript *dscript = swfdec_debugger_script_new (script);
- g_hash_table_insert (debugger->scripts, jscript, dscript);
+ g_hash_table_insert (debugger->scripts, script, dscript);
g_signal_emit (debugger, signals[SCRIPT_ADDED], 0, dscript);
}
SwfdecDebuggerScript *
-swfdec_debugger_get_script (SwfdecDebugger *debugger, JSScript *script)
+swfdec_debugger_get_script (SwfdecDebugger *debugger, SwfdecScript *script)
{
SwfdecDebuggerScript *dscript = g_hash_table_lookup (debugger->scripts, script);
@@ -149,7 +170,7 @@ swfdec_debugger_get_script (SwfdecDebugg
}
void
-swfdec_debugger_remove_script (SwfdecDebugger *debugger, JSScript *script)
+swfdec_debugger_remove_script (SwfdecDebugger *debugger, SwfdecScript *script)
{
SwfdecDebuggerScript *dscript = g_hash_table_lookup (debugger->scripts, script);
@@ -211,15 +232,43 @@ swfdec_debugger_do_breakpoint (SwfdecDeb
}
static JSTrapStatus
-swfdec_debugger_handle_breakpoint (JSContext *cx, JSScript *script, jsbytecode *pc,
- jsval *rval, void *closure)
+swfdec_debugger_interrupt_cb (JSContext *cx, JSScript *script,
+ jsbytecode *pc, jsval *rval, void *debugger)
{
- SwfdecDebugger *debugger = JS_GetContextPrivate (cx);
-
- swfdec_debugger_do_breakpoint (debugger, GPOINTER_TO_UINT (closure));
+ SwfdecDebuggerScript *dscript;
+ guint line;
+ if (!swfdec_debugger_get_current (debugger, &dscript, &line))
+ return JSTRAP_CONTINUE;
+ if (dscript->commands[line].breakpoint) {
+ swfdec_debugger_do_breakpoint (debugger, dscript->commands[line].breakpoint);
+ } else if (SWFDEC_DEBUGGER (debugger)->stepping) {
+ swfdec_debugger_do_breakpoint (debugger, 0);
+ }
return JSTRAP_CONTINUE;
}
+static void
+swfdec_debugger_update_interrupting (SwfdecDebugger *debugger)
+{
+ guint i;
+ gboolean should_interrupt = debugger->stepping;
+
+ for (i = 1; i < debugger->breakpoints->len && !should_interrupt; i++) {
+ Breakpoint *br = &g_array_index (debugger->breakpoints, Breakpoint, i);
+
+ if (br->script) {
+ should_interrupt = TRUE;
+ break;
+ }
+ }
+ if (should_interrupt) {
+ JS_SetInterrupt (JS_GetRuntime (SWFDEC_PLAYER (debugger)->jscx),
+ swfdec_debugger_interrupt_cb, debugger);
+ } else {
+ JS_ClearInterrupt (JS_GetRuntime (SWFDEC_PLAYER (debugger)->jscx), NULL, NULL);
+ }
+}
+
guint
swfdec_debugger_set_breakpoint (SwfdecDebugger *debugger,
SwfdecDebuggerScript *script, guint line)
@@ -242,10 +291,6 @@ swfdec_debugger_set_breakpoint (SwfdecDe
break;
br = NULL;
}
- if (!JS_SetTrap (SWFDEC_PLAYER (debugger)->jscx, script->script,
- script->commands[line].code, swfdec_debugger_handle_breakpoint,
- GUINT_TO_POINTER (i + 1)))
- return 0;
if (br == NULL) {
g_array_set_size (debugger->breakpoints, debugger->breakpoints->len + 1);
@@ -255,6 +300,7 @@ swfdec_debugger_set_breakpoint (SwfdecDe
br->script = script;
br->line = line;
script->commands[line].breakpoint = i + 1;
+ swfdec_debugger_update_interrupting (debugger);
g_signal_emit (debugger, signals[BREAKPOINT_ADDED], 0, i + 1);
return i + 1;
}
@@ -275,16 +321,15 @@ swfdec_debugger_unset_breakpoint (Swfdec
if (br->script == NULL)
return;
- JS_ClearTrap (SWFDEC_PLAYER (debugger)->jscx, br->script->script,
- br->script->commands[br->line].code, NULL, NULL);
g_signal_emit (debugger, signals[BREAKPOINT_REMOVED], 0, id);
br->script->commands[br->line].breakpoint = 0;
br->script = NULL;
+ swfdec_debugger_update_interrupting (debugger);
}
static gboolean
-swfdec_debugger_get_from_js (SwfdecDebugger *debugger, JSScript *script, jsbytecode *pc,
- SwfdecDebuggerScript **script_out, guint *line_out)
+swfdec_debugger_get_from_js (SwfdecDebugger *debugger, SwfdecScript *script,
+ jsbytecode *pc, SwfdecDebuggerScript **script_out, guint *line_out)
{
guint line;
SwfdecDebuggerScript *dscript = swfdec_debugger_get_script (debugger, script);
@@ -292,7 +337,7 @@ swfdec_debugger_get_from_js (SwfdecDebug
if (dscript == NULL)
return FALSE;
for (line = 0; line < dscript->n_commands; line++) {
- if (pc == (jsbytecode *) dscript->commands[line].code) {
+ if (pc == dscript->commands[line].code) {
if (script_out)
*script_out = dscript;
if (line_out)
@@ -311,16 +356,16 @@ swfdec_debugger_get_current (SwfdecDebug
{
JSStackFrame *frame = NULL;
JSContext *cx;
- JSScript *script;
jsbytecode *pc;
cx = SWFDEC_PLAYER (debugger)->jscx;
JS_FrameIterator (cx, &frame);
if (frame == NULL)
return FALSE;
- script = JS_GetFrameScript (cx, frame);
+ if (frame->swf == NULL)
+ return FALSE;
pc = JS_GetFramePC (cx, frame);
- return swfdec_debugger_get_from_js (debugger, script, pc, dscript, line);
+ return swfdec_debugger_get_from_js (debugger, frame->swf, pc, dscript, line);
}
gboolean
@@ -358,15 +403,6 @@ swfdec_debugger_get_n_breakpoints (Swfde
return debugger->breakpoints->len;
}
-static JSTrapStatus
-swfdec_debugger_interrupt_cb (JSContext *cx, JSScript *script,
- jsbytecode *pc, jsval *rval, void *debugger)
-{
- if (swfdec_debugger_get_current (debugger, NULL, NULL))
- swfdec_debugger_do_breakpoint (debugger, 0);
- return JSTRAP_CONTINUE;
-}
-
void
swfdec_debugger_set_stepping (SwfdecDebugger *debugger, gboolean stepping)
{
@@ -375,12 +411,6 @@ swfdec_debugger_set_stepping (SwfdecDebu
if (debugger->stepping == stepping)
return;
debugger->stepping = stepping;
- if (stepping) {
- JS_SetInterrupt (JS_GetRuntime (SWFDEC_PLAYER (debugger)->jscx),
- swfdec_debugger_interrupt_cb, debugger);
- } else {
- JS_ClearInterrupt (JS_GetRuntime (SWFDEC_PLAYER (debugger)->jscx), NULL, NULL);
- }
}
gboolean
diff --git a/libswfdec/swfdec_debugger.h b/libswfdec/swfdec_debugger.h
index bd54f9f..7c87604 100644
--- a/libswfdec/swfdec_debugger.h
+++ b/libswfdec/swfdec_debugger.h
@@ -23,8 +23,8 @@
#include <glib-object.h>
#include <libswfdec/swfdec.h>
#include <libswfdec/swfdec_player_internal.h>
+#include <libswfdec/swfdec_script.h>
#include <libswfdec/swfdec_types.h>
-#include <libswfdec/js/jsapi.h>
G_BEGIN_DECLS
@@ -41,14 +41,13 @@ typedef struct _SwfdecDebuggerCommand Sw
#define SWFDEC_DEBUGGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFDEC_TYPE_DEBUGGER, SwfdecDebuggerClass))
struct _SwfdecDebuggerCommand {
- gpointer code; /* pointer to start bytecode in JScript */
+ gconstpointer code; /* pointer to start bytecode in SwfdecScript */
guint breakpoint; /* id of breakpoint pointing here */
char * description; /* string describing the action */
};
struct _SwfdecDebuggerScript {
- JSScript * script; /* the script */
- char * name; /* descriptive name of script */
+ SwfdecScript * script; /* the script */
SwfdecDebuggerCommand *commands; /* commands executed in the script (NULL-terminated) */
guint n_commands; /* number of commands */
};
@@ -88,14 +87,11 @@ void swfdec_debugger_set_stepping (Swf
gboolean swfdec_debugger_get_stepping (SwfdecDebugger * debugger);
void swfdec_debugger_add_script (SwfdecDebugger * debugger,
- JSScript * script,
- const char * name,
- SwfdecDebuggerCommand *commands,
- guint n_commands);
+ SwfdecScript * script);
SwfdecDebuggerScript * swfdec_debugger_get_script (SwfdecDebugger * debugger,
- JSScript * script);
+ SwfdecScript * script);
void swfdec_debugger_remove_script (SwfdecDebugger * debugger,
- JSScript * script);
+ SwfdecScript * script);
void swfdec_debugger_foreach_script (SwfdecDebugger * debugger,
GFunc func,
gpointer data);
diff --git a/libswfdec/swfdec_event.c b/libswfdec/swfdec_event.c
index 7ed820b..d988ad3 100644
--- a/libswfdec/swfdec_event.c
+++ b/libswfdec/swfdec_event.c
@@ -146,7 +146,7 @@ swfdec_event_list_parse (SwfdecEventList
event.key = key;
name = g_strconcat (description, ".",
swfdec_event_list_condition_name (conditions), NULL);
- event.script = swfdec_script_new (bits, name, version);
+ event.script = swfdec_script_new_for_player (list->player, bits, name, version);
g_free (name);
if (event.script)
g_array_append_val (list->events, event);
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index e5c205f..a3bb563 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -23,6 +23,7 @@
#include "swfdec_script.h"
#include "swfdec_debug.h"
+#include "swfdec_debugger.h"
#include "swfdec_scriptable.h"
#include "js/jscntxt.h"
#include "js/jsinterp.h"
@@ -1105,13 +1106,14 @@ swfdec_script_print_action (guint action
}
}
-typedef gboolean (* SwfdecScriptForeachFunc) (guint action, const guint8 *data, guint len, gpointer user_data);
static gboolean
-swfdec_script_foreach (SwfdecBits *bits, SwfdecScriptForeachFunc func, gpointer user_data)
+swfdec_script_foreach_internal (SwfdecBits *bits, SwfdecScriptForeachFunc func, gpointer user_data)
{
guint action, len;
const guint8 *data;
+ gconstpointer bytecode;
+ bytecode = bits->ptr;
while ((action = swfdec_bits_get_u8 (bits))) {
if (action & 0x80) {
len = swfdec_bits_get_u16 (bits);
@@ -1124,16 +1126,29 @@ swfdec_script_foreach (SwfdecBits *bits,
SWFDEC_ERROR ("script too short");
return FALSE;
}
- if (!func (action, data, len, user_data))
+ if (!func (bytecode, action, data, len, user_data))
return FALSE;
+ bytecode = bits->ptr;
}
return TRUE;
}
/*** PUBLIC API ***/
+gboolean
+swfdec_script_foreach (SwfdecScript *script, SwfdecScriptForeachFunc func, gpointer user_data)
+{
+ SwfdecBits bits;
+
+ g_return_val_if_fail (script != NULL, FALSE);
+ g_return_val_if_fail (func != NULL, FALSE);
+
+ swfdec_bits_init (&bits, script->buffer);
+ return swfdec_script_foreach_internal (&bits, func, user_data);
+}
+
static gboolean
-validate_action (guint action, const guint8 *data, guint len, gpointer scriptp)
+validate_action (gconstpointer bytecode, guint action, const guint8 *data, guint len, gpointer scriptp)
{
SwfdecScript *script = scriptp;
int version = EXTRACT_VERSION (script->version);
@@ -1158,12 +1173,30 @@ validate_action (guint action, const gui
}
SwfdecScript *
+swfdec_script_new_for_player (SwfdecPlayer *player, SwfdecBits *bits,
+ const char *name, unsigned int version)
+{
+ SwfdecScript *script;
+
+ g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
+ g_return_val_if_fail (bits != NULL, NULL);
+
+ script = swfdec_script_new (bits, name, version);
+ if (SWFDEC_IS_DEBUGGER (player) && script) {
+ swfdec_debugger_add_script (SWFDEC_DEBUGGER (player), script);
+ script->debugger = player;
+ }
+ return script;
+}
+
+SwfdecScript *
swfdec_script_new (SwfdecBits *bits, const char *name, unsigned int version)
{
SwfdecScript *script;
const guchar *start;
g_return_val_if_fail (bits != NULL, NULL);
+
if (version < MINSCRIPTVERSION) {
SWFDEC_ERROR ("swfdec version %u doesn't support scripts", version);
return NULL;
@@ -1176,7 +1209,7 @@ swfdec_script_new (SwfdecBits *bits, con
script->name = g_strdup (name ? name : "Unnamed script");
script->version = version;
- if (!swfdec_script_foreach (bits, validate_action, script)) {
+ if (!swfdec_script_foreach_internal (bits, validate_action, script)) {
/* assign a random buffer here so we have something to unref */
script->buffer = bits->buffer;
swfdec_buffer_ref (script->buffer);
@@ -1203,6 +1236,11 @@ swfdec_script_unref (SwfdecScript *scrip
g_return_if_fail (script->refcount > 0);
script->refcount--;
+ if (script->refcount == 1 && script->debugger) {
+ script->debugger = NULL;
+ swfdec_debugger_remove_script (script->debugger, script);
+ return;
+ }
if (script->refcount > 0)
return;
@@ -1266,13 +1304,37 @@ swfdec_script_interpret (SwfdecScript *s
goto out;
}
- /* only valid return value */
while (TRUE) {
/* check pc */
if (pc < startpc || pc >= endpc) {
SWFDEC_ERROR ("pc %p not in valid range [%p, %p] anymore", pc, startpc, endpc);
goto internal_error;
}
+
+ /* run interrupt handler */
+ if (cx->runtime->interruptHandler) {
+ jsval tmp;
+ switch (cx->runtime->interruptHandler (cx, NULL, pc, &tmp,
+ cx->runtime->interruptHandlerData)) {
+ case JSTRAP_ERROR:
+ ok = JS_FALSE;
+ goto out;
+ case JSTRAP_CONTINUE:
+ break;
+ case JSTRAP_RETURN:
+ fp->rval = tmp;
+ goto out;
+ case JSTRAP_THROW:
+ cx->throwing = JS_TRUE;
+ cx->exception = tmp;
+ ok = JS_FALSE;
+ goto out;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+ }
+
/* decode next action */
action = *pc;
spec = actions + action;
@@ -1433,3 +1495,4 @@ swfdec_script_execute (SwfdecScript *scr
return ok ? frame.rval : JSVAL_VOID;
}
+
diff --git a/libswfdec/swfdec_script.h b/libswfdec/swfdec_script.h
index d8688c3..1cea4a7 100644
--- a/libswfdec/swfdec_script.h
+++ b/libswfdec/swfdec_script.h
@@ -29,17 +29,25 @@ G_BEGIN_DECLS
//typedef struct _SwfdecScript SwfdecScript;
+typedef gboolean (* SwfdecScriptForeachFunc) (gconstpointer bytecode, guint action,
+ const guint8 *data, guint len, gpointer user_data);
+
/* FIXME: May want to typedef to SwfdecBuffer directly */
struct _SwfdecScript {
SwfdecBuffer * buffer; /* buffer holding the script */
unsigned int refcount; /* reference count */
char * name; /* name identifying this script */
unsigned int version; /* version of the script */
+ gpointer debugger; /* debugger owning us or NULL */
};
SwfdecScript * swfdec_script_new (SwfdecBits * bits,
const char * name,
unsigned int version);
+SwfdecScript * swfdec_script_new_for_player (SwfdecPlayer * player,
+ SwfdecBits * bits,
+ const char * name,
+ unsigned int version);
void swfdec_script_ref (SwfdecScript * script);
void swfdec_script_unref (SwfdecScript * script);
@@ -49,9 +57,13 @@ JSBool swfdec_script_interpret (Swfdec
jsval swfdec_script_execute (SwfdecScript * script,
SwfdecScriptable * scriptable);
+gboolean swfdec_script_foreach (SwfdecScript * script,
+ SwfdecScriptForeachFunc func,
+ gpointer user_data);
char * swfdec_script_print_action (guint action,
const guint8 * data,
guint len);
+
G_END_DECLS
#endif
diff --git a/libswfdec/swfdec_tag.c b/libswfdec/swfdec_tag.c
index 3896101..e7c8aa8 100644
--- a/libswfdec/swfdec_tag.c
+++ b/libswfdec/swfdec_tag.c
@@ -297,7 +297,7 @@ tag_func_do_action (SwfdecSwfDecoder * s
name = g_strdup_printf ("Sprite%u.Frame%u", SWFDEC_CHARACTER (s->parse_sprite)->id,
s->parse_sprite->parse_frame);
- script = swfdec_script_new (&s->b, name, s->version);
+ script = swfdec_script_new_for_player (SWFDEC_DECODER (s)->player, &s->b, name, s->version);
g_free (name);
if (script)
swfdec_sprite_add_action (s->parse_sprite, s->parse_sprite->parse_frame,
diff --git a/player/swfdec_debug_scripts.c b/player/swfdec_debug_scripts.c
index 89bebce..3877da8 100644
--- a/player/swfdec_debug_scripts.c
+++ b/player/swfdec_debug_scripts.c
@@ -40,7 +40,7 @@ add_row (gpointer scriptp, gpointer stor
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, COLUMN_SCRIPT, script,
- COLUMN_NAME, script->name, -1);
+ COLUMN_NAME, script->script->name, -1);
}
static void
diff --git a/player/swfdec_player_manager.c b/player/swfdec_player_manager.c
index d51e49b..82d55ed 100644
--- a/player/swfdec_player_manager.c
+++ b/player/swfdec_player_manager.c
@@ -137,7 +137,7 @@ swfdec_player_manager_class_init (Swfdec
signals[MESSAGE] = g_signal_new ("message", G_TYPE_FROM_CLASS (g_class),
G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__UINT_POINTER, /* FIXME */
- G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_STRING);
+ G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_POINTER);
}
static void
@@ -458,7 +458,7 @@ command_break (SwfdecPlayerManager *mana
guint id = swfdec_debugger_set_breakpoint (SWFDEC_DEBUGGER (manager->player),
manager->interrupt_script, line);
swfdec_player_manager_output (manager, "%u: %s line %u: %s",
- id, manager->interrupt_script->name, line,
+ id, manager->interrupt_script->script->name, line,
manager->interrupt_script->commands[line].description);
} else {
swfdec_player_manager_error (manager,
@@ -494,7 +494,7 @@ command_breakpoints (SwfdecPlayerManager
for (i = 1; i <= n; i++) {
if (swfdec_debugger_get_breakpoint (debugger, i, &script, &line)) {
swfdec_player_manager_output (manager, "%u: %s line %u: %s",
- i, script->name, line, script->commands[line].description);
+ i, script->script->name, line, script->commands[line].description);
}
}
}
@@ -552,7 +552,7 @@ do_find (gpointer scriptp, gpointer data
for (i = 0; i < script->n_commands; i++) {
if (strstr (script->commands[i].description, data->string)) {
swfdec_player_manager_output (data->manager, "%s %u: %s",
- script->name, i, script->commands[i].description);
+ script->script->name, i, script->commands[i].description);
}
}
}
diff-tree 52828a39c261a28bf65734800692391b4f76b7c8 (from b8b6df20af7044cda18cfde12662492f2903ecb0)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Jan 26 18:05:39 2007 +0100
use automatic hscrollbars, too
diff --git a/player/swfdebug.c b/player/swfdebug.c
index 2f041f1..490814e 100644
--- a/player/swfdebug.c
+++ b/player/swfdebug.c
@@ -214,7 +214,7 @@ view_swf (SwfdecPlayer *player, double s
scroll = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_box_pack_start (GTK_BOX (vbox), scroll, TRUE, TRUE, 0);
scripts = swfdec_debug_scripts_new (SWFDEC_DEBUGGER (player));
gtk_container_add (GTK_CONTAINER (scroll), scripts);
@@ -251,7 +251,7 @@ view_swf (SwfdecPlayer *player, double s
scroll = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
gtk_box_pack_start (GTK_BOX (hbox), scroll, TRUE, TRUE, 0);
widget = swfdec_debug_script_new (SWFDEC_DEBUGGER (player));
gtk_container_add (GTK_CONTAINER (scroll), widget);
diff-tree b8b6df20af7044cda18cfde12662492f2903ecb0 (from fc10e6599a2821de28900eb4f570654e4fe1958a)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Jan 26 10:03:05 2007 +0100
rework case sensitivity once again - this time making it global and set only on startup
I really should do a testsuite with embedding movies and testing their case
sensitivity so I know what the official Flash player does
diff --git a/libswfdec/js/jsatom.c b/libswfdec/js/jsatom.c
index c4c85b7..f0816b2 100644
--- a/libswfdec/js/jsatom.c
+++ b/libswfdec/js/jsatom.c
@@ -673,10 +673,10 @@ out:
JSAtom *
js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
{
- if (flags & ATOM_NOCASE)
- return js_AtomizeStringWithCompare (cx, str, flags, js_compare_atom_keys_no_case);
- else
+ if (cx->caseSensitive)
return js_AtomizeStringWithCompare (cx, str, flags, js_compare_atom_keys);
+ else
+ return js_AtomizeStringWithCompare (cx, str, flags, js_compare_atom_keys_no_case);
}
JS_FRIEND_API(JSAtom *)
diff --git a/libswfdec/js/jsatom.h b/libswfdec/js/jsatom.h
index d9d2025..6f486c3 100644
--- a/libswfdec/js/jsatom.h
+++ b/libswfdec/js/jsatom.h
@@ -58,7 +58,6 @@ JS_BEGIN_EXTERN_C
#define ATOM_PINNED 0x01 /* atom is pinned against GC */
#define ATOM_INTERNED 0x02 /* pinned variant for JS_Intern* API */
#define ATOM_MARK 0x04 /* atom is reachable via GC */
-#define ATOM_NOCASE 0x20 /* treat atom case-insensitive */
#define ATOM_NOCOPY 0x40 /* don't copy atom string bytes */
#define ATOM_TMPSTR 0x80 /* internal, to avoid extra string */
diff --git a/libswfdec/swfdec_edittext_movie.c b/libswfdec/swfdec_edittext_movie.c
index e3d2119..421f6bc 100644
--- a/libswfdec/swfdec_edittext_movie.c
+++ b/libswfdec/swfdec_edittext_movie.c
@@ -80,7 +80,7 @@ swfdec_edit_text_movie_iterate (SwfdecMo
jsobj = swfdec_scriptable_get_object (parent);
if (jsobj == NULL)
return;
- val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable, FALSE);
+ val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable);
if (JSVAL_IS_VOID (val))
return;
@@ -110,7 +110,7 @@ swfdec_edit_text_movie_init_movie (Swfde
if (jsobj == NULL)
return;
if (text->text->variable_prefix) {
- val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable_prefix, FALSE);
+ val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable_prefix);
if (!JSVAL_IS_OBJECT (val))
return;
jsobj = JSVAL_TO_OBJECT (val);
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index 1601b4b..524707c 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -300,18 +300,20 @@ fail:
static JSBool
swfdec_js_eval_get_property (JSContext *cx, JSObject *obj,
- const char *name, gboolean initial, gboolean ignore_case, jsval *ret)
+ const char *name, jsval *ret)
{
JSAtom *atom;
JSObject *pobj;
JSProperty *prop;
- atom = js_Atomize (cx, name, strlen(name), ignore_case ? ATOM_NOCASE : 0);
+ atom = js_Atomize (cx, name, strlen(name), 0);
if (!atom)
return JS_FALSE;
- if (initial) {
+ if (obj) {
return OBJ_GET_PROPERTY (cx, obj, (jsid) atom, ret);
} else {
+ if (cx->fp == NULL || cx->fp->scopeChain == NULL)
+ return JS_FALSE;
if (!js_FindProperty (cx, (jsid) atom, &obj, &pobj, &prop))
return JS_FALSE;
if (!prop)
@@ -324,18 +326,20 @@ swfdec_js_eval_get_property (JSContext *
static JSBool
swfdec_js_eval_set_property (JSContext *cx, JSObject *obj,
- const char *name, gboolean initial, gboolean ignore_case, jsval *ret)
+ const char *name, jsval *ret)
{
JSAtom *atom;
JSObject *pobj;
JSProperty *prop;
- atom = js_Atomize (cx, name, strlen(name), ignore_case ? ATOM_NOCASE : 0);
+ atom = js_Atomize (cx, name, strlen(name), 0);
if (!atom)
return JS_FALSE;
- if (initial) {
+ if (obj) {
return OBJ_SET_PROPERTY (cx, obj, (jsid) atom, ret);
} else {
+ if (cx->fp == NULL || cx->fp->scopeChain == NULL)
+ return JS_FALSE;
if (!js_FindProperty (cx, (jsid) atom, &obj, &pobj, &prop))
return JS_FALSE;
if (!prop)
@@ -348,23 +352,25 @@ swfdec_js_eval_set_property (JSContext *
static gboolean
swfdec_js_eval_internal (JSContext *cx, JSObject *obj, const char *str,
- gboolean ignore_case, jsval *val, gboolean set)
+ jsval *val, gboolean set)
{
jsval cur;
char *work = NULL;
- gboolean initial = TRUE;
SWFDEC_LOG ("eval called with \"%s\" on %p", str, obj);
if (strchr (str, '/')) {
work = swfdec_js_slash_to_dot (str);
str = work;
}
- cur = OBJECT_TO_JSVAL (obj);
if (g_str_has_prefix (str, "this")) {
str += 4;
if (*str == '.')
str++;
+ if (cx->fp == NULL)
+ goto out;
+ obj = cx->fp->thisp;
}
+ cur = OBJECT_TO_JSVAL (obj);
while (str != NULL && *str != '\0') {
char *dot = strchr (str, '.');
if (!JSVAL_IS_OBJECT (cur))
@@ -372,21 +378,20 @@ swfdec_js_eval_internal (JSContext *cx,
obj = JSVAL_TO_OBJECT (cur);
if (dot) {
char *name = g_strndup (str, dot - str);
- if (!swfdec_js_eval_get_property (cx, obj, name, initial, ignore_case, &cur))
+ if (!swfdec_js_eval_get_property (cx, obj, name, &cur))
goto out;
g_free (name);
str = dot + 1;
} else {
if (set) {
- if (!swfdec_js_eval_set_property (cx, obj, str, initial, ignore_case, val))
+ if (!swfdec_js_eval_set_property (cx, obj, str, val))
goto out;
} else {
- if (!swfdec_js_eval_get_property (cx, obj, str, initial, ignore_case, &cur))
+ if (!swfdec_js_eval_get_property (cx, obj, str, &cur))
goto out;
}
str = NULL;
}
- initial = FALSE;
}
g_free (work);
@@ -403,7 +408,6 @@ out:
* @cx: a #JSContext
* @obj: #JSObject to use as a source for evaluating
* @str: The string to evaluate
- * @ignore_case: TRUE for case insensitive evaluation
*
* This function works like the Actionscript eval function used on @obj.
* It handles both slash-style and dot-style notation.
@@ -411,23 +415,24 @@ out:
* Returns: the value or JSVAL_VOID if no value was found.
**/
jsval
-swfdec_js_eval (JSContext *cx, JSObject *obj, const char *str,
- gboolean ignore_case)
+swfdec_js_eval (JSContext *cx, JSObject *obj, const char *str)
{
jsval ret;
g_return_val_if_fail (cx != NULL, JSVAL_VOID);
- g_return_val_if_fail (obj != NULL, JSVAL_VOID);
g_return_val_if_fail (str != NULL, JSVAL_VOID);
- if (!swfdec_js_eval_internal (cx, obj, str, ignore_case, &ret, FALSE))
+ if (!swfdec_js_eval_internal (cx, obj, str, &ret, FALSE))
ret = JSVAL_VOID;
return ret;
}
void
swfdec_js_eval_set (JSContext *cx, JSObject *obj, const char *str,
- jsval val, gboolean ignore_case)
+ jsval val)
{
- swfdec_js_eval_internal (cx, obj, str, ignore_case, &val, TRUE);
+ g_return_if_fail (cx != NULL);
+ g_return_if_fail (str != NULL);
+
+ swfdec_js_eval_internal (cx, obj, str, &val, TRUE);
}
diff --git a/libswfdec/swfdec_js.h b/libswfdec/swfdec_js.h
index ea49a72..5e58152 100644
--- a/libswfdec/swfdec_js.h
+++ b/libswfdec/swfdec_js.h
@@ -49,13 +49,11 @@ void swfdec_js_movie_remove_property (S
char * swfdec_js_slash_to_dot (const char * slash_str);
jsval swfdec_js_eval (JSContext * cx,
JSObject * obj,
- const char * str,
- gboolean ignore_case);
+ const char * str);
void swfdec_js_eval_set (JSContext * cx,
JSObject * obj,
const char * str,
- jsval val,
- gboolean ignore_case);
+ jsval val);
/* support functions */
const char * swfdec_js_to_string (JSContext * cx,
diff --git a/libswfdec/swfdec_js_global.c b/libswfdec/swfdec_js_global.c
index 27522c1..328d74d 100644
--- a/libswfdec/swfdec_js_global.c
+++ b/libswfdec/swfdec_js_global.c
@@ -33,7 +33,7 @@ swfdec_js_global_eval (JSContext *cx, JS
const char *bytes = swfdec_js_to_string (cx, argv[0]);
if (bytes == NULL)
return JS_FALSE;
- *rval = swfdec_js_eval (cx, obj, bytes, FALSE);
+ *rval = swfdec_js_eval (cx, obj, bytes);
} else {
*rval = argv[0];
}
diff --git a/libswfdec/swfdec_root_movie.c b/libswfdec/swfdec_root_movie.c
index 440f9d4..9121560 100644
--- a/libswfdec/swfdec_root_movie.c
+++ b/libswfdec/swfdec_root_movie.c
@@ -32,6 +32,7 @@
#include "swfdec_loadertarget.h"
#include "swfdec_player_internal.h"
#include "swfdec_swf_decoder.h"
+#include "js/jsapi.h"
static void swfdec_root_movie_loader_target_init (SwfdecLoaderTargetInterface *iface);
@@ -67,6 +68,13 @@ swfdec_root_movie_loader_target_do_init
swfdec_player_initialize (movie->player, movie->decoder->rate,
movie->decoder->width, movie->decoder->height);
+ if (SWFDEC_IS_SWF_DECODER (movie->decoder) &&
+ movie->player->roots->next == 0) {
+ /* if we're the only child */
+ /* FIXME: check case sensitivity wrt embedding movies of different version */
+ JS_SetContextCaseSensitive (movie->player->jscx,
+ SWFDEC_SWF_DECODER (movie->decoder)->version > 6);
+ }
if (SWFDEC_IS_FLV_DECODER (movie->decoder)) {
swfdec_flv_decoder_add_movie (SWFDEC_FLV_DECODER (movie->decoder),
SWFDEC_MOVIE (movie));
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 32af30e..e5c205f 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -315,8 +315,7 @@ swfdec_action_get_variable (JSContext *c
s = swfdec_js_to_string (cx, cx->fp->sp[-1]);
if (s == NULL)
return JS_FALSE;
- cx->fp->sp[-1] = swfdec_js_eval (cx, cx->fp->scopeChain, s,
- ((SwfdecScript *) cx->fp->swf)->version < 7);
+ cx->fp->sp[-1] = swfdec_js_eval (cx, cx->fp->scopeChain, s);
return JS_TRUE;
}
@@ -329,8 +328,7 @@ swfdec_action_set_variable (JSContext *c
if (s == NULL)
return JS_FALSE;
- swfdec_js_eval_set (cx, cx->fp->scopeChain, s, cx->fp->sp[-1],
- ((SwfdecScript *) cx->fp->swf)->version < 7);
+ swfdec_js_eval_set (cx, cx->fp->scopeChain, s, cx->fp->sp[-1]);
cx->fp->sp -= 2;
return JS_TRUE;
}
@@ -441,8 +439,7 @@ swfdec_eval_jsval (JSContext *cx, JSObje
const char *bytes = swfdec_js_to_string (cx, *val);
if (bytes == NULL)
return JS_FALSE;
- *val = swfdec_js_eval (cx, obj, bytes,
- ((SwfdecScript *) cx->fp->swf)->version < 7);
+ *val = swfdec_js_eval (cx, obj, bytes);
} else {
*val = OBJECT_TO_JSVAL (obj);
}
@@ -458,7 +455,7 @@ swfdec_action_get_property (JSContext *c
guint32 id;
val = cx->fp->sp[-2];
- if (!swfdec_eval_jsval (cx, cx->fp->scopeChain, &val))
+ if (!swfdec_eval_jsval (cx, NULL, &val))
return JS_FALSE;
movie = swfdec_scriptable_from_jsval (cx, val, SWFDEC_TYPE_MOVIE);
val = JSVAL_VOID;
@@ -493,7 +490,7 @@ swfdec_action_set_property (JSContext *c
guint32 id;
val = cx->fp->sp[-3];
- if (!swfdec_eval_jsval (cx, cx->fp->scopeChain, &val))
+ if (!swfdec_eval_jsval (cx, NULL, &val))
return JS_FALSE;
movie = swfdec_scriptable_from_jsval (cx, val, SWFDEC_TYPE_MOVIE);
if (movie == NULL) {
diff-tree fc10e6599a2821de28900eb4f570654e4fe1958a (from 4db4a99c916781cbceb31ca171c242867d4047cd)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Jan 25 16:29:56 2007 +0100
That line must've been accidentally removed somewhere
diff --git a/test/swfedit_token.c b/test/swfedit_token.c
index 3327b81..8c8b075 100644
--- a/test/swfedit_token.c
+++ b/test/swfedit_token.c
@@ -112,6 +112,7 @@ swfedit_from_string_unsigned (const char
return FALSE;
if (u > max)
return FALSE;
+ *result = GUINT_TO_POINTER (u);
return TRUE;
}
diff-tree 4db4a99c916781cbceb31ca171c242867d4047cd (from 9dab0726ed4e35c06038b8700492bd62658ff689)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 24 21:37:13 2007 +0100
use swfdec_js_eval_set for SetVariable
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index b2c4c81..32af30e 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -329,11 +329,8 @@ swfdec_action_set_variable (JSContext *c
if (s == NULL)
return JS_FALSE;
- if (strpbrk (s, "./:")) {
- SWFDEC_WARNING ("FIXME: implement paths");
- }
- if (!JS_SetProperty (cx, cx->fp->scopeChain, s, &cx->fp->sp[-1]))
- return JS_FALSE;
+ swfdec_js_eval_set (cx, cx->fp->scopeChain, s, cx->fp->sp[-1],
+ ((SwfdecScript *) cx->fp->swf)->version < 7);
cx->fp->sp -= 2;
return JS_TRUE;
}
diff-tree 9dab0726ed4e35c06038b8700492bd62658ff689 (from 6d219aa23eb4010d5438fce453650c158d09a720)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 24 21:36:55 2007 +0100
implement swfdec_js_eval_set
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index bbd6a43..1601b4b 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -322,30 +322,38 @@ swfdec_js_eval_get_property (JSContext *
}
}
-/**
- * swfdec_js_eval:
- * @cx: a #JSContext
- * @obj: #JSObject to use as a source for evaluating
- * @str: The string to evaluate
- * @ignore_case: TRUE for case insensitive evaluation
- *
- * This function works like the Actionscript eval function used on @obj.
- * It handles both slash-style and dot-style notation.
- *
- * Returns: the value or JSVAL_VOID if no value was found.
- **/
-jsval
-swfdec_js_eval (JSContext *cx, JSObject *obj, const char *str,
- gboolean ignore_case)
+static JSBool
+swfdec_js_eval_set_property (JSContext *cx, JSObject *obj,
+ const char *name, gboolean initial, gboolean ignore_case, jsval *ret)
+{
+ JSAtom *atom;
+ JSObject *pobj;
+ JSProperty *prop;
+
+ atom = js_Atomize (cx, name, strlen(name), ignore_case ? ATOM_NOCASE : 0);
+ if (!atom)
+ return JS_FALSE;
+ if (initial) {
+ return OBJ_SET_PROPERTY (cx, obj, (jsid) atom, ret);
+ } else {
+ if (!js_FindProperty (cx, (jsid) atom, &obj, &pobj, &prop))
+ return JS_FALSE;
+ if (!prop)
+ return JS_FALSE;
+ if (pobj)
+ obj = pobj;
+ return OBJ_SET_PROPERTY (cx, obj, (jsid) prop->id, ret);
+ }
+}
+
+static gboolean
+swfdec_js_eval_internal (JSContext *cx, JSObject *obj, const char *str,
+ gboolean ignore_case, jsval *val, gboolean set)
{
jsval cur;
char *work = NULL;
gboolean initial = TRUE;
- g_return_val_if_fail (cx != NULL, JSVAL_VOID);
- g_return_val_if_fail (obj != NULL, JSVAL_VOID);
- g_return_val_if_fail (str != NULL, JSVAL_VOID);
-
SWFDEC_LOG ("eval called with \"%s\" on %p", str, obj);
if (strchr (str, '/')) {
work = swfdec_js_slash_to_dot (str);
@@ -369,19 +377,57 @@ swfdec_js_eval (JSContext *cx, JSObject
g_free (name);
str = dot + 1;
} else {
- if (!swfdec_js_eval_get_property (cx, obj, str, initial, ignore_case, &cur))
- goto out;
+ if (set) {
+ if (!swfdec_js_eval_set_property (cx, obj, str, initial, ignore_case, val))
+ goto out;
+ } else {
+ if (!swfdec_js_eval_get_property (cx, obj, str, initial, ignore_case, &cur))
+ goto out;
+ }
str = NULL;
}
initial = FALSE;
}
g_free (work);
- return cur;
+ *val = cur;
+ return TRUE;
out:
SWFDEC_DEBUG ("error: returning void for %s", str);
g_free (work);
- return JSVAL_VOID;
+ return FALSE;
}
+/**
+ * swfdec_js_eval:
+ * @cx: a #JSContext
+ * @obj: #JSObject to use as a source for evaluating
+ * @str: The string to evaluate
+ * @ignore_case: TRUE for case insensitive evaluation
+ *
+ * This function works like the Actionscript eval function used on @obj.
+ * It handles both slash-style and dot-style notation.
+ *
+ * Returns: the value or JSVAL_VOID if no value was found.
+ **/
+jsval
+swfdec_js_eval (JSContext *cx, JSObject *obj, const char *str,
+ gboolean ignore_case)
+{
+ jsval ret;
+
+ g_return_val_if_fail (cx != NULL, JSVAL_VOID);
+ g_return_val_if_fail (obj != NULL, JSVAL_VOID);
+ g_return_val_if_fail (str != NULL, JSVAL_VOID);
+
+ if (!swfdec_js_eval_internal (cx, obj, str, ignore_case, &ret, FALSE))
+ ret = JSVAL_VOID;
+ return ret;
+}
+void
+swfdec_js_eval_set (JSContext *cx, JSObject *obj, const char *str,
+ jsval val, gboolean ignore_case)
+{
+ swfdec_js_eval_internal (cx, obj, str, ignore_case, &val, TRUE);
+}
diff --git a/libswfdec/swfdec_js.h b/libswfdec/swfdec_js.h
index 47e97ff..ea49a72 100644
--- a/libswfdec/swfdec_js.h
+++ b/libswfdec/swfdec_js.h
@@ -51,6 +51,11 @@ jsval swfdec_js_eval (JSContext * cx
JSObject * obj,
const char * str,
gboolean ignore_case);
+void swfdec_js_eval_set (JSContext * cx,
+ JSObject * obj,
+ const char * str,
+ jsval val,
+ gboolean ignore_case);
/* support functions */
const char * swfdec_js_to_string (JSContext * cx,
diff-tree 6d219aa23eb4010d5438fce453650c158d09a720 (from 00501d98ab1ec0257887814ccc9d582b3b8113a3)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 24 18:44:35 2007 +0100
add support for colors and the SetBackground tag
diff --git a/test/swfdec_out.c b/test/swfdec_out.c
index b795b28..bf7aa9e 100644
--- a/test/swfdec_out.c
+++ b/test/swfdec_out.c
@@ -213,6 +213,7 @@ swfdec_out_put_rect (SwfdecOut *out, Swf
guint req, tmp;
g_return_if_fail (out != NULL);
+ g_return_if_fail (rect != NULL);
x0 = rect->x0;
y0 = rect->y0;
@@ -233,3 +234,25 @@ swfdec_out_put_rect (SwfdecOut *out, Swf
swfdec_out_put_sbits (out, y1, req);
swfdec_out_syncbits (out);
}
+
+void
+swfdec_out_put_rgb (SwfdecOut *out, SwfdecColor color)
+{
+ g_return_if_fail (out != NULL);
+
+ swfdec_out_put_u8 (out, SWF_COLOR_R (color));
+ swfdec_out_put_u8 (out, SWF_COLOR_G (color));
+ swfdec_out_put_u8 (out, SWF_COLOR_B (color));
+}
+
+void
+swfdec_out_put_rgba (SwfdecOut *out, SwfdecColor color)
+{
+ g_return_if_fail (out != NULL);
+
+ swfdec_out_put_u8 (out, SWF_COLOR_R (color));
+ swfdec_out_put_u8 (out, SWF_COLOR_G (color));
+ swfdec_out_put_u8 (out, SWF_COLOR_B (color));
+ swfdec_out_put_u8 (out, SWF_COLOR_A (color));
+}
+
diff --git a/test/swfdec_out.h b/test/swfdec_out.h
index b6d155f..d1f916c 100644
--- a/test/swfdec_out.h
+++ b/test/swfdec_out.h
@@ -21,6 +21,7 @@
#define __SWFDEC_OUT_H__
#include <libswfdec/swfdec_buffer.h>
+#include <libswfdec/swfdec_color.h>
#include <libswfdec/swfdec_rect.h>
G_BEGIN_DECLS
@@ -64,6 +65,10 @@ void swfdec_out_put_u16 (SwfdecOut * o
void swfdec_out_put_u32 (SwfdecOut * out,
guint i);
+void swfdec_out_put_rgb (SwfdecOut * out,
+ SwfdecColor color);
+void swfdec_out_put_rgba (SwfdecOut * out,
+ SwfdecColor color);
void swfdec_out_put_rect (SwfdecOut * out,
SwfdecRect * rect);
diff --git a/test/swfedit_tag.c b/test/swfedit_tag.c
index 55020a0..dd15978 100644
--- a/test/swfedit_tag.c
+++ b/test/swfedit_tag.c
@@ -96,6 +96,30 @@ swfedit_rect_read (SwfdecBits *bits)
return rect;
}
+static void
+swfedit_rgb_write (gpointer data, SwfdecOut *out)
+{
+ swfdec_out_put_rgb (out, GPOINTER_TO_UINT (data));
+}
+
+static gpointer
+swfedit_rgb_read (SwfdecBits *bits)
+{
+ return GUINT_TO_POINTER (swfdec_bits_get_color (bits));
+}
+
+static void
+swfedit_rgba_write (gpointer data, SwfdecOut *out)
+{
+ swfdec_out_put_rgba (out, GPOINTER_TO_UINT (data));
+}
+
+static gpointer
+swfedit_rgba_read (SwfdecBits *bits)
+{
+ return GUINT_TO_POINTER (swfdec_bits_get_rgba (bits));
+}
+
struct {
void (* write) (gpointer data, SwfdecOut *out);
gpointer (* read) (SwfdecBits *bits);
@@ -106,6 +130,8 @@ struct {
{ swfedit_u16_write, swfedit_u16_read },
{ swfedit_u32_write, swfedit_u32_read },
{ swfedit_rect_write, swfedit_rect_read },
+ { swfedit_rgb_write, swfedit_rgb_read },
+ { swfedit_rgba_write, swfedit_rgba_read },
};
void
@@ -156,14 +182,16 @@ swfedit_tag_read_token (SwfeditToken *to
typedef struct {
const char * name; /* name to use for this field */
SwfeditTokenType type; /* type of this field */
- guint n_items; /* field to look at for item count */
+ guint n_items; /* field to look at for item count (or 0 to use 1 item) */
guint hint; /* hint to pass to field when creating */
} SwfeditTagDefinition;
static const SwfeditTagDefinition ShowFrame[] = { { NULL, 0, 0, 0 } };
+static const SwfeditTagDefinition SetBackgroundColor[] = { { "color", SWFEDIT_TOKEN_RGB, 0, 0 }, { NULL, 0, 0, 0 } };
static const SwfeditTagDefinition *tags[] = {
[SWFDEC_TAG_SHOWFRAME] = ShowFrame,
+ [SWFDEC_TAG_SETBACKGROUNDCOLOR] = SetBackgroundColor,
};
static const SwfeditTagDefinition *
diff --git a/test/swfedit_token.c b/test/swfedit_token.c
index ecf471c..3327b81 100644
--- a/test/swfedit_token.c
+++ b/test/swfedit_token.c
@@ -22,42 +22,57 @@
#endif
#include <stdlib.h>
+#include <string.h>
#include <gtk/gtk.h>
#include <libswfdec/swfdec_buffer.h>
+#include <libswfdec/swfdec_color.h>
#include "swfedit_token.h"
/*** CONVERTERS ***/
static gboolean
+swfedit_parse_hex (const char *s, guint *result)
+{
+ guint byte;
+
+ if (s[0] >= '0' && s[0] <= '9')
+ byte = s[0] - '0';
+ else if (s[0] >= 'a' && s[0] <= 'f')
+ byte = s[0] + 10 - 'a';
+ else if (s[0] >= 'A' && s[0] <= 'F')
+ byte = s[0] + 10 - 'A';
+ else
+ return FALSE;
+ s++;
+ byte *= 16;
+ if (s[0] >= '0' && s[0] <= '9')
+ byte += s[0] - '0';
+ else if (s[0] >= 'a' && s[0] <= 'f')
+ byte += s[0] + 10 - 'a';
+ else if (s[0] >= 'A' && s[0] <= 'F')
+ byte += s[0] + 10 - 'A';
+ else
+ return FALSE;
+ *result = byte;
+ return TRUE;
+}
+
+static gboolean
swfedit_binary_from_string (const char *s, gpointer* result)
{
GByteArray *array = g_byte_array_new ();
- guint8 byte;
+ guint byte;
+ guint8 add;
while (g_ascii_isspace (*s)) s++;
do {
- if (s[0] >= '0' && s[0] <= '9')
- byte = s[0] - '0';
- else if (s[0] >= 'a' && s[0] <= 'f')
- byte = s[0] + 10 - 'a';
- else if (s[0] >= 'A' && s[0] <= 'F')
- byte = s[0] + 10 - 'A';
- else
+ if (!swfedit_parse_hex (s, &byte))
break;
- s++;
- byte *= 16;
- if (s[0] >= '0' && s[0] <= '9')
- byte += s[0] - '0';
- else if (s[0] >= 'a' && s[0] <= 'f')
- byte += s[0] + 10 - 'a';
- else if (s[0] >= 'A' && s[0] <= 'F')
- byte += s[0] + 10 - 'A';
- else
- break;
- s++;
- g_byte_array_append (array, &byte, 1);
+ s += 2;
+ add = byte;
+ g_byte_array_append (array, &add, 1);
while (g_ascii_isspace (*s)) s++;
- } while (TRUE);
+ } while (*s != '\0');
if (*s == '\0') {
SwfdecBuffer *buffer = swfdec_buffer_new ();
buffer->length = array->len;
@@ -97,7 +112,6 @@ swfedit_from_string_unsigned (const char
return FALSE;
if (u > max)
return FALSE;
- *result = GUINT_TO_POINTER ((guint) u);
return TRUE;
}
@@ -140,6 +154,63 @@ swfedit_rect_to_string (gconstpointer va
(int) rect->x1, (int) rect->y1);
}
+static gboolean
+swfedit_rgb_from_string (const char *s, gpointer* result)
+{
+ guint r, g, b;
+ if (strlen (s) != 6)
+ return FALSE;
+ if (!swfedit_parse_hex (s, &r))
+ return FALSE;
+ s += 2;
+ if (!swfedit_parse_hex (s, &g))
+ return FALSE;
+ s += 2;
+ if (!swfedit_parse_hex (s, &b))
+ return FALSE;
+ *result = GUINT_TO_POINTER (SWF_COLOR_COMBINE (r, g, b, 0xFF));
+ return TRUE;
+}
+
+static char *
+swfedit_rgb_to_string (gconstpointer value)
+{
+ guint c = GPOINTER_TO_UINT (value);
+
+ return g_strdup_printf ("%02X%02X%02X", SWF_COLOR_R (c),
+ SWF_COLOR_G (c), SWF_COLOR_B (c));
+}
+
+static gboolean
+swfedit_rgba_from_string (const char *s, gpointer* result)
+{
+ guint r, g, b, a;
+ if (strlen (s) != 8)
+ return FALSE;
+ if (!swfedit_parse_hex (s, &a))
+ return FALSE;
+ s += 2;
+ if (!swfedit_parse_hex (s, &r))
+ return FALSE;
+ s += 2;
+ if (!swfedit_parse_hex (s, &g))
+ return FALSE;
+ s += 2;
+ if (!swfedit_parse_hex (s, &b))
+ return FALSE;
+ *result = GUINT_TO_POINTER (SWF_COLOR_COMBINE (r, g, b, a));
+ return TRUE;
+}
+
+static char *
+swfedit_rgba_to_string (gconstpointer value)
+{
+ guint c = GPOINTER_TO_UINT (value);
+
+ return g_strdup_printf ("%02X%02X%02X%02X", SWF_COLOR_R (c),
+ SWF_COLOR_G (c), SWF_COLOR_B (c), SWF_COLOR_A (c));
+}
+
struct {
gboolean (* from_string) (const char *s, gpointer *);
char * (* to_string) (gconstpointer value);
@@ -151,6 +222,8 @@ struct {
{ swfedit_uint16_from_string, swfedit_to_string_unsigned, NULL },
{ swfedit_uint32_from_string, swfedit_to_string_unsigned, NULL },
{ swfedit_rect_from_string, swfedit_rect_to_string, g_free },
+ { swfedit_rgb_from_string, swfedit_rgb_to_string, NULL },
+ { swfedit_rgba_from_string, swfedit_rgba_to_string, NULL },
};
/*** GTK_TREE_MODEL ***/
diff --git a/test/swfedit_token.h b/test/swfedit_token.h
index 8dec753..7909188 100644
--- a/test/swfedit_token.h
+++ b/test/swfedit_token.h
@@ -32,6 +32,8 @@ typedef enum {
SWFEDIT_TOKEN_UINT16,
SWFEDIT_TOKEN_UINT32,
SWFEDIT_TOKEN_RECT,
+ SWFEDIT_TOKEN_RGB,
+ SWFEDIT_TOKEN_RGBA,
SWFEDIT_N_TOKENS
} SwfeditTokenType;
diff-tree 00501d98ab1ec0257887814ccc9d582b3b8113a3 (from e0270bcea5766d30ae6eeb7f8b0f0ef062f121f4)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 24 18:44:11 2007 +0100
implement StringAdd and GetURL, so Steve dances again
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 171877f..b2c4c81 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -773,9 +773,62 @@ swfdec_action_increment (JSContext *cx,
return JS_NewNumberValue (cx, d, &cx->fp->sp[-1]);
}
+static JSBool
+swfdec_action_get_url (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ SwfdecMovie *movie;
+ SwfdecBits bits;
+ const char *url, *target;
+
+ swfdec_bits_init_data (&bits, data, len);
+ url = swfdec_bits_skip_string (&bits);
+ target = swfdec_bits_skip_string (&bits);
+ if (swfdec_bits_left (&bits)) {
+ SWFDEC_WARNING ("leftover bytes in GetURL action");
+ }
+ movie = swfdec_action_get_target (cx);
+ if (movie)
+ swfdec_root_movie_load (SWFDEC_ROOT_MOVIE (movie->root), url, target);
+ else
+ SWFDEC_WARNING ("no movie to load");
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_string_add (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ JSString *lval, *rval;
+
+ rval = JS_ValueToString (cx, cx->fp->sp[-1]);
+ lval = JS_ValueToString (cx, cx->fp->sp[-2]);
+ if (lval == NULL || rval == NULL)
+ return FALSE;
+ lval = JS_ConcatStrings (cx, lval, rval);
+ if (lval == NULL)
+ return FALSE;
+ cx->fp->sp--;
+ cx->fp->sp[-1] = STRING_TO_JSVAL (lval);
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
+swfdec_action_print_get_url (guint action, const guint8 *data, guint len)
+{
+ SwfdecBits bits;
+ const char *url, *target;
+
+ swfdec_bits_init_data (&bits, data, len);
+ url = swfdec_bits_skip_string (&bits);
+ target = swfdec_bits_skip_string (&bits);
+ if (swfdec_bits_left (&bits)) {
+ SWFDEC_WARNING ("leftover bytes in GetURL action");
+ }
+ return g_strdup_printf ("GetURL %s %s", url, target);
+}
+
+static char *
swfdec_action_print_if (guint action, const guint8 *data, guint len)
{
if (len != 2) {
@@ -942,7 +995,7 @@ static const SwfdecActionSpec actions[25
[0x1c] = { "GetVariable", NULL, 1, 1, { NULL, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable } },
[0x1d] = { "SetVariable", NULL, 2, 0, { NULL, swfdec_action_set_variable, swfdec_action_set_variable, swfdec_action_set_variable, swfdec_action_set_variable } },
[0x20] = { "SetTarget2", NULL },
- [0x21] = { "StringAdd", NULL },
+ [0x21] = { "StringAdd", NULL, 2, 1, { NULL, swfdec_action_string_add, swfdec_action_string_add, swfdec_action_string_add, swfdec_action_string_add } },
[0x22] = { "GetProperty", NULL, 2, 1, { NULL, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property } },
[0x23] = { "SetProperty", NULL, 3, 0, { NULL, swfdec_action_set_property, swfdec_action_set_property, swfdec_action_set_property, swfdec_action_set_property } },
[0x24] = { "CloneSprite", NULL },
@@ -1010,7 +1063,7 @@ static const SwfdecActionSpec actions[25
/* version 3 */
[0x81] = { "GotoFrame", swfdec_action_print_goto_frame, 0, 0, { swfdec_action_goto_frame, swfdec_action_goto_frame, swfdec_action_goto_frame, swfdec_action_goto_frame, swfdec_action_goto_frame } },
- [0x83] = { "GetURL", NULL },
+ [0x83] = { "GetURL", swfdec_action_print_get_url, 0, 0, { swfdec_action_get_url, swfdec_action_get_url, swfdec_action_get_url, swfdec_action_get_url, swfdec_action_get_url } },
/* version 5 */
[0x87] = { "StoreRegister", NULL },
[0x88] = { "ConstantPool", swfdec_action_print_constant_pool, 0, 0, { NULL, NULL, swfdec_action_constant_pool, swfdec_action_constant_pool, swfdec_action_constant_pool } },
diff-tree e0270bcea5766d30ae6eeb7f8b0f0ef062f121f4 (from 6efabb680e16b9144d8b4e880c18396861190d69)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 24 18:43:48 2007 +0100
make the color functions return a SwfdecColor
diff --git a/libswfdec/swfdec_bits.c b/libswfdec/swfdec_bits.c
index 1a7e402..418e9eb 100644
--- a/libswfdec/swfdec_bits.c
+++ b/libswfdec/swfdec_bits.c
@@ -471,10 +471,10 @@ swfdec_bits_get_string_length (SwfdecBit
return ret;
}
-unsigned int
+SwfdecColor
swfdec_bits_get_color (SwfdecBits * bits)
{
- int r, g, b;
+ unsigned int r, g, b;
r = swfdec_bits_get_u8 (bits);
g = swfdec_bits_get_u8 (bits);
@@ -483,10 +483,10 @@ swfdec_bits_get_color (SwfdecBits * bits
return SWF_COLOR_COMBINE (r, g, b, 0xff);
}
-unsigned int
+SwfdecColor
swfdec_bits_get_rgba (SwfdecBits * bits)
{
- int r, g, b, a;
+ unsigned int r, g, b, a;
r = swfdec_bits_get_u8 (bits);
g = swfdec_bits_get_u8 (bits);
diff --git a/libswfdec/swfdec_bits.h b/libswfdec/swfdec_bits.h
index 08ae1d8..a44c9e2 100644
--- a/libswfdec/swfdec_bits.h
+++ b/libswfdec/swfdec_bits.h
@@ -65,8 +65,8 @@ const char *swfdec_bits_skip_string (Swf
guint swfdec_bits_skip_bytes (SwfdecBits *bits, guint bytes);
char *swfdec_bits_get_string (SwfdecBits * bits);
char *swfdec_bits_get_string_length (SwfdecBits * bits, unsigned int len);
-unsigned int swfdec_bits_get_color (SwfdecBits * bits);
-unsigned int swfdec_bits_get_rgba (SwfdecBits * bits);
+SwfdecColor swfdec_bits_get_color (SwfdecBits * bits);
+SwfdecColor swfdec_bits_get_rgba (SwfdecBits * bits);
SwfdecGradient *swfdec_bits_get_gradient (SwfdecBits * bits);
SwfdecGradient *swfdec_bits_get_gradient_rgba (SwfdecBits * bits);
SwfdecGradient *swfdec_bits_get_morph_gradient (SwfdecBits * bits);
diff-tree 6efabb680e16b9144d8b4e880c18396861190d69 (from f1207b1451c4061e86adf62637134d63909ab754)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 24 16:40:58 2007 +0100
add initial support for auto-extraction of contents
diff --git a/test/swfedit_tag.c b/test/swfedit_tag.c
index 0a9fb9b..55020a0 100644
--- a/test/swfedit_tag.c
+++ b/test/swfedit_tag.c
@@ -25,6 +25,7 @@
#include <gtk/gtk.h>
#include <libswfdec/swfdec_bits.h>
+#include <libswfdec/swfdec_tag.h>
#include "swfedit_tag.h"
#include "swfdec_out.h"
@@ -150,6 +151,29 @@ swfedit_tag_read_token (SwfeditToken *to
swfedit_token_add (token, name, type, data);
}
+/*** TAGS ***/
+
+typedef struct {
+ const char * name; /* name to use for this field */
+ SwfeditTokenType type; /* type of this field */
+ guint n_items; /* field to look at for item count */
+ guint hint; /* hint to pass to field when creating */
+} SwfeditTagDefinition;
+
+static const SwfeditTagDefinition ShowFrame[] = { { NULL, 0, 0, 0 } };
+
+static const SwfeditTagDefinition *tags[] = {
+ [SWFDEC_TAG_SHOWFRAME] = ShowFrame,
+};
+
+static const SwfeditTagDefinition *
+swfedit_tag_get_definition (guint tag)
+{
+ if (tag >= G_N_ELEMENTS (tags))
+ return NULL;
+ return tags[tag];
+}
+
/*** SWFEDIT_TAG ***/
G_DEFINE_TYPE (SwfeditTag, swfedit_tag, SWFEDIT_TYPE_TOKEN)
@@ -179,13 +203,23 @@ SwfeditTag *
swfedit_tag_new (SwfeditToken *parent, guint tag, SwfdecBuffer *buffer)
{
SwfeditTag *item;
+ const SwfeditTagDefinition *def;
g_return_val_if_fail (SWFEDIT_IS_TOKEN (parent), NULL);
item = g_object_new (SWFEDIT_TYPE_TAG, NULL);
item->tag = tag;
SWFEDIT_TOKEN (item)->parent = parent;
- swfedit_token_add (SWFEDIT_TOKEN (item), "contents", SWFEDIT_TOKEN_BINARY, buffer);
+ def = swfedit_tag_get_definition (tag);
+ if (def) {
+ SwfdecBits bits;
+ swfdec_bits_init (&bits, buffer);
+ for (;def->name != NULL; def++) {
+ swfedit_tag_read_token (SWFEDIT_TOKEN (item), &bits, def->name, def->type);
+ }
+ } else {
+ swfedit_token_add (SWFEDIT_TOKEN (item), "contents", SWFEDIT_TOKEN_BINARY, buffer);
+ }
return item;
}
diff-tree f1207b1451c4061e86adf62637134d63909ab754 (from 2699f0ac28fe220c12fe6f98b05c50937125aeea)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 24 16:40:35 2007 +0100
handle tokens without children
diff --git a/test/swfedit_token.c b/test/swfedit_token.c
index b2210fd..ecf471c 100644
--- a/test/swfedit_token.c
+++ b/test/swfedit_token.c
@@ -309,6 +309,8 @@ swfedit_token_iter_children (GtkTreeMode
} else {
token = SWFEDIT_TOKEN (tree_model);
}
+ if (token->tokens->len == 0)
+ return FALSE;
iter->stamp = 0; /* FIXME */
iter->user_data = token;
iter->user_data2 = GINT_TO_POINTER (0);
@@ -322,7 +324,7 @@ swfedit_token_iter_has_child (GtkTreeMod
SwfeditTokenEntry *entry = &g_array_index (token->tokens, SwfeditTokenEntry, GPOINTER_TO_INT (iter->user_data2));
REPORT;
- return entry->type == SWFEDIT_TOKEN_OBJECT;
+ return entry->type == SWFEDIT_TOKEN_OBJECT && SWFEDIT_TOKEN (entry->value)->tokens->len > 0;
}
static gint
@@ -333,7 +335,7 @@ swfedit_token_iter_n_children (GtkTreeMo
REPORT;
if (entry->type != SWFEDIT_TOKEN_OBJECT)
- return FALSE;
+ return 0;
token = entry->value;
return token->tokens->len;
diff-tree 2699f0ac28fe220c12fe6f98b05c50937125aeea (from 4d09855e83ee699d590e8916e4af318ab79cc99b)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 24 15:44:38 2007 +0100
remove debugging g_print
diff --git a/test/swfdec_out.c b/test/swfdec_out.c
index 70dcc7c..b795b28 100644
--- a/test/swfdec_out.c
+++ b/test/swfdec_out.c
@@ -168,7 +168,6 @@ swfdec_out_put_bits (SwfdecOut *out, gui
*out->ptr = 0;
value &= (1 << bits_now) - 1;
value <<= 8 - out->idx - bits_now;
- g_print ("putting %02X in the next %u bits\n", value, bits_now);
*out->ptr |= value;
out->idx += bits_now;
g_assert (out->idx <= 8);
diff-tree 4d09855e83ee699d590e8916e4af318ab79cc99b (from 82e3f5645e07b82da355444ae96ccbb6eba637dd)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 24 15:14:12 2007 +0100
implement saving
diff --git a/test/Makefile.am b/test/Makefile.am
index d168cfd..33a647c 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -19,12 +19,14 @@ swfedit_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_
swfedit_LDFLAGS = $(SWF_LIBS) $(GTK_LIBS)
swfedit_SOURCES = \
+ swfdec_out.c \
swfedit.c \
swfedit_file.c \
swfedit_tag.c \
swfedit_token.c
noinst_HEADERS = \
+ swfdec_out.h \
swfedit_file.h \
swfedit_tag.h \
swfedit_token.h
diff --git a/test/swfdec_out.c b/test/swfdec_out.c
new file mode 100644
index 0000000..70dcc7c
--- /dev/null
+++ b/test/swfdec_out.c
@@ -0,0 +1,236 @@
+/* Swfdec
+ * Copyright (C) 2007 Benjamin Otte <otte at 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 "swfdec_out.h"
+
+SwfdecOut *
+swfdec_out_open (void)
+{
+ SwfdecOut *out = g_new0 (SwfdecOut, 1);
+
+ out->data = g_malloc (SWFDEC_OUT_INITIAL);
+ out->ptr = out->data;
+ out->end = out->data + SWFDEC_OUT_INITIAL;
+
+ return out;
+}
+
+static void
+swfdec_out_syncbits (SwfdecOut *out)
+{
+ g_return_if_fail (out != NULL);
+
+ if (out->idx > 0) {
+ out->ptr++;
+ out->idx = 0;
+ }
+}
+
+SwfdecBuffer *
+swfdec_out_close (SwfdecOut *out)
+{
+ SwfdecBuffer *buffer;
+
+ g_return_val_if_fail (out != NULL, NULL);
+
+ swfdec_out_syncbits (out);
+
+ buffer = swfdec_buffer_new ();
+ buffer->data = out->data;
+ buffer->length = out->ptr - out->data;
+
+ g_free (out);
+
+ return buffer;
+}
+
+unsigned int
+swfdec_out_left (SwfdecOut *out)
+{
+ g_return_val_if_fail (out != NULL, 0);
+
+ return (out->end - out->ptr) * 8 - out->idx;
+}
+
+void
+swfdec_out_ensure_bits (SwfdecOut *out, unsigned int bits)
+{
+ unsigned int current, taken, needed;
+
+ g_return_if_fail (out != NULL);
+
+ current = swfdec_out_left (out);
+ if (current >= bits)
+ return;
+ taken = out->ptr - out->data;
+ needed = (bits - current + 7) / 8;
+ needed += SWFDEC_OUT_STEP;
+ needed -= needed % SWFDEC_OUT_STEP;
+ needed += out->end - out->data;
+ out->data = g_realloc (out->data, needed);
+ out->ptr = out->data + taken;
+ out->end = out->data + needed;
+}
+
+void
+swfdec_out_prepare_bytes (SwfdecOut *out, unsigned int bytes)
+{
+ g_return_if_fail (out != NULL);
+
+ swfdec_out_syncbits (out);
+ swfdec_out_ensure_bits (out, bytes * 8);
+}
+
+void
+swfdec_out_put_buffer (SwfdecOut *out, SwfdecBuffer *buffer)
+{
+ g_return_if_fail (out != NULL);
+
+ swfdec_out_prepare_bytes (out, buffer->length);
+ memcpy (out->ptr, buffer->data, buffer->length);
+ out->ptr += buffer->length;
+}
+
+void
+swfdec_out_put_u8 (SwfdecOut *out, guint i)
+{
+ g_return_if_fail (i <= G_MAXUINT8);
+
+ swfdec_out_prepare_bytes (out, 1);
+ *out->ptr = i;
+ out->ptr++;
+}
+
+void
+swfdec_out_put_u16 (SwfdecOut *out, guint i)
+{
+ g_return_if_fail (i <= G_MAXUINT16);
+
+ swfdec_out_prepare_bytes (out, 2);
+ *(guint16 *)out->ptr = GUINT16_TO_LE (i);
+ out->ptr += 2;
+}
+
+void
+swfdec_out_put_u32 (SwfdecOut *out, guint i)
+{
+ g_return_if_fail (i <= G_MAXUINT32);
+
+ swfdec_out_prepare_bytes (out, 4);
+ *(guint32 *)out->ptr = GUINT32_TO_LE (i);
+ out->ptr += 4;
+}
+
+void
+swfdec_out_put_bit (SwfdecOut *out, gboolean bit)
+{
+ g_return_if_fail (out != NULL);
+
+ swfdec_out_put_bits (out, bit ? 1 : 0, 1);
+}
+
+void
+swfdec_out_put_bits (SwfdecOut *out, guint bits, guint n_bits)
+{
+ g_return_if_fail (out != NULL);
+
+ swfdec_out_ensure_bits (out, n_bits);
+
+ /* FIXME: implement this less braindead */
+ while (n_bits) {
+ guint bits_now = MIN (n_bits, 8 - out->idx);
+ guint value = bits >> (n_bits - bits_now);
+
+ /* clear data if necessary */
+ if (out->idx == 0)
+ *out->ptr = 0;
+ value &= (1 << bits_now) - 1;
+ value <<= 8 - out->idx - bits_now;
+ g_print ("putting %02X in the next %u bits\n", value, bits_now);
+ *out->ptr |= value;
+ out->idx += bits_now;
+ g_assert (out->idx <= 8);
+ if (out->idx == 8) {
+ out->ptr ++;
+ out->idx = 0;
+ }
+ n_bits -= bits_now;
+ }
+}
+
+void
+swfdec_out_put_sbits (SwfdecOut *out, int bits, guint n_bits)
+{
+ g_return_if_fail (out != NULL);
+ swfdec_out_put_bits (out, bits, n_bits);
+}
+
+static guint
+swfdec_out_bits_required (guint x)
+{
+ guint ret = 0;
+
+ while (x > 0) {
+ x >>= 1;
+ ret++;
+ }
+ return ret;
+}
+
+static guint
+swfdec_out_sbits_required (int x)
+{
+ if (x < 0)
+ x = -x;
+ return swfdec_out_bits_required (x) + 1;
+}
+
+void
+swfdec_out_put_rect (SwfdecOut *out, SwfdecRect *rect)
+{
+ int x0, x1, y0, y1;
+ guint req, tmp;
+
+ g_return_if_fail (out != NULL);
+
+ x0 = rect->x0;
+ y0 = rect->y0;
+ x1 = rect->x1;
+ y1 = rect->y1;
+ req = swfdec_out_sbits_required (x0);
+ tmp = swfdec_out_sbits_required (y0);
+ req = MAX (req, tmp);
+ tmp = swfdec_out_sbits_required (x1);
+ req = MAX (req, tmp);
+ tmp = swfdec_out_sbits_required (y1);
+ req = MAX (req, tmp);
+ swfdec_out_syncbits (out);
+ swfdec_out_put_bits (out, req, 5);
+ swfdec_out_put_sbits (out, x0, req);
+ swfdec_out_put_sbits (out, x1, req);
+ swfdec_out_put_sbits (out, y0, req);
+ swfdec_out_put_sbits (out, y1, req);
+ swfdec_out_syncbits (out);
+}
diff --git a/test/swfdec_out.h b/test/swfdec_out.h
new file mode 100644
index 0000000..b6d155f
--- /dev/null
+++ b/test/swfdec_out.h
@@ -0,0 +1,73 @@
+/* Swfdec
+ * Copyright (C) 2007 Benjamin Otte <otte at 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
+ */
+
+#ifndef __SWFDEC_OUT_H__
+#define __SWFDEC_OUT_H__
+
+#include <libswfdec/swfdec_buffer.h>
+#include <libswfdec/swfdec_rect.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _SwfdecOut SwfdecOut;
+
+struct _SwfdecOut {
+ unsigned char * data;
+ unsigned char * ptr;
+ unsigned int idx;
+ unsigned char * end;
+};
+
+#define SWFDEC_OUT_INITIAL (32)
+#define SWFDEC_OUT_STEP (32)
+
+SwfdecOut * swfdec_out_open (void);
+SwfdecBuffer * swfdec_out_close (SwfdecOut * out);
+
+unsigned int swfdec_out_left (SwfdecOut * out);
+void swfdec_out_ensure_bits (SwfdecOut * out,
+ unsigned int bits);
+void swfdec_out_prepare_bytes (SwfdecOut * out,
+ unsigned int bytes);
+
+void swfdec_out_put_bit (SwfdecOut * out,
+ gboolean bit);
+void swfdec_out_put_bits (SwfdecOut * out,
+ guint bits,
+ guint n_bits);
+void swfdec_out_put_sbits (SwfdecOut * out,
+ int bits,
+ guint n_bits);
+void swfdec_out_put_buffer (SwfdecOut * out,
+ SwfdecBuffer * buffer);
+void swfdec_out_put_u8 (SwfdecOut * out,
+ guint i);
+void swfdec_out_put_u16 (SwfdecOut * out,
+ guint i);
+void swfdec_out_put_u32 (SwfdecOut * out,
+ guint i);
+
+void swfdec_out_put_rect (SwfdecOut * out,
+ SwfdecRect * rect);
+
+
+G_END_DECLS
+
+#endif
diff --git a/test/swfedit.c b/test/swfedit.c
index e16d645..258f25e 100644
--- a/test/swfedit.c
+++ b/test/swfedit.c
@@ -27,12 +27,26 @@
static void
save (GtkButton *button, SwfeditFile *file)
{
+ GtkWidget *dialog;
GError *error = NULL;
- if (!swfedit_file_save (file, &error)) {
- g_printerr ("Error saving fils: %s\n", error->message);
- g_error_free (error);
+ dialog = gtk_file_chooser_dialog_new ("Save file...",
+ GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (button))),
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_OK,
+ NULL);
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+ gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), file->filename);
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
+ g_free (file->filename);
+ file->filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+ if (!swfedit_file_save (file, &error)) {
+ g_printerr ("Error saving file: %s\n", error->message);
+ g_error_free (error);
+ }
}
+ gtk_widget_destroy (dialog);
}
static void
diff --git a/test/swfedit_file.c b/test/swfedit_file.c
index d660655..dd5e035 100644
--- a/test/swfedit_file.c
+++ b/test/swfedit_file.c
@@ -27,6 +27,7 @@
#include "libswfdec/swfdec_buffer.h"
#include "libswfdec/swfdec_debug.h"
#include "libswfdec/swfdec_swf_decoder.h"
+#include "swfdec_out.h"
#include "swfedit_file.h"
#include "swfedit_tag.h"
@@ -103,7 +104,7 @@ swf_parse_header1 (SwfeditFile *file, Sw
swfedit_token_add (SWFEDIT_TOKEN (file), "version", SWFEDIT_TOKEN_UINT8,
GUINT_TO_POINTER (swfdec_bits_get_u8 (bits)));
- bytes_total = swfdec_bits_get_u32 (bits);
+ bytes_total = swfdec_bits_get_u32 (bits) - 8;
if (sig1 == 'C') {
/* compressed */
@@ -113,7 +114,7 @@ swf_parse_header1 (SwfeditFile *file, Sw
"Unable to uncompress file");
return ret;
} else {
- SwfdecBuffer *ret = swfdec_bits_get_buffer (bits, -1);
+ SwfdecBuffer *ret = swfdec_bits_get_buffer (bits, bytes_total);
if (ret == NULL)
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
"File too small");
@@ -124,14 +125,9 @@ swf_parse_header1 (SwfeditFile *file, Sw
static void
swf_parse_header2 (SwfeditFile *file, SwfdecBits *bits)
{
- SwfdecRect rect;
-
- swfdec_bits_get_rect (bits, &rect);
- swfdec_bits_syncbits (bits);
- swfedit_token_add (SWFEDIT_TOKEN (file), "rate", SWFEDIT_TOKEN_UINT16,
- GUINT_TO_POINTER (swfdec_bits_get_u16 (bits)));
- swfedit_token_add (SWFEDIT_TOKEN (file), "frames", SWFEDIT_TOKEN_UINT16,
- GUINT_TO_POINTER (swfdec_bits_get_u16 (bits)));
+ swfedit_tag_read_token (SWFEDIT_TOKEN (file), bits, "rect", SWFEDIT_TOKEN_RECT);
+ swfedit_tag_read_token (SWFEDIT_TOKEN (file), bits, "rate", SWFEDIT_TOKEN_UINT16);
+ swfedit_tag_read_token (SWFEDIT_TOKEN (file), bits, "frames", SWFEDIT_TOKEN_UINT16);
}
static gboolean
@@ -193,13 +189,21 @@ swfedit_file_new (const char *filename,
SwfeditFile *file;
SwfdecBuffer *buffer;
SwfdecBits bits;
+ char *absolute;
+ if (g_path_is_absolute (filename)) {
+ absolute = g_strdup (filename);
+ } else {
+ char *dir = g_get_current_dir ();
+ absolute = g_build_filename (dir, filename, NULL);
+ g_free (dir);
+ }
buffer = swfdec_buffer_new_from_file (filename, error);
if (buffer == NULL)
return NULL;
swfdec_bits_init (&bits, buffer);
file = g_object_new (SWFEDIT_TYPE_FILE, NULL);
- file->filename = g_strdup (filename);
+ file->filename = absolute;
if (!swfedit_file_parse (file, &bits, error)) {
swfdec_buffer_unref (buffer);
g_object_unref (file);
@@ -212,7 +216,53 @@ swfedit_file_new (const char *filename,
static SwfdecBuffer *
swfedit_file_write (SwfeditFile *file)
{
- return NULL;
+ guint i;
+ SwfeditToken *token = SWFEDIT_TOKEN (file);
+ SwfdecBufferQueue *queue;
+ SwfdecBuffer *buffer;
+ SwfdecOut *out;
+
+ queue = swfdec_buffer_queue_new ();
+ /* write second part of header */
+ out = swfdec_out_open ();
+ swfedit_tag_write_token (token, out, 1);
+ swfedit_tag_write_token (token, out, 2);
+ swfedit_tag_write_token (token, out, 3);
+ swfdec_buffer_queue_push (queue, swfdec_out_close (out));
+
+ for (i = 4; i < token->tokens->len; i++) {
+ SwfeditTokenEntry *entry = &g_array_index (token->tokens, SwfeditTokenEntry, i);
+ g_assert (entry->type == SWFEDIT_TOKEN_OBJECT);
+
+ buffer = swfedit_tag_write (entry->value);
+ out = swfdec_out_open ();
+ swfdec_out_put_u16 (out, SWFEDIT_TAG (entry->value)->tag << 6 |
+ MIN (buffer->length, 0x3f));
+ if (buffer->length >= 0x3f) {
+ swfdec_out_put_u32 (out, buffer->length);
+ }
+ swfdec_buffer_queue_push (queue, swfdec_out_close (out));
+ swfdec_buffer_queue_push (queue, buffer);
+ }
+ /* write closing tag */
+ buffer = swfdec_buffer_new_and_alloc0 (2);
+ swfdec_buffer_queue_push (queue, buffer);
+
+ /* FIXME: implement compression */
+ out = swfdec_out_open ();
+ swfdec_out_put_u8 (out, 'F');
+ swfdec_out_put_u8 (out, 'W');
+ swfdec_out_put_u8 (out, 'S');
+ swfedit_tag_write_token (token, out, 0);
+ g_print ("length: %u", swfdec_buffer_queue_get_depth (queue));
+ swfdec_out_put_u32 (out, swfdec_buffer_queue_get_depth (queue) + 8);
+ swfdec_out_prepare_bytes (out, swfdec_buffer_queue_get_depth (queue));
+ while ((buffer = swfdec_buffer_queue_pull_buffer (queue))) {
+ swfdec_out_put_buffer (out, buffer);
+ swfdec_buffer_unref (buffer);
+ }
+ swfdec_buffer_queue_free (queue);
+ return swfdec_out_close (out);
}
gboolean
diff --git a/test/swfedit_tag.c b/test/swfedit_tag.c
index 94ac4f9..0a9fb9b 100644
--- a/test/swfedit_tag.c
+++ b/test/swfedit_tag.c
@@ -23,7 +23,134 @@
#include <stdlib.h>
#include <gtk/gtk.h>
+
+#include <libswfdec/swfdec_bits.h>
#include "swfedit_tag.h"
+#include "swfdec_out.h"
+
+/*** LOAD/SAVE ***/
+
+static void
+swfedit_binary_write (gpointer data, SwfdecOut *out)
+{
+ swfdec_out_put_buffer (out, data);
+}
+
+static gpointer
+swfedit_binary_read (SwfdecBits *bits)
+{
+ SwfdecBuffer *buffer = swfdec_bits_get_buffer (bits, -1);
+ if (buffer == NULL)
+ buffer = swfdec_buffer_new ();
+ return buffer;
+}
+
+static void
+swfedit_u8_write (gpointer data, SwfdecOut *out)
+{
+ swfdec_out_put_u8 (out, GPOINTER_TO_UINT (data));
+}
+
+static gpointer
+swfedit_u8_read (SwfdecBits *bits)
+{
+ return GUINT_TO_POINTER (swfdec_bits_get_u8 (bits));
+}
+
+static void
+swfedit_u16_write (gpointer data, SwfdecOut *out)
+{
+ swfdec_out_put_u16 (out, GPOINTER_TO_UINT (data));
+}
+
+static gpointer
+swfedit_u16_read (SwfdecBits *bits)
+{
+ return GUINT_TO_POINTER (swfdec_bits_get_u16 (bits));
+}
+
+static void
+swfedit_u32_write (gpointer data, SwfdecOut *out)
+{
+ swfdec_out_put_u32 (out, GPOINTER_TO_UINT (data));
+}
+
+static gpointer
+swfedit_u32_read (SwfdecBits *bits)
+{
+ return GUINT_TO_POINTER (swfdec_bits_get_u32 (bits));
+}
+
+static void
+swfedit_rect_write (gpointer data, SwfdecOut *out)
+{
+ swfdec_out_put_rect (out, data);
+}
+
+static gpointer
+swfedit_rect_read (SwfdecBits *bits)
+{
+ SwfdecRect *rect = g_new (SwfdecRect, 1);
+ swfdec_bits_get_rect (bits, rect);
+ return rect;
+}
+
+struct {
+ void (* write) (gpointer data, SwfdecOut *out);
+ gpointer (* read) (SwfdecBits *bits);
+} operations[SWFEDIT_N_TOKENS] = {
+ { NULL, NULL },
+ { swfedit_binary_write, swfedit_binary_read },
+ { swfedit_u8_write, swfedit_u8_read },
+ { swfedit_u16_write, swfedit_u16_read },
+ { swfedit_u32_write, swfedit_u32_read },
+ { swfedit_rect_write, swfedit_rect_read },
+};
+
+void
+swfedit_tag_write_token (SwfeditToken *token, SwfdecOut *out, guint i)
+{
+ SwfeditTokenEntry *entry;
+
+ g_return_if_fail (SWFEDIT_IS_TOKEN (token));
+ g_return_if_fail (i < token->tokens->len);
+
+ entry = &g_array_index (token->tokens,
+ SwfeditTokenEntry, i);
+ g_assert (operations[entry->type].write != NULL);
+ operations[entry->type].write (entry->value, out);
+}
+
+SwfdecBuffer *
+swfedit_tag_write (SwfeditTag *tag)
+{
+ guint i;
+ SwfdecOut *out;
+
+ g_return_val_if_fail (SWFEDIT_IS_TAG (tag), NULL);
+
+ out = swfdec_out_open ();
+ for (i = 0; i < SWFEDIT_TOKEN (tag)->tokens->len; i++) {
+ swfedit_tag_write_token (SWFEDIT_TOKEN (tag), out, i);
+ }
+ return swfdec_out_close (out);
+}
+
+void
+swfedit_tag_read_token (SwfeditToken *token, SwfdecBits *bits,
+ const char *name, SwfeditTokenType type)
+{
+ gpointer data;
+
+ g_return_if_fail (SWFEDIT_IS_TOKEN (token));
+ g_return_if_fail (name != NULL);
+
+ g_assert (operations[type].read != NULL);
+ data = operations[type].read (bits);
+ swfedit_token_add (token, name, type, data);
+}
+
+/*** SWFEDIT_TAG ***/
G_DEFINE_TYPE (SwfeditTag, swfedit_tag, SWFEDIT_TYPE_TOKEN)
diff --git a/test/swfedit_tag.h b/test/swfedit_tag.h
index 07c11f2..46fdb5f 100644
--- a/test/swfedit_tag.h
+++ b/test/swfedit_tag.h
@@ -21,6 +21,7 @@
#define __SWFEDIT_TAG_H__
#include <libswfdec/swfdec_buffer.h>
+#include "swfdec_out.h"
#include "swfedit_token.h"
G_BEGIN_DECLS
@@ -47,10 +48,18 @@ struct _SwfeditTagClass {
GType swfedit_tag_get_type (void);
-SwfeditTag * swfedit_tag_new (SwfeditToken * parent,
- guint tag,
- SwfdecBuffer * buffer);
-
+SwfeditTag * swfedit_tag_new (SwfeditToken * parent,
+ guint tag,
+ SwfdecBuffer * buffer);
+
+SwfdecBuffer * swfedit_tag_write (SwfeditTag * tag);
+void swfedit_tag_write_token (SwfeditToken * token,
+ SwfdecOut * out,
+ guint i);
+void swfedit_tag_read_token (SwfeditToken * token,
+ SwfdecBits * bits,
+ const char * name,
+ SwfeditTokenType type);
G_END_DECLS
diff --git a/test/swfedit_token.c b/test/swfedit_token.c
index f3623fc..b2210fd 100644
--- a/test/swfedit_token.c
+++ b/test/swfedit_token.c
@@ -125,6 +125,21 @@ swfedit_to_string_unsigned (gconstpointe
return g_strdup_printf ("%u", GPOINTER_TO_UINT (value));
}
+static gboolean
+swfedit_rect_from_string (const char *s, gpointer* result)
+{
+ return FALSE;
+}
+
+static char *
+swfedit_rect_to_string (gconstpointer value)
+{
+ const SwfdecRect *rect = value;
+
+ return g_strdup_printf ("%d, %d, %d, %d", (int) rect->x0, (int) rect->y0,
+ (int) rect->x1, (int) rect->y1);
+}
+
struct {
gboolean (* from_string) (const char *s, gpointer *);
char * (* to_string) (gconstpointer value);
@@ -135,6 +150,7 @@ struct {
{ swfedit_uint8_from_string, swfedit_to_string_unsigned, NULL },
{ swfedit_uint16_from_string, swfedit_to_string_unsigned, NULL },
{ swfedit_uint32_from_string, swfedit_to_string_unsigned, NULL },
+ { swfedit_rect_from_string, swfedit_rect_to_string, g_free },
};
/*** GTK_TREE_MODEL ***/
diff --git a/test/swfedit_token.h b/test/swfedit_token.h
index 5235d03..8dec753 100644
--- a/test/swfedit_token.h
+++ b/test/swfedit_token.h
@@ -31,6 +31,7 @@ typedef enum {
SWFEDIT_TOKEN_UINT8,
SWFEDIT_TOKEN_UINT16,
SWFEDIT_TOKEN_UINT32,
+ SWFEDIT_TOKEN_RECT,
SWFEDIT_N_TOKENS
} SwfeditTokenType;
diff-tree 82e3f5645e07b82da355444ae96ccbb6eba637dd (from 89df12bea205242dd0554a48a0e7721de67d531b)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 24 15:13:58 2007 +0100
add swfedit
diff --git a/test/.gitignore b/test/.gitignore
index ef52ce4..9280a20 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -11,3 +11,4 @@ Makefile.in
dump
parse
swfdec-extract
+swfedit
diff-tree 89df12bea205242dd0554a48a0e7721de67d531b (from 91403c6d7fbda752ba3403e676d679afdb2bf1b0)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 24 15:11:05 2007 +0100
We need at least gtk-2.8
diff --git a/configure.ac b/configure.ac
index eb69535..fbf58c3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -78,7 +78,7 @@ fi
AC_SUBST(PANGO_LIBS)
AC_SUBST(PANGO_CFLAGS)
-PKG_CHECK_MODULES(GTK, gtk+-2.0, HAVE_GTK=yes, HAVE_GTK=no)
+PKG_CHECK_MODULES(GTK, gtk+-2.0 >= 2.8.0, HAVE_GTK=yes, HAVE_GTK=no)
AC_SUBST(GTK_LIBS)
AC_SUBST(GTK_CFLAGS)
if test "$HAVE_GTK" = "no"; then
diff-tree 91403c6d7fbda752ba3403e676d679afdb2bf1b0 (from 800b8b573d0d3553336f8541163a4731888bfbbb)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 24 15:10:35 2007 +0100
we don't have the header in the uncompressed buffer
diff --git a/libswfdec/swfdec_swf_decoder.c b/libswfdec/swfdec_swf_decoder.c
index 6539921..0bc1099 100644
--- a/libswfdec/swfdec_swf_decoder.c
+++ b/libswfdec/swfdec_swf_decoder.c
@@ -143,7 +143,7 @@ swf_inflate_init (SwfdecSwfDecoder * s)
ret = inflateInit (z);
SWFDEC_DEBUG ("inflateInit returned %d", ret);
- s->uncompressed_buffer = swfdec_buffer_new_and_alloc (dec->bytes_total);
+ s->uncompressed_buffer = swfdec_buffer_new_and_alloc (dec->bytes_total - 8);
z->next_out = s->uncompressed_buffer->data;
z->avail_out = s->uncompressed_buffer->length;
z->opaque = NULL;
diff-tree 800b8b573d0d3553336f8541163a4731888bfbbb (from b32e8c5b76f4dfde34c72057feb9d9970bea2e7a)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 24 15:10:04 2007 +0100
ignore 0-length buffers in bufferqueue
diff --git a/libswfdec/swfdec_buffer.c b/libswfdec/swfdec_buffer.c
index 3e9af24..c4ac67e 100644
--- a/libswfdec/swfdec_buffer.c
+++ b/libswfdec/swfdec_buffer.c
@@ -177,6 +177,13 @@ swfdec_buffer_queue_free (SwfdecBufferQu
void
swfdec_buffer_queue_push (SwfdecBufferQueue * queue, SwfdecBuffer * buffer)
{
+ g_return_if_fail (queue != NULL);
+ g_return_if_fail (buffer != NULL);
+
+ if (buffer->length == 0) {
+ swfdec_buffer_unref (buffer);
+ return;
+ }
queue->buffers = g_list_append (queue->buffers, buffer);
queue->depth += buffer->length;
}
diff-tree b32e8c5b76f4dfde34c72057feb9d9970bea2e7a (from 3d7f4a9fd93c17adc999370d40eff49d1983f126)
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Jan 23 15:16:17 2007 +0100
export the entry format and rename it to SwfeditTokenEntry
diff --git a/test/swfedit_token.c b/test/swfedit_token.c
index bb1e76b..f3623fc 100644
--- a/test/swfedit_token.c
+++ b/test/swfedit_token.c
@@ -137,14 +137,6 @@ struct {
{ swfedit_uint32_from_string, swfedit_to_string_unsigned, NULL },
};
-/*** STRUCTS ***/
-
-typedef struct {
- char * name;
- SwfeditTokenType type;
- gpointer value;
-} Entry;
-
/*** GTK_TREE_MODEL ***/
#if 0
@@ -191,12 +183,12 @@ swfedit_token_get_iter (GtkTreeModel *tr
{
SwfeditToken *token = SWFEDIT_TOKEN (tree_model);
guint i = gtk_tree_path_get_indices (path)[0];
- Entry *entry;
+ SwfeditTokenEntry *entry;
REPORT;
if (i > token->tokens->len)
return FALSE;
- entry = &g_array_index (token->tokens, Entry, i);
+ entry = &g_array_index (token->tokens, SwfeditTokenEntry, i);
if (gtk_tree_path_get_depth (path) > 1) {
GtkTreePath *new;
int j;
@@ -232,7 +224,7 @@ swfedit_token_get_path (GtkTreeModel *tr
guint i;
SwfeditToken *parent = token->parent;
for (i = 0; i < parent->tokens->len; i++) {
- Entry *entry = &g_array_index (parent->tokens, Entry, i);
+ SwfeditTokenEntry *entry = &g_array_index (parent->tokens, SwfeditTokenEntry, i);
if (entry->type != SWFEDIT_TOKEN_OBJECT)
continue;
if (entry->value == token)
@@ -249,7 +241,7 @@ swfedit_token_get_value (GtkTreeModel *t
gint column, GValue *value)
{
SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
- Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2));
+ SwfeditTokenEntry *entry = &g_array_index (token->tokens, SwfeditTokenEntry, GPOINTER_TO_INT (iter->user_data2));
REPORT;
switch (column) {
@@ -289,12 +281,12 @@ static gboolean
swfedit_token_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent)
{
SwfeditToken *token;
- Entry *entry;
+ SwfeditTokenEntry *entry;
REPORT;
if (parent) {
token = SWFEDIT_TOKEN (parent->user_data);
- entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (parent->user_data2));
+ entry = &g_array_index (token->tokens, SwfeditTokenEntry, GPOINTER_TO_INT (parent->user_data2));
if (entry->type != SWFEDIT_TOKEN_OBJECT)
return FALSE;
token = entry->value;
@@ -311,7 +303,7 @@ static gboolean
swfedit_token_iter_has_child (GtkTreeModel *tree_model, GtkTreeIter *iter)
{
SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
- Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2));
+ SwfeditTokenEntry *entry = &g_array_index (token->tokens, SwfeditTokenEntry, GPOINTER_TO_INT (iter->user_data2));
REPORT;
return entry->type == SWFEDIT_TOKEN_OBJECT;
@@ -321,7 +313,7 @@ static gint
swfedit_token_iter_n_children (GtkTreeModel *tree_model, GtkTreeIter *iter)
{
SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
- Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2));
+ SwfeditTokenEntry *entry = &g_array_index (token->tokens, SwfeditTokenEntry, GPOINTER_TO_INT (iter->user_data2));
REPORT;
if (entry->type != SWFEDIT_TOKEN_OBJECT)
@@ -336,12 +328,12 @@ swfedit_token_iter_nth_child (GtkTreeMod
GtkTreeIter *parent, gint n)
{
SwfeditToken *token;
- Entry *entry;
+ SwfeditTokenEntry *entry;
REPORT;
if (parent) {
token = SWFEDIT_TOKEN (parent->user_data);
- entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (parent->user_data2));
+ entry = &g_array_index (token->tokens, SwfeditTokenEntry, GPOINTER_TO_INT (parent->user_data2));
if (entry->type != SWFEDIT_TOKEN_OBJECT)
return FALSE;
@@ -370,7 +362,7 @@ swfedit_token_iter_parent (GtkTreeModel
return FALSE;
for (i = 0; i < parent->tokens->len; i++) {
- Entry *entry = &g_array_index (parent->tokens, Entry, i);
+ SwfeditTokenEntry *entry = &g_array_index (parent->tokens, SwfeditTokenEntry, i);
if (entry->type != SWFEDIT_TOKEN_OBJECT)
continue;
if (entry->value == token)
@@ -411,7 +403,7 @@ swfedit_token_dispose (GObject *object)
guint i;
for (i = 0; i < token->tokens->len; i++) {
- Entry *entry = &g_array_index (token->tokens, Entry, i);
+ SwfeditTokenEntry *entry = &g_array_index (token->tokens, SwfeditTokenEntry, i);
g_free (entry->name);
if (converters[entry->type].free)
converters[entry->type].free (entry->value);
@@ -432,7 +424,7 @@ swfedit_token_class_init (SwfeditTokenCl
static void
swfedit_token_init (SwfeditToken *token)
{
- token->tokens = g_array_new (FALSE, FALSE, sizeof (Entry));
+ token->tokens = g_array_new (FALSE, FALSE, sizeof (SwfeditTokenEntry));
}
SwfeditToken *
@@ -447,7 +439,7 @@ swfedit_token_new (void)
void
swfedit_token_add (SwfeditToken *token, const char *name, SwfeditTokenType type, gpointer value)
{
- Entry entry = { NULL, type, value };
+ SwfeditTokenEntry entry = { NULL, type, value };
g_return_if_fail (SWFEDIT_IS_TOKEN (token));
g_return_if_fail (name != NULL);
@@ -461,7 +453,7 @@ void
swfedit_token_set (SwfeditToken *token, GtkTreeIter *iter, const char *value)
{
GtkTreeModel *model;
- Entry *entry;
+ SwfeditTokenEntry *entry;
guint i;
gpointer new;
GtkTreePath *path;
@@ -473,7 +465,7 @@ swfedit_token_set (SwfeditToken *token,
model = GTK_TREE_MODEL (token);
token = iter->user_data;
i = GPOINTER_TO_UINT (iter->user_data2);
- entry = &g_array_index (token->tokens, Entry, i);
+ entry = &g_array_index (token->tokens, SwfeditTokenEntry, i);
if (converters[entry->type].from_string == NULL)
return;
if (!converters[entry->type].from_string (value, &new))
diff --git a/test/swfedit_token.h b/test/swfedit_token.h
index 1640027..5235d03 100644
--- a/test/swfedit_token.h
+++ b/test/swfedit_token.h
@@ -40,6 +40,8 @@ typedef enum {
SWFEDIT_COLUMN_VALUE
} SwfeditColumn;
+typedef struct _SwfeditTokenEntry SwfeditTokenEntry;
+
typedef struct _SwfeditToken SwfeditToken;
typedef struct _SwfeditTokenClass SwfeditTokenClass;
@@ -50,12 +52,18 @@ typedef struct _SwfeditTokenClass Swfedi
#define SWFEDIT_TOKEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFEDIT_TYPE_TOKEN, SwfeditTokenClass))
#define SWFEDIT_TOKEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFEDIT_TYPE_TOKEN, SwfeditTokenClass))
+struct _SwfeditTokenEntry {
+ char * name;
+ SwfeditTokenType type;
+ gpointer value;
+};
+
struct _SwfeditToken {
GObject object;
SwfeditToken * parent; /* parent of this token or NULL */
gchar * name; /* name of token */
- GArray * tokens; /* list of tokens */
+ GArray * tokens; /* of SwfeditTokenEntry */
};
struct _SwfeditTokenClass {
diff-tree 3d7f4a9fd93c17adc999370d40eff49d1983f126 (from 705e9e78e30cdb063445873c670cdbdfb918d07e)
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Jan 23 14:41:40 2007 +0100
add stubs for saving
diff --git a/test/swfedit.c b/test/swfedit.c
index 5dd2535..e16d645 100644
--- a/test/swfedit.c
+++ b/test/swfedit.c
@@ -25,6 +25,17 @@
#include "swfedit_file.h"
static void
+save (GtkButton *button, SwfeditFile *file)
+{
+ GError *error = NULL;
+
+ if (!swfedit_file_save (file, &error)) {
+ g_printerr ("Error saving fils: %s\n", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
cell_renderer_edited (GtkCellRenderer *renderer, char *path,
char *new_text, SwfeditFile *file)
{
@@ -41,26 +52,29 @@ static gboolean
open_window (char *filename)
{
SwfeditFile *file;
- GtkWidget *window, *scroll, *treeview;
+ GtkWidget *window, *scroll, *box, *button, *treeview;
GError *error = NULL;
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
file = swfedit_file_new (filename, &error);
if (file == NULL) {
- g_printerr ("Error openeing file %s: %s\n", filename, error->message);
+ g_printerr ("Error opening file %s: %s\n", filename, error->message);
g_error_free (error);
return FALSE;
}
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (window), filename);
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+ box = gtk_vbox_new (FALSE, 3);
+ gtk_container_add (GTK_CONTAINER (window), box);
+
scroll = gtk_scrolled_window_new (NULL, NULL);
- gtk_container_add (GTK_CONTAINER (window), scroll);
+ gtk_box_pack_start (GTK_BOX (box), scroll, TRUE, TRUE, 0);
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (file));
gtk_container_add (GTK_CONTAINER (scroll), treeview);
- gtk_widget_show_all (window);
renderer = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes ("Name", renderer,
@@ -76,6 +90,11 @@ open_window (char *filename)
gtk_tree_view_column_set_resizable (column, TRUE);
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+ button = gtk_button_new_from_stock (GTK_STOCK_SAVE);
+ g_signal_connect (button, "clicked", G_CALLBACK (save), file);
+ gtk_box_pack_start (GTK_BOX (box), button, FALSE, TRUE, 0);
+
+ gtk_widget_show_all (window);
return TRUE;
}
diff --git a/test/swfedit_file.c b/test/swfedit_file.c
index 7f2f240..d660655 100644
--- a/test/swfedit_file.c
+++ b/test/swfedit_file.c
@@ -37,8 +37,6 @@ swfedit_file_dispose (GObject *object)
{
SwfeditFile *file = SWFEDIT_FILE (object);
- g_list_foreach (file->tags, (GFunc) g_object_unref, NULL);
- g_list_free (file->tags);
g_free (file->filename);
G_OBJECT_CLASS (swfedit_file_parent_class)->dispose (object);
@@ -210,3 +208,30 @@ swfedit_file_new (const char *filename,
swfdec_buffer_unref (buffer);
return file;
}
+
+static SwfdecBuffer *
+swfedit_file_write (SwfeditFile *file)
+{
+ return NULL;
+}
+
+gboolean
+swfedit_file_save (SwfeditFile *file, GError **error)
+{
+ SwfdecBuffer *buffer;
+ gboolean ret;
+
+ g_return_val_if_fail (SWFEDIT_IS_FILE (file), FALSE);
+
+ buffer = swfedit_file_write (file);
+ if (buffer == NULL) {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ "Failed to render file");
+ return FALSE;
+ }
+ ret = g_file_set_contents (file->filename, (char *) buffer->data,
+ buffer->length, error);
+ swfdec_buffer_unref (buffer);
+ return ret;
+}
+
diff --git a/test/swfedit_file.h b/test/swfedit_file.h
index 39a89c5..e904950 100644
--- a/test/swfedit_file.h
+++ b/test/swfedit_file.h
@@ -39,9 +39,6 @@ struct _SwfeditFile {
SwfeditToken token;
char * filename; /* name this file is saved to */
-
- /* defined objects */
- GList * tags; /* ordered list of all tags in the file */
};
struct _SwfeditFileClass {
@@ -53,6 +50,9 @@ GType swfedit_file_get_type (void);
SwfeditFile * swfedit_file_new (const char * filename,
GError ** error);
+gboolean swfedit_file_save (SwfeditFile * file,
+ GError ** error);
+
G_END_DECLS
diff-tree 705e9e78e30cdb063445873c670cdbdfb918d07e (from ce02af774584cc4bb00655d77b6e7e350b77402c)
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Jan 23 14:41:24 2007 +0100
change read/write to from_string/to_string
diff --git a/test/swfedit_token.c b/test/swfedit_token.c
index 2819b52..bb1e76b 100644
--- a/test/swfedit_token.c
+++ b/test/swfedit_token.c
@@ -12,7 +12,7 @@
* 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
+ * License along with this library; if not, to_string to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
@@ -29,7 +29,7 @@
/*** CONVERTERS ***/
static gboolean
-swfedit_binary_read (const char *s, gpointer* result)
+swfedit_binary_from_string (const char *s, gpointer* result)
{
GByteArray *array = g_byte_array_new ();
guint8 byte;
@@ -71,7 +71,7 @@ swfedit_binary_read (const char *s, gpoi
}
static char *
-swfedit_binary_write (gconstpointer value)
+swfedit_binary_to_string (gconstpointer value)
{
guint i;
const SwfdecBuffer *buffer = value;
@@ -86,7 +86,7 @@ swfedit_binary_write (gconstpointer valu
}
static gboolean
-swfedit_read_unsigned (const char *s, gulong max, gpointer* result)
+swfedit_from_string_unsigned (const char *s, gulong max, gpointer* result)
{
char *end;
gulong u;
@@ -102,39 +102,39 @@ swfedit_read_unsigned (const char *s, gu
}
static gboolean
-swfedit_uint8_read (const char *s, gpointer* result)
+swfedit_uint8_from_string (const char *s, gpointer* result)
{
- return swfedit_read_unsigned (s, G_MAXUINT8, result);
+ return swfedit_from_string_unsigned (s, G_MAXUINT8, result);
}
static gboolean
-swfedit_uint16_read (const char *s, gpointer* result)
+swfedit_uint16_from_string (const char *s, gpointer* result)
{
- return swfedit_read_unsigned (s, G_MAXUINT16, result);
+ return swfedit_from_string_unsigned (s, G_MAXUINT16, result);
}
static gboolean
-swfedit_uint32_read (const char *s, gpointer* result)
+swfedit_uint32_from_string (const char *s, gpointer* result)
{
- return swfedit_read_unsigned (s, G_MAXUINT32, result);
+ return swfedit_from_string_unsigned (s, G_MAXUINT32, result);
}
static char *
-swfedit_write_unsigned (gconstpointer value)
+swfedit_to_string_unsigned (gconstpointer value)
{
return g_strdup_printf ("%u", GPOINTER_TO_UINT (value));
}
struct {
- gboolean (* read) (const char *s, gpointer *);
- char * (* write) (gconstpointer value);
+ gboolean (* from_string) (const char *s, gpointer *);
+ char * (* to_string) (gconstpointer value);
void (* free) (gpointer value);
} converters[SWFEDIT_N_TOKENS] = {
{ NULL, NULL, g_object_unref },
- { swfedit_binary_read, swfedit_binary_write, (GDestroyNotify) swfdec_buffer_unref },
- { swfedit_uint8_read, swfedit_write_unsigned, NULL },
- { swfedit_uint16_read, swfedit_write_unsigned, NULL },
- { swfedit_uint32_read, swfedit_write_unsigned, NULL },
+ { swfedit_binary_from_string, swfedit_binary_to_string, (GDestroyNotify) swfdec_buffer_unref },
+ { swfedit_uint8_from_string, swfedit_to_string_unsigned, NULL },
+ { swfedit_uint16_from_string, swfedit_to_string_unsigned, NULL },
+ { swfedit_uint32_from_string, swfedit_to_string_unsigned, NULL },
};
/*** STRUCTS ***/
@@ -259,12 +259,12 @@ swfedit_token_get_value (GtkTreeModel *t
return;
case SWFEDIT_COLUMN_VALUE_VISIBLE:
g_value_init (value, G_TYPE_BOOLEAN);
- g_value_set_boolean (value, converters[entry->type].write != NULL);
+ g_value_set_boolean (value, converters[entry->type].to_string != NULL);
return;
case SWFEDIT_COLUMN_VALUE:
g_value_init (value, G_TYPE_STRING);
- if (converters[entry->type].write)
- g_value_take_string (value, converters[entry->type].write (entry->value));
+ if (converters[entry->type].to_string)
+ g_value_take_string (value, converters[entry->type].to_string (entry->value));
return;
default:
break;
@@ -474,9 +474,9 @@ swfedit_token_set (SwfeditToken *token,
token = iter->user_data;
i = GPOINTER_TO_UINT (iter->user_data2);
entry = &g_array_index (token->tokens, Entry, i);
- if (converters[entry->type].read == NULL)
+ if (converters[entry->type].from_string == NULL)
return;
- if (!converters[entry->type].read (value, &new))
+ if (!converters[entry->type].from_string (value, &new))
return;
if (converters[entry->type].free != NULL)
converters[entry->type].free (entry->value);
diff-tree ce02af774584cc4bb00655d77b6e7e350b77402c (from b5b36b679993d6c5576dc83f4deacd80fe2e5ce3)
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Jan 23 10:05:46 2007 +0100
enable editing of properties
diff --git a/test/swfedit.c b/test/swfedit.c
index 71a86aa..5dd2535 100644
--- a/test/swfedit.c
+++ b/test/swfedit.c
@@ -24,6 +24,19 @@
#include <gtk/gtk.h>
#include "swfedit_file.h"
+static void
+cell_renderer_edited (GtkCellRenderer *renderer, char *path,
+ char *new_text, SwfeditFile *file)
+{
+ GtkTreeIter iter;
+
+ if (!gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (file),
+ &iter, path)) {
+ g_assert_not_reached ();
+ }
+ swfedit_token_set (SWFEDIT_TOKEN (file), &iter, new_text);
+}
+
static gboolean
open_window (char *filename)
{
@@ -57,6 +70,7 @@ open_window (char *filename)
renderer = gtk_cell_renderer_text_new ();
g_object_set (G_OBJECT (renderer), "editable", TRUE, NULL);
+ g_signal_connect (renderer, "edited", G_CALLBACK (cell_renderer_edited), file);
column = gtk_tree_view_column_new_with_attributes ("Value", renderer,
"text", SWFEDIT_COLUMN_VALUE, "visible", SWFEDIT_COLUMN_VALUE_VISIBLE, NULL);
gtk_tree_view_column_set_resizable (column, TRUE);
diff-tree b5b36b679993d6c5576dc83f4deacd80fe2e5ce3 (from d6679238c4929bf1d9cbb997b1ba9987c018e01e)
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Jan 23 10:05:35 2007 +0100
make parsing binary data work
diff --git a/test/swfedit_token.c b/test/swfedit_token.c
index 4e027eb..2819b52 100644
--- a/test/swfedit_token.c
+++ b/test/swfedit_token.c
@@ -45,13 +45,13 @@ swfedit_binary_read (const char *s, gpoi
else
break;
s++;
- byte *= 255;
+ byte *= 16;
if (s[0] >= '0' && s[0] <= '9')
- byte = s[0] - '0';
+ byte += s[0] - '0';
else if (s[0] >= 'a' && s[0] <= 'f')
- byte = s[0] + 10 - 'a';
+ byte += s[0] + 10 - 'a';
else if (s[0] >= 'A' && s[0] <= 'F')
- byte = s[0] + 10 - 'A';
+ byte += s[0] + 10 - 'A';
else
break;
s++;
diff-tree d6679238c4929bf1d9cbb997b1ba9987c018e01e (from 1af4da9dd02f8d5cd65b06bf25c6ac013bc26450)
Author: Benjamin Otte <otte at gnome.org>
Date: Tue Jan 23 10:04:05 2007 +0100
ensure _get_nth_child works with token == NULL
I hate it that you need -O2 to catch uninitialized variables
diff --git a/test/swfedit_token.c b/test/swfedit_token.c
index 704b98b..4e027eb 100644
--- a/test/swfedit_token.c
+++ b/test/swfedit_token.c
@@ -347,9 +347,11 @@ swfedit_token_iter_nth_child (GtkTreeMod
return FALSE;
token = entry->value;
- if ((guint) n >= token->tokens->len)
- return FALSE;
+ } else {
+ token = SWFEDIT_TOKEN (tree_model);
}
+ if ((guint) n >= token->tokens->len)
+ return FALSE;
iter->stamp = 0; /* FIXME */
iter->user_data = token;
iter->user_data2 = GINT_TO_POINTER (n);
diff-tree 1af4da9dd02f8d5cd65b06bf25c6ac013bc26450 (from 97ce107c67c3bcbd363eaf12e3669ca8226e4143)
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 22 22:05:34 2007 +0100
print the actual tag name
diff --git a/test/swfedit_file.c b/test/swfedit_file.c
index 2ae8fa2..7f2f240 100644
--- a/test/swfedit_file.c
+++ b/test/swfedit_file.c
@@ -26,6 +26,7 @@
#include "libswfdec/swfdec_bits.h"
#include "libswfdec/swfdec_buffer.h"
#include "libswfdec/swfdec_debug.h"
+#include "libswfdec/swfdec_swf_decoder.h"
#include "swfedit_file.h"
#include "swfedit_tag.h"
@@ -152,7 +153,7 @@ swfedit_file_parse (SwfeditFile *file, S
guint tag_len = x & 0x3f;
SwfdecBuffer *buffer;
SwfeditTag *item;
- char *name;
+
if (tag_len == 0x3f)
tag_len = swfdec_bits_get_u32 (bits);
if (tag == 0)
@@ -167,9 +168,9 @@ swfedit_file_parse (SwfeditFile *file, S
return FALSE;
}
item = swfedit_tag_new (SWFEDIT_TOKEN (file), tag, buffer);
- name = g_strdup_printf ("Tag %u", tag);
- swfedit_token_add (SWFEDIT_TOKEN (file), name, SWFEDIT_TOKEN_OBJECT, item);
- g_free (name);
+ swfedit_token_add (SWFEDIT_TOKEN (file),
+ swfdec_swf_decoder_get_tag_name (tag),
+ SWFEDIT_TOKEN_OBJECT, item);
}
swfdec_buffer_unref (next);
return TRUE;
diff-tree 97ce107c67c3bcbd363eaf12e3669ca8226e4143 (from bd5adea0669a5dbbbe75e887a400d6e538de0555)
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 22 22:03:11 2007 +0100
make it not crash
includes adding optional debugging help for the treeview
diff --git a/test/swfedit.c b/test/swfedit.c
index 76fa744..71a86aa 100644
--- a/test/swfedit.c
+++ b/test/swfedit.c
@@ -28,7 +28,7 @@ static gboolean
open_window (char *filename)
{
SwfeditFile *file;
- GtkWidget *window, *treeview;
+ GtkWidget *window, *scroll, *treeview;
GError *error = NULL;
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
@@ -42,8 +42,11 @@ open_window (char *filename)
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+ scroll = gtk_scrolled_window_new (NULL, NULL);
+ gtk_container_add (GTK_CONTAINER (window), scroll);
+
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (file));
- gtk_container_add (GTK_CONTAINER (window), treeview);
+ gtk_container_add (GTK_CONTAINER (scroll), treeview);
gtk_widget_show_all (window);
renderer = gtk_cell_renderer_text_new ();
diff --git a/test/swfedit_file.c b/test/swfedit_file.c
index e995c1b..2ae8fa2 100644
--- a/test/swfedit_file.c
+++ b/test/swfedit_file.c
@@ -155,6 +155,8 @@ swfedit_file_parse (SwfeditFile *file, S
char *name;
if (tag_len == 0x3f)
tag_len = swfdec_bits_get_u32 (bits);
+ if (tag == 0)
+ break;
if (tag_len > 0)
buffer = swfdec_bits_get_buffer (bits, tag_len);
else
@@ -164,7 +166,7 @@ swfedit_file_parse (SwfeditFile *file, S
"Invalid contents in file");
return FALSE;
}
- item = swfedit_tag_new (tag, buffer);
+ item = swfedit_tag_new (SWFEDIT_TOKEN (file), tag, buffer);
name = g_strdup_printf ("Tag %u", tag);
swfedit_token_add (SWFEDIT_TOKEN (file), name, SWFEDIT_TOKEN_OBJECT, item);
g_free (name);
diff --git a/test/swfedit_tag.c b/test/swfedit_tag.c
index 9bbebeb..94ac4f9 100644
--- a/test/swfedit_tag.c
+++ b/test/swfedit_tag.c
@@ -49,12 +49,15 @@ swfedit_tag_init (SwfeditTag *tag)
}
SwfeditTag *
-swfedit_tag_new (guint tag, SwfdecBuffer *buffer)
+swfedit_tag_new (SwfeditToken *parent, guint tag, SwfdecBuffer *buffer)
{
SwfeditTag *item;
+ g_return_val_if_fail (SWFEDIT_IS_TOKEN (parent), NULL);
+
item = g_object_new (SWFEDIT_TYPE_TAG, NULL);
item->tag = tag;
+ SWFEDIT_TOKEN (item)->parent = parent;
swfedit_token_add (SWFEDIT_TOKEN (item), "contents", SWFEDIT_TOKEN_BINARY, buffer);
return item;
}
diff --git a/test/swfedit_tag.h b/test/swfedit_tag.h
index aad879e..07c11f2 100644
--- a/test/swfedit_tag.h
+++ b/test/swfedit_tag.h
@@ -47,7 +47,8 @@ struct _SwfeditTagClass {
GType swfedit_tag_get_type (void);
-SwfeditTag * swfedit_tag_new (guint tag,
+SwfeditTag * swfedit_tag_new (SwfeditToken * parent,
+ guint tag,
SwfdecBuffer * buffer);
diff --git a/test/swfedit_token.c b/test/swfedit_token.c
index 78951f2..704b98b 100644
--- a/test/swfedit_token.c
+++ b/test/swfedit_token.c
@@ -80,7 +80,7 @@ swfedit_binary_write (gconstpointer valu
for (i = 0; i < buffer->length; i++) {
if (i && i % 4 == 0)
g_string_append_c (string, ' ');
- g_string_append_printf (string, "%2X", buffer->data[i]);
+ g_string_append_printf (string, "%02X", buffer->data[i]);
}
return g_string_free (string, FALSE);
}
@@ -147,9 +147,15 @@ typedef struct {
/*** GTK_TREE_MODEL ***/
+#if 0
+# define REPORT g_print ("%s\n", G_STRFUNC)
+#else
+# define REPORT
+#endif
static GtkTreeModelFlags
swfedit_token_get_flags (GtkTreeModel *tree_model)
{
+ REPORT;
return 0;
}
@@ -158,12 +164,14 @@ swfedit_token_get_n_columns (GtkTreeMode
{
SwfeditToken *token = SWFEDIT_TOKEN (tree_model);
+ REPORT;
return token->tokens->len;
}
static GType
swfedit_token_get_column_type (GtkTreeModel *tree_model, gint index_)
{
+ REPORT;
switch (index_) {
case SWFEDIT_COLUMN_NAME:
return G_TYPE_STRING;
@@ -185,6 +193,7 @@ swfedit_token_get_iter (GtkTreeModel *tr
guint i = gtk_tree_path_get_indices (path)[0];
Entry *entry;
+ REPORT;
if (i > token->tokens->len)
return FALSE;
entry = &g_array_index (token->tokens, Entry, i);
@@ -199,7 +208,7 @@ swfedit_token_get_iter (GtkTreeModel *tr
new = gtk_tree_path_new ();
indices = gtk_tree_path_get_indices (path);
for (j = 1; j < gtk_tree_path_get_depth (path); j++) {
- gtk_tree_path_append_index (path, indices[j]);
+ gtk_tree_path_append_index (new, indices[j]);
}
ret = swfedit_token_get_iter (GTK_TREE_MODEL (entry->value), iter, new);
gtk_tree_path_free (new);
@@ -218,6 +227,7 @@ swfedit_token_get_path (GtkTreeModel *tr
SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
GtkTreePath *path = gtk_tree_path_new_from_indices (GPOINTER_TO_INT (iter->user_data2), -1);
+ REPORT;
while (token->parent) {
guint i;
SwfeditToken *parent = token->parent;
@@ -241,6 +251,7 @@ swfedit_token_get_value (GtkTreeModel *t
SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2));
+ REPORT;
switch (column) {
case SWFEDIT_COLUMN_NAME:
g_value_init (value, G_TYPE_STRING);
@@ -266,6 +277,7 @@ swfedit_token_iter_next (GtkTreeModel *t
{
SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
+ REPORT;
if ((guint) GPOINTER_TO_INT (iter->user_data2) + 1 >= token->tokens->len)
return FALSE;
@@ -276,14 +288,21 @@ swfedit_token_iter_next (GtkTreeModel *t
static gboolean
swfedit_token_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent)
{
- SwfeditToken *token = SWFEDIT_TOKEN (parent->user_data);
- Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (parent->user_data2));
-
- if (entry->type != SWFEDIT_TOKEN_OBJECT)
- return FALSE;
+ SwfeditToken *token;
+ Entry *entry;
+ REPORT;
+ if (parent) {
+ token = SWFEDIT_TOKEN (parent->user_data);
+ entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (parent->user_data2));
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ return FALSE;
+ token = entry->value;
+ } else {
+ token = SWFEDIT_TOKEN (tree_model);
+ }
iter->stamp = 0; /* FIXME */
- iter->user_data = entry->value;
+ iter->user_data = token;
iter->user_data2 = GINT_TO_POINTER (0);
return TRUE;
}
@@ -294,6 +313,7 @@ swfedit_token_iter_has_child (GtkTreeMod
SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2));
+ REPORT;
return entry->type == SWFEDIT_TOKEN_OBJECT;
}
@@ -303,6 +323,7 @@ swfedit_token_iter_n_children (GtkTreeMo
SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2));
+ REPORT;
if (entry->type != SWFEDIT_TOKEN_OBJECT)
return FALSE;
@@ -317,6 +338,7 @@ swfedit_token_iter_nth_child (GtkTreeMod
SwfeditToken *token;
Entry *entry;
+ REPORT;
if (parent) {
token = SWFEDIT_TOKEN (parent->user_data);
entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (parent->user_data2));
@@ -341,6 +363,7 @@ swfedit_token_iter_parent (GtkTreeModel
SwfeditToken *token = SWFEDIT_TOKEN (child->user_data);
SwfeditToken *parent = token->parent;
+ REPORT;
if (parent == NULL)
return FALSE;
@@ -352,7 +375,7 @@ swfedit_token_iter_parent (GtkTreeModel
break;
}
iter->stamp = 0; /* FIXME */
- iter->user_data = token;
+ iter->user_data = parent;
iter->user_data2 = GINT_TO_POINTER (i);
return TRUE;
}
diff-tree bd5adea0669a5dbbbe75e887a400d6e538de0555 (from parents)
Merge: 8c426c32f7343fff4ff23015f5f7eee647b5aee7 72caf9482e2e7eb4bdc6cc0fa7578beb31645bac
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 22 18:40:04 2007 +0100
Merge branch 'interpreter' of ssh://company@git.freedesktop.org/git/swfdec into interpreter
diff-tree 72caf9482e2e7eb4bdc6cc0fa7578beb31645bac (from ac526c14b6a853304588e1c71ccc0ab709ac072e)
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 22 18:34:59 2007 +0100
add a first shot at an swf file editor that is supposed to allow creating
broken files for testing purposes when it's done
diff --git a/test/Makefile.am b/test/Makefile.am
index 01c4f45..d168cfd 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,6 +1,10 @@
SUBDIRS = sound trace various
-noinst_PROGRAMS = swfdec-extract dump parse
+if WITH_GTK
+noinst_PROGRAMS = swfdec-extract dump parse swfedit
+else
+noinst_PROGRAMS = swfdec-extract dump parse
+endif
dump_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(CAIRO_CFLAGS) $(PANGO_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
dump_LDFLAGS = $(SWF_LIBS) $(CAIRO_LIBS) $(PANGO_LIBS)
@@ -11,3 +15,16 @@ parse_LDFLAGS = $(SWF_LIBS) $(CAIRO_LIBS
swfdec_extract_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(CAIRO_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
swfdec_extract_LDFLAGS = $(SWF_LIBS) $(CAIRO_LIBS)
+swfedit_CFLAGS = $(GLOBAL_CFLAGS) $(SWF_CFLAGS) $(GTK_CFLAGS) -DXP_UNIX -I$(top_builddir)/libswfdec/js
+swfedit_LDFLAGS = $(SWF_LIBS) $(GTK_LIBS)
+
+swfedit_SOURCES = \
+ swfedit.c \
+ swfedit_file.c \
+ swfedit_tag.c \
+ swfedit_token.c
+
+noinst_HEADERS = \
+ swfedit_file.h \
+ swfedit_tag.h \
+ swfedit_token.h
diff --git a/test/swfedit.c b/test/swfedit.c
new file mode 100644
index 0000000..76fa744
--- /dev/null
+++ b/test/swfedit.c
@@ -0,0 +1,81 @@
+/* Swfedit
+ * Copyright (C) 2007 Benjamin Otte <otte at 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 <gtk/gtk.h>
+#include "swfedit_file.h"
+
+static gboolean
+open_window (char *filename)
+{
+ SwfeditFile *file;
+ GtkWidget *window, *treeview;
+ GError *error = NULL;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *renderer;
+
+ file = swfedit_file_new (filename, &error);
+ if (file == NULL) {
+ g_printerr ("Error openeing file %s: %s\n", filename, error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
+
+ treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (file));
+ gtk_container_add (GTK_CONTAINER (window), treeview);
+ gtk_widget_show_all (window);
+
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Name", renderer,
+ "text", SWFEDIT_COLUMN_NAME, NULL);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (G_OBJECT (renderer), "editable", TRUE, NULL);
+ column = gtk_tree_view_column_new_with_attributes ("Value", renderer,
+ "text", SWFEDIT_COLUMN_VALUE, "visible", SWFEDIT_COLUMN_VALUE_VISIBLE, NULL);
+ gtk_tree_view_column_set_resizable (column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+ return TRUE;
+}
+
+int
+main (int argc, char **argv)
+{
+ gtk_init (&argc, &argv);
+
+ if (argc <= 1) {
+ g_print ("Usage: %s FILENAME\n", argv[0]);
+ return 1;
+ }
+ if (open_window (argv[1])) {
+ gtk_main ();
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
diff --git a/test/swfedit_file.c b/test/swfedit_file.c
new file mode 100644
index 0000000..e995c1b
--- /dev/null
+++ b/test/swfedit_file.c
@@ -0,0 +1,209 @@
+/* Swfedit
+ * Copyright (C) 2007 Benjamin Otte <otte at 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 <zlib.h>
+
+#include "libswfdec/swfdec_bits.h"
+#include "libswfdec/swfdec_buffer.h"
+#include "libswfdec/swfdec_debug.h"
+#include "swfedit_file.h"
+#include "swfedit_tag.h"
+
+G_DEFINE_TYPE (SwfeditFile, swfedit_file, SWFEDIT_TYPE_TOKEN)
+
+static void
+swfedit_file_dispose (GObject *object)
+{
+ SwfeditFile *file = SWFEDIT_FILE (object);
+
+ g_list_foreach (file->tags, (GFunc) g_object_unref, NULL);
+ g_list_free (file->tags);
+ g_free (file->filename);
+
+ G_OBJECT_CLASS (swfedit_file_parent_class)->dispose (object);
+}
+
+static void *
+zalloc (void *opaque, unsigned int items, unsigned int size)
+{
+ return g_malloc (items * size);
+}
+
+static void
+zfree (void *opaque, void *addr)
+{
+ g_free (addr);
+}
+
+static SwfdecBuffer *
+swfenc_file_inflate (SwfdecBits *bits, guint size)
+{
+ SwfdecBuffer *decoded, *encoded;
+ z_stream z;
+ int ret;
+
+ encoded = swfdec_bits_get_buffer (bits, -1);
+ if (encoded == NULL)
+ return NULL;
+ decoded = swfdec_buffer_new_and_alloc (size);
+ z.zalloc = zalloc;
+ z.zfree = zfree;
+ z.opaque = NULL;
+ z.next_in = encoded->data;
+ z.avail_in = encoded->length;
+ z.next_out = decoded->data;
+ z.avail_out = decoded->length;
+ ret = inflateInit (&z);
+ SWFDEC_DEBUG ("inflateInit returned %d", ret);
+ if (ret >= Z_OK) {
+ ret = inflate (&z, Z_SYNC_FLUSH);
+ SWFDEC_DEBUG ("inflate returned %d", ret);
+ }
+ inflateEnd (&z);
+ swfdec_buffer_unref (encoded);
+ if (ret < Z_OK) {
+ swfdec_buffer_unref (decoded);
+ return NULL;
+ }
+ return decoded;
+}
+
+static SwfdecBuffer *
+swf_parse_header1 (SwfeditFile *file, SwfdecBits *bits, GError **error)
+{
+ guint sig1, sig2, sig3, bytes_total;
+
+ sig1 = swfdec_bits_get_u8 (bits);
+ sig2 = swfdec_bits_get_u8 (bits);
+ sig3 = swfdec_bits_get_u8 (bits);
+ if ((sig1 != 'F' && sig1 != 'C') || sig2 != 'W' || sig3 != 'S') {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ "This is not a SWF file");
+ return NULL;
+ }
+
+ swfedit_token_add (SWFEDIT_TOKEN (file), "version", SWFEDIT_TOKEN_UINT8,
+ GUINT_TO_POINTER (swfdec_bits_get_u8 (bits)));
+ bytes_total = swfdec_bits_get_u32 (bits);
+
+ if (sig1 == 'C') {
+ /* compressed */
+ SwfdecBuffer *ret = swfenc_file_inflate (bits, bytes_total);
+ if (ret == NULL)
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ "Unable to uncompress file");
+ return ret;
+ } else {
+ SwfdecBuffer *ret = swfdec_bits_get_buffer (bits, -1);
+ if (ret == NULL)
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ "File too small");
+ return ret;
+ }
+}
+
+static void
+swf_parse_header2 (SwfeditFile *file, SwfdecBits *bits)
+{
+ SwfdecRect rect;
+
+ swfdec_bits_get_rect (bits, &rect);
+ swfdec_bits_syncbits (bits);
+ swfedit_token_add (SWFEDIT_TOKEN (file), "rate", SWFEDIT_TOKEN_UINT16,
+ GUINT_TO_POINTER (swfdec_bits_get_u16 (bits)));
+ swfedit_token_add (SWFEDIT_TOKEN (file), "frames", SWFEDIT_TOKEN_UINT16,
+ GUINT_TO_POINTER (swfdec_bits_get_u16 (bits)));
+}
+
+static gboolean
+swfedit_file_parse (SwfeditFile *file, SwfdecBits *bits, GError **error)
+{
+ SwfdecBuffer *next;
+
+ next = swf_parse_header1 (file, bits, error);
+ if (next == NULL)
+ return FALSE;
+ swfdec_bits_init (bits, next);
+ swf_parse_header2 (file, bits);
+
+ while (swfdec_bits_left (bits)) {
+ guint x = swfdec_bits_get_u16 (bits);
+ G_GNUC_UNUSED guint tag = (x >> 6) & 0x3ff;
+ guint tag_len = x & 0x3f;
+ SwfdecBuffer *buffer;
+ SwfeditTag *item;
+ char *name;
+ if (tag_len == 0x3f)
+ tag_len = swfdec_bits_get_u32 (bits);
+ if (tag_len > 0)
+ buffer = swfdec_bits_get_buffer (bits, tag_len);
+ else
+ buffer = swfdec_buffer_new ();
+ if (buffer == NULL) {
+ g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+ "Invalid contents in file");
+ return FALSE;
+ }
+ item = swfedit_tag_new (tag, buffer);
+ name = g_strdup_printf ("Tag %u", tag);
+ swfedit_token_add (SWFEDIT_TOKEN (file), name, SWFEDIT_TOKEN_OBJECT, item);
+ g_free (name);
+ }
+ swfdec_buffer_unref (next);
+ return TRUE;
+}
+
+static void
+swfedit_file_class_init (SwfeditFileClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->dispose = swfedit_file_dispose;
+}
+
+static void
+swfedit_file_init (SwfeditFile *s)
+{
+}
+
+SwfeditFile *
+swfedit_file_new (const char *filename, GError **error)
+{
+ SwfeditFile *file;
+ SwfdecBuffer *buffer;
+ SwfdecBits bits;
+
+ buffer = swfdec_buffer_new_from_file (filename, error);
+ if (buffer == NULL)
+ return NULL;
+ swfdec_bits_init (&bits, buffer);
+ file = g_object_new (SWFEDIT_TYPE_FILE, NULL);
+ file->filename = g_strdup (filename);
+ if (!swfedit_file_parse (file, &bits, error)) {
+ swfdec_buffer_unref (buffer);
+ g_object_unref (file);
+ return NULL;
+ }
+ swfdec_buffer_unref (buffer);
+ return file;
+}
diff --git a/test/swfedit_file.h b/test/swfedit_file.h
new file mode 100644
index 0000000..39a89c5
--- /dev/null
+++ b/test/swfedit_file.h
@@ -0,0 +1,59 @@
+/* Swfedit
+ * Copyright (C) 2007 Benjamin Otte <otte at 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
+ */
+
+#ifndef __SWFEDIT_FILE_H__
+#define __SWFEDIT_FILE_H__
+
+#include <libswfdec/swfdec_rect.h>
+#include "swfedit_token.h"
+
+G_BEGIN_DECLS
+
+typedef struct _SwfeditFile SwfeditFile;
+typedef struct _SwfeditFileClass SwfeditFileClass;
+
+#define SWFEDIT_TYPE_FILE (swfedit_file_get_type())
+#define SWFEDIT_IS_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFEDIT_TYPE_FILE))
+#define SWFEDIT_IS_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFEDIT_TYPE_FILE))
+#define SWFEDIT_FILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFEDIT_TYPE_FILE, SwfeditFile))
+#define SWFEDIT_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFEDIT_TYPE_FILE, SwfeditFileClass))
+#define SWFEDIT_FILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFEDIT_TYPE_FILE, SwfeditFileClass))
+
+struct _SwfeditFile {
+ SwfeditToken token;
+
+ char * filename; /* name this file is saved to */
+
+ /* defined objects */
+ GList * tags; /* ordered list of all tags in the file */
+};
+
+struct _SwfeditFileClass {
+ SwfeditTokenClass token_class;
+};
+
+GType swfedit_file_get_type (void);
+
+SwfeditFile * swfedit_file_new (const char * filename,
+ GError ** error);
+
+
+G_END_DECLS
+
+#endif
diff --git a/test/swfedit_tag.c b/test/swfedit_tag.c
new file mode 100644
index 0000000..9bbebeb
--- /dev/null
+++ b/test/swfedit_tag.c
@@ -0,0 +1,61 @@
+/* Swfedit
+ * Copyright (C) 2007 Benjamin Otte <otte at 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 <stdlib.h>
+#include <gtk/gtk.h>
+#include "swfedit_tag.h"
+
+G_DEFINE_TYPE (SwfeditTag, swfedit_tag, SWFEDIT_TYPE_TOKEN)
+
+static void
+swfedit_tag_dispose (GObject *object)
+{
+ //SwfeditTag *tag = SWFEDIT_TAG (object);
+
+ G_OBJECT_CLASS (swfedit_tag_parent_class)->dispose (object);
+}
+
+static void
+swfedit_tag_class_init (SwfeditTagClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->dispose = swfedit_tag_dispose;
+}
+
+static void
+swfedit_tag_init (SwfeditTag *tag)
+{
+}
+
+SwfeditTag *
+swfedit_tag_new (guint tag, SwfdecBuffer *buffer)
+{
+ SwfeditTag *item;
+
+ item = g_object_new (SWFEDIT_TYPE_TAG, NULL);
+ item->tag = tag;
+ swfedit_token_add (SWFEDIT_TOKEN (item), "contents", SWFEDIT_TOKEN_BINARY, buffer);
+ return item;
+}
+
diff --git a/test/swfedit_tag.h b/test/swfedit_tag.h
new file mode 100644
index 0000000..aad879e
--- /dev/null
+++ b/test/swfedit_tag.h
@@ -0,0 +1,56 @@
+/* Swfedit
+ * Copyright (C) 2007 Benjamin Otte <otte at 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
+ */
+
+#ifndef __SWFEDIT_TAG_H__
+#define __SWFEDIT_TAG_H__
+
+#include <libswfdec/swfdec_buffer.h>
+#include "swfedit_token.h"
+
+G_BEGIN_DECLS
+
+typedef struct _SwfeditTag SwfeditTag;
+typedef struct _SwfeditTagClass SwfeditTagClass;
+
+#define SWFEDIT_TYPE_TAG (swfedit_tag_get_type())
+#define SWFEDIT_IS_TAG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFEDIT_TYPE_TAG))
+#define SWFEDIT_IS_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFEDIT_TYPE_TAG))
+#define SWFEDIT_TAG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFEDIT_TYPE_TAG, SwfeditTag))
+#define SWFEDIT_TAG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFEDIT_TYPE_TAG, SwfeditTagClass))
+#define SWFEDIT_TAG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFEDIT_TYPE_TAG, SwfeditTagClass))
+
+struct _SwfeditTag {
+ SwfeditToken token;
+
+ guint tag; /* tag type */
+};
+
+struct _SwfeditTagClass {
+ SwfeditTokenClass token_class;
+};
+
+GType swfedit_tag_get_type (void);
+
+SwfeditTag * swfedit_tag_new (guint tag,
+ SwfdecBuffer * buffer);
+
+
+G_END_DECLS
+
+#endif
diff --git a/test/swfedit_token.c b/test/swfedit_token.c
new file mode 100644
index 0000000..78951f2
--- /dev/null
+++ b/test/swfedit_token.c
@@ -0,0 +1,464 @@
+/* Swfedit
+ * Copyright (C) 2007 Benjamin Otte <otte at 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 <stdlib.h>
+#include <gtk/gtk.h>
+#include <libswfdec/swfdec_buffer.h>
+#include "swfedit_token.h"
+
+/*** CONVERTERS ***/
+
+static gboolean
+swfedit_binary_read (const char *s, gpointer* result)
+{
+ GByteArray *array = g_byte_array_new ();
+ guint8 byte;
+
+ while (g_ascii_isspace (*s)) s++;
+ do {
+ if (s[0] >= '0' && s[0] <= '9')
+ byte = s[0] - '0';
+ else if (s[0] >= 'a' && s[0] <= 'f')
+ byte = s[0] + 10 - 'a';
+ else if (s[0] >= 'A' && s[0] <= 'F')
+ byte = s[0] + 10 - 'A';
+ else
+ break;
+ s++;
+ byte *= 255;
+ if (s[0] >= '0' && s[0] <= '9')
+ byte = s[0] - '0';
+ else if (s[0] >= 'a' && s[0] <= 'f')
+ byte = s[0] + 10 - 'a';
+ else if (s[0] >= 'A' && s[0] <= 'F')
+ byte = s[0] + 10 - 'A';
+ else
+ break;
+ s++;
+ g_byte_array_append (array, &byte, 1);
+ while (g_ascii_isspace (*s)) s++;
+ } while (TRUE);
+ if (*s == '\0') {
+ SwfdecBuffer *buffer = swfdec_buffer_new ();
+ buffer->length = array->len;
+ buffer->data = array->data;
+ g_byte_array_free (array, FALSE);
+ *result = buffer;
+ return TRUE;
+ }
+ g_byte_array_free (array, TRUE);
+ return FALSE;
+}
+
+static char *
+swfedit_binary_write (gconstpointer value)
+{
+ guint i;
+ const SwfdecBuffer *buffer = value;
+ GString *string = g_string_new ("");
+
+ for (i = 0; i < buffer->length; i++) {
+ if (i && i % 4 == 0)
+ g_string_append_c (string, ' ');
+ g_string_append_printf (string, "%2X", buffer->data[i]);
+ }
+ return g_string_free (string, FALSE);
+}
+
+static gboolean
+swfedit_read_unsigned (const char *s, gulong max, gpointer* result)
+{
+ char *end;
+ gulong u;
+
+ g_assert (max <= G_MAXUINT);
+ u = strtoul (s, &end, 10);
+ if (*end != '\0')
+ return FALSE;
+ if (u > max)
+ return FALSE;
+ *result = GUINT_TO_POINTER ((guint) u);
+ return TRUE;
+}
+
+static gboolean
+swfedit_uint8_read (const char *s, gpointer* result)
+{
+ return swfedit_read_unsigned (s, G_MAXUINT8, result);
+}
+
+static gboolean
+swfedit_uint16_read (const char *s, gpointer* result)
+{
+ return swfedit_read_unsigned (s, G_MAXUINT16, result);
+}
+
+static gboolean
+swfedit_uint32_read (const char *s, gpointer* result)
+{
+ return swfedit_read_unsigned (s, G_MAXUINT32, result);
+}
+
+static char *
+swfedit_write_unsigned (gconstpointer value)
+{
+ return g_strdup_printf ("%u", GPOINTER_TO_UINT (value));
+}
+
+struct {
+ gboolean (* read) (const char *s, gpointer *);
+ char * (* write) (gconstpointer value);
+ void (* free) (gpointer value);
+} converters[SWFEDIT_N_TOKENS] = {
+ { NULL, NULL, g_object_unref },
+ { swfedit_binary_read, swfedit_binary_write, (GDestroyNotify) swfdec_buffer_unref },
+ { swfedit_uint8_read, swfedit_write_unsigned, NULL },
+ { swfedit_uint16_read, swfedit_write_unsigned, NULL },
+ { swfedit_uint32_read, swfedit_write_unsigned, NULL },
+};
+
+/*** STRUCTS ***/
+
+typedef struct {
+ char * name;
+ SwfeditTokenType type;
+ gpointer value;
+} Entry;
+
+/*** GTK_TREE_MODEL ***/
+
+static GtkTreeModelFlags
+swfedit_token_get_flags (GtkTreeModel *tree_model)
+{
+ return 0;
+}
+
+static gint
+swfedit_token_get_n_columns (GtkTreeModel *tree_model)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (tree_model);
+
+ return token->tokens->len;
+}
+
+static GType
+swfedit_token_get_column_type (GtkTreeModel *tree_model, gint index_)
+{
+ switch (index_) {
+ case SWFEDIT_COLUMN_NAME:
+ return G_TYPE_STRING;
+ case SWFEDIT_COLUMN_VALUE_VISIBLE:
+ return G_TYPE_BOOLEAN;
+ case SWFEDIT_COLUMN_VALUE:
+ return G_TYPE_STRING;
+ default:
+ break;
+ }
+ g_assert_not_reached ();
+ return G_TYPE_NONE;
+}
+
+static gboolean
+swfedit_token_get_iter (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreePath *path)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (tree_model);
+ guint i = gtk_tree_path_get_indices (path)[0];
+ Entry *entry;
+
+ if (i > token->tokens->len)
+ return FALSE;
+ entry = &g_array_index (token->tokens, Entry, i);
+ if (gtk_tree_path_get_depth (path) > 1) {
+ GtkTreePath *new;
+ int j;
+ int *indices;
+ gboolean ret;
+
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ return FALSE;
+ new = gtk_tree_path_new ();
+ indices = gtk_tree_path_get_indices (path);
+ for (j = 1; j < gtk_tree_path_get_depth (path); j++) {
+ gtk_tree_path_append_index (path, indices[j]);
+ }
+ ret = swfedit_token_get_iter (GTK_TREE_MODEL (entry->value), iter, new);
+ gtk_tree_path_free (new);
+ return ret;
+ } else {
+ iter->stamp = 0; /* FIXME */
+ iter->user_data = token;
+ iter->user_data2 = GINT_TO_POINTER (i);
+ return TRUE;
+ }
+}
+
+static GtkTreePath *
+swfedit_token_get_path (GtkTreeModel *tree_model, GtkTreeIter *iter)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
+ GtkTreePath *path = gtk_tree_path_new_from_indices (GPOINTER_TO_INT (iter->user_data2), -1);
+
+ while (token->parent) {
+ guint i;
+ SwfeditToken *parent = token->parent;
+ for (i = 0; i < parent->tokens->len; i++) {
+ Entry *entry = &g_array_index (parent->tokens, Entry, i);
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ continue;
+ if (entry->value == token)
+ break;
+ }
+ gtk_tree_path_prepend_index (path, i);
+ token = parent;
+ }
+ return path;
+}
+
+static void
+swfedit_token_get_value (GtkTreeModel *tree_model, GtkTreeIter *iter,
+ gint column, GValue *value)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
+ Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2));
+
+ switch (column) {
+ case SWFEDIT_COLUMN_NAME:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, entry->name);
+ return;
+ case SWFEDIT_COLUMN_VALUE_VISIBLE:
+ g_value_init (value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (value, converters[entry->type].write != NULL);
+ return;
+ case SWFEDIT_COLUMN_VALUE:
+ g_value_init (value, G_TYPE_STRING);
+ if (converters[entry->type].write)
+ g_value_take_string (value, converters[entry->type].write (entry->value));
+ return;
+ default:
+ break;
+ }
+ g_assert_not_reached ();
+}
+
+static gboolean
+swfedit_token_iter_next (GtkTreeModel *tree_model, GtkTreeIter *iter)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
+
+ if ((guint) GPOINTER_TO_INT (iter->user_data2) + 1 >= token->tokens->len)
+ return FALSE;
+
+ iter->user_data2++;
+ return TRUE;
+}
+
+static gboolean
+swfedit_token_iter_children (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *parent)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (parent->user_data);
+ Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (parent->user_data2));
+
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ return FALSE;
+
+ iter->stamp = 0; /* FIXME */
+ iter->user_data = entry->value;
+ iter->user_data2 = GINT_TO_POINTER (0);
+ return TRUE;
+}
+
+static gboolean
+swfedit_token_iter_has_child (GtkTreeModel *tree_model, GtkTreeIter *iter)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
+ Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2));
+
+ return entry->type == SWFEDIT_TOKEN_OBJECT;
+}
+
+static gint
+swfedit_token_iter_n_children (GtkTreeModel *tree_model, GtkTreeIter *iter)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (iter->user_data);
+ Entry *entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (iter->user_data2));
+
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ return FALSE;
+
+ token = entry->value;
+ return token->tokens->len;
+}
+
+static gboolean
+swfedit_token_iter_nth_child (GtkTreeModel *tree_model, GtkTreeIter *iter,
+ GtkTreeIter *parent, gint n)
+{
+ SwfeditToken *token;
+ Entry *entry;
+
+ if (parent) {
+ token = SWFEDIT_TOKEN (parent->user_data);
+ entry = &g_array_index (token->tokens, Entry, GPOINTER_TO_INT (parent->user_data2));
+
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ return FALSE;
+
+ token = entry->value;
+ if ((guint) n >= token->tokens->len)
+ return FALSE;
+ }
+ iter->stamp = 0; /* FIXME */
+ iter->user_data = token;
+ iter->user_data2 = GINT_TO_POINTER (n);
+ return TRUE;
+}
+
+static gboolean
+swfedit_token_iter_parent (GtkTreeModel *tree_model, GtkTreeIter *iter, GtkTreeIter *child)
+{
+ guint i;
+ SwfeditToken *token = SWFEDIT_TOKEN (child->user_data);
+ SwfeditToken *parent = token->parent;
+
+ if (parent == NULL)
+ return FALSE;
+
+ for (i = 0; i < parent->tokens->len; i++) {
+ Entry *entry = &g_array_index (parent->tokens, Entry, i);
+ if (entry->type != SWFEDIT_TOKEN_OBJECT)
+ continue;
+ if (entry->value == token)
+ break;
+ }
+ iter->stamp = 0; /* FIXME */
+ iter->user_data = token;
+ iter->user_data2 = GINT_TO_POINTER (i);
+ return TRUE;
+}
+
+static void
+swfedit_token_tree_model_init (GtkTreeModelIface *iface)
+{
+ iface->get_flags = swfedit_token_get_flags;
+ iface->get_n_columns = swfedit_token_get_n_columns;
+ iface->get_column_type = swfedit_token_get_column_type;
+ iface->get_iter = swfedit_token_get_iter;
+ iface->get_path = swfedit_token_get_path;
+ iface->get_value = swfedit_token_get_value;
+ iface->iter_next = swfedit_token_iter_next;
+ iface->iter_children = swfedit_token_iter_children;
+ iface->iter_has_child = swfedit_token_iter_has_child;
+ iface->iter_n_children = swfedit_token_iter_n_children;
+ iface->iter_nth_child = swfedit_token_iter_nth_child;
+ iface->iter_parent = swfedit_token_iter_parent;
+}
+
+/*** SWFEDIT_TOKEN ***/
+
+G_DEFINE_TYPE_WITH_CODE (SwfeditToken, swfedit_token, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL, swfedit_token_tree_model_init))
+
+static void
+swfedit_token_dispose (GObject *object)
+{
+ SwfeditToken *token = SWFEDIT_TOKEN (object);
+ guint i;
+
+ for (i = 0; i < token->tokens->len; i++) {
+ Entry *entry = &g_array_index (token->tokens, Entry, i);
+ g_free (entry->name);
+ if (converters[entry->type].free)
+ converters[entry->type].free (entry->value);
+ }
+ g_array_free (token->tokens, TRUE);
+
+ G_OBJECT_CLASS (swfedit_token_parent_class)->dispose (object);
+}
+
+static void
+swfedit_token_class_init (SwfeditTokenClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->dispose = swfedit_token_dispose;
+}
+
+static void
+swfedit_token_init (SwfeditToken *token)
+{
+ token->tokens = g_array_new (FALSE, FALSE, sizeof (Entry));
+}
+
+SwfeditToken *
+swfedit_token_new (void)
+{
+ SwfeditToken *token;
+
+ token = g_object_new (SWFEDIT_TYPE_TOKEN, NULL);
+ return token;
+}
+
+void
+swfedit_token_add (SwfeditToken *token, const char *name, SwfeditTokenType type, gpointer value)
+{
+ Entry entry = { NULL, type, value };
+
+ g_return_if_fail (SWFEDIT_IS_TOKEN (token));
+ g_return_if_fail (name != NULL);
+ g_return_if_fail (type < SWFEDIT_N_TOKENS);
+
+ entry.name = g_strdup (name);
+ g_array_append_val (token->tokens, entry);
+}
+
+void
+swfedit_token_set (SwfeditToken *token, GtkTreeIter *iter, const char *value)
+{
+ GtkTreeModel *model;
+ Entry *entry;
+ guint i;
+ gpointer new;
+ GtkTreePath *path;
+
+ g_return_if_fail (SWFEDIT_IS_TOKEN (token));
+ g_return_if_fail (iter != NULL);
+ g_return_if_fail (value != NULL);
+
+ model = GTK_TREE_MODEL (token);
+ token = iter->user_data;
+ i = GPOINTER_TO_UINT (iter->user_data2);
+ entry = &g_array_index (token->tokens, Entry, i);
+ if (converters[entry->type].read == NULL)
+ return;
+ if (!converters[entry->type].read (value, &new))
+ return;
+ if (converters[entry->type].free != NULL)
+ converters[entry->type].free (entry->value);
+ entry->value = new;
+
+ path = gtk_tree_model_get_path (model, iter);
+ gtk_tree_model_row_changed (model, path, iter);
+ gtk_tree_path_free (path);
+}
+
diff --git a/test/swfedit_token.h b/test/swfedit_token.h
new file mode 100644
index 0000000..1640027
--- /dev/null
+++ b/test/swfedit_token.h
@@ -0,0 +1,79 @@
+/* Swfedit
+ * Copyright (C) 2007 Benjamin Otte <otte at 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
+ */
+
+#ifndef __SWFEDIT_TOKEN_H__
+#define __SWFEDIT_TOKEN_H__
+
+#include <gtk/gtk.h>
+#include <libswfdec/swfdec_rect.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+ SWFEDIT_TOKEN_OBJECT,
+ SWFEDIT_TOKEN_BINARY,
+ SWFEDIT_TOKEN_UINT8,
+ SWFEDIT_TOKEN_UINT16,
+ SWFEDIT_TOKEN_UINT32,
+ SWFEDIT_N_TOKENS
+} SwfeditTokenType;
+
+typedef enum {
+ SWFEDIT_COLUMN_NAME,
+ SWFEDIT_COLUMN_VALUE_VISIBLE,
+ SWFEDIT_COLUMN_VALUE
+} SwfeditColumn;
+
+typedef struct _SwfeditToken SwfeditToken;
+typedef struct _SwfeditTokenClass SwfeditTokenClass;
+
+#define SWFEDIT_TYPE_TOKEN (swfedit_token_get_type())
+#define SWFEDIT_IS_TOKEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SWFEDIT_TYPE_TOKEN))
+#define SWFEDIT_IS_TOKEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SWFEDIT_TYPE_TOKEN))
+#define SWFEDIT_TOKEN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SWFEDIT_TYPE_TOKEN, SwfeditToken))
+#define SWFEDIT_TOKEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SWFEDIT_TYPE_TOKEN, SwfeditTokenClass))
+#define SWFEDIT_TOKEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SWFEDIT_TYPE_TOKEN, SwfeditTokenClass))
+
+struct _SwfeditToken {
+ GObject object;
+
+ SwfeditToken * parent; /* parent of this token or NULL */
+ gchar * name; /* name of token */
+ GArray * tokens; /* list of tokens */
+};
+
+struct _SwfeditTokenClass {
+ GObjectClass object_class;
+};
+
+GType swfedit_token_get_type (void);
+
+SwfeditToken * swfedit_token_new (void);
+void swfedit_token_add (SwfeditToken * token,
+ const char * name,
+ SwfeditTokenType type,
+ gpointer value);
+void swfedit_token_set (SwfeditToken * token,
+ GtkTreeIter * iter,
+ const char * value);
+
+
+G_END_DECLS
+
+#endif
diff-tree ac526c14b6a853304588e1c71ccc0ab709ac072e (from 134ac8ae16f9e1cf5dc68f4ebb97bba74bed0235)
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 22 18:32:04 2007 +0100
convert the parsing code to the recent SwfdecBits API
diff --git a/libswfdec/swfdec_swf_decoder.c b/libswfdec/swfdec_swf_decoder.c
index a43c9ac..6539921 100644
--- a/libswfdec/swfdec_swf_decoder.c
+++ b/libswfdec/swfdec_swf_decoder.c
@@ -206,10 +206,7 @@ swf_parse_header2 (SwfdecSwfDecoder * s)
return SWFDEC_STATUS_NEEDBITS;
}
- s->b.buffer = buffer;
- s->b.ptr = buffer->data;
- s->b.idx = 0;
- s->b.end = buffer->data + buffer->length;
+ swfdec_bits_init (&s->b, buffer);
swfdec_bits_get_rect (&s->b, &rect);
if (rect.x0 != 0.0 || rect.y0 != 0.0)
@@ -239,7 +236,6 @@ swfdec_swf_decoder_parse (SwfdecDecoder
{
SwfdecSwfDecoder *s = SWFDEC_SWF_DECODER (dec);
int ret = SWFDEC_STATUS_OK;
- const unsigned char *endptr;
SwfdecBuffer *buffer;
s->b = s->parse;
@@ -271,12 +267,7 @@ swfdec_swf_decoder_parse (SwfdecDecoder
if (buffer == NULL) {
return SWFDEC_STATUS_NEEDBITS;
}
-
- s->b.buffer = buffer;
- s->b.ptr = buffer->data;
- s->b.idx = 0;
- s->b.end = buffer->data + buffer->length;
-
+ swfdec_bits_init (&s->b, buffer);
x = swfdec_bits_get_u16 (&s->b);
tag = (x >> 6) & 0x3ff;
@@ -288,10 +279,7 @@ swfdec_swf_decoder_parse (SwfdecDecoder
if (buffer == NULL) {
return SWFDEC_STATUS_NEEDBITS;
}
- s->b.buffer = buffer;
- s->b.ptr = buffer->data;
- s->b.idx = 0;
- s->b.end = buffer->data + buffer->length;
+ swfdec_bits_init (&s->b, buffer);
swfdec_bits_get_u16 (&s->b);
tag_len = swfdec_bits_get_u32 (&s->b);
@@ -313,21 +301,11 @@ swfdec_swf_decoder_parse (SwfdecDecoder
buffer = swfdec_buffer_queue_pull (s->input_queue, header_length);
swfdec_buffer_unref (buffer);
- if (tag_len > 0) {
+ if (tag_len > 0)
buffer = swfdec_buffer_queue_pull (s->input_queue, tag_len);
- s->b.buffer = buffer;
- s->b.ptr = buffer->data;
- s->b.idx = 0;
- s->b.end = buffer->data + buffer->length;
- endptr = s->b.ptr + tag_len;
- } else {
+ else
buffer = NULL;
- s->b.buffer = NULL;
- s->b.ptr = NULL;
- s->b.idx = 0;
- s->b.end = NULL;
- endptr = NULL;
- }
+ swfdec_bits_init (&s->b, buffer);
func = swfdec_swf_decoder_get_tag_func (tag);
if (func == NULL) {
SWFDEC_WARNING ("tag function not implemented for %d %s",
@@ -338,18 +316,10 @@ swfdec_swf_decoder_parse (SwfdecDecoder
s->parse_sprite = NULL;
swfdec_bits_syncbits (&s->b);
- if (s->b.ptr < endptr) {
+ if (swfdec_bits_left (&s->b)) {
SWFDEC_WARNING
("early finish (%d bytes) at %d, tag %d %s, length %d",
- endptr - s->b.ptr,
- swfdec_buffer_queue_get_offset (s->input_queue), tag,
- swfdec_swf_decoder_get_tag_name (tag), tag_len);
- //dumpbits (&s->b);
- }
- if (s->b.ptr > endptr) {
- SWFDEC_WARNING
- ("parse_overrun (%d bytes) at %d, tag %d %s, length %d",
- s->b.ptr - endptr,
+ swfdec_bits_left (&s->b) / 8,
swfdec_buffer_queue_get_offset (s->input_queue), tag,
swfdec_swf_decoder_get_tag_name (tag), tag_len);
}
diff-tree 134ac8ae16f9e1cf5dc68f4ebb97bba74bed0235 (from 878ec656b0711cd19c11554d0617109a058af799)
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 22 18:17:48 2007 +0100
allow NULL buffer in swfdec_bits_init and 0 length in swfdec_bits_get_buffer
This simplifies error checking, since we catch errors in those cases anyway:
- NULL buffer bits are like data bits that finished reading
- 0 length get_buffer returns NULL, which is a valid return value for the error case
diff --git a/libswfdec/swfdec_bits.c b/libswfdec/swfdec_bits.c
index 72cc3df..1a7e402 100644
--- a/libswfdec/swfdec_bits.c
+++ b/libswfdec/swfdec_bits.c
@@ -31,16 +31,27 @@
#include "swfdec_rect.h"
+/**
+ * swfdec_bits_init:
+ * @bits: a #SwfdecBits
+ * @buffer: buffer to use for data or NULL
+ *
+ * initializes @bits for use with the data in @buffer. The buffer will not be
+ * referenced, so you are responsible for keeping it around while @bits is used.
+ **/
void
swfdec_bits_init (SwfdecBits *bits, SwfdecBuffer *buffer)
{
g_return_if_fail (bits != NULL);
- g_return_if_fail (buffer != NULL);
- bits->buffer = buffer;
- bits->ptr = buffer->data;
- bits->idx = 0;
- bits->end = buffer->data + buffer->length;
+ if (buffer) {
+ bits->buffer = buffer;
+ bits->ptr = buffer->data;
+ bits->idx = 0;
+ bits->end = buffer->data + buffer->length;
+ } else {
+ memset (bits, 0, sizeof (SwfdecBits));
+ }
}
/**
@@ -567,7 +578,7 @@ swfdec_bits_get_buffer (SwfdecBits *bits
{
SwfdecBuffer *buffer;
- g_return_val_if_fail (len > 0 || len == -1, NULL);
+ g_return_val_if_fail (len >= -1, NULL);
if (len > 0) {
SWFDEC_BYTES_CHECK (bits, (unsigned int) len);
@@ -575,9 +586,9 @@ swfdec_bits_get_buffer (SwfdecBits *bits
swfdec_bits_syncbits (bits);
len = bits->end - bits->ptr;
g_assert (len >= 0);
- if (len == 0)
- return NULL;
}
+ if (len == 0)
+ return NULL;
if (bits->buffer) {
buffer = swfdec_buffer_new_subbuffer (bits->buffer, bits->ptr - bits->buffer->data, len);
} else {
diff-tree 8c426c32f7343fff4ff23015f5f7eee647b5aee7 (from f2e4bc2ff2bfa289f325e525619b79dcf4815f9c)
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 22 10:54:05 2007 +0100
implement Increment and Decrement
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 909cba4..171877f 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -753,6 +753,26 @@ swfdec_action_if (JSContext *cx, guint a
return JS_TRUE;
}
+static JSBool
+swfdec_action_decrement (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ double d;
+
+ d = swfdec_action_to_number (cx, cx->fp->sp[-1]);
+ d--;
+ return JS_NewNumberValue (cx, d, &cx->fp->sp[-1]);
+}
+
+static JSBool
+swfdec_action_increment (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ double d;
+
+ d = swfdec_action_to_number (cx, cx->fp->sp[-1]);
+ d++;
+ return JS_NewNumberValue (cx, d, &cx->fp->sp[-1]);
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -967,8 +987,8 @@ static const SwfdecActionSpec actions[25
[0x4d] = { "Swap", NULL },
[0x4e] = { "GetMember", NULL, 2, 1, { NULL, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member } },
[0x4f] = { "SetMember", NULL, 3, 0, { NULL, swfdec_action_set_member, swfdec_action_set_member, swfdec_action_set_member, swfdec_action_set_member } },
- [0x50] = { "Increment", NULL },
- [0x51] = { "Decrement", NULL },
+ [0x50] = { "Increment", NULL, 1, 1, { NULL, NULL, swfdec_action_increment, swfdec_action_increment, swfdec_action_increment } },
+ [0x51] = { "Decrement", NULL, 1, 1, { NULL, NULL, swfdec_action_decrement, swfdec_action_decrement, swfdec_action_decrement } },
[0x52] = { "CallMethod", NULL, -1, 1, { NULL, NULL, swfdec_action_call_method, swfdec_action_call_method, swfdec_action_call_method } },
[0x53] = { "NewMethod", NULL },
/* version 6 */
diff-tree f2e4bc2ff2bfa289f325e525619b79dcf4815f9c (from 568f6fdf0b44ea7cfcc87b33ed4ac09e88bbd47e)
Author: Benjamin Otte <otte at gnome.org>
Date: Mon Jan 22 10:23:59 2007 +0100
Implement Jump, If and Not
Also includes a fix to voncert booleans to numbers correctly
11/44 failures
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 104af78..909cba4 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -527,6 +527,8 @@ swfdec_action_to_number (JSContext *cx,
return JSVAL_TO_INT (val);
} else if (JSVAL_IS_DOUBLE (val)) {
return *JSVAL_TO_DOUBLE (val);
+ } else if (JSVAL_IS_BOOLEAN (val)) {
+ return JSVAL_TO_BOOLEAN (val);
} else {
return 0;
}
@@ -704,9 +706,76 @@ swfdec_action_new_comparison_7 (JSContex
return JS_TRUE;
}
+static JSBool
+swfdec_action_not_4 (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ double d;
+
+ d = swfdec_action_to_number (cx, cx->fp->sp[-1]);
+ cx->fp->sp[-1] = INT_TO_JSVAL (d == 0 ? 1 : 0);
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_not_5 (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ double d;
+
+ d = swfdec_action_to_number (cx, cx->fp->sp[-1]);
+ cx->fp->sp[-1] = d == 0 ? JSVAL_TRUE : JSVAL_FALSE;
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_jump (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ if (len != 2) {
+ SWFDEC_ERROR ("Jump action length invalid (is %u, should be 2", len);
+ return JS_FALSE;
+ }
+ cx->fp->pc += 4 + GINT16_FROM_LE (*((gint16*) data));
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_if (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ double d;
+
+ if (len != 2) {
+ SWFDEC_ERROR ("Jump action length invalid (is %u, should be 2", len);
+ return JS_FALSE;
+ }
+ d = swfdec_action_to_number (cx, cx->fp->sp[-1]);
+ cx->fp->sp--;
+ if (d != 0)
+ cx->fp->pc += 4 + GINT16_FROM_LE (*((gint16*) data));
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
+swfdec_action_print_if (guint action, const guint8 *data, guint len)
+{
+ if (len != 2) {
+ SWFDEC_ERROR ("If action length invalid (is %u, should be 2", len);
+ return NULL;
+ }
+ return g_strdup_printf ("If %d", GINT16_FROM_LE (*((gint16*) data)));
+}
+
+static char *
+swfdec_action_print_jump (guint action, const guint8 *data, guint len)
+{
+ if (len != 2) {
+ SWFDEC_ERROR ("Jump action length invalid (is %u, should be 2", len);
+ return NULL;
+ }
+ return g_strdup_printf ("Jump %d", GINT16_FROM_LE (*((gint16*) data)));
+}
+
+static char *
swfdec_action_print_push (guint action, const guint8 *data, guint len)
{
gboolean first = TRUE;
@@ -844,7 +913,7 @@ static const SwfdecActionSpec actions[25
[0x0f] = { "Less", NULL },
[0x10] = { "And", NULL },
[0x11] = { "Or", NULL },
- [0x12] = { "Not", NULL },
+ [0x12] = { "Not", NULL, 1, 1, { NULL, swfdec_action_not_4, swfdec_action_not_5, swfdec_action_not_5, swfdec_action_not_5 } },
[0x13] = { "StringEquals", NULL },
[0x14] = { "StringLength", NULL },
[0x15] = { "StringExtract", NULL },
@@ -938,12 +1007,12 @@ static const SwfdecActionSpec actions[25
[0x94] = { "With", NULL },
/* version 4 */
[0x96] = { "Push", swfdec_action_print_push, 0, -1, { NULL, swfdec_action_push, swfdec_action_push, swfdec_action_push, swfdec_action_push } },
- [0x99] = { "Jump", NULL },
+ [0x99] = { "Jump", swfdec_action_print_jump, 0, 0, { NULL, swfdec_action_jump, swfdec_action_jump, swfdec_action_jump, swfdec_action_jump } },
[0x9a] = { "GetURL2", NULL },
/* version 5 */
[0x9b] = { "DefineFunction", NULL },
/* version 4 */
- [0x9d] = { "If", NULL },
+ [0x9d] = { "If", swfdec_action_print_if, 1, 0, { NULL, swfdec_action_if, swfdec_action_if, swfdec_action_if, swfdec_action_if } },
[0x9e] = { "Call", NULL },
[0x9f] = { "GotoFrame2", NULL }
};
diff-tree 568f6fdf0b44ea7cfcc87b33ed4ac09e88bbd47e (from e06e79a0c20256854b9073ee7c73a047e81dd820)
Author: Benjamin Otte <otte at gnome.org>
Date: Sun Jan 21 20:48:06 2007 +0100
fix binary ops for undefined2-7.swf
13/44 failures
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 3bbd168..104af78 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -540,8 +540,15 @@ swfdec_action_binary (JSContext *cx, gui
rval = cx->fp->sp[-1];
lval = cx->fp->sp[-2];
- l = swfdec_action_to_number (cx, lval);
- r = swfdec_action_to_number (cx, rval);
+ if (((SwfdecScript *) cx->fp->swf)->version < 7) {
+ l = swfdec_action_to_number (cx, lval);
+ r = swfdec_action_to_number (cx, rval);
+ } else {
+ if (!JS_ValueToNumber(cx, lval, &l) ||
+ !JS_ValueToNumber(cx, rval, &r))
+ return JS_FALSE;
+ }
+ cx->fp->sp--;
switch (action) {
case 0x0a:
l = l + r;
@@ -557,17 +564,22 @@ swfdec_action_binary (JSContext *cx, gui
JSString *str = JS_InternString (cx, "#ERROR#");
if (str == NULL)
return JS_FALSE;
- cx->fp->sp--;
cx->fp->sp[-1] = STRING_TO_JSVAL (str);
return JS_TRUE;
}
+ if (((SwfdecScript *) cx->fp->swf)->version >= 7 &&
+ JSVAL_IS_VOID (rval)) {
+ cx->fp->sp[-1] = DOUBLE_TO_JSVAL (r < 0 ?
+ cx->runtime->jsNegativeInfinity :
+ cx->runtime->jsPositiveInfinity);
+ return JS_TRUE;
+ }
l = l / r;
break;
default:
g_assert_not_reached ();
return r;
}
- cx->fp->sp--;
return JS_NewNumberValue (cx, l, &cx->fp->sp[-1]);
}
diff-tree e06e79a0c20256854b9073ee7c73a047e81dd820 (from 659db3d36cca2f586498ba8dd554f17dd50906f4)
Author: Benjamin Otte <otte at gnome.org>
Date: Sun Jan 21 19:24:27 2007 +0100
implement Less2 and Greater actions and fix a big bug
The code used to always execute the v7 script.
14/44 failues
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 5b9f960..3bbd168 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -651,6 +651,47 @@ swfdec_action_set_member (JSContext *cx,
return JS_TRUE;
}
+static JSBool
+swfdec_action_new_comparison_6 (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ jsval lval, rval;
+ double d, d2;
+
+ rval = cx->fp->sp[-1];
+ lval = cx->fp->sp[-2];
+ cx->fp->sp--;
+ d = swfdec_action_to_number (cx, lval);
+ d2 = swfdec_action_to_number (cx, rval);
+ if (action == 0x48)
+ cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (d < d2);
+ else
+ cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (d > d2);
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_new_comparison_7 (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ jsval lval, rval;
+
+ rval = cx->fp->sp[-1];
+ lval = cx->fp->sp[-2];
+ cx->fp->sp--;
+ if (JSVAL_IS_VOID (rval) || JSVAL_IS_VOID (lval)) {
+ cx->fp->sp[-1] = JSVAL_VOID;
+ } else if (JSVAL_IS_STRING(lval) && JSVAL_IS_STRING(rval)) {
+ int comp = JS_CompareStrings (JSVAL_TO_STRING (lval), JSVAL_TO_STRING (rval));
+ cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (action == 0x48 ? comp < 0 : comp > 0);
+ } else {
+ double d, d2;
+ if (!JS_ValueToNumber(cx, lval, &d) ||
+ !JS_ValueToNumber(cx, rval, &d2))
+ return JS_FALSE;
+ cx->fp->sp[-1] = BOOLEAN_TO_JSVAL (action == 0x48 ? d < d2 : d > d2);
+ }
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -762,7 +803,7 @@ swfdec_action_print_wait_for_frame (guin
/* defines minimum and maximum versions for which we have seperate scripts */
#define MINSCRIPTVERSION 3
#define MAXSCRIPTVERSION 7
-#define EXTRACT_VERSION(v) MAX ((v) - MINSCRIPTVERSION, MAXSCRIPTVERSION - MINSCRIPTVERSION)
+#define EXTRACT_VERSION(v) MIN ((v) - MINSCRIPTVERSION, MAXSCRIPTVERSION - MINSCRIPTVERSION)
typedef JSBool (* SwfdecActionExec) (JSContext *cx, guint action, const guint8 *data, guint len);
typedef struct {
@@ -837,7 +878,7 @@ static const SwfdecActionSpec actions[25
[0x45] = { "TargetPath", NULL },
[0x46] = { "Enumerate", NULL },
[0x47] = { "Add2", NULL, 2, 1, { NULL, NULL, NULL, NULL, swfdec_action_add2_7 } },
- [0x48] = { "Less2", NULL },
+ [0x48] = { "Less2", NULL, 2, 1, { NULL, NULL, swfdec_action_new_comparison_6, swfdec_action_new_comparison_6, swfdec_action_new_comparison_7 } },
[0x49] = { "Equals2", NULL },
[0x4a] = { "ToNumber", NULL },
[0x4b] = { "ToString", NULL },
@@ -861,7 +902,7 @@ static const SwfdecActionSpec actions[25
[0x65] = { "BitURShift", NULL },
/* version 6 */
[0x66] = { "StrictEquals", NULL },
- [0x67] = { "Greater", NULL },
+ [0x67] = { "Greater", NULL, 2, 1, { NULL, NULL, NULL, swfdec_action_new_comparison_6, swfdec_action_new_comparison_7 } },
[0x68] = { "StringGreater", NULL },
/* version 7 */
[0x69] = { "Extends", NULL },
diff-tree 659db3d36cca2f586498ba8dd554f17dd50906f4 (from 39276bcb05d190d1fc6a0c35490774ee309f4ffb)
Author: Benjamin Otte <otte at gnome.org>
Date: Sat Jan 20 17:01:06 2007 +0100
Fix case handling (don't make it global anymore) and implement SetVariable
with this there's 17/44 failures
diff --git a/libswfdec/js/jsatom.c b/libswfdec/js/jsatom.c
index f0816b2..c4c85b7 100644
--- a/libswfdec/js/jsatom.c
+++ b/libswfdec/js/jsatom.c
@@ -673,10 +673,10 @@ out:
JSAtom *
js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
{
- if (cx->caseSensitive)
- return js_AtomizeStringWithCompare (cx, str, flags, js_compare_atom_keys);
- else
+ if (flags & ATOM_NOCASE)
return js_AtomizeStringWithCompare (cx, str, flags, js_compare_atom_keys_no_case);
+ else
+ return js_AtomizeStringWithCompare (cx, str, flags, js_compare_atom_keys);
}
JS_FRIEND_API(JSAtom *)
diff --git a/libswfdec/js/jsatom.h b/libswfdec/js/jsatom.h
index 6f486c3..d9d2025 100644
--- a/libswfdec/js/jsatom.h
+++ b/libswfdec/js/jsatom.h
@@ -58,6 +58,7 @@ JS_BEGIN_EXTERN_C
#define ATOM_PINNED 0x01 /* atom is pinned against GC */
#define ATOM_INTERNED 0x02 /* pinned variant for JS_Intern* API */
#define ATOM_MARK 0x04 /* atom is reachable via GC */
+#define ATOM_NOCASE 0x20 /* treat atom case-insensitive */
#define ATOM_NOCOPY 0x40 /* don't copy atom string bytes */
#define ATOM_TMPSTR 0x80 /* internal, to avoid extra string */
diff --git a/libswfdec/swfdec_edittext_movie.c b/libswfdec/swfdec_edittext_movie.c
index 421f6bc..e3d2119 100644
--- a/libswfdec/swfdec_edittext_movie.c
+++ b/libswfdec/swfdec_edittext_movie.c
@@ -80,7 +80,7 @@ swfdec_edit_text_movie_iterate (SwfdecMo
jsobj = swfdec_scriptable_get_object (parent);
if (jsobj == NULL)
return;
- val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable);
+ val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable, FALSE);
if (JSVAL_IS_VOID (val))
return;
@@ -110,7 +110,7 @@ swfdec_edit_text_movie_init_movie (Swfde
if (jsobj == NULL)
return;
if (text->text->variable_prefix) {
- val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable_prefix);
+ val = swfdec_js_eval (parent->jscx, jsobj, text->text->variable_prefix, FALSE);
if (!JSVAL_IS_OBJECT (val))
return;
jsobj = JSVAL_TO_OBJECT (val);
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index cf14f65..bbd6a43 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -300,29 +300,26 @@ fail:
static JSBool
swfdec_js_eval_get_property (JSContext *cx, JSObject *obj,
- const char *name, gboolean initial, jsval *ret)
+ const char *name, gboolean initial, gboolean ignore_case, jsval *ret)
{
JSAtom *atom;
JSObject *pobj;
JSProperty *prop;
- if (!JS_GetProperty (cx, obj, name, ret))
- return JS_FALSE;
- if (!JSVAL_IS_VOID (*ret))
- return JS_TRUE;
- if (!initial)
- return JS_FALSE;
-
- atom = js_Atomize(cx, name, strlen(name), 0);
+ atom = js_Atomize (cx, name, strlen(name), ignore_case ? ATOM_NOCASE : 0);
if (!atom)
return JS_FALSE;
- if (!js_FindProperty (cx, (jsid) atom, &obj, &pobj, &prop))
- return JS_FALSE;
- if (!prop)
- return JS_FALSE;
- if (pobj)
- obj = pobj;
- return OBJ_GET_PROPERTY (cx, obj, (jsid) prop->id, ret);
+ if (initial) {
+ return OBJ_GET_PROPERTY (cx, obj, (jsid) atom, ret);
+ } else {
+ if (!js_FindProperty (cx, (jsid) atom, &obj, &pobj, &prop))
+ return JS_FALSE;
+ if (!prop)
+ return JS_FALSE;
+ if (pobj)
+ obj = pobj;
+ return OBJ_GET_PROPERTY (cx, obj, (jsid) prop->id, ret);
+ }
}
/**
@@ -330,6 +327,7 @@ swfdec_js_eval_get_property (JSContext *
* @cx: a #JSContext
* @obj: #JSObject to use as a source for evaluating
* @str: The string to evaluate
+ * @ignore_case: TRUE for case insensitive evaluation
*
* This function works like the Actionscript eval function used on @obj.
* It handles both slash-style and dot-style notation.
@@ -337,7 +335,8 @@ swfdec_js_eval_get_property (JSContext *
* Returns: the value or JSVAL_VOID if no value was found.
**/
jsval
-swfdec_js_eval (JSContext *cx, JSObject *obj, const char *str)
+swfdec_js_eval (JSContext *cx, JSObject *obj, const char *str,
+ gboolean ignore_case)
{
jsval cur;
char *work = NULL;
@@ -365,12 +364,12 @@ swfdec_js_eval (JSContext *cx, JSObject
obj = JSVAL_TO_OBJECT (cur);
if (dot) {
char *name = g_strndup (str, dot - str);
- if (!swfdec_js_eval_get_property (cx, obj, name, initial, &cur))
+ if (!swfdec_js_eval_get_property (cx, obj, name, initial, ignore_case, &cur))
goto out;
g_free (name);
str = dot + 1;
} else {
- if (!swfdec_js_eval_get_property (cx, obj, str, initial, &cur))
+ if (!swfdec_js_eval_get_property (cx, obj, str, initial, ignore_case, &cur))
goto out;
str = NULL;
}
@@ -384,3 +383,5 @@ out:
g_free (work);
return JSVAL_VOID;
}
+
+
diff --git a/libswfdec/swfdec_js.h b/libswfdec/swfdec_js.h
index ced8046..47e97ff 100644
--- a/libswfdec/swfdec_js.h
+++ b/libswfdec/swfdec_js.h
@@ -49,7 +49,8 @@ void swfdec_js_movie_remove_property (S
char * swfdec_js_slash_to_dot (const char * slash_str);
jsval swfdec_js_eval (JSContext * cx,
JSObject * obj,
- const char * str);
+ const char * str,
+ gboolean ignore_case);
/* support functions */
const char * swfdec_js_to_string (JSContext * cx,
diff --git a/libswfdec/swfdec_js_global.c b/libswfdec/swfdec_js_global.c
index 328d74d..27522c1 100644
--- a/libswfdec/swfdec_js_global.c
+++ b/libswfdec/swfdec_js_global.c
@@ -33,7 +33,7 @@ swfdec_js_global_eval (JSContext *cx, JS
const char *bytes = swfdec_js_to_string (cx, argv[0]);
if (bytes == NULL)
return JS_FALSE;
- *rval = swfdec_js_eval (cx, obj, bytes);
+ *rval = swfdec_js_eval (cx, obj, bytes, FALSE);
} else {
*rval = argv[0];
}
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 23ca8ef..5b9f960 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -315,7 +315,26 @@ swfdec_action_get_variable (JSContext *c
s = swfdec_js_to_string (cx, cx->fp->sp[-1]);
if (s == NULL)
return JS_FALSE;
- cx->fp->sp[-1] = swfdec_js_eval (cx, cx->fp->scopeChain, s);
+ cx->fp->sp[-1] = swfdec_js_eval (cx, cx->fp->scopeChain, s,
+ ((SwfdecScript *) cx->fp->swf)->version < 7);
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_set_variable (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ const char *s;
+
+ s = swfdec_js_to_string (cx, cx->fp->sp[-2]);
+ if (s == NULL)
+ return JS_FALSE;
+
+ if (strpbrk (s, "./:")) {
+ SWFDEC_WARNING ("FIXME: implement paths");
+ }
+ if (!JS_SetProperty (cx, cx->fp->scopeChain, s, &cx->fp->sp[-1]))
+ return JS_FALSE;
+ cx->fp->sp -= 2;
return JS_TRUE;
}
@@ -425,7 +444,8 @@ swfdec_eval_jsval (JSContext *cx, JSObje
const char *bytes = swfdec_js_to_string (cx, *val);
if (bytes == NULL)
return JS_FALSE;
- *val = swfdec_js_eval (cx, obj, bytes);
+ *val = swfdec_js_eval (cx, obj, bytes,
+ ((SwfdecScript *) cx->fp->swf)->version < 7);
} else {
*val = OBJECT_TO_JSVAL (obj);
}
@@ -500,6 +520,57 @@ out:
return JS_TRUE;
}
+static double
+swfdec_action_to_number (JSContext *cx, jsval val)
+{
+ if (JSVAL_IS_INT (val)) {
+ return JSVAL_TO_INT (val);
+ } else if (JSVAL_IS_DOUBLE (val)) {
+ return *JSVAL_TO_DOUBLE (val);
+ } else {
+ return 0;
+ }
+}
+
+static JSBool
+swfdec_action_binary (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ jsval lval, rval;
+ double l, r;
+
+ rval = cx->fp->sp[-1];
+ lval = cx->fp->sp[-2];
+ l = swfdec_action_to_number (cx, lval);
+ r = swfdec_action_to_number (cx, rval);
+ switch (action) {
+ case 0x0a:
+ l = l + r;
+ break;
+ case 0x0b:
+ l = l - r;
+ break;
+ case 0x0c:
+ l = l * r;
+ break;
+ case 0x0d:
+ if (r == 0 && ((SwfdecScript *) cx->fp->swf)->version < 5) {
+ JSString *str = JS_InternString (cx, "#ERROR#");
+ if (str == NULL)
+ return JS_FALSE;
+ cx->fp->sp--;
+ cx->fp->sp[-1] = STRING_TO_JSVAL (str);
+ return JS_TRUE;
+ }
+ l = l / r;
+ break;
+ default:
+ g_assert_not_reached ();
+ return r;
+ }
+ cx->fp->sp--;
+ return JS_NewNumberValue (cx, l, &cx->fp->sp[-1]);
+}
+
static JSBool
swfdec_action_add2_7 (JSContext *cx, guint action, const guint8 *data, guint len)
{
@@ -539,7 +610,7 @@ swfdec_action_add2_7 (JSContext *cx, gui
return JS_FALSE;
d += d2;
cx->fp->sp--;
- return JS_NewDoubleValue(cx, d, &cx->fp->sp[-1]);
+ return JS_NewNumberValue(cx, d, &cx->fp->sp[-1]);
}
return JS_TRUE;
}
@@ -712,10 +783,10 @@ static const SwfdecActionSpec actions[25
[0x08] = { "ToggleQuality", NULL },
[0x09] = { "StopSounds", NULL },
/* version 4 */
- [0x0a] = { "Add", NULL },
- [0x0b] = { "Subtract", NULL },
- [0x0c] = { "Multiply", NULL },
- [0x0d] = { "Divide", NULL },
+ [0x0a] = { "Add", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
+ [0x0b] = { "Subtract", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
+ [0x0c] = { "Multiply", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
+ [0x0d] = { "Divide", NULL, 2, 1, { NULL, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary, swfdec_action_binary } },
[0x0e] = { "Equals", NULL },
[0x0f] = { "Less", NULL },
[0x10] = { "And", NULL },
@@ -727,7 +798,7 @@ static const SwfdecActionSpec actions[25
[0x17] = { "Pop", NULL, 1, 0, { NULL, swfdec_action_pop, swfdec_action_pop, swfdec_action_pop, swfdec_action_pop } },
[0x18] = { "ToInteger", NULL },
[0x1c] = { "GetVariable", NULL, 1, 1, { NULL, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable } },
- [0x1d] = { "SetVariable", NULL },
+ [0x1d] = { "SetVariable", NULL, 2, 0, { NULL, swfdec_action_set_variable, swfdec_action_set_variable, swfdec_action_set_variable, swfdec_action_set_variable } },
[0x20] = { "SetTarget2", NULL },
[0x21] = { "StringAdd", NULL },
[0x22] = { "GetProperty", NULL, 2, 1, { NULL, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property } },
diff-tree 39276bcb05d190d1fc6a0c35490774ee309f4ffb (from 41d6a77090dff7583e4a61937120db79d1c4c547)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Jan 19 22:14:26 2007 +0100
fix SetMember
20/44 failures
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 0256d8c..23ca8ef 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -427,7 +427,7 @@ swfdec_eval_jsval (JSContext *cx, JSObje
return JS_FALSE;
*val = swfdec_js_eval (cx, obj, bytes);
} else {
- SWFDEC_ERROR ("huh?");
+ *val = OBJECT_TO_JSVAL (obj);
}
return JS_TRUE;
}
@@ -475,7 +475,7 @@ swfdec_action_set_property (JSContext *c
JSObject *jsobj;
guint32 id;
- val = cx->fp->sp[-2];
+ val = cx->fp->sp[-3];
if (!swfdec_eval_jsval (cx, cx->fp->scopeChain, &val))
return JS_FALSE;
movie = swfdec_scriptable_from_jsval (cx, val, SWFDEC_TYPE_MOVIE);
@@ -483,7 +483,7 @@ swfdec_action_set_property (JSContext *c
SWFDEC_WARNING ("specified target does not reference a movie clip");
goto out;
}
- if (!JS_ValueToECMAUint32 (cx, cx->fp->sp[-1], &id))
+ if (!JS_ValueToECMAUint32 (cx, cx->fp->sp[-2], &id))
return JS_FALSE;
if (id > (((SwfdecScript *) cx->fp->swf)->version > 4 ? 21 : 18))
@@ -492,7 +492,7 @@ swfdec_action_set_property (JSContext *c
if (!(jsobj = swfdec_scriptable_get_object (SWFDEC_SCRIPTABLE (movie))))
return JS_FALSE;
- if (!JS_SetProperty (cx, jsobj, properties[id], &cx->fp->sp[-3]))
+ if (!JS_SetProperty (cx, jsobj, properties[id], &cx->fp->sp[-1]))
return JS_FALSE;
out:
diff-tree 41d6a77090dff7583e4a61937120db79d1c4c547 (from f07034751126d85a58b48ff77bbf57c5dc8021ca)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Jan 19 21:17:45 2007 +0100
push a double, not a float
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 583c2f1..0256d8c 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -251,7 +251,7 @@ swfdec_action_push (JSContext *cx, guint
break;
case 6: /* double */
{
- double d = swfdec_bits_get_float (&bits);
+ double d = swfdec_bits_get_double (&bits);
if (!JS_NewDoubleValue (cx, d, cx->fp->sp))
return JS_FALSE;
cx->fp->sp++;
diff-tree f07034751126d85a58b48ff77bbf57c5dc8021ca (from 34c98c5cf9deb0b5fc10f0cbee7bf368f3653000)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Jan 19 21:16:28 2007 +0100
fix string Add2
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index e4bf0d4..583c2f1 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -520,11 +520,11 @@ swfdec_action_add2_7 (JSContext *cx, gui
JSString *str, *str2;
if (cond) {
str = JSVAL_TO_STRING (lval);
- if ((str2 = js_ValueToString (cx, rval)) != NULL)
+ if ((str2 = js_ValueToString (cx, rval)) == NULL)
return JS_FALSE;
} else {
str2 = JSVAL_TO_STRING (rval);
- if ((str = js_ValueToString (cx, lval)) != NULL)
+ if ((str = js_ValueToString (cx, lval)) == NULL)
return JS_FALSE;
}
str = js_ConcatStrings (cx, str, str2);
diff-tree 34c98c5cf9deb0b5fc10f0cbee7bf368f3653000 (from 756c3c6c257d890fd5b35221ab7451017bb56d03)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Jan 19 21:16:11 2007 +0100
implement SetMember
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 8f073b7..e4bf0d4 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -563,6 +563,23 @@ swfdec_action_get_member (JSContext *cx,
return JS_TRUE;
}
+static JSBool
+swfdec_action_set_member (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ const char *s;
+
+ s = swfdec_js_to_string (cx, cx->fp->sp[-2]);
+ if (s == NULL)
+ return JS_FALSE;
+
+ if (JSVAL_IS_OBJECT (cx->fp->sp[-3])) {
+ if (!JS_SetProperty (cx, JSVAL_TO_OBJECT (cx->fp->sp[-3]), s, &cx->fp->sp[-1]))
+ return JS_FALSE;
+ }
+ cx->fp->sp -= 3;
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -756,7 +773,7 @@ static const SwfdecActionSpec actions[25
[0x4c] = { "PushDuplicate", NULL },
[0x4d] = { "Swap", NULL },
[0x4e] = { "GetMember", NULL, 2, 1, { NULL, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member } },
- [0x4f] = { "SetMember", NULL }, /* apparently the result is ignored */
+ [0x4f] = { "SetMember", NULL, 3, 0, { NULL, swfdec_action_set_member, swfdec_action_set_member, swfdec_action_set_member, swfdec_action_set_member } },
[0x50] = { "Increment", NULL },
[0x51] = { "Decrement", NULL },
[0x52] = { "CallMethod", NULL, -1, 1, { NULL, NULL, swfdec_action_call_method, swfdec_action_call_method, swfdec_action_call_method } },
diff-tree 756c3c6c257d890fd5b35221ab7451017bb56d03 (from 469151c6400bd4dde8b9e0356274bbec5f105c4b)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Jan 19 19:34:22 2007 +0100
implement GetMember and Add2 for Flash7
30/44 failures
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index b8d3dc6..8f073b7 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -500,6 +500,69 @@ out:
return JS_TRUE;
}
+static JSBool
+swfdec_action_add2_7 (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ jsval rval, lval;
+ gboolean cond;
+
+ rval = cx->fp->sp[-1];
+ lval = cx->fp->sp[-2];
+ if (!JSVAL_IS_PRIMITIVE (rval)) {
+ if (!OBJ_DEFAULT_VALUE (cx, JSVAL_TO_OBJECT (rval), 0 , &rval))
+ return JS_FALSE;
+ }
+ if (!JSVAL_IS_PRIMITIVE (lval)) {
+ if (!OBJ_DEFAULT_VALUE (cx, JSVAL_TO_OBJECT (lval), 0 , &lval))
+ return JS_FALSE;
+ }
+ if ((cond = JSVAL_IS_STRING (lval)) || JSVAL_IS_STRING (rval)) {
+ JSString *str, *str2;
+ if (cond) {
+ str = JSVAL_TO_STRING (lval);
+ if ((str2 = js_ValueToString (cx, rval)) != NULL)
+ return JS_FALSE;
+ } else {
+ str2 = JSVAL_TO_STRING (rval);
+ if ((str = js_ValueToString (cx, lval)) != NULL)
+ return JS_FALSE;
+ }
+ str = js_ConcatStrings (cx, str, str2);
+ if (!str)
+ return JS_FALSE;
+ cx->fp->sp--;
+ cx->fp->sp[-1] = STRING_TO_JSVAL (str);
+ } else {
+ double d, d2;
+ if (!JS_ValueToNumber(cx, lval, &d) ||
+ !JS_ValueToNumber(cx, rval, &d2))
+ return JS_FALSE;
+ d += d2;
+ cx->fp->sp--;
+ return JS_NewDoubleValue(cx, d, &cx->fp->sp[-1]);
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_get_member (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ const char *s;
+
+ s = swfdec_js_to_string (cx, cx->fp->sp[-1]);
+ if (s == NULL)
+ return JS_FALSE;
+
+ if (JSVAL_IS_OBJECT (cx->fp->sp[-2])) {
+ if (!JS_GetProperty (cx, JSVAL_TO_OBJECT (cx->fp->sp[-2]), s, &cx->fp->sp[-2]))
+ return JS_FALSE;
+ } else {
+ cx->fp->sp[-2] = JSVAL_VOID;
+ }
+ cx->fp->sp--;
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -685,14 +748,14 @@ static const SwfdecActionSpec actions[25
[0x44] = { "Typeof", NULL },
[0x45] = { "TargetPath", NULL },
[0x46] = { "Enumerate", NULL },
- [0x47] = { "Add2", NULL },
+ [0x47] = { "Add2", NULL, 2, 1, { NULL, NULL, NULL, NULL, swfdec_action_add2_7 } },
[0x48] = { "Less2", NULL },
[0x49] = { "Equals2", NULL },
[0x4a] = { "ToNumber", NULL },
[0x4b] = { "ToString", NULL },
[0x4c] = { "PushDuplicate", NULL },
[0x4d] = { "Swap", NULL },
- [0x4e] = { "GetMember", NULL },
+ [0x4e] = { "GetMember", NULL, 2, 1, { NULL, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member, swfdec_action_get_member } },
[0x4f] = { "SetMember", NULL }, /* apparently the result is ignored */
[0x50] = { "Increment", NULL },
[0x51] = { "Decrement", NULL },
diff-tree 469151c6400bd4dde8b9e0356274bbec5f105c4b (from 1df9fa9d227af58658f4c2b9bf1e9a6719c4d9dc)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Jan 19 13:27:27 2007 +0100
add GetProperty and SetProperty actions
32/44 failures now
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index e688089..b8d3dc6 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -410,6 +410,96 @@ swfdec_action_pop (JSContext *cx, guint
return JS_TRUE;
}
+static const char *properties[22] = {
+ "_x", "_y", "_xscale", "_yscale", "_currentframe",
+ "_totalframes", "_alpha", "_visible", "_width", "_height",
+ "_rotation", "_target", "_framesloaded", "_name", "_droptarget",
+ "_url", "_highquality", "_focusrect", "_soundbuftime", "_quality",
+ "_xmouse", "_ymouse"
+};
+
+static JSBool
+swfdec_eval_jsval (JSContext *cx, JSObject *obj, jsval *val)
+{
+ if (JSVAL_IS_STRING (*val)) {
+ const char *bytes = swfdec_js_to_string (cx, *val);
+ if (bytes == NULL)
+ return JS_FALSE;
+ *val = swfdec_js_eval (cx, obj, bytes);
+ } else {
+ SWFDEC_ERROR ("huh?");
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_get_property (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ jsval val;
+ SwfdecMovie *movie;
+ JSObject *jsobj;
+ guint32 id;
+
+ val = cx->fp->sp[-2];
+ if (!swfdec_eval_jsval (cx, cx->fp->scopeChain, &val))
+ return JS_FALSE;
+ movie = swfdec_scriptable_from_jsval (cx, val, SWFDEC_TYPE_MOVIE);
+ val = JSVAL_VOID;
+ if (movie == NULL) {
+ SWFDEC_WARNING ("specified target does not reference a movie clip");
+ goto out;
+ }
+ if (!JS_ValueToECMAUint32 (cx, cx->fp->sp[-1], &id))
+ return JS_FALSE;
+
+ if (id > (((SwfdecScript *) cx->fp->swf)->version > 4 ? 21 : 18))
+ goto out;
+
+ if (!(jsobj = swfdec_scriptable_get_object (SWFDEC_SCRIPTABLE (movie))))
+ return JS_FALSE;
+
+ if (!JS_GetProperty (cx, jsobj, properties[id], &val))
+ return JS_FALSE;
+
+out:
+ cx->fp->sp -= 1;
+ cx->fp->sp[-1] = val;
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_set_property (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ jsval val;
+ SwfdecMovie *movie;
+ JSObject *jsobj;
+ guint32 id;
+
+ val = cx->fp->sp[-2];
+ if (!swfdec_eval_jsval (cx, cx->fp->scopeChain, &val))
+ return JS_FALSE;
+ movie = swfdec_scriptable_from_jsval (cx, val, SWFDEC_TYPE_MOVIE);
+ if (movie == NULL) {
+ SWFDEC_WARNING ("specified target does not reference a movie clip");
+ goto out;
+ }
+ if (!JS_ValueToECMAUint32 (cx, cx->fp->sp[-1], &id))
+ return JS_FALSE;
+
+ if (id > (((SwfdecScript *) cx->fp->swf)->version > 4 ? 21 : 18))
+ goto out;
+
+ if (!(jsobj = swfdec_scriptable_get_object (SWFDEC_SCRIPTABLE (movie))))
+ return JS_FALSE;
+
+ if (!JS_SetProperty (cx, jsobj, properties[id], &cx->fp->sp[-3]))
+ return JS_FALSE;
+
+out:
+ cx->fp->sp -= 3;
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -560,8 +650,8 @@ static const SwfdecActionSpec actions[25
[0x1d] = { "SetVariable", NULL },
[0x20] = { "SetTarget2", NULL },
[0x21] = { "StringAdd", NULL },
- [0x22] = { "GetProperty", NULL },
- [0x23] = { "SetProperty", NULL },
+ [0x22] = { "GetProperty", NULL, 2, 1, { NULL, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property, swfdec_action_get_property } },
+ [0x23] = { "SetProperty", NULL, 3, 0, { NULL, swfdec_action_set_property, swfdec_action_set_property, swfdec_action_set_property, swfdec_action_set_property } },
[0x24] = { "CloneSprite", NULL },
[0x25] = { "RemoveSprite", NULL },
[0x26] = { "Trace", NULL, 1, 0, { NULL, swfdec_action_trace, swfdec_action_trace, swfdec_action_trace, swfdec_action_trace } },
diff-tree 1df9fa9d227af58658f4c2b9bf1e9a6719c4d9dc (from 1fbe061229c9be6b6374f95fc0e70a786e8a33d5)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Jan 19 13:27:05 2007 +0100
add stub for _quality property
diff --git a/libswfdec/swfdec_js_movie.c b/libswfdec/swfdec_js_movie.c
index f5bf871..70ddece 100644
--- a/libswfdec/swfdec_js_movie.c
+++ b/libswfdec/swfdec_js_movie.c
@@ -1056,6 +1056,7 @@ static JSPropertySpec movieclip_props[]
{"_highquality", -1, MC_PROP_ATTRS, not_reached, not_reached },
{"_focusrect", -1, MC_PROP_ATTRS, not_reached, not_reached },
{"_soundbuftime", -1, MC_PROP_ATTRS, not_reached, not_reached },
+ {"_quality", -1, MC_PROP_ATTRS, not_reached, not_reached },
{"_xmouse", -1, MC_PROP_ATTRS, not_reached, not_reached },
{"_ymouse", -1, MC_PROP_ATTRS, not_reached, not_reached },
{"_parent", -1, MC_PROP_ATTRS | JSPROP_READONLY, mc_parent, NULL},
diff-tree 1fbe061229c9be6b6374f95fc0e70a786e8a33d5 (from 5f777f6697273122587f8bcf645e3a81a7f77228)
Author: Benjamin Otte <otte at gnome.org>
Date: Fri Jan 19 12:53:56 2007 +0100
implement CallMethod and Pop + lots of bugfixing
after this commit, test/trace has 33/44 failures
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index ed5ac44..e688089 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -304,7 +304,7 @@ swfdec_action_push (JSContext *cx, guint
return JS_FALSE;
}
}
- return swfdec_bits_left (&bits) ? JS_TRUE : JS_FALSE;
+ return swfdec_bits_left (&bits) ? JS_FALSE : JS_TRUE;
}
static JSBool
@@ -326,6 +326,7 @@ swfdec_action_trace (JSContext *cx, guin
const char *bytes;
bytes = swfdec_js_to_string (cx, cx->fp->sp[-1]);
+ cx->fp->sp--;
if (bytes == NULL)
return JS_TRUE;
@@ -333,6 +334,82 @@ swfdec_action_trace (JSContext *cx, guin
return JS_TRUE;
}
+/**
+ * swfdec_action_invoke:
+ * @cx: the #JSContext
+ * @n_args: number of arguments
+ *
+ * This function is similar to js_Invoke, however it uses a reversed stack
+ * order. sp[-1] has to be the function to call, sp[-2] will be the object the
+ * function is called on, sp[-3] is the first argument, followed by the rest of
+ * the arguments. The function reorders the stack on success and pushes the
+ * return value on top.
+ *
+ * Returns: JS_TRUE on success, JS_FALSE on failure.
+ **/
+static JSBool
+swfdec_action_call (JSContext *cx, guint n_args, guint flags)
+{
+ int i, j;
+ jsval tmp;
+
+ j = -1;
+ i = - (n_args + 2);
+ while (i < j) {
+ tmp = cx->fp->sp[j];
+ cx->fp->sp[j] = cx->fp->sp[i];
+ cx->fp->sp[i] = tmp;
+ j--;
+ i++;
+ }
+ return js_Invoke (cx, n_args, flags);
+}
+
+static JSBool
+swfdec_action_call_method (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ JSStackFrame *fp = cx->fp;
+ const char *s;
+ guint32 n_args;
+ JSObject *obj;
+ jsval fun;
+
+ s = swfdec_js_to_string (cx, fp->sp[-1]);
+ if (s == NULL)
+ return JS_FALSE;
+ if (!JS_ValueToECMAUint32 (cx, fp->sp[-3], &n_args))
+ return JS_FALSE;
+ if (n_args + 3 > (guint) (fp->sp - fp->spbase))
+ return JS_FALSE;
+
+ if (!JSVAL_IS_OBJECT (fp->sp[-2]))
+ goto fail;
+ obj = JSVAL_TO_OBJECT (fp->sp[-2]);
+ if (s[0] == '\0') {
+ fun = OBJECT_TO_JSVAL (obj);
+ } else {
+ if (!JS_GetProperty (cx, obj, s, &fun))
+ return JS_FALSE;
+ }
+ fp->sp--;
+ fp->sp[-1] = fun;
+ fp->sp[-2] = OBJECT_TO_JSVAL (obj);
+ swfdec_action_call (cx, n_args, 0);
+ return JS_TRUE;
+
+fail:
+ fp->sp -= 2 + n_args;
+ fp->sp[-1] = JSVAL_VOID;
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_pop (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ cx->fp->sp--;
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -477,7 +554,7 @@ static const SwfdecActionSpec actions[25
[0x13] = { "StringEquals", NULL },
[0x14] = { "StringLength", NULL },
[0x15] = { "StringExtract", NULL },
- [0x17] = { "Pop", NULL },
+ [0x17] = { "Pop", NULL, 1, 0, { NULL, swfdec_action_pop, swfdec_action_pop, swfdec_action_pop, swfdec_action_pop } },
[0x18] = { "ToInteger", NULL },
[0x1c] = { "GetVariable", NULL, 1, 1, { NULL, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable } },
[0x1d] = { "SetVariable", NULL },
@@ -529,7 +606,7 @@ static const SwfdecActionSpec actions[25
[0x4f] = { "SetMember", NULL }, /* apparently the result is ignored */
[0x50] = { "Increment", NULL },
[0x51] = { "Decrement", NULL },
- [0x52] = { "CallMethod", NULL },
+ [0x52] = { "CallMethod", NULL, -1, 1, { NULL, NULL, swfdec_action_call_method, swfdec_action_call_method, swfdec_action_call_method } },
[0x53] = { "NewMethod", NULL },
/* version 6 */
[0x54] = { "InstanceOf", NULL },
@@ -726,7 +803,7 @@ swfdec_script_interpret (SwfdecScript *s
guint8 *startpc, *pc, *endpc, *nextpc;
JSBool ok = JS_TRUE;
void *mark;
- jsval *startsp, *endsp;
+ jsval *startsp, *endsp, *checksp;
int stack_check;
guint action, len;
guint8 *data;
@@ -800,6 +877,8 @@ swfdec_script_interpret (SwfdecScript *s
goto internal_error;
}
if (spec->add < 0) {
+ /* HACK FIXME: if added args are -1, we pass the number of free space on the stack
+ * instead of the action */
action = endsp - fp->sp;
} else {
if (fp->sp + spec->add - MAX (spec->remove, 0) > endsp) {
@@ -807,9 +886,18 @@ swfdec_script_interpret (SwfdecScript *s
goto internal_error;
}
}
+ checksp = (spec->add >= 0 && spec->remove >= 0) ? fp->sp + spec->add - spec->remove : NULL;
ok = spec->exec[version] (cx, action, data, len);
- if (!ok)
+ if (!ok) {
+ SWFDEC_WARNING ("action %s failed", spec->name);
goto out;
+ }
+ if (checksp != NULL && checksp != fp->sp) {
+ /* check stack was handled like expected */
+ g_error ("action %s was supposed to change the stack by %d (+%d -%d), but it changed by %d",
+ spec->name, spec->add - spec->remove, spec->add, spec->remove,
+ fp->sp - checksp + spec->add - spec->remove);
+ }
if (fp->pc == pc) {
fp->pc = pc = nextpc;
} else {
diff-tree 5f777f6697273122587f8bcf645e3a81a7f77228 (from 878ec656b0711cd19c11554d0617109a058af799)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Jan 18 18:15:51 2007 +0100
implement Trace action
includes changing the API to have a swfdec_player_trace function
diff --git a/libswfdec/swfdec_js_global.c b/libswfdec/swfdec_js_global.c
index daa8f75..328d74d 100644
--- a/libswfdec/swfdec_js_global.c
+++ b/libswfdec/swfdec_js_global.c
@@ -50,8 +50,7 @@ swfdec_js_trace (JSContext *cx, JSObject
if (bytes == NULL)
return JS_TRUE;
- /* FIXME: accumulate and emit after JS handling? */
- g_signal_emit_by_name (player, "trace", bytes);
+ swfdec_player_trace (player, bytes);
return JS_TRUE;
}
diff --git a/libswfdec/swfdec_player.c b/libswfdec/swfdec_player.c
index 811e7c6..4b29d28 100644
--- a/libswfdec/swfdec_player.c
+++ b/libswfdec/swfdec_player.c
@@ -837,6 +837,16 @@ swfdec_player_stop_all_sounds (SwfdecPla
}
void
+swfdec_player_trace (SwfdecPlayer *player, const char *text)
+{
+ g_return_if_fail (SWFDEC_IS_PLAYER (player));
+ g_return_if_fail (text != NULL);
+
+ /* FIXME: accumulate and emit after JS handling? */
+ g_signal_emit (player, signals[TRACE], 0, text);
+}
+
+void
swfdec_player_invalidate (SwfdecPlayer *player, const SwfdecRect *rect)
{
if (swfdec_rect_is_empty (rect)) {
diff --git a/libswfdec/swfdec_player_internal.h b/libswfdec/swfdec_player_internal.h
index dd10949..2da8ecc 100644
--- a/libswfdec/swfdec_player_internal.h
+++ b/libswfdec/swfdec_player_internal.h
@@ -122,6 +122,8 @@ void swfdec_player_set_drag_movie (Swfd
SwfdecMovie * drag,
gboolean center,
SwfdecRect * rect);
+void swfdec_player_trace (SwfdecPlayer * player,
+ const char * text);
void swfdec_player_stop_all_sounds (SwfdecPlayer * player);
SwfdecRootMovie * swfdec_player_add_level_from_loader
(SwfdecPlayer * player,
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 49ad92f..ed5ac44 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -31,6 +31,7 @@
#include "swfdec_decoder.h"
#include "swfdec_js.h"
#include "swfdec_movie.h"
+#include "swfdec_player_internal.h"
#include "swfdec_root_movie.h"
/*** CONSTANT POOLS ***/
@@ -318,6 +319,20 @@ swfdec_action_get_variable (JSContext *c
return JS_TRUE;
}
+static JSBool
+swfdec_action_trace (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ SwfdecPlayer *player = JS_GetContextPrivate (cx);
+ const char *bytes;
+
+ bytes = swfdec_js_to_string (cx, cx->fp->sp[-1]);
+ if (bytes == NULL)
+ return JS_TRUE;
+
+ swfdec_player_trace (player, bytes);
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -472,7 +487,7 @@ static const SwfdecActionSpec actions[25
[0x23] = { "SetProperty", NULL },
[0x24] = { "CloneSprite", NULL },
[0x25] = { "RemoveSprite", NULL },
- [0x26] = { "Trace", NULL },
+ [0x26] = { "Trace", NULL, 1, 0, { NULL, swfdec_action_trace, swfdec_action_trace, swfdec_action_trace, swfdec_action_trace } },
[0x27] = { "StartDrag", NULL },
[0x28] = { "EndDrag", NULL },
[0x29] = { "StringLess", NULL },
diff-tree 878ec656b0711cd19c11554d0617109a058af799 (from 8a1b77a18b9266e33c5e92ebeb0a8edbb7b6e643)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Jan 18 15:05:37 2007 +0100
implement GetVariable, fix a missing break in print_push and add better debugging
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index a27f037..49ad92f 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -29,6 +29,7 @@
#include <string.h>
#include "swfdec_decoder.h"
+#include "swfdec_js.h"
#include "swfdec_movie.h"
#include "swfdec_root_movie.h"
@@ -305,6 +306,18 @@ swfdec_action_push (JSContext *cx, guint
return swfdec_bits_left (&bits) ? JS_TRUE : JS_FALSE;
}
+static JSBool
+swfdec_action_get_variable (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ const char *s;
+
+ s = swfdec_js_to_string (cx, cx->fp->sp[-1]);
+ if (s == NULL)
+ return JS_FALSE;
+ cx->fp->sp[-1] = swfdec_js_eval (cx, cx->fp->scopeChain, s);
+ return JS_TRUE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
@@ -352,6 +365,7 @@ swfdec_action_print_push (guint action,
break;
case 7: /* 32bit int */
g_string_append_printf (string, "%u", swfdec_bits_get_u32 (&bits));
+ break;
case 8: /* 8bit ConstantPool address */
g_string_append_printf (string, "Pool %u", swfdec_bits_get_u8 (&bits));
break;
@@ -450,7 +464,7 @@ static const SwfdecActionSpec actions[25
[0x15] = { "StringExtract", NULL },
[0x17] = { "Pop", NULL },
[0x18] = { "ToInteger", NULL },
- [0x1c] = { "GetVariable", NULL },
+ [0x1c] = { "GetVariable", NULL, 1, 1, { NULL, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable, swfdec_action_get_variable } },
[0x1d] = { "SetVariable", NULL },
[0x20] = { "SetTarget2", NULL },
[0x21] = { "StringAdd", NULL },
@@ -604,8 +618,9 @@ validate_action (guint action, const gui
/* ensure there's a function to execute this opcode, otherwise fail */
if (actions[action].exec[version] == NULL) {
- SWFDEC_ERROR ("no opcode for %u %s", action,
- actions[action].name ? actions[action].name : "Unknown");
+ SWFDEC_ERROR ("no function for %u %s in v%u", action,
+ actions[action].name ? actions[action].name : "Unknown",
+ script->version);
return FALSE;
}
/* we might want to do stuff here for certain actions */
diff-tree 8a1b77a18b9266e33c5e92ebeb0a8edbb7b6e643 (from c41b8582293535b64bf83c19843bd4eae8662e6f)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Jan 18 12:52:36 2007 +0100
implement ConstantPool and Push
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 5b01510..a27f037 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -27,18 +27,86 @@
#include "js/jscntxt.h"
#include "js/jsinterp.h"
-/*** SUPPORT FUNCTIONS ***/
-
+#include <string.h>
#include "swfdec_decoder.h"
#include "swfdec_movie.h"
#include "swfdec_root_movie.h"
+/*** CONSTANT POOLS ***/
+
+typedef GPtrArray SwfdecConstantPool;
+
+static SwfdecConstantPool *
+swfdec_constant_pool_new_from_action (const guint8 *data, guint len)
+{
+ guint8 *next;
+ guint i, n;
+ GPtrArray *pool;
+
+ if (len < 2) {
+ SWFDEC_ERROR ("constant pool too small");
+ return NULL;
+ }
+ n = GUINT16_FROM_LE (*((guint16*) data));
+ data += 2;
+ len -= 2;
+ pool = g_ptr_array_sized_new (n);
+ g_ptr_array_set_size (pool, n);
+ for (i = 0; i < n; i++) {
+ next = memchr (data, 0, len);
+ if (next == NULL) {
+ SWFDEC_ERROR ("not enough strings available");
+ g_ptr_array_free (pool, TRUE);
+ return NULL;
+ }
+ next++;
+ g_ptr_array_index (pool, i) = (gpointer) data;
+ len -= next - data;
+ data = next;
+ }
+ if (len != 0) {
+ SWFDEC_WARNING ("constant pool didn't consume whole buffer (%u bytes leftover)", len);
+ }
+ return pool;
+}
+
+static guint
+swfdec_constant_pool_size (SwfdecConstantPool *pool)
+{
+ return pool->len;
+}
+
+static const char *
+swfdec_constant_pool_get (SwfdecConstantPool *pool, guint i)
+{
+ g_assert (i < pool->len);
+ return g_ptr_array_index (pool, i);
+}
+
+static void
+swfdec_constant_pool_free (SwfdecConstantPool *pool)
+{
+ g_ptr_array_free (pool, TRUE);
+}
+
+/*** SUPPORT FUNCTIONS ***/
+
static SwfdecMovie *
swfdec_action_get_target (JSContext *cx)
{
return swfdec_scriptable_from_jsval (cx, OBJECT_TO_JSVAL (cx->fp->scopeChain), SWFDEC_TYPE_MOVIE);
}
+static JSBool
+swfdec_action_push_string (JSContext *cx, const char *s)
+{
+ JSString *string = JS_NewStringCopyZ (cx, s);
+ if (string == NULL)
+ return JS_FALSE;
+ *cx->fp->sp++ = STRING_TO_JSVAL (string);
+ return JS_TRUE;
+}
+
/*** ALL THE ACTION IS HERE ***/
static JSBool
@@ -130,9 +198,194 @@ swfdec_action_wait_for_frame (JSContext
return JS_TRUE;
}
+static JSBool
+swfdec_action_constant_pool (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ SwfdecConstantPool *pool;
+
+ pool = swfdec_constant_pool_new_from_action (data, len);
+ if (pool == NULL)
+ return JS_FALSE;
+ if (cx->fp->constant_pool)
+ swfdec_constant_pool_free (cx->fp->constant_pool);
+ cx->fp->constant_pool = pool;
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_push (JSContext *cx, guint stackspace, const guint8 *data, guint len)
+{
+ /* FIXME: supply API for this */
+ SwfdecBits bits;
+
+ swfdec_bits_init_data (&bits, data, len);
+ while (swfdec_bits_left (&bits) && stackspace-- > 0) {
+ guint type = swfdec_bits_get_u8 (&bits);
+ SWFDEC_LOG ("push type %u", type);
+ switch (type) {
+ case 0: /* string */
+ {
+ const char *s = swfdec_bits_skip_string (&bits);
+ if (!swfdec_action_push_string (cx, s))
+ return JS_FALSE;
+ break;
+ }
+ case 1: /* float */
+ {
+ double d = swfdec_bits_get_float (&bits);
+ if (!JS_NewDoubleValue (cx, d, cx->fp->sp))
+ return JS_FALSE;
+ cx->fp->sp++;
+ break;
+ }
+ case 2: /* null */
+ *cx->fp->sp++ = JSVAL_NULL;
+ break;
+ case 3: /* undefined */
+ *cx->fp->sp++ = JSVAL_VOID;
+ break;
+ case 5: /* boolean */
+ *cx->fp->sp++ = swfdec_bits_get_u8 (&bits) ? JSVAL_TRUE : JSVAL_FALSE;
+ break;
+ case 6: /* double */
+ {
+ double d = swfdec_bits_get_float (&bits);
+ if (!JS_NewDoubleValue (cx, d, cx->fp->sp))
+ return JS_FALSE;
+ cx->fp->sp++;
+ break;
+ }
+ case 7: /* 32bit int */
+ {
+ /* FIXME: spec says U32, do they mean this? */
+ guint i = swfdec_bits_get_u32 (&bits);
+ *cx->fp->sp++ = INT_TO_JSVAL (i);
+ break;
+ }
+ case 8: /* 8bit ConstantPool address */
+ {
+ guint i = swfdec_bits_get_u8 (&bits);
+ SwfdecConstantPool *pool = cx->fp->constant_pool;
+ if (pool == NULL) {
+ SWFDEC_ERROR ("no constant pool to push from");
+ return JS_FALSE;
+ }
+ if (i >= swfdec_constant_pool_size (pool)) {
+ SWFDEC_ERROR ("constant pool index %u too high - only %u elements",
+ i, swfdec_constant_pool_size (pool));
+ return JS_FALSE;
+ }
+ if (!swfdec_action_push_string (cx, swfdec_constant_pool_get (pool, i)))
+ return JS_FALSE;
+ break;
+ }
+ case 9: /* 16bit ConstantPool address */
+ {
+ guint i = swfdec_bits_get_u16 (&bits);
+ SwfdecConstantPool *pool = cx->fp->constant_pool;
+ if (pool == NULL) {
+ SWFDEC_ERROR ("no constant pool to push from");
+ return JS_FALSE;
+ }
+ if (i >= swfdec_constant_pool_size (pool)) {
+ SWFDEC_ERROR ("constant pool index %u too high - only %u elements",
+ i, swfdec_constant_pool_size (pool));
+ return JS_FALSE;
+ }
+ if (!swfdec_action_push_string (cx, swfdec_constant_pool_get (pool, i)))
+ return JS_FALSE;
+ break;
+ }
+ case 4: /* register */
+ default:
+ SWFDEC_ERROR ("Push: type %u not implemented", type);
+ return JS_FALSE;
+ }
+ }
+ return swfdec_bits_left (&bits) ? JS_TRUE : JS_FALSE;
+}
+
/*** PRINT FUNCTIONS ***/
static char *
+swfdec_action_print_push (guint action, const guint8 *data, guint len)
+{
+ gboolean first = TRUE;
+ SwfdecBits bits;
+ GString *string = g_string_new ("Push");
+
+ swfdec_bits_init_data (&bits, data, len);
+ while (swfdec_bits_left (&bits)) {
+ guint type = swfdec_bits_get_u8 (&bits);
+ if (first)
+ g_string_append (string, " ");
+ else
+ g_string_append (string, ", ");
+ first = FALSE;
+ switch (type) {
+ case 0: /* string */
+ {
+ const char *s = swfdec_bits_skip_string (&bits);
+ if (!s) {
+ g_string_free (string, TRUE);
+ return NULL;
+ }
+ g_string_append_c (string, '"');
+ g_string_append (string, s);
+ g_string_append_c (string, '"');
+ break;
+ }
+ case 1: /* float */
+ g_string_append_printf (string, "%g", swfdec_bits_get_float (&bits));
+ break;
+ case 2: /* null */
+ g_string_append (string, "null");
+ break;
+ case 3: /* undefined */
+ g_string_append (string, "void");
+ break;
+ case 5: /* boolean */
+ g_string_append (string, swfdec_bits_get_u8 (&bits) ? "True" : "False");
+ break;
+ case 6: /* double */
+ g_string_append_printf (string, "%g", swfdec_bits_get_double (&bits));
+ break;
+ case 7: /* 32bit int */
+ g_string_append_printf (string, "%u", swfdec_bits_get_u32 (&bits));
+ case 8: /* 8bit ConstantPool address */
+ g_string_append_printf (string, "Pool %u", swfdec_bits_get_u8 (&bits));
+ break;
+ case 9: /* 16bit ConstantPool address */
+ g_string_append_printf (string, "Pool %u", swfdec_bits_get_u16 (&bits));
+ break;
+ case 4: /* register */
+ default:
+ SWFDEC_ERROR ("Push: type %u not implemented", type);
+ return JS_FALSE;
+ }
+ }
+ return g_string_free (string, FALSE);
+}
+
+static char *
+swfdec_action_print_constant_pool (guint action, const guint8 *data, guint len)
+{
+ guint i;
+ GString *string;
+ SwfdecConstantPool *pool;
+
+ pool = swfdec_constant_pool_new_from_action (data, len);
+ if (pool == NULL)
+ return JS_FALSE;
+ string = g_string_new ("ConstantPool");
+ for (i = 0; i < swfdec_constant_pool_size (pool); i++) {
+ g_string_append (string, i ? ", " : " ");
+ g_string_append (string, swfdec_constant_pool_get (pool, i));
+ }
+ return g_string_free (string, FALSE);
+}
+
+static char *
swfdec_action_print_goto_frame (guint action, const guint8 *data, guint len)
{
guint frame;
@@ -162,13 +415,14 @@ swfdec_action_print_wait_for_frame (guin
/* defines minimum and maximum versions for which we have seperate scripts */
#define MINSCRIPTVERSION 3
#define MAXSCRIPTVERSION 7
+#define EXTRACT_VERSION(v) MAX ((v) - MINSCRIPTVERSION, MAXSCRIPTVERSION - MINSCRIPTVERSION)
typedef JSBool (* SwfdecActionExec) (JSContext *cx, guint action, const guint8 *data, guint len);
typedef struct {
const char * name; /* name identifying the action */
char * (* print) (guint action, const guint8 *data, guint len);
int remove; /* values removed from stack or -1 for dynamic */
- guint add; /* values added to the stack */
+ int add; /* values added to the stack or -1 for dynamic */
SwfdecActionExec exec[MAXSCRIPTVERSION - MINSCRIPTVERSION + 1];
/* array is for version 3, 4, 5, 6, 7+ */
} SwfdecActionSpec;
@@ -270,7 +524,7 @@ static const SwfdecActionSpec actions[25
[0x83] = { "GetURL", NULL },
/* version 5 */
[0x87] = { "StoreRegister", NULL },
- [0x88] = { "ConstantPool", NULL },
+ [0x88] = { "ConstantPool", swfdec_action_print_constant_pool, 0, 0, { NULL, NULL, swfdec_action_constant_pool, swfdec_action_constant_pool, swfdec_action_constant_pool } },
/* version 3 */
[0x8a] = { "WaitForFrame", swfdec_action_print_wait_for_frame, 0, 0, { swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame } },
[0x8b] = { "SetTarget", NULL },
@@ -283,7 +537,7 @@ static const SwfdecActionSpec actions[25
/* version 5 */
[0x94] = { "With", NULL },
/* version 4 */
- [0x96] = { "Push", NULL },
+ [0x96] = { "Push", swfdec_action_print_push, 0, -1, { NULL, swfdec_action_push, swfdec_action_push, swfdec_action_push, swfdec_action_push } },
[0x99] = { "Jump", NULL },
[0x9a] = { "GetURL2", NULL },
/* version 5 */
@@ -320,7 +574,7 @@ static gboolean
swfdec_script_foreach (SwfdecBits *bits, SwfdecScriptForeachFunc func, gpointer user_data)
{
guint action, len;
- guint8 *data;
+ const guint8 *data;
while ((action = swfdec_bits_get_u8 (bits))) {
if (action & 0x80) {
@@ -343,10 +597,19 @@ swfdec_script_foreach (SwfdecBits *bits,
/*** PUBLIC API ***/
static gboolean
-validate_action (guint action, const guint8 *data, guint len, gpointer script)
+validate_action (guint action, const guint8 *data, guint len, gpointer scriptp)
{
+ SwfdecScript *script = scriptp;
+ int version = EXTRACT_VERSION (script->version);
+
+ /* ensure there's a function to execute this opcode, otherwise fail */
+ if (actions[action].exec[version] == NULL) {
+ SWFDEC_ERROR ("no opcode for %u %s", action,
+ actions[action].name ? actions[action].name : "Unknown");
+ return FALSE;
+ }
/* we might want to do stuff here for certain actions */
-#if 0
+#if 1
{
char *foo = swfdec_script_print_action (action, data, len);
if (foo == NULL)
@@ -361,7 +624,7 @@ SwfdecScript *
swfdec_script_new (SwfdecBits *bits, const char *name, unsigned int version)
{
SwfdecScript *script;
- guchar *start;
+ const guchar *start;
g_return_val_if_fail (bits != NULL, NULL);
if (version < MINSCRIPTVERSION) {
@@ -442,7 +705,7 @@ swfdec_script_interpret (SwfdecScript *s
/* set up general stuff */
swfdec_script_ref (script);
- version = MAX (script->version - MINSCRIPTVERSION, MAXSCRIPTVERSION - MINSCRIPTVERSION);
+ version = EXTRACT_VERSION (script->version);
*rval = JSVAL_VOID;
fp = cx->fp;
/* set up the script */
@@ -506,9 +769,13 @@ swfdec_script_interpret (SwfdecScript *s
spec->name, spec->remove, fp->sp - fp->spbase);
goto internal_error;
}
- if (fp->sp + spec->add - MAX (spec->remove, 0) > endsp) {
- SWFDEC_ERROR ("FIXME: implement stack expansion, we got an overflow");
- goto internal_error;
+ if (spec->add < 0) {
+ action = endsp - fp->sp;
+ } else {
+ if (fp->sp + spec->add - MAX (spec->remove, 0) > endsp) {
+ SWFDEC_ERROR ("FIXME: implement stack expansion, we got an overflow");
+ goto internal_error;
+ }
}
ok = spec->exec[version] (cx, action, data, len);
if (!ok)
@@ -574,6 +841,7 @@ swfdec_script_execute (SwfdecScript *scr
frame.varobj = obj;
frame.fun = NULL;
frame.swf = script;
+ frame.constant_pool = NULL;
frame.thisp = obj;
frame.argc = frame.nvars = 0;
frame.argv = frame.vars = NULL;
@@ -604,6 +872,10 @@ swfdec_script_execute (SwfdecScript *scr
*/
ok = swfdec_script_interpret (script, cx, &frame.rval);
+ /* FIXME: where to clean this up? */
+ if (frame.constant_pool)
+ swfdec_constant_pool_free (frame.constant_pool);
+
cx->fp = oldfp;
if (oldfp) {
g_assert (cx->dormantFrameChain == oldfp);
diff-tree c41b8582293535b64bf83c19843bd4eae8662e6f (from 539f1f3151a6deb4f231f3289d3c8c232eb21bc7)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Jan 18 12:51:56 2007 +0100
add the constant pool to the stack frame
diff --git a/libswfdec/js/jsinterp.h b/libswfdec/js/jsinterp.h
index b22166d..88bab68 100644
--- a/libswfdec/js/jsinterp.h
+++ b/libswfdec/js/jsinterp.h
@@ -56,6 +56,7 @@ struct JSStackFrame {
JSObject *varobj; /* variables object, where vars go */
JSScript *script; /* script being interpreted or NULL */
void *swf; /* SwfdecScript being executed if script is NULL */
+ void *constant_pool; /* constant pool used by SwfdecScript */
JSFunction *fun; /* function being called or null */
JSObject *thisp; /* "this" pointer if in method */
uintN argc; /* actual argument count */
diff-tree 539f1f3151a6deb4f231f3289d3c8c232eb21bc7 (from c3f0eaf5706a0d972132a0ea4fcaff5aa79ec122)
Author: Benjamin Otte <otte at gnome.org>
Date: Thu Jan 18 12:47:17 2007 +0100
implement swfdec_bits_init_from_data to use SwfdecBits without a buffer
Also make bits.ptr and bits.end const variables.
This required cleaning up lots of old code that still accessed SwfdecBits directly
I bet there were a lot of security issues there ;)
diff --git a/libswfdec/swfdec_bits.c b/libswfdec/swfdec_bits.c
index f9f2749..72cc3df 100644
--- a/libswfdec/swfdec_bits.c
+++ b/libswfdec/swfdec_bits.c
@@ -43,6 +43,27 @@ swfdec_bits_init (SwfdecBits *bits, Swfd
bits->end = buffer->data + buffer->length;
}
+/**
+ * swfdec_bits_init_data:
+ * @bits: the #SwfdecBits to initialize
+ * @data: data to initialize with
+ * @len: length of the data
+ *
+ * Initializes @bits for use with the given @data. All operations on @bits will
+ * return copies of the data, so after use, you can free the supplied data.
+ **/
+void
+swfdec_bits_init_data (SwfdecBits *bits, const guint8 *data, guint len)
+{
+ g_return_if_fail (bits != NULL);
+ g_return_if_fail (data != NULL);
+
+ bits->buffer = NULL;
+ bits->ptr = data;
+ bits->idx = 0;
+ bits->end = bits->ptr + len;
+}
+
unsigned int
swfdec_bits_left (SwfdecBits *b)
{
@@ -557,7 +578,12 @@ swfdec_bits_get_buffer (SwfdecBits *bits
if (len == 0)
return NULL;
}
- buffer = swfdec_buffer_new_subbuffer (bits->buffer, bits->ptr - bits->buffer->data, len);
+ if (bits->buffer) {
+ buffer = swfdec_buffer_new_subbuffer (bits->buffer, bits->ptr - bits->buffer->data, len);
+ } else {
+ buffer = swfdec_buffer_new_and_alloc (len);
+ memcpy (buffer->data, bits->ptr, len);
+ }
bits->ptr += len;
return buffer;
}
diff --git a/libswfdec/swfdec_bits.h b/libswfdec/swfdec_bits.h
index 86440f7..08ae1d8 100644
--- a/libswfdec/swfdec_bits.h
+++ b/libswfdec/swfdec_bits.h
@@ -32,13 +32,14 @@ typedef struct _SwfdecBits SwfdecBits;
struct _SwfdecBits
{
- SwfdecBuffer *buffer;
- unsigned char *ptr;
- unsigned int idx;
- unsigned char *end;
+ SwfdecBuffer * buffer; /* buffer data is taken from or NULL */
+ const unsigned char * ptr; /* current location to read from */
+ unsigned int idx; /* bits already read from ptr */
+ const unsigned char * end; /* pointer after last byte */
};
void swfdec_bits_init (SwfdecBits *bits, SwfdecBuffer *buffer);
+void swfdec_bits_init_data (SwfdecBits *bits, const guint8 *data, guint len);
unsigned int swfdec_bits_left (SwfdecBits *b);
int swfdec_bits_getbit (SwfdecBits * b);
unsigned int swfdec_bits_getbits (SwfdecBits * b, unsigned int n);
diff --git a/libswfdec/swfdec_codec_screen.c b/libswfdec/swfdec_codec_screen.c
index 305db49..de21d21 100644
--- a/libswfdec/swfdec_codec_screen.c
+++ b/libswfdec/swfdec_codec_screen.c
@@ -140,7 +140,7 @@ swfdec_codec_screen_decode (gpointer cod
if (inflateReset(&screen->z) != Z_OK) {
SWFDEC_ERROR ("error resetting zlib decoder: %s", screen->z.msg);
}
- screen->z.next_in = bits.ptr;
+ screen->z.next_in = (void *) bits.ptr;
if (swfdec_bits_skip_bytes (&bits, size) != size) {
SWFDEC_ERROR ("not enough bytes available");
return NULL;
diff --git a/libswfdec/swfdec_image.c b/libswfdec/swfdec_image.c
index 6c2dcae..c9df0de 100644
--- a/libswfdec/swfdec_image.c
+++ b/libswfdec/swfdec_image.c
@@ -99,46 +99,30 @@ zfree (void *opaque, void *addr)
g_free (addr);
}
-static void *
-lossless (void *zptr, int zlen, int *plen)
+static guint8 *
+lossless (const guint8 *zptr, int zlen, int len)
{
- void *data;
- int len;
- z_stream *z;
+ guint8 *data;
+ z_stream z = { NULL, };
int ret;
- z = g_new0 (z_stream, 1);
- z->zalloc = zalloc;
- z->zfree = zfree;
- z->opaque = NULL;
-
- z->next_in = zptr;
- z->avail_in = zlen;
-
- data = NULL;
- len = 0;
- ret = inflateInit (z);
- while (z->avail_in > 0) {
- if (z->avail_out == 0) {
- len += 1024;
- data = g_realloc (data, len);
- z->next_out = data + z->total_out;
- z->avail_out += 1024;
- }
- ret = inflate (z, Z_SYNC_FLUSH);
- if (ret != Z_OK)
- break;
- }
+ z.zalloc = zalloc;
+ z.zfree = zfree;
+ z.opaque = NULL;
+
+ data = g_malloc (len);
+ z.next_in = (Bytef *) zptr;
+ z.avail_in = zlen;
+ z.next_out = data;
+ z.avail_out = len;
+
+ ret = inflateInit (&z);
+ ret = inflate (&z, Z_SYNC_FLUSH);
if (ret != Z_STREAM_END) {
SWFDEC_WARNING ("lossless: ret == %d", ret);
}
+ inflateEnd (&z);
- if (plen)
- (*plen) = z->total_out;
-
- inflateEnd (z);
-
- g_free (z);
return data;
}
@@ -278,11 +262,8 @@ int
tag_func_define_bits_jpeg_3 (SwfdecSwfDecoder * s)
{
SwfdecBits *bits = &s->b;
- int id;
+ guint id;
SwfdecImage *image;
- unsigned char *endptr;
-
- endptr = bits->ptr + bits->buffer->length;
id = swfdec_bits_get_u16 (bits);
SWFDEC_LOG (" id = %d", id);
@@ -292,9 +273,7 @@ tag_func_define_bits_jpeg_3 (SwfdecSwfDe
return SWFDEC_STATUS_OK;
image->type = SWFDEC_IMAGE_TYPE_JPEG3;
- image->raw_data = swfdec_buffer_ref (bits->buffer);
-
- bits->ptr += bits->buffer->length - 2;
+ image->raw_data = swfdec_bits_get_buffer (bits, -1);
return SWFDEC_STATUS_OK;
}
@@ -306,21 +285,20 @@ swfdec_image_jpeg3_load (SwfdecImage *im
unsigned char *image_data;
unsigned char *alpha_data;
SwfdecBits bits;
- int len;
+ SwfdecBuffer *buffer;
int jpeg_length;
- bits.buffer = image->raw_data;
- bits.ptr = image->raw_data->data;
- bits.idx = 0;
- bits.end = bits.ptr + image->raw_data->length;
-
- bits.ptr += 2;
+ swfdec_bits_init (&bits, image->raw_data);
jpeg_length = swfdec_bits_get_u32 (&bits);
+ buffer = swfdec_bits_get_buffer (&bits, jpeg_length);
+ if (buffer == NULL)
+ return;
dec = jpeg_rgb_decoder_new ();
- jpeg_rgb_decoder_addbits (dec, bits.ptr, jpeg_length);
+ jpeg_rgb_decoder_addbits (dec, buffer->data, buffer->length);
+ swfdec_buffer_unref (buffer);
jpeg_rgb_decoder_parse (dec);
jpeg_rgb_decoder_get_image_size (dec, &image->width, &image->height);
if (image->width == 0 || image->height == 0) {
@@ -332,9 +310,9 @@ swfdec_image_jpeg3_load (SwfdecImage *im
&image->rowstride, &image->width, &image->height);
jpeg_rgb_decoder_free (dec);
- bits.ptr += jpeg_length;
-
- alpha_data = lossless (bits.ptr, bits.end - bits.ptr, &len);
+ buffer = swfdec_bits_get_buffer (&bits, -1);
+ alpha_data = lossless (buffer->data, buffer->length, image->width * image->height);
+ swfdec_buffer_unref (buffer);
merge_alpha (image, image_data, alpha_data);
g_free (alpha_data);
@@ -372,19 +350,12 @@ swfdec_image_lossless_load (SwfdecImage
int format;
int color_table_size;
unsigned char *ptr;
- int len;
unsigned char *endptr;
SwfdecBits bits;
unsigned char *image_data = NULL;
int have_alpha = (image->type == SWFDEC_IMAGE_TYPE_LOSSLESS2);
- bits.buffer = image->raw_data;
- bits.ptr = image->raw_data->data;
- bits.idx = 0;
- bits.end = bits.ptr + image->raw_data->length;
- endptr = bits.ptr + bits.buffer->length;
-
- bits.ptr += 2;
+ swfdec_bits_init (&bits, image->raw_data);
format = swfdec_bits_get_u8 (&bits);
SWFDEC_LOG (" format = %d", format);
@@ -406,7 +377,7 @@ swfdec_image_lossless_load (SwfdecImage
if (image->width == 0 || image->height == 0)
return;
swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height);
- ptr = lossless (bits.ptr, endptr - bits.ptr, &len);
+ ptr = lossless (bits.ptr, endptr - bits.ptr, image->width * image->height);
bits.ptr = endptr;
if (format == 3) {
@@ -531,9 +502,8 @@ tag_func_define_bits_lossless (SwfdecSwf
return SWFDEC_STATUS_OK;
image->type = SWFDEC_IMAGE_TYPE_LOSSLESS;
- image->raw_data = swfdec_buffer_ref (bits->buffer);
+ image->raw_data = swfdec_bits_get_buffer (bits, -1);
- bits->ptr += bits->buffer->length - 2;
return SWFDEC_STATUS_OK;
}
@@ -552,9 +522,7 @@ tag_func_define_bits_lossless_2 (SwfdecS
return SWFDEC_STATUS_OK;
image->type = SWFDEC_IMAGE_TYPE_LOSSLESS2;
- image->raw_data = swfdec_buffer_ref (bits->buffer);
-
- bits->ptr += bits->buffer->length - 2;
+ image->raw_data = swfdec_bits_get_buffer (bits, -1);
return SWFDEC_STATUS_OK;
}
diff --git a/libswfdec/swfdec_swf_decoder.c b/libswfdec/swfdec_swf_decoder.c
index e7be205..a43c9ac 100644
--- a/libswfdec/swfdec_swf_decoder.c
+++ b/libswfdec/swfdec_swf_decoder.c
@@ -239,7 +239,7 @@ swfdec_swf_decoder_parse (SwfdecDecoder
{
SwfdecSwfDecoder *s = SWFDEC_SWF_DECODER (dec);
int ret = SWFDEC_STATUS_OK;
- unsigned char *endptr;
+ const unsigned char *endptr;
SwfdecBuffer *buffer;
s->b = s->parse;
diff --git a/libswfdec/swfdec_tag.c b/libswfdec/swfdec_tag.c
index 4f57b1a..3896101 100644
--- a/libswfdec/swfdec_tag.c
+++ b/libswfdec/swfdec_tag.c
@@ -212,7 +212,6 @@ tag_func_define_sprite (SwfdecSwfDecoder
s->parse_sprite = sprite;
while (1) {
- unsigned char *endptr;
int x;
int tag;
guint tag_len;
@@ -258,7 +257,7 @@ tag_func_define_sprite (SwfdecSwfDecoder
SWFDEC_ERROR ("invalid tag %d %s during DefineSprite",
tag, swfdec_swf_decoder_get_tag_name (tag));
} else {
- endptr = parse.ptr + tag_len;
+ const unsigned char *endptr = parse.ptr + tag_len;
ret = func (s);
swfdec_bits_syncbits (bits);
@@ -311,22 +310,11 @@ int
tag_func_do_init_action (SwfdecSwfDecoder * s)
{
SwfdecBits *bits = &s->b;
- int len;
SwfdecBuffer *buffer;
SwfdecCharacter *character;
- unsigned char *endptr;
- //int retcode = SWF_ERROR;
-
- endptr = bits->ptr + bits->buffer->length;
character = swfdec_swf_decoder_get_character (s, swfdec_bits_get_u16 (bits));
-
- len = bits->end - bits->ptr;
-
- buffer = swfdec_buffer_new_subbuffer (bits->buffer,
- bits->ptr - bits->buffer->data, len);
-
- bits->ptr += len;
+ buffer = swfdec_bits_get_buffer (bits, -1);
if (SWFDEC_IS_SPRITE (character)) {
SWFDEC_WARNING ("init actions not implemented yet");
@@ -339,7 +327,6 @@ tag_func_do_init_action (SwfdecSwfDecode
}
swfdec_buffer_unref (buffer);
- //return retcode;
return SWFDEC_STATUS_OK;
}
@@ -389,11 +376,8 @@ tag_func_define_button_2 (SwfdecSwfDecod
int flags;
int offset;
SwfdecButton *button;
- unsigned char *endptr;
char *script_name;
- endptr = bits->ptr + bits->buffer->length;
-
id = swfdec_bits_get_u16 (bits);
button = swfdec_swf_decoder_create_character (s, id, SWFDEC_TYPE_BUTTON);
if (!button)
@@ -476,11 +460,8 @@ tag_func_define_button (SwfdecSwfDecoder
SwfdecBits *bits = &s->b;
int id;
SwfdecButton *button;
- unsigned char *endptr;
char *script_name;
- endptr = bits->ptr + bits->buffer->length;
-
id = swfdec_bits_get_u16 (bits);
button = swfdec_swf_decoder_create_character (s, id, SWFDEC_TYPE_BUTTON);
if (!button)
diff-tree c3f0eaf5706a0d972132a0ea4fcaff5aa79ec122 (from 3e6fcd37cb3157514beaf45cb90e2c68d2138b86)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 17 22:51:45 2007 +0100
add the SwfdecSCript to the stack frame
also, some more functions are implemented (like WaitForFrame, it needs this)
diff --git a/libswfdec/js/jsinterp.c b/libswfdec/js/jsinterp.c
index 1a45a77..1d15966 100644
--- a/libswfdec/js/jsinterp.c
+++ b/libswfdec/js/jsinterp.c
@@ -832,6 +832,7 @@ have_fun:
frame.varobj = NULL;
frame.callobj = frame.argsobj = NULL;
frame.script = script;
+ frame.swf = swf;
frame.fun = fun;
frame.argc = argc;
frame.argv = sp - argc;
diff --git a/libswfdec/js/jsinterp.h b/libswfdec/js/jsinterp.h
index d68957d..b22166d 100644
--- a/libswfdec/js/jsinterp.h
+++ b/libswfdec/js/jsinterp.h
@@ -54,7 +54,8 @@ struct JSStackFrame {
JSObject *callobj; /* lazily created Call object */
JSObject *argsobj; /* lazily created arguments object */
JSObject *varobj; /* variables object, where vars go */
- JSScript *script; /* script being interpreted */
+ JSScript *script; /* script being interpreted or NULL */
+ void *swf; /* SwfdecScript being executed if script is NULL */
JSFunction *fun; /* function being called or null */
JSObject *thisp; /* "this" pointer if in method */
uintN argc; /* actual argument count */
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
index 3d39a72..5b01510 100644
--- a/libswfdec/swfdec_script.c
+++ b/libswfdec/swfdec_script.c
@@ -29,7 +29,9 @@
/*** SUPPORT FUNCTIONS ***/
+#include "swfdec_decoder.h"
#include "swfdec_movie.h"
+#include "swfdec_root_movie.h"
static SwfdecMovie *
swfdec_action_get_target (JSContext *cx)
@@ -45,9 +47,91 @@ swfdec_action_stop (JSContext *cx, guint
SwfdecMovie *movie = swfdec_action_get_target (cx);
if (movie)
movie->stopped = TRUE;
+ else
+ SWFDEC_ERROR ("no movie to stop");
return JS_TRUE;
}
+static JSBool
+swfdec_action_play (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ SwfdecMovie *movie = swfdec_action_get_target (cx);
+ if (movie)
+ movie->stopped = FALSE;
+ else
+ SWFDEC_ERROR ("no movie to play");
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_goto_frame (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ SwfdecMovie *movie = swfdec_action_get_target (cx);
+ guint frame;
+
+ if (len != 2) {
+ SWFDEC_ERROR ("GotoFrame action length invalid (is %u, should be 2", len);
+ return JS_FALSE;
+ }
+ frame = GUINT16_FROM_LE (*((guint16 *) data));
+ if (movie) {
+ swfdec_movie_goto (movie, frame);
+ movie->stopped = TRUE;
+ } else {
+ SWFDEC_ERROR ("no movie to goto on");
+ }
+ return JS_TRUE;
+}
+
+static JSBool
+swfdec_action_wait_for_frame (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ SwfdecMovie *movie = swfdec_action_get_target (cx);
+ guint frame, jump, loaded;
+
+ if (len != 3) {
+ SWFDEC_ERROR ("WaitForFrame action length invalid (is %u, should be 3", len);
+ return JS_TRUE;
+ }
+ if (movie == NULL) {
+ SWFDEC_ERROR ("no movie for WaitForFrame");
+ return JS_TRUE;
+ }
+
+ frame = GUINT16_FROM_LE (*((guint16 *) data));
+ jump = data[2];
+ if (SWFDEC_IS_ROOT_MOVIE (movie)) {
+ SwfdecDecoder *dec = SWFDEC_ROOT_MOVIE (movie->root)->decoder;
+ loaded = dec->frames_loaded;
+ g_assert (loaded <= movie->n_frames);
+ } else {
+ loaded = movie->n_frames;
+ }
+ if (loaded < frame) {
+ SwfdecScript *script = cx->fp->swf;
+ guint8 *pc = cx->fp->pc;
+ guint8 *endpc = script->buffer->data + script->buffer->length;
+
+ /* jump instructions */
+ g_assert (script);
+ do {
+ if (pc >= endpc)
+ break;
+ if (*pc & 0x80) {
+ if (pc + 2 >= endpc)
+ break;
+ pc += 3 + GUINT16_FROM_LE (*((guint16 *) (pc + 1)));
+ } else {
+ pc++;
+ }
+ } while (jump-- > 0);
+ cx->fp->pc = pc;
+ }
+ return JS_TRUE;
+}
+
+/*** PRINT FUNCTIONS ***/
+
static char *
swfdec_action_print_goto_frame (guint action, const guint8 *data, guint len)
{
@@ -93,7 +177,7 @@ static const SwfdecActionSpec actions[25
/* version 3 */
[0x04] = { "NextFrame", NULL },
[0x05] = { "PreviousFrame", NULL },
- [0x06] = { "Play", NULL },
+ [0x06] = { "Play", NULL, 0, 0, { swfdec_action_play, swfdec_action_play, swfdec_action_play, swfdec_action_play, swfdec_action_play } },
[0x07] = { "Stop", NULL, 0, 0, { swfdec_action_stop, swfdec_action_stop, swfdec_action_stop, swfdec_action_stop, swfdec_action_stop } },
[0x08] = { "ToggleQuality", NULL },
[0x09] = { "StopSounds", NULL },
@@ -182,13 +266,13 @@ static const SwfdecActionSpec actions[25
[0x69] = { "Extends", NULL },
/* version 3 */
- [0x81] = { "GotoFrame", swfdec_action_print_goto_frame },
+ [0x81] = { "GotoFrame", swfdec_action_print_goto_frame, 0, 0, { swfdec_action_goto_frame, swfdec_action_goto_frame, swfdec_action_goto_frame, swfdec_action_goto_frame, swfdec_action_goto_frame } },
[0x83] = { "GetURL", NULL },
/* version 5 */
[0x87] = { "StoreRegister", NULL },
[0x88] = { "ConstantPool", NULL },
/* version 3 */
- [0x8a] = { "WaitForFrame", swfdec_action_print_wait_for_frame },
+ [0x8a] = { "WaitForFrame", swfdec_action_print_wait_for_frame, 0, 0, { swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame, swfdec_action_wait_for_frame } },
[0x8b] = { "SetTarget", NULL },
[0x8c] = { "GotoLabel", NULL },
/* version 4 */
@@ -262,12 +346,14 @@ static gboolean
validate_action (guint action, const guint8 *data, guint len, gpointer script)
{
/* we might want to do stuff here for certain actions */
+#if 0
{
char *foo = swfdec_script_print_action (action, data, len);
if (foo == NULL)
return FALSE;
g_print ("%s\n", foo);
}
+#endif
return TRUE;
}
@@ -362,6 +448,7 @@ swfdec_script_interpret (SwfdecScript *s
/* set up the script */
startpc = pc = script->buffer->data;
endpc = startpc + script->buffer->length;
+ fp->pc = pc;
/* set up stack */
startsp = js_AllocStack (cx, STACKSIZE, &mark);
if (!startsp) {
@@ -426,7 +513,11 @@ swfdec_script_interpret (SwfdecScript *s
ok = spec->exec[version] (cx, action, data, len);
if (!ok)
goto out;
- pc = nextpc;
+ if (fp->pc == pc) {
+ fp->pc = pc = nextpc;
+ } else {
+ pc = fp->pc;
+ }
}
out:
@@ -482,6 +573,7 @@ swfdec_script_execute (SwfdecScript *scr
frame.script = NULL;
frame.varobj = obj;
frame.fun = NULL;
+ frame.swf = script;
frame.thisp = obj;
frame.argc = frame.nvars = 0;
frame.argv = frame.vars = NULL;
diff-tree 3e6fcd37cb3157514beaf45cb90e2c68d2138b86 (from bbafcb875054f54987db4b37da1bd6f40ada79f4)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 17 22:51:10 2007 +0100
remove leftover code from when the root movie contained the root script
diff --git a/libswfdec/swfdec_js_movie.c b/libswfdec/swfdec_js_movie.c
index 30eb161..f5bf871 100644
--- a/libswfdec/swfdec_js_movie.c
+++ b/libswfdec/swfdec_js_movie.c
@@ -693,8 +693,7 @@ mc_framesloaded (JSContext *cx, JSObject
g_assert (movie);
/* only root movies can be partially loaded */
- if (SWFDEC_IS_ROOT_MOVIE (movie) ||
- SWFDEC_IS_ROOT_MOVIE (movie->parent)) {
+ if (SWFDEC_IS_ROOT_MOVIE (movie)) {
SwfdecDecoder *dec = SWFDEC_ROOT_MOVIE (movie->root)->decoder;
loaded = dec->frames_loaded;
g_assert (loaded <= movie->n_frames);
diff-tree bbafcb875054f54987db4b37da1bd6f40ada79f4 (from 7005f0c65edf0177ea22cbb4514c7df1cbb099c1)
Author: Benjamin Otte <otte at gnome.org>
Date: Wed Jan 17 16:06:25 2007 +0100
Add skeleton for interpreter
I hope I know what I'm doing here
diff --git a/libswfdec/Makefile.am b/libswfdec/Makefile.am
index 485f97f..7233f02 100644
--- a/libswfdec/Makefile.am
+++ b/libswfdec/Makefile.am
@@ -15,6 +15,7 @@ lib_LTLIBRARIES = libswfdec- at SWFDEC_MAJO
js_cflags = -I$(srcdir)/js/ -I./js -DXP_UNIX -DDEBUG
+# swfdec_debugger.c
libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES = \
swfdec_audio.c \
swfdec_audio_event.c \
@@ -32,9 +33,7 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES
$(CODECS) \
swfdec_codec_screen.c \
swfdec_color.c \
- swfdec_compiler.c \
swfdec_debug.c \
- swfdec_debugger.c \
swfdec_decoder.c \
swfdec_edittext.c \
swfdec_edittext_movie.c \
@@ -64,6 +63,7 @@ libswfdec_ at SWFDEC_MAJORMINOR@_la_SOURCES
swfdec_rect.c \
swfdec_ringbuffer.c \
swfdec_root_movie.c \
+ swfdec_script.c \
swfdec_scriptable.c \
swfdec_shape.c \
swfdec_sound.c \
@@ -109,7 +109,6 @@ noinst_HEADERS = \
swfdec_character.h \
swfdec_codec.h \
swfdec_color.h \
- swfdec_compiler.h \
swfdec_debug.h \
swfdec_debugger.h \
swfdec_decoder.h \
@@ -134,6 +133,7 @@ noinst_HEADERS = \
swfdec_rect.h \
swfdec_ringbuffer.h \
swfdec_root_movie.h \
+ swfdec_script.h \
swfdec_scriptable.h \
swfdec_shape.h \
swfdec_sound.h \
diff --git a/libswfdec/js/jsfun.h b/libswfdec/js/jsfun.h
index 5dad235..ad4249d 100644
--- a/libswfdec/js/jsfun.h
+++ b/libswfdec/js/jsfun.h
@@ -52,6 +52,7 @@ struct JSFunction {
JSObject *object; /* back-pointer to GC'ed object header */
JSNative native; /* native method pointer or null */
JSScript *script; /* interpreted bytecode descriptor or null */
+ void *swf; /* Actionscript or null */
uint16 nargs; /* minimum number of actual arguments */
uint16 extra; /* number of arg slots for local GC roots */
uint16 nvars; /* number of local variables */
diff --git a/libswfdec/js/jsgc.c b/libswfdec/js/jsgc.c
index b25d2b5..88d64ca 100644
--- a/libswfdec/js/jsgc.c
+++ b/libswfdec/js/jsgc.c
@@ -1214,20 +1214,23 @@ restart:
GC_MARK(cx, fp->argsobj, "arguments object", NULL);
if (fp->varobj)
GC_MARK(cx, fp->varobj, "variables object", NULL);
- if (fp->script) {
+ if (fp->script)
js_MarkScript(cx, fp->script, NULL);
- if (fp->spbase) {
- /*
- * Don't mark what has not been pushed yet, or what
- * has been popped already.
- */
- depth = fp->script->depth;
- nslots = (JS_UPTRDIFF(fp->sp, fp->spbase)
- < depth * sizeof(jsval))
- ? (uintN)(fp->sp - fp->spbase)
- : depth;
- GC_MARK_JSVALS(cx, nslots, fp->spbase, "operand");
- }
+ if (fp->spbase) {
+ /*
+ * Don't mark what has not been pushed yet, or what
+ * has been popped already.
+ */
+ if (fp->script) {
+ depth = fp->script->depth;
+ nslots = (JS_UPTRDIFF(fp->sp, fp->spbase)
+ < depth * sizeof(jsval))
+ ? (uintN)(fp->sp - fp->spbase)
+ : depth;
+ } else {
+ nslots = JS_UPTRDIFF(fp->sp, fp->spbase);
+ }
+ GC_MARK_JSVALS(cx, nslots, fp->spbase, "operand");
}
GC_MARK(cx, fp->thisp, "this", NULL);
if (fp->argv) {
diff --git a/libswfdec/js/jsinterp.c b/libswfdec/js/jsinterp.c
index ff45d22..1a45a77 100644
--- a/libswfdec/js/jsinterp.c
+++ b/libswfdec/js/jsinterp.c
@@ -626,6 +626,9 @@ ComputeThis(JSContext *cx, JSObject *thi
return JS_TRUE;
}
+extern JSBool
+swfdec_script_interpret(void *script, JSContext *cx, jsval *rval);
+
/*
* Find a function reference and its 'this' object implicit first parameter
* under argc arguments on cx's stack, and call the function. Push missing
@@ -646,6 +649,7 @@ js_Invoke(JSContext *cx, uintN argc, uin
JSNative native;
JSFunction *fun;
JSScript *script;
+ void *swf;
uintN minargs, nvars;
intN nslots, nalloc, surplus;
JSInterpreterHook hook;
@@ -815,6 +819,7 @@ have_fun:
fun = (JSFunction *) JS_GetPrivate(cx, funobj);
native = fun->native;
script = fun->script;
+ swf = fun->swf;
minargs = fun->nargs + fun->extra;
nvars = fun->nvars;
@@ -956,6 +961,9 @@ have_fun:
#endif
}
ok = js_Interpret(cx, &v);
+ } else if (swf) {
+ frame.scopeChain = funobj; /* FIXME */
+ ok = swfdec_script_interpret(swf, cx, &v);
} else {
/* fun might be onerror trying to report a syntax error in itself. */
frame.scopeChain = NULL;
diff --git a/libswfdec/swfdec_button_movie.c b/libswfdec/swfdec_button_movie.c
index 92d40b9..998413d 100644
--- a/libswfdec/swfdec_button_movie.c
+++ b/libswfdec/swfdec_button_movie.c
@@ -76,7 +76,8 @@ swfdec_button_movie_execute (SwfdecButto
| SWFDEC_BUTTON_OVER_DOWN_TO_IDLE)) == 0);
}
if (movie->button->events)
- swfdec_event_list_execute (movie->button->events, SWFDEC_MOVIE (movie)->parent, condition, 0);
+ swfdec_event_list_execute (movie->button->events,
+ SWFDEC_SCRIPTABLE (SWFDEC_MOVIE (movie)->parent), condition, 0);
}
#define CONTENT_IN_FRAME(content, frame) \
diff --git a/libswfdec/swfdec_compiler.c b/libswfdec/swfdec_compiler.c
index abeec0b..45983b6 100644
--- a/libswfdec/swfdec_compiler.c
+++ b/libswfdec/swfdec_compiler.c
@@ -1246,23 +1246,6 @@ typedef struct {
static const SwfdecActionSpec * swfdec_action_find (guint action);
-void
-swfdec_disassemble (SwfdecPlayer *player, JSScript *script)
-{
- guint i;
-
- for (i = 0; i < script->length; i ++) {
- g_print ("%02X ", script->code[i]);
- if (i % 16 == 15)
- g_print ("\n");
- else if (i % 4 == 3)
- g_print (" ");
- }
- if (i % 16 != 15)
- g_print ("\n");
- js_Disassemble (player->jscx, script, JS_TRUE, stdout);
-}
-
/**
* swfdec_compile:
* @player: a #SwfdecPlayer
diff --git a/libswfdec/swfdec_compiler.h b/libswfdec/swfdec_compiler.h
index e91b7cd..d3b8c9c 100644
--- a/libswfdec/swfdec_compiler.h
+++ b/libswfdec/swfdec_compiler.h
@@ -6,10 +6,9 @@
#include <libswfdec/swfdec_bits.h>
#include <libswfdec/swfdec_player.h>
+#error "swfdec_compiler.h is out of the game now!"
G_BEGIN_DECLS
-void swfdec_disassemble (SwfdecPlayer * player,
- JSScript * script);
JSScript * swfdec_compile (SwfdecPlayer * player,
SwfdecBits * bits,
int version,
diff --git a/libswfdec/swfdec_event.c b/libswfdec/swfdec_event.c
index ca08fb7..7ed820b 100644
--- a/libswfdec/swfdec_event.c
+++ b/libswfdec/swfdec_event.c
@@ -22,17 +22,17 @@
#endif
#include <js/jsapi.h>
#include "swfdec_event.h"
-#include "swfdec_compiler.h"
#include "swfdec_debug.h"
#include "swfdec_js.h"
#include "swfdec_player_internal.h"
+#include "swfdec_script.h"
typedef struct _SwfdecEvent SwfdecEvent;
struct _SwfdecEvent {
unsigned int conditions;
guint8 key;
- JSScript * script;
+ SwfdecScript *script;
};
struct _SwfdecEventList {
@@ -81,7 +81,7 @@ swfdec_event_list_free (SwfdecEventList
for (i = 0; i < list->events->len; i++) {
SwfdecEvent *event = &g_array_index (list->events, SwfdecEvent, i);
- swfdec_compiler_destroy_script (list->player, event->script);
+ swfdec_script_unref (event->script);
}
g_array_free (list->events, TRUE);
g_free (list);
@@ -146,14 +146,14 @@ swfdec_event_list_parse (SwfdecEventList
event.key = key;
name = g_strconcat (description, ".",
swfdec_event_list_condition_name (conditions), NULL);
- event.script = swfdec_compile (list->player, bits, version, name);
+ event.script = swfdec_script_new (bits, name, version);
g_free (name);
if (event.script)
g_array_append_val (list->events, event);
}
void
-swfdec_event_list_execute (SwfdecEventList *list, SwfdecMovie *movie,
+swfdec_event_list_execute (SwfdecEventList *list, SwfdecScriptable *scriptable,
unsigned int conditions, guint8 key)
{
unsigned int i;
@@ -164,8 +164,8 @@ swfdec_event_list_execute (SwfdecEventLi
SwfdecEvent *event = &g_array_index (list->events, SwfdecEvent, i);
if ((event->conditions & conditions) &&
event->key == key) {
- SWFDEC_LOG ("executing script for event %u on movie %s", conditions, movie->name);
- swfdec_js_execute_script (list->player, movie, event->script, NULL);
+ SWFDEC_LOG ("executing script for event %u on scriptable %p", conditions, scriptable);
+ swfdec_script_execute (event->script, scriptable);
}
}
}
diff --git a/libswfdec/swfdec_event.h b/libswfdec/swfdec_event.h
index 8251937..2906bb4 100644
--- a/libswfdec/swfdec_event.h
+++ b/libswfdec/swfdec_event.h
@@ -59,7 +59,7 @@ void swfdec_event_list_parse (SwfdecE
guint8 key,
const char * description);
void swfdec_event_list_execute (SwfdecEventList * list,
- SwfdecMovie * movie,
+ SwfdecScriptable * scriptable,
unsigned int condition,
guint8 key);
gboolean swfdec_event_list_has_conditions(SwfdecEventList * list,
diff --git a/libswfdec/swfdec_js.c b/libswfdec/swfdec_js.c
index 4ce01a5..cf14f65 100644
--- a/libswfdec/swfdec_js.c
+++ b/libswfdec/swfdec_js.c
@@ -30,7 +30,6 @@
#include "swfdec_player_internal.h"
#include "swfdec_debug.h"
#include "swfdec_js.h"
-#include "swfdec_compiler.h"
#include "swfdec_root_movie.h"
#include "swfdec_swf_decoder.h"
@@ -130,6 +129,23 @@ swfdec_js_finish_player (SwfdecPlayer *p
}
}
+static void
+swfdec_disassemble (SwfdecPlayer *player, JSScript *script)
+{
+ guint i;
+
+ for (i = 0; i < script->length; i ++) {
+ g_print ("%02X ", script->code[i]);
+ if (i % 16 == 15)
+ g_print ("\n");
+ else if (i % 4 == 3)
+ g_print (" ");
+ }
+ if (i % 16 != 15)
+ g_print ("\n");
+ js_Disassemble (player->jscx, script, JS_TRUE, stdout);
+}
+
/**
* swfdec_js_execute_script:
* @s: a @SwfdecPlayer
diff --git a/libswfdec/swfdec_movie.c b/libswfdec/swfdec_movie.c
index 16ff859..a851cd2 100644
--- a/libswfdec/swfdec_movie.c
+++ b/libswfdec/swfdec_movie.c
@@ -339,7 +339,7 @@ swfdec_movie_execute_script (SwfdecMovie
guint condition = GPOINTER_TO_UINT (data);
g_assert (movie->content->events);
- swfdec_event_list_execute (movie->content->events, movie, condition, 0);
+ swfdec_event_list_execute (movie->content->events, SWFDEC_SCRIPTABLE (movie), condition, 0);
}
/**
diff --git a/libswfdec/swfdec_script.c b/libswfdec/swfdec_script.c
new file mode 100644
index 0000000..3d39a72
--- /dev/null
+++ b/libswfdec/swfdec_script.c
@@ -0,0 +1,523 @@
+/* Swfdec
+ * Copyright (C) 2007 Benjamin Otte <otte at 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 "swfdec_script.h"
+#include "swfdec_debug.h"
+#include "swfdec_scriptable.h"
+#include "js/jscntxt.h"
+#include "js/jsinterp.h"
+
+/*** SUPPORT FUNCTIONS ***/
+
+#include "swfdec_movie.h"
+
+static SwfdecMovie *
+swfdec_action_get_target (JSContext *cx)
+{
+ return swfdec_scriptable_from_jsval (cx, OBJECT_TO_JSVAL (cx->fp->scopeChain), SWFDEC_TYPE_MOVIE);
+}
+
+/*** ALL THE ACTION IS HERE ***/
+
+static JSBool
+swfdec_action_stop (JSContext *cx, guint action, const guint8 *data, guint len)
+{
+ SwfdecMovie *movie = swfdec_action_get_target (cx);
+ if (movie)
+ movie->stopped = TRUE;
+ return JS_TRUE;
+}
+
+static char *
+swfdec_action_print_goto_frame (guint action, const guint8 *data, guint len)
+{
+ guint frame;
+
+ if (len != 2)
+ return NULL;
+
+ frame = GUINT16_FROM_LE (*((guint16 *) data));
+ return g_strdup_printf ("GotoFrame %u", frame);
+}
+
+static char *
+swfdec_action_print_wait_for_frame (guint action, const guint8 *data, guint len)
+{
+ guint frame, jump;
+
+ if (len != 3)
+ return NULL;
+
+ frame = GUINT16_FROM_LE (*((guint16 *) data));
+ jump = data[2];
+ return g_strdup_printf ("WaitForFrame %u %u", frame, jump);
+}
+
+/*** BIG FUNCTION TABLE ***/
+
+/* defines minimum and maximum versions for which we have seperate scripts */
+#define MINSCRIPTVERSION 3
+#define MAXSCRIPTVERSION 7
+
+typedef JSBool (* SwfdecActionExec) (JSContext *cx, guint action, const guint8 *data, guint len);
+typedef struct {
+ const char * name; /* name identifying the action */
+ char * (* print) (guint action, const guint8 *data, guint len);
+ int remove; /* values removed from stack or -1 for dynamic */
+ guint add; /* values added to the stack */
+ SwfdecActionExec exec[MAXSCRIPTVERSION - MINSCRIPTVERSION + 1];
+ /* array is for version 3, 4, 5, 6, 7+ */
+} SwfdecActionSpec;
+
+static const SwfdecActionSpec actions[256] = {
+ /* version 3 */
+ [0x04] = { "NextFrame", NULL },
+ [0x05] = { "PreviousFrame", NULL },
+ [0x06] = { "Play", NULL },
+ [0x07] = { "Stop", NULL, 0, 0, { swfdec_action_stop, swfdec_action_stop, swfdec_action_stop, swfdec_action_stop, swfdec_action_stop } },
+ [0x08] = { "ToggleQuality", NULL },
+ [0x09] = { "StopSounds", NULL },
+ /* version 4 */
+ [0x0a] = { "Add", NULL },
+ [0x0b] = { "Subtract", NULL },
+ [0x0c] = { "Multiply", NULL },
+ [0x0d] = { "Divide", NULL },
+ [0x0e] = { "Equals", NULL },
+ [0x0f] = { "Less", NULL },
+ [0x10] = { "And", NULL },
+ [0x11] = { "Or", NULL },
+ [0x12] = { "Not", NULL },
+ [0x13] = { "StringEquals", NULL },
+ [0x14] = { "StringLength", NULL },
+ [0x15] = { "StringExtract", NULL },
+ [0x17] = { "Pop", NULL },
+ [0x18] = { "ToInteger", NULL },
+ [0x1c] = { "GetVariable", NULL },
+ [0x1d] = { "SetVariable", NULL },
+ [0x20] = { "SetTarget2", NULL },
+ [0x21] = { "StringAdd", NULL },
+ [0x22] = { "GetProperty", NULL },
+ [0x23] = { "SetProperty", NULL },
+ [0x24] = { "CloneSprite", NULL },
+ [0x25] = { "RemoveSprite", NULL },
+ [0x26] = { "Trace", NULL },
+ [0x27] = { "StartDrag", NULL },
+ [0x28] = { "EndDrag", NULL },
+ [0x29] = { "StringLess", NULL },
+ /* version 7 */
+ [0x2a] = { "Throw", NULL },
+ [0x2b] = { "Cast", NULL },
+ [0x2c] = { "Implements", NULL },
+ /* version 4 */
+ [0x30] = { "RandomNumber", NULL },
+ [0x31] = { "MBStringLength", NULL },
+ [0x32] = { "CharToAscii", NULL },
+ [0x33] = { "AsciiToChar", NULL },
+ [0x34] = { "GetTime", NULL },
+ [0x35] = { "MBStringExtract", NULL },
+ [0x36] = { "MBCharToAscii", NULL },
+ [0x37] = { "MVAsciiToChar", NULL },
+ /* version 5 */
+ [0x3a] = { "Delete", NULL },
+ [0x3b] = { "Delete2", NULL },
+ [0x3c] = { "DefineLocal", NULL },
+ [0x3d] = { "CallFunction", NULL },
+ [0x3e] = { "Return", NULL },
+ [0x3f] = { "Modulo", NULL },
+ [0x40] = { "NewObject", NULL },
+ [0x41] = { "DefineLocal2", NULL },
+ [0x42] = { "InitArray", NULL },
+ [0x43] = { "InitObject", NULL },
+ [0x44] = { "Typeof", NULL },
+ [0x45] = { "TargetPath", NULL },
+ [0x46] = { "Enumerate", NULL },
+ [0x47] = { "Add2", NULL },
+ [0x48] = { "Less2", NULL },
+ [0x49] = { "Equals2", NULL },
+ [0x4a] = { "ToNumber", NULL },
+ [0x4b] = { "ToString", NULL },
+ [0x4c] = { "PushDuplicate", NULL },
+ [0x4d] = { "Swap", NULL },
+ [0x4e] = { "GetMember", NULL },
+ [0x4f] = { "SetMember", NULL }, /* apparently the result is ignored */
+ [0x50] = { "Increment", NULL },
+ [0x51] = { "Decrement", NULL },
+ [0x52] = { "CallMethod", NULL },
+ [0x53] = { "NewMethod", NULL },
+ /* version 6 */
+ [0x54] = { "InstanceOf", NULL },
+ [0x55] = { "Enumerate2", NULL },
+ /* version 5 */
+ [0x60] = { "BitAnd", NULL },
+ [0x61] = { "BitOr", NULL },
+ [0x62] = { "BitXor", NULL },
+ [0x63] = { "BitLShift", NULL },
+ [0x64] = { "BitRShift", NULL },
+ [0x65] = { "BitURShift", NULL },
+ /* version 6 */
+ [0x66] = { "StrictEquals", NULL },
+ [0x67] = { "Greater", NULL },
+ [0x68] = { "StringGreater", NULL },
+ /* version 7 */
+ [0x69] = { "Extends", NULL },
+
+ /* version 3 */
+ [0x81] = { "GotoFrame", swfdec_action_print_goto_frame },
+ [0x83] = { "GetURL", NULL },
+ /* version 5 */
+ [0x87] = { "StoreRegister", NULL },
+ [0x88] = { "ConstantPool", NULL },
+ /* version 3 */
+ [0x8a] = { "WaitForFrame", swfdec_action_print_wait_for_frame },
+ [0x8b] = { "SetTarget", NULL },
+ [0x8c] = { "GotoLabel", NULL },
+ /* version 4 */
+ [0x8d] = { "WaitForFrame2", NULL },
+ /* version 7 */
+ [0x8e] = { "DefineFunction2", NULL },
+ [0x8f] = { "Try", NULL },
+ /* version 5 */
+ [0x94] = { "With", NULL },
+ /* version 4 */
+ [0x96] = { "Push", NULL },
+ [0x99] = { "Jump", NULL },
+ [0x9a] = { "GetURL2", NULL },
+ /* version 5 */
+ [0x9b] = { "DefineFunction", NULL },
+ /* version 4 */
+ [0x9d] = { "If", NULL },
+ [0x9e] = { "Call", NULL },
+ [0x9f] = { "GotoFrame2", NULL }
+};
+
+char *
+swfdec_script_print_action (guint action, const guint8 *data, guint len)
+{
+ const SwfdecActionSpec *spec = actions + action;
+
+ if (action & 0x80) {
+ if (spec->print == NULL) {
+ SWFDEC_ERROR ("action %u %s has no print statement",
+ action, spec->name ? spec->name : "Unknown");
+ return NULL;
+ }
+ return spec->print (action, data, len);
+ } else {
+ if (spec->name == NULL) {
+ SWFDEC_ERROR ("action %u is unknown", action);
+ return NULL;
+ }
+ return g_strdup (spec->name);
+ }
+}
+
+typedef gboolean (* SwfdecScriptForeachFunc) (guint action, const guint8 *data, guint len, gpointer user_data);
+static gboolean
+swfdec_script_foreach (SwfdecBits *bits, SwfdecScriptForeachFunc func, gpointer user_data)
+{
+ guint action, len;
+ guint8 *data;
+
+ while ((action = swfdec_bits_get_u8 (bits))) {
+ if (action & 0x80) {
+ len = swfdec_bits_get_u16 (bits);
+ data = bits->ptr;
+ } else {
+ len = 0;
+ data = NULL;
+ }
+ if (swfdec_bits_skip_bytes (bits, len) != len) {
+ SWFDEC_ERROR ("script too short");
+ return FALSE;
+ }
+ if (!func (action, data, len, user_data))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/*** PUBLIC API ***/
+
+static gboolean
+validate_action (guint action, const guint8 *data, guint len, gpointer script)
+{
+ /* we might want to do stuff here for certain actions */
+ {
+ char *foo = swfdec_script_print_action (action, data, len);
+ if (foo == NULL)
+ return FALSE;
+ g_print ("%s\n", foo);
+ }
+ return TRUE;
+}
+
+SwfdecScript *
+swfdec_script_new (SwfdecBits *bits, const char *name, unsigned int version)
+{
+ SwfdecScript *script;
+ guchar *start;
+
+ g_return_val_if_fail (bits != NULL, NULL);
+ if (version < MINSCRIPTVERSION) {
+ SWFDEC_ERROR ("swfdec version %u doesn't support scripts", version);
+ return NULL;
+ }
+
+ swfdec_bits_syncbits (bits);
+ start = bits->ptr;
+ script = g_new0 (SwfdecScript, 1);
+ script->refcount = 1;
+ script->name = g_strdup (name ? name : "Unnamed script");
+ script->version = version;
+
+ if (!swfdec_script_foreach (bits, validate_action, script)) {
+ /* assign a random buffer here so we have something to unref */
+ script->buffer = bits->buffer;
+ swfdec_buffer_ref (script->buffer);
+ swfdec_script_unref (script);
+ return NULL;
+ }
+ script->buffer = swfdec_buffer_new_subbuffer (bits->buffer, start - bits->buffer->data,
+ bits->ptr - start);
+ return script;
+}
+
+void
+swfdec_script_ref (SwfdecScript *script)
+{
+ g_return_if_fail (script != NULL);
+
+ script->refcount++;
+}
+
+void
+swfdec_script_unref (SwfdecScript *script)
+{
+ g_return_if_fail (script != NULL);
+ g_return_if_fail (script->refcount > 0);
+
+ script->refcount--;
+ if (script->refcount > 0)
+ return;
+
+ swfdec_buffer_unref (script->buffer);
+ g_free (script->name);
+ g_free (script);
+}
+
+#ifndef MAX_INTERP_LEVEL
+#if defined(XP_OS2)
+#define MAX_INTERP_LEVEL 250
+#elif defined _MSC_VER && _MSC_VER <= 800
+#define MAX_INTERP_LEVEL 30
+#else
+#define MAX_INTERP_LEVEL 1000
+#endif
+#endif
+
+/* random guess */
+#define STACKSIZE 100
+
+/* FIXME: the implementation of this function needs the usual debugging hooks
+ * found in mozilla */
+JSBool
+swfdec_script_interpret (SwfdecScript *script, JSContext *cx, jsval *rval)
+{
+ JSStackFrame *fp;
+ guint8 *startpc, *pc, *endpc, *nextpc;
+ JSBool ok = JS_TRUE;
+ void *mark;
+ jsval *startsp, *endsp;
+ int stack_check;
+ guint action, len;
+ guint8 *data;
+ guint version;
+ const SwfdecActionSpec *spec;
+
+ /* set up general stuff */
+ swfdec_script_ref (script);
+ version = MAX (script->version - MINSCRIPTVERSION, MAXSCRIPTVERSION - MINSCRIPTVERSION);
+ *rval = JSVAL_VOID;
+ fp = cx->fp;
+ /* set up the script */
+ startpc = pc = script->buffer->data;
+ endpc = startpc + script->buffer->length;
+ /* set up stack */
+ startsp = js_AllocStack (cx, STACKSIZE, &mark);
+ if (!startsp) {
+ ok = JS_FALSE;
+ goto out;
+ }
+ fp->spbase = startsp;
+ fp->sp = startsp;
+ endsp = startsp + STACKSIZE;
+ /* Check for too much nesting, or too deep a C stack. */
+ if (++cx->interpLevel == MAX_INTERP_LEVEL ||
+ !JS_CHECK_STACK_SIZE(cx, stack_check)) {
+ JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_OVER_RECURSED);
+ ok = JS_FALSE;
+ goto out;
+ }
+
+ /* only valid return value */
+ while (TRUE) {
+ /* check pc */
+ if (pc < startpc || pc >= endpc) {
+ SWFDEC_ERROR ("pc %p not in valid range [%p, %p] anymore", pc, startpc, endpc);
+ goto internal_error;
+ }
+ /* decode next action */
+ action = *pc;
+ spec = actions + action;
+ if (action == 0)
+ break;
+ if (action & 0x80) {
+ if (pc + 2 >= endpc) {
+ SWFDEC_ERROR ("action %u length value out of range", action);
+ goto internal_error;
+ }
+ data = pc + 3;
+ len = pc[1] | pc[2] << 8;
+ if (data + len > endpc) {
+ SWFDEC_ERROR ("action %u length %u out of range", action, len);
+ goto internal_error;
+ }
+ nextpc = pc + 3 + len;
+ } else {
+ data = NULL;
+ len = 0;
+ nextpc = pc + 1;
+ }
+ /* check action is valid */
+ if (spec->exec[version] == NULL) {
+ SWFDEC_ERROR ("cannot interpret action %u %s for version %u", action,
+ spec->name ? spec->name : "Unknown", script->version);
+ goto internal_error;
+ }
+ if (fp->sp - spec->remove < startsp) {
+ SWFDEC_ERROR ("stack underflow while trying to execute %s - requires %u args, only got %u",
+ spec->name, spec->remove, fp->sp - fp->spbase);
+ goto internal_error;
+ }
+ if (fp->sp + spec->add - MAX (spec->remove, 0) > endsp) {
+ SWFDEC_ERROR ("FIXME: implement stack expansion, we got an overflow");
+ goto internal_error;
+ }
+ ok = spec->exec[version] (cx, action, data, len);
+ if (!ok)
+ goto out;
+ pc = nextpc;
+ }
+
+out:
+#if 0
+ /* FIXME: exception handling */
+ if (!ok && cx->throwing) {
+ /*
+ * Look for a try block within this frame that can catch the exception.
+ */
+ SCRIPT_FIND_CATCH_START(script, pc, pc);
+ if (pc) {
+ len = 0;
+ cx->throwing = JS_FALSE; /* caught */
+ ok = JS_TRUE;
+ goto advance_pc;
+ }
+ }
+#endif
+no_catch:
+
+ /* Reset sp before freeing stack slots, because our caller may GC soon. */
+ fp->sp = fp->spbase;
+ fp->spbase = NULL;
+ js_FreeStack(cx, mark);
+ cx->interpLevel--;
+ swfdec_script_unref (script);
+ return ok;
+
+internal_error:
+ *rval = JSVAL_VOID;
+ ok = JS_TRUE;
+ goto no_catch;
+}
+
+jsval
+swfdec_script_execute (SwfdecScript *script, SwfdecScriptable *scriptable)
+{
+ JSContext *cx;
+ JSStackFrame *oldfp, frame;
+ JSObject *obj;
+ JSBool ok;
+
+ g_return_val_if_fail (script != NULL, JSVAL_VOID);
+ g_return_val_if_fail (SWFDEC_IS_SCRIPTABLE (scriptable), JSVAL_VOID);
+
+ cx = scriptable->jscx;
+ obj = swfdec_scriptable_get_object (scriptable);
+ if (obj == NULL)
+ return JSVAL_VOID;
+ oldfp = cx->fp;
+
+ frame.callobj = frame.argsobj = NULL;
+ frame.script = NULL;
+ frame.varobj = obj;
+ frame.fun = NULL;
+ frame.thisp = obj;
+ frame.argc = frame.nvars = 0;
+ frame.argv = frame.vars = NULL;
+ frame.annotation = NULL;
+ frame.sharpArray = NULL;
+ frame.rval = JSVAL_VOID;
+ frame.down = NULL;
+ frame.scopeChain = obj;
+ frame.pc = NULL;
+ frame.sp = oldfp ? oldfp->sp : NULL;
+ frame.spbase = NULL;
+ frame.sharpDepth = 0;
+ frame.flags = 0;
+ frame.dormantNext = NULL;
+ frame.objAtomMap = NULL;
+
+ if (oldfp) {
+ g_assert (!oldfp->dormantNext);
+ oldfp->dormantNext = cx->dormantFrameChain;
+ cx->dormantFrameChain = oldfp;
+ }
+
+ cx->fp = &frame;
+
+ /*
+ * Use frame.rval, not result, so the last result stays rooted across any
+ * GC activations nested within this js_Interpret.
+ */
+ ok = swfdec_script_interpret (script, cx, &frame.rval);
+
+ cx->fp = oldfp;
+ if (oldfp) {
+ g_assert (cx->dormantFrameChain == oldfp);
+ cx->dormantFrameChain = oldfp->dormantNext;
+ oldfp->dormantNext = NULL;
+ }
+
+ return ok ? frame.rval : JSVAL_VOID;
+}
diff --git a/libswfdec/swfdec_script.h b/libswfdec/swfdec_script.h
new file mode 100644
index 0000000..d8688c3
--- /dev/null
+++ b/libswfdec/swfdec_script.h
@@ -0,0 +1,57 @@
+/* Swfdec
+ * Copyright (C) 2007 Benjamin Otte <otte at 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
+ */
+
+#ifndef _SWFDEC_SCRIPT_H_
+#define _SWFDEC_SCRIPT_H_
+
+#include <libswfdec/swfdec.h>
+#include <libswfdec/swfdec_types.h>
+#include <libswfdec/swfdec_bits.h>
+#include <libswfdec/js/jsapi.h>
+
+G_BEGIN_DECLS
+
+//typedef struct _SwfdecScript SwfdecScript;
+
+/* FIXME: May want to typedef to SwfdecBuffer directly */
+struct _SwfdecScript {
+ SwfdecBuffer * buffer; /* buffer holding the script */
+ unsigned int refcount; /* reference count */
+ char * name; /* name identifying this script */
+ unsigned int version; /* version of the script */
+};
+
+SwfdecScript * swfdec_script_new (SwfdecBits * bits,
+ const char * name,
+ unsigned int version);
+void swfdec_script_ref (SwfdecScript * script);
+void swfdec_script_unref (SwfdecScript * script);
+
+JSBool swfdec_script_interpret (SwfdecScript * script,
+ JSContext * cx,
+ jsval * rval);
+jsval swfdec_script_execute (SwfdecScript * script,
+ SwfdecScriptable * scriptable);
+
+char * swfdec_script_print_action (guint action,
+ const guint8 * data,
+ guint len);
+G_END_DECLS
+
+#endif
diff --git a/libswfdec/swfdec_sprite.c b/libswfdec/swfdec_sprite.c
index ffb8eb7..7f1668e 100644
--- a/libswfdec/swfdec_sprite.c
+++ b/libswfdec/swfdec_sprite.c
@@ -25,10 +25,10 @@
#include <string.h>
#include "swfdec_sprite.h"
-#include "swfdec_compiler.h"
#include "swfdec_debug.h"
#include "swfdec_movie.h"
#include "swfdec_player_internal.h"
+#include "swfdec_script.h"
#include "swfdec_sound.h"
#include "swfdec_sprite_movie.h"
#include "swfdec_swf_decoder.h"
@@ -65,7 +65,7 @@ swfdec_sprite_dispose (GObject *object)
&g_array_index (sprite->frames[i].actions, SwfdecSpriteAction, j);
switch (action->type) {
case SWFDEC_SPRITE_ACTION_SCRIPT:
- swfdec_compiler_destroy_script (sprite->player, action->data);
+ swfdec_script_unref (action->data);
break;
case SWFDEC_SPRITE_ACTION_ADD:
case SWFDEC_SPRITE_ACTION_UPDATE:
diff --git a/libswfdec/swfdec_sprite_movie.c b/libswfdec/swfdec_sprite_movie.c
index f303f33..8485d82 100644
--- a/libswfdec/swfdec_sprite_movie.c
+++ b/libswfdec/swfdec_sprite_movie.c
@@ -29,6 +29,7 @@
#include "swfdec_player_internal.h"
#include "swfdec_ringbuffer.h"
#include "swfdec_root_movie.h"
+#include "swfdec_script.h"
#include "swfdec_sprite.h"
static SwfdecMovie *
@@ -63,8 +64,7 @@ swfdec_sprite_movie_remove_child (Swfdec
static void
swfdec_sprite_movie_run_script (SwfdecMovie *movie, gpointer data)
{
- SwfdecPlayer *player = SWFDEC_ROOT_MOVIE (movie->root)->player;
- swfdec_js_execute_script (player, movie, data, NULL);
+ swfdec_script_execute (data, SWFDEC_SCRIPTABLE (movie));
}
static void
diff --git a/libswfdec/swfdec_tag.c b/libswfdec/swfdec_tag.c
index 7b6f00e..4f57b1a 100644
--- a/libswfdec/swfdec_tag.c
+++ b/libswfdec/swfdec_tag.c
@@ -31,7 +31,6 @@
#include "swfdec_tag.h"
#include "swfdec_bits.h"
#include "swfdec_button.h"
-#include "swfdec_compiler.h"
#include "swfdec_debug.h"
#include "swfdec_edittext.h"
#include "swfdec_font.h"
@@ -39,6 +38,7 @@
#include "swfdec_morphshape.h"
#include "swfdec_movie.h" /* for SwfdecContent */
#include "swfdec_pattern.h"
+#include "swfdec_script.h"
#include "swfdec_shape.h"
#include "swfdec_sound.h"
#include "swfdec_sprite.h"
@@ -293,12 +293,12 @@ tag_func_define_sprite (SwfdecSwfDecoder
int
tag_func_do_action (SwfdecSwfDecoder * s)
{
- JSScript *script;
+ SwfdecScript *script;
char *name;
name = g_strdup_printf ("Sprite%u.Frame%u", SWFDEC_CHARACTER (s->parse_sprite)->id,
s->parse_sprite->parse_frame);
- script = swfdec_compile (SWFDEC_DECODER (s)->player, &s->b, s->version, name);
+ script = swfdec_script_new (&s->b, name, s->version);
g_free (name);
if (script)
swfdec_sprite_add_action (s->parse_sprite, s->parse_sprite->parse_frame,
diff --git a/libswfdec/swfdec_types.h b/libswfdec/swfdec_types.h
index 49212d5..3228a36 100644
--- a/libswfdec/swfdec_types.h
+++ b/libswfdec/swfdec_types.h
@@ -44,6 +44,7 @@ typedef struct _SwfdecShape SwfdecShape;
typedef struct _SwfdecShapeVec SwfdecShapeVec;
typedef struct _SwfdecRect SwfdecRect;
typedef struct _SwfdecRootMovie SwfdecRootMovie;
+typedef struct _SwfdecScript SwfdecScript;
typedef struct _SwfdecScriptable SwfdecScriptable;
typedef struct _SwfdecSound SwfdecSound;
typedef struct _SwfdecSoundChunk SwfdecSoundChunk;
More information about the Swfdec
mailing list