⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swfdec_movie.c

📁 Swfdec is a decoder/renderer for Macromedia Flash animations. The decoding and rendering engine is
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Swfdec * Copyright (C) 2006-2007 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 <math.h>#include <stdlib.h>#include <string.h>#include <strings.h>#include <errno.h>#include "swfdec_movie.h"#include "swfdec_as_context.h"#include "swfdec_as_strings.h"#include "swfdec_button_movie.h"#include "swfdec_debug.h"#include "swfdec_event.h"#include "swfdec_graphic.h"#include "swfdec_loader_internal.h"#include "swfdec_player_internal.h"#include "swfdec_sprite.h"#include "swfdec_sprite_movie.h"#include "swfdec_swf_instance.h"/*** MOVIE ***/enum {  PROP_0,  PROP_DEPTH};G_DEFINE_ABSTRACT_TYPE (SwfdecMovie, swfdec_movie, SWFDEC_TYPE_AS_OBJECT)static voidswfdec_movie_init (SwfdecMovie * movie){  movie->xscale = 100;  movie->yscale = 100;  cairo_matrix_init_identity (&movie->original_transform);  cairo_matrix_init_identity (&movie->matrix);  cairo_matrix_init_identity (&movie->inverse_matrix);  swfdec_color_transform_init_identity (&movie->color_transform);  swfdec_color_transform_init_identity (&movie->original_ctrans);  movie->visible = TRUE;  swfdec_rect_init_empty (&movie->extents);}/** * swfdec_movie_invalidate: * @movie: movie to invalidate * * Invalidates the area currently occupied by movie. If the area this movie * occupies has changed, call swfdec_movie_queue_update () instead. **/voidswfdec_movie_invalidate (SwfdecMovie *movie){  SwfdecRect rect = movie->extents;  SWFDEC_LOG ("invalidating %g %g  %g %g", rect.x0, rect.y0, rect.x1, rect.y1);  if (swfdec_rect_is_empty (&rect))    return;  while (movie->parent) {    movie = movie->parent;    if (movie->cache_state > SWFDEC_MOVIE_INVALID_EXTENTS)      return;    swfdec_rect_transform (&rect, &rect, &movie->matrix);  }  swfdec_player_invalidate (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context), &rect);}/** * swfdec_movie_queue_update: * @movie: a #SwfdecMovie * @state: how much needs to be updated * * Queues an update of all cached values inside @movie and invalidates it. **/voidswfdec_movie_queue_update (SwfdecMovie *movie, SwfdecMovieCacheState state){  g_return_if_fail (SWFDEC_IS_MOVIE (movie));  if (movie->cache_state < SWFDEC_MOVIE_INVALID_EXTENTS &&      state >= SWFDEC_MOVIE_INVALID_EXTENTS)    swfdec_movie_invalidate (movie);  while (movie && movie->cache_state < state) {    movie->cache_state = state;    movie = movie->parent;    state = SWFDEC_MOVIE_INVALID_CHILDREN;  }}static voidswfdec_movie_update_extents (SwfdecMovie *movie){  SwfdecMovieClass *klass;  GList *walk;  SwfdecRect *rect = &movie->original_extents;  SwfdecRect *extents = &movie->extents;  swfdec_rect_init_empty (rect);  for (walk = movie->list; walk; walk = walk->next) {    swfdec_rect_union (rect, rect, &SWFDEC_MOVIE (walk->data)->extents);  }  klass = SWFDEC_MOVIE_GET_CLASS (movie);  if (klass->update_extents)    klass->update_extents (movie, rect);  if (swfdec_rect_is_empty (rect)) {    *extents = *rect;    return;  }  swfdec_rect_transform (extents, rect, &movie->matrix);  if (movie->parent && movie->parent->cache_state < SWFDEC_MOVIE_INVALID_EXTENTS) {    /* no need to invalidate here */    movie->parent->cache_state = SWFDEC_MOVIE_INVALID_EXTENTS;  }}static voidswfdec_movie_update_matrix (SwfdecMovie *movie){  double d, e;  /* we operate on x0 and y0 when setting movie._x and movie._y */  if (movie->modified) {    movie->matrix.xx = movie->original_transform.xx;    movie->matrix.yx = movie->original_transform.yx;    movie->matrix.xy = movie->original_transform.xy;    movie->matrix.yy = movie->original_transform.yy;  } else {    movie->matrix = movie->original_transform;  }  d = movie->xscale / swfdec_matrix_get_xscale (&movie->original_transform);  e = movie->yscale / swfdec_matrix_get_yscale (&movie->original_transform);  cairo_matrix_scale (&movie->matrix, d, e);  if (isfinite (movie->rotation)) {    d = movie->rotation - swfdec_matrix_get_rotation (&movie->original_transform);    cairo_matrix_rotate (&movie->matrix, d * G_PI / 180);  }  swfdec_matrix_ensure_invertible (&movie->matrix, &movie->inverse_matrix);  swfdec_movie_update_extents (movie);}static voidswfdec_movie_do_update (SwfdecMovie *movie){  GList *walk;  for (walk = movie->list; walk; walk = walk->next) {    SwfdecMovie *child = walk->data;    if (child->cache_state != SWFDEC_MOVIE_UP_TO_DATE)      swfdec_movie_do_update (child);  }  switch (movie->cache_state) {    case SWFDEC_MOVIE_INVALID_CHILDREN:      break;    case SWFDEC_MOVIE_INVALID_EXTENTS:      swfdec_movie_update_extents (movie);      break;    case SWFDEC_MOVIE_INVALID_MATRIX:      swfdec_movie_update_matrix (movie);      break;    case SWFDEC_MOVIE_UP_TO_DATE:    default:      g_assert_not_reached ();  }  if (movie->cache_state > SWFDEC_MOVIE_INVALID_EXTENTS)    swfdec_movie_invalidate (movie);  movie->cache_state = SWFDEC_MOVIE_UP_TO_DATE;}/** * swfdec_movie_update: * @movie: a #SwfdecMovie * * Brings the cached values of @movie up-to-date if they are not. This includes * transformation matrices and extents. It needs to be called before accessing * the relevant values. **/voidswfdec_movie_update (SwfdecMovie *movie){  g_return_if_fail (SWFDEC_IS_MOVIE (movie));  if (movie->cache_state == SWFDEC_MOVIE_UP_TO_DATE)    return;  if (movie->parent && movie->parent->cache_state != SWFDEC_MOVIE_UP_TO_DATE) {    swfdec_movie_update (movie->parent);  } else {    swfdec_movie_do_update (movie);  }}SwfdecMovie *swfdec_movie_find (SwfdecMovie *movie, int depth){  GList *walk;  g_return_val_if_fail (SWFDEC_IS_MOVIE (movie), NULL);  for (walk = movie->list; walk; walk = walk->next) {    SwfdecMovie *cur= walk->data;    if (cur->depth < depth)      continue;    if (cur->depth == depth)      return cur;    break;  }  return NULL;}static gbooleanswfdec_movie_do_remove (SwfdecMovie *movie){  SwfdecPlayer *player;  SWFDEC_LOG ("removing %s %s", G_OBJECT_TYPE_NAME (movie), movie->name);  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);  movie->will_be_removed = TRUE;  while (movie->list) {    GList *walk = movie->list;    while (walk && SWFDEC_MOVIE (walk->data)->will_be_removed)      walk = walk->next;    if (walk == NULL)      break;    swfdec_movie_remove (walk->data);  }  /* FIXME: all of this here or in destroy callback? */  if (player->mouse_grab == movie)    player->mouse_grab = NULL;  if (player->mouse_drag == movie)    player->mouse_drag = NULL;  swfdec_movie_invalidate (movie);  swfdec_movie_set_depth (movie, -32769 - movie->depth); /* don't ask me why... */  if (SWFDEC_IS_SPRITE_MOVIE (movie))    return !swfdec_movie_queue_script (movie, SWFDEC_EVENT_UNLOAD);  else    return TRUE;}/** * swfdec_movie_remove: * @movie: #SwfdecMovie to remove * * Removes this movie from its parent. In contrast to swfdec_movie_destroy (), * it will definitely cause a removal from the display list, but depending on * movie, it might still be possible to reference it from Actionscript. **/voidswfdec_movie_remove (SwfdecMovie *movie){  gboolean result;  g_return_if_fail (SWFDEC_IS_MOVIE (movie));  if (movie->state > SWFDEC_MOVIE_STATE_RUNNING)    return;  result = swfdec_movie_do_remove (movie);  movie->state = SWFDEC_MOVIE_STATE_REMOVED;  if (result)    swfdec_movie_destroy (movie);}/** * swfdec_movie_destroy: * @movie: #SwfdecMovie to destroy * * Removes this movie from its parent. After this it will no longer be present, * neither visually nor via ActionScript. This function will not cause an  * unload event. Compare with swfdec_movie_destroy (). **/voidswfdec_movie_destroy (SwfdecMovie *movie){  SwfdecMovieClass *klass = SWFDEC_MOVIE_GET_CLASS (movie);  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);  g_assert (movie->state < SWFDEC_MOVIE_STATE_DESTROYED);  if (movie->state < SWFDEC_MOVIE_STATE_REMOVED) {    swfdec_movie_do_remove (movie);  }  SWFDEC_LOG ("destroying movie %s", movie->name);  while (movie->list) {    swfdec_movie_destroy (movie->list->data);  }  if (movie->parent) {    movie->parent->list = g_list_remove (movie->parent->list, movie);  } else {    player->roots = g_list_remove (player->roots, movie);  }  /* FIXME: figure out how to handle destruction pre-init/construct.   * This is just a stop-gap measure to avoid dead movies in those queues */  g_queue_remove (player->init_queue, movie);  g_queue_remove (player->construct_queue, movie);  swfdec_player_remove_all_actions (player, movie);  if (klass->finish_movie)    klass->finish_movie (movie);  player->movies = g_list_remove (player->movies, movie);  movie->state = SWFDEC_MOVIE_STATE_DESTROYED;  /* unset prototype here, so we don't work in AS anymore */  SWFDEC_AS_OBJECT (movie)->prototype = NULL;  g_object_unref (movie);}/** * swfdec_movie_run_init: * @movie: a #SwfdecMovie * * Runs onClipEvent(initialize) on the given @movie. */voidswfdec_movie_run_init (SwfdecMovie *movie){  SwfdecPlayer *player;  g_return_if_fail (SWFDEC_IS_MOVIE (movie));  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);  g_queue_remove (player->init_queue, movie);  swfdec_movie_execute_script (movie, SWFDEC_EVENT_INITIALIZE);}/** * swfdec_movie_run_construct: * @movie: a #SwfdecMovie * * Runs the constructors for @movie. This is (in the given order)  * onClipEvent(construct), movie.onConstruct and the constructor registered * via Object.registerClass. **/voidswfdec_movie_run_construct (SwfdecMovie *movie){  SwfdecPlayer *player;  g_return_if_fail (SWFDEC_IS_MOVIE (movie));  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);  g_queue_remove (player->construct_queue, movie);  swfdec_movie_execute_script (movie, SWFDEC_EVENT_CONSTRUCT);  swfdec_as_object_call (SWFDEC_AS_OBJECT (movie), SWFDEC_AS_STR_constructor, 0, NULL, NULL);}voidswfdec_movie_execute_script (SwfdecMovie *movie, SwfdecEventType condition){  const char *name;  g_return_if_fail (SWFDEC_IS_MOVIE (movie));  g_return_if_fail (condition != 0);  if (movie->events) {    swfdec_event_list_execute (movie->events, 	SWFDEC_AS_OBJECT (movie), condition, 0);  }  name = swfdec_event_type_get_name (condition);  if (name != NULL)    swfdec_as_object_call (SWFDEC_AS_OBJECT (movie), name, 0, NULL, NULL);}static voidswfdec_movie_do_execute_script (gpointer movie, gpointer condition){  swfdec_movie_execute_script (movie, GPOINTER_TO_UINT (condition));}/** * swfdec_movie_queue_script: * @movie: a #SwfdecMovie * @condition: the event that should happen * * Queues execution of all scripts associated with the given event. * * Returns: TRUE if there were any such events **/gbooleanswfdec_movie_queue_script (SwfdecMovie *movie, SwfdecEventType condition){  SwfdecPlayer *player;    g_return_val_if_fail (SWFDEC_IS_MOVIE (movie), FALSE);  g_return_val_if_fail (condition != 0, FALSE);  if (movie->events) {    if (!swfdec_event_list_has_conditions (movie->events, 	  SWFDEC_AS_OBJECT (movie), condition, 0))      return FALSE;  } else {    const char *name = swfdec_event_type_get_name (condition);    if (name == NULL ||	!swfdec_as_object_has_function (SWFDEC_AS_OBJECT (movie), name))      return FALSE;  }  player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context);  swfdec_player_add_action (player, movie, swfdec_movie_do_execute_script,       GUINT_TO_POINTER (condition));  return TRUE;}/**

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -