📄 swfdec_movie.c
字号:
}/* FIXME: This function can definitely be implemented easier */static SwfdecMovie *swfdec_movie_get_by_name (SwfdecPlayer *player, const char *name){ GList *walk; int i = SWFDEC_AS_CONTEXT (player)->version; gulong l; char *end; if ((i >= 7 && !g_str_has_prefix (name, "_level")) || strncasecmp (name, "_level", 6) != 0) return NULL; errno = 0; l = strtoul (name + 6, &end, 10); if (errno != 0 || *end != 0 || l > G_MAXINT) return NULL; i = l - 16384; for (walk = player->roots; walk; walk = walk->next) { SwfdecMovie *cur = walk->data; if (cur->depth < i) continue; if (cur->depth == i) return cur; break; } return NULL;}static gbooleanswfdec_movie_get_variable (SwfdecAsObject *object, SwfdecAsObject *orig, const char *variable, SwfdecAsValue *val, guint *flags){ SwfdecMovie *movie = SWFDEC_MOVIE (object); if (movie->state == SWFDEC_MOVIE_STATE_DESTROYED) return FALSE; if (SWFDEC_AS_OBJECT_CLASS (swfdec_movie_parent_class)->get (object, orig, variable, val, flags)) return TRUE; if (swfdec_movie_get_asprop (movie, variable, val)) { *flags = 0; return TRUE; } /* FIXME: check that this is correct */ if (object->context->version > 5 && variable == SWFDEC_AS_STR__global) { SWFDEC_AS_VALUE_SET_OBJECT (val, object->context->global); *flags = 0; return TRUE; } movie = swfdec_movie_get_by_name (SWFDEC_PLAYER (object->context), variable); if (movie) { SWFDEC_AS_VALUE_SET_OBJECT (val, SWFDEC_AS_OBJECT (movie)); *flags = 0; return TRUE; } return FALSE;}static voidswfdec_movie_set_variable (SwfdecAsObject *object, const char *variable, const SwfdecAsValue *val, guint flags){ SwfdecMovie *movie = SWFDEC_MOVIE (object); if (movie->state == SWFDEC_MOVIE_STATE_DESTROYED) return; if (swfdec_movie_set_asprop (movie, variable, val)) return; SWFDEC_AS_OBJECT_CLASS (swfdec_movie_parent_class)->set (object, variable, val, flags);}static char *swfdec_movie_get_debug (SwfdecAsObject *object){ SwfdecMovie *movie = SWFDEC_MOVIE (object); return swfdec_movie_get_path (movie);}static gbooleanswfdec_movie_iterate_end (SwfdecMovie *movie){ return movie->parent == NULL || movie->state < SWFDEC_MOVIE_STATE_REMOVED;}static voidswfdec_movie_class_init (SwfdecMovieClass * movie_class){ GObjectClass *object_class = G_OBJECT_CLASS (movie_class); SwfdecAsObjectClass *asobject_class = SWFDEC_AS_OBJECT_CLASS (movie_class); object_class->dispose = swfdec_movie_dispose; object_class->get_property = swfdec_movie_get_property; object_class->set_property = swfdec_movie_set_property; asobject_class->mark = swfdec_movie_mark; asobject_class->get = swfdec_movie_get_variable; asobject_class->set = swfdec_movie_set_variable; asobject_class->debug = swfdec_movie_get_debug; g_object_class_install_property (object_class, PROP_DEPTH, g_param_spec_int ("depth", "depth", "z order inside the parent", G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); movie_class->iterate_end = swfdec_movie_iterate_end;}voidswfdec_movie_initialize (SwfdecMovie *movie){ SwfdecMovieClass *klass; g_return_if_fail (SWFDEC_IS_MOVIE (movie)); klass = SWFDEC_MOVIE_GET_CLASS (movie); if (klass->init_movie) klass->init_movie (movie);}voidswfdec_movie_set_depth (SwfdecMovie *movie, int depth){ g_return_if_fail (SWFDEC_IS_MOVIE (movie)); if (movie->depth == depth) return; swfdec_movie_invalidate (movie); movie->depth = depth; if (movie->parent) { movie->parent->list = g_list_sort (movie->parent->list, swfdec_movie_compare_depths); } else { SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context); player->roots = g_list_sort (player->roots, swfdec_movie_compare_depths); } g_object_notify (G_OBJECT (movie), "depth");}/** * swfdec_movie_new: * @player: a #SwfdecPlayer * @depth: depth of movie * @parent: the parent movie or %NULL to make this a root movie * @graphic: the graphic that is displayed by this movie or %NULL to create an * empty movieclip * @name: a garbage-collected string to be used as the name for this movie or * %NULL for a default one. * * Creates a new movie #SwfdecMovie for the given properties. No movie may exist * at the given @depth. The actual type of * this movie depends on the @graphic parameter. The movie will be initialized * with default properties. No script execution will be scheduled. After all * properties are set, the new-movie signal will be emitted if @player is a * debugger. * * Returns: a new #SwfdecMovie **/SwfdecMovie *swfdec_movie_new (SwfdecPlayer *player, int depth, SwfdecMovie *parent, SwfdecGraphic *graphic, const char *name){ SwfdecMovie *movie; gsize size; g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL); g_return_val_if_fail (parent == NULL || SWFDEC_IS_MOVIE (parent), NULL); g_return_val_if_fail (graphic == NULL || SWFDEC_IS_GRAPHIC (graphic), NULL); /* create the right movie */ if (graphic == NULL) { movie = g_object_new (SWFDEC_TYPE_SPRITE_MOVIE, "depth", depth, NULL); size = sizeof (SwfdecSpriteMovie); } else { SwfdecGraphicClass *klass = SWFDEC_GRAPHIC_GET_CLASS (graphic); g_return_val_if_fail (klass->create_movie != NULL, NULL); movie = klass->create_movie (graphic, &size); movie->graphic = g_object_ref (graphic); movie->depth = depth; } /* register it to the VM */ /* FIXME: It'd be nice if we'd not overuse memory here when calling this function from a script */ if (!swfdec_as_context_use_mem (SWFDEC_AS_CONTEXT (player), size)) { size = 0; } g_object_ref (movie); /* set essential properties */ movie->parent = parent; if (parent) { movie->swf = g_object_ref (parent->swf); parent->list = g_list_insert_sorted (parent->list, movie, swfdec_movie_compare_depths); SWFDEC_DEBUG ("inserting %s %s (depth %d) into %s %p", G_OBJECT_TYPE_NAME (movie), movie->name, movie->depth, G_OBJECT_TYPE_NAME (parent), parent); } else { player->roots = g_list_insert_sorted (player->roots, movie, swfdec_movie_compare_depths); } /* set its name */ if (name) { movie->original_name = name; movie->name = name; } else { movie->original_name = SWFDEC_AS_STR_EMPTY; if (SWFDEC_IS_SPRITE_MOVIE (movie) || SWFDEC_IS_BUTTON_MOVIE (movie)) { movie->name = swfdec_as_context_give_string (SWFDEC_AS_CONTEXT (player), g_strdup_printf ("instance%u", ++player->unnamed_count)); } else { movie->name = SWFDEC_AS_STR_EMPTY; } } /* add the movie to the global movies list */ /* NB: adding to the movies list happens before setting the parent. * Setting the parent does a gotoAndPlay(0) for Sprites which can cause * new movies to be created (and added to this list) */ player->movies = g_list_prepend (player->movies, movie); /* only add the movie here, because it needs to be setup for the debugger */ swfdec_as_object_add (SWFDEC_AS_OBJECT (movie), SWFDEC_AS_CONTEXT (player), size); return movie;}/* FIXME: since this is only used in PlaceObject, wouldn't it be easier to just have * swfdec_movie_update_static_properties (movie); that's notified when any of these change * and let PlaceObject modify the movie directly? */voidswfdec_movie_set_static_properties (SwfdecMovie *movie, const cairo_matrix_t *transform, const SwfdecColorTransform *ctrans, int ratio, int clip_depth, SwfdecEventList *events){ g_return_if_fail (SWFDEC_IS_MOVIE (movie)); g_return_if_fail (clip_depth >= -16384 || clip_depth <= 0); g_return_if_fail (ratio >= -1); if (movie->modified) { SWFDEC_LOG ("%s has already been modified by scripts, ignoring updates", movie->name); return; } if (transform) { movie->original_transform = *transform; movie->matrix.x0 = movie->original_transform.x0; movie->matrix.y0 = movie->original_transform.y0; movie->xscale = swfdec_matrix_get_xscale (&movie->original_transform); movie->yscale = swfdec_matrix_get_yscale (&movie->original_transform); movie->rotation = swfdec_matrix_get_rotation (&movie->original_transform); swfdec_movie_queue_update (movie, SWFDEC_MOVIE_INVALID_MATRIX); } if (ctrans) { movie->original_ctrans = *ctrans; swfdec_movie_invalidate (movie); } if (ratio >= 0 && (guint) ratio != movie->original_ratio) { movie->original_ratio = ratio; swfdec_movie_queue_update (movie, SWFDEC_MOVIE_INVALID_EXTENTS); } if (clip_depth && clip_depth != movie->clip_depth) { movie->clip_depth = clip_depth; /* FIXME: is this correct? */ swfdec_movie_invalidate (movie->parent ? movie->parent : movie); } if (events) { if (movie->events) swfdec_event_list_free (movie->events); movie->events = swfdec_event_list_copy (events); }}/** * swfdec_movie_duplicate: * @movie: #SwfdecMovie to copy * @name: garbage-collected name for the new copy * @depth: depth to put this movie in * * Creates a duplicate of @movie. The duplicate will not be initialized or * queued up for any events. You have to do this manually. In particular calling * swfdec_movie_initialize() on the returned movie must be done. * * Returns: a newly created movie or %NULL on error **/SwfdecMovie *swfdec_movie_duplicate (SwfdecMovie *movie, const char *name, int depth){ SwfdecMovie *parent, *copy; g_return_val_if_fail (SWFDEC_IS_MOVIE (movie), NULL); g_return_val_if_fail (name != NULL, NULL); parent = movie->parent; if (movie->parent == NULL) { SWFDEC_FIXME ("don't know how to duplicate root movies"); return NULL; } copy = swfdec_movie_find (movie->parent, depth); if (copy) { SWFDEC_LOG ("depth %d already occupied while duplicating, removing old movie", depth); swfdec_movie_remove (copy); } copy = swfdec_movie_new (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context), depth, parent, movie->graphic, name); if (copy == NULL) return NULL; swfdec_movie_set_static_properties (copy, &movie->original_transform, &movie->original_ctrans, movie->original_ratio, movie->clip_depth, movie->events); return copy;}SwfdecMovie *swfdec_movie_new_for_content (SwfdecMovie *parent, const SwfdecContent *content){ SwfdecPlayer *player; SwfdecMovie *movie; g_return_val_if_fail (SWFDEC_IS_MOVIE (parent), NULL); g_return_val_if_fail (SWFDEC_IS_GRAPHIC (content->graphic), NULL); g_return_val_if_fail (swfdec_movie_find (parent, content->depth) == NULL, NULL); SWFDEC_DEBUG ("new movie for parent %p", parent); player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (parent)->context); movie = swfdec_movie_new (player, content->depth, parent, content->graphic, content->name ? swfdec_as_context_get_string (SWFDEC_AS_CONTEXT (player), content->name) : NULL); swfdec_movie_set_static_properties (movie, content->has_transform ? &content->transform : NULL, content->has_color_transform ? &content->color_transform : NULL, content->ratio, content->clip_depth, content->events); if (SWFDEC_IS_SPRITE_MOVIE (movie)) { g_queue_push_tail (player->init_queue, movie); g_queue_push_tail (player->construct_queue, movie); swfdec_movie_queue_script (movie, SWFDEC_EVENT_LOAD); } swfdec_movie_initialize (movie); return movie;}voidswfdec_movie_load (SwfdecMovie *movie, const char *url, const char *target, SwfdecLoaderRequest request, const char *data, gsize data_len){ SwfdecPlayer *player; g_return_if_fail (SWFDEC_IS_MOVIE (movie)); g_return_if_fail (url != NULL); g_return_if_fail (target != NULL); player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context); /* yay for the multiple uses of GetURL - one of the crappier Flash things */ if (g_str_has_prefix (target, "_level")) { const char *nr = target + strlen ("_level"); char *end; guint depth; errno = 0; depth = strtoul (nr, &end, 10); if (errno == 0 && *end == '\0') { if (url[0] == '\0') { swfdec_player_remove_level (player, depth); } else { SwfdecLoader *loader = swfdec_loader_load (movie->swf->loader, url, request, data, data_len); g_assert (loader); swfdec_player_add_level_from_loader (player, depth, loader, NULL); } } else { SWFDEC_ERROR ("%s does not specify a valid level", target); } /* FIXME: what do we do here? Is returning correct?*/ return; } swfdec_player_launch (player, url, target);}char *swfdec_movie_get_path (SwfdecMovie *movie){ GString *s; g_return_val_if_fail (SWFDEC_IS_MOVIE (movie), NULL); s = g_string_new (""); do { if (movie->parent) { g_string_prepend (s, movie->name); g_string_prepend_c (s, '.'); } else { char *ret = g_strdup_printf ("_level%u%s", movie->depth + 16384, s->str); g_string_free (s, TRUE); return ret; } movie = movie->parent; } while (TRUE); g_assert_not_reached (); return NULL;}intswfdec_movie_compare_depths (gconstpointer a, gconstpointer b){ if (SWFDEC_MOVIE (a)->depth < SWFDEC_MOVIE (b)->depth) return -1; if (SWFDEC_MOVIE (a)->depth > SWFDEC_MOVIE (b)->depth) return 1; return 0;}/** * swfdec_depth_classify: * @depth: the depth to classify * * Classifies a depth. This classification is mostly used when deciding if * certain operations are valid in ActionScript. * * Returns: the classification of the depth. **/SwfdecDepthClassswfdec_depth_classify (int depth){ if (depth < -16384) return SWFDEC_DEPTH_CLASS_EMPTY; if (depth < 0) return SWFDEC_DEPTH_CLASS_TIMELINE; if (depth < 1048576) return SWFDEC_DEPTH_CLASS_DYNAMIC; if (depth < 2130690046) return SWFDEC_DEPTH_CLASS_RESERVED; return SWFDEC_DEPTH_CLASS_EMPTY;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -