📄 swfdec_movie.c
字号:
* swfdec_movie_set_variables: * @script: a #SwfdecMovie * @variables: variables to set on @movie in application-x-www-form-urlencoded * format * * Verifies @variables to be encoded correctly and sets them as string * properties on the given @movie. **/voidswfdec_movie_set_variables (SwfdecMovie *movie, const char *variables){ SwfdecAsObject *as; g_return_if_fail (SWFDEC_IS_MOVIE (movie)); g_return_if_fail (variables != NULL); as = SWFDEC_AS_OBJECT (movie); SWFDEC_DEBUG ("setting variables on %p: %s", movie, variables); while (TRUE) { char *name, *value; const char *asname; SwfdecAsValue val; while (*variables == '&') variables++; if (*variables == '\0') break; if (!swfdec_urldecode_one (variables, &name, &value, &variables)) { SWFDEC_WARNING ("variables invalid at \"%s\"", variables); break; } if (*variables != '\0' && *variables != '&') { SWFDEC_WARNING ("variables not delimited with & at \"%s\"", variables); g_free (name); g_free (value); break; } asname = swfdec_as_context_give_string (as->context, name); SWFDEC_AS_VALUE_SET_STRING (&val, swfdec_as_context_get_string (as->context, value)); g_free (value); swfdec_as_object_set_variable (as, asname, &val); SWFDEC_LOG ("Set variable \"%s\" to \"%s\"", name, value); }}/* NB: coordinates are in movie's coordiante system. Use swfdec_movie_get_mouse * if you have global coordinates */gbooleanswfdec_movie_mouse_in (SwfdecMovie *movie, double x, double y){ SwfdecMovieClass *klass; GList *walk; klass = SWFDEC_MOVIE_GET_CLASS (movie); if (klass->mouse_in != NULL && klass->mouse_in (movie, x, y)) return TRUE; for (walk = movie->list; walk; walk = walk->next) { double tmp_x = x; double tmp_y = y; SwfdecMovie *cur = walk->data; cairo_matrix_transform_point (&cur->inverse_matrix, &tmp_x, &tmp_y); if (swfdec_movie_mouse_in (cur, tmp_x, tmp_y)) return TRUE; } return FALSE;}voidswfdec_movie_local_to_global (SwfdecMovie *movie, double *x, double *y){ g_return_if_fail (SWFDEC_IS_MOVIE (movie)); g_return_if_fail (x != NULL); g_return_if_fail (y != NULL); do { cairo_matrix_transform_point (&movie->matrix, x, y); } while ((movie = movie->parent));}voidswfdec_movie_rect_local_to_global (SwfdecMovie *movie, SwfdecRect *rect){ g_return_if_fail (SWFDEC_IS_MOVIE (movie)); g_return_if_fail (rect != NULL); swfdec_movie_local_to_global (movie, &rect->x0, &rect->y0); swfdec_movie_local_to_global (movie, &rect->x1, &rect->y1); if (rect->x0 > rect->x1) { double tmp = rect->x1; rect->x1 = rect->x0; rect->x0 = tmp; } if (rect->y0 > rect->y1) { double tmp = rect->y1; rect->y1 = rect->y0; rect->y0 = tmp; }}voidswfdec_movie_global_to_local (SwfdecMovie *movie, double *x, double *y){ g_return_if_fail (SWFDEC_IS_MOVIE (movie)); g_return_if_fail (x != NULL); g_return_if_fail (y != NULL); 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);}voidswfdec_movie_rect_global_to_local (SwfdecMovie *movie, SwfdecRect *rect){ g_return_if_fail (SWFDEC_IS_MOVIE (movie)); g_return_if_fail (rect != NULL); swfdec_movie_global_to_local (movie, &rect->x0, &rect->y0); swfdec_movie_global_to_local (movie, &rect->x1, &rect->y1); if (rect->x0 > rect->x1) { double tmp = rect->x1; rect->x1 = rect->x0; rect->x0 = tmp; } if (rect->y0 > rect->y1) { double tmp = rect->y1; rect->y1 = rect->y0; rect->y0 = tmp; }}/** * 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. **/voidswfdec_movie_get_mouse (SwfdecMovie *movie, double *x, double *y){ SwfdecPlayer *player; g_return_if_fail (SWFDEC_IS_MOVIE (movie)); g_return_if_fail (x != NULL); g_return_if_fail (y != NULL); player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context); *x = player->mouse_x; *y = player->mouse_y; swfdec_player_stage_to_global (player, x, y); swfdec_movie_global_to_local (movie, x, y);}voidswfdec_movie_send_mouse_change (SwfdecMovie *movie, gboolean release){ double x, y; gboolean mouse_in; int button; SwfdecMovieClass *klass; swfdec_movie_get_mouse (movie, &x, &y); if (release) { mouse_in = FALSE; button = 0; } else { mouse_in = swfdec_movie_mouse_in (movie, x, y); button = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (movie)->context)->mouse_button; } klass = SWFDEC_MOVIE_GET_CLASS (movie); g_assert (klass->mouse_change != NULL); klass->mouse_change (movie, x, y, mouse_in, button);}/** * swfdec_movie_get_movie_at: * @movie: a #SwfdecMovie * @x: x coordinate in parent's coordinate space * @y: y coordinate in the parent's coordinate space * * Gets the child at the given coordinates. The coordinates are in the * coordinate system of @movie's parent (or the global coordinate system for * root movies). * * Returns: the child of @movie at the given coordinates or %NULL if none **/SwfdecMovie *swfdec_movie_get_movie_at (SwfdecMovie *movie, double x, double y){ GList *walk, *clip_walk; int clip_depth = 0; SwfdecMovie *ret; SwfdecMovieClass *klass; SWFDEC_LOG ("%s %p getting mouse at: %g %g", G_OBJECT_TYPE_NAME (movie), movie, x, y); if (!swfdec_rect_contains (&movie->extents, x, y)) { return NULL; } cairo_matrix_transform_point (&movie->inverse_matrix, &x, &y); /* first check if the movie can handle mouse events, and if it can, * ignore its children. * Dunno if that's correct */ klass = SWFDEC_MOVIE_GET_CLASS (movie); if (klass->mouse_change) { if (swfdec_movie_mouse_in (movie, x, y)) return movie; else return NULL; } for (walk = clip_walk = g_list_last (movie->list); walk; walk = walk->prev) { SwfdecMovie *child = walk->data; if (walk == clip_walk) { clip_depth = 0; for (clip_walk = clip_walk->prev; clip_walk; clip_walk = clip_walk->prev) { SwfdecMovie *clip = walk->data; if (clip->clip_depth) { double tmpx = x, tmpy = y; cairo_matrix_transform_point (&clip->inverse_matrix, &tmpx, &tmpy); if (!swfdec_movie_mouse_in (clip, tmpx, tmpy)) { SWFDEC_LOG ("skipping depth %d to %d due to clipping", clip->depth, clip->clip_depth); clip_depth = child->clip_depth; } break; } } } if (child->clip_depth) { SWFDEC_LOG ("resetting clip depth"); clip_depth = 0; continue; } if (child->depth <= clip_depth && clip_depth) { SWFDEC_DEBUG ("ignoring depth=%d, it's clipped (clip_depth %d)", child->depth, clip_depth); continue; } if (!child->visible) { SWFDEC_LOG ("child %s %s (depth %d) is invisible, ignoring", G_OBJECT_TYPE_NAME (movie), movie->name, movie->depth); continue; } ret = swfdec_movie_get_movie_at (child, x, y); if (ret) return ret; } return NULL;}voidswfdec_movie_render (SwfdecMovie *movie, cairo_t *cr, const SwfdecColorTransform *color_transform, const SwfdecRect *inval, gboolean fill){ SwfdecMovieClass *klass; GList *g; int clip_depth = 0; SwfdecColorTransform trans; SwfdecRect rect; g_return_if_fail (SWFDEC_IS_MOVIE (movie)); g_return_if_fail (cr != NULL); if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) { g_warning ("%s", cairo_status_to_string (cairo_status (cr))); } g_return_if_fail (color_transform != NULL); g_return_if_fail (inval != NULL); if (!swfdec_rect_intersect (NULL, &movie->extents, inval)) { SWFDEC_LOG ("not rendering %s %s, extents %g %g %g %g are not in invalid area %g %g %g %g", G_OBJECT_TYPE_NAME (movie), movie->name, movie->extents.x0, movie->extents.y0, movie->extents.x1, movie->extents.y1, inval->x0, inval->y0, inval->x1, inval->y1); return; } if (!movie->visible) { SWFDEC_LOG ("not rendering %s %p, movie is invisible", G_OBJECT_TYPE_NAME (movie), movie->name); return; } cairo_save (cr); SWFDEC_LOG ("transforming movie, transform: %g %g %g %g %g %g", movie->matrix.xx, movie->matrix.yy, movie->matrix.xy, movie->matrix.yx, movie->matrix.x0, movie->matrix.y0); cairo_transform (cr, &movie->matrix); swfdec_rect_transform (&rect, inval, &movie->inverse_matrix); SWFDEC_LOG ("%sinvalid area is now: %g %g %g %g", movie->parent ? " " : "", rect.x0, rect.y0, rect.x1, rect.y1); swfdec_color_transform_chain (&trans, &movie->original_ctrans, color_transform); swfdec_color_transform_chain (&trans, &movie->color_transform, &trans); for (g = movie->list; g; g = g_list_next (g)) { SwfdecMovie *child = g->data; if (child->clip_depth) { if (clip_depth) { /* FIXME: is clipping additive? */ SWFDEC_INFO ("unsetting clip depth %d for new clip depth", clip_depth); cairo_restore (cr); clip_depth = 0; } if (fill == FALSE) { SWFDEC_WARNING ("clipping inside clipping not implemented"); } else { /* FIXME FIXME FIXME: overlapping objects in the clip movie cause problems * due to them being accumulated with CAIRO_FILL_RULE_EVEN_ODD */ SWFDEC_INFO ("clipping up to depth %d by using %p with depth %d", child->clip_depth, child, child->depth); clip_depth = child->clip_depth; cairo_save (cr); swfdec_movie_render (child, cr, &trans, &rect, FALSE); cairo_clip (cr); continue; } } if (clip_depth && child->depth > clip_depth) { SWFDEC_INFO ("unsetting clip depth %d for depth %d", clip_depth, child->depth); clip_depth = 0; cairo_restore (cr); } SWFDEC_LOG ("rendering %p with depth %d", child, child->depth); swfdec_movie_render (child, cr, &trans, &rect, fill); } if (clip_depth) { SWFDEC_INFO ("unsetting clip depth %d after rendering", clip_depth); clip_depth = 0; cairo_restore (cr); } klass = SWFDEC_MOVIE_GET_CLASS (movie); if (klass->render) klass->render (movie, cr, &trans, &rect, fill);#if 0 /* code to draw a red rectangle around the area occupied by this movie clip */ { double x = 1.0, y = 0.0; cairo_transform (cr, &movie->inverse_transform); cairo_user_to_device_distance (cr, &x, &y); cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); cairo_set_line_width (cr, 1 / sqrt (x * x + y * y)); cairo_rectangle (cr, object->extents.x0 + 10, object->extents.y0 + 10, object->extents.x1 - object->extents.x0 - 20, object->extents.y1 - object->extents.y0 - 20); cairo_stroke (cr); }#endif if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) { g_warning ("error rendering with cairo: %s", cairo_status_to_string (cairo_status (cr))); } cairo_restore (cr);}static voidswfdec_movie_get_property (GObject *object, guint param_id, GValue *value, GParamSpec * pspec){ SwfdecMovie *movie = SWFDEC_MOVIE (object); switch (param_id) { case PROP_DEPTH: g_value_set_int (value, movie->depth); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; }}static voidswfdec_movie_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec * pspec){ SwfdecMovie *movie = SWFDEC_MOVIE (object); switch (param_id) { case PROP_DEPTH: movie->depth = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; }}static voidswfdec_movie_dispose (GObject *object){ SwfdecMovie * movie = SWFDEC_MOVIE (object); g_assert (movie->list == NULL); SWFDEC_LOG ("disposing movie %s (depth %d)", movie->name, movie->depth); if (movie->swf) { g_object_unref (movie->swf); movie->swf = NULL; } if (movie->events) { swfdec_event_list_free (movie->events); movie->events = NULL; } if (movie->graphic) { g_object_unref (movie->graphic); movie->graphic = NULL; } G_OBJECT_CLASS (swfdec_movie_parent_class)->dispose (G_OBJECT (movie));}static voidswfdec_movie_mark (SwfdecAsObject *object){ SwfdecMovie *movie = SWFDEC_MOVIE (object); GList *walk; swfdec_as_string_mark (movie->original_name); swfdec_as_string_mark (movie->name); for (walk = movie->list; walk; walk = walk->next) { swfdec_as_object_mark (walk->data); } SWFDEC_AS_OBJECT_CLASS (swfdec_movie_parent_class)->mark (object);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -