Allow frame iteration in both directions

This commit is contained in:
Přemysl Eric Janouch 2021-11-26 20:54:08 +01:00
parent bd7f2f8c98
commit 18e96d8c9d
Signed by: p
GPG Key ID: A0420B94F92B9493
3 changed files with 19 additions and 1 deletions

View File

@ -317,6 +317,8 @@ load_wuffs_frame(struct load_wuffs_frame_context *ctx, GError **error)
(void *) (intptr_t) (wuffs_base__frame_config__duration(&fc) / (void *) (intptr_t) (wuffs_base__frame_config__duration(&fc) /
WUFFS_BASE__FLICKS_PER_MILLISECOND), NULL); WUFFS_BASE__FLICKS_PER_MILLISECOND), NULL);
cairo_surface_set_user_data(surface, &fastiv_io_key_frame_previous,
ctx->result_tail, NULL);
if (ctx->result_tail) if (ctx->result_tail)
cairo_surface_set_user_data(ctx->result_tail, &fastiv_io_key_frame_next, cairo_surface_set_user_data(ctx->result_tail, &fastiv_io_key_frame_next,
surface, (cairo_destroy_func_t) cairo_surface_destroy); surface, (cairo_destroy_func_t) cairo_surface_destroy);
@ -466,6 +468,11 @@ open_wuffs(
while (load_wuffs_frame(&ctx, error)) while (load_wuffs_frame(&ctx, error))
; ;
// Wrap the chain around, since our caller receives only one pointer.
if (ctx.result)
cairo_surface_set_user_data(ctx.result, &fastiv_io_key_frame_previous,
ctx.result_tail, NULL);
fail: fail:
free(ctx.workbuf.ptr); free(ctx.workbuf.ptr);
g_clear_pointer(&ctx.meta_exif, g_bytes_unref); g_clear_pointer(&ctx.meta_exif, g_bytes_unref);
@ -1024,6 +1031,7 @@ cairo_user_data_key_t fastiv_io_key_orientation;
cairo_user_data_key_t fastiv_io_key_icc; cairo_user_data_key_t fastiv_io_key_icc;
cairo_user_data_key_t fastiv_io_key_frame_next; cairo_user_data_key_t fastiv_io_key_frame_next;
cairo_user_data_key_t fastiv_io_key_frame_previous;
cairo_user_data_key_t fastiv_io_key_frame_duration; cairo_user_data_key_t fastiv_io_key_frame_duration;
cairo_user_data_key_t fastiv_io_key_loops; cairo_user_data_key_t fastiv_io_key_loops;

View File

@ -37,6 +37,10 @@ extern cairo_user_data_key_t fastiv_io_key_icc;
/// The next frame in a sequence, as a surface, in a chain, pre-composited. /// The next frame in a sequence, as a surface, in a chain, pre-composited.
/// There is no wrap-around. /// There is no wrap-around.
extern cairo_user_data_key_t fastiv_io_key_frame_next; extern cairo_user_data_key_t fastiv_io_key_frame_next;
/// The previous frame in a sequence, as a surface, in a chain, pre-composited.
/// This is a weak pointer that wraps around, and needn't be present
/// for static images.
extern cairo_user_data_key_t fastiv_io_key_frame_previous;
/// Frame duration in milliseconds as an intptr_t. /// Frame duration in milliseconds as an intptr_t.
extern cairo_user_data_key_t fastiv_io_key_frame_duration; extern cairo_user_data_key_t fastiv_io_key_frame_duration;
/// How many times to repeat the animation, or zero for +inf, as a uintptr_t. /// How many times to repeat the animation, or zero for +inf, as a uintptr_t.

View File

@ -452,9 +452,15 @@ fastiv_view_key_press_event(GtkWidget *widget, GdkEventKey *event)
gtk_widget_queue_resize(widget); gtk_widget_queue_resize(widget);
return TRUE; return TRUE;
case GDK_KEY_bracketleft:
if (!(self->frame = cairo_surface_get_user_data(
self->frame, &fastiv_io_key_frame_previous)))
self->frame = self->surface;
gtk_widget_queue_draw(widget);
return TRUE;
case GDK_KEY_bracketright: case GDK_KEY_bracketright:
if (!(self->frame = cairo_surface_get_user_data( if (!(self->frame = cairo_surface_get_user_data(
self->frame, &fastiv_io_key_frame_next))) self->frame, &fastiv_io_key_frame_next)))
self->frame = self->surface; self->frame = self->surface;
gtk_widget_queue_draw(widget); gtk_widget_queue_draw(widget);
return TRUE; return TRUE;