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

📄 swfdec_movie.c

📁 Swfdec still is development software, but has also followed a rigid no-crashes-allowed policy. I b
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 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 <string.h>#include <math.h>#include <js/jsapi.h>#include "swfdec_movie.h"#include "swfdec_debug.h"#include "swfdec_debugger.h"#include "swfdec_event.h"#include "swfdec_graphic.h"#include "swfdec_js.h"#include "swfdec_player_internal.h"#include "swfdec_root_movie.h"#include "swfdec_sprite.h"/*** MOVIE ***/static const SwfdecContent default_content = SWFDEC_CONTENT_DEFAULT;G_DEFINE_ABSTRACT_TYPE (SwfdecMovie, swfdec_movie, SWFDEC_TYPE_SCRIPTABLE)static voidswfdec_movie_init (SwfdecMovie * movie){  movie->content = &default_content;  movie->xscale = 100;  movie->yscale = 100;  cairo_matrix_init_identity (&movie->matrix);  cairo_matrix_init_identity (&movie->inverse_matrix);  swfdec_color_transform_init_identity (&movie->color_transform);  movie->visible = TRUE;  movie->n_frames = 1;  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_ROOT_MOVIE (movie)->player, &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, SwfdecMovieState 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;  movie->matrix.xx = movie->content->transform.xx;  movie->matrix.xy = movie->content->transform.xy;  movie->matrix.yx = movie->content->transform.yx;  movie->matrix.yy = movie->content->transform.yy;  d = movie->xscale / swfdec_matrix_get_xscale (&movie->content->transform);  e = movie->yscale / swfdec_matrix_get_yscale (&movie->content->transform);  cairo_matrix_scale (&movie->matrix, d, e);  d = movie->rotation - swfdec_matrix_get_rotation (&movie->content->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);  }}/** * swfdec_movie_set_content: * @movie: a #SwfdecMovie * @content: #SwfdecContent to set for this movie or NULL to unset * * Sets new contents for @movie. Note that name and graphic of @content must  * be identical to the current content of @movie. **/voidswfdec_movie_set_content (SwfdecMovie *movie, const SwfdecContent *content){  const SwfdecContent *old_content;  SwfdecMovieClass *klass;  g_return_if_fail (SWFDEC_IS_MOVIE (movie));  if (movie->content == content)    return;  if (content == NULL) {    content = &default_content;  } else if (movie->content != &default_content) {    g_return_if_fail (movie->depth == content->depth);    g_return_if_fail (movie->content->graphic == content->graphic);    if (content->name) {      g_return_if_fail (movie->content->name != NULL);      g_return_if_fail (g_str_equal (content->name, movie->content->name));    } else {      g_return_if_fail (movie->content->name == NULL);    }  }  SWFDEC_LOG ("setting content of movie %s from %p to %p",       movie->name, movie->content, content);  old_content = movie->content;  klass = SWFDEC_MOVIE_GET_CLASS (movie);  if (klass->content_changed)    klass->content_changed (movie, content);  movie->content = content;  if (!movie->modified) {    movie->matrix = content->transform;    movie->xscale = swfdec_matrix_get_xscale (&movie->matrix);    movie->yscale = swfdec_matrix_get_yscale (&movie->matrix);    movie->rotation = swfdec_matrix_get_rotation (&movie->matrix);    swfdec_movie_queue_update (movie, SWFDEC_MOVIE_INVALID_MATRIX);  }}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 *movie = walk->data;    if (movie->depth < depth)      continue;    if (movie->depth == depth)      return movie;    break;  }  return NULL;}typedef void (* SwfdecMovieRemoveFunc) (SwfdecMovie *, gpointer);static voidswfdec_movie_do_remove (SwfdecMovie *movie, gpointer child_remove){  movie->will_be_removed = TRUE;  /* remove all children */  while (movie->list) {    (*(SwfdecMovieRemoveFunc) child_remove) (movie->list->data, child_remove);  }  if (SWFDEC_ROOT_MOVIE (movie->root)->player->mouse_grab == movie)    SWFDEC_ROOT_MOVIE (movie->root)->player->mouse_grab = NULL;  if (SWFDEC_ROOT_MOVIE (movie->root)->player->mouse_drag == movie)    SWFDEC_ROOT_MOVIE (movie->root)->player->mouse_drag = NULL;  swfdec_movie_invalidate (movie);  if (movie->parent) {    SwfdecPlayer *player = SWFDEC_ROOT_MOVIE (movie->root)->player;    if (SWFDEC_IS_DEBUGGER (player) &&	g_list_find (movie->parent->list, movie)) {      movie->parent->list = g_list_remove (movie->parent->list, movie);      g_signal_emit_by_name (player, "movie-removed", movie);    } else {      movie->parent->list = g_list_remove (movie->parent->list, movie);    }  } else {    SwfdecPlayer *player = SWFDEC_ROOT_MOVIE (movie)->player;    if (SWFDEC_IS_DEBUGGER (player) &&	g_list_find (player->roots, movie)) {      player->roots = g_list_remove (player->roots, movie);      g_signal_emit_by_name (player, "movie-removed", movie);    } else {      player->roots = g_list_remove (player->roots, 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_ROOT_MOVIE (movie->root)->player;  SWFDEC_LOG ("destroying movie %s", movie->name);  swfdec_movie_do_remove (movie, swfdec_movie_destroy);  swfdec_movie_set_content (movie, NULL);  if (klass->finish_movie)    klass->finish_movie (movie);  swfdec_js_movie_remove_jsobject (movie);  player->movies = g_list_remove (player->movies, movie);  g_object_unref (movie);}/** * 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){  g_return_if_fail (SWFDEC_IS_MOVIE (movie));  SWFDEC_LOG ("removing %s %s", G_OBJECT_TYPE_NAME (movie), movie->name);  swfdec_movie_do_remove (movie, swfdec_movie_remove);  if (!swfdec_movie_queue_script (movie, SWFDEC_EVENT_UNLOAD))    swfdec_movie_destroy (movie);}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->content->events) {    swfdec_event_list_execute (movie->content->events, 	SWFDEC_SCRIPTABLE (movie), condition, 0);  }  name = swfdec_event_type_get_name (condition);  if (name != NULL)    swfdec_scriptable_execute (SWFDEC_SCRIPTABLE (movie), name, 0, 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->content->events) {    if (!swfdec_event_list_has_conditions (movie->content->events, 	  SWFDEC_SCRIPTABLE (movie), condition, 0))      return FALSE;  } else {    const char *name = swfdec_event_type_get_name (condition);    if (name == NULL ||	!swfdec_scriptable_can_execute (SWFDEC_SCRIPTABLE (movie), name))      return FALSE;  }  player = SWFDEC_ROOT_MOVIE (movie->root)->player;  swfdec_player_add_action (player, movie, swfdec_movie_do_execute_script,       GUINT_TO_POINTER (condition));  return TRUE;}/* NB: coordinates are in movie's coordiante system. Use swfdec_movie_get_mouse * if you have global coordinates */static gbooleanswfdec_movie_mouse_in (SwfdecMovie *movie, double x, double y){  SwfdecMovieClass *klass;  klass = SWFDEC_MOVIE_GET_CLASS (movie);  if (klass->mouse_in == NULL)    return FALSE;  return klass->mouse_in (movie, x, y);}voidswfdec_movie_local_to_global (SwfdecMovie *movie, double *x, double *y){  do {    cairo_matrix_transform_point (&movie->matrix, x, y);  } while ((movie = movie->parent));}voidswfdec_movie_global_to_local (SwfdecMovie *movie, double *x, double *y){  if (movie->parent)    swfdec_movie_global_to_local (movie->parent, x, y);  if (movie->cache_state >= SWFDEC_MOVIE_INVALID_MATRIX)    swfdec_movie_update (movie);  cairo_matrix_transform_point (&movie->inverse_matrix, x, y);}/** * swfdec_movie_get_mouse: * @movie: a #SwfdecMovie * @x: pointer to hold result of X coordinate * @y: pointer to hold result of y coordinate * * Gets the mouse coordinates in the coordinate space of @movie. **/

⌨️ 快捷键说明

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