[Swfdec] 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 test/swfdec-extract.c test/swfdec_out.c test/swfedit_token.c

Benjamin Otte company at kemper.freedesktop.org
Tue Feb 6 03:18:37 PST 2007


 libswfdec/swfdec_bits.c     |    4 
 libswfdec/swfdec_color.c    |   41 +++---
 libswfdec/swfdec_color.h    |   29 +++-
 libswfdec/swfdec_edittext.c |    2 
 libswfdec/swfdec_image.c    |  269 +++++++++++++++++++++++---------------------
 libswfdec/swfdec_image.h    |    9 -
 libswfdec/swfdec_pattern.c  |   29 +---
 libswfdec/swfdec_sprite.c   |    7 -
 test/dump.c                 |   34 +++++
 test/swfdec-extract.c       |   14 ++
 test/swfdec_out.c           |   14 +-
 test/swfedit_token.c        |   12 -
 12 files changed, 276 insertions(+), 188 deletions(-)

New commits:
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 d7db95f092791ed1e81ad2d2e4f9e3fb345d6f79 (from ad56f27f4cc82a6913a7adcf05704b2cb91e6c61)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Feb 4 16:14:23 2007 +0100

    export images, too

diff --git a/test/swfdec-extract.c b/test/swfdec-extract.c
index bea068e..b4a2951 100644
--- a/test/swfdec-extract.c
+++ b/test/swfdec-extract.c
@@ -35,6 +35,7 @@
 #include <libswfdec/swfdec_audio_stream.h>
 #include <libswfdec/swfdec_button.h>
 #include <libswfdec/swfdec_graphic.h>
+#include <libswfdec/swfdec_image.h>
 #include <libswfdec/swfdec_player_internal.h>
 #include <libswfdec/swfdec_root_movie.h>
 #include <libswfdec/swfdec_sound.h>
@@ -206,6 +207,16 @@ export_graphic (SwfdecGraphic *graphic, 
   return surface_destroy_for_type (surface, filename);
 }
 
+static gboolean
+export_image (SwfdecImage *image, const char *filename)
+{
+  cairo_surface_t *surface = swfdec_image_create_surface (image);
+
+  if (surface == NULL)
+    return FALSE;
+  return surface_destroy_for_type (surface, filename);
+}
+
 static void
 usage (const char *app)
 {
@@ -258,6 +269,9 @@ main (int argc, char *argv[])
   } 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);
     ret = 1;
diff-tree ad56f27f4cc82a6913a7adcf05704b2cb91e6c61 (from 32e4b86c8fac7b199a4f2d210f0ec6d67347091c)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Feb 4 16:14:13 2007 +0100

    add debugging message when parsing color transforms

