Benjamin Otte
2007-Jan-29 13:33 UTC
[Swfdec] Branch 'interpreter' - 18 commits - libswfdec/swfdec_image.c libswfdec/swfdec_image.h libswfdec/swfdec_js.c libswfdec/swfdec_js_color.c libswfdec/swfdec_js_sound.c libswfdec/swfdec_pattern.c libswfdec/swfdec_scriptable.c libswfdec/swfdec_script.c
libswfdec/swfdec_image.c | 113 ++++++++---- libswfdec/swfdec_image.h | 5 libswfdec/swfdec_js.c | 5 libswfdec/swfdec_js_color.c | 8 libswfdec/swfdec_js_sound.c | 7 libswfdec/swfdec_pattern.c | 3 libswfdec/swfdec_script.c | 376 +++++++++++++++++++++++++++++++++++++++--- libswfdec/swfdec_scriptable.c | 2 8 files changed, 441 insertions(+), 78 deletions(-) New commits: diff-tree d8b4748701572b483c96bbb4a66a6f026cd1c1d7 (from 1986ae14a62fc9d28ac38f53621fadaf9b42877f) Author: Benjamin Otte <otte@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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@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 2cb8680a8577ff5d018b50e7da55c233e8eaa4af (from 7005f0c65edf0177ea22cbb4514c7df1cbb099c1) Author: Benjamin Otte <otte@gnome.org> Date: Fri Jan 26 22:54:14 2007 +0100 implement caching in the target's surface type This is a naive way that only caches in the last used format, but it should be good enough for most uses diff --git a/libswfdec/swfdec_image.c b/libswfdec/swfdec_image.c index 6c2dcae..0cf6502 100644 --- a/libswfdec/swfdec_image.c +++ b/libswfdec/swfdec_image.c @@ -185,15 +185,15 @@ tag_func_define_bits_jpeg (SwfdecSwfDeco } static void -swfdec_image_create_surface (SwfdecImage *image, guint8 *data) +swfdec_image_create_surface (SwfdecImage *image, guint8 *data, gboolean has_alpha) { static const cairo_user_data_key_t key; g_assert (image->surface == NULL); image->surface = cairo_image_surface_create_for_data (data, - CAIRO_FORMAT_ARGB32, image->width, image->height, - image->rowstride); + has_alpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, + image->width, image->height, image->rowstride); cairo_surface_set_user_data (image->surface, &key, data, g_free); } @@ -220,7 +220,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); + swfdec_image_create_surface (image, image_data, FALSE); SWFDEC_LOG (" width = %d", image->width); SWFDEC_LOG (" height = %d", image->height); @@ -268,7 +268,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); + swfdec_image_create_surface (image, image_data, FALSE); SWFDEC_LOG (" width = %d", image->width); SWFDEC_LOG (" height = %d", image->height); @@ -339,7 +339,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); + swfdec_image_create_surface (image, image_data, TRUE); SWFDEC_LOG (" width = %d", image->width); SWFDEC_LOG (" height = %d", image->height); @@ -464,6 +464,7 @@ swfdec_image_lossless_load (SwfdecImage if (have_alpha) { SWFDEC_INFO("16bit images aren't allowed to have alpha, ignoring"); + have_alpha = FALSE; } image_data = g_malloc (4 * image->width * image->height); @@ -513,7 +514,7 @@ swfdec_image_lossless_load (SwfdecImage } } - swfdec_image_create_surface (image, image_data); + swfdec_image_create_surface (image, image_data, have_alpha); } int @@ -626,3 +627,33 @@ swfdec_image_get_surface (SwfdecImage *i return image->surface; } +cairo_surface_t * +swfdec_image_get_surface_for_target (SwfdecImage *image, cairo_surface_t *target) +{ + cairo_surface_t *current, *similar; + cairo_t *copy; + cairo_content_t content; + + current = swfdec_image_get_surface (image); + if (cairo_surface_get_type (current) == cairo_surface_get_type (target)) + return current; + + /* 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; + similar = cairo_surface_create_similar (target, + content, + image->width, image->height); + copy = cairo_create (similar); + cairo_set_source_surface (copy, current, 0, 0); + cairo_paint (copy); + cairo_destroy (copy); + cairo_surface_destroy (current); + image->surface = similar; + return similar; +} diff --git a/libswfdec/swfdec_image.h b/libswfdec/swfdec_image.h index af230f2..bcd22f0 100644 --- a/libswfdec/swfdec_image.h +++ b/libswfdec/swfdec_image.h @@ -65,7 +65,10 @@ struct _SwfdecImageClass { GType swfdec_image_get_type (void); -cairo_surface_t * swfdec_image_get_surface (SwfdecImage * image); +cairo_surface_t * swfdec_image_get_surface (SwfdecImage * image); +cairo_surface_t * swfdec_image_get_surface_for_target + (SwfdecImage * image, + cairo_surface_t * target); int swfdec_image_jpegtables (SwfdecSwfDecoder * s); int tag_func_define_bits_jpeg (SwfdecSwfDecoder * s); diff --git a/libswfdec/swfdec_pattern.c b/libswfdec/swfdec_pattern.c index 312118f..f8902ef 100644 --- a/libswfdec/swfdec_pattern.c +++ b/libswfdec/swfdec_pattern.c @@ -267,7 +267,8 @@ swfdec_image_pattern_paint (SwfdecPatter cairo_matrix_t mat; cairo_surface_t *surface; - surface = swfdec_image_get_surface (image->image); + surface = swfdec_image_get_surface_for_target (image->image, + cairo_get_target (cr)); cairo_append_path (cr, (cairo_path_t *) path); color = swfdec_color_apply_transform (0xFFFFFFFF, trans); pattern = cairo_pattern_create_for_surface (surface);
Reasonably Related Threads
- 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
- Branch 'interpreter' - 8 commits - libswfdec/swfdec_bits.c libswfdec/swfdec_color.c libswfdec/swfdec_color.h libswfdec/swfdec_edittext.c libswfdec/swfdec_image.c libswfdec/swfdec_image.h libswfdec/swfdec_pattern.c libswfdec/swfdec_sprite.c test/dump.c
- Branch 'interpreter' - 4 commits - libswfdec/js libswfdec/swfdec_bits.c libswfdec/swfdec_bits.h libswfdec/swfdec_codec_screen.c libswfdec/swfdec_image.c libswfdec/swfdec_script.c libswfdec/swfdec_swf_decoder.c libswfdec/swfdec_tag.c
- 3 commits - libswfdec/swfdec_image.c libswfdec/swfdec_image.h
- 21 commits - configure.ac libswfdec/swfdec_audio_event.c libswfdec/swfdec_bits.c libswfdec/swfdec_button_movie.c libswfdec/swfdec_color.c libswfdec/swfdec_color.h libswfdec/swfdec_compiler.c libswfdec/swfdec_edittext.c libswfdec/swfdec_image.c