[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

Benjamin Otte company at kemper.freedesktop.org
Mon Jan 29 13:33:00 PST 2007


 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 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 2cb8680a8577ff5d018b50e7da55c233e8eaa4af (from 7005f0c65edf0177ea22cbb4514c7df1cbb099c1)
Author: Benjamin Otte <otte at 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);


More information about the Swfdec mailing list