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
31 #include "swfdec_tag.h"
32 #include "swfdec_bits.h"
33 #include "swfdec_button.h"
34 #include "swfdec_debug.h"
35 #include "swfdec_text_field.h"
36 #include "swfdec_filter.h"
37 #include "swfdec_font.h"
38 #include "swfdec_image.h"
39 #include "swfdec_morphshape.h"
40 #include "swfdec_pattern.h"
41 #include "swfdec_player_internal.h"
42 #include "swfdec_script_internal.h"
43 #include "swfdec_shape.h"
44 #include "swfdec_sound.h"
45 #include "swfdec_sprite.h"
46 #include "swfdec_text.h"
47 #include "swfdec_video.h"
50 tag_func_end (SwfdecSwfDecoder
* s
, guint tag
)
52 return SWFDEC_STATUS_OK
;
56 tag_func_protect (SwfdecSwfDecoder
* s
, guint tag
)
59 SWFDEC_INFO ("This file is really protected.");
64 if (swfdec_bits_left (&s
->b
)) {
65 /* FIXME: What's this for? */
66 swfdec_bits_get_u16 (&s
->b
);
67 s
->password
= swfdec_bits_get_string (&s
->b
, s
->version
);
69 return SWFDEC_STATUS_OK
;
73 tag_func_frame_label (SwfdecSwfDecoder
* s
, guint tag
)
75 SwfdecSpriteFrame
*frame
= &s
->parse_sprite
->frames
[s
->parse_sprite
->parse_frame
];
78 SWFDEC_WARNING ("adding another label for frame %d (%s)",
79 s
->parse_sprite
->parse_frame
, (char *)frame
->labels
->data
);
81 frame
->labels
= g_slist_prepend (frame
->labels
,
82 swfdec_bits_get_string (&s
->b
, s
->version
));
83 SWFDEC_LOG ("frame %d named %s", s
->parse_sprite
->parse_frame
,
84 (char *)frame
->labels
->data
);
86 return SWFDEC_STATUS_OK
;
93 tag_func_define_text (SwfdecSwfDecoder
* s
, guint tag
)
95 SwfdecBits
*bits
= &s
->b
;
99 SwfdecText
*text
= NULL
;
100 SwfdecTextGlyph glyph
= { 0 };
102 id
= swfdec_bits_get_u16 (bits
);
103 text
= swfdec_swf_decoder_create_character (s
, id
, SWFDEC_TYPE_TEXT
);
105 return SWFDEC_STATUS_OK
;
107 glyph
.color
= 0xffffffff;
109 swfdec_bits_get_rect (bits
, &SWFDEC_GRAPHIC (text
)->extents
);
110 swfdec_bits_get_matrix (bits
, &text
->transform
, &text
->transform_inverse
);
111 swfdec_bits_syncbits (bits
);
112 n_glyph_bits
= swfdec_bits_get_u8 (bits
);
113 n_advance_bits
= swfdec_bits_get_u8 (bits
);
115 //printf(" n_glyph_bits = %d\n", n_glyph_bits);
116 //printf(" n_advance_bits = %d\n", n_advance_bits);
118 while (swfdec_bits_peekbits (bits
, 8) != 0) {
121 type
= swfdec_bits_getbit (bits
);
127 n_glyphs
= swfdec_bits_getbits (bits
, 7);
128 if (glyph
.font
== NULL
)
129 SWFDEC_ERROR ("no font for %d glyphs", n_glyphs
);
130 for (i
= 0; i
< n_glyphs
; i
++) {
131 glyph
.glyph
= swfdec_bits_getbits (bits
, n_glyph_bits
);
133 if (glyph
.font
!= NULL
)
134 g_array_append_val (text
->glyphs
, glyph
);
135 glyph
.x
+= swfdec_bits_getsbits (bits
, n_advance_bits
);
145 reserved
= swfdec_bits_getbits (bits
, 3);
146 has_font
= swfdec_bits_getbit (bits
);
147 has_color
= swfdec_bits_getbit (bits
);
148 has_y_offset
= swfdec_bits_getbit (bits
);
149 has_x_offset
= swfdec_bits_getbit (bits
);
151 glyph
.font
= swfdec_swf_decoder_get_character (s
, swfdec_bits_get_u16 (bits
));
152 //printf(" font = %d\n",font);
155 if (tag
== SWFDEC_TAG_DEFINETEXT
) {
156 glyph
.color
= swfdec_bits_get_color (bits
);
158 glyph
.color
= swfdec_bits_get_rgba (bits
);
160 //printf(" color = %08x\n",glyph.color);
163 glyph
.x
= swfdec_bits_get_s16 (bits
);
166 glyph
.y
= swfdec_bits_get_s16 (bits
);
169 glyph
.height
= swfdec_bits_get_u16 (bits
);
172 swfdec_bits_syncbits (bits
);
174 swfdec_bits_get_u8 (bits
);
176 return SWFDEC_STATUS_OK
;
180 tag_func_define_sprite (SwfdecSwfDecoder
* s
, guint define_sprite_tag
)
184 SwfdecSprite
*sprite
;
190 id
= swfdec_bits_get_u16 (&parse
);
191 sprite
= swfdec_swf_decoder_create_character (s
, id
, SWFDEC_TYPE_SPRITE
);
193 return SWFDEC_STATUS_OK
;
195 SWFDEC_LOG (" ID: %d", id
);
197 swfdec_sprite_set_n_frames (sprite
, swfdec_bits_get_u16 (&parse
), SWFDEC_DECODER (s
)->rate
);
199 s
->parse_sprite
= sprite
;
200 while (swfdec_bits_left (&parse
)) {
205 x
= swfdec_bits_get_u16 (&parse
);
208 if (tag_len
== 0x3f) {
209 tag_len
= swfdec_bits_get_u32 (&parse
);
211 SWFDEC_INFO ("sprite parsing at %td, tag %d %s, length %d",
212 parse
.buffer
? parse
.ptr
- parse
.buffer
->data
: 0, tag
,
213 swfdec_swf_decoder_get_tag_name (tag
), tag_len
);
216 swfdec_bits_init_data (&s
->b
, NULL
, 0);
218 swfdec_bits_init_bits (&s
->b
, &parse
, tag_len
);
221 func
= swfdec_swf_decoder_get_tag_func (tag
);
224 } else if (func
== NULL
) {
225 SWFDEC_FIXME ("tag function not implemented for %d %s",
226 tag
, swfdec_swf_decoder_get_tag_name (tag
));
227 } else if ((swfdec_swf_decoder_get_tag_flag (tag
) & 1) == 0) {
228 SWFDEC_ERROR ("invalid tag %d %s during DefineSprite",
229 tag
, swfdec_swf_decoder_get_tag_name (tag
));
230 } else if (s
->parse_sprite
->parse_frame
< s
->parse_sprite
->n_frames
) {
233 if (swfdec_bits_left (&s
->b
)) {
234 SWFDEC_WARNING ("early parse finish (%d bytes)",
235 swfdec_bits_left (&s
->b
) / 8);
238 SWFDEC_ERROR ("data after last frame");
242 /* sanity check the sprite */
243 if (s
->parse_sprite
->n_frames
!= s
->parse_sprite
->parse_frame
) {
244 SWFDEC_INFO ("not enough frames in sprite %u (have %u, want %u), filling up with empty frames",
245 id
, s
->parse_sprite
->parse_frame
, s
->parse_sprite
->n_frames
);
246 s
->parse_sprite
->parse_frame
= s
->parse_sprite
->n_frames
;
250 /* this assumes that no recursive DefineSprite happens and we check it doesn't */
251 s
->parse_sprite
= s
->main_sprite
;
252 SWFDEC_LOG ("done parsing this sprite");
254 return SWFDEC_STATUS_OK
;
258 tag_func_file_attributes (SwfdecSwfDecoder
*s
, guint tag
)
260 if (swfdec_bits_getbits (&s
->b
, 3))
261 SWFDEC_INFO ("reserved bits (1) aren't 0");
262 s
->has_metadata
= swfdec_bits_getbit (&s
->b
);
263 SWFDEC_LOG (" has metadata: %d", s
->has_metadata
);
264 if (swfdec_bits_getbits (&s
->b
, 3))
265 SWFDEC_INFO ("reserved bits (2) aren't 0");
266 s
->use_network
= swfdec_bits_getbit (&s
->b
);
267 SWFDEC_LOG (" use network: %d", s
->use_network
);
268 if (swfdec_bits_getbits (&s
->b
, 24))
269 SWFDEC_INFO ("reserved bits (3) aren't 0");
270 /* initialize default security if it wasn't initialized yet */
272 return SWFDEC_STATUS_OK
;
276 tag_func_enqueue (SwfdecSwfDecoder
*s
, guint tag
)
278 SwfdecBuffer
*buffer
;
280 buffer
= swfdec_bits_get_buffer (&s
->b
, -1);
281 SWFDEC_LOG ("queueing %s tag for sprite %u", swfdec_swf_decoder_get_tag_name (tag
),
282 SWFDEC_CHARACTER (s
->parse_sprite
)->id
);
283 swfdec_sprite_add_action (s
->parse_sprite
, tag
, buffer
);
285 return SWFDEC_STATUS_OK
;
289 tag_func_show_frame (SwfdecSwfDecoder
* s
, guint tag
)
291 SWFDEC_DEBUG("show_frame %d of id %d", s
->parse_sprite
->parse_frame
,
292 SWFDEC_CHARACTER (s
->parse_sprite
)->id
);
294 s
->parse_sprite
->parse_frame
++;
295 tag_func_enqueue (s
, tag
);
297 return SWFDEC_STATUS_IMAGE
;
301 tag_func_do_action (SwfdecSwfDecoder
* s
, guint tag
)
303 SwfdecScript
*script
;
307 if (swfdec_bits_left (&s
->b
) == 0) {
308 SWFDEC_WARNING ("empty script, ignoring");
309 return SWFDEC_STATUS_OK
;
311 name
= g_strdup_printf ("Sprite%u_Frame%u", SWFDEC_CHARACTER (s
->parse_sprite
)->id
,
312 s
->parse_sprite
->parse_frame
);
314 script
= swfdec_script_new_from_bits (&bits
, name
, s
->version
);
317 swfdec_swf_decoder_add_script (s
, script
);
318 tag_func_enqueue (s
, tag
);
321 return SWFDEC_STATUS_OK
;
325 tag_func_do_init_action (SwfdecSwfDecoder
* s
, guint tag
)
327 SwfdecScript
*script
;
333 id
= swfdec_bits_get_u16 (&bits
);
334 if (swfdec_bits_left (&bits
) == 0) {
335 SWFDEC_WARNING ("empty script, ignoring");
336 return SWFDEC_STATUS_OK
;
338 name
= g_strdup_printf ("Init %u", id
);
339 script
= swfdec_script_new_from_bits (&bits
, name
, s
->version
);
342 swfdec_swf_decoder_add_script (s
, script
);
343 tag_func_enqueue (s
, tag
);
346 return SWFDEC_STATUS_OK
;
349 /* only needed for the codec finding stuff */
351 tag_func_sound_stream_head (SwfdecSwfDecoder
*s
, guint tag
)
354 SwfdecAudioFormat playback_format
, format
;
355 guint playback_codec
, codec
;
360 /* we don't care about playback suggestions */
361 playback_codec
= swfdec_bits_getbits (&bits
, 4);
362 playback_format
= swfdec_audio_format_parse (&bits
);
363 SWFDEC_LOG (" suggested playback format: %s", swfdec_audio_format_to_string (playback_format
));
365 codec
= swfdec_bits_getbits (&bits
, 4);
366 format
= swfdec_audio_format_parse (&bits
);
367 n_samples
= swfdec_bits_get_u16 (&bits
);
368 SWFDEC_LOG (" codec: %u", codec
);
369 SWFDEC_LOG (" format: %s", swfdec_audio_format_to_string (format
));
370 SWFDEC_LOG (" samples: %u", n_samples
);
372 swfdec_decoder_use_audio_codec (SWFDEC_DECODER (s
), codec
, format
);
374 return tag_func_enqueue (s
, tag
);
378 tag_func_metadata (SwfdecSwfDecoder
*s
, guint tag
)
382 meta
= swfdec_bits_get_string (&s
->b
, s
->version
);
384 SWFDEC_ERROR ("invalid metadata contents");
385 return SWFDEC_STATUS_OK
;
387 SWFDEC_LOG ("metadata: %s", meta
);
390 SWFDEC_ERROR ("Duplicated metadata tag, ignoring");
391 /* FIXME: or use this one? */
396 return SWFDEC_STATUS_OK
;
399 struct tag_func_struct
405 static struct tag_func_struct tag_funcs
[] = {
406 [SWFDEC_TAG_END
] = {"End", tag_func_end
, SWFDEC_TAG_DEFINE_SPRITE
},
407 [SWFDEC_TAG_SHOWFRAME
] = {"ShowFrame", tag_func_show_frame
, SWFDEC_TAG_DEFINE_SPRITE
},
408 [SWFDEC_TAG_DEFINESHAPE
] = {"DefineShape", tag_define_shape
, 0},
409 [SWFDEC_TAG_FREECHARACTER
] = {"FreeCharacter", NULL
, 0},
410 [SWFDEC_TAG_PLACEOBJECT
] = {"PlaceObject", tag_func_enqueue
, SWFDEC_TAG_DEFINE_SPRITE
},
411 [SWFDEC_TAG_REMOVEOBJECT
] = {"RemoveObject", tag_func_enqueue
, SWFDEC_TAG_DEFINE_SPRITE
},
412 [SWFDEC_TAG_DEFINEBITSJPEG
] = {"DefineBitsJPEG", tag_func_define_bits_jpeg
, 0},
413 [SWFDEC_TAG_DEFINEBUTTON
] = {"DefineButton", tag_func_define_button
, 0},
414 [SWFDEC_TAG_JPEGTABLES
] = {"JPEGTables", swfdec_image_jpegtables
, 0},
415 [SWFDEC_TAG_SETBACKGROUNDCOLOR
] =
416 {"SetBackgroundColor", tag_func_enqueue
, SWFDEC_TAG_DEFINE_SPRITE
},
417 [SWFDEC_TAG_DEFINEFONT
] = {"DefineFont", tag_func_define_font
, 0},
418 [SWFDEC_TAG_DEFINETEXT
] = {"DefineText", tag_func_define_text
, 0},
419 [SWFDEC_TAG_DOACTION
] = {"DoAction", tag_func_do_action
, SWFDEC_TAG_DEFINE_SPRITE
},
420 [SWFDEC_TAG_DEFINEFONTINFO
] = {"DefineFontInfo", tag_func_define_font_info
, 0},
421 [SWFDEC_TAG_DEFINESOUND
] = {"DefineSound", tag_func_define_sound
, 0},
422 [SWFDEC_TAG_STARTSOUND
] = {"StartSound", tag_func_enqueue
, SWFDEC_TAG_DEFINE_SPRITE
},
423 [SWFDEC_TAG_DEFINEBUTTONSOUND
] =
424 {"DefineButtonSound", tag_func_define_button_sound
, 0},
425 [SWFDEC_TAG_SOUNDSTREAMHEAD
] = {"SoundStreamHead", tag_func_sound_stream_head
, SWFDEC_TAG_DEFINE_SPRITE
},
426 [SWFDEC_TAG_SOUNDSTREAMBLOCK
] = {"SoundStreamBlock", tag_func_enqueue
, SWFDEC_TAG_DEFINE_SPRITE
},
427 [SWFDEC_TAG_DEFINEBITSLOSSLESS
] =
428 {"DefineBitsLossless", tag_func_define_bits_lossless
, 0},
429 [SWFDEC_TAG_DEFINEBITSJPEG2
] = {"DefineBitsJPEG2", tag_func_define_bits_jpeg_2
, 0},
430 [SWFDEC_TAG_DEFINESHAPE2
] = {"DefineShape2", tag_define_shape
, 0},
431 [SWFDEC_TAG_DEFINEBUTTONCXFORM
] = {"DefineButtonCXForm", NULL
, 0},
432 [SWFDEC_TAG_PROTECT
] = {"Protect", tag_func_protect
, 0},
433 [SWFDEC_TAG_PLACEOBJECT2
] = {"PlaceObject2", tag_func_enqueue
, SWFDEC_TAG_DEFINE_SPRITE
},
434 [SWFDEC_TAG_REMOVEOBJECT2
] = {"RemoveObject2", tag_func_enqueue
, SWFDEC_TAG_DEFINE_SPRITE
},
435 [SWFDEC_TAG_DEFINESHAPE3
] = {"DefineShape3", tag_define_shape_3
, 0},
436 [SWFDEC_TAG_DEFINETEXT2
] = {"DefineText2", tag_func_define_text
, 0},
437 [SWFDEC_TAG_DEFINEBUTTON2
] = {"DefineButton2", tag_func_define_button_2
, 0},
438 [SWFDEC_TAG_DEFINEBITSJPEG3
] = {"DefineBitsJPEG3", tag_func_define_bits_jpeg_3
, 0},
439 [SWFDEC_TAG_DEFINEBITSLOSSLESS2
] =
440 {"DefineBitsLossless2", tag_func_define_bits_lossless_2
, 0},
441 [SWFDEC_TAG_DEFINEEDITTEXT
] = {"DefineEditText", tag_func_define_edit_text
, 0},
442 [SWFDEC_TAG_DEFINEMOVIE
] = {"DefineMovie", NULL
, 0},
443 [SWFDEC_TAG_DEFINESPRITE
] = {"DefineSprite", tag_func_define_sprite
, 0},
444 [SWFDEC_TAG_NAMECHARACTER
] = {"NameCharacter", NULL
, 0},
445 [SWFDEC_TAG_PRODUCTINFO
] = {"ProductInfo", NULL
, 0},
446 [SWFDEC_TAG_GENERATORTEXT
] = {"GeneratorText", NULL
, 0},
447 [SWFDEC_TAG_FRAMELABEL
] = {"FrameLabel", tag_func_frame_label
, SWFDEC_TAG_DEFINE_SPRITE
},
448 [SWFDEC_TAG_SOUNDSTREAMHEAD2
] = {"SoundStreamHead2", tag_func_sound_stream_head
, SWFDEC_TAG_DEFINE_SPRITE
},
449 [SWFDEC_TAG_DEFINEMORPHSHAPE
] =
450 {"DefineMorphShape", tag_define_morph_shape
, 0},
451 [SWFDEC_TAG_DEFINEFONT2
] = {"DefineFont2", tag_func_define_font_2
, 0},
452 [SWFDEC_TAG_TEMPLATECOMMAND
] = {"TemplateCommand", NULL
, 0},
453 [SWFDEC_TAG_GENERATOR3
] = {"Generator3", NULL
, 0},
454 [SWFDEC_TAG_EXTERNALFONT
] = {"ExternalFont", NULL
, 0},
455 [SWFDEC_TAG_EXPORTASSETS
] = {"ExportAssets", tag_func_enqueue
, 0},
456 [SWFDEC_TAG_IMPORTASSETS
] = {"ImportAssets", NULL
, 0},
457 [SWFDEC_TAG_ENABLEDEBUGGER
] = {"EnableDebugger", NULL
, 0},
458 [SWFDEC_TAG_DOINITACTION
] = {"DoInitAction", tag_func_do_init_action
, SWFDEC_TAG_DEFINE_SPRITE
},
459 [SWFDEC_TAG_DEFINEVIDEOSTREAM
] = {"DefineVideoStream", tag_func_define_video
, SWFDEC_TAG_DEFINE_SPRITE
},
460 [SWFDEC_TAG_VIDEOFRAME
] = {"VideoFrame", tag_func_video_frame
, SWFDEC_TAG_DEFINE_SPRITE
},
461 [SWFDEC_TAG_DEFINEFONTINFO2
] = {"DefineFontInfo2", tag_func_define_font_info
, 0},
462 [SWFDEC_TAG_DEBUGID
] = {"DebugID", NULL
, 0},
463 [SWFDEC_TAG_ENABLEDEBUGGER2
] = {"EnableDebugger2", NULL
, 0},
464 [SWFDEC_TAG_SCRIPTLIMITS
] = {"ScriptLimits", NULL
, 0},
465 [SWFDEC_TAG_SETTABINDEX
] = {"SetTabIndex", NULL
, SWFDEC_TAG_DEFINE_SPRITE
},
466 [SWFDEC_TAG_FILEATTRIBUTES
] = {"FileAttributes", tag_func_file_attributes
, SWFDEC_TAG_FIRST_ONLY
},
467 [SWFDEC_TAG_PLACEOBJECT3
] = {"PlaceObject3", tag_func_enqueue
, SWFDEC_TAG_DEFINE_SPRITE
},
468 [SWFDEC_TAG_IMPORTASSETS2
] = {"ImportAssets2", NULL
, 0},
469 [SWFDEC_TAG_DEFINEFONTALIGNZONES
] = {"DefineFontAlignZones", NULL
, 0},
470 [SWFDEC_TAG_CSMTEXTSETTINGS
] = {"CSMTextSettings", NULL
, 0},
471 [SWFDEC_TAG_DEFINEFONT3
] = {"DefineFont3", tag_func_define_font_2
, 0},
472 [SWFDEC_TAG_SYMBOLCLASS
] = {"SymbolClass", NULL
, SWFDEC_TAG_DEFINE_SPRITE
},
473 [SWFDEC_TAG_METADATA
] = {"Metadata", tag_func_metadata
, 0},
474 [SWFDEC_TAG_DEFINESCALINGGRID
] = {"DefineScalingGrid", NULL
, 0},
475 [SWFDEC_TAG_DOABC
] = {"DoAbc", NULL
, SWFDEC_TAG_DEFINE_SPRITE
},
476 [SWFDEC_TAG_DEFINESHAPE4
] = {"DefineShape4", tag_define_shape_4
, 0},
477 [SWFDEC_TAG_DEFINEMORPHSHAPE2
] = {"DefineMorphShape2", NULL
, 0},
478 [SWFDEC_TAG_PRIVATE_IMAGE
] = { "PrivateImage", NULL
, 0},
479 [SWFDEC_TAG_DEFINESCENEDATA
] = { "DefineSceneData", NULL
, 0},
480 [SWFDEC_TAG_DEFINEBINARYDATA
] = { "DefineBinaryData", NULL
, 0},
481 [SWFDEC_TAG_DEFINEFONTNAME
] = { "DefineFontName", tag_func_define_font_name
, 0},
482 [SWFDEC_TAG_STARTSOUND2
] = {"StartSound2", NULL
, SWFDEC_TAG_DEFINE_SPRITE
}
485 static const int n_tag_funcs
= sizeof (tag_funcs
) / sizeof (tag_funcs
[0]);
488 swfdec_swf_decoder_get_tag_name (int tag
)
490 if (tag
>= 0 && tag
< n_tag_funcs
) {
491 if (tag_funcs
[tag
].name
) {
492 return tag_funcs
[tag
].name
;
500 swfdec_swf_decoder_get_tag_func (int tag
)
502 if (tag
>= 0 && tag
< n_tag_funcs
) {
503 if (tag_funcs
[tag
].func
) {
504 return tag_funcs
[tag
].func
;
512 swfdec_swf_decoder_get_tag_flag (int tag
)
514 if (tag
>= 0 && tag
< n_tag_funcs
) {
515 return tag_funcs
[tag
].flag
;