diff --git a/libswfdec/swfdec_sprite.c b/libswfdec/swfdec_sprite.c
index 074bb37..246776a 100644
--- a/libswfdec/swfdec_sprite.c
+++ b/libswfdec/swfdec_sprite.c
@@ -364,6 +364,11 @@ swfdec_spriteseg_place_object_2 (SwfdecS
   }
   if (has_color_transform) {
     swfdec_bits_get_color_transform (bits, &content->color_transform);
+    SWFDEC_LOG ("  color transform = %d %d  %d %d  %d %d  %d %d",
+	content->color_transform.ra, content->color_transform.rb,
+	content->color_transform.ga, content->color_transform.gb,
+	content->color_transform.ba, content->color_transform.bb,
+	content->color_transform.aa, content->color_transform.ab);
   }
   swfdec_bits_syncbits (bits);
   if (has_ratio) {
diff-tree 32e4b86c8fac7b199a4f2d210f0ec6d67347091c (from 2399ad61b0ffc8fcbd1c395dc841deec152e29e4)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Feb 4 14:53:42 2007 +0100

    rename swfdec_image_get_surface* to swfdec_image_create_surface*
    
    - The renamed functions give out a reference to the surface now.
    - Ensure that surfaces created by those functions get unreffed properly
    - Add an obvious optimization by not applying the color transform if the
      transform is the identity transform

diff --git a/libswfdec/swfdec_image.c b/libswfdec/swfdec_image.c
index e276508..224e101 100644
--- a/libswfdec/swfdec_image.c
+++ b/libswfdec/swfdec_image.c
@@ -647,7 +647,7 @@ swfdec_image_create_surface (SwfdecImage
 }
 
 cairo_surface_t *
-swfdec_image_get_surface_transformed (SwfdecImage *image, const SwfdecColorTransform *trans)
+swfdec_image_create_surface_transformed (SwfdecImage *image, const SwfdecColorTransform *trans)
 {
   static const cairo_user_data_key_t key;
   cairo_surface_t *surface;
@@ -659,6 +659,10 @@ swfdec_image_get_surface_transformed (Sw
   g_return_val_if_fail (SWFDEC_IS_IMAGE (image), NULL);
   g_return_val_if_fail (trans != NULL, NULL);
 
+  /* obvious optimization */
+  if (swfdec_color_transform_is_identity (trans))
+    return swfdec_image_create_surface (image);
+
   if (!swfdec_image_ensure_loaded (image))
     return NULL;
 
diff --git a/libswfdec/swfdec_image.h b/libswfdec/swfdec_image.h
index ad40181..3c1e71e 100644
--- a/libswfdec/swfdec_image.h
+++ b/libswfdec/swfdec_image.h
@@ -66,8 +66,8 @@ struct _SwfdecImageClass {
 
 GType			swfdec_image_get_type		(void);
 
-cairo_surface_t *	swfdec_image_get_surface	(SwfdecImage *		image);
-cairo_surface_t *	swfdec_image_get_surface_transformed 
+cairo_surface_t *	swfdec_image_create_surface	(SwfdecImage *		image);
+cairo_surface_t *	swfdec_image_create_surface_transformed 
 							(SwfdecImage *		image,
 							 const SwfdecColorTransform *trans);
 
diff --git a/libswfdec/swfdec_pattern.c b/libswfdec/swfdec_pattern.c
index 938f827..536698a 100644
--- a/libswfdec/swfdec_pattern.c
+++ b/libswfdec/swfdec_pattern.c
@@ -266,9 +266,10 @@ swfdec_image_pattern_paint (SwfdecPatter
   cairo_matrix_t mat;
   cairo_surface_t *surface;
   
-  surface = swfdec_image_get_surface_transformed (image->image, trans);
+  surface = swfdec_image_create_surface_transformed (image->image, trans);
   cairo_append_path (cr, (cairo_path_t *) path);
   pattern = cairo_pattern_create_for_surface (surface);
+  cairo_surface_destroy (surface);
   swfdec_matrix_morph (&mat, &pat->start_transform, &pat->end_transform, ratio);
   cairo_pattern_set_matrix (pattern, &mat);
   cairo_pattern_set_extend (pattern, image->extend);
@@ -626,7 +627,7 @@ swfdec_pattern_to_string (SwfdecPattern 
   if (SWFDEC_IS_IMAGE_PATTERN (pattern)) {
     SwfdecImagePattern *image = SWFDEC_IMAGE_PATTERN (pattern);
     if (image->image->width == 0)
-      swfdec_image_get_surface (image->image);
+      cairo_surface_destroy (swfdec_image_create_surface (image->image));
     return g_strdup_printf ("%ux%u image %u (%s, %s)", image->image->width,
 	image->image->height, SWFDEC_CHARACTER (image->image)->id,
 	image->extend == CAIRO_EXTEND_REPEAT ? "repeat" : "no repeat",
diff-tree 2399ad61b0ffc8fcbd1c395dc841deec152e29e4 (from 180879c4af107625b53f37ba8bcc990eb20baf8b)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Feb 4 14:49:54 2007 +0100

    add swfdec_color_transform_is_identity
    
    useful for optimizations

diff --git a/libswfdec/swfdec_color.c b/libswfdec/swfdec_color.c
index 7761653..73276a0 100644
--- a/libswfdec/swfdec_color.c
+++ b/libswfdec/swfdec_color.c
@@ -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
@@ -125,6 +125,13 @@ swfdec_color_transform_init_color (Swfde
   trans->ab = SWFDEC_COLOR_A (color);
 }
 
+gboolean
+swfdec_color_transform_is_identity (const SwfdecColorTransform * trans)
+{
+  return trans->ra == 256 && trans->ga == 256 && trans->ba == 256 && trans->aa == 256 &&
+      trans->rb == 0 && trans->gb == 0 && trans->bb == 0 && trans->ab == 0;
+}
+
 /**
  * swfdec_color_transform_chain:
  * @dest: #SwfdecColorTransform to take the result
diff --git a/libswfdec/swfdec_color.h b/libswfdec/swfdec_color.h
index b38c269..46fdea4 100644
--- a/libswfdec/swfdec_color.h
+++ b/libswfdec/swfdec_color.h
@@ -72,6 +72,7 @@ SwfdecColor swfdec_color_apply_morph (Sw
 void swfdec_color_set_source (cairo_t *cr, SwfdecColor color);
 void swfdec_color_transform_init_identity (SwfdecColorTransform * trans);
 void swfdec_color_transform_init_color (SwfdecColorTransform *trans, SwfdecColor 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,
diff-tree 180879c4af107625b53f37ba8bcc990eb20baf8b (from fa335acfbd3526f57dfb66c68e59334a79d90901)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Feb 4 14:33:59 2007 +0100

    rework images to be correctly color transformed
    
    - use new SWFDEC_COLOR_INDEX variables when decoding - avoids #if
    - ditch caching as we might need the unpremultiplied image for color transforms
    - implement swfdec_image_get_surface_transformed
    - use it in the image pattern

diff --git a/libswfdec/swfdec_image.c b/libswfdec/swfdec_image.c
index 0cf6502..e276508 100644
--- a/libswfdec/swfdec_image.c
+++ b/libswfdec/swfdec_image.c
@@ -50,7 +50,10 @@ swfdec_image_unload (SwfdecCached *cache
   if (image->surface) {
     cairo_surface_destroy (image->surface);
     image->surface = NULL;
+  } else if (image->data) {
+    g_free (image->data);
   }
+  image->data = NULL;
 }
 
 static void
@@ -185,24 +188,9 @@ tag_func_define_bits_jpeg (SwfdecSwfDeco
 }
 
 static void
-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,
-      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);
-}
-
-static void
 swfdec_image_jpeg_load (SwfdecImage *image)
 {
   JpegRGBDecoder *dec;
-  unsigned char *image_data;
 
   dec = jpeg_rgb_decoder_new ();
 
@@ -217,10 +205,9 @@ swfdec_image_jpeg_load (SwfdecImage *ima
     return;
   }
   swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height);
-  jpeg_rgb_decoder_get_image (dec, &image_data,
+  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_LOG ("  width = %d", image->width);
   SWFDEC_LOG ("  height = %d", image->height);
@@ -252,7 +239,6 @@ static void
 swfdec_image_jpeg2_load (SwfdecImage *image)
 {
   JpegRGBDecoder *dec;
-  unsigned char *image_data;
 
   dec = jpeg_rgb_decoder_new ();
 
@@ -265,10 +251,9 @@ swfdec_image_jpeg2_load (SwfdecImage *im
     return;
   }
   swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height);
-  jpeg_rgb_decoder_get_image (dec, &image_data,
+  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_LOG ("  width = %d", image->width);
   SWFDEC_LOG ("  height = %d", image->height);
@@ -303,7 +288,6 @@ static void
 swfdec_image_jpeg3_load (SwfdecImage *image)
 {
   JpegRGBDecoder *dec;
-  unsigned char *image_data;
   unsigned char *alpha_data;
   SwfdecBits bits;
   int len;
@@ -328,7 +312,7 @@ swfdec_image_jpeg3_load (SwfdecImage *im
     return;
   }
   swfdec_cached_load (SWFDEC_CACHED (image), 4 * image->width * image->height);
-  jpeg_rgb_decoder_get_image (dec, &image_data,
+  jpeg_rgb_decoder_get_image (dec, &image->data,
       &image->rowstride, &image->width, &image->height);
   jpeg_rgb_decoder_free (dec);
 
@@ -336,11 +320,9 @@ swfdec_image_jpeg3_load (SwfdecImage *im
 
   alpha_data = lossless (bits.ptr, bits.end - bits.ptr, &len);
 
-  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, TRUE);
-
   SWFDEC_LOG ("  width = %d", image->width);
   SWFDEC_LOG ("  height = %d", image->height);
 }
@@ -355,11 +337,7 @@ merge_alpha (SwfdecImage * image, unsign
   for (y = 0; y < image->height; y++) {
     p = image_data + y * image->rowstride;
     for (x = 0; x < image->width; x++) {
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-      p[3] = *alpha;
-#else
-      p[0] = *alpha;
-#endif
+      p[SWFDEC_COLOR_INDEX_ALPHA] = *alpha;
       p += 4;
       alpha++;
     }
@@ -375,7 +353,6 @@ swfdec_image_lossless_load (SwfdecImage 
   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;
@@ -414,7 +391,7 @@ swfdec_image_lossless_load (SwfdecImage 
     unsigned char *indexed_data;
     int i;
 
-    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);
@@ -450,7 +427,7 @@ swfdec_image_lossless_load (SwfdecImage 
       }
       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);
 
     g_free (color_table);
@@ -467,25 +444,18 @@ swfdec_image_lossless_load (SwfdecImage 
       have_alpha = FALSE;
     }
 
-    image_data = g_malloc (4 * image->width * image->height);
-    idata = image_data;
+    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 = p[1] | (p[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
+        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;
         idata += 4;
       }
@@ -495,26 +465,17 @@ swfdec_image_lossless_load (SwfdecImage 
   if (format == 5) {
     int i, j;
 
-    image_data = ptr;
+    image->data = ptr;
     image->rowstride = image->width * 4;
 
-    if (!have_alpha) {
-      /* 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;
-        }
+    /* 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;
       }
     }
   }
-
-  swfdec_image_create_surface (image, image_data, have_alpha);
 }
 
 int
@@ -592,68 +553,131 @@ swfdec_image_colormap_decode (SwfdecImag
   }
 }
 
+static gboolean
+swfdec_image_ensure_loaded (SwfdecImage *image)
+{
+  if (image->data == NULL) {
+    switch (image->type) {
+      case SWFDEC_IMAGE_TYPE_JPEG:
+	swfdec_image_jpeg_load (image);
+	break;
+      case SWFDEC_IMAGE_TYPE_JPEG2:
+	swfdec_image_jpeg2_load (image);
+	break;
+      case SWFDEC_IMAGE_TYPE_JPEG3:
+	swfdec_image_jpeg3_load (image);
+	break;
+      case SWFDEC_IMAGE_TYPE_LOSSLESS:
+	swfdec_image_lossless_load (image);
+	break;
+      case SWFDEC_IMAGE_TYPE_LOSSLESS2:
+	swfdec_image_lossless_load (image);
+	break;
+      case SWFDEC_IMAGE_TYPE_UNKNOWN:
+      default:
+	g_assert_not_reached ();
+	break;
+    }
+    if (image->data == NULL) {
+      SWFDEC_WARNING ("failed to load image data");
+      return FALSE;
+    }
+  } else {
+    swfdec_cached_use (SWFDEC_CACHED (image));
+  }
+  return TRUE;
+}
+
+static void
+swfdec_image_premultiply (guint8 *data, guint n)
+{
+  guint i;
+
+  for (i = 0; i < n; i++, data += 4) {
+    if (data[SWFDEC_COLOR_INDEX_ALPHA] == 0xFF)
+      continue;
+    if (data[SWFDEC_COLOR_INDEX_ALPHA] == 0) {
+      data[SWFDEC_COLOR_INDEX_RED] = data[SWFDEC_COLOR_INDEX_GREEN] = data[SWFDEC_COLOR_INDEX_BLUE] = 0;
+    } else {
+      data[SWFDEC_COLOR_INDEX_RED] = (guint) data[SWFDEC_COLOR_INDEX_RED] * data[SWFDEC_COLOR_INDEX_ALPHA] / 255;
+      data[SWFDEC_COLOR_INDEX_GREEN] = (guint) data[SWFDEC_COLOR_INDEX_GREEN] * data[SWFDEC_COLOR_INDEX_ALPHA] / 255;
+      data[SWFDEC_COLOR_INDEX_BLUE] = (guint) data[SWFDEC_COLOR_INDEX_BLUE] * data[SWFDEC_COLOR_INDEX_ALPHA] / 255;
+    }
+  }
+}
+
+static gboolean
+swfdec_image_has_alpha (SwfdecImage *image)
+{
+  return image->type == SWFDEC_IMAGE_TYPE_LOSSLESS2 ||
+      image->type == SWFDEC_IMAGE_TYPE_JPEG3;
+}
+
 cairo_surface_t *
-swfdec_image_get_surface (SwfdecImage *image)
+swfdec_image_create_surface (SwfdecImage *image)
 {
+  static const cairo_user_data_key_t key;
+
   g_return_val_if_fail (SWFDEC_IS_IMAGE (image), NULL);
 
+  if (!swfdec_image_ensure_loaded (image))
+    return NULL;
   if (image->surface) {
-    swfdec_cached_use (SWFDEC_CACHED (image));
+    cairo_surface_reference (image->surface);
     return image->surface;
   }
 
-  switch (image->type) {
-    case SWFDEC_IMAGE_TYPE_JPEG:
-      swfdec_image_jpeg_load (image);
-      break;
-    case SWFDEC_IMAGE_TYPE_JPEG2:
-      swfdec_image_jpeg2_load (image);
-      break;
-    case SWFDEC_IMAGE_TYPE_JPEG3:
-      swfdec_image_jpeg3_load (image);
-      break;
-    case SWFDEC_IMAGE_TYPE_LOSSLESS:
-      swfdec_image_lossless_load (image);
-      break;
-    case SWFDEC_IMAGE_TYPE_LOSSLESS2:
-      swfdec_image_lossless_load (image);
-      break;
-    case SWFDEC_IMAGE_TYPE_UNKNOWN:
-    default:
-      g_assert_not_reached ();
-      break;
+  if (swfdec_image_has_alpha (image)) {
+    cairo_surface_t *surface;
+    guint8 *data;
+    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 
+	image->width, image->height);
+    /* FIXME: only works if rowstride == image->width * 4 */
+    data = cairo_image_surface_get_data (surface);
+    memcpy (data, image->data, image->width * image->height * 4);
+    swfdec_image_premultiply (data, image->width * image->height);
+    return surface;
+  } else {
+    image->surface = cairo_image_surface_create_for_data (image->data,
+	CAIRO_FORMAT_RGB24, image->width, image->height, image->rowstride);
+    cairo_surface_set_user_data (image->surface, &key, image->data, g_free);
+    cairo_surface_reference (image->surface);
+    return image->surface;
   }
-
-  return image->surface;
 }
 
 cairo_surface_t *
-swfdec_image_get_surface_for_target (SwfdecImage *image, cairo_surface_t *target)
+swfdec_image_get_surface_transformed (SwfdecImage *image, const SwfdecColorTransform *trans)
 {
-  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;
+  static const cairo_user_data_key_t key;
+  cairo_surface_t *surface;
+  guint8 *tdata;
+  const guint8 *sdata;
+  guint i, n;
+  gboolean has_alpha = FALSE;
+
+  g_return_val_if_fail (SWFDEC_IS_IMAGE (image), NULL);
+  g_return_val_if_fail (trans != NULL, NULL);
+
+  if (!swfdec_image_ensure_loaded (image))
+    return NULL;
+
+  tdata = g_try_malloc (image->width * image->height * 4);
+  if (!tdata) {
+    SWFDEC_ERROR ("failed to allocate memory for transformed image");
+    return NULL;
+  }
+  sdata = image->data;
+  n = image->width * image->height;
+  for (i = 0; i < n; i++) {
+    ((guint32 *) tdata)[i] = swfdec_color_apply_transform (((guint32 *) sdata)[i], trans);
+    has_alpha |= tdata[4 * i + SWFDEC_COLOR_INDEX_ALPHA] != 0xFF;
+  }
+  if (has_alpha)
+    swfdec_image_premultiply (tdata, n);
+  surface = cairo_image_surface_create_for_data (tdata,
+      has_alpha ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24, 
+      image->width, image->height, image->width * 4);
+  cairo_surface_set_user_data (surface, &key, tdata, g_free);
+  return surface;
 }
diff --git a/libswfdec/swfdec_image.h b/libswfdec/swfdec_image.h
index bcd22f0..ad40181 100644
--- a/libswfdec/swfdec_image.h
+++ b/libswfdec/swfdec_image.h
@@ -48,10 +48,11 @@ typedef enum {
 struct _SwfdecImage {
   SwfdecCached		cached;
 
-  cairo_surface_t *	surface;	/* surface that is on-demand loaded */
+  guint8 *		data;		/* image data in CAIRO_FORMAT_ARGB32 but NOT premultiplied */	
   int			width;
   int			height;
   int			rowstride;
+  cairo_surface_t *	surface;	/* surface that owns the data pointer or NULL (doesn't always work) */
 
   SwfdecImageType	type;
   SwfdecBuffer *	jpegtables;
@@ -66,9 +67,9 @@ struct _SwfdecImageClass {
 GType			swfdec_image_get_type		(void);
 
 cairo_surface_t *	swfdec_image_get_surface	(SwfdecImage *		image);
-cairo_surface_t *	swfdec_image_get_surface_for_target 
+cairo_surface_t *	swfdec_image_get_surface_transformed 
 							(SwfdecImage *		image,
-							 cairo_surface_t *	target);
+							 const SwfdecColorTransform *trans);
 
 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 2a614b0..938f827 100644
--- a/libswfdec/swfdec_pattern.c
+++ b/libswfdec/swfdec_pattern.c
@@ -263,14 +263,11 @@ swfdec_image_pattern_paint (SwfdecPatter
 {
   SwfdecImagePattern *image = SWFDEC_IMAGE_PATTERN (pat);
   cairo_pattern_t *pattern;
-  SwfdecColor color;
   cairo_matrix_t mat;
   cairo_surface_t *surface;
   
-  surface = swfdec_image_get_surface_for_target (image->image, 
-      cairo_get_target (cr));
+  surface = swfdec_image_get_surface_transformed (image->image, trans);
   cairo_append_path (cr, (cairo_path_t *) path);
-  color = swfdec_color_apply_transform (0xFFFFFFFF, trans);
   pattern = cairo_pattern_create_for_surface (surface);
   swfdec_matrix_morph (&mat, &pat->start_transform, &pat->end_transform, ratio);
   cairo_pattern_set_matrix (pattern, &mat);
@@ -278,14 +275,7 @@ swfdec_image_pattern_paint (SwfdecPatter
   cairo_pattern_set_filter (pattern, image->filter);
   cairo_set_source (cr, pattern);
   cairo_pattern_destroy (pattern);
-  if (SWFDEC_COLOR_A (color) < 255) {
-    cairo_save (cr);
-    cairo_clip (cr);
-    cairo_paint_with_alpha (cr, SWFDEC_COLOR_A (color) / 255.);
-    cairo_restore (cr);
-  } else {
-    cairo_fill (cr);
-  }
+  cairo_fill (cr);
 }
 
 static void
diff-tree fa335acfbd3526f57dfb66c68e59334a79d90901 (from 251f13c696e0c8c8eb10534d0ed9407d7fd26d19)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Feb 4 14:29:48 2007 +0100

    update SwfdecColor format from RGBA to ARGB
    
    This makes SwfdecColor match a pixel in an image in CAIRO_FORMAT_ARGB32

diff --git a/libswfdec/swfdec_color.h b/libswfdec/swfdec_color.h
index 07870c3..b38c269 100644
--- a/libswfdec/swfdec_color.h
+++ b/libswfdec/swfdec_color.h
@@ -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
@@ -24,6 +24,8 @@
 
 #include <libswfdec/swfdec_types.h>
 
+/* Pixel value in the same colorspace as cairo - endian-dependant ARGB.
+ * The alpha pixel must be present */
 typedef unsigned int SwfdecColor;
 
 struct _SwfdecColorTransform {
@@ -46,11 +48,25 @@ struct swfdec_gradient_struct
   SwfdecGradientEntry array[1];
 };
 
-#define SWFDEC_COLOR_COMBINE(r,g,b,a)	(((r)<<24) | ((g)<<16) | ((b)<<8) | (a))
-#define SWFDEC_COLOR_R(x)		(((x)>>24)&0xff)
-#define SWFDEC_COLOR_G(x)		(((x)>>16)&0xff)
-#define SWFDEC_COLOR_B(x)		(((x)>>8)&0xff)
-#define SWFDEC_COLOR_A(x)		((x)&0xff)
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+#define SWFDEC_COLOR_INDEX_ALPHA (3)
+#define SWFDEC_COLOR_INDEX_RED (2)
+#define SWFDEC_COLOR_INDEX_GREEN (1)
+#define SWFDEC_COLOR_INDEX_BLUE (0)
+#elif G_BYTE_ORDER == G_BIG_ENDIAN
+#define SWFDEC_COLOR_INDEX_ALPHA (0)
+#define SWFDEC_COLOR_INDEX_RED (1)
+#define SWFDEC_COLOR_INDEX_GREEN (2)
+#define SWFDEC_COLOR_INDEX_BLUE (3)
+#else
+#error "Unknown byte order"
+#endif
+
+#define SWFDEC_COLOR_COMBINE(r,g,b,a)	(((a)<<24) | ((r)<<16) | ((g)<<8) | (b))
+#define SWFDEC_COLOR_A(x)		(((x)>>24)&0xff)
+#define SWFDEC_COLOR_R(x)		(((x)>>16)&0xff)
+#define SWFDEC_COLOR_G(x)		(((x)>>8)&0xff)
+#define SWFDEC_COLOR_B(x)		((x)&0xff)
 
 SwfdecColor swfdec_color_apply_morph (SwfdecColor start, SwfdecColor end, unsigned int ratio);
 void swfdec_color_set_source (cairo_t *cr, SwfdecColor color);
diff-tree 251f13c696e0c8c8eb10534d0ed9407d7fd26d19 (from 12bf86eb10e873ca735fad310d7ab9e517f6662b)
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Feb 4 13:07:18 2007 +0100

    s/SWF_COLOR/SWFDEC_COLOR/
    
    fight wrong prefixes!

diff --git a/libswfdec/swfdec_bits.c b/libswfdec/swfdec_bits.c
index fb18394..5013e49 100644
--- a/libswfdec/swfdec_bits.c
+++ b/libswfdec/swfdec_bits.c
@@ -450,7 +450,7 @@ swfdec_bits_get_color (SwfdecBits * bits
   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
@@ -463,7 +463,7 @@ swfdec_bits_get_rgba (SwfdecBits * bits)
   b = swfdec_bits_get_u8 (bits);
   a = swfdec_bits_get_u8 (bits);
 
-  return SWF_COLOR_COMBINE (r, g, b, a);
+  return SWFDEC_COLOR_COMBINE (r, g, b, a);
 }
 
 SwfdecGradient *
diff --git a/libswfdec/swfdec_color.c b/libswfdec/swfdec_color.c
index 0d8a8be..7761653 100644
--- a/libswfdec/swfdec_color.c
+++ b/libswfdec/swfdec_color.c
@@ -40,20 +40,20 @@ swfdec_color_apply_morph (SwfdecColor st
     return end;
   start_ratio = 65535 - ratio;
   end_ratio = ratio;
-  r = (SWF_COLOR_R (start) * start_ratio + SWF_COLOR_R (end) * end_ratio) / 65535;
-  g = (SWF_COLOR_G (start) * start_ratio + SWF_COLOR_G (end) * end_ratio) / 65535;
-  b = (SWF_COLOR_B (start) * start_ratio + SWF_COLOR_B (end) * end_ratio) / 65535;
-  a = (SWF_COLOR_A (start) * start_ratio + SWF_COLOR_A (end) * end_ratio) / 65535;
+  r = (SWFDEC_COLOR_R (start) * start_ratio + SWFDEC_COLOR_R (end) * end_ratio) / 65535;
+  g = (SWFDEC_COLOR_G (start) * start_ratio + SWFDEC_COLOR_G (end) * end_ratio) / 65535;
+  b = (SWFDEC_COLOR_B (start) * start_ratio + SWFDEC_COLOR_B (end) * end_ratio) / 65535;
+  a = (SWFDEC_COLOR_A (start) * start_ratio + SWFDEC_COLOR_A (end) * end_ratio) / 65535;
 
-  return SWF_COLOR_COMBINE (r, g, b, a);
+  return SWFDEC_COLOR_COMBINE (r, g, b, a);
 }
 
 void 
 swfdec_color_set_source (cairo_t *cr, SwfdecColor color)
 {
   cairo_set_source_rgba (cr, 
-      SWF_COLOR_R (color) / 255.0, SWF_COLOR_G (color) / 255.0,
-      SWF_COLOR_B (color) / 255.0, SWF_COLOR_A (color) / 255.0);
+      SWFDEC_COLOR_R (color) / 255.0, SWFDEC_COLOR_G (color) / 255.0,
+      SWFDEC_COLOR_B (color) / 255.0, SWFDEC_COLOR_A (color) / 255.0);
 }
 
 unsigned int
@@ -61,10 +61,10 @@ swfdec_color_apply_transform (unsigned i
 {
   int r, g, b, a;
 
-  r = SWF_COLOR_R (in);
-  g = SWF_COLOR_G (in);
-  b = SWF_COLOR_B (in);
-  a = SWF_COLOR_A (in);
+  r = SWFDEC_COLOR_R (in);
+  g = SWFDEC_COLOR_G (in);
+  b = SWFDEC_COLOR_B (in);
+  a = SWFDEC_COLOR_A (in);
 
   SWFDEC_LOG ("in rgba %d,%d,%d,%d", r, g, b, a);
 
@@ -80,7 +80,7 @@ swfdec_color_apply_transform (unsigned i
 
   SWFDEC_LOG ("out rgba %d,%d,%d,%d", r, g, b, a);
 
-  return SWF_COLOR_COMBINE (r, g, b, a);
+  return SWFDEC_COLOR_COMBINE (r, g, b, a);
 }
 
 /**
@@ -116,13 +116,13 @@ void
 swfdec_color_transform_init_color (SwfdecColorTransform *trans, SwfdecColor color)
 {
   trans->ra = 0;
-  trans->rb = SWF_COLOR_R (color);
+  trans->rb = SWFDEC_COLOR_R (color);
   trans->ga = 0;
-  trans->gb = SWF_COLOR_G (color);
+  trans->gb = SWFDEC_COLOR_G (color);
   trans->ba = 0;
-  trans->bb = SWF_COLOR_B (color);
+  trans->bb = SWFDEC_COLOR_B (color);
   trans->aa = 0;
-  trans->ab = SWF_COLOR_A (color);
+  trans->ab = SWFDEC_COLOR_A (color);
 }
 
 /**
diff --git a/libswfdec/swfdec_color.h b/libswfdec/swfdec_color.h
index 39e48fe..07870c3 100644
--- a/libswfdec/swfdec_color.h
+++ b/libswfdec/swfdec_color.h
@@ -46,11 +46,11 @@ struct swfdec_gradient_struct
   SwfdecGradientEntry array[1];
 };
 
-#define SWF_COLOR_COMBINE(r,g,b,a)	(((r)<<24) | ((g)<<16) | ((b)<<8) | (a))
-#define SWF_COLOR_R(x)		(((x)>>24)&0xff)
-#define SWF_COLOR_G(x)		(((x)>>16)&0xff)
-#define SWF_COLOR_B(x)		(((x)>>8)&0xff)
-#define SWF_COLOR_A(x)		((x)&0xff)
+#define SWFDEC_COLOR_COMBINE(r,g,b,a)	(((r)<<24) | ((g)<<16) | ((b)<<8) | (a))
+#define SWFDEC_COLOR_R(x)		(((x)>>24)&0xff)
+#define SWFDEC_COLOR_G(x)		(((x)>>16)&0xff)
+#define SWFDEC_COLOR_B(x)		(((x)>>8)&0xff)
+#define SWFDEC_COLOR_A(x)		((x)&0xff)
 
 SwfdecColor swfdec_color_apply_morph (SwfdecColor start, SwfdecColor end, unsigned int ratio);
 void swfdec_color_set_source (cairo_t *cr, SwfdecColor color);
diff --git a/libswfdec/swfdec_edittext.c b/libswfdec/swfdec_edittext.c
index d38b33a..37727eb 100644
--- a/libswfdec/swfdec_edittext.c
+++ b/libswfdec/swfdec_edittext.c
@@ -148,7 +148,7 @@ tag_func_define_edit_text (SwfdecSwfDeco
     SWFDEC_LOG ("  color = %u", text->color);
   } else {
     SWFDEC_WARNING ("FIXME: figure out default color");
-    text->color = SWF_COLOR_COMBINE (255, 255, 255, 255);
+    text->color = SWFDEC_COLOR_COMBINE (255, 255, 255, 255);
   }
   if (has_max_length) {
     text->max_length = swfdec_bits_get_u16 (b);
diff --git a/libswfdec/swfdec_pattern.c b/libswfdec/swfdec_pattern.c
index f8902ef..2a614b0 100644
--- a/libswfdec/swfdec_pattern.c
+++ b/libswfdec/swfdec_pattern.c
@@ -278,10 +278,10 @@ swfdec_image_pattern_paint (SwfdecPatter
   cairo_pattern_set_filter (pattern, image->filter);
   cairo_set_source (cr, pattern);
   cairo_pattern_destroy (pattern);
-  if (SWF_COLOR_A (color) < 255) {
+  if (SWFDEC_COLOR_A (color) < 255) {
     cairo_save (cr);
     cairo_clip (cr);
-    cairo_paint_with_alpha (cr, SWF_COLOR_A (color) / 255.);
+    cairo_paint_with_alpha (cr, SWFDEC_COLOR_A (color) / 255.);
     cairo_restore (cr);
   } else {
     cairo_fill (cr);
@@ -368,8 +368,8 @@ swfdec_gradient_pattern_paint (SwfdecPat
 	      gradient->gradient->array[i + 1].ratio * ratio;
       offset /= 65535 * 255;
       cairo_pattern_add_color_stop_rgba (pattern, offset,
-	  SWF_COLOR_R(color) / 255.0, SWF_COLOR_G(color) / 255.0,
-	  SWF_COLOR_B(color) / 255.0, SWF_COLOR_A(color) / 255.0);
+	  SWFDEC_COLOR_R(color) / 255.0, SWFDEC_COLOR_G(color) / 255.0,
+	  SWFDEC_COLOR_B(color) / 255.0, SWFDEC_COLOR_A(color) / 255.0);
     }
   } else {
     for (i = 0; i < gradient->gradient->n_gradients; i++){
@@ -377,8 +377,8 @@ swfdec_gradient_pattern_paint (SwfdecPat
 	  trans);
       offset = gradient->gradient->array[i].ratio / 255.0;
       cairo_pattern_add_color_stop_rgba (pattern, offset,
-	  SWF_COLOR_R(color) / 255.0, SWF_COLOR_G(color) / 255.0,
-	  SWF_COLOR_B(color) / 255.0, SWF_COLOR_A(color) / 255.0);
+	  SWFDEC_COLOR_R(color) / 255.0, SWFDEC_COLOR_G(color) / 255.0,
+	  SWFDEC_COLOR_B(color) / 255.0, SWFDEC_COLOR_A(color) / 255.0);
     }
   }
   cairo_set_source (cr, pattern);
@@ -460,7 +460,7 @@ swfdec_pattern_parse (SwfdecSwfDecoder *
     if (paint_id == 65535) {
       /* FIXME: someone explain this magic paint id here */
       pattern = g_object_new (SWFDEC_TYPE_COLOR_PATTERN, NULL);
-      SWFDEC_COLOR_PATTERN (pattern)->start_color = SWF_COLOR_COMBINE (0, 255, 255, 255);
+      SWFDEC_COLOR_PATTERN (pattern)->start_color = SWFDEC_COLOR_COMBINE (0, 255, 255, 255);
       SWFDEC_COLOR_PATTERN (pattern)->end_color = SWFDEC_COLOR_PATTERN (pattern)->start_color;
       swfdec_bits_get_matrix (bits, &pattern->start_transform, NULL);
       pattern->end_transform = pattern->start_transform;
@@ -540,7 +540,7 @@ swfdec_pattern_parse_morph (SwfdecSwfDec
     if (paint_id == 65535) {
       /* FIXME: someone explain this magic paint id here */
       pattern = g_object_new (SWFDEC_TYPE_COLOR_PATTERN, NULL);
-      SWFDEC_COLOR_PATTERN (pattern)->start_color = SWF_COLOR_COMBINE (0, 255, 255, 255);
+      SWFDEC_COLOR_PATTERN (pattern)->start_color = SWFDEC_COLOR_COMBINE (0, 255, 255, 255);
       SWFDEC_COLOR_PATTERN (pattern)->end_color = SWFDEC_COLOR_PATTERN (pattern)->start_color;
       swfdec_bits_get_matrix (bits, &pattern->start_transform, NULL);
       swfdec_bits_get_matrix (bits, &pattern->end_transform, NULL);
diff --git a/libswfdec/swfdec_sprite.c b/libswfdec/swfdec_sprite.c
index 9201218..074bb37 100644
--- a/libswfdec/swfdec_sprite.c
+++ b/libswfdec/swfdec_sprite.c
@@ -503,7 +503,7 @@ swfdec_sprite_set_n_frames (SwfdecSprite
     sprite->frames[i].sound_samples = 44100 * 256 / rate;
   }
   /* default bg is white */
-  sprite->frames[0].bg_color = SWF_COLOR_COMBINE (0xFF, 0xFF, 0xFF, 0xFF);
+  sprite->frames[0].bg_color = SWFDEC_COLOR_COMBINE (0xFF, 0xFF, 0xFF, 0xFF);
 
   SWFDEC_LOG ("n_frames = %d", sprite->n_frames);
 }


More information about the Swfdec mailing list