add a test that ensures non-increasing gradient ratios work
[swfdec.git] / test / dump.c
blob77bd382de950086d350d03f42b616ce89dc0a15d
1 /* Swfdec
2 * Copyright (C) 2003-2006 David Schleef <ds@schleef.org>
3 * 2005-2006 Eric Anholt <eric@anholt.net>
4 * 2006-2007 Benjamin Otte <otte@gnome.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include <stdio.h>
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <stdlib.h>
29 #include <sys/stat.h>
30 #include <glib.h>
31 #include <glib-object.h>
32 #include <libswfdec/swfdec.h>
33 #include <libswfdec/swfdec_button.h>
34 #include <libswfdec/swfdec_text_field.h>
35 #include <libswfdec/swfdec_font.h>
36 #include <libswfdec/swfdec_image.h>
37 #include <libswfdec/swfdec_movie.h>
38 #include <libswfdec/swfdec_player_internal.h>
39 #include <libswfdec/swfdec_sprite.h>
40 #include <libswfdec/swfdec_shape.h>
41 #include <libswfdec/swfdec_sound.h>
42 #include <libswfdec/swfdec_swf_decoder.h>
43 #include <libswfdec/swfdec_resource.h>
44 #include <libswfdec/swfdec_tag.h>
45 #include <libswfdec/swfdec_text.h>
47 static gboolean verbose = FALSE;
49 static const char *
50 get_audio_format_name (guint codec)
52 switch (codec) {
53 case SWFDEC_AUDIO_CODEC_ADPCM:
54 return "ADPCM";
55 case SWFDEC_AUDIO_CODEC_MP3:
56 return "MP3";
57 case SWFDEC_AUDIO_CODEC_UNCOMPRESSED:
58 return "uncompressed";
59 case SWFDEC_AUDIO_CODEC_NELLYMOSER:
60 return "Nellymoser";
61 default:
62 return "Unknown";
66 static void
67 dump_sound (SwfdecSound *sound)
69 g_print (" codec: %s\n", get_audio_format_name (sound->codec));
70 if (verbose) {
71 g_print (" format: %s\n", swfdec_audio_format_to_string (sound->format));
72 g_print (" samples: %u (%gs)\n", sound->n_samples,
73 (double) sound->n_samples / swfdec_audio_format_get_rate (sound->format));
77 static void
78 dump_sprite (SwfdecSwfDecoder *dec, SwfdecSprite *s)
80 if (!verbose) {
81 g_print (" %u frames\n", s->n_frames);
82 } else {
83 guint i, j, tag;
84 SwfdecBuffer *buffer;
85 SwfdecSound *sound = NULL;
87 for (i = 0; i < s->n_frames; i++) {
88 SwfdecSpriteFrame *frame = &s->frames[i];
89 if (frame->sound_head != sound &&
90 frame->sound_block != NULL) {
91 sound = frame->sound_head;
92 for (j = i; j < s->n_frames; j++) {
93 SwfdecSpriteFrame *cur = &s->frames[i];
94 if (cur->sound_head != sound)
95 break;
97 if (sound)
98 g_print (" %4u -%4u sound: %s %s\n", i, j,
99 get_audio_format_name (sound->codec),
100 swfdec_audio_format_to_string (sound->format));
104 j = 0;
105 for (i = 0; ; i++) {
106 if (!swfdec_sprite_get_action (s, i, &tag, &buffer))
107 break;
108 switch (tag) {
109 case SWFDEC_TAG_DOACTION:
110 g_print (" %4u script\n", j);
111 break;
112 case SWFDEC_TAG_PLACEOBJECT2:
113 case SWFDEC_TAG_PLACEOBJECT3:
115 SwfdecBits bits;
116 gboolean has_char, is_move;
117 guint depth;
119 swfdec_bits_init (&bits, buffer);
120 swfdec_bits_getbits (&bits, 6);
121 has_char = swfdec_bits_getbit (&bits);
122 is_move = swfdec_bits_getbit (&bits);
123 if (tag == SWFDEC_TAG_PLACEOBJECT3)
124 swfdec_bits_get_u8 (&bits);
125 depth = swfdec_bits_get_u16 (&bits);
126 g_print (" %4u %5u %s", j, depth, is_move ? "move" : "place");
127 if (has_char) {
128 SwfdecCharacter *c;
129 c = swfdec_swf_decoder_get_character (dec, swfdec_bits_get_u16 (&bits));
130 if (c)
131 g_print (" %s %u", G_OBJECT_TYPE_NAME (c), c->id);
133 g_print ("\n");
135 break;
136 case SWFDEC_TAG_REMOVEOBJECT:
137 case SWFDEC_TAG_REMOVEOBJECT2:
139 SwfdecBits bits;
140 swfdec_bits_init (&bits, buffer);
141 if (tag == SWFDEC_TAG_REMOVEOBJECT)
142 swfdec_bits_get_u16 (&bits);
143 g_print (" %4u %5u remove\n", j, swfdec_bits_get_u16 (&bits));
145 break;
146 case SWFDEC_TAG_SHOWFRAME:
147 j++;
148 break;
149 case SWFDEC_TAG_STARTSOUND:
150 /* FIXME add info about what sound etc */
151 g_print (" %4u start sound\n", j);
152 break;
153 default:
154 g_assert_not_reached ();
160 static void
161 dump_path (cairo_path_t *path)
163 int i;
164 cairo_path_data_t *data = path->data;
165 const char *name;
167 for (i = 0; i < path->num_data; i++) {
168 name = NULL;
169 switch (data[i].header.type) {
170 case CAIRO_PATH_CURVE_TO:
171 g_print (" curve %g %g (%g %g . %g %g)\n",
172 data[i + 3].point.x, data[i + 3].point.y,
173 data[i + 1].point.x, data[i + 1].point.y,
174 data[i + 2].point.x, data[i + 2].point.y);
175 i += 3;
176 break;
177 case CAIRO_PATH_LINE_TO:
178 name = "line ";
179 case CAIRO_PATH_MOVE_TO:
180 if (!name)
181 name = "move ";
182 i++;
183 g_print (" %s %g %g\n", name, data[i].point.x, data[i].point.y);
184 break;
185 case CAIRO_PATH_CLOSE_PATH:
186 g_print (" close\n");
187 break;
188 default:
189 g_assert_not_reached ();
190 break;
195 static void
196 dump_shape (SwfdecShape *shape)
198 GSList *walk;
200 for (walk = shape->draws; walk; walk = walk->next) {
201 if (SWFDEC_IS_PATTERN (walk->data)) {
202 SwfdecPattern *pattern = walk->data;
203 char *str = swfdec_pattern_to_string (pattern);
204 g_print ("%s\n", str);
205 g_free (str);
206 if (verbose) {
207 g_print (" %g %g %g %g %g %g\n",
208 pattern->start_transform.xx, pattern->start_transform.xy,
209 pattern->start_transform.yx, pattern->start_transform.yy,
210 pattern->start_transform.x0, pattern->start_transform.y0);
212 } else if (SWFDEC_IS_STROKE (walk->data)) {
213 SwfdecStroke *line = walk->data;
214 g_print ("line (width %u, color #%08X)\n", line->start_width, line->start_color);
215 } else {
216 g_print ("not filled\n");
218 if (verbose) {
219 dump_path (&SWFDEC_DRAW (walk->data)->path);
224 static void
225 dump_text_field (SwfdecTextField *text)
227 g_print (" %s\n", text->input ? text->input : "");
228 if (verbose) {
229 if (text->variable)
230 g_print (" variable %s\n", text->variable);
231 else
232 g_print (" no variable\n");
236 static void
237 dump_text (SwfdecText *text)
239 guint i;
240 gunichar2 uni[text->glyphs->len];
241 char *s;
243 for (i = 0; i < text->glyphs->len; i++) {
244 SwfdecTextGlyph *glyph = &g_array_index (text->glyphs, SwfdecTextGlyph, i);
245 uni[i] = g_array_index (glyph->font->glyphs, SwfdecFontEntry, glyph->glyph).value;
246 if (uni[i] == 0)
247 goto fallback;
249 s = g_utf16_to_utf8 (uni, text->glyphs->len, NULL, NULL, NULL);
250 if (s == NULL)
251 goto fallback;
252 g_print (" text: %s\n", s);
253 g_free (s);
254 return;
256 fallback:
257 g_print (" %u characters\n", text->glyphs->len);
260 static void
261 dump_font (SwfdecFont *font)
263 unsigned int i;
264 if (font->name)
265 g_print (" %s\n", font->name);
266 g_print (" %u characters\n", font->glyphs->len);
267 if (verbose) {
268 for (i = 0; i < font->glyphs->len; i++) {
269 gunichar2 c = g_array_index (font->glyphs, SwfdecFontEntry, i).value;
270 char *s;
271 if (c == 0 || (s = g_utf16_to_utf8 (&c, 1, NULL, NULL, NULL)) == NULL) {
272 g_print (" ");
273 } else {
274 g_print ("%s ", s);
275 g_free (s);
278 g_print ("\n");
282 static void
283 dump_button (SwfdecButton *button)
287 static const char *
288 get_image_type_name (SwfdecImageType type)
290 switch (type) {
291 case SWFDEC_IMAGE_TYPE_JPEG:
292 return "JPEG with global table";
293 case SWFDEC_IMAGE_TYPE_JPEG2:
294 return "JPEG";
295 case SWFDEC_IMAGE_TYPE_JPEG3:
296 return "JPEG with alpha";
297 case SWFDEC_IMAGE_TYPE_LOSSLESS:
298 return "lossless";
299 case SWFDEC_IMAGE_TYPE_LOSSLESS2:
300 return "lossless with alpha";
301 case SWFDEC_IMAGE_TYPE_PNG:
302 return "PNG";
303 case SWFDEC_IMAGE_TYPE_UNKNOWN:
304 default:
305 g_assert_not_reached ();
306 return "Unknown";
310 static void
311 dump_image (SwfdecImage *image)
313 cairo_surface_destroy (swfdec_image_create_surface (image));
314 g_print (" %s %u x %u\n", get_image_type_name (image->type),
315 image->width, image->height);
318 static void
319 dump_object (gpointer value, gpointer dec)
321 SwfdecCharacter *c = value;
323 g_print ("%d: %s\n", c->id, G_OBJECT_TYPE_NAME (c));
324 if (verbose && SWFDEC_IS_GRAPHIC (c)) {
325 SwfdecGraphic *graphic = SWFDEC_GRAPHIC (c);
326 g_print (" extents: %g %g %g %g\n", graphic->extents.x0, graphic->extents.y0,
327 graphic->extents.x1, graphic->extents.y1);
329 if (SWFDEC_IS_IMAGE (c)) {
330 dump_image (SWFDEC_IMAGE (c));
332 if (SWFDEC_IS_SPRITE (c)) {
333 dump_sprite (dec, SWFDEC_SPRITE (c));
335 if (SWFDEC_IS_SHAPE(c)) {
336 dump_shape(SWFDEC_SHAPE(c));
338 if (SWFDEC_IS_TEXT (c)) {
339 dump_text (SWFDEC_TEXT (c));
341 if (SWFDEC_IS_TEXT_FIELD (c)) {
342 dump_text_field (SWFDEC_TEXT_FIELD (c));
344 if (SWFDEC_IS_FONT (c)) {
345 dump_font (SWFDEC_FONT (c));
347 if (SWFDEC_IS_BUTTON (c)) {
348 dump_button (SWFDEC_BUTTON (c));
350 if (SWFDEC_IS_SOUND (c)) {
351 dump_sound (SWFDEC_SOUND (c));
355 static void
356 enqueue (gpointer key, gpointer value, gpointer listp)
358 GList **list = listp;
360 *list = g_list_prepend (*list, value);
363 static int
364 sort_by_id (gconstpointer a, gconstpointer b)
366 if (SWFDEC_CHARACTER (a)->id < SWFDEC_CHARACTER (b)->id)
367 return -1;
368 return 1;
372 main (int argc, char *argv[])
374 SwfdecSwfDecoder *s;
375 SwfdecPlayer *player;
376 GError *error = NULL;
377 GOptionEntry options[] = {
378 { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "bew verbose", NULL },
379 { NULL }
381 GOptionContext *ctx;
382 GList *list = NULL;
384 ctx = g_option_context_new ("");
385 g_option_context_add_main_entries (ctx, options, "options");
386 g_option_context_parse (ctx, &argc, &argv, &error);
387 g_option_context_free (ctx);
388 if (error) {
389 g_printerr ("Error parsing command line arguments: %s\n", error->message);
390 g_error_free (error);
391 return 1;
394 swfdec_init();
396 if(argc < 2){
397 g_print ("usage: %s [OPTIONS] file\n", argv[0]);
398 return 0;
401 player = swfdec_player_new_from_file (argv[1]);
402 if (player->resource->loader->error) {
403 g_printerr ("Couldn't open file \"%s\": %s\n", argv[1], player->resource->loader->error);
404 g_object_unref (player);
405 return 1;
407 /* FIXME: HACK! */
408 swfdec_player_advance (player, 0);
409 if (!swfdec_player_is_initialized (player)) {
410 g_printerr ("File \"%s\" is not a SWF file\n", argv[1]);
411 g_object_unref (player);
412 player = NULL;
413 return 1;
415 s = (SwfdecSwfDecoder *) SWFDEC_MOVIE (player->roots->data)->resource->decoder;
416 /* FIXME: can happen after a _root.loadMovie() call */
417 if (!SWFDEC_IS_SWF_DECODER (s)) {
418 g_printerr ("Movie already unloaded from \"%s\"\n", argv[1]);
419 g_object_unref (player);
420 player = NULL;
421 return 1;
424 g_print ("file:\n");
425 g_print (" version: %d\n", s->version);
426 g_print (" rate : %g fps\n", SWFDEC_DECODER (s)->rate / 256.0);
427 g_print (" size : %ux%u pixels\n", SWFDEC_DECODER (s)->width, SWFDEC_DECODER (s)->height);
428 g_print ("objects:\n");
429 g_hash_table_foreach (s->characters, enqueue, &list);
430 list = g_list_sort (list, sort_by_id);
431 g_list_foreach (list, dump_object, s);
432 g_list_free (list);
434 g_print ("main sprite:\n");
435 dump_sprite (s, s->main_sprite);
436 g_object_unref (player);
437 s = NULL;
438 player = NULL;
440 return 0;