📄 swfdec_sprite_movie.c
字号:
/* Swfdec * Copyright (C) 2006 Benjamin Otte <otte@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 <strings.h>#include "swfdec_sprite_movie.h"#include "swfdec_as_internal.h"#include "swfdec_as_strings.h"#include "swfdec_audio_event.h"#include "swfdec_audio_stream.h"#include "swfdec_debug.h"#include "swfdec_graphic_movie.h"#include "swfdec_player_internal.h"#include "swfdec_ringbuffer.h"#include "swfdec_script.h"#include "swfdec_sprite.h"#include "swfdec_swf_instance.h"#include "swfdec_tag.h"#include "swfdec_utils.h"/*** SWFDEC_SPRITE_MOVIE ***/static gbooleanswfdec_sprite_movie_remove_child (SwfdecMovie *movie, int depth){ SwfdecMovie *child = swfdec_movie_find (movie, depth); if (child == NULL) return FALSE; swfdec_movie_remove (child); return TRUE;}static voidswfdec_sprite_movie_run_script (gpointer movie, gpointer data){ swfdec_as_object_run (movie, data);}static cairo_operator_tswfdec_sprite_convert_operator (guint operator){ return CAIRO_OPERATOR_OVER;}static intswfdec_get_clipeventflags (SwfdecMovie *movie, SwfdecBits * bits){ if (SWFDEC_SWF_DECODER (movie->swf->decoder)->version <= 5) { return swfdec_bits_get_u16 (bits); } else { return swfdec_bits_get_u32 (bits); }}static gbooleanswfdec_sprite_movie_perform_place (SwfdecSpriteMovie *movie, SwfdecBits *bits, guint tag){ SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context); SwfdecMovie *mov = SWFDEC_MOVIE (movie); SwfdecMovie *cur; gboolean has_clip_actions; gboolean has_clip_depth; gboolean has_name; gboolean has_ratio; gboolean has_ctrans; gboolean has_transform; gboolean has_character; gboolean move; gboolean depth; gboolean cache; gboolean has_blend_mode = 0; gboolean has_filter = 0; int clip_depth; cairo_matrix_t transform; SwfdecColorTransform ctrans; guint ratio, id, version; SwfdecEventList *events; const char *name; SwfdecGraphic *graphic; version = SWFDEC_SWF_DECODER (mov->swf->decoder)->version; /* 1) check which stuff is set */ has_clip_actions = swfdec_bits_getbit (bits); has_clip_depth = swfdec_bits_getbit (bits); has_name = swfdec_bits_getbit (bits); has_ratio = swfdec_bits_getbit (bits); has_ctrans = swfdec_bits_getbit (bits); has_transform = swfdec_bits_getbit (bits); has_character = swfdec_bits_getbit (bits); move = swfdec_bits_getbit (bits); SWFDEC_LOG ("performing PlaceObject%d on movie %s", tag == SWFDEC_TAG_PLACEOBJECT2 ? 2 : 3, mov->name); SWFDEC_LOG (" has_clip_actions = %d", has_clip_actions); SWFDEC_LOG (" has_clip_depth = %d", has_clip_depth); SWFDEC_LOG (" has_name = %d", has_name); SWFDEC_LOG (" has_ratio = %d", has_ratio); SWFDEC_LOG (" has_ctrans = %d", has_ctrans); SWFDEC_LOG (" has_transform = %d", has_transform); SWFDEC_LOG (" has_character = %d", has_character); SWFDEC_LOG (" move = %d", move); if (tag == SWFDEC_TAG_PLACEOBJECT3) { swfdec_bits_getbits (bits, 5); cache = swfdec_bits_getbit (bits); has_blend_mode = swfdec_bits_getbit (bits); has_filter = swfdec_bits_getbit (bits); SWFDEC_LOG (" cache = %d", cache); SWFDEC_LOG (" has filter = %d", has_filter); SWFDEC_LOG (" has blend mode = %d", has_blend_mode); } /* 2) read all properties */ depth = swfdec_bits_get_u16 (bits); if (depth >= 16384) { SWFDEC_FIXME ("depth of placement too high: %u >= 16384", depth); } SWFDEC_LOG (" depth = %d (=> %d)", depth, depth - 16384); depth -= 16384; if (has_character) { id = swfdec_bits_get_u16 (bits); SWFDEC_LOG (" id = %d", id); } else { id = 0; } if (has_transform) { swfdec_bits_get_matrix (bits, &transform, NULL); SWFDEC_LOG (" matrix = { %g %g, %g %g } + { %g %g }", transform.xx, transform.yx, transform.xy, transform.yy, transform.x0, transform.y0); } if (has_ctrans) { swfdec_bits_get_color_transform (bits, &ctrans); SWFDEC_LOG (" color transform = %d %d %d %d %d %d %d %d", ctrans.ra, ctrans.rb, ctrans.ga, ctrans.gb, ctrans.ba, ctrans.bb, ctrans.aa, ctrans.ab); } if (has_ratio) { ratio = swfdec_bits_get_u16 (bits); SWFDEC_LOG (" ratio = %d", ratio); } else { ratio = -1; } if (has_name) { char *s = swfdec_bits_get_string_with_version (bits, version); name = swfdec_as_context_give_string (SWFDEC_AS_CONTEXT (player), s); SWFDEC_LOG (" name = %s", name); } else { name = NULL; } if (has_clip_depth) { clip_depth = swfdec_bits_get_u16 (bits) - 16384; SWFDEC_LOG (" clip_depth = %d (=> %d)", clip_depth + 16384, clip_depth); } else { clip_depth = 0; } if (has_filter) swfdec_filters_parse (bits); if (has_blend_mode) { /* FIXME: implement */ guint operator = swfdec_bits_get_u8 (bits); swfdec_sprite_convert_operator (operator); SWFDEC_ERROR (" operator = %u", operator); } if (has_clip_actions) { int reserved, clip_event_flags, event_flags, key_code; char *script_name; events = swfdec_event_list_new (player); reserved = swfdec_bits_get_u16 (bits); clip_event_flags = swfdec_get_clipeventflags (mov, bits); if (name) script_name = g_strdup (name); else if (id) script_name = g_strdup_printf ("Sprite%u", id); else script_name = g_strdup ("unknown"); while ((event_flags = swfdec_get_clipeventflags (mov, bits)) != 0) { guint length = swfdec_bits_get_u32 (bits); SwfdecBits action_bits; swfdec_bits_init_bits (&action_bits, bits, length); if (event_flags & SWFDEC_EVENT_KEY_PRESS) key_code = swfdec_bits_get_u8 (&action_bits); else key_code = 0; SWFDEC_INFO ("clip event with flags 0x%X, key code %d", event_flags, key_code);#define SWFDEC_IMPLEMENTED_EVENTS \ (SWFDEC_EVENT_LOAD | SWFDEC_EVENT_UNLOAD | SWFDEC_EVENT_ENTER | SWFDEC_EVENT_INITIALIZE | SWFDEC_EVENT_CONSTRUCT | \ SWFDEC_EVENT_MOUSE_DOWN | SWFDEC_EVENT_MOUSE_MOVE | SWFDEC_EVENT_MOUSE_UP) if (event_flags & ~SWFDEC_IMPLEMENTED_EVENTS) { SWFDEC_ERROR ("using non-implemented clip events %u", event_flags & ~SWFDEC_IMPLEMENTED_EVENTS); } swfdec_event_list_parse (events, &action_bits, version, event_flags, key_code, script_name); if (swfdec_bits_left (&action_bits)) { SWFDEC_ERROR ("not all action data was parsed: %u bytes left", swfdec_bits_left (&action_bits)); } } g_free (script_name); } else { events = NULL; } /* 3) perform the actions depending on the set properties */ cur = swfdec_movie_find (mov, depth); graphic = swfdec_swf_decoder_get_character (SWFDEC_SWF_DECODER (mov->swf->decoder), id); if (move) { if (cur == NULL) { SWFDEC_INFO ("no movie at depth %d, ignoring move command", depth); goto out; } if (graphic) { SwfdecMovieClass *klass = SWFDEC_MOVIE_GET_CLASS (cur); if (klass->replace) klass->replace (cur, graphic); } swfdec_movie_set_static_properties (cur, has_transform ? &transform : NULL, has_ctrans ? &ctrans : NULL, ratio, clip_depth, events); } else { if (cur != NULL && version > 5) { SWFDEC_INFO ("depth %d is already occupied by movie %s, not placing", depth, cur->name); goto out; } if (!SWFDEC_IS_GRAPHIC (graphic)) { SWFDEC_FIXME ("character %u is not a graphic (does it even exist?), aborting", id); if (events) swfdec_event_list_free (events); return FALSE; } cur = swfdec_movie_new (player, depth, mov, graphic, name); swfdec_movie_set_static_properties (cur, has_transform ? &transform : NULL, has_ctrans ? &ctrans : NULL, ratio, clip_depth, events); if (SWFDEC_IS_SPRITE_MOVIE (cur)) { g_queue_push_tail (player->init_queue, cur); g_queue_push_tail (player->construct_queue, cur); swfdec_movie_queue_script (cur, SWFDEC_EVENT_LOAD); } swfdec_movie_initialize (cur); }out: if (events) swfdec_event_list_free (events); return TRUE;}static gbooleanswfdec_sprite_movie_perform_one_action (SwfdecSpriteMovie *movie, guint tag, SwfdecBuffer *buffer, gboolean skip_scripts){ SwfdecMovie *mov = SWFDEC_MOVIE (movie); SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (mov)->context); SwfdecBits bits; g_assert (mov->swf); swfdec_bits_init (&bits, buffer); SWFDEC_LOG ("%p: executing %uth tag %s in frame %u", movie, movie->next_action - 1, swfdec_swf_decoder_get_tag_name (tag), movie->frame); switch (tag) { case SWFDEC_TAG_DOACTION: SWFDEC_LOG ("SCRIPT action"); if (!skip_scripts) { SwfdecScript *script = swfdec_swf_decoder_get_script ( SWFDEC_SWF_DECODER (mov->swf->decoder), buffer->data); g_assert (script); swfdec_player_add_action (player, mov, swfdec_sprite_movie_run_script, script); } return TRUE; case SWFDEC_TAG_PLACEOBJECT2: case SWFDEC_TAG_PLACEOBJECT3: return swfdec_sprite_movie_perform_place (movie, &bits, tag); case SWFDEC_TAG_REMOVEOBJECT: /* yes, this code is meant to be like this - the following u16 is the * character id, that we don't care about, the rest is like RemoveObject2 */ swfdec_bits_get_u16 (&bits); /* fall through */ case SWFDEC_TAG_REMOVEOBJECT2: { int depth = swfdec_bits_get_u16 (&bits); SWFDEC_LOG ("REMOVE action: depth %d => %d", depth, depth - 16384); depth -= 16384; if (!swfdec_sprite_movie_remove_child (mov, depth)) SWFDEC_INFO ("could not remove, no child at depth %d", depth); } return TRUE; case SWFDEC_TAG_SHOWFRAME: if (movie->frame < movie->n_frames) { movie->frame++; } else { SWFDEC_ERROR ("too many ShowFrame tags"); } return FALSE; default: g_assert_not_reached (); return FALSE; }}static gbooleanswfdec_movie_is_compatible (SwfdecMovie *movie, SwfdecMovie *with){ g_assert (movie->depth == with->depth); if (movie->original_ratio != with->original_ratio) return FALSE; if (G_OBJECT_TYPE (movie) != G_OBJECT_TYPE (with)) return FALSE; return TRUE;}static GList *my_g_list_split (GList *list, GList *split){ GList *prev;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